CMS 3D CMS Logo

Classes | Functions | Variables

python::rootplot::rootmath Namespace Reference

Classes

class  Target
 Classes #############################################################. More...

Functions

def add
def allsame
def alltrue
def bayes_divide
def divide
def main
def newadd
def operator_func
def pathdiff
def pathdiff2
def pathdiff3
def scale_with_error
def subtract
def walk_rootfile
 Implementation ######################################################.

Variables

string __license__
tuple ROOT = loadROOT()

Detailed Description

rootmath description

Function Documentation

def python::rootplot::rootmath::add (   outfile,
  dest,
  hists,
  scales = None,
  dest_path = "",
  scale_errors = None 
)

Definition at line 263 of file rootmath.py.

00264                                                                            :
00265     if not scales:
00266         scales = [1. for i in range(len(hists))]
00267     if not scale_errors:
00268         scale_errors = [None for i in range(len(hists))]
00269     sumhist = hists[0].Clone(os.path.basename(dest))
00270     sumhist = scale_with_error(sumhist, scales[0], scale_errors[0])
00271     #sumhist.Scale(scales[0])
00272     for i in range(1,len(hists)):
00273         sumhist.Add(scale_with_error(hists[i], scales[i], scale_errors[i]))
00274         #sumhist.Add(hists[i], scales[i])
00275     if dest_path:
00276         outfile.cd()
00277         if not ROOT.gDirectory.GetDirectory(dest_path):
00278             ROOT.gDirectory.mkdir(dest_path)
00279         ROOT.gDirectory.cd(dest_path)
00280     sumhist.Write()
00281     ROOT.gDirectory.cd("/")
00282 
@operator_func
def python::rootplot::rootmath::allsame (   iterable)

Definition at line 145 of file rootmath.py.

00146                      :
00147     for element in iterable:
00148         if element != iterable[0]:
00149             return False
00150     return True

def python::rootplot::rootmath::alltrue (   iterable)

Definition at line 151 of file rootmath.py.

00152                      :
00153     for element in iterable:
00154         if element != True:
00155             return False
00156     return True

def python::rootplot::rootmath::bayes_divide (   outfile,
  dest,
  numer,
  denom 
)

Definition at line 296 of file rootmath.py.

00297                                              :
00298     quotient = ROOT.TGraphAsymmErrors()
00299     quotient.SetName(os.path.basename(dest))
00300     quotient.BayesDivide(numer, denom)
00301     quotient.Write()

def python::rootplot::rootmath::divide (   outfile,
  dest,
  numer,
  denom 
)

Definition at line 290 of file rootmath.py.

00291                                        :
00292     quotient = numer.Clone(os.path.basename(dest))
00293     quotient.Divide(numer, denom)
00294     quotient.Write()
00295 
@operator_func
def python::rootplot::rootmath::main ( )

Definition at line 302 of file rootmath.py.

