29 *******************************************************************************
30 * * 'Physisics do not like it, *
31 * * physisics do not need it, *
32 * * physisics do not use it' *
33 * * ****************************
35 * Helper module, which effectively 'imports' few useful C++ algorithmic *
36 * base classes into Python *
38 *******************************************************************************
39 * The major imported classes are : *
41 * (1) GaudiAlgo - analogue for GaudiAlgorithm C++ class from GaudiAlg package *
42 * (2) HistoAlgo - analogue for GaudiHistoAlg C++ class from GaudiAlg package *
43 * (3) TupleAlgo - analogue for GaudiTupleAlg C++ class from GaudiAlg package *
44 *******************************************************************************
48 __author__ =
"Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr"
78 from GaudiKernel
import ROOT6WorkAroundEnabled
96 AlgDecorator = cpp.GaudiPython.AlgDecorator
97 HistoDecorator = cpp.GaudiPython.HistoDecorator
98 TupleAlgDecorator = cpp.GaudiPython.TupleAlgDecorator
99 TupleDecorator = cpp.GaudiPython.TupleDecorator
127 def _tool_(self, interface, typename, name=None, parent=None, create=True):
129 Useful method to locate the tool a certain
134 t1 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator')
135 # locate private tool
136 t2 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator',parent=self)
137 # locate public tool with defined name
138 t3 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator/MyExt1')
139 # locate private tool with defined name
140 t4 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator/MyExt2',parent=self)
141 # locate public tool with defined name
142 t5 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator','MyExt3')
143 # locate private tool with defined name
144 t6 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator','MyExt4',parent=self)
148 interface = cpp.IAlgTool
152 typename +=
"/" + name
153 _tool = AlgDecorator.tool_(self, typename, parent, create)
158 self.Warning(
"Invalid cast to interface %s" % interface)
180 Useful method to locate a service:
184 ntsvc = self.svc( INTupleSvc , 'NTUpleSvc' )
188 interface = cpp.IInterface
189 _svc = AlgDecorator.svc_(self, name, create)
194 self.Warning(
"Invalid cast to interface %s" % interface)
208 The constructor from unique algorithm instance name & parameters
210 self._Base.__init__(self, self, name)
212 algMgr = appMgr._algmgr
213 status = algMgr.addAlgorithm(self)
214 if status.isFailure():
215 raise RuntimeError(
'Unable to add Algorithm "' + name +
'"')
218 setattr(self, key, args[key])
220 if "GaudiPythonAlgos" not in appMgr.__dict__:
221 appMgr.__dict__[
"GaudiPythonAlgos"] = []
222 appMgr.__dict__[
"GaudiPythonAlgos"].append(self)
234 The default initialization (initialization of base C++ class + data)
236 status = self._Base.initialize_(self)
237 if status.isFailure():
241 _e = self._Base.evtSvc(self)
245 _d = self._Base.detSvc(self)
261 The default initialization (initialization of base C++ class + data members)
264 if status.isFailure():
268 _h = self._Base.histoSvc(self)
284 The default initialization (initialization of base C++ class + data members)
287 if status.isFailure():
291 if self.produceNTuples():
292 _n = self._Base.ntupleSvc(self)
296 if self.produceEvtCols():
297 _n = self._Base.evtColSvc(self)
325 Trivial helper function to access Event Data and Event Data Service
329 # get event data service
333 hits = self.evtSvc('MC/Calo/Hits')
337 return self._evtSvc_[location]
361 Trivial helper function to access Detector Data and Event Data Service
364 # get detector data service
368 lhcb = self.detSvc('/dd/Structure/LHCb')
372 return self._detSvc_[location]
396 Trivial helper function to access Histogram Data and Histogram Data Service
400 # get histogram data service
401 svc = self.histoSvc()
404 histo = self.histoSvc('/stat/Calo/1')
407 return self._histoSvc_
408 return self._histoSvc_[address]
417 Trivial function to access the data in TES using the data service
419 return self._evtSvc_[location]
428 Trivial function to access the data in TDS using data service
430 return self._detSvc_[location]
437 def _get_(self, location, rootInTES=True):
439 Get the object from Transient Event Store using GaudiCommon machinery,
440 respecting RootInTES behaviour
442 return AlgDecorator.get_(self, location, rootInTES)
451 Check the object in Transient Event Store using GaudiCommon machinery,
452 respecting RootInTES behaviour
454 return AlgDecorator.exist_(self, location, rootInTES)
463 Trivial function to access N-Tuple Service
465 return self._ntupleSvc_
474 Trivial function to access Event Collection Service
476 return self._evtcolSvc_
483 The default finalization : finalize the base C++ class
485 status = self._Base.finalize_(self)
501 The trivial function which checks the existence of the property with given name
503 return cpp.Gaudi.Utils.hasProperty(self, pname)
512 Get the property by name
514 if not self.hasProperty(pname):
515 raise AttributeError(
"property %s does not exist" % pname)
525 Set the property from the value
527 if not self.hasProperty(pname):
528 raise AttributeError(
"property %s does not exist" % pname)
529 return self._ialg.__setattr__(pname, pvalue)
538 Get the attribute (or property)
539 - if the attribute name corresponds to the property name, property value is returned
541 if self.hasProperty(pname):
547 return getattr(self._ialg, pname)
548 except AttributeError:
550 raise AttributeError(
"attribute/property %s does not exist" % pname)
559 Set the attribute (or property) :
560 - if the attribute name corresponds to the property name, the property is updated
562 if not self.hasProperty(pname):
563 self.__dict__[pname] = pvalue
565 self._ialg.__setattr__(pname, pvalue)
568 _GaudiAlgorithm = cpp.GaudiPython.PyAlg(
"GaudiAlgorithm")
569 _GaudiHistoAlg = cpp.GaudiPython.PyAlg(
"GaudiHistoAlg")
570 _GaudiTupleAlg = cpp.GaudiPython.PyAlg(
"GaudiTupleAlg")
639 *******************************************************************************
640 * * 'Physisics do not like it, *
641 * * physisics do not need it, *
642 * * physisics do not use it' *
643 * * ****************************
646 * from GaudiAlg.Algs import GaudiAlgo, SUCCESS *
648 * class MyClass(GaudiAlgo) : *
649 * ' My specific Algorithm, derived from GaudiAlgo base class ' *
650 * def __init__( self , name , **args ) : *
651 * 'Constructor from algorithm instance name & parameters' *
652 * #invoke the constructor of base class *
653 * GaudiAlgo.__init__(self , name , **args ) *
655 * def initialize ( self ) : *
656 * 'Algorithm initialization' *
657 * # initialize the base class *
658 * status = GaudiAlgo.initialize( self ) *
659 * if status.isFailure() : return status *
661 * # locate the services and tools *
663 * # locate some tool: *
664 * extrapolator = self.tool(ITrExtrapolator,'TrExtrapolator') *
666 * # locate the service *
667 * rndmSvc = self.svc(IRndmGenSvc, 'RndmGenSvc') *
672 * def execute ( self ) : *
673 * 'Major method (from IAlgorithm interface)' *
675 * # get some data from Transient Event Store *
676 * tracks = self.get('/Event/Rec/Tracks') *
679 * c1 = self.counter('#Tracks') *
680 * c2 = self.counter('No Tracks') *
681 * if tracks.empty : *
683 * c1 += tracks->size() *
685 * if 1000 < tracks.size() : *
686 * return self.Error('The event is *VERY* busy') *
690 *******************************************************************************
769 *******************************************************************************
770 * * 'Physisics do not like it, *
771 * * physisics do not need it, *
772 * * physisics do not use it' *
773 * * ****************************
776 * from GaudiAlg.Algs import HistoAlgo, SUCCESS *
778 * class MyClass(HistoAlgo) : *
779 * ' My specific Algorithm, derived from GaudiAlgo base class ' *
780 * def __init__( self , name , **args ) : *
781 * 'Constructor from algorithm instance name' *
782 * #invoke the constructor of base class *
783 * HistoAlgo.__init__(self , name , **args ) *
785 * def execute ( self ) : *
786 * 'Major method (from IAlgorithm interface)' *
788 * # get some data from Transient Event Store *
789 * tracks = self.get('/Event/Rec/Tracks') *
791 * self.plot1D ( tracks->size() , '#tracks' , 0 , 100 ) *
795 * Alternatively the histogram could be booked in advance: *
797 * class MyClass(HistoAlgo) : *
798 * ' My specific Algorithm, derived from GaudiAlgo base class ' *
799 * def __init__( self , name ) : *
800 * 'Constructor from algorithm instance name' *
801 * #invoke the constructor of base class *
802 * HistoAlgo.__init__(self , name ) *
804 * def initialize ( self ) : *
805 * 'Algorithm initialization' *
806 * # initialize the base class *
807 * status = HistoAlgo.initialize( self ) *
808 * if status.isFailure() : return status *
810 * # book the histogram *
811 * self.h1 = selff.book1D ( '#tracks' , 0 , 100 ) *
816 * def execute ( self ) : *
817 * 'Major method (from IAlgorithm interface)' *
819 * # get some data from Transient Event Store *
820 * tracks = self.get('/Event/Rec/Tracks') *
822 * # fill the histogram *
823 * self.h1.fill ( tracks->size() ) *
827 *******************************************************************************
883 *******************************************************************************
884 * * 'Physisics do not like it, *
885 * * physisics do not need it, *
886 * * physisics do not use it' *
887 * * ****************************
890 * from GaudiAlg.Algs import TupleAlgo, SUCCESS *
892 * class MyClass(TupleAlgo) : *
893 * ' My specific Algorithm, derived from TupleAlgo base class ' *
894 * def __init__( self , name , **args ) : *
895 * 'Constructor from algorithm instance name & parameters' *
896 * #invoke the constructor of base class *
897 * TupleAlgo.__init__(self , name , **args ) *
899 * def execute ( self ) : *
900 * 'Major method (from IAlgorithm interface)' *
902 * # get some data from Transient Event Store *
903 * tracks = self.get('/Event/Rec/Tracks') *
905 * tup = self.nTuple('My N-Tuple') *
907 * for track in tracks : *
911 * chi2 = track.chi2 () *
914 * tup.column ( 'pt' , pt ) *
915 * tup.column ( 'p' , p ) *
916 * tup.column ( 'chi2' , chi2 ) *
922 *******************************************************************************
937 GaudiAlgo._Base = _GaudiAlgorithm
938 HistoAlgo._Base = _GaudiHistoAlg
939 TupleAlgo._Base = _GaudiTupleAlg
942 GaudiAlgo.initialize = _initialize_
943 HistoAlgo.initialize = _initialize_histo_
944 TupleAlgo.initialize = _initialize_tuple_
949 The stub 'start' method needed by the internal implementation of PyAlg<>.
955 GaudiAlgo.start = _start_
956 HistoAlgo.start = _start_
957 TupleAlgo.start = _start_
962 The fictive 'execute' method, which MUST be overwitten by user
964 raise RuntimeError(
"Execute method is not implemented for %s" % self.name())
967 GaudiAlgo.execute = _execute_
968 HistoAlgo.execute = _execute_
969 TupleAlgo.execute = _execute_
974 The stub 'stop' method needed by the internal implementation of PyAlg<>.
980 GaudiAlgo.stop = _stop_
981 HistoAlgo.stop = _stop_
982 TupleAlgo.stop = _stop_
989 The basic method to fill (book-on-demand) 1D-histogram
991 The histogram will be created/booked dautomatically according to the
994 - literal or numerical ID (optional)
998 - number of bins (default is 100)
1000 The reference to the histogram is returned and could be used for later manipulations
1003 return HistoDecorator.plot1D(s, *a)
1011 The basic method to fill (book-on-demand) 2D-histogram
1013 The histogram will be created/booked dautomatically according to the
1016 - literal or numerical ID (optional)
1022 - number of X-bins (default is 50)
1023 - number of Y-bins (default is 50)
1025 The reference to the histogram is returned and could be used for later manipulations
1028 return HistoDecorator.plot2D(s, *a)
1036 The basic method to fill (book-on-demand) 3D-histogram
1038 The histogram will be created/booked dautomatically according to the
1041 - literal or numerical ID (optional)
1049 - number of X-bins (default is 10)
1050 - number of Y-bins (default is 10)
1051 - number of Y-bins (default is 10)
1053 The reference to the histogram is returned and could be used for later manipulations
1056 return HistoDecorator.plot3D(s, *a)
1064 The basic method to fill (book-on-demand) 1D profile histogram
1066 The profile histogram will be created/booked dautomatically
1067 according to the specifications:
1069 - literal or numerical ID (optional)
1073 - number of X-bins (default is 100)
1075 The reference to the histogram is returned and could be used for later manipulations
1078 return HistoDecorator.profile1D(s, *a)
1086 The basic method to fill (book-on-demand) 2D profile histiogram
1088 The profile histogram will be created/booked automatically
1089 according to the specifications:
1091 - literal or numerical ID (optional)
1097 - number of X-bins (default is 50)
1098 - number of Y-bins (default is 50)
1100 The reference to the histogram is returned and could be used for later manipulations
1103 return HistoDecorator.profile2D(s, *a)
1108 _plot1D_.__doc__ +=
"\n" + HistoDecorator.plot1D.__doc__
1109 _plot2D_.__doc__ +=
"\n" + HistoDecorator.plot2D.__doc__
1110 _plot3D_.__doc__ +=
"\n" + HistoDecorator.plot3D.__doc__
1111 _profile1D_.__doc__ +=
"\n" + HistoDecorator.profile1D.__doc__
1112 _profile2D_.__doc__ +=
"\n" + HistoDecorator.profile2D.__doc__
1117 if not issubclass(t, list)
and not issubclass(t, tuple):
1119 for klass
in klasses:
1120 klass.plot = _plot1D_
1121 klass.plot1D = _plot1D_
1122 klass.plot2D = _plot2D_
1123 klass.plot3D = _plot3D_
1124 klass.profile1D = _profile1D_
1125 klass.profile2D = _profile2D_
1135 Retrieve (book-on-demand) N-Tuple object
1137 return TupleAlgDecorator.nTuple(s, *a)
1145 Retrieve (book-on-demand) N-Tuple object for Event Tag Collections
1147 return TupleAlgDecorator.evtCol(s, *a)
1150 _nTuple_.__doc__ +=
"\n" + TupleAlgDecorator.nTuple.__doc__
1151 _evtCol_.__doc__ +=
"\n" + TupleAlgDecorator.evtCol.__doc__
1156 if not issubclass(t, list)
and not issubclass(t, tuple):
1158 for klass
in klasses:
1159 klass.nTuple = _nTuple_
1160 klass.evtCol = _evtCol_
1161 klass.ntupleSvc = _ntupleSvc
1162 klass.tupleSvc = _ntupleSvc
1163 klass.ntupSvc = _ntupleSvc
1164 klass.tupSvc = _ntupleSvc
1165 klass.evtColSvc = _evtcolSvc
1166 klass.evtcolSvc = _evtcolSvc
1173 Tuple = cpp.Tuples.Tuple
1174 _Dec = TupleDecorator
1178 """Helper decorator class to workaround ROOT-6697"""
1183 dispatcher = func.disp
if hasattr(func,
"disp")
else func.__overload__
1185 mapping = {int:
"int", bool:
"bool", float:
"double"}
1188 "const Tuples::Tuple& tuple, const string& name, const %s value"
1191 mapping[k] = dispatcher(signature)
1196 Explicitly call the explicit signature for the case with 3 arguments and
1197 the last one is 'int', 'bool' or 'float', for the other cases fall back
1198 on the default dispatcher.
1206 return self.
func(*a)
1210 hasattr(_Dec.column,
"disp")
or hasattr(_Dec.column,
"__overload__")
1217 Access to underlying INTuple object
1219 return _Dec.nTuple(s, *a)
1224 Access to underlying NTuple::Tuple object
1226 return _Dec.ntuple(s, *a)
1231 Valid NTuple::Tuple object?
1233 return _Dec.valid(s, *a)
1238 Commit the row/record to n-tuple
1240 return _Dec.write(s, *a)
1245 Fill the certain column to n-tuple
1247 return _Dec.column(s, *a)
1252 Fill the 'long long' column
1254 return _Dec.column_ll(s, *a)
1259 Fill the 'unsigned long long' column
1261 return _Dec.column_ull(s, *a)
1266 Fill the fixed-size array column
1268 return _Dec.array(s, *a)
1273 Fill the fixed-size matrix column
1275 return _Dec.matrix(s, *a)
1280 Fill the floating-size array column
1282 return _Dec.farray(s, *a)
1287 Fill the floating-size matrix column
1289 return _Dec.fmatrix(s, *a)
1292 _t_nTuple_.__doc__ +=
"\n" + _Dec.nTuple.__doc__
1293 _t_ntuple_.__doc__ +=
"\n" + _Dec.ntuple.__doc__
1294 _t_valid_.__doc__ +=
"\n" + _Dec.valid.__doc__
1295 _t_write_.__doc__ +=
"\n" + _Dec.write.__doc__
1296 _t_column_.__doc__ +=
"\n" + _Dec.column.__doc__
1297 _t_column_ll_.__doc__ +=
"\n" + _Dec.column_ll.__doc__
1298 _t_column_ull_.__doc__ +=
"\n" + _Dec.column_ull.__doc__
1299 _t_array_.__doc__ +=
"\n" + _Dec.array.__doc__
1300 _t_matrix_.__doc__ +=
"\n" + _Dec.matrix.__doc__
1301 _t_farray_.__doc__ +=
"\n" + _Dec.farray.__doc__
1302 _t_fmatrix_.__doc__ +=
"\n" + _Dec.fmatrix.__doc__
1304 Tuple.nTuple = _t_nTuple_
1305 Tuple.ntuple = _t_ntuple_
1306 Tuple.valid = _t_valid_
1307 Tuple.write = _t_write_
1308 Tuple.column = _t_column_
1309 Tuple.column_ll = _t_column_ll_
1310 Tuple.column_ull = _t_column_ull_
1311 Tuple.array = _t_array_
1312 Tuple.matrix = _t_matrix_
1313 Tuple.farray = _t_farray_
1314 Tuple.fmatrix = _t_fmatrix_
1321 "eventSvc": _evtSvc,
1323 "histoSvc": _histoSvc,
1324 "histSvc": _histoSvc,
1329 "finalize": _finalize_,
1331 "hasProperty": _hasProperty_,
1332 "getProperty": _getProperty_,
1333 "setProperty": _setProperty_,
1334 "__setattr__": _set_attr_,
1335 "__getattr__": _get_attr_,
1342 if not issubclass(t, list)
and not issubclass(t, tuple):
1344 for _alg
in klasses:
1345 for key
in _alg_map_:
1346 setattr(_alg, key, _alg_map_[key])
1360 """Helper function to fill histogram/ntuple using 'map'-operation"""
1365 if hasattr(sequence,
"size"):
1366 vct.reserve(vct.size() + sequence.size())
1367 elif hasattr(sequence,
"__len__"):
1368 vct.reserve(vct.size() + len(sequence))
1369 for object
in sequence:
1370 vct.push_back(
func(object))
1386 _func = getattr(AlgDecorator, method)
1387 _num = _func(self, _tools)
1388 if _tools.size() != _num:
1389 raise RuntimeError(
"Unable to extract Tools")
1391 for _tool
in _tools:
1392 _res += [
iAlgTool(_tool.name(), _tool)]
1401 Retrieve the list of tools,
1402 aquired by component through GaudiCommon<TYPE> base:
1404 >>> alg = ... ## get the algorithm
1405 >>> tools = alg.Tools() ## get the tools
1406 >>> for tool in tools :
1410 _cmp = getattr(self,
"_ialg")
1412 self.retrieveInterface()
1413 _cmp = getattr(self,
"_ialg")
1422 Retrieve the list of tools,
1423 aquired by component through GaudiCommon<TYPE> base:
1425 >>> tool = ... ## get the tool
1426 >>> tools = tool.Tools() ## get the tools
1427 >>> for t in tools :
1431 _cmp = getattr(self,
"_itool")
1433 self.retrieveInterface()
1434 _cmp = getattr(self,
"_itool")
1447 _func = getattr(AlgDecorator, method)
1448 return _func(self, name)
1456 Retrieve the counter managed GaudiCommon<TYPE> base by name:
1458 >>> alg = ... ## get the algorithm
1459 >>> cnt = alg.Counter('#accept') ## get the counter
1463 _cmp = getattr(self,
"_ialg")
1465 self.retrieveInterface()
1466 _cmp = getattr(self,
"_ialg")
1475 Retrieve the counter managed GaudiCommon<TYPE> base by name:
1477 >>> tool = ... ## get the tool
1478 >>> cnt = tool.Counter('#accept') ## get the counter
1482 _cmp = getattr(self,
"_itool")
1484 self.retrieveInterface()
1485 _cmp = getattr(self,
"_itool")
1492 cpp.GaudiAlg.ID.__repr__ = cpp.GaudiAlg.ID.idAsString
1493 cpp.GaudiAlg.ID.__str__ = cpp.GaudiAlg.ID.idAsString
1494 cpp.StatEntity.__repr__ = cpp.StatEntity.toString
1495 cpp.StatEntity.__str__ = cpp.StatEntity.toString
1502 Get All histogram form the component
1514 _fun = getattr(HistoDecorator, method)
1515 _num = _fun(component, _ids, _his)
1516 if _ids.size() != _num
or _his.size() != _num:
1517 raise RuntimeError(
"Unable to extract Histos!")
1518 for _i
in range(0, _num):
1521 _id = _id.numericID()
1523 _id = _id.literalID()
1525 _id = _id.idAsString()
1526 _res[_id] = _his[_i]
1531 id = cpp.GaudiAlg.ID(name)
1532 for i
in (name, id.literalID(), id.numericID(), id.idAsString(), id):
1533 h = _res.get(i,
None)
1545 Retrieve all histograms & profiles, booked through GauydiHistos<TYPE> base:
1547 >>> alg = ... ## get the algorithm
1548 >>> histos = alg.Histos() ## get all histograms & profiles
1549 >>> for key in histos :
1550 ... print(key, histos[key])
1552 Retrive the histogram with the certain ID :
1554 >>> alg = ... ## get the algorithm
1555 >>> histo = alg.Histos('some histo ID') ## get the histo by ID
1559 _cmp = getattr(self,
"_ialg")
1561 self.retrieveInterface()
1562 _cmp = getattr(self,
"_ialg")
1571 Retrieve all histograms & profiles, booked through GauydiHistos<TYPE> base:
1573 >>> tool = ... ## get the tool
1574 >>> histos = tool.Histos() ## get all histograms & profiles
1575 >>> for key in histos :
1576 ... print(key, histos[key])
1578 Retrive the historgam with certain ID :
1580 >>> tool = ... ## get the tool
1581 >>> histo = tool.Histos('some histo ID') ## get the histo by ID
1585 _cmp = getattr(self,
"_itool")
1587 self.retrieveInterface()
1588 _cmp = getattr(self,
"_itool")
1594 _Tools_a_.__doc__ +=
"\n" + AlgDecorator._tools_a_.__doc__
1595 _Tools_t_.__doc__ +=
"\n" + AlgDecorator._tools_t_.__doc__
1596 _Counter_a_.__doc__ +=
"\n" + AlgDecorator._counter_a_.__doc__
1597 _Counter_t_.__doc__ +=
"\n" + AlgDecorator._counter_t_.__doc__
1598 _Histos_a_.__doc__ +=
"\n" + HistoDecorator._histos_a_.__doc__
1599 _Histos_t_.__doc__ +=
"\n" + HistoDecorator._histos_t_.__doc__
1601 iAlgorithm.Tools = _Tools_a_
1602 iAlgTool.Tools = _Tools_t_
1603 iAlgorithm.Counter = _Counter_a_
1604 iAlgTool.Counter = _Counter_t_
1605 iAlgorithm.Histos = _Histos_a_
1606 iAlgTool.Histos = _Histos_t_
1617 print(__doc__, __author__)
1618 print(
"\t\t\tDoc-string for class GaudiAlgo \n", GaudiAlgo.__doc__)
1619 print(
"\t\t\tDoc-string for class HistoAlgo \n", HistoAlgo.__doc__)
1620 print(
"\t\t\tDoc-string for class TupleAlgo \n", TupleAlgo.__doc__)
1626 if __name__ ==
"__main__":