ATLAS Offline Software
Loading...
Searching...
No Matches
PyKernel.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3"""core module for an interactive analysis
4
5Examples are in `PyAnalysisExamples/PlotTest.py`_ and `PyAnalysisExamples/HistTest.py`_
6
7.. _PyAnalysisExamples/HistTest.py: http://atlas-sw.cern.ch/cgi-bin/viewcvs-atlas.cgi/offline/PhysicsAnalysis/PyAnalysis/PyAnalysisExamples/share/HistTest.py?rev=HEAD&content-type=text/vnd.viewcvs-markup
8
9.. _PyAnalysisExamples/PlotTest.py: http://atlas-sw.cern.ch/cgi-bin/viewcvs-atlas.cgi/offline/PhysicsAnalysis/PyAnalysis/PyAnalysisExamples/share/PlotTest.py?rev=HEAD&content-type=text/vnd.viewcvs-markup
10
11:author: Tadashi Maeno
12:contact: tmaeno@bnl.gov
13
14"""
15__docformat__ = "restructuredtext en"
16
17# remove these lines when epydoc
18#"""
19import re
20import cppyy
21from math import * # noqa: F403
22from AthenaCommon.SystemOfUnits import * # noqa: F403
23
24# global name space
25GNS = cppyy.gbl
26
27#"""
28
29# Event Loop Types
30_PreProcess = 0
31_NormalProcess = 1
32_HybridProcess = 2
33
34# dummy class for TAG and AANT
35class _DummyClass: pass
36GNS.AttributeList = _DummyClass
37GNS.AANT = _DummyClass
38del _DummyClass
39
40storeGate = None
41detStore = None
42
43
44# initialize core
45def init (v_theApp, v_rootStream=None):
46 """Initialize core
47
48 This method is called in `PyKernel/InitPyKernel.py`_.
49
50 :param v_theApp: reference to the application manager. theApp
51
52 **examples**::
53
54 athena> PyKernel.init(theApp)
55
56 .. _PyKernel/InitPyKernel.py: http://atlas-sw.cern.ch/cgi-bin/viewcvs-atlas.cgi/offline/Control/PyKernel/share/InitPyKernel.py?rev=HEAD&content-type=text/vnd.viewcvs-markup
57
58 """
59 # application manager
60 global theApp
61 theApp = v_theApp
62 # root stream
63 global rootStream
64 rootStream = v_rootStream
65 # event loop type
66 global eventLoopType
67 eventLoopType = _HybridProcess
68 # event counter
69 global curEvent
70 curEvent = 0
71 if hasattr (theApp, 'curEvent'):
72 # patch some methods
73 method = "nextEvent"
74 mobj = _SetEventCounter(method)
75 setattr(theApp.__class__,method,mobj)
76 method = "run"
77 mobj = _SetEventCounter(method)
78 setattr(theApp.__class__,method,mobj)
79
80
81# a function object to set event counter in ROOT stream
83 """Function object to set event counter in ROOT stream.
84 This class is used to patch, e.g., theApp.nextEvent(), run() ...
85
86 :param methodObj: reference to method to be patched
87
88 """
89 def __init__(self,methodName):
90 self.methodObj = getattr(theApp,methodName)
91 # method emulation
92 def __call__ (self,*var):
93 global curEvent
94 # set event counter. For pre-process internal curEvent is used
95 if eventLoopType != _PreProcess:
96 curEvent = theApp.curEvent()
97 # get ROOT entry
98 if eventLoopType != _NormalProcess and rootStream:
99 rootStream.GetEntry(curEvent)
100 # return if pre-process
101 if eventLoopType == _PreProcess:
102 # increment event counter
103 curEvent = curEvent+1
104 return GNS.StatusCode(1)
105 # call original method
106 return self.methodObj(var)
107
108
109# retrieve object from StoreGate
110def retrieve (aClass, aKey=None):
111 """Retrieve object from StoreGate
112
113 :param aClass: type of the class
114 :param aKey: key of the object
115
116 **examples**::
117
118 athena> obj = PyKernel.retrieve(g.MyClass,'mykey')
119 athena> obj = PyKernel.retrieve(g.MyClass) # when only one MyClass obj is in SG
120 where the prefix 'g' is the global namespace provided by cppyy
121 g = cppyy.gbl
122
123 """
124 #import workaround
125 if aClass == GNS.AttributeList:
126 return rootStream
127 if aClass == GNS.AANT:
128 return rootStream
129 global storeGate
130 if storeGate is None:
131 import AthenaPython.PyAthena as PyAthena
132 storeGate = PyAthena.py_svc('StoreGateSvc/StoreGateSvc')
133 if aKey:
134 ret = storeGate.retrieve(aClass,aKey)
135 else:
136 ret = storeGate.retrieve(aClass)
137 return ret
138
139
140# retrieve object from DetectorStore
141def retrieveDet (aClass, aKey=None):
142 """Retrieve object from DetectorStore
143
144 :param aClass: type of the class
145 :param aKey: key of the object
146
147 **examples**::
148
149 athena> obj = PyKernel.retrieveDet(g.MyClass,'mykey')
150 athena> obj = PyKernel.retrieveDet(g.MyClass) # when only one MyClass obj is in SG
151 where the prefix 'g' is the global namespace provided by cppyy
152 g = cppyy.gbl
153
154 """
155 #import workaround
156 if detStore is None:
157 import AthenaPython.PyAthena as PyAthena
158 storeGate = PyAthena.py_svc('StoreGateSvc/DetectorStore') # noqa: F841
159 if aKey:
160 ret = detStore.retrieve(aClass,aKey)
161 else:
162 ret = detStore.retrieve(aClass)
163 return ret
164
165
166# fill a histogram
167def fill (hist, classAndKey, value, criteria="True", nEvent=100):
168 '''
169 Fill 1D-histogram
170
171 :param hist: reference to AIDA or ROOT histogram
172 :param classAndKey: combination of class name and key separeted with "#". "Class#Key"
173 :param value: physics parameter in string
174 :param criteria: selection criteria
175 :param nEvent: number of event to be processed
176
177 **examples**::
178
179 athena> fill(h,"ElectronContainer#ElectronCollection","$x.pt()")
180 fill hist with pt of electrons
181 "$x" denotes an element of "Class#Key", if "Class#Key" is a collection
182
183 athena> fill(h,"MissingET#MET_Calib","$x.sumet()")
184 fill hist with et of MissingET.
185 "$x" denotes "Class#Key" itself, if "Class#Key" is not a vector-like class
186
187 athena> fill(h,"ElectronContainer#ElectronCollection","$x.pt()","$x.pz()>0")
188 apply a selection criteria
189
190 For more detail of parameters, see `PyAnalysisExamples/PlotTest.py`_
191
192 .. _PyAnalysisExamples/PlotTest.py: http://atlas-sw.cern.ch/cgi-bin/viewcvs-atlas.cgi/offline/PhysicsAnalysis/PyAnalysis/PyAnalysisExamples/share/PlotTest.py?rev=HEAD&content-type=text/vnd.viewcvs-markup
193
194 '''
195
196 # number of buffered events
197 bufEvent = nEvent
198 if nEvent > 100:
199 bufEvent = 100
200
201 # convert class&key to a store gate access
202 commandSG = "None"
203 if classAndKey != "":
204 commandSG = _parseString(classAndKey)
205
206 # build commands
207 if callable(value):
208 # if function pointer
209 commandV = "value()"
210 else:
211 # if string, parse value/criteria
212 commandV = _parseString(value)
213 if callable(criteria):
214 # if function pointer
215 commandC = "criteria()"
216 else:
217 # if string, parse value/criteria
218 commandC = _parseString(criteria)
219
220 # initialize application mgr
221 theApp.initialize()
222
223 # buffer to determine x-range of histgram
224 buf = []
225
226 # loop over nEvent
227 for iE in range(nEvent):
228 # get object from SG
229 theApp.nextEvent()
230 try:
231 obj = eval(commandSG)
232
233 # check if the obj is a vector-like class
234 if hasattr(obj,'size') and hasattr(obj,'__getitem__'):
235 lSize = obj.size()
236 isCollection = True
237 else:
238 lSize = 1
239 isCollection = False
240 # if NULL
241 if obj == 0:
242 lSize = 0
243 except Exception:
244 lSize = 0
245
246 # loop over all elements
247 for iC in range(lSize):
248 # parameter name "x" must be consistent with the parsed strings
249 if isCollection:
250 x = obj[iC] # noqa: F841
251 else:
252 x = obj # noqa: F841
253
254 # eval value/criteria commands
255 try:
256 vX = eval(commandV)
257 vC = eval(commandC)
258
259 # evaluate vC/vX. "vC" and "vX" must be consistent with commands
260 if vC:
261 if iE < bufEvent:
262 buf.append(vX)
263 else:
264 h.Fill(vX) # noqa: F405
265 except Exception:
266 pass
267
268 # if not a collection escape from loop
269 if not isCollection:
270 break
271
272 # create Histogram
273 if (iE+1) == bufEvent:
274 if len(buf)==0:
275 minX=0
276 else:
277 minX = min(buf)
278
279 if minX<0:
280 minX *= 1.1
281 elif minX>0:
282 minX *= 0.9
283 else:
284 minX = -1
285
286 if len(buf)==0:
287 maxX=0
288 else:
289 maxX = max(buf)
290
291 if maxX<0:
292 maxX *= 0.9
293 elif maxX>0:
294 maxX *= 1.1
295 else:
296 maxX = 1
297
298 # create histogram if hist is None
299 if hist is None:
300 lpath = '/stat/tmp/PyKernelHist'
301 unregister(lpath)
302 # determine title of histo
303 if callable(value):
304 title = value.__name__
305 else:
306 title = value
307 h = book(lpath, title, 100, minX, maxX) # noqa: F405
308 else:
309 h = hist
310
311 # buffered elements
312 for vB in buf:
313 h.Fill(vB)
314
315 return h
316
317
318# plot a histogram
319def plot (classAndKey, value="$x", criteria="True", nEvent=100):
320 """Plot 1D-histogram
321
322 :param classAndKey: combination of class name and key separeted with '#'. 'Class#Key'
323 :param value: physics parameter in string
324 :param criteria: selection criteria
325 :param nEvent: number of event to be processed
326
327 **examples**::
328
329 athena> plot('ElectronContainer#ElectronCollection','$x.pt()')
330 plot pt of electrons
331
332 For detail, see `PyAnalysisExamples/PlotTest.py`_
333
334 .. _PyAnalysisExamples/PlotTest.py: http://atlas-sw.cern.ch/cgi-bin/viewcvs-atlas.cgi/offline/PhysicsAnalysis/PyAnalysis/PyAnalysisExamples/share/PlotTest.py?rev=HEAD&content-type=text/vnd.viewcvs-markup
335
336 """
337
338 # fill a histogram
339 h = fill (None, classAndKey, value, criteria, nEvent)
340 # draw
341 h.Draw()
342 # this return is needed to draw up the canvas.
343 # note that PyKernel._hSave = h doesn't work although it keeps the hist in memory
344 return h
345
346
347# fill 2D histogram
348def fill2 (hist, classAndKey, valueX, valueY, criteria="True", nEvent=100):
349 """Fill 2D-histogram
350
351 :param hist: reference to AIDA or ROOT histogram
352 :param classAndKey: combination of class name and key separeted with '#', 'Class#Key'
353 :param valueX: physics parameter for X in string
354 :param valueY: physics parameter for Y in string
355 :param criteria: selection criteria
356 :param nEvent: number of event to be processed
357
358 For detail, see `fill`
359
360 """
361
362 # number of buffered events
363 bufEvent = nEvent
364 if nEvent > 100:
365 bufEvent = 100
366
367 # convert class&key to a store gate access
368 commandSG = "None"
369 if classAndKey != "":
370 commandSG = _parseString(classAndKey)
371
372 # build commands
373 if callable(valueX):
374 # if function pointer
375 commandX = "valueX()"
376 else:
377 # if string, parse value/criteria
378 commandX = _parseString(valueX)
379 if callable(valueY):
380 # if function pointer
381 commandY = "valueY()"
382 else:
383 # if string, parse value/criteria
384 commandY = _parseString(valueY)
385 if callable(criteria):
386 # if function pointer
387 commandC = "criteria()"
388 else:
389 # if string, parse value/criteria
390 commandC = _parseString(criteria)
391
392 # initialize application mgr
393 theApp.initialize()
394
395 # buffer to determine xy-range of histgram
396 bufX = []
397 bufY = []
398
399 # loop over nEvent
400 for iE in range(nEvent):
401 # get object from SG
402 theApp.nextEvent()
403 try:
404 obj = eval(commandSG)
405
406 # check if the obj is a vector-like class
407 if hasattr(obj,'size') and hasattr(obj,'__getitem__'):
408 lSize = obj.size()
409 isCollection = True
410 else:
411 lSize = 1
412 isCollection = False
413 # if NULL
414 if obj == 0:
415 lSize = 0
416 except Exception:
417 lSize = 0
418
419 # loop over all elements
420 for iC in range(lSize):
421 # parameter name "x" must be consistent with the parsed strings
422 if isCollection:
423 x = obj[iC] # noqa: F841
424 else:
425 x = obj # noqa: F841
426
427 # eval value/criteria commands
428 try:
429 vX = eval(commandX)
430 vY = eval(commandY)
431 vC = eval(commandC)
432
433 # evaluate vC/vX. "vC" and "vX" must be consistent with commands
434 if vC:
435 if iE < bufEvent:
436 bufX.append(vX)
437 bufY.append(vY)
438 else:
439 h.Fill(vX,vY) # noqa: F405
440 except Exception:
441 pass
442
443 # if not a collection escape from loop
444 if not isCollection:
445 break
446
447 # create Histogram
448 if (iE+1) == bufEvent:
449 if len(bufX)==0:
450 minX=0
451 else:
452 minX = min(bufX)
453
454 if minX<0:
455 minX *= 1.1
456 elif minX>0:
457 minX *= 0.9
458 else:
459 minX = -1
460
461 if len(bufX)==0:
462 maxX=0
463 else:
464 maxX = max(bufX)
465
466 if maxX<0:
467 maxX *= 0.9
468 elif maxX>0:
469 maxX *= 1.1
470 else:
471 maxX = 1
472
473 if len(bufY)==0:
474 minY=0
475 else:
476 minY = min(bufY)
477
478 if minY<0:
479 minY *= 1.1
480 elif minY>0:
481 minY *= 0.9
482 else:
483 minY = -1
484
485 if len(bufY)==0:
486 maxY=0
487 else:
488 maxY = max(bufY)
489
490 if maxY<0:
491 maxY *= 0.9
492 elif maxY>0:
493 maxY *= 1.1
494 else:
495 maxY = 1
496
497 # create histogram if hist is None
498 if hist is None:
499 lpath = '/stat/tmp/PyKernelHist'
500 unregister(lpath)
501 # determine title of histo
502 if callable(valueX):
503 titleX = valueX.__name__
504 else:
505 titleX = valueX
506 if callable(valueY):
507 titleY = valueY.__name__
508 else:
509 titleY = valueY
510 h = book(lpath, titleY+" vs "+titleX, 100, minX, maxX, 100, minY, maxY) # noqa: F405
511 else:
512 h = hist
513
514 # buffered elements
515 for iB in range(len(bufX)):
516 vX = bufX[iB]
517 vY = bufY[iB]
518 h.Fill(vX,vY)
519
520 return h
521
522
523# plot 2D histogram
524def plot2 (classAndKey, valueX="$x", valueY="$x", criteria="True", nEvent=100):
525 """Plot 2D-histogram
526
527 :param classAndKey: combination of class name and key separeted with '#', 'Class#Key'
528 :param valueX: physics parameter for X in string
529 :param valueY: physics parameter for Y in string
530 :param criteria: selection criteria
531 :param nEvent: number of event to be processed
532
533 For detail, see `plot`
534
535 """
536 h = fill2 (None, classAndKey, valueX, valueY, criteria, nEvent)
537 # draw
538 h.Draw('BOX')
539 # this return is needed to draw up the canvas.
540 # note that PyKernel._hSave = h doesn't work although it keeps the hist in memory
541 return h
542
543
544# fill profile histogram
545def fillProf (hist, classAndKey, valueX, valueY, criteria="True", nEvent=100):
546 """Fill profile-histogram
547
548 :param hist: reference to AIDA or ROOT histogram
549 :param classAndKey: combination of class name and key separeted with '#', 'Class#Key'
550 :param valueX: physics parameter for X in string
551 :param valueY: physics parameter for Y in string
552 :param criteria: selection criteria
553 :param nEvent: number of event to be processed
554
555 For detail, see `fill`
556
557 """
558
559 # number of buffered events
560 bufEvent = nEvent
561 if nEvent > 100:
562 bufEvent = 100
563
564 # convert class&key to a store gate access
565 commandSG = "None"
566 if classAndKey != "":
567 commandSG = _parseString(classAndKey)
568
569 # build commands
570 if callable(valueX):
571 # if function pointer
572 commandX = "valueX()"
573 else:
574 # if string, parse value/criteria
575 commandX = _parseString(valueX)
576 if callable(valueY):
577 # if function pointer
578 commandY = "valueY()"
579 else:
580 # if string, parse value/criteria
581 commandY = _parseString(valueY)
582 if callable(criteria):
583 # if function pointer
584 commandC = "criteria()"
585 else:
586 # if string, parse value/criteria
587 commandC = _parseString(criteria)
588
589 # initialize application mgr
590 theApp.initialize()
591
592 # buffer to determine xy-range of histgram
593 bufX = []
594 bufY = []
595
596 # loop over nEvent
597 for iE in range(nEvent):
598 # get object from SG
599 theApp.nextEvent()
600 try:
601 obj = eval(commandSG)
602
603 # check if the obj is a vector-like class
604 if hasattr(obj,'size') and hasattr(obj,'__getitem__'):
605 lSize = obj.size()
606 isCollection = True
607 else:
608 lSize = 1
609 isCollection = False
610 # if NULL
611 if obj == 0:
612 lSize = 0
613 except Exception:
614 lSize = 0
615
616 # loop over all elements
617 for iC in range(lSize):
618 # parameter name "x" must be consistent with the parsed strings
619 if isCollection:
620 x = obj[iC] # noqa: F841
621 else:
622 x = obj # noqa: F841
623
624 # eval value/criteria commands
625 try:
626 vX = eval(commandX)
627 vY = eval(commandY)
628 vC = eval(commandC)
629
630 # evaluate vC/vX. "vC" and "vX" must be consistent with commands
631 if vC:
632 if iE < bufEvent:
633 bufX.append(vX)
634 bufY.append(vY)
635 else:
636 h.Fill(vX,vY) # noqa: F405
637 except Exception:
638 pass
639
640 # if not a collection escape from loop
641 if not isCollection:
642 break
643
644 # create Histogram
645 if (iE+1) == bufEvent:
646 if len(bufX)==0:
647 minX=0
648 else:
649 minX = min(bufX)
650
651 if minX<0:
652 minX *= 1.1
653 elif minX>0:
654 minX *= 0.9
655 else:
656 minX = -1
657
658 if len(bufX)==0:
659 maxX=0
660 else:
661 maxX = max(bufX)
662
663 if maxX<0:
664 maxX *= 0.9
665 elif maxX>0:
666 maxX *= 1.1
667 else:
668 maxX = 1
669
670 # create histogram if hist is None
671 if hist is None:
672 lpath = '/stat/tmp/PyKernelHist'
673 unregister(lpath)
674 # determine title of histo
675 if callable(valueX):
676 titleX = valueX.__name__
677 else:
678 titleX = valueX
679 if callable(valueY):
680 titleY = valueY.__name__
681 else:
682 titleY = valueY
683 h = bookProf(lpath, titleY+" vs "+titleX, 100, minX, maxX) # noqa: F405
684 else:
685 h = hist
686
687 # buffered elements
688 for iB in range(len(bufX)):
689 vX = bufX[iB]
690 vY = bufY[iB]
691 h.Fill(vX,vY)
692
693 return h
694
695
696# plot profileD histogram
697def plotProf (classAndKey, valueX="$x", valueY="$x", criteria="True", nEvent=100):
698 """Plot profile-histogram
699
700 :param classAndKey: combination of class name and key separeted with '#', 'Class#Key'
701 :param valueX: physics parameter for X in string
702 :param valueY: physics parameter for Y in string
703 :param criteria: selection criteria
704 :param nEvent: number of event to be processed
705
706 For detail, see `plot`
707
708 """
709 h = fillProf (None, classAndKey, valueX, valueY, criteria, nEvent)
710 # draw
711 h.Draw()
712 # this return is needed to draw up the canvas.
713 # note that PyKernel._hSave = h doesn't work although it keeps the hist in memory
714 return h
715
716
717# parse string
718def _parseString (str):
719 # remove $
720 str = re.sub(r"\$", "", str)
721 # replace XXX#YYY with StoreGate access
722 cK = re.findall(r'([\w_]+)#([\w_\*]+)',str)
723 for iCK in cK:
724 # when XXX#*
725 if iCK[1]=='*':
726 bStr = iCK[0]+r"#\*"
727 aStr = 'retrieve(GNS.'+iCK[0]+')'
728 else:
729 bStr = iCK[0]+"#"+iCK[1]
730 aStr = 'retrieve(GNS.'+iCK[0]+',"'+iCK[1]+'")'
731 str = re.sub(bStr, aStr, str)
732 return str
733
734
735# dump objects in StoreGate
736def dumpSG ():
737 '''
738 Dump objects in StoreGate
739
740 **examples**::
741
742 athena> dumpSG()
743
744 '''
745 print (GNS.StoreGate.pointer().dump())
746
747
748# unregister histogram from HistogramSvc
749def unregister (path):
750 '''
751 Unregister histogram from HistogramSvc
752
753 :param path: path to the histogram
754
755 **examples**::
756
757 athena> unregister("/stat/tmpHist")
758
759 '''
760 return theApp.histSvc().unregisterObject(path)
761
762
763# dump histograms in HistogramSvc
764def dumpHist ():
765 '''
766 Dump histograms in HistogramSvc
767
768 **examples**::
769
770 athena> dumpHist()
771
772 '''
773 theApp.histSvc().dump()
774
775
776# set event loop type to pre-process
778 '''
779 Set event loop type to pre-process
780
781 '''
782 global curEvent
783 curEvent = theApp.curEvent()
784 global eventLoopType
785 eventLoopType = _PreProcess
786
787
788# set event loop type to normal-process
790 '''
791 Set event loop type to normal-process
792
793 '''
794 global eventLoopType
795 eventLoopType = _NormalProcess
796
797
798# set event loop type to hybrid-process
800 '''
801 Set event loop type to hybrid-process
802
803 '''
804 global eventLoopType
805 eventLoopType = _HybridProcess
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
__init__(self, methodName)
Definition PyKernel.py:89
-event-from-file
fill2(hist, classAndKey, valueX, valueY, criteria="True", nEvent=100)
Definition PyKernel.py:348
retrieve(aClass, aKey=None)
Definition PyKernel.py:110
fillProf(hist, classAndKey, valueX, valueY, criteria="True", nEvent=100)
Definition PyKernel.py:545
fill(hist, classAndKey, value, criteria="True", nEvent=100)
Definition PyKernel.py:167
plot2(classAndKey, valueX="$x", valueY="$x", criteria="True", nEvent=100)
Definition PyKernel.py:524
plotProf(classAndKey, valueX="$x", valueY="$x", criteria="True", nEvent=100)
Definition PyKernel.py:697
init(v_theApp, v_rootStream=None)
Definition PyKernel.py:45
retrieveDet(aClass, aKey=None)
Definition PyKernel.py:141