14 # pragma warning( disable : 2259 )
20 # pragma warning( disable : 4996 )
23 #include <AIDA/IAnnotation.h>
24 #include <AIDA/IAxis.h>
25 #include <AIDA/IHistogram1D.h>
26 #include <AIDA/IProfile1D.h>
35 #include <fmt/format.h>
46 constexpr
bool essentiallyEqual(
double const a,
double const b ) {
67 Bin(
const double h = 0,
const double e = 0,
const double l = -1 ) : height(
h ), error( e ), lower(
l ) {}
76 Bin& operator+=(
const Bin& right ) {
77 height +=
right.height;
78 const double e2 = error * error +
right.error *
right.error;
86 double maxY(
const bool withErr )
const {
89 [&](
double m,
const Bin& b ) { return std::max( m, withErr ? b.height + b.error : b.height ); } );
92 double minY(
const bool withErr )
const {
95 [&](
double m,
const Bin& b ) { return std::min( m, withErr ? b.height - b.error : b.height ); } );
98 Histo rebin(
const unsigned int bin )
const {
105 for (
unsigned int ibin = 0; ibin < bins.size(); ++ibin ) {
106 const Bin& current = bins[ibin];
107 if ( nh.bins.empty() ) {
108 nh.bins.push_back( current );
109 }
else if ( 0 == ibin % bin ) {
110 nh.bins.push_back( current );
112 nh.bins.back() += current;
118 int nullBin()
const {
119 for (
auto ib = bins.cbegin(); bins.cend() != ib + 1; ++ib ) {
120 if ( ib->lower <= 0 && 0 < ( ib + 1 )->lower ) {
return ib - bins.cbegin(); }
148 const TAxis* axis =
root->GetXaxis();
150 const int nbins = axis->GetNbins();
154 hist.under = Histo::Bin(
root->GetBinContent( 0 ),
root->GetBinError( 0 ), axis->GetXmin() );
156 hist.over = Histo::Bin(
root->GetBinContent( nbins + 1 ),
root->GetBinError( nbins + 1 ), axis->GetXmax() );
159 for (
int ibin = 1; ibin <= nbins; ++ibin ) {
161 hist.bins.emplace_back(
root->GetBinContent( ibin ),
root->GetBinError( ibin ), axis->GetBinLowEdge( ibin ) );
173 StatusCode _getHisto(
const TProfile*
root, Histo& hist,
const bool ) {
174 const TH1* histo =
root;
175 return _getHisto( histo, hist );
185 StatusCode _getHisto(
const AIDA::IHistogram1D* aida, Histo& hist ) {
191 const AIDA::IAxis& axis = aida->axis();
192 const int nbins = axis.bins();
195 hist.under = Histo::Bin( aida->binHeight( AIDA::IAxis::UNDERFLOW_BIN ),
196 aida->binError( AIDA::IAxis::UNDERFLOW_BIN ), axis.lowerEdge() );
198 hist.over = Histo::Bin( aida->binHeight( AIDA::IAxis::OVERFLOW_BIN ), aida->binError( AIDA::IAxis::OVERFLOW_BIN ),
201 for (
int ibin = 0; ibin < nbins; ++ibin ) {
203 hist.bins.emplace_back( aida->binHeight( ibin ), aida->binError( ibin ), axis.binLowerEdge( ibin ) );
215 StatusCode _getHisto(
const AIDA::IProfile1D* aida, Histo& hist,
const bool spread ) {
221 const AIDA::IAxis& axis = aida->axis();
222 const int nbins = axis.bins();
226 Histo::Bin( aida->binHeight( AIDA::IAxis::UNDERFLOW_BIN ),
227 spread ? aida->binRms( AIDA::IAxis::UNDERFLOW_BIN ) : aida->binError( AIDA::IAxis::UNDERFLOW_BIN ),
231 Histo::Bin( aida->binHeight( AIDA::IAxis::OVERFLOW_BIN ),
232 spread ? aida->binRms( AIDA::IAxis::OVERFLOW_BIN ) : aida->binError( AIDA::IAxis::OVERFLOW_BIN ),
235 for (
int ibin = 0; ibin < nbins; ++ibin ) {
237 hist.bins.emplace_back( aida->binHeight( ibin ), spread ? aida->binRms( ibin ) : aida->binError( ibin ),
238 axis.binLowerEdge( ibin ) );
248 inline unsigned int rebin(
const unsigned int bins,
const unsigned int imax ) {
249 if ( 0 == imax ) {
return 1; }
250 unsigned int ibin = 1;
251 while ( bins > imax * ibin ) { ++ibin; }
264 else if ( essentiallyEqual( 1.0,
v ) ) {
268 auto r = decompose( -
v );
269 return { -r.first, r.second };
270 }
else if ( 0.1 >
v ) {
277 }
else if ( 1 <
v ) {
292 inline double _pow(
double x,
unsigned long n ) {
293 double y =
n % 2 ? x : 1;
296 if (
n % 2 ) { y *= x; }
301 inline double rValMin(
double v );
307 inline double rValMax(
double v ) {
308 if ( 0 >
v ) {
return -1 * rValMin( -
v ); }
312 const double f =
std::ceil( 20 * r.first ) / 2;
313 const int l = r.second - 1;
314 return 0 <
l ? f * _pow( 10,
l ) : f / _pow( 10, -
l );
321 inline double rValMin(
double v ) {
322 if ( 0 >
v ) {
return -1 * rValMax( -
v ); }
325 const double f =
std::floor( 20 * r.first ) / 2;
326 const int l = r.second - 1;
327 return 0 <
l ? f * _pow( 10,
l ) : f / _pow( 10, -
l );
343 char symbBin(
const Histo::Bin& bin,
const double yLow,
const double yHigh,
const bool yNull,
const bool errors ) {
344 if ( errors && yLow <= bin.height && bin.height < yHigh ) {
347 else if ( errors && yHigh < bin.height - bin.error ) {
349 }
else if ( errors && yLow >= bin.height + bin.error ) {
351 }
else if ( errors ) {
353 }
else if ( yLow <= bin.height && bin.height < yHigh ) {
355 }
else if ( 0 <= bin.height && yLow <= bin.height && 0 < yHigh && !yNull ) {
358 else if ( 0 > bin.height && yHigh > bin.height && 0 >= yLow && !yNull ) {
371 if ( 40 > width ) {
return dumpText( histo, 40, height, errors,
stream ); }
372 if ( 200 < width ) {
return dumpText( histo, 200, height, errors,
stream ); }
373 if ( 150 < height ) {
return dumpText( histo, width, 150, errors,
stream ); }
374 if ( 20 > height ) {
return dumpText( histo, width, 20, errors,
stream ); }
375 if ( height > width ) {
return dumpText( histo, width, width, errors,
stream ); }
377 const unsigned int nBins = histo.bins.size();
378 if ( nBins > width ) {
380 Histo r = histo.rebin( rebin( nBins, width ) );
381 return dumpText( r, width, height, errors,
stream );
385 double yMax =
std::max( rValMax( histo.maxY( errors ) ), 0.0 );
386 double yMin =
std::min( rValMin( histo.minY( errors ) ), 0.0 );
388 if ( essentiallyEqual( yMin, yMax ) ) { yMax = yMin + 1; }
392 if ( 1 >= _ny ) { _ny = 10; }
396 if ( 20 > yBins ) { yBins = 20; }
397 const double yScale = ( yMax - yMin ) / yBins;
400 const int ySkip = 0 == yBins % 13 ? 13
401 : 0 == yBins % 11 ? 11
418 int iNull = histo.nullBin();
428 for (
int yLine = -1; yLine < yBins; ++yLine ) {
429 const double yHigh = yMax - yScale * yLine;
431 const double yLow = yMax - yScale * ( yLine + 1 );
435 const bool ynull = ( yLow <= 0 && 0 < yHigh );
436 const bool yfirst = -1 == yLine || yBins - 1 == yLine;
437 const bool ylab = ( 0 == ( yLine + 1 ) % ySkip ) || yfirst || ynull;
440 line1 += yLabel( ( yLow <= 0 && 0 < yHigh ) ? 0.0 : yLow );
448 line1 += symbBin( histo.under, yLow, yHigh, ynull, errors );
450 line1 += ynull ?
"-+" : ylab ?
" +" :
" |";
454 for (
auto ibin = histo.bins.cbegin(); histo.bins.cend() != ibin; ++ibin ) {
456 const int i = ibin - histo.bins.cbegin();
458 const bool xnull = ibin->lower <= 0 && ( ibin + 1 ) != histo.bins.cend() && 0 < ( ibin + 1 )->lower;
459 const bool xlab = iNull == i % xSkip;
461 char symb = symbBin( *ibin, yLow, yHigh, ynull, errors );
464 if ( ( ynull || yfirst ) && xlab ) {
466 }
else if ( ynull || yfirst ) {
470 else if ( ylab && xnull ) {
472 }
else if ( xnull ) {
476 else if ( ylab || xlab ) {
485 std::string line3 = ynull ?
"->" : ylab ?
"+ " :
"| ";
488 line3 += symbBin( histo.over, yLow, yHigh, ynull, errors );
496 for (
auto ib = histo.bins.cbegin(); histo.bins.cend() != ib; ++ib ) { xlabels.
push_back( xLabel( ib->lower ) ); }
498 const std::string oLabel = xLabel( histo.over.lower );
499 const std::string uLabel = xLabel( histo.under.lower );
501 static const std::string s_UNDERFLOW(
"UNDERFLOW" );
502 static const std::string s_OVERFLOW(
" OVERFLOW" );
505 for (
unsigned int yLine = 0; yLine < 12; ++yLine ) {
508 if ( yLine < s_UNDERFLOW.size() ) {
509 line += s_UNDERFLOW[yLine];
516 if ( uLabel.
size() > yLine ) {
517 line += uLabel[yLine];
522 for (
auto ibin = histo.bins.cbegin(); histo.bins.cend() != ibin; ++ibin ) {
523 int ib = ibin - histo.bins.cbegin();
524 const bool xlab = ( iNull == ib % xSkip );
525 if ( xlab && yLine < xlabels[ib].
size() ) {
526 line += xlabels[ib][yLine];
532 if ( oLabel.
size() > yLine ) {
533 line += oLabel[yLine];
540 if ( yLine < s_OVERFLOW.size() ) {
541 line += s_OVERFLOW[yLine];
569 if ( !histo ) {
return stream.str(); }
577 Mean : {:11.5g} +- {:<10.4g}
578 Rms : {:11.5g} +- {:<10.4g}
579 Skewness : {:11.5g} +- {:<10.4g}
580 Kurtosis : {:11.5g} +- {:<10.4g}
583 | All | In Range | Underflow | Overflow | #Equivalent | Integral | Total |
584 | {:^9} | {:^9} | {:^9} | {:^9} | {:^11.5g} | {:^11.5g} | {:^11.5g} |
587 path( histo ), histo->title(),
592 histo->allEntries(), histo->entries(), histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ),
593 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ), histo->equivalentBinEntries(),
594 histo->sumBinHeights(), histo->sumAllBinHeights() );
596 const AIDA::IAnnotation& a = histo->annotation();
598 stream <<
" Annotation\n";
599 for (
int i = 0; i < a.size(); ++i ) {
600 stream <<
fmt::format(
" | {:<25.25s} : {:<45.45s} |\n", a.key( i ), a.value( i ) );
605 return dumpText( hist, width, height, errors,
stream ).str();
620 if ( !histo ) {
return stream.str(); }
622 StatusCode sc = _getHisto( histo, hist, spread );
632 | All | In Range | Underflow | Overflow | Integral | Total |
633 | {:^9} | {:^9} | {:^9} | {:^9} | {:^11.5g} | {:^11.5g} |
636 path( histo ), histo->title(),
637 histo->mean(), histo->rms(), histo->allEntries(), histo->entries(),
638 histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ),
639 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ), histo->sumBinHeights(),
640 histo->sumAllBinHeights() );
642 const AIDA::IAnnotation& a = histo->annotation();
644 stream <<
" Annotation\n";
645 for (
int i = 0; i < a.size(); ++i ) {
646 stream <<
fmt::format(
" | {:<25.25s} : {:<45.45s} |\n", a.key( i ), a.value( i ) );
651 return dumpText( hist, width, height,
true,
stream ).str();
663 const bool errors ) {
664 const TProfile* profile =
dynamic_cast<const TProfile*
>( histo );
665 if ( profile ) {
return histoDump( profile, width, height ); }
669 if ( !histo ) {
return stream.str(); }
677 Mean : {:11.5g} +- {:<10.4g}
678 Rms : {:11.5g} +- {:<10.4g}
683 | All | Underflow | Overflow | #Equivalent | Integral |
684 | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} |
687 histo->GetName(), histo->GetTitle(),
688 histo->GetMean(), histo->GetMeanError(), histo->GetRMS(), histo->GetRMSError(),
689 histo->GetSkewness(), histo->GetKurtosis(), histo->GetEntries(), histo->GetBinContent( 0 ),
690 histo->GetBinContent( histo->GetNbinsX() + 1 ), histo->GetEffectiveEntries(),
693 return dumpText( hist, width, height, errors,
stream ).str();
708 if ( !histo ) {
return stream.str(); }
710 StatusCode sc = _getHisto( histo, hist,
true );
720 | All | Underflow | Overflow | Integral |
721 | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} |
724 histo->GetName(), histo->GetTitle(),
725 histo->GetMean(), histo->GetRMS(), histo->GetSkewness(), histo->GetKurtosis(),
726 histo->GetEntries(), histo->GetBinContent( 0 ), histo->GetBinContent( histo->GetNbinsX() + 1 ),
729 return dumpText( hist, width, height,
true,
stream ).str();