00303           :
00304     parser = argparse.ArgumentParser()
00305     parser.add_argument('filenames', type=str, nargs='+',
00306                        help='root files to process')
00307     parser.add_argument('--dirs', type=str, nargs='+', default=['/'],
00308                         help='target directories in the root files; paths to '
00309                         'histograms will be relative to these')
00310     parser.add_argument('--add', default=[], action='append', nargs='*',
00311                         help='a list of directories or histograms to add')
00312     parser.add_argument('--subtract', default=[], action='append', nargs='*',
00313                         help='a list of directories or histograms to subtract')
00314     parser.add_argument('--divide', default=[], action='append', nargs='*',
00315                         help='2 directories or histograms to divide')
00316     parser.add_argument('--bayes-divide', default=[], action='append', nargs='*',
00317                         help='2 directories or histograms from which to make '
00318                         'an efficiency plot')
00319     args = parser.parse_args()
00320     separators = {'add' : '_plus_',
00321                   'subtract' : '_minus_',
00322                   'divide' : '_div_',
00323                   'bayes_divide' : '_eff_'}
00324 
00325     files = [ROOT.TFile(x, 'read') for x in args.filenames]
00326     outfile = ROOT.TFile('out.root', 'recreate')
00327     dirs = []
00328     for d in args.dirs:
00329         dirs += rootglob(files[0], d)
00330 
00331     if len(files) == 1:
00332         f = files[0]
00333         for thisdir in dirs:
00334             for operation_type, separator in separators.items():
00335                 for arg_set in getattr(args, operation_type):
00336                     paths = [joined(thisdir, x) for x in arg_set]
00337                     if f.GetDirectory(paths[0]):
00338                         destdir = pathdiff(paths, separator)
00339                         for target in [os.path.basename(x) for x in
00340                                        rootglob(f, paths[0] + '/*')]:
00341                             hists = [f.GetDirectory(x).Get(target)
00342                                      for x in paths]
00343                             if not alltrue([x and x.InheritsFrom('TH1')
00344                                             for x in hists]):
00345                                 continue
00346                             dest = joined(destdir, target)
00347                             math_func = globals()[operation_type]
00348                             math_func(outfile, dest, hists)
00349                     else:
00350                         hists = [f.GetDirectory(thisdir).Get(x) for x in paths]
00351                         if not alltrue([x and x.InheritsFrom('TH1') 
00352                                         for x in hists]):
00353                             continue
00354                         dest = pathdiff(paths, separator)
00355                         math_func = globals()[operation_type]
00356                         math_func(outfile, dest, hists)
00357     else:
00358         for operation_type, separator in separators.items():
00359             arg_sets = getattr(args, operation_type)
00360             if arg_sets and arg_sets != [[]]:
00361                 raise ValueError("No arguments to --%s allowed when multiple "
00362                                  "files are specified" % operation_type)
00363             elif arg_sets:
00364                 if 'divide' in operation_type and len(files) != 2:
00365                     raise ValueError("Exactly 2 files are expected with --%s; "
00366                                      "%i given" % (operation_type, len(files)))
00367                 for path, folders, objects in walk_rootfile(files[0]):
00368                     for obj in objects:
00369                         hists = [x.GetDirectory(path).Get(obj) for x in files]
00370                         if not alltrue([x and x.InheritsFrom('TH1') 
00371                                         for x in hists]):
00372                             continue
00373                         math_func = globals()[operation_type]
00374                         math_func(outfile, joined(path, obj), hists)
00375 
00376     outfile.Close()

def python::rootplot::rootmath::newadd (   outfile,
  targets,
  dest_path = "" 
)
Description.

Definition at line 64 of file rootmath.py.

00065                                           :
00066     """Description."""
00067     if allsame([x.filename for x in targets]):
00068         f = ROOT.TFile(targets[0].filename, 'read')
00069         paths = [x.path for x in targets]
00070         scales = [x.scale for x in targets]
00071         scale_errors = [x.scale_error for x in targets]
00072         if f.GetDirectory(paths[0]):
00073             destdir = pathdiff2(paths)    # What does this do?
00074             for h in [os.path.basename(x) for x in
00075                       rootglob(f, paths[0] + '/*')]:
00076                 hists = [f.GetDirectory(x).Get(h) for x in paths]
00077                 if not alltrue([x and x.InheritsFrom('TH1') for x in hists]):
00078                     continue
00079                 dest = joined(destdir, h)
00080                 add(outfile, dest, hists, scales, dest_path, scale_errors=scale_errors)
00081         else:
00082             hists = [f.Get(x) for x in paths]
00083             if alltrue([x and x.InheritsFrom('TH1') for x in hists]):
00084                 dest = pathdiff2(paths)
00085                 add(outfile, dest, hists, scales, scale_errors=scale_errors)
00086     else:
00087         dict_targets = {}  # Stores paths and scales, key = filename
00088         dict_tfiles = {}   # Stores map from filenames to Root.TFile() objects
00089         for target in targets:
00090             dict_targets.setdefault(target.filename, []).append((target.path, target.scale))
00091             if (target.filename not in dict_tfiles):
00092                 # Only open root files once
00093                 dict_tfiles[target.filename] = ROOT.TFile(target.filename, 'read')
00094         # dict_targets now a dictionary, with keys the filenames, example:
00095         # {'fileA.root': [('path0',scale0), ('path1', scale1)],
00096         #  'fileB.root': [('path3', scale3)]}
00097         f = ROOT.TFile(targets[0].filename, 'read')
00098         if f.GetDirectory(targets[0].path):
00099             # Create list of histograms to get
00100             destdir = '/'               # should probably use pathdiff2 somehow
00101             histnames = [os.path.basename(x) for x in
00102                          rootglob(f, targets[0].path + '/*')]
00103             f.Close()
00104             # For each histogram name found, grab it from
00105             # every file & path
00106             for histname in histnames:
00107                 hists = []
00108                 scales = []
00109                 for filename in dict_targets:
00110                     tfile_cur = dict_tfiles[filename]
00111                     for path, scale in dict_targets[filename]:
00112                         hists.append(tfile_cur.GetDirectory(path).Get(histname))
00113                         scales.append(scale)
00114                         #print "%s:%s:%s:%f" % (filename, path, histname, scale)
00115                 if not alltrue([x and x.InheritsFrom('TH1') for x in hists]):
00116                     continue
00117                 dest = joined(destdir, histname)
00118                 add(outfile, dest, hists, scales, dest_path)
00119         else:
00120             print "Code not written yet to add histograms from multiple files"
00121             return
00122         return
00123 

