14 # pragma warning( disable : 2259 ) 17 # pragma warning( disable : 1572 ) 23 # pragma warning( disable : 4996 ) 27 #include "AIDA/IAnnotation.h" 28 #include "AIDA/IAxis.h" 29 #include "AIDA/IHistogram1D.h" 30 #include "AIDA/IProfile1D.h" 38 #include <fmt/format.h> 64 Bin(
const double h = 0,
const double e = 0,
const double l = -1 ) : height( h ), error( e ), lower(
l ) {}
73 Bin& operator+=(
const Bin& right ) {
74 height +=
right.height;
75 const double e2 = error * error +
right.error *
right.error;
83 double maxY(
const bool withErr )
const {
86 [&](
double m,
const Bin& b ) { return std::max( m, withErr ? b.height + b.error : b.height ); } );
89 double minY(
const bool withErr )
const {
92 [&](
double m,
const Bin& b ) { return std::min( m, withErr ? b.height - b.error : b.height ); } );
95 Histo rebin(
const unsigned int bin )
const {
102 for (
unsigned int ibin = 0; ibin < bins.size(); ++ibin ) {
103 const Bin& current = bins[ibin];
104 if ( nh.bins.empty() ) {
105 nh.bins.push_back( current );
106 }
else if ( 0 == ibin % bin ) {
107 nh.bins.push_back( current );
109 nh.bins.back() += current;
115 int nullBin()
const {
116 for (
auto ib = bins.cbegin(); bins.cend() != ib + 1; ++ib ) {
117 if ( ib->lower <= 0 && 0 < ( ib + 1 )->lower ) {
return ib - bins.cbegin(); }
145 const TAxis* axis =
root->GetXaxis();
147 const int nbins = axis->GetNbins();
151 hist.under = Histo::Bin(
root->GetBinContent( 0 ),
root->GetBinError( 0 ), axis->GetXmin() );
153 hist.over = Histo::Bin(
root->GetBinContent( nbins + 1 ),
root->GetBinError( nbins + 1 ), axis->GetXmax() );
156 for (
int ibin = 1; ibin <= nbins; ++ibin ) {
158 hist.bins.emplace_back(
root->GetBinContent( ibin ),
root->GetBinError( ibin ), axis->GetBinLowEdge( ibin ) );
170 StatusCode _getHisto(
const TProfile*
root, Histo& hist,
const bool ) {
171 const TH1* histo =
root;
172 return _getHisto( histo, hist );
182 StatusCode _getHisto(
const AIDA::IHistogram1D* aida, Histo& hist ) {
188 const AIDA::IAxis& axis = aida->axis();
189 const int nbins = axis.bins();
192 hist.under = Histo::Bin( aida->binHeight( AIDA::IAxis::UNDERFLOW_BIN ),
193 aida->binError( AIDA::IAxis::UNDERFLOW_BIN ), axis.lowerEdge() );
195 hist.over = Histo::Bin( aida->binHeight( AIDA::IAxis::OVERFLOW_BIN ), aida->binError( AIDA::IAxis::OVERFLOW_BIN ),
198 for (
int ibin = 0; ibin < nbins; ++ibin ) {
200 hist.bins.emplace_back( aida->binHeight( ibin ), aida->binError( ibin ), axis.binLowerEdge( ibin ) );
212 StatusCode _getHisto(
const AIDA::IProfile1D* aida, Histo& hist,
const bool spread ) {
218 const AIDA::IAxis& axis = aida->axis();
219 const int nbins = axis.bins();
223 Histo::Bin( aida->binHeight( AIDA::IAxis::UNDERFLOW_BIN ),
224 spread ? aida->binRms( AIDA::IAxis::UNDERFLOW_BIN ) : aida->binError( AIDA::IAxis::UNDERFLOW_BIN ),
228 Histo::Bin( aida->binHeight( AIDA::IAxis::OVERFLOW_BIN ),
229 spread ? aida->binRms( AIDA::IAxis::OVERFLOW_BIN ) : aida->binError( AIDA::IAxis::OVERFLOW_BIN ),
232 for (
int ibin = 0; ibin < nbins; ++ibin ) {
234 hist.bins.emplace_back( aida->binHeight( ibin ), spread ? aida->binRms( ibin ) : aida->binError( ibin ),
235 axis.binLowerEdge( ibin ) );
245 inline unsigned int rebin(
const unsigned int bins,
const unsigned int imax ) {
246 if ( 0 == imax ) {
return 1; }
247 unsigned int ibin = 1;
248 while ( bins > imax * ibin ) { ++ibin; }
265 auto r = decompose( -v );
266 return {-r.first, r.second};
267 }
else if ( 0.1 > v ) {
274 }
else if ( 1 < v ) {
289 inline double _pow(
double x,
unsigned long n ) {
290 double y =
n % 2 ? x : 1;
293 if (
n % 2 ) { y *= x; }
298 inline double rValMin(
double v );
304 inline double rValMax(
double v ) {
309 return -1 * rValMin( -v );
314 const double f =
std::ceil( 20 * r.first ) / 2;
315 const int l = r.second - 1;
316 return 0 <
l ? f * _pow( 10,
l ) : f / _pow( 10, -
l );
323 inline double rValMin(
double v ) {
328 return -1 * rValMax( -v );
332 const double f =
std::floor( 20 * r.first ) / 2;
333 const int l = r.second - 1;
334 return 0 <
l ? f * _pow( 10,
l ) : f / _pow( 10, -
l );
350 char symbBin(
const Histo::Bin& bin,
const double yLow,
const double yHigh,
const bool yNull,
const bool errors ) {
351 if ( errors && yLow <= bin.height && bin.height < yHigh ) {
354 else if ( errors && yHigh < bin.height - bin.error ) {
356 }
else if ( errors && yLow >= bin.height + bin.error ) {
358 }
else if ( errors ) {
360 }
else if ( yLow <= bin.height && bin.height < yHigh ) {
362 }
else if ( 0 <= bin.height && yLow <= bin.height && 0 < yHigh && !yNull ) {
365 else if ( 0 > bin.height && yHigh > bin.height && 0 >= yLow && !yNull ) {
378 if ( 40 > width ) {
return dumpText( histo, 40, height, errors, stream ); }
379 if ( 200 < width ) {
return dumpText( histo, 200, height, errors, stream ); }
380 if ( 150 < height ) {
return dumpText( histo, width, 150, errors, stream ); }
381 if ( 20 > height ) {
return dumpText( histo, width, 20, errors, stream ); }
382 if ( height > width ) {
return dumpText( histo, width, width, errors, stream ); }
384 const unsigned int nBins = histo.bins.size();
385 if ( nBins > width ) {
387 Histo r = histo.rebin( rebin( nBins, width ) );
388 return dumpText( r, width, height, errors, stream );
392 double yMax =
std::max( rValMax( histo.maxY( errors ) ), 0.0 );
393 double yMin =
std::min( rValMin( histo.minY( errors ) ), 0.0 );
395 if ( yMin == yMax ) { yMax = yMin + 1; }
399 if ( 1 >= _ny ) { _ny = 10; }
403 if ( 20 > yBins ) { yBins = 20; }
404 const double yScale = ( yMax - yMin ) / yBins;
416 : 0 == yBins % 7 ? 7 : 0 == yBins % 6 ? 6 : 0 == yBins % 5 ? 5 : 0 == yBins % 4 ? 4 : 10;
420 0 == nBins % 7 ? 7 : 0 == nBins % 6 ? 6 : 0 == nBins % 5 ? 5 : 0 == nBins % 4 ? 4 : 10;
422 int iNull = histo.nullBin();
432 for (
int yLine = -1; yLine < yBins; ++yLine ) {
433 const double yHigh = yMax - yScale * yLine;
435 const double yLow = yMax - yScale * ( yLine + 1 );
439 const bool ynull = ( yLow <= 0 && 0 < yHigh );
440 const bool yfirst = -1 == yLine || yBins - 1 == yLine;
441 const bool ylab = ( 0 == ( yLine + 1 ) % ySkip ) || yfirst || ynull;
444 line1 += yLabel( ( yLow <= 0 && 0 < yHigh ) ? 0.0 : yLow );
452 line1 += symbBin( histo.under, yLow, yHigh, ynull, errors );
454 line1 += ynull ?
"-+" : ylab ?
" +" :
" |";
458 for (
auto ibin = histo.bins.cbegin(); histo.bins.cend() != ibin; ++ibin ) {
460 const int i = ibin - histo.bins.cbegin();
462 const bool xnull = ibin->lower <= 0 && ( ibin + 1 ) != histo.bins.cend() && 0 < ( ibin + 1 )->lower;
463 const bool xlab = iNull == i % xSkip;
465 char symb = symbBin( *ibin, yLow, yHigh, ynull, errors );
468 if ( ( ynull || yfirst ) && xlab ) {
470 }
else if ( ynull || yfirst ) {
474 else if ( ylab && xnull ) {
476 }
else if ( xnull ) {
480 else if ( ylab || xlab ) {
489 std::string line3 = ynull ?
"->" : ylab ?
"+ " :
"| ";
492 line3 += symbBin( histo.over, yLow, yHigh, ynull, errors );
494 stream << line1 << line2 << line3 <<
std::endl;
500 for (
auto ib = histo.bins.cbegin(); histo.bins.cend() != ib; ++ib ) { xlabels.
push_back( xLabel( ib->lower ) ); }
502 const std::string oLabel = xLabel( histo.over.lower );
503 const std::string uLabel = xLabel( histo.under.lower );
505 static const std::string s_UNDERFLOW(
"UNDERFLOW" );
506 static const std::string s_OVERFLOW(
" OVERFLOW" );
509 for (
unsigned int yLine = 0; yLine < 12; ++yLine ) {
512 if ( yLine < s_UNDERFLOW.size() ) {
513 line += s_UNDERFLOW[yLine];
520 if ( uLabel.
size() > yLine ) {
521 line += uLabel[yLine];
526 for (
auto ibin = histo.bins.cbegin(); histo.bins.cend() != ibin; ++ibin ) {
527 int ib = ibin - histo.bins.cbegin();
528 const bool xlab = ( iNull == ib % xSkip );
529 if ( xlab && yLine < xlabels[ib].
size() ) {
530 line += xlabels[ib][yLine];
536 if ( oLabel.
size() > yLine ) {
537 line += oLabel[yLine];
544 if ( yLine < s_OVERFLOW.size() ) {
545 line += s_OVERFLOW[yLine];
571 if ( !histo ) {
return stream; }
579 Mean : {:11.5g} +- {:<10.4g} 580 Rms : {:11.5g} +- {:<10.4g} 581 Skewness : {:11.5g} +- {:<10.4g} 582 Kurtosis : {:11.5g} +- {:<10.4g} 585 | All | In Range | Underflow | Overflow | #Equivalent | Integral | Total | 586 | {:^9} | {:^9} | {:^9} | {:^9} | {:^11.5g} | {:^11.5g} | {:^11.5g} | 589 path( histo ), histo->title(), 594 histo->allEntries(), histo->entries(), histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ),
595 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ), histo->equivalentBinEntries(),
596 histo->sumBinHeights(), histo->sumAllBinHeights() );
598 const AIDA::IAnnotation& a = histo->annotation();
600 stream <<
" Annotation\n";
601 for (
int i = 0; i < a.size(); ++i ) {
602 stream <<
fmt::format(
" | {:<25.25s} : {:<45.45s} |\n", a.key( i ), a.value( i ) );
607 return dumpText( hist, width, height, errors, stream );
624 histoDump_( histo, stream, width, height, errors );
642 if ( !histo ) {
return stream; }
644 StatusCode sc = _getHisto( histo, hist, spread );
654 | All | In Range | Underflow | Overflow | Integral | Total | 655 | {:^9} | {:^9} | {:^9} | {:^9} | {:^11.5g} | {:^11.5g} | 658 path( histo ), histo->title(), 659 histo->mean(), histo->rms(), histo->allEntries(), histo->entries(),
660 histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ),
661 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ), histo->sumBinHeights(),
662 histo->sumAllBinHeights() );
664 const AIDA::IAnnotation& a = histo->annotation();
666 stream <<
" Annotation\n";
667 for (
int i = 0; i < a.size(); ++i ) {
668 stream <<
fmt::format(
" | {:<25.25s} : {:<45.45s} |\n", a.key( i ), a.value( i ) );
673 return dumpText( hist, width, height,
true, stream );
688 histoDump_( histo, stream, width, height, spread );
704 const TProfile* profile = dynamic_cast<const TProfile*>( histo );
705 if ( profile ) {
return histoDump_( profile, stream, width, height ); }
708 if ( !histo ) {
return stream; }
716 Mean : {:11.5g} +- {:<10.4g} 717 Rms : {:11.5g} +- {:<10.4g} 722 | All | Underflow | Overflow | #Equivalent | Integral | 723 | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} | 726 histo->GetName(), histo->GetTitle(), 727 histo->GetMean(), histo->GetMeanError(), histo->GetRMS(), histo->GetRMSError(),
728 histo->GetSkewness(), histo->GetKurtosis(), histo->GetEntries(), histo->GetBinContent( 0 ),
729 histo->GetBinContent( histo->GetNbinsX() + 1 ), histo->GetEffectiveEntries(),
732 return dumpText( hist, width, height, errors, stream );
748 if ( !histo ) {
return stream; }
750 StatusCode sc = _getHisto( histo, hist,
true );
760 | All | Underflow | Overflow | Integral | 761 | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} | 764 histo->GetName(), histo->GetTitle(), 765 histo->GetMean(), histo->GetRMS(), histo->GetSkewness(), histo->GetKurtosis(),
766 histo->GetEntries(), histo->GetBinContent( 0 ), histo->GetBinContent( histo->GetNbinsX() + 1 ),
769 return dumpText( hist, width, height,
true, stream );
782 const bool errors ) {
784 histoDump_( histo, stream, width, height, errors );
constexpr auto size(const T &, Args &&...) noexcept
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
static double rmsErr(const AIDA::IHistogram1D *histo)
get an error in the rms value
GAUDI_API std::ostream & histoDump_(const AIDA::IHistogram1D *histo, std::ostream &stream, const std::size_t width=80, const std::size_t height=50, const bool errors=false)
dump the text representation of the histogram
GAUDI_API std::string histoDump(const AIDA::IHistogram1D *histo, const std::size_t width=80, const std::size_t height=50, const bool errors=false)
dump the text representation of the histogram
constexpr static const auto SUCCESS
static double meanErr(const AIDA::IHistogram1D *histo)
get an error in the mean value
static double rms(const AIDA::IHistogram1D *histo)
get the rms value for the histogram (just for completeness)
This class is used for returning status codes from appropriate routines.
static double kurtosisErr(const AIDA::IHistogram1D *histo)
get the error in kurtosis for the histogram
constexpr static const auto FAILURE
static double mean(const AIDA::IHistogram1D *histo)
get the mean value for the histogram (just for completeness)
static double skewnessErr(const AIDA::IHistogram1D *histo)
get the error in skewness for the histogram
static double kurtosis(const AIDA::IHistogram1D *histo)
get the kurtosis for the histogram
static double skewness(const AIDA::IHistogram1D *histo)
get the skewness for the histogram