5 Collection of utilities to ease interaction with ROOT. 
    7 Unsurprisingly, this module requires ROOT. 
   11   "splitROOTpath", 
"createROOTpath", 
"getROOTclass",
 
   22   The ROOT interpreter likes to peek at the command line arguments and interpret 
   24   For example, an option `-b` will be interpreted to set ROOT in batch mode. 
   25   Likewise, if a `--help` argument is present on the command line, the 
   26   interpreter will print the ROOT help message and, even worse, halt the script. 
   27   This is clearly not very friendly to the script. 
   29   The initialization of the interpreter happens lazily the first time anything 
   30   is read out of `ROOT` module: `import ROOT` is not enough, but pretty much 
   31   everything after that involving ROOT is (exception: `ROOT.gROOT` will not 
   32   trigger the interpreter, but trying to get anything out of `ROOT.gROOT` will). 
   33   That makes it complicate to control when that happens. 
   35   This function triggers the interpreter initialization after having removed all 
   36   command line options, and finally restores them (we use a context manager to 
   37   show that we know Python). The loaded module is returned. 
   39   This function is called as soon as this module is imported. It is important 
   40   that this happens as early as possible, possibly as a replacement of ROOT 
   43       from ROOTutils import ROOT 
   45       from ROOTutils import * 
   53   try:              alreadyLoaded = 
'gInterpreter' in dir(ROOT)
 
   54   except NameError: alreadyLoaded = 
False 
   57       "ROOT module was loaded before ROOTutils.py: command line arguments may be garbled" 
   59     return sys.modules[
'ROOT']
 
   65       logging.debug(
"Saving command line: %s", self.args)
 
   66       sys.argv = sys.argv[0:1]
 
   68        "Replaced command line %s with %s before loading ROOT module",
 
   70     def __exit__(self, exc_type, exc_value, traceback):
 
   72       logging.debug(
"Restored command line %s", sys.argv)
 
   89   return "( %g, %g )" % (v.X(), v.Y())
 
   91   return "( %g, %g, %g )" % (v.X(), v.Y(), v.Z())
 
   93   return "( %g, %g, %g; %g )" % (v.X(), v.Y(), v.Z(), v.T())
 
   95 ROOT.TVector2.__str__ = TVector2ToString
 
   96 ROOT.TVector3.__str__ = TVector3ToString
 
   97 ROOT.TLorentzVector.__str__ = TLorentzVectorToString
 
  105   Returns the specified path split into file path and ROOT directory path. 
  107   The `path` is in the form: 
  108   "/UNIX/path/to/file.root:internal/ROOT/directory/and/object". 
  109   The returned value is a pair `(filePath, dirPath)`: in the example, that 
  110   would be `("/UNIX/path/to/file.root", "internal/ROOT/directory/and/object")`. 
  112   Note: for compatibility with some ROOT tradition, the separator ':' can be 
  118     filePath, ROOTpath = path.rsplit(
'.root')
 
  120     raise RuntimeError(
"Path '{}' does not include a ROOT file.".
format(path))
 
  124   return filePath, ROOTpath
 
  131   Creates a complete ROOT directory path. 
  133   The `path` is in the form: 
  134   "/UNIX/path/to/file.root:internal/ROOT/directory/structure". 
  135   The ROOT file `/UNIX/path/to/file.root` will be created with the specified 
  136   `fileMode` (path may be relative), then the `TDirectoryFile` hierarchy 
  137   `internal/ROOT/directory/structure` will be created under it. 
  138   The return value is a pair `(file, dir)`, where `file` is a open `TFile` 
  139   for `/UNIX/path/to/file.root` and `dir` is the `TDirectory` object of 
  142   Remember to keep track of `file`, or else python may close it compromising 
  148   ROOTfile = ROOT.TFile(filePath, fileMode)
 
  149   if not ROOTfile.IsOpen():
 
  151       (
"Can't open ROOT file '{}' in '{}' mode".
format(filePath, fileMode))
 
  154   ROOTpathElements = ROOTpath.split(
'/')
 
  156   for ROOTdirName 
in ROOTpathElements:
 
  157     if not ROOTdirName: 