def python::rootplot::rootmath::operator_func (   fn)

Definition at line 239 of file rootmath.py.

00240                      :
00241     def newfunc(outfile, dest, hists, scales=None, dest_path="", scale_errors=None):
00242         outfile.cd()
00243         for d in os.path.dirname(dest).split('/'):
00244             if not ROOT.gDirectory.GetDirectory(d):
00245                 ROOT.gDirectory.mkdir(d)
00246             ROOT.gDirectory.cd(d)
00247         fn(outfile, dest, hists, scales, dest_path, scale_errors)
00248     return newfunc

def python::rootplot::rootmath::pathdiff (   paths,
  joiner 
)
Return the appropriate destination for an object.

In all cases, the result will be placed in the deepest directory shared by
all paths.  If the histogram names are the same, the result will be named
based on the first directories that they do not share.  Otherwise, the 
result will be named based on the names of the other histograms.

>>> pathdiff(['/dirA/dirB/dirX/hist', '/dirA/dirB/dirY/hist'], '_div_')
'/dirA/dirB/dirX_div_dirY'
>>> pathdiff(['/dirA/hist1', '/dirA/hist2', '/dirA/hist3'], '_plus_')
'/dirA/hist1_plus_hist2_plus_hist3'
>>> pathdiff(['/hist1', '/dirA/hist2'], '_minus_')
'/hist1_minus_hist2'

Definition at line 157 of file rootmath.py.

00158                            :
00159     """
00160     Return the appropriate destination for an object.
00161     
00162     In all cases, the result will be placed in the deepest directory shared by
00163     all paths.  If the histogram names are the same, the result will be named
00164     based on the first directories that they do not share.  Otherwise, the 
00165     result will be named based on the names of the other histograms.
00166 
00167     >>> pathdiff(['/dirA/dirB/dirX/hist', '/dirA/dirB/dirY/hist'], '_div_')
00168     '/dirA/dirB/dirX_div_dirY'
00169     >>> pathdiff(['/dirA/hist1', '/dirA/hist2', '/dirA/hist3'], '_plus_')
00170     '/dirA/hist1_plus_hist2_plus_hist3'
00171     >>> pathdiff(['/hist1', '/dirA/hist2'], '_minus_')
00172     '/hist1_minus_hist2'
00173     """
00174     paths = [x.split('/') for x in paths]
00175     dest = '/'
00176     for i in range(len(paths[0])):
00177         if allsame([p[i] for p in paths]):
00178             dest = joined(dest, paths[0][i])
00179         else:
00180             break
00181     name = joiner.join([p[-1] for p in paths])
00182     if allsame([p[-1] for p in paths]):
00183         for i in range(len(paths[0])):
00184             if not allsame([p[i] for p in paths]):
00185                 name = joiner.join([p[i] for p in paths])
00186     return joined(dest, name)

def python::rootplot::rootmath::pathdiff2 (   paths,
  joiner = '__',
  truncate = False 
)
Placeholder.

Definition at line 187 of file rootmath.py.

00188                                                  :
00189     """
00190     Placeholder.
00191     """
00192     paths = [x.split('/') for x in paths]
00193     commonbeginning = ''
00194     for i in range(len(paths[0])):
00195         if allsame([p[i] for p in paths]):
00196             commonbeginning = joined(commonbeginning, paths[0][i])
00197         else:
00198             break
00199     commonending = ''
00200     for i in range(-1, -1 * len(paths[0]), -1):
00201         if allsame([p[i] for p in paths]):
00202             commonending = joined(paths[0][i], commonending)
00203         else:
00204             break
00205     #return commonbeginning, commonending
00206     if truncate:
00207         return commonending
00208     else:
00209         return joined(commonbeginning, commonending)

