14 # pragma warning( disable : 2259 ) 17 # pragma warning( disable : 1572 ) 23 # pragma warning( disable : 4996 ) 39 #include "AIDA/IAnnotation.h" 40 #include "AIDA/IAxis.h" 41 #include "AIDA/IHistogram1D.h" 42 #include "AIDA/IProfile1D.h" 56 #include "boost/format.hpp" 82 Bin(
const double h = 0,
const double e = 0,
const double l = -1 ) : height( h ), error( e ), lower(
l ) {}
91 Bin& operator+=(
const Bin& right ) {
92 height +=
right.height;
93 const double e2 = error * error +
right.error *
right.error;
101 double maxY(
const bool withErr )
const {
104 [&](
double m,
const Bin& b ) { return std::max( m, withErr ? b.height + b.error : b.height ); } );
107 double minY(
const bool withErr )
const {
110 [&](
double m,
const Bin& b ) { return std::min( m, withErr ? b.height - b.error : b.height ); } );
113 Histo rebin(
const unsigned int bin )
const {
120 for (
unsigned int ibin = 0; ibin < bins.size(); ++ibin ) {
121 const Bin& current = bins[ibin];
122 if ( nh.bins.empty() ) {
123 nh.bins.push_back( current );
124 }
else if ( 0 == ibin % bin ) {
125 nh.bins.push_back( current );
127 nh.bins.back() += current;
133 int nullBin()
const {
134 for (
auto ib = bins.cbegin(); bins.cend() != ib + 1; ++ib ) {
135 if ( ib->lower <= 0 && 0 < ( ib + 1 )->lower ) {
return ib - bins.cbegin(); }
163 const TAxis* axis =
root->GetXaxis();
165 const int nbins = axis->GetNbins();
169 hist.under = Histo::Bin(
root->GetBinContent( 0 ),
root->GetBinError( 0 ), axis->GetXmin() );
171 hist.over = Histo::Bin(
root->GetBinContent( nbins + 1 ),
root->GetBinError( nbins + 1 ), axis->GetXmax() );
174 for (
int ibin = 1; ibin <= nbins; ++ibin ) {
176 hist.bins.emplace_back(
root->GetBinContent( ibin ),
root->GetBinError( ibin ), axis->GetBinLowEdge( ibin ) );
188 StatusCode _getHisto(
const TProfile*
root, Histo& hist,
const bool ) {
189 const TH1* histo =
root;
190 return _getHisto( histo, hist );
200 StatusCode _getHisto(
const AIDA::IHistogram1D* aida, Histo& hist ) {
206 const AIDA::IAxis& axis = aida->axis();
207 const int nbins = axis.bins();
210 hist.under = Histo::Bin( aida->binHeight( AIDA::IAxis::UNDERFLOW_BIN ),
211 aida->binError( AIDA::IAxis::UNDERFLOW_BIN ), axis.lowerEdge() );
213 hist.over = Histo::Bin( aida->binHeight( AIDA::IAxis::OVERFLOW_BIN ), aida->binError( AIDA::IAxis::OVERFLOW_BIN ),
216 for (
int ibin = 0; ibin < nbins; ++ibin ) {
218 hist.bins.emplace_back( aida->binHeight( ibin ), aida->binError( ibin ), axis.binLowerEdge( ibin ) );
230 StatusCode _getHisto(
const AIDA::IProfile1D* aida, Histo& hist,
const bool spread ) {
236 const AIDA::IAxis& axis = aida->axis();
237 const int nbins = axis.bins();
241 Histo::Bin( aida->binHeight( AIDA::IAxis::UNDERFLOW_BIN ),
242 spread ? aida->binRms( AIDA::IAxis::UNDERFLOW_BIN ) : aida->binError( AIDA::IAxis::UNDERFLOW_BIN ),
246 Histo::Bin( aida->binHeight( AIDA::IAxis::OVERFLOW_BIN ),
247 spread ? aida->binRms( AIDA::IAxis::OVERFLOW_BIN ) : aida->binError( AIDA::IAxis::OVERFLOW_BIN ),
250 for (
int ibin = 0; ibin < nbins; ++ibin ) {
252 hist.bins.emplace_back( aida->binHeight( ibin ), spread ? aida->binRms( ibin ) : aida->binError( ibin ),
253 axis.binLowerEdge( ibin ) );
263 inline unsigned int rebin(
const unsigned int bins,
const unsigned int imax ) {
264 if ( 0 == imax ) {
return 1; }
265 unsigned int ibin = 1;
266 while ( bins > imax * ibin ) { ++ibin; }
283 auto r = decompose( -v );
284 return {-r.first, r.second};
285 }
else if ( 0.1 > v ) {
292 }
else if ( 1 < v ) {
307 inline double _pow(
double x,
unsigned long n ) {
308 double y =
n % 2 ? x : 1;
311 if (
n % 2 ) { y *= x; }
316 inline double rValMin(
double v );
322 inline double rValMax(
double v ) {
327 return -1 * rValMin( -v );
332 const double f =
std::ceil( 20 * r.first ) / 2;
333 const int l = r.second - 1;
334 return 0 <
l ? f * _pow( 10,
l ) : f / _pow( 10, -
l );
341 inline double rValMin(
double v ) {
346 return -1 * rValMax( -v );
350 const double f =
std::floor( 20 * r.first ) / 2;
351 const int l = r.second - 1;
352 return 0 <
l ? f * _pow( 10,
l ) : f / _pow( 10, -
l );
376 char symbBin(
const Histo::Bin& bin,
const double yLow,
const double yHigh,
const bool yNull,
const bool errors ) {
377 if ( errors && yLow <= bin.height && bin.height < yHigh ) {
380 else if ( errors && yHigh < bin.height - bin.error ) {
382 }
else if ( errors && yLow >= bin.height + bin.error ) {
384 }
else if ( errors ) {
386 }
else if ( yLow <= bin.height && bin.height < yHigh ) {
388 }
else if ( 0 <= bin.height && yLow <= bin.height && 0 < yHigh && !yNull ) {
391 else if ( 0 > bin.height && yHigh > bin.height && 0 >= yLow && !yNull ) {
404 if ( 40 > width ) {
return dumpText( histo, 40, height, errors, stream ); }
405 if ( 200 < width ) {
return dumpText( histo, 200, height, errors, stream ); }
406 if ( 150 < height ) {
return dumpText( histo, width, 150, errors, stream ); }
407 if ( 20 > height ) {
return dumpText( histo, width, 20, errors, stream ); }
408 if ( height > width ) {
return dumpText( histo, width, width, errors, stream ); }
410 const unsigned int nBins = histo.bins.size();
411 if ( nBins > width ) {
413 Histo r = histo.rebin( rebin( nBins, width ) );
414 return dumpText( r, width, height, errors, stream );
418 double yMax =
std::max( rValMax( histo.maxY( errors ) ), 0.0 );
419 double yMin =
std::min( rValMin( histo.minY( errors ) ), 0.0 );
421 if ( yMin == yMax ) { yMax = yMin + 1; }
425 if ( 1 >= _ny ) { _ny = 10; }
429 if ( 20 > yBins ) { yBins = 20; }
430 const double yScale = ( yMax - yMin ) / yBins;
442 : 0 == yBins % 7 ? 7 : 0 == yBins % 6 ? 6 : 0 == yBins % 5 ? 5 : 0 == yBins % 4 ? 4 : 10;
446 0 == nBins % 7 ? 7 : 0 == nBins % 6 ? 6 : 0 == nBins % 5 ? 5 : 0 == nBins % 4 ? 4 : 10;
448 int iNull = histo.nullBin();
458 for (
int yLine = -1; yLine < yBins; ++yLine ) {
459 const double yHigh = yMax - yScale * yLine;
461 const double yLow = yMax - yScale * ( yLine + 1 );
465 const bool ynull = ( yLow <= 0 && 0 < yHigh );
466 const bool yfirst = -1 == yLine || yBins - 1 == yLine;
467 const bool ylab = ( 0 == ( yLine + 1 ) % ySkip ) || yfirst || ynull;
470 line1 += yLabel( ( yLow <= 0 && 0 < yHigh ) ? 0.0 : yLow );
478 line1 += symbBin( histo.under, yLow, yHigh, ynull, errors );
480 line1 += ynull ?
"-+" : ylab ?
" +" :
" |";
484 for (
auto ibin = histo.bins.cbegin(); histo.bins.cend() != ibin; ++ibin ) {
486 const int i = ibin - histo.bins.cbegin();
488 const bool xnull = ibin->lower <= 0 && ( ibin + 1 ) != histo.bins.cend() && 0 < ( ibin + 1 )->lower;
489 const bool xlab = iNull == i % xSkip;
491 char symb = symbBin( *ibin, yLow, yHigh, ynull, errors );
494 if ( ( ynull || yfirst ) && xlab ) {
496 }
else if ( ynull || yfirst ) {
500 else if ( ylab && xnull ) {
502 }
else if ( xnull ) {
506 else if ( ylab || xlab ) {
515 std::string line3 = ynull ?
"->" : ylab ?
"+ " :
"| ";
518 line3 += symbBin( histo.over, yLow, yHigh, ynull, errors );
520 stream << line1 << line2 << line3 <<
std::endl;
526 for (
auto ib = histo.bins.cbegin(); histo.bins.cend() != ib; ++ib ) { xlabels.
push_back( xLabel( ib->lower ) ); }
528 const std::string oLabel = xLabel( histo.over.lower );
529 const std::string uLabel = xLabel( histo.under.lower );
531 static const std::string s_UNDERFLOW(
"UNDERFLOW" );
532 static const std::string s_OVERFLOW(
" OVERFLOW" );
535 for (
unsigned int yLine = 0; yLine < 12; ++yLine ) {
538 if ( yLine < s_UNDERFLOW.size() ) {
539 line += s_UNDERFLOW[yLine];
546 if ( uLabel.
size() > yLine ) {
547 line += uLabel[yLine];
552 for (
auto ibin = histo.bins.cbegin(); histo.bins.cend() != ibin; ++ibin ) {
553 int ib = ibin - histo.bins.cbegin();
554 const bool xlab = ( iNull == ib % xSkip );
555 if ( xlab && yLine < xlabels[ib].
size() ) {
556 line += xlabels[ib][yLine];
562 if ( oLabel.
size() > yLine ) {
563 line += oLabel[yLine];
570 if ( yLine < s_OVERFLOW.size() ) {
571 line += s_OVERFLOW[yLine];
597 if ( !histo ) {
return stream; }
620 stream <<
boost::format(
" Entries :\n | %=9s | %=9s | %=9s | %9s | %=11s | %=11s | %=11s |" ) %
"All" %
621 "In Range" %
"Underflow" %
"Overflow" %
"#Equivalent" %
"Integral" %
"Total" 623 <<
boost::format(
" | %=9d | %=9d | %=9d | %=9d | %=11.5g | %=11.5g | %=11.5g |" ) % histo->allEntries() %
624 histo->entries() % histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ) %
625 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN ) % histo->equivalentBinEntries() %
626 histo->sumBinHeights() % histo->sumAllBinHeights()
630 const AIDA::IAnnotation& a = histo->annotation();
631 if ( 0 != a.size() ) {
633 for (
int i = 0; i < a.size(); ++i ) {
639 return dumpText( hist, width, height, errors, stream );
656 histoDump_( histo, stream, width, height, errors );
674 if ( !histo ) {
return stream; }
676 StatusCode sc = _getHisto( histo, hist, spread );
687 stream <<
boost::format(
" Entries :\n | %=9s | %=9s | %=9s | %9s | %=11s | %=11s |" ) %
"All" %
"In Range" %
691 %
"Integral" %
"Total" 693 <<
boost::format(
" | %=9d | %=9d | %=9d | %=9d | %=11.5g | %=11.5g |" ) % histo->allEntries() %
694 histo->entries() % histo->binEntries( AIDA::IAxis::UNDERFLOW_BIN ) %
695 histo->binEntries( AIDA::IAxis::OVERFLOW_BIN )
697 % histo->sumBinHeights() % histo->sumAllBinHeights()
701 const AIDA::IAnnotation& a = histo->annotation();
702 if ( 0 != a.size() ) {
704 for (
int i = 0; i < a.size(); ++i ) {
710 return dumpText( hist, width, height,
true, stream );
725 histoDump_( histo, stream, width, height, spread );
741 const TProfile* profile = dynamic_cast<const TProfile*>( histo );
742 if ( profile ) {
return histoDump_( profile, stream, width, height ); }
745 if ( !histo ) {
return stream; }
754 stream <<
boost::format(
" Mean : %11.5g +- %-10.4g " ) % histo->GetMean() % histo->GetMeanError() <<
std::endl 760 stream <<
boost::format(
" Entries :\n | %=11s | %=11s | %=11s | %=11s | %=11s |" ) %
"All" %
"Underflow" %
761 "Overflow" %
"#Equivalent" %
"Integral" 763 <<
boost::format(
" | %=11.5g | %=11.5g | %=11.5g | %=11.5g | %=11.5g |" ) % histo->GetEntries() %
764 histo->GetBinContent( 0 ) % histo->GetBinContent( histo->GetNbinsX() + 1 ) %
765 histo->GetEffectiveEntries() % histo->Integral()
769 return dumpText( hist, width, height, errors, stream );
785 if ( !histo ) {
return stream; }
787 StatusCode sc = _getHisto( histo, hist,
true );
798 stream <<
boost::format(
" Entries :\n | %=11s | %=11s | %=11s | %=11s |" ) %
"All" %
"Underflow" %
"Overflow" %
801 <<
boost::format(
" | %=11.5g | %=11.5g | %=11.5g | %=11.5g |" ) % histo->GetEntries() %
802 histo->GetBinContent( 0 ) % histo->GetBinContent( histo->GetNbinsX() + 1 ) % histo->Integral()
806 return dumpText( hist, width, height,
true, stream );
819 const bool errors ) {
821 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