19 This module contains set of simple and useful utilities for booking and
20 manipulations with Gaudi-AIDA histograms, inspired by Thomas' request
22 The module contains following public symbols:
24 - book for booking of various 1D,2D&3D-histograms
25 - bookProf for booking of various 1D&2D-profiles
26 - getAsAIDA for retrieval of histograms/profiles from HTS in AIDA format
27 - getAsROOT for retrieval of histograms/profiles from HTS in ROOT format
28 - fill for smart filling of 1D-histogram (AIDA or ROOT)
29 - aida2root for conversion of AIDA histogram to ROOT
30 - HistoStats for many statistical information
31 - HistoFile class for storing histograms to a file
32 - histoDump for dumping of the histogram in text format (a'la HBOOK)
33 - dumpHisto for dumping of the histogram in text format (a'la HBOOK)
36 from __future__
import print_function
38 __author__ =
"Vanya BELYAEV ibelyaev@physics.syr.edu"
69 Helper private auxiliary function to get Application Manager
71 gaudi = kwargs.get(
'gaudi',
None)
75 raise RuntimeError(
'Unable to get valid ApplicationMgr')
77 state = gaudi._isvc.FSMState()
78 if state < cpp.Gaudi.StateMachine.CONFIGURED:
80 state = gaudi._isvc.FSMState()
81 if state < cpp.Gaudi.StateMachine.INITIALIZED:
93 Helper private auxiliary function to get iHistogramSvs
95 svc = kwargs.get(
'service',
None)
97 svc = kwargs.get(
'svc',
None)
101 return gaudi.histsvc()
110 Helper private auxiliary function to get iDataSvs
112 svc = kwargs.get(
'service',
None)
114 svc = kwargs.get(
'svc',
None)
118 return gaudi.evtsvc()
127 The trivial function to book the various 1D,2D&3D-histograms
129 (1) book the trivial 1D histogram with full path
131 >>> h1D = book ( 'path/to/my/histo' , ## path in Histogram Transient Store
132 'cosine of decay angle ' , ## histogram title
133 100 , ## number of bins
137 (2) book the trivial 1D histogram with directory path and string ID :
139 >>> h1D = book ( 'path/to/directory' , ## the path to directory in HTS
140 'H1' , ## string histogram identifier
141 'cosine of decay angle ' , ## histogram title
142 100 , ## number of bins
146 (3) book the trivial 1D histogram with directory path and integer ID :
148 >>> h1D = book ( 'path/to/directory' , ## the path to directory in HTS
149 124 , ## integer histogram identifier
150 'cosine of decay angle ' , ## histogram title
151 100 , ## number of bins
155 (4) book the trivial 2D histogram with full path
157 >>> h1D = book ( 'path/to/my/histo' , ## path in Histogram Transient Store
158 'm12**2 versus m13**2' , ## histogram title
159 50 , ## number of X-bins
162 50 , ## number of Y-bins
166 (5) book the trivial 2D histogram with directory path and literal ID
168 >>> h1D = book ( 'path/to/directory' , ## path in Histogram Transient Store
169 'Dalitz1' , ## literal histogram identifier
170 'm12**2 versus m13**2' , ## histogram title
171 50 , ## number of X-bins
174 50 , ## number of Y-bins
178 (6) book the trivial 2D histogram with directory path and integer ID
180 >>> h1D = book ( 'path/to/directory' , ## path in Histogram Transient Store
181 854 , ## integer histogram identifier
182 'm12**2 versus m13**2' , ## histogram title
183 50 , ## number of X-bins
186 50 , ## number of Y-bins
190 (7) book the trivial 3D histogram with full path
192 >>> h1D = book ( 'path/to/my/histo' , ## path in Histogram Transient Store
193 'x vs y vs z ' , ## histogram title
194 10 , ## number of X-bins
197 10 , ## number of Y-bins
200 10 , ## number of Z-bins
204 (8) book the trivial 3D histogram with directory path and literal ID
206 >>> h1D = book ( 'path/to/directory' , ## path in Histogram Transient Store
207 'xyz' , ## literal histogram identifier
208 'x vs y vs z' , ## histogram title
209 10 , ## number of X-bins
212 10 , ## number of Y-bins
215 10 , ## number of Z-bins
219 (9) book the trivial 3D histogram with directory path and integer ID
221 >>> h1D = book ( 'path/to/directory' , ## path in Histogram Transient Store
222 888 , ## integer histogram identifier
223 'x vs y vs z' , ## histogram title
224 10 , ## number of X-bins
227 10 , ## number of Y-bins
230 10 , ## number of Z-bins
234 Many other booking methods are available,
235 e.g. for the histograms with non-equidistant bins, see IHistogamSvc::book
238 if useROOT
or kwargs.get(
'useROOT',
239 False)
or not kwargs.get(
'useAIDA',
True):
240 from ROOT
import TH1D
244 if not str
is type(a1):
247 return TH1D(a0 + a1, a2, *args[3:])
249 return TH1D(a0, a1, *args[2:])
253 raise RuntimeError(
'Unable to get valid HistogramService ')
255 return svc.book(*args)
258 book.__doc__ +=
'\n\n' +
'\thelp(iHistogramSvc.book) : \n\n' \
259 + iHistogramSvc.book . __doc__
260 book.__doc__ +=
'\n\n' +
'\thelp(IHistogramSvc::book) : \n\n' \
261 + cpp.IHistogramSvc.book . __doc__
270 The trivial function to book 1D&2D profile histograms:
272 (1) book 1D-profile histogram with full path in Histogram Transient Store:
273 >>> histo = bookProf ( 'path/to/my/profile' , ## path in Histogram Transient Store
274 'Energy Correction' , ## the histogram title
275 100 , ## number of X-bins
279 (2) book 1D-profile histogram with directory path and literal ID
280 >>> histo = bookProf ( 'path/to/my/profile' , ## path in Histogram Transient Store
281 'Calibration' , ## the histogram literal identifier
282 'Energy Correction' , ## the histogram title
283 100 , ## number of X-bins
287 (3) book 1D-profile histogram with directory path and integer ID
288 >>> histo = bookProf ( 'path/to/my/profile' , ## path in Histogram Transient Store
289 418 , ## the histogram integer identifier
290 'Energy Correction' , ## the histogram title
291 100 , ## number of X-bins
295 (4) book 2D-profile histogram with full path in Histogram Transient Store:
296 >>> histo = bookProf ( 'path/to/my/profile' , ## path in Histogram Transient Store
297 'Energy Correction' , ## the histogram title
298 50 , ## number of X-bins
301 50 , ## number of Y-bins
305 (5) book 2D-profile histogram with directory path and literal ID
306 >>> histo = bookProf ( 'path/to/my/profile' , ## path in Histogram Transient Store
307 'Calibration' , ## the histogram literal identifier
308 'Energy Correction' , ## the histogram title
309 50 , ## number of X-bins
312 50 , ## number of Y-bins
316 (6) book 2D-profile histogram with directory path and integer ID
317 >>> histo = bookProf ( 'path/to/my/profile' , ## path in Histogram Transient Store
318 418 , ## the histogram integer identifier
319 'Energy Correction' , ## the histogram title
320 50 , ## number of X-bins
323 50 , ## number of Y-bins
327 Many other booking methods are available,
328 e.g. for the histograms with non-equidistant bins, see IHistogamSvc::book
333 raise RuntimeError(
'Unable to get valid HistogramService ')
335 return svc.bookProf(*args)
338 bookProf.__doc__ +=
'\n\n' +
'\thelp(iHistogramSvc.bookProf) : \n\n' \
339 + iHistogramSvc.bookProf . __doc__
340 bookProf.__doc__ +=
'\n\n' +
'\thelp(IHistogramSvc::bookProf) : \n\n' \
341 + cpp.IHistogramSvc.bookProf . __doc__
350 The most trivial function to retrieve the histogram from Histogram Transient Store
351 The histogram is returned by reference to its AIDA-representation (if possible)
353 >>> h = getAsAIDA ( 'some/path/to/my/histogram' )
358 raise RuntimeError(
'Unable to get valid HistogramService ')
360 return svc.getAsAIDA(path)
363 getAsAIDA.__doc__ +=
'\n\n' +
'\thelp(iHistogramSvc.getAsAIDA) : \n\n' \
364 + iHistogramSvc.getAsAIDA . __doc__
365 getAsAIDA.__doc__ +=
'\n\n' +
'\thelp(iHistogramSvc.retrieve) : \n\n' \
366 + iHistogramSvc.retrieve . __doc__
375 The most trivial function to retrieve the histogram from Histogram Transient Store
376 The histogram is returned by reference to its underlying native ROOT-representation (if possible)
378 >>> h = getAsROOT ( 'some/path/to/my/histogram' )
383 raise RuntimeError(
'Unable to get valid HistogramService ')
385 return svc.getAsROOT(path)
388 getAsROOT.__doc__ +=
'\n\n' +
'\thelp(iHistogramSvc.getAsROOT) : \n\n' \
389 + iHistogramSvc.getAsROOT . __doc__
402 The function which allows 'the smart fill' of 1D-histogram
406 The most trivial case, fill with the value
407 >>> fill ( histo , 1.0 )
409 Fill from any iterable object (sequence)
410 >>> fill ( histo , [1,,2,3,4,5,10] )
412 Fill from iterable object and apply the function:
413 >>> fill ( histo , [1,2,3,4,5] , math.sin )
416 >>> fill ( histo , [1,2,3,4,5] , lambda x : x*x )
419 >>> fill ( histo , [1,2,3,4,5] , fun = lambda x : x*x )
421 Use internal attributes:
422 >>> tracks = evtSvc['Rec/Track/Best'] ## iterable container of tracks
423 >>> fill ( histo , tracks , lambda t : t.pt() )
425 Apply the predicate: fill only even numbers:
426 >>> fill ( histo , [1,2,3,4,5,6,7] , lambda x : x , lambda y : y%2 )
428 The same (omit the trivial function) :
429 >>> fill ( histo , [1,2,3,4,5,6,7] , cut = lambda y : y%2 )
431 Apply the predicate: fill only pt for positively charged tracks:
432 >>> tracks = evtSvc['Rec/Track/Best']
433 >>> fill ( histo , tracks , lambda t : t.pt() , lambda t : 0<t.charge() )
436 >>> fill ( histo , tracks ,
437 fun = lambda t : t.pt() ,
438 cut = lambda t : 0<t.charge() )
440 Ordinary functions are also fine:
441 >>> def myfun ( track ) : return sin( track.pt() + track.p() )
442 >>> def mycut ( track ) : return track.p() > 100 * GeV
443 >>> fill ( histo , tracks , myfun , mycut )
445 The 'data' could be the address in TES, in this case the object
446 is retrieved from TES and the method is applied to the objects,
448 >>> fill ( histo , ## the reference to the histogram
449 'Rec/Track/Best' , ## the location of objects in TES
450 lambda t : t.pt() ) ## function to be used for histogram fill
451 >>> fill ( histo , ## the reference to the histogram
452 'Rec/Track/Best' , ## the address of objects in TES
453 lambda t : t.pt() , ## the function to be used for histogram fill
454 lambda t : t.charge()>0 ) ## the criteria to select tracks
456 The arguments 'fun' and 'cut' could be strings, in this case
457 they are evaluated by python before usage.
458 This option could be often very useful.
463 if type(data) == str:
466 return fill(histo, data, fun, cut, **kwargs)
470 fun = eval(fun, globals())
474 cut = eval(cut, globals())
476 if not hasattr(data,
'__iter__'):
479 if not hasattr(histo,
'fill')
and hasattr(histo,
'Fill'):
480 setattr(histo,
'fill', getattr(histo,
'Fill'))
485 histo.fill(fun(item))
492 aida2root = cpp.Gaudi.Utils.Aida2ROOT.aida2root
502 >>> aida = ... ## get AIDA histogram
503 >>> root = aida.toROOT() ## convert it to ROOT
509 _to_root_.__doc__ += aida2root.__doc__
511 for t
in (cpp.AIDA.IHistogram3D, cpp.AIDA.IHistogram2D, cpp.AIDA.IHistogram1D,
512 cpp.AIDA.IProfile2D, cpp.AIDA.IProfile1D):
513 if not hasattr(t,
'Fill')
and hasattr(t,
'fill'):
514 setattr(t,
'Fill', getattr(t,
'fill'))
515 for attr
in (
'toROOT',
'toRoot',
'asROOT',
'asRoot',
'AsROOT',
'AsRoot'):
516 if not hasattr(t, attr):
517 setattr(t, attr, _to_root_)
519 cpp.AIDA.IHistogram3D. __repr__ =
lambda s: cpp.GaudiAlg.Print3D.toString(
521 cpp.AIDA.IHistogram3D.__str__ = cpp.AIDA.IHistogram3D.__repr__
523 HistoStats = cpp.Gaudi.Utils.HistoStats
531 Evaluate 'bin-by-bin' momentum of order 'order' around the value 'value'
535 >>> print(h1.moment ( 5 ))
538 return HistoStats.moment(self, order, value)
547 Evaluate error for 'bin-by-bin' momentum of order 'order' around the value 'value'
551 >>> print(h1.momentErr ( 5 ))
554 return HistoStats.momentErr(self, order)
563 Evaluate 'bin-by-bin' central momentum (around mean value)
567 >>> print(h1.centralMoment ( 5 ))
570 return HistoStats.centralMoment(self, order)
579 Evaluate error for 'bin-by-bin' central momentum (around mean value)
583 >>> print(h1.centralMomentErr ( 5 ))
586 return HistoStats.centralMomentErr(self, order)
595 Evaluate 'bin-by-bin' skewness for 1D AIDA histogram
598 >>> print(h1.skewness())
601 return HistoStats.skewness(self)
610 Evaluate error for 'bin-by-bin' skewness
613 >>> print(h1.skewnessErr())
616 return HistoStats.skewnessErr(self)
625 Evaluate 'bin-by-bin' kurtosis
628 >>> print(h1.kurtosis ())
631 return HistoStats.kurtosis(self)
640 Evaluate error for 'bin-by-bin' kurtotis for 1D AIDA histogram
643 >>> print(h1.kurtotisErr())
646 return HistoStats.kurtosisErr(self)
654 Number of equivalent entries
656 return HistoStats.nEff(self)
664 Evaluate the MEAN value
666 return HistoStats.mean(self)
674 Evaluate the error for MEAN estimate
676 return HistoStats.meanErr(self)
684 Evaluate the RMS for AIDA histogram
686 return HistoStats.rms(self)
694 Evaluate the error for RMS estimate
696 return HistoStats.rmsErr(self)
704 Get an error in the sum bin height ('in-range integral')
706 return HistoStats.sumBinHeightErr(self)
713 """ Get an error in the sum bin height ('in-range integral') """
714 return HistoStats.sumAllBinHeightErr(self)
722 The fraction of overflow entries (useful for shape comparison)
724 return HistoStats.overflowEntriesFrac(self)
732 The error for fraction of overflow entries (useful for shape comparison)
734 return HistoStats.overflowEntriesFracErr(self)
742 The fraction of underflow entries (useful for shape comparison)
744 return HistoStats.underflowEntriesFrac(self)
752 The error for fraction of underflow entries (useful for shape comparison)
754 return HistoStats.underflowEntriesFracErr(self)
762 The fraction of overflow integral (useful for shape comparison)
764 return HistoStats.overflowIntegralFrac(self)
772 The error for fraction of overflow integral (useful for shape comparison)
774 return HistoStats.overflowIntegralFracErr(self)
782 The fraction of underflow integral (useful for shape comparison)
784 return HistoStats.underflowIntegralFrac(self)
792 The error for fraction of underflow integral (useful for shape comparison)
794 return HistoStats.underflowIntegralFracErr(self)
805 Get number of entries in histogram up to the certain bin (not-included)
807 attention: underflow bin is included!
810 >>> print(h1.nEntries ( 10 ))
812 Get number of entries in histogram form the certain
813 minimal bin up to the certain maximal bin (not-included)
816 >>> print(h1.nEntries ( 10 , 15 ))
819 if i2 < i1
or i2 < 0:
820 return HistoStats.nEntries(self, i1)
821 return HistoStats.nEntries(self, i1, i2)
829 Get the fraction of entries in histogram up to the certain bin (not-included)
831 attention: underflow bin is included!
834 >>> print(h1.nEntriesFrac ( 10 ))
836 Get the fraction of entries in histogram form the certain
837 minimal bin up to the certain maximal bin (not-included)
840 >>> print(h1.nEntriesFrac ( 10 , 15 ))
843 if i2 < i1
or i2 < 0:
844 return HistoStats.nEntriesFrac(self, i1)
845 return HistoStats.nEntriesFrac(self, i1, i2)
853 Get error for fraction of entries in histogram up to the certain bin (not-included)
855 attention: underflow bin is included!
858 >>> print(h1.nEntriesFracErr( 10 ))
860 Get error fraction of entries in histogram form the certain
861 minimal bin up to the certain maximal bin (not-included)
864 >>> print(h1.nEntriesFracErr ( 10 , 15 ))
867 if i2 < i1
or i2 < 0:
868 return HistoStats.nEntriesFracErr(self, i1)
869 return HistoStats.nEntriesFracErr(self, i1, i2)
873 i1DH = cpp.AIDA.IHistogram1D
875 if not hasattr(i1DH,
'moment'):
876 i1DH.moment = _moment_
877 if not hasattr(i1DH,
'momentErr'):
878 i1DH.momentErr = _momentErr_
879 if not hasattr(i1DH,
'centralMoment'):
880 i1DH.centralMoment = _centralMoment_
881 if not hasattr(i1DH,
'momentMomentErr'):
882 i1DH.centralMomentErr = _centralMomentErr_
883 if not hasattr(i1DH,
'nEff'):
885 if not hasattr(i1DH,
'mean'):
887 if not hasattr(i1DH,
'meanErr'):
888 i1DH.meanErr = _meanErr_
889 if not hasattr(i1DH,
'rms'):
891 if not hasattr(i1DH,
'rmsErr'):
892 i1DH.rmsErr = _rmsErr_
893 if not hasattr(i1DH,
'skewness'):
894 i1DH.skewness = _skewness_
895 if not hasattr(i1DH,
'skewnessErr'):
896 i1DH.skewnessErr = _skewnessErr_
897 if not hasattr(i1DH,
'kurtosis'):
898 i1DH.kurtosis = _kurtosis_
899 if not hasattr(i1DH,
'kurtosisErr'):
900 i1DH.kurtosisErr = _kurtosisErr_
902 if not hasattr(i1DH,
'overflowEntriesFrac'):
903 i1DH.overflowEntriesFrac = _overflowEntriesFrac_
904 if not hasattr(i1DH,
'overflowEntriesFracErr'):
905 i1DH.overflowEntriesFracErr = _overflowEntriesFracErr_
906 if not hasattr(i1DH,
'underflowEntriesFrac'):
907 i1DH.underflowEntriesFrac = _underflowEntriesFrac_
908 if not hasattr(i1DH,
'underflowEntriesFracErr'):
909 i1DH.underflowEntriesFracErr = _underflowEntriesFracErr_
911 if not hasattr(i1DH,
'overflowIntegralFrac'):
912 i1DH.overflowIntegralFrac = _overflowIntegralFrac_
913 if not hasattr(i1DH,
'overflowIntegralFracErr'):
914 i1DH.overflowIntegralFracErr = _overflowIntegralFracErr_
915 if not hasattr(i1DH,
'underflowIntegralFrac'):
916 i1DH.underflowIntegralFrac = _underflowIntegralFrac_
917 if not hasattr(i1DH,
'underflowIntegralFracErr'):
918 i1DH.underflowIntegralFracErr = _underflowIntegralFracErr_
920 if not hasattr(i1DH,
'nEntries'):
921 i1DH.nEntries = _nEntries_
922 if not hasattr(i1DH,
'nEntriesFrac'):
923 i1DH.nEntriesFrac = _nEntriesFrac_
924 if not hasattr(i1DH,
'nEntriesFracErr'):
925 i1DH.nEntriesFracErr = _nEntriesFracErr_
932 Get the path in THS for the given AIDA object:
935 >>> print(aida.path())
938 return cpp.Gaudi.Utils.Histos.path(self)
941 iBH = cpp.AIDA.IBaseHistogram
942 if not hasattr(iBH,
'path'):
944 if not hasattr(iBH,
'TESpath'):
946 if not hasattr(iBH,
'location'):
947 iBH.location = _path_
954 Dump the histogram/profile in text format (a'la HBOOK)
957 >>> print(dumpHisto ( histo ))
959 >>> print(histo.dump())
960 >>> print(histo.dump( 20 , 20 ))
961 >>> print(histo.dump( 20 , 20 , True ))
966 return cpp.Gaudi.Utils.Histos.histoDump(histo, *args)
969 __dumpHisto__.__doc__ =
'\n' + cpp.Gaudi.Utils.Histos.histoDump.__doc__
973 histoDump = __dumpHisto__
974 dumpHisto = __dumpHisto__
976 for t
in (cpp.AIDA.IHistogram1D, cpp.AIDA.IProfile1D, ROOT.TH1D, ROOT.TH1F,
977 ROOT.TH1, ROOT.TProfile):
978 for method
in (
'dump',
'dumpHisto',
'dumpAsText'):
979 if not hasattr(t, method):
980 setattr(t, method, __dumpHisto__)
987 Class to write histograms to a ROOT file.
988 hFile = HistoFile("myFile.root")
994 hFile.save(myHisto0, myHisto1, myHisto2)
995 histoList = [h0, h1, h2, h3]
996 hFile.save(histoList)
1000 __author__ =
"Juan Palacios juan.palacios@nikhef.nl"
1003 self.
file = ROOT.TFile(fileName,
"RECREATE")
1004 from GaudiPython
import gbl
1007 gbl.AIDA.IHistogram1D, gbl.AIDA.IHistogram2D,
1008 gbl.AIDA.IHistogram3D, gbl.AIDA.IProfile1D, gbl.AIDA.IProfile2D,
1013 histoType =
type(histo)
1021 This function stores histograms on the file for future saving.
1022 It takes an arbitrary number of AIDA or ROOT histograms or
1026 if type(args[0]) == list:
1041 if '__main__' == __name__:
1046 print(sys.modules[__name__].__dict__[o].__doc__)