def python::rootplot::rootmath::pathdiff3 (   paths,
  joiner = '__' 
)
Return the appropriate destination for an object.

If the final objects in each path match, then the return value will be the
matching part of the paths.  Otherwise, the output path will simply be those
names joined together with *joiner*.  See the examples below.

>>> pathdiff3(['/dirA/dirX/hist', '/dirA/dirY/hist'])
'/hist'
>>> pathdiff3(['/dirA/dirX/dirB/hist', '/dirA/dirY/dirB/hist'])
'/dirB/hist'
>>> pathdiff3(['/dirA/hist1', '/dirA/hist2', '/dirA/hist3'], '_plus_')
'/hist1_plus_hist2_plus_hist3'
>>> pathdiff3(['/hist1', '/dirA/hist2'], '_div_')
'/hist1_div_hist2'

Definition at line 210 of file rootmath.py.

00211                                  :
00212     """
00213     Return the appropriate destination for an object.
00214     
00215     If the final objects in each path match, then the return value will be the
00216     matching part of the paths.  Otherwise, the output path will simply be those
00217     names joined together with *joiner*.  See the examples below.
00218     
00219     >>> pathdiff3(['/dirA/dirX/hist', '/dirA/dirY/hist'])
00220     '/hist'
00221     >>> pathdiff3(['/dirA/dirX/dirB/hist', '/dirA/dirY/dirB/hist'])
00222     '/dirB/hist'
00223     >>> pathdiff3(['/dirA/hist1', '/dirA/hist2', '/dirA/hist3'], '_plus_')
00224     '/hist1_plus_hist2_plus_hist3'
00225     >>> pathdiff3(['/hist1', '/dirA/hist2'], '_div_')
00226     '/hist1_div_hist2'
00227     """
00228     paths = [x.split('/') for x in paths]
00229     if allsame([x[-1] for x in paths]):
00230         dest = paths[0][-1]
00231         for i in range(-2, min([len(x) for x in paths]) * -1, -1):
00232             if allsame([p[i] for p in paths]):
00233                 dest = joined(paths[0][i], dest)
00234             else:
00235                 break
00236         return '/' + dest
00237     else:
00238         return '/' + joiner.join([x[-1] for x in paths])

def python::rootplot::rootmath::scale_with_error (   hist,
  scale,
  scale_error = None 
)
Scale a histogram by a scale factor that has an error.
This takes into account the scale error to set new error bars.

Definition at line 249 of file rootmath.py.

00250                                                    :
00251     '''Scale a histogram by a scale factor that has an error.
00252     This takes into account the scale error to set new error bars.'''
00253     hist_new = hist.Clone()
00254     if scale_error:
00255         for i in range(hist_new.GetNbinsX()+2):
00256             hist_new.SetBinContent(i, scale)
00257             hist_new.SetBinError(i, scale_error)
00258         hist_new.Multiply(hist)
00259     else:
00260         hist_new.Scale(scale)
00261     return hist_new
00262 
@operator_func
def python::rootplot::rootmath::subtract (   outfile,
  dest,
  hists 
)

Definition at line 283 of file rootmath.py.

00284                                   :
00285     diffhist = hists[0].Clone(os.path.basename(dest))
00286     for hist in hists[1:]:
00287         diffhist.Add(hist, -1)
00288     diffhist.Write()
00289 
@operator_func
def python::rootplot::rootmath::walk_rootfile (   rootfile,
  path = '' 
)

Implementation ######################################################.

Definition at line 127 of file rootmath.py.

00128                                     :
00129     #### Yield (path, folders, objects) for each directory under path.
00130     keys = rootfile.GetDirectory(path).GetListOfKeys()
00131     folders, objects = [], []
00132     for key in keys:
00133         name = key.GetName()
00134         classname = key.GetClassName()
00135         newpath = joined(path, name)
00136         dimension = 0
00137         if 'TDirectory' in classname:
00138             folders.append(name)
00139         else:
00140             objects.append(name)
00141     yield path, folders, objects
00142     for folder in folders:
00143         for x in walk_rootfile(rootfile, joined(path, folder)):
00144             yield x


Variable Documentation

Initial value:
00001 '''\
00002 Copyright (c) 2009-2010 Jeff Klukas <klukas@wisc.edu>
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 '''

Definition at line 5 of file rootmath.py.

Definition at line 43 of file rootmath.py.