continue  
  158     daughterDir = ROOTdir.GetDirectory(ROOTdirName)
 
  160       daughterDir = ROOTdir.CreateDirectory(ROOTdirName)
 
  162       raise RuntimeError(
"Can't access directory '{}' under '{}'".format
 
  163        (ROOTdirName, ROOTdir.GetPath()))
 
  164     ROOTdir = daughterDir
 
  167   return ROOTfile, ROOTdir
 
  174   Object changing ROOT directory while on scope. 
  176   The purpose is to make a ROOT directory current only as long as it is needed. 
  177   The most typical uses of this objects include the automatic restoration of 
  178   the previous directory as the object falls out of scope. 
  179   Two methods are supported: 
  182         def writeEverythingInto(dir, everything): 
  183           dirChanger = ROOTutils.DirectoryChanger(dir) 
  184           for item in everything: item.Write() 
  185         # writeEverythingInto() 
  187   2. local scope (equivalent to using `activateDirectory()`): 
  189         with DirectoryChanger(dir): 
  190           for item in everything: item.Write() 
  196     if saveDir: self.
saveDir(saveDir)
 
  204   def saveDir(self, ROOTdir): self.oldDir = ROOTdir
 
  207     if self.
newDir: self.newDir.cd()
 
  210     if self.
oldDir: self.oldDir.cd()
 
  220   def __exit__(self, exc_type, exc_value, traceback):
 
  229   Sets a directory with `DirectoryChanger`. 
  233         dir = outputFile.GetDirectory("plots") 
  234         with activateDirectory(dir): 
  235           for plot in plots: item.Write() 
  244   """Returns the object specified by `classPath` within ROOT module. 
  246   Throws `AttributeError` if any object in the path is not available. 
  248   Example: `getROOTclass('geo::GeometryCore')` returns `ROOT.geo.GeometryCore`. 
  250   classPath = classPath.replace(
'::', 
'.').lstrip(
'.')
 
  252   for objName 
in classPath.split(
'.'):
 
  253     base = getattr(base, objName)
 
  261  fileListPath: 
"path of the file list",
 
  262  comment: 
"(default: '#') character used to introduce a comment" = 
'#',
 
  263  fileListSuffixes: 
"suffix of entries to recursively add file lists" = [],
 
  264  ) -> 
"a list of file names":
 
  265   """Returns a list of file names as found in the specified file list. 
  267   The `fileListPath` path is read as a text file; each line represents a full 
  269   Empty lines and lines starting with a comment character are ignored. 
  270   Also if blanks and a comment character are found, the content of the line 
  271   from the first of those blank characters on is ignored as part of a comment. 
  272   If `comment` is `None`, this feature is disabled. 
  274   If file list suffixes are specified, a line ending with any of those suffixes 
  275   will be considered a file list itself, and recursively expanded. 
  277   If `fileListPath` can't be read, an exception is raised. 
  283   with 
open(fileListPath, 
'r') as fileList: 
  287       if not line: 
continue 
  289         if line.startswith(comment): 
continue 
  291         words = line.split(comment)
 
  293         for left, right 
in zip(words[:-1], words[1:]):
 
  294           if left 
and left[-1].isspace():
 
  295             logging.debug(
"Comment starting at line %d between '%s' and '%s'", iLine, left, right)
 
  297           line += comment + right
 
  302       for suffix 
in fileListSuffixes:
 
  303         if not line.endswith(suffix): 
continue 
  304         logging.debug(
"Adding content of file list from line %d ('%s')", iLine, line)
 
  305         extra = 
expandFileList(line, comment=comment, fileListSuffixes=fileListSuffixes)
 
  306         logging.debug(
"%d entries collected under file list '%s'", len(extra), line)
 
  310         logging.debug(
"Line %d added to the list", iLine)
 
static std::string format(PyObject *obj, unsigned int pos, unsigned int indent, unsigned int maxlen, unsigned int depth)
 
def splitROOTpath
File management. 
 
def TVector2ToString
Print vectors easily. 
 
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration. 
 
def ROOTloader
Try to save the command line arguments from unconsiderate ROOT behaviour. 
 
def TLorentzVectorToString
 
def expandFileList
this is not really specific to ROOT, but we often have ROOT file lists 
 
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time. 
 
open(RACETRACK) or die("Could not open file $RACETRACK for writing")