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 ) {
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 );
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;
407 const int ySkip = 0 == yBins % 13 ? 13
408 : 0 == yBins % 11 ? 11
425 int iNull =
histo.nullBin();
435 for (
int yLine = -1; yLine < yBins; ++yLine ) {
436 const double yHigh = yMax - yScale * yLine;
438 const double yLow = yMax - yScale * ( yLine + 1 );
442 const bool ynull = ( yLow <= 0 && 0 < yHigh );
443 const bool yfirst = -1 == yLine || yBins - 1 == yLine;
444 const bool ylab = ( 0 == ( yLine + 1 ) % ySkip ) || yfirst || ynull;
447 line1 += yLabel( ( yLow <= 0 && 0 < yHigh ) ? 0.0 : yLow );
455 line1 += symbBin(
histo.under, yLow, yHigh, ynull, errors );
457 line1 += ynull ?
"-+" : ylab ?
" +" :
" |";
461 for (
auto ibin =
histo.bins.cbegin();
histo.bins.cend() != ibin; ++ibin ) {
463 const int i = ibin -
histo.bins.cbegin();
465 const bool xnull = ibin->lower <= 0 && ( ibin + 1 ) !=
histo.bins.cend() && 0 < ( ibin + 1 )->lower;
466 const bool xlab = iNull == i % xSkip;
468 char symb = symbBin( *ibin, yLow, yHigh, ynull, errors );
471 if ( ( ynull || yfirst ) && xlab ) {
473 }
else if ( ynull || yfirst ) {
477 else if ( ylab && xnull ) {
479 }
else if ( xnull ) {
483 else if ( ylab || xlab ) {
492 std::string line3 = ynull ?
"->" : ylab ?
"+ " :
"| ";
495 line3 += symbBin(
histo.over, yLow, yHigh, ynull, errors );
503 for (
auto ib =
histo.bins.cbegin();
histo.bins.cend() != ib; ++ib ) { xlabels.
push_back( xLabel( ib->lower ) ); }
508 static const std::string s_UNDERFLOW(
"UNDERFLOW" );
509 static const std::string s_OVERFLOW(
" OVERFLOW" );
512 for (
unsigned int yLine = 0; yLine < 12; ++yLine ) {
515 if ( yLine < s_UNDERFLOW.size() ) {
516 line += s_UNDERFLOW[yLine];
523 if ( uLabel.
size() > yLine ) {
524 line += uLabel[yLine];
529 for (
auto ibin =
histo.bins.cbegin();
histo.bins.cend() != ibin; ++ibin ) {
530 int ib = ibin -
histo.bins.cbegin();
531 const bool xlab = ( iNull == ib % xSkip );
532 if ( xlab && yLine < xlabels[ib].
size() ) {
533 line += xlabels[ib][yLine];
539 if ( oLabel.
size() > yLine ) {
540 line += oLabel[yLine];
547 if ( yLine < s_OVERFLOW.size() ) {
548 line += s_OVERFLOW[yLine];
582 Mean : {:11.5g} +- {:<10.4g}
583 Rms : {:11.5g} +- {:<10.4g}
584 Skewness : {:11.5g} +- {:<10.4g}
585 Kurtosis : {:11.5g} +- {:<10.4g}
588 | All | In Range | Underflow | Overflow | #Equivalent | Integral | Total |
589 | {:^9} | {:^9} | {:^9} | {:^9} | {:^11.5g} | {:^11.5g} | {:^11.5g} |
597 histo->allEntries(),
histo->entries(),
histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ),
598 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ),
histo->equivalentBinEntries(),
599 histo->sumBinHeights(),
histo->sumAllBinHeights() );
601 const AIDA::IAnnotation& a =
histo->annotation();
603 stream <<
" Annotation\n";
604 for (
int i = 0; i < a.size(); ++i ) {
605 stream <<
fmt::format(
" | {:<25.25s} : {:<45.45s} |\n", a.key( i ), a.value( i ) );
610 return dumpText( hist, width, height, errors,
stream );
657 | All | In Range | Underflow | Overflow | Integral | Total |
658 | {:^9} | {:^9} | {:^9} | {:^9} | {:^11.5g} | {:^11.5g} |
663 histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ),
664 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ),
histo->sumBinHeights(),
665 histo->sumAllBinHeights() );
667 const AIDA::IAnnotation& a =
histo->annotation();
669 stream <<
" Annotation\n";
670 for (
int i = 0; i < a.size(); ++i ) {
671 stream <<
fmt::format(
" | {:<25.25s} : {:<45.45s} |\n", a.key( i ), a.value( i ) );
676 return dumpText( hist, width, height,
true,
stream );
707 const TProfile* profile =
dynamic_cast<const TProfile*
>(
histo );
719 Mean : {:11.5g} +- {:<10.4g}
720 Rms : {:11.5g} +- {:<10.4g}
725 | All | Underflow | Overflow | #Equivalent | Integral |
726 | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} |
732 histo->GetBinContent(
histo->GetNbinsX() + 1 ),
histo->GetEffectiveEntries(),
735 return dumpText( hist, width, height, errors,
stream );
763 | All | Underflow | Overflow | Integral |
764 | {:^11.5g} | {:^11.5g} | {:^11.5g} | {:^11.5g} |
772 return dumpText( hist, width, height,
true,
stream );
785 const bool errors ) {