330def _py_init_THistSvc():
331 import cppyy
332
333 _load_dict( "libGaudiKernelDict" )
334
335
336
337 global ITHistSvc
338 ITHistSvc = cppyy.gbl.ITHistSvc
339
340 ROOT = _import_ROOT()
341 @property
342 def _py_cache(self):
343 try:
344 return self.__py_cache
345 except AttributeError:
346 self.__py_cache = dict()
347 return self.__py_cache
348 ITHistSvc._py_cache = _py_cache
349
350
351
352 ITHistSvc._cpp_regHist = ITHistSvc.regHist
353 ITHistSvc._cpp_regGraph = ITHistSvc.regGraph
354 ITHistSvc._cpp_regEfficiency = ITHistSvc.regEfficiency
355 ITHistSvc._cpp_regTree = ITHistSvc.regTree
356
357 def book(self, oid, obj=None, *args, **kw):
358 """book a histogram, profile or tree
359 @param oid is the unique object identifier even across streams,
360 ie: 'stream'+'id'
361 @param obj either an already full-fledge constructed ROOT object
362 or None (then `*args` or `**kw` need to be correctly setup)
363 @param *args list of arguments to give to the constructor of the
364 ROOT object one wants to book
365 @param **kw a dictionary containing a key 'args' being the list of
366 arguments to the constructor of the ROOT objects one wants to
367 book
368 examples:
369 >>> th.book('/temp/1d/h1', 'TH1D', args=('h1','h1',100,0.,100.))
370 >>> th.book('/temp/1d/h2', ROOT.TH1D, args=('h2','h2',100,0.,100.))
371 >>> th.book('/temp/1d/h3', ROOT.TH1D, 'h3','h3',100,0.,100.)
372 >>> th.book('/temp/1d/h4', ROOT.TH1D('h4','h4',100,0.,100.))
373 >>> th.book('/temp/1d/h5', obj=ROOT.TH1D('h5','h5',100,0.,100.))
374 >>> th.book('/temp/1d/h6', klass='TH1D', args=('h6','h6',100,0.,100.))
375
376 >>> th.book('/temp/tree/t1', ROOT.TTree('t1','t1'))
377 >>> th.book('/temp/tree/t2', obj=ROOT.TTree('t2','t2'))
378 >>> th.book('/temp/tree/t3', klass='TTree', args=('t3','t3'))
379 """
380 _err = "please provide _either_ an already constructed ROOT object or"\
381 "a class name/class type (with appropriate arguments)"
382 klass = kw.get('klass', None)
383 assert not (obj is None and klass is None), _err
384 assert not (obj is not None and klass is not None), _err
385
386 if isinstance(obj, (str,type)):
387 klass=obj
388 obj=None
389 if obj:
390 if isinstance(obj, ROOT.TH1):
391
392 meth = self._cpp_regHist
393 elif isinstance(obj, (ROOT.TGraph,)):
394 meth = self._cpp_regGraph
395 elif isinstance(obj, (ROOT.TEfficiency,)):
396 meth = self._cpp_regEfficiency
397 elif isinstance(obj, (ROOT.TTree,)):
398 meth = self._cpp_regTree
399 else:
400 raise TypeError(
"invalid type '%r'"%
type(obj))
401 if meth(oid, obj).isSuccess():
402 self._py_cache[oid]=obj
403 return obj
404 raise RuntimeError('could not book object [%r]'%obj)
405
406 if klass:
407 if isinstance(klass, str):
408 klass = getattr(ROOT, klass)
409 if args:
410 return self.book(oid, obj=klass(*args))
411 if kw and 'args' in kw:
412 return self.book(oid, obj=klass(*kw['args']))
413 err = "invalid arguments: either provide a valid `*args` or "\
414 "a `**kw` containing a 'args' key"
415 raise RuntimeError(err)
416 raise RuntimeError("unforseen case: oid='%r' obj='%r' args='%r' "
417 "kw='%r'"%(oid,obj,args,kw))
418
419 ITHistSvc.book = book
420
421 def get(self, oid, klass=None):
422 """retrieve an already booked ROOT object.
423 If the object was booked on the C++ side, try to use the `klass` hint
424 (the usual string or type) to find the object in the correct 'folder'
425 (histograms, graphs or trees).
426 If `klass` is None, then go through all the folders iteratively (slow)
427 """
428 try:
429 return self._py_cache[oid]
430 except KeyError:
431 pass
432 def _get_helper(klass, hsvc, meth, oid, update_cache=True):
433 makeNullPtr = ROOT.MakeNullPointer
434 o = makeNullPtr(klass)
435 if meth(oid, o).isSuccess():
436 if update_cache:
437 hsvc._py_cache[oid] = o
438 return o
439 return
440 if klass:
441 if isinstance(klass, str):
442 klass = getattr(ROOT, klass)
443 if issubclass(klass, (ROOT.TH1,)):
444 return _get_helper(klass, self, self.getHist, oid)
445 if issubclass(klass, (ROOT.TGraph,)):
446 return _get_helper(klass, self, self.getGraph, oid)
447 if issubclass(klass, (ROOT.TEfficiency,)):
448 return _get_helper(klass, self, self.getEfficiency, oid)
449 if issubclass(klass, (ROOT.TTree,)):
450 return _get_helper(klass, self, self.getTree, oid)
451 raise RuntimeError('unsupported type [%r]'%klass)
452
453
454
455
456
457 oids = [n for n in self.getHists() if n not in self._py_cache.keys()]
458 for name in oids:
459 obj = _get_helper(ROOT.TH1, self, self.getHist, name,
460 update_cache=False)
461 if obj:
462
463 klass = getattr(ROOT, obj.ClassName())
464 obj = _get_helper(klass, self, self.getHist, name)
465
466
467 oids = [n for n in self.getGraphs() if n not in self._py_cache.keys()]
468 for name in oids:
469 _get_helper(ROOT.TGraph, self, self.getGraph, name)
470
471
472 oids = [n for n in self.getEfficiencies() if n not in self._py_cache.keys()]
473 for name in oids:
474 _get_helper(ROOT.TEfficiency, self, self.getEfficiency, name)
475
476
477 oids = [n for n in self.getTrees() if n not in self._py_cache.keys()]
478 for name in oids:
479 _get_helper(ROOT.TTree, self, self.getTree, name)
480
481
482 return self._py_cache[oid]
483
484 ITHistSvc.get = get
485 del get
486
487 def getitem(self, oid):
488 return self.get(oid)
489 ITHistSvc.__getitem__ = getitem
490 del getitem
491
492 def delitem(self, oid):
493 if isinstance(oid, str):
494 self.get(oid)
495 del self._py_cache[oid]
496 assert self.deReg(oid).isSuccess(), \
497 "could not remove object [%r]"%oid
498 return
499 ITHistSvc.__delitem__ = delitem
500
501 def setitem(self, k, v):
502 return self.book(k, obj=v)
503 ITHistSvc.__setitem__ = setitem
504 del setitem
505
506 def regObject(self, regFcn, oid, oid_type=None):
507 """Helper method to register object 'oid' using 'regFcn'."""
508 if oid_type is not None:
509 return self.book(oid,obj=oid_type)
510 if regFcn(self,oid).isSuccess():
511
512 return self.get(oid)
513 err = ''.join(['invalid arguments oid=',repr(oid),' oid_type=',
514 repr(oid_type)])
515 raise ValueError(err)
516
517 ITHistSvc.regHist = partialmethod(regObject, ITHistSvc._cpp_regHist)
518 ITHistSvc.regTree = partialmethod(regObject, ITHistSvc._cpp_regTree)
519 ITHistSvc.regEfficiency = partialmethod(regObject, ITHistSvc._cpp_regEfficiency)
520 ITHistSvc.regGraph = partialmethod(regObject, ITHistSvc._cpp_regGraph)
521 del regObject
522
523 def load(self, oid, oid_type):
524 """Helper method to load a given object `oid' from a stream, knowing
525 its type. `oid_type' is a string whose value is either:
526 - 'hist', to load any THx and TProfiles
527 - 'tree', to load TTrees
528 - 'efficiency', to load TEfficiency
529 - 'graph', to load TGraph and TGraphErrors
530 """
531 if oid_type == 'hist':
532 return self.regHist(oid)
533 elif oid_type == 'tree':
534 return self.regTree(oid)
535 elif oid_type == 'efficiency':
536 return self.regEfficiency(oid)
537 elif oid_type == 'graph':
538 return self.regGraph(oid)
539 else:
540 raise ValueError(f'oid_type (={oid_type}) MUST be one of hist, tree, efficiency, graph')
541
542 ITHistSvc.load = load
543 del load
544
545
546
547 for n in ('__contains__',
548 '__iter__',
549 '__len__',
550 'has_key',
551 'items', 'iteritems',
552 'iterkeys', 'itervalues',
553 'keys', 'values'):
554 code = """\
555def %s(self, *args, **kw):
556 return self._py_cache.%s(*args,**kw)
557ITHistSvc.%s = %s
558del %s""" % (n,n,n,n,n)
559 exec (code, globals(),locals())
560
561
562 def __bool__(self):
563 return self is not None
564 ITHistSvc.__bool__ = __bool__
565 del __bool__
566
567 def pop(self, k):
568 obj = self.get(k)
569 assert self.deReg(obj).isSuccess(), \
570 "could not remove object [%r]"%k
571 return obj
572 ITHistSvc.pop = pop
573 del pop
574
575 def popitem(self):
576 k = self.iterkeys().next()
577 return (k, self.pop(k))
578 ITHistSvc.popitem = popitem
579 del popitem
580
581
582
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)