4 #pragma warning(disable:2259)
7 #pragma warning(disable:1572)
13 #pragma warning(disable:4996)
28 #include "AIDA/IHistogram1D.h"
29 #include "AIDA/IProfile1D.h"
30 #include "AIDA/IAxis.h"
31 #include "AIDA/IAnnotation.h"
35 #include "GaudiKernel/StatusCode.h"
45 #include "boost/format.hpp"
49 #include "GaudiUtils/HistoDump.h"
50 #include "GaudiUtils/HistoTableFormat.h"
51 #include "GaudiUtils/HistoStats.h"
74 Bin (
const double h = 0 ,
88 Bin& operator+= (
const Bin& right )
90 height += right.height ;
91 const double e2 = error * error + right.error * right.error ;
92 error = std::sqrt ( e2 ) ;
99 double maxY (
const bool withErr )
const
102 std::max ( under.height, over.height ),
103 [&](
double m,
const Bin& b) {
104 return std::max ( m, withErr ? b.height + b.error : b.height ) ;
108 double minY (
const bool withErr )
const
111 std::min ( under.height, over.height ),
112 [&](
double m,
const Bin& b) {
113 return std::min ( m, withErr ? b.height - b.error : b.height ) ;
117 Histo rebin (
const unsigned int bin )
const
125 for (
unsigned int ibin = 0 ; ibin < bins.size() ; ++ibin )
127 const Bin& current = bins[ibin] ;
128 if ( nh.bins.empty() ) { nh.bins.push_back ( current ) ; }
129 else if ( 0 == ibin % bin ) { nh.bins.push_back ( current ) ; }
130 else { nh.bins.back() += current ; }
137 for (
auto ib = bins.cbegin() ; bins.cend() != ib + 1 ; ++ib )
138 {
if ( ib->lower <= 0 && 0 < (ib+1)->lower ) {
return ib - bins.cbegin() ; } }
142 typedef std::vector<Bin> Bins ;
166 const TAxis* axis = root->GetXaxis() ;
168 const int nbins = axis->GetNbins () ;
172 hist.under = Histo::Bin ( root -> GetBinContent ( 0 ) ,
173 root -> GetBinError ( 0 ) ,
174 axis -> GetXmin () ) ;
176 hist.over = Histo::Bin ( root -> GetBinContent ( nbins + 1 ) ,
177 root -> GetBinError ( nbins + 1 ) ,
178 axis -> GetXmax () ) ;
181 for (
int ibin = 1 ; ibin <= nbins ; ++ibin )
184 hist.bins.emplace_back( root -> GetBinContent ( ibin ) ,
185 root -> GetBinError ( ibin ) ,
186 axis -> GetBinLowEdge ( ibin ) ) ;
202 const TH1* histo =
root ;
203 return _getHisto ( histo , hist ) ;
214 (
const AIDA::IHistogram1D* aida , Histo& hist )
221 const AIDA::IAxis& axis = aida -> axis () ;
222 const int nbins = axis . bins () ;
225 hist.under = Histo::Bin ( aida -> binHeight ( AIDA::IAxis::UNDERFLOW_BIN ) ,
226 aida -> binError ( AIDA::IAxis::UNDERFLOW_BIN ) ,
227 axis . lowerEdge () ) ;
229 hist.over = Histo::Bin ( aida -> binHeight ( AIDA::IAxis::OVERFLOW_BIN ) ,
230 aida -> binError ( AIDA::IAxis::OVERFLOW_BIN ) ,
231 axis . upperEdge () ) ;
233 for (
int ibin = 0 ; ibin < nbins ; ++ibin )
236 hist.bins.emplace_back ( aida -> binHeight ( ibin ) ,
237 aida -> binError ( ibin ) ,
238 axis . binLowerEdge ( ibin ) ) ;
251 (
const AIDA::IProfile1D* aida ,
260 const AIDA::IAxis& axis = aida -> axis () ;
261 const int nbins = axis . bins () ;
264 hist.under = Histo::Bin ( aida -> binHeight ( AIDA::IAxis::UNDERFLOW_BIN ) ,
266 aida -> binRms ( AIDA::IAxis::UNDERFLOW_BIN ) :
267 aida -> binError ( AIDA::IAxis::UNDERFLOW_BIN ) ,
268 axis . lowerEdge () ) ;
270 hist.over = Histo::Bin ( aida -> binHeight ( AIDA::IAxis::OVERFLOW_BIN ) ,
272 aida -> binRms ( AIDA::IAxis::OVERFLOW_BIN ) :
273 aida -> binError ( AIDA::IAxis::OVERFLOW_BIN ) ,
274 axis . upperEdge () ) ;
276 for (
int ibin = 0 ; ibin < nbins ; ++ibin )
279 hist.bins.emplace_back( aida -> binHeight ( ibin ) ,
281 aida -> binRms ( ibin ) :
282 aida -> binError ( ibin ) ,
283 axis . binLowerEdge ( ibin ) ) ;
293 inline unsigned int rebin
294 (
const unsigned int bins ,
295 const unsigned int imax )
297 if ( 0 == imax ) {
return 1 ; }
298 unsigned int ibin = 1 ;
299 while ( bins > imax * ibin ) { ++ibin ; }
308 std::pair<double,int> decompose (
double v )
310 if ( 0 == v ) {
return std::make_pair ( 0.0 , 0 ) ; }
311 else if ( 1 == v ) {
return std::make_pair ( 1.0 , 0 ) ; }
314 std::pair<double,int> r = decompose ( -v ) ;
315 return std::pair<double,int>( -r.first , r.second ) ;
320 while ( 0.1 > v ) { ++
i ; v *= 10 ; }
321 return std::make_pair ( v , -i ) ;
326 while ( 1 <= v ) { ++
i ; v /= 10 ; }
327 return std::make_pair ( v , i ) ;
329 return std::make_pair ( v , 1 ) ;
336 inline double _pow (
double x ,
unsigned long n )
338 double y = n % 2 ? x : 1;
342 if ( n % 2) { y *= x; }
351 inline double rValMax (
const double v ) ;
357 inline double rValMin (
const double v ) ;
363 inline double rValMax (
const double v )
365 if ( 0 == v ) {
return 0 ; }
366 else if ( 0 > v ) {
return -1 * rValMin ( -v ) ; }
368 std::pair<double,int> r = decompose ( v ) ;
370 const double f = std::ceil ( 20 * r.first ) / 2 ;
371 const int l = r.second - 1 ;
372 return 0 < l ? f * _pow ( 10 , l ) : f / _pow ( 10 , -l ) ;
379 inline double rValMin (
const double v )
381 if ( 0 == v ) {
return 0 ; }
382 else if ( 0 > v ) {
return -1 * rValMax ( -v ) ; }
384 std::pair<double,int> r = decompose ( v ) ;
385 const double f = std::floor ( 20 * r.first ) / 2 ;
386 const int l = r.second - 1 ;
387 return 0 < l ? f * _pow ( 10 , l ) : f / _pow ( 10 , -l ) ;
394 inline std::string yLabel (
const double value )
405 inline std::string xLabel (
const double value )
413 char symbBin (
const Histo::Bin& bin ,
419 if ( errors && yLow <= bin.height && bin.height < yHigh ) {
return '*' ; }
420 else if ( errors && yHigh < bin.height - bin.error ) {
return ' ' ; }
421 else if ( errors && yLow >= bin.height + bin.error ) {
return ' ' ; }
422 else if ( errors ) {
return 'I' ; }
423 else if ( yLow <= bin.height && bin.height < yHigh ) {
return '*' ; }
424 else if ( 0 <= bin.height && yLow <= bin.height && 0 < yHigh && !yNull ) {
return '*' ; }
425 else if ( 0 > bin.height && yHigh > bin.height && 0 >= yLow && !yNull ) {
return '*' ; }
434 std::ostream& dumpText
435 (
const Histo& histo ,
436 const std::size_t width ,
437 const std::size_t height ,
439 std::ostream& stream )
441 if ( 40 > width ) {
return dumpText ( histo , 40 , height , errors , stream ) ; }
442 if ( 200 < width ) {
return dumpText ( histo , 200 , height , errors , stream ) ; }
443 if ( 150 < height ) {
return dumpText ( histo , width , 150 , errors , stream ) ; }
444 if ( 20 > height ) {
return dumpText ( histo , width , 20 , errors , stream ) ; }
445 if ( height > width ) {
return dumpText ( histo , width , width , errors , stream ) ; }
447 const unsigned int nBins = histo.bins.size() ;
451 Histo r = histo.rebin ( rebin ( nBins , width ) ) ;
452 return dumpText ( r , width , height , errors , stream ) ;
456 double yMax = std::max ( rValMax ( histo.maxY ( errors ) ) , 0.0 ) ;
457 double yMin = std::min ( rValMin ( histo.minY ( errors ) ) , 0.0 ) ;
459 if ( yMin == yMax ) { yMax = yMin + 1 ; }
461 std::pair<double,int> r = decompose ( yMax - yMin ) ;
462 double _ny = std::ceil ( 10 * r.first ) ;
463 if ( 1 >= _ny ) { _ny = 10 ; }
464 int yBins = (int) std::max ( 1. , std::ceil ( height / _ny ) ) ;
467 if ( 20 > yBins ) { yBins = 20 ; }
468 const double yScale = ( yMax - yMin ) / yBins ;
472 0 == yBins % 13 ? 13 :
473 0 == yBins % 11 ? 11 :
479 0 == yBins % 4 ? 4 : 10 ;
486 0 == nBins % 4 ? 4 : 10 ;
488 int iNull = histo.nullBin() ;
490 if ( 0 <= iNull ) { iNull %= xSkip ; }
493 stream << std::endl ;
495 for (
int yLine = -1 ; yLine < yBins ; ++yLine )
497 const double yHigh = yMax - yScale * yLine ;
499 const double yLow = yMax - yScale * ( yLine + 1 ) ;
501 std::string line1 =
" " ;
503 const bool ynull = ( yLow <= 0 && 0 < yHigh ) ;
504 const bool yfirst = -1 == yLine || yBins -1 == yLine ;
506 ( 0 == ( yLine + 1 ) % ySkip ) || yfirst || ynull ;
508 if ( ylab ) { line1 += yLabel ( ( yLow <= 0 && 0 < yHigh ) ? 0.0 : yLow ) ; }
509 else { line1 += std::string( 10 ,
' ' ) ; }
514 line1 += symbBin ( histo.under , yLow , yHigh , ynull , errors ) ;
522 for (
auto ibin = histo.bins.cbegin() ;
523 histo.bins.cend() != ibin ; ++ibin )
526 const int i = ibin - histo.bins.cbegin () ;
529 ibin->lower <= 0 && ( ibin + 1 ) != histo.bins.cend() && 0 < (ibin+1)->lower ;
530 const bool xlab = iNull == i % xSkip ;
532 char symb = symbBin ( *ibin, yLow , yHigh , ynull , errors ) ;
536 if ( ( ynull || yfirst ) && xlab ) { symb =
'+' ; }
537 else if ( ynull || yfirst ) { symb =
'-' ; }
539 else if ( ylab && xnull ) { symb =
'+' ; }
540 else if ( xnull ) { symb =
'|' ; }
542 else if ( ylab || xlab ) { symb =
'.' ; }
554 line3 += symbBin ( histo.over , yLow , yHigh , ynull , errors ) ;
556 stream << line1 << line2 << line3 << std::endl ;
561 std::vector<std::string> xlabels ;
562 for (
auto ib = histo.bins.cbegin() ; histo.bins.cend() != ib ; ++ib )
563 { xlabels.push_back ( xLabel ( ib->lower ) ) ; }
565 const std::string oLabel = xLabel ( histo.over.lower ) ;
566 const std::string uLabel = xLabel ( histo.under.lower ) ;
568 static const std::string s_UNDERFLOW (
"UNDERFLOW" ) ;
569 static const std::string s_OVERFLOW (
" OVERFLOW" ) ;
572 for (
unsigned int yLine = 0 ; yLine < 12 ; ++yLine )
574 std::string
line = std::string ( 12 ,
' ' ) ;
576 if ( yLine < s_UNDERFLOW.size() ) { line += s_UNDERFLOW[yLine] ; }
577 else { line +=
' ' ; }
581 if ( uLabel.size() > yLine ) { line += uLabel[yLine] ; }
582 else { line +=
' ' ; }
584 for (
auto ibin = histo.bins.cbegin() ; histo.bins.cend() != ibin ; ++ibin )
586 int ib = ibin - histo.bins.cbegin() ;
587 const bool xlab = ( iNull == ib % xSkip ) ;
588 if ( xlab && yLine < xlabels[ib].size() ) { line += xlabels[ib][yLine] ; }
589 else { line +=
' ' ; }
592 if ( oLabel.size() > yLine ) { line += oLabel[yLine] ; }
593 else { line +=
' ' ; }
597 if ( yLine < s_OVERFLOW.size() ) { line += s_OVERFLOW[yLine] ; }
598 else { line +=
' ' ; }
600 stream << line << std::endl ;
619 (
const AIDA::IHistogram1D* histo ,
620 std::ostream& stream ,
621 const std::size_t width ,
622 const std::size_t height ,
625 stream << std::endl ;
626 if ( !histo ) {
return stream ; }
629 if ( sc.
isFailure() ) {
return stream ; }
658 <<
boost::format (
" Entries :\n | %=9s | %=9s | %=9s | %9s | %=11s | %=11s | %=11s |")
667 <<
boost::format (
" | %=9d | %=9d | %=9d | %=9d | %=11.5g | %=11.5g | %=11.5g |")
668 % histo -> allEntries ()
669 % histo -> entries ()
670 % histo -> binEntries ( AIDA::IAxis::UNDERFLOW_BIN )
671 % histo -> binEntries ( AIDA::IAxis::OVERFLOW_BIN )
672 % histo -> equivalentBinEntries ()
673 % histo -> sumBinHeights ()
674 % histo -> sumAllBinHeights ()
678 const AIDA::IAnnotation& a = histo->annotation () ;
681 stream <<
" Annotation" << std::endl ;
682 for (
int i = 0 ; i < a.size() ; ++
i )
690 stream << std::endl ;
693 return dumpText ( hist , width , height , errors , stream ) ;
708 (
const AIDA::IHistogram1D* histo ,
709 const std::size_t width ,
710 const std::size_t height ,
713 std::ostringstream stream ;
714 histoDump_ ( histo , stream , width , height , errors );
715 return stream.str() ;
730 (
const AIDA::IProfile1D* histo ,
731 std::ostream& stream ,
732 const std::size_t width ,
733 const std::size_t height ,
736 stream << std::endl ;
737 if ( !histo ) {
return stream ; }
740 if ( sc.
isFailure() ) {
return stream ; }
757 <<
boost::format (
" Entries :\n | %=9s | %=9s | %=9s | %9s | %=11s | %=11s |")
766 <<
boost::format (
" | %=9d | %=9d | %=9d | %=9d | %=11.5g | %=11.5g |")
767 % histo -> allEntries ()
768 % histo -> entries ()
769 % histo -> binEntries ( AIDA::IAxis::UNDERFLOW_BIN )
770 % histo -> binEntries ( AIDA::IAxis::OVERFLOW_BIN )
772 % histo -> sumBinHeights ()
773 % histo -> sumAllBinHeights ()
777 const AIDA::IAnnotation& a = histo->annotation () ;
780 stream <<
" Annotation" << std::endl ;
781 for (
int i = 0 ; i < a.size() ; ++
i )
789 stream << std::endl ;
792 return dumpText ( hist , width , height ,
true , stream ) ;
805 (
const AIDA::IProfile1D* histo ,
806 const std::size_t width ,
807 const std::size_t height ,
810 std::ostringstream stream ;
811 histoDump_ ( histo , stream , width , height , spread );
812 return stream.str() ;
827 std::ostream& stream ,
828 const std::size_t width ,
829 const std::size_t height ,
832 const TProfile* profile =
dynamic_cast<const TProfile*
> ( histo ) ;
834 {
return histoDump_ ( profile , stream , width , height ) ; }
836 stream << std::endl ;
837 if ( !histo ) {
return stream ; }
840 if ( sc.
isFailure() ) {
return stream ; }
844 % histo -> GetName ()
847 % histo -> GetTitle ()
853 % histo -> GetMean ()
854 % histo -> GetMeanError ()
858 % histo -> GetRMSError ()
861 % histo -> GetSkewness ()
864 % histo -> GetKurtosis ()
869 <<
boost::format (
" Entries :\n | %=11s | %=11s | %=11s | %=11s | %=11s |")
876 <<
boost::format (
" | %=11.5g | %=11.5g | %=11.5g | %=11.5g | %=11.5g |")
877 % histo -> GetEntries ()
878 % histo -> GetBinContent ( 0 )
879 % histo -> GetBinContent ( histo->GetNbinsX() + 1 )
880 % histo -> GetEffectiveEntries ()
885 return dumpText ( hist , width , height , errors , stream ) ;
899 (
const TProfile* histo ,
900 std::ostream& stream ,
901 const std::size_t width ,
902 const std::size_t height )
904 stream << std::endl ;
905 if ( ! histo ) {
return stream ; }
908 if ( sc.
isFailure() ) {
return stream ; }
912 % histo -> GetName ()
915 % histo -> GetTitle ()
927 <<
boost::format (
" Entries :\n | %=11s | %=11s | %=11s | %=11s |")
933 <<
boost::format (
" | %=11.5g | %=11.5g | %=11.5g | %=11.5g |")
934 % histo -> GetEntries ()
935 % histo -> GetBinContent ( 0 )
936 % histo -> GetBinContent ( histo->GetNbinsX() + 1 )
941 return dumpText ( hist , width , height ,
true , stream ) ;
955 const std::size_t width ,
956 const std::size_t height ,
959 std::ostringstream stream ;
960 histoDump_ ( histo , stream , width , height , errors );
961 return stream.str() ;
974 (
const TProfile* histo ,
975 const std::size_t width ,
976 const std::size_t height )
978 std::ostringstream stream ;
979 histoDump_ ( histo , stream , width , height );
980 return stream.str() ;
static double rmsErr(const AIDA::IHistogram1D *histo)
get an error in the rms value
auto begin(reverse_wrapper< T > &w)
static double meanErr(const AIDA::IHistogram1D *histo)
get an error in the mean value
bool isFailure() const
Test for a status code of FAILURE.
static double rms(const AIDA::IHistogram1D *histo)
get the rms value for the histogram (just for completeness)
auto end(reverse_wrapper< T > &w)
This class is used for returning status codes from appropriate routines.
GAUDI_API double Integral(const Genfun::AbsFunction &function, const double a, const double b, const GaudiMath::Integration::Type type=GaudiMath::Integration::Adaptive, const GaudiMath::Integration::KronrodRule rule=GaudiMath::Integration::Default, const double epsabs=1.e-10, const double epsrel=1.e-7, const size_t size=1000)
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
static double kurtosisErr(const AIDA::IHistogram1D *histo)
get the error in kurtosis for the histogram
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
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
static double skewness(const AIDA::IHistogram1D *histo)
get the skewness for the histogram