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 *******************************************************************************
46 from __future__
import print_function
49 __author__ =
"Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr"
79 from GaudiKernel
import ROOT6WorkAroundEnabled
97 AlgDecorator = cpp.GaudiPython.AlgDecorator
98 HistoDecorator = cpp.GaudiPython.HistoDecorator
99 TupleAlgDecorator = cpp.GaudiPython.TupleAlgDecorator
100 TupleDecorator = cpp.GaudiPython.TupleDecorator
128 def _tool_(self, interface, typename, name=None, parent=None, create=True):
130 Useful method to locate the tool a certain
135 t1 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator')
136 # locate private tool
137 t2 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator',parent=self)
138 # locate public tool with defined name
139 t3 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator/MyExt1')
140 # locate private tool with defined name
141 t4 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator/MyExt2',parent=self)
142 # locate public tool with defined name
143 t5 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator','MyExt3')
144 # locate private tool with defined name
145 t6 = self.tool(ITrExtrapolator,'TrParabolicExtrapolator','MyExt4',parent=self)
149 interface = cpp.IAlgTool
153 typename +=
"/" + name
154 _tool = AlgDecorator.tool_(self, typename, parent, create)
159 self.Warning(
"Invalid cast to interface %s" % interface)
181 Useful method to locate a service:
185 ntsvc = self.svc( INTupleSvc , 'NTUpleSvc' )
189 interface = cpp.IInterface
190 _svc = AlgDecorator.svc_(self, name, create)
195 self.Warning(
"Invalid cast to interface %s" % interface)
209 The constructor from unique algorithm instance name & parameters
211 self._Base.__init__(self, self, name)
213 algMgr = appMgr._algmgr
214 status = algMgr.addAlgorithm(self)
215 if status.isFailure():
216 raise RuntimeError(
'Unable to add Algorithm "' + name +
'"')
219 setattr(self, key, args[key])
221 if "GaudiPythonAlgos" not in appMgr.__dict__:
222 appMgr.__dict__[
"GaudiPythonAlgos"] = []
223 appMgr.__dict__[
"GaudiPythonAlgos"].append(self)
235 The default initialization (initialization of base C++ class + data)
237 status = self._Base.initialize_(self)
238 if status.isFailure():
242 _e = self._Base.evtSvc(self)
246 _d = self._Base.detSvc(self)
262 The default initialization (initialization of base C++ class + data members)
265 if status.isFailure():
269 _h = self._Base.histoSvc(self)
285 The default initialization (initialization of base C++ class + data members)
288 if status.isFailure():
292 if self.produceNTuples():
293 _n = self._Base.ntupleSvc(self)
297 if self.produceEvtCols():
298 _n = self._Base.evtColSvc(self)
326 Trivial helper function to access Event Data and Event Data Service
330 # get event data service
334 hits = self.evtSvc('MC/Calo/Hits')
338 return self._evtSvc_[location]
362 Trivial helper function to access Detector Data and Event Data Service
365 # get detector data service
369 lhcb = self.detSvc('/dd/Structure/LHCb')
373 return self._detSvc_[location]
397 Trivial helper function to access Histogram Data and Histogram Data Service
401 # get histogram data service
402 svc = self.histoSvc()
405 histo = self.histoSvc('/stat/Calo/1')
408 return self._histoSvc_
409 return self._histoSvc_[address]
418 Trivial function to access the data in TES using the data service
420 return self._evtSvc_[location]
429 Trivial function to access the data in TDS using data service
431 return self._detSvc_[location]
438 def _get_(self, location, rootInTES=True):
440 Get the object from Transient Event Store using GaudiCommon machinery,
441 respecting RootInTES behaviour
443 return AlgDecorator.get_(self, location, rootInTES)
452 Check the object in Transient Event Store using GaudiCommon machinery,
453 respecting RootInTES behaviour
455 return AlgDecorator.exist_(self, location, rootInTES)
464 Trivial function to access N-Tuple Service
466 return self._ntupleSvc_
475 Trivial function to access Event Collection Service
477 return self._evtcolSvc_
484 The default finalization : finalize the base C++ class
486 status = self._Base.finalize_(self)
502 The trivial function which checks the existence of the property with given name
504 return cpp.Gaudi.Utils.hasProperty(self, pname)
513 Get the property by name
515 if not self.hasProperty(pname):
516 raise AttributeError(
"property %s does not exist" % pname)
517 return self._ialg.__getattr__(pname)
526 Set the property from the value
528 if not self.hasProperty(pname):
529 raise AttributeError(
"property %s does not exist" % pname)
530 return self._ialg.__setattr__(pname, pvalue)
539 Get the attribute (or property)
540 - if the attribute name corresponds to the property name, property value is returned
542 if self.hasProperty(pname):
543 return self._ialg.__getattr__(pname)
548 return getattr(self._ialg, pname)
549 except AttributeError:
551 raise AttributeError(
"attribute/property %s does not exist" % pname)
560 Set the attribute (or property) :
561 - if the attribute name corresponds to the property name, the property is updated
563 if not self.hasProperty(pname):
564 self.__dict__[pname] = pvalue
566 self._ialg.__setattr__(pname, pvalue)
569 _GaudiAlgorithm = cpp.GaudiPython.PyAlg(
"GaudiAlgorithm")
570 _GaudiHistoAlg = cpp.GaudiPython.PyAlg(
"GaudiHistoAlg")
571 _GaudiTupleAlg = cpp.GaudiPython.PyAlg(
"GaudiTupleAlg")
640 *******************************************************************************
641 * * 'Physisics do not like it, *
642 * * physisics do not need it, *
643 * * physisics do not use it' *
644 * * ****************************
647 * from GaudiPython.GaudiAlgs import GaudiAlgo, SUCCESS *
649 * class MyClass(GaudiAlgo) : *
650 * ' My specific Algorithm, derived from GaudiAlgo base class ' *
651 * def __init__( self , name , **args ) : *
652 * 'Constructor from algorithm instance name & parameters' *
653 * #invoke the constructor of base class *
654 * GaudiAlgo.__init__(self , name , **args ) *
656 * def initialize ( self ) : *
657 * 'Algorithm initialization' *
658 * # initialize the base class *
659 * status = GaudiAlgo.initialize( self ) *
660 * if status.isFailure() : return status *
662 * # locate the services and tools *
664 * # locate some tool: *
665 * extrapolator = self.tool(ITrExtrapolator,'TrExtrapolator') *
667 * # locate the service *
668 * rndmSvc = self.svc(IRndmGenSvc, 'RndmGenSvc') *
673 * def execute ( self ) : *
674 * 'Major method (from IAlgorithm interface)' *
676 * # get some data from Transient Event Store *
677 * tracks = self.get('/Event/Rec/Tracks') *
680 * c1 = self.counter('#Tracks') *
681 * c2 = self.counter('No Tracks') *
682 * if tracks.empty : *
684 * c1 += tracks->size() *
686 * if 1000 < tracks.size() : *
687 * return self.Error('The event is *VERY* busy') *
691 *******************************************************************************
770 *******************************************************************************
771 * * 'Physisics do not like it, *
772 * * physisics do not need it, *
773 * * physisics do not use it' *
774 * * ****************************
777 * from GaudiPython.GaudiAlgs import HistoAlgo, SUCCESS *
779 * class MyClass(HistoAlgo) : *
780 * ' My specific Algorithm, derived from GaudiAlgo base class ' *
781 * def __init__( self , name , **args ) : *
782 * 'Constructor from algorithm instance name' *
783 * #invoke the constructor of base class *
784 * HistoAlgo.__init__(self , name , **args ) *
786 * def execute ( self ) : *
787 * 'Major method (from IAlgorithm interface)' *
789 * # get some data from Transient Event Store *
790 * tracks = self.get('/Event/Rec/Tracks') *
792 * self.plot1D ( tracks->size() , '#tracks' , 0 , 100 ) *
796 * Alternatively the histogram could be booked in advance: *
798 * class MyClass(HistoAlgo) : *
799 * ' My specific Algorithm, derived from GaudiAlgo base class ' *
800 * def __init__( self , name ) : *
801 * 'Constructor from algorithm instance name' *
802 * #invoke the constructor of base class *
803 * HistoAlgo.__init__(self , name ) *
805 * def initialize ( self ) : *
806 * 'Algorithm initialization' *
807 * # initialize the base class *
808 * status = HistoAlgo.initialize( self ) *
809 * if status.isFailure() : return status *
811 * # book the histogram *
812 * self.h1 = selff.book1D ( '#tracks' , 0 , 100 ) *
817 * def execute ( self ) : *
818 * 'Major method (from IAlgorithm interface)' *
820 * # get some data from Transient Event Store *
821 * tracks = self.get('/Event/Rec/Tracks') *
823 * # fill the histogram *
824 * self.h1.fill ( tracks->size() ) *
828 *******************************************************************************
884 *******************************************************************************
885 * * 'Physisics do not like it, *
886 * * physisics do not need it, *
887 * * physisics do not use it' *
888 * * ****************************
891 * from GaudiPython.GaudiAlgs import TupleAlgo, SUCCESS *
893 * class MyClass(TupleAlgo) : *
894 * ' My specific Algorithm, derived from TupleAlgo base class ' *
895 * def __init__( self , name , **args ) : *
896 * 'Constructor from algorithm instance name & parameters' *
897 * #invoke the constructor of base class *
898 * TupleAlgo.__init__(self , name , **args ) *
900 * def execute ( self ) : *
901 * 'Major method (from IAlgorithm interface)' *
903 * # get some data from Transient Event Store *
904 * tracks = self.get('/Event/Rec/Tracks') *
906 * tup = self.nTuple('My N-Tuple') *
908 * for track in tracks : *
912 * chi2 = track.chi2 () *
915 * tup.column ( 'pt' , pt ) *
916 * tup.column ( 'p' , p ) *
917 * tup.column ( 'chi2' , chi2 ) *
923 *******************************************************************************
938 GaudiAlgo._Base = _GaudiAlgorithm
939 HistoAlgo._Base = _GaudiHistoAlg
940 TupleAlgo._Base = _GaudiTupleAlg
943 GaudiAlgo.initialize = _initialize_
944 HistoAlgo.initialize = _initialize_histo_
945 TupleAlgo.initialize = _initialize_tuple_
950 The stub 'start' method needed by the internal implementation of PyAlg<>.
956 GaudiAlgo.start = _start_
957 HistoAlgo.start = _start_
958 TupleAlgo.start = _start_
963 The fictive 'execute' method, which MUST be overwitten by user
965 raise RuntimeError(
"Execute method is not implemented for %s" % self.name())
968 GaudiAlgo.execute = _execute_
969 HistoAlgo.execute = _execute_
970 TupleAlgo.execute = _execute_
975 The stub 'stop' method needed by the internal implementation of PyAlg<>.
981 GaudiAlgo.stop = _stop_
982 HistoAlgo.stop = _stop_
983 TupleAlgo.stop = _stop_
990 The basic method to fill (book-on-demand) 1D-histogram
992 The histogram will be created/booked dautomatically according to the
995 - literal or numerical ID (optional)
999 - number of bins (default is 100)
1001 The reference to the histogram is returned and could be used for later manipulations
1004 return HistoDecorator.plot1D(s, *a)
1012 The basic method to fill (book-on-demand) 2D-histogram
1014 The histogram will be created/booked dautomatically according to the
1017 - literal or numerical ID (optional)
1023 - number of X-bins (default is 50)
1024 - number of Y-bins (default is 50)
1026 The reference to the histogram is returned and could be used for later manipulations
1029 return HistoDecorator.plot2D(s, *a)
1037 The basic method to fill (book-on-demand) 3D-histogram
1039 The histogram will be created/booked dautomatically according to the
1042 - literal or numerical ID (optional)
1050 - number of X-bins (default is 10)
1051 - number of Y-bins (default is 10)
1052 - number of Y-bins (default is 10)
1054 The reference to the histogram is returned and could be used for later manipulations
1057 return HistoDecorator.plot3D(s, *a)
1065 The basic method to fill (book-on-demand) 1D profile histogram
1067 The profile histogram will be created/booked dautomatically
1068 according to the specifications:
1070 - literal or numerical ID (optional)
1074 - number of X-bins (default is 100)
1076 The reference to the histogram is returned and could be used for later manipulations
1079 return HistoDecorator.profile1D(s, *a)
1087 The basic method to fill (book-on-demand) 2D profile histiogram
1089 The profile histogram will be created/booked automatically
1090 according to the specifications:
1092 - literal or numerical ID (optional)
1098 - number of X-bins (default is 50)
1099 - number of Y-bins (default is 50)
1101 The reference to the histogram is returned and could be used for later manipulations
1104 return HistoDecorator.profile2D(s, *a)
1109 _plot1D_.__doc__ +=
"\n" + HistoDecorator.plot1D.__doc__
1110 _plot2D_.__doc__ +=
"\n" + HistoDecorator.plot2D.__doc__
1111 _plot3D_.__doc__ +=
"\n" + HistoDecorator.plot3D.__doc__
1112 _profile1D_.__doc__ +=
"\n" + HistoDecorator.profile1D.__doc__
1113 _profile2D_.__doc__ +=
"\n" + HistoDecorator.profile2D.__doc__
1118 if not issubclass(t, list)
and not issubclass(t, tuple):
1120 for klass
in klasses:
1121 klass.plot = _plot1D_
1122 klass.plot1D = _plot1D_
1123 klass.plot2D = _plot2D_
1124 klass.plot3D = _plot3D_
1125 klass.profile1D = _profile1D_
1126 klass.profile2D = _profile2D_
1136 Retrieve (book-on-demand) N-Tuple object
1138 return TupleAlgDecorator.nTuple(s, *a)
1146 Retrieve (book-on-demand) N-Tuple object for Event Tag Collections
1148 return TupleAlgDecorator.evtCol(s, *a)
1151 _nTuple_.__doc__ +=
"\n" + TupleAlgDecorator.nTuple.__doc__
1152 _evtCol_.__doc__ +=
"\n" + TupleAlgDecorator.evtCol.__doc__
1157 if not issubclass(t, list)
and not issubclass(t, tuple):
1159 for klass
in klasses:
1160 klass.nTuple = _nTuple_
1161 klass.evtCol = _evtCol_
1162 klass.ntupleSvc = _ntupleSvc
1163 klass.tupleSvc = _ntupleSvc
1164 klass.ntupSvc = _ntupleSvc
1165 klass.tupSvc = _ntupleSvc
1166 klass.evtColSvc = _evtcolSvc
1167 klass.evtcolSvc = _evtcolSvc
1174 Tuple = cpp.Tuples.Tuple
1175 _Dec = TupleDecorator
1179 """Helper decorator class to workaround ROOT-6697"""
1184 dispatcher = func.disp
if hasattr(func,
"disp")
else func.__overload__
1186 mapping = {int:
"int", bool:
"bool", float:
"double"}
1189 "const Tuples::Tuple& tuple, const string& name, const %s value"
1192 mapping[k] = dispatcher(signature)
1197 Explicitly call the explicit signature for the case with 3 arguments and
1198 the last one is 'int', 'bool' or 'float', for the other cases fall back
1199 on the default dispatcher.
1207 return self.
func(*a)
1211 hasattr(_Dec.column,
"disp")
or hasattr(_Dec.column,
"__overload__")
1218 Access to underlying INTuple object
1220 return _Dec.nTuple(s, *a)
1225 Access to underlying NTuple::Tuple object
1227 return _Dec.ntuple(s, *a)
1232 Valid NTuple::Tuple object?
1234 return _Dec.valid(s, *a)
1239 Commit the row/record to n-tuple
1241 return _Dec.write(s, *a)
1246 Fill the certain column to n-tuple
1248 return _Dec.column(s, *a)
1253 Fill the 'long long' column
1255 return _Dec.column_ll(s, *a)
1260 Fill the 'unsigned long long' column
1262 return _Dec.column_ull(s, *a)
1267 Fill the fixed-size array column
1269 return _Dec.array(s, *a)
1274 Fill the fixed-size matrix column
1276 return _Dec.matrix(s, *a)
1281 Fill the floating-size array column
1283 return _Dec.farray(s, *a)
1288 Fill the floating-size matrix column
1290 return _Dec.fmatrix(s, *a)
1293 _t_nTuple_.__doc__ +=
"\n" + _Dec.nTuple.__doc__
1294 _t_ntuple_.__doc__ +=
"\n" + _Dec.ntuple.__doc__
1295 _t_valid_.__doc__ +=
"\n" + _Dec.valid.__doc__
1296 _t_write_.__doc__ +=
"\n" + _Dec.write.__doc__
1297 _t_column_.__doc__ +=
"\n" + _Dec.column.__doc__
1298 _t_column_ll_.__doc__ +=
"\n" + _Dec.column_ll.__doc__
1299 _t_column_ull_.__doc__ +=
"\n" + _Dec.column_ull.__doc__
1300 _t_array_.__doc__ +=
"\n" + _Dec.array.__doc__
1301 _t_matrix_.__doc__ +=
"\n" + _Dec.matrix.__doc__
1302 _t_farray_.__doc__ +=
"\n" + _Dec.farray.__doc__
1303 _t_fmatrix_.__doc__ +=
"\n" + _Dec.fmatrix.__doc__
1305 Tuple.nTuple = _t_nTuple_
1306 Tuple.ntuple = _t_ntuple_
1307 Tuple.valid = _t_valid_
1308 Tuple.write = _t_write_
1309 Tuple.column = _t_column_
1310 Tuple.column_ll = _t_column_ll_
1311 Tuple.column_ull = _t_column_ull_
1312 Tuple.array = _t_array_
1313 Tuple.matrix = _t_matrix_
1314 Tuple.farray = _t_farray_
1315 Tuple.fmatrix = _t_fmatrix_
1322 "eventSvc": _evtSvc,
1324 "histoSvc": _histoSvc,
1325 "histSvc": _histoSvc,
1330 "finalize": _finalize_,
1332 "hasProperty": _hasProperty_,
1333 "getProperty": _getProperty_,
1334 "setProperty": _setProperty_,
1335 "__setattr__": _set_attr_,
1336 "__getattr__": _get_attr_,
1343 if not issubclass(t, list)
and not issubclass(t, tuple):
1345 for _alg
in klasses:
1346 for key
in _alg_map_:
1347 setattr(_alg, key, _alg_map_[key])
1361 """Helper function to fill histogram/ntuple using 'map'-operation"""
1366 if hasattr(sequence,
"size"):
1367 vct.reserve(vct.size() + sequence.size())
1368 elif hasattr(sequence,
"__len__"):
1369 vct.reserve(vct.size() + len(sequence))
1370 for object
in sequence:
1371 vct.push_back(
func(object))
1387 _func = getattr(AlgDecorator, method)
1388 _num = _func(self, _tools)
1389 if _tools.size() != _num:
1390 raise RuntimeError(
"Unable to extract Tools")
1392 for _tool
in _tools:
1393 _res += [
iAlgTool(_tool.name(), _tool)]
1402 Retrieve the list of tools,
1403 aquired by component through GaudiCommon<TYPE> base:
1405 >>> alg = ... ## get the algorithm
1406 >>> tools = alg.Tools() ## get the tools
1407 >>> for tool in tools :
1411 _cmp = getattr(self,
"_ialg")
1413 self.retrieveInterface()
1414 _cmp = getattr(self,
"_ialg")
1423 Retrieve the list of tools,
1424 aquired by component through GaudiCommon<TYPE> base:
1426 >>> tool = ... ## get the tool
1427 >>> tools = tool.Tools() ## get the tools
1428 >>> for t in tools :
1432 _cmp = getattr(self,
"_itool")
1434 self.retrieveInterface()
1435 _cmp = getattr(self,
"_itool")
1448 _func = getattr(AlgDecorator, method)
1449 return _func(self, name)
1457 Retrieve the counter managed GaudiCommon<TYPE> base by name:
1459 >>> alg = ... ## get the algorithm
1460 >>> cnt = alg.Counter('#accept') ## get the counter
1464 _cmp = getattr(self,
"_ialg")
1466 self.retrieveInterface()
1467 _cmp = getattr(self,
"_ialg")
1476 Retrieve the counter managed GaudiCommon<TYPE> base by name:
1478 >>> tool = ... ## get the tool
1479 >>> cnt = tool.Counter('#accept') ## get the counter
1483 _cmp = getattr(self,
"_itool")
1485 self.retrieveInterface()
1486 _cmp = getattr(self,
"_itool")
1493 cpp.GaudiAlg.ID.__repr__ = cpp.GaudiAlg.ID.idAsString
1494 cpp.GaudiAlg.ID.__str__ = cpp.GaudiAlg.ID.idAsString
1495 cpp.StatEntity.__repr__ = cpp.StatEntity.toString
1496 cpp.StatEntity.__str__ = cpp.StatEntity.toString
1503 Get All histogram form the component
1515 _fun = getattr(HistoDecorator, method)
1516 _num = _fun(component, _ids, _his)
1517 if _ids.size() != _num
or _his.size() != _num:
1518 raise RuntimeError(
"Unable to extract Histos!")
1519 for _i
in range(0, _num):
1522 _id = _id.numericID()
1524 _id = _id.literalID()
1526 _id = _id.idAsString()
1527 _res[_id] = _his[_i]
1532 id = cpp.GaudiAlg.ID(name)
1533 for i
in (name, id.literalID(), id.numericID(), id.idAsString(), id):
1534 h = _res.get(i,
None)
1546 Retrieve all histograms & profiles, booked through GauydiHistos<TYPE> base:
1548 >>> alg = ... ## get the algorithm
1549 >>> histos = alg.Histos() ## get all histograms & profiles
1550 >>> for key in histos :
1551 ... print(key, histos[key])
1553 Retrive the histogram with the certain ID :
1555 >>> alg = ... ## get the algorithm
1556 >>> histo = alg.Histos('some histo ID') ## get the histo by ID
1560 _cmp = getattr(self,
"_ialg")
1562 self.retrieveInterface()
1563 _cmp = getattr(self,
"_ialg")
1572 Retrieve all histograms & profiles, booked through GauydiHistos<TYPE> base:
1574 >>> tool = ... ## get the tool
1575 >>> histos = tool.Histos() ## get all histograms & profiles
1576 >>> for key in histos :
1577 ... print(key, histos[key])
1579 Retrive the historgam with certain ID :
1581 >>> tool = ... ## get the tool
1582 >>> histo = tool.Histos('some histo ID') ## get the histo by ID
1586 _cmp = getattr(self,
"_itool")
1588 self.retrieveInterface()
1589 _cmp = getattr(self,
"_itool")
1595 _Tools_a_.__doc__ +=
"\n" + AlgDecorator._tools_a_.__doc__
1596 _Tools_t_.__doc__ +=
"\n" + AlgDecorator._tools_t_.__doc__
1597 _Counter_a_.__doc__ +=
"\n" + AlgDecorator._counter_a_.__doc__
1598 _Counter_t_.__doc__ +=
"\n" + AlgDecorator._counter_t_.__doc__
1599 _Histos_a_.__doc__ +=
"\n" + HistoDecorator._histos_a_.__doc__
1600 _Histos_t_.__doc__ +=
"\n" + HistoDecorator._histos_t_.__doc__
1602 iAlgorithm.Tools = _Tools_a_
1603 iAlgTool.Tools = _Tools_t_
1604 iAlgorithm.Counter = _Counter_a_
1605 iAlgTool.Counter = _Counter_t_
1606 iAlgorithm.Histos = _Histos_a_
1607 iAlgTool.Histos = _Histos_t_
1618 print(__doc__, __author__)
1619 print(
"\t\t\tDoc-string for class GaudiAlgo \n", GaudiAlgo.__doc__)
1620 print(
"\t\t\tDoc-string for class HistoAlgo \n", HistoAlgo.__doc__)
1621 print(
"\t\t\tDoc-string for class TupleAlgo \n", TupleAlgo.__doc__)
1627 if __name__ ==
"__main__":