CMS 3D CMS Logo

Classes | Functions | Variables
python.rootplot.rootmath Namespace Reference

Classes

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

Functions

def add (outfile, dest, hists, scales=None, dest_path="", scale_errors=None)
 
def allsame (iterable)
 
def alltrue (iterable)
 
def bayes_divide (outfile, dest, numer, denom)
 
def divide (outfile, dest, numer, denom)
 
def main ()
 
def newadd (outfile, targets, dest_path="")
 
def operator_func (fn)
 
def pathdiff (paths, joiner)
 
def pathdiff2 (paths, joiner='__', truncate=False)
 
def pathdiff3 (paths, joiner='__')
 
def scale_with_error (hist, scale, scale_error=None)
 
def subtract (outfile, dest, hists)
 
def walk_rootfile (rootfile, path='')
 Implementation ######################################################. More...
 

Variables

 __license__
 
 ROOT
 

Detailed Description

rootmath description

Function Documentation

◆ add()

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

Definition at line 266 of file rootmath.py.

266 def add(outfile, dest, hists, scales=None, dest_path="", scale_errors=None):
267  if not scales:
268  scales = [1. for i in range(len(hists))]
269  if not scale_errors:
270  scale_errors = [None for i in range(len(hists))]
271  sumhist = hists[0].Clone(os.path.basename(dest))
272  sumhist = scale_with_error(sumhist, scales[0], scale_errors[0])
273  #sumhist.Scale(scales[0])
274  for i in range(1,len(hists)):
275  sumhist.Add(scale_with_error(hists[i], scales[i], scale_errors[i]))
276  #sumhist.Add(hists[i], scales[i])
277  if dest_path:
278  outfile.cd()
279  if not ROOT.gDirectory.GetDirectory(dest_path):
280  ROOT.gDirectory.mkdir(dest_path)
281  ROOT.gDirectory.cd(dest_path)
282  sumhist.Write()
283  ROOT.gDirectory.cd("/")
284 
285 @operator_func

References FastTimerService_cff.range, and python.rootplot.rootmath.scale_with_error().

Referenced by python.rootplot.rootmath.newadd().

◆ allsame()

def python.rootplot.rootmath.allsame (   iterable)

Definition at line 148 of file rootmath.py.

148 def allsame(iterable):
149  for element in iterable:
150  if element != iterable[0]:
151  return False
152  return True
153 

Referenced by python.rootplot.rootmath.newadd(), python.rootplot.rootmath.pathdiff(), python.rootplot.rootmath.pathdiff2(), and python.rootplot.rootmath.pathdiff3().

◆ alltrue()

def python.rootplot.rootmath.alltrue (   iterable)

Definition at line 154 of file rootmath.py.

154 def alltrue(iterable):
155  for element in iterable:
156  if element != True:
157  return False
158  return True
159 

Referenced by python.rootplot.rootmath.main(), and python.rootplot.rootmath.newadd().

◆ bayes_divide()

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

Definition at line 299 of file rootmath.py.

299 def bayes_divide(outfile, dest, numer, denom):
300  quotient = ROOT.TGraphAsymmErrors()
301  quotient.SetName(os.path.basename(dest))
302  quotient.BayesDivide(numer, denom)
303  quotient.Write()
304 

◆ divide()

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

Definition at line 293 of file rootmath.py.

293 def divide(outfile, dest, numer, denom):
294  quotient = numer.Clone(os.path.basename(dest))
295  quotient.Divide(numer, denom)
296  quotient.Write()
297 
298 @operator_func

◆ main()

def python.rootplot.rootmath.main ( )

Definition at line 305 of file rootmath.py.

305 def main():
306  parser = argparse.ArgumentParser()
307  parser.add_argument('filenames', type=str, nargs='+',
308  help='root files to process')
309  parser.add_argument('--dirs', type=str, nargs='+', default=['/'],
310  help='target directories in the root files; paths to '
311  'histograms will be relative to these')
312  parser.add_argument('--add', default=[], action='append', nargs='*',
313  help='a list of directories or histograms to add')
314  parser.add_argument('--subtract', default=[], action='append', nargs='*',
315  help='a list of directories or histograms to subtract')
316  parser.add_argument('--divide', default=[], action='append', nargs='*',
317  help='2 directories or histograms to divide')
318  parser.add_argument('--bayes-divide', default=[], action='append', nargs='*',
319  help='2 directories or histograms from which to make '
320  'an efficiency plot')
321  args = parser.parse_args()
322  separators = {'add' : '_plus_',
323  'subtract' : '_minus_',
324  'divide' : '_div_',
325  'bayes_divide' : '_eff_'}
326 
327  files = [ROOT.TFile(x, 'read') for x in args.filenames]
328  outfile = ROOT.TFile('out.root', 'recreate')
329  dirs = []
330  for d in args.dirs:
331  dirs += rootglob(files[0], d)
332 
333  if len(files) == 1:
334  f = files[0]
335  for thisdir in dirs:
336  for operation_type, separator in separators.items():
337  for arg_set in getattr(args, operation_type):
338  paths = [joined(thisdir, x) for x in arg_set]
339  if f.GetDirectory(paths[0]):
340  destdir = pathdiff(paths, separator)
341  for target in [os.path.basename(x) for x in
342  rootglob(f, paths[0] + '/*')]:
343  hists = [f.GetDirectory(x).Get(target)
344  for x in paths]
345  if not alltrue([x and x.InheritsFrom('TH1')
346  for x in hists]):
347  continue
348  dest = joined(destdir, target)
349  math_func = globals()[operation_type]
350  math_func(outfile, dest, hists)
351  else:
352  hists = [f.GetDirectory(thisdir).Get(x) for x in paths]
353  if not alltrue([x and x.InheritsFrom('TH1')
354  for x in hists]):
355  continue
356  dest = pathdiff(paths, separator)
357  math_func = globals()[operation_type]
358  math_func(outfile, dest, hists)
359  else:
360  for operation_type, separator in separators.items():
361  arg_sets = getattr(args, operation_type)
362  if arg_sets and arg_sets != [[]]:
363  raise ValueError("No arguments to --%s allowed when multiple "
364  "files are specified" % operation_type)
365  elif arg_sets:
366  if 'divide' in operation_type and len(files) != 2:
367  raise ValueError("Exactly 2 files are expected with --%s; "
368  "%i given" % (operation_type, len(files)))
369  for path, folders, objects in walk_rootfile(files[0]):
370  for obj in objects:
371  hists = [x.GetDirectory(path).Get(obj) for x in files]
372  if not alltrue([x and x.InheritsFrom('TH1')
373  for x in hists]):
374  continue
375  math_func = globals()[operation_type]
376  math_func(outfile, joined(path, obj), hists)
377 
378  outfile.Close()
379 

References python.rootplot.rootmath.alltrue(), python.rootplot.rootmath.pathdiff(), python.rootplot.utilities.rootglob(), and python.rootplot.rootmath.walk_rootfile().

◆ newadd()

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

Definition at line 67 of file rootmath.py.

67 def newadd(outfile, targets, dest_path=""):
68  """Description."""
69  if allsame([x.filename for x in targets]):
70  f = ROOT.TFile(targets[0].filename, 'read')
71  paths = [x.path for x in targets]
72  scales = [x.scale for x in targets]
73  scale_errors = [x.scale_error for x in targets]
74  if f.GetDirectory(paths[0]):
75  destdir = pathdiff2(paths) # What does this do?
76  for h in [os.path.basename(x) for x in
77  rootglob(f, paths[0] + '/*')]:
78  hists = [f.GetDirectory(x).Get(h) for x in paths]
79  if not alltrue([x and x.InheritsFrom('TH1') for x in hists]):
80  continue
81  dest = joined(destdir, h)
82  add(outfile, dest, hists, scales, dest_path, scale_errors=scale_errors)
83  else:
84  hists = [f.Get(x) for x in paths]
85  if alltrue([x and x.InheritsFrom('TH1') for x in hists]):
86  dest = pathdiff2(paths)
87  add(outfile, dest, hists, scales, scale_errors=scale_errors)
88  else:
89  dict_targets = {} # Stores paths and scales, key = filename
90  dict_tfiles = {} # Stores map from filenames to Root.TFile() objects
91  for target in targets:
92  dict_targets.setdefault(target.filename, []).append((target.path, target.scale))
93  if (target.filename not in dict_tfiles):
94  # Only open root files once
95  dict_tfiles[target.filename] = ROOT.TFile(target.filename, 'read')
96  # dict_targets now a dictionary, with keys the filenames, example:
97  # {'fileA.root': [('path0',scale0), ('path1', scale1)],
98  # 'fileB.root': [('path3', scale3)]}
99  f = ROOT.TFile(targets[0].filename, 'read')
100  if f.GetDirectory(targets[0].path):
101  # Create list of histograms to get
102  destdir = '/' # should probably use pathdiff2 somehow
103  histnames = [os.path.basename(x) for x in
104  rootglob(f, targets[0].path + '/*')]
105  f.Close()
106  # For each histogram name found, grab it from
107  # every file & path
108  for histname in histnames:
109  hists = []
110  scales = []
111  for filename in dict_targets:
112  tfile_cur = dict_tfiles[filename]
113  for path, scale in dict_targets[filename]:
114  hists.append(tfile_cur.GetDirectory(path).Get(histname))
115  scales.append(scale)
116  #print "%s:%s:%s:%f" % (filename, path, histname, scale)
117  if not alltrue([x and x.InheritsFrom('TH1') for x in hists]):
118  continue
119  dest = joined(destdir, histname)
120  add(outfile, dest, hists, scales, dest_path)
121  else:
122  print("Code not written yet to add histograms from multiple files")
123  return
124  return
125 
126 

References python.rootplot.rootmath.add(), python.rootplot.rootmath.allsame(), python.rootplot.rootmath.alltrue(), mps_setup.append, python.rootplot.rootmath.pathdiff2(), edm.print(), and python.rootplot.utilities.rootglob().

◆ operator_func()

def python.rootplot.rootmath.operator_func (   fn)

Definition at line 242 of file rootmath.py.

242 def operator_func(fn):
243  def newfunc(outfile, dest, hists, scales=None, dest_path="", scale_errors=None):
244  outfile.cd()
245  for d in os.path.dirname(dest).split('/'):
246  if not ROOT.gDirectory.GetDirectory(d):
247  ROOT.gDirectory.mkdir(d)
248  ROOT.gDirectory.cd(d)
249  fn(outfile, dest, hists, scales, dest_path, scale_errors)
250  return newfunc
251 

References personalPlayback.fn, and cms::dd.split().

◆ pathdiff()

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 160 of file rootmath.py.

160 def pathdiff(paths, joiner):
161  """
162  Return the appropriate destination for an object.
163 
164  In all cases, the result will be placed in the deepest directory shared by
165  all paths. If the histogram names are the same, the result will be named
166  based on the first directories that they do not share. Otherwise, the
167  result will be named based on the names of the other histograms.
168 
169  >>> pathdiff(['/dirA/dirB/dirX/hist', '/dirA/dirB/dirY/hist'], '_div_')
170  '/dirA/dirB/dirX_div_dirY'
171  >>> pathdiff(['/dirA/hist1', '/dirA/hist2', '/dirA/hist3'], '_plus_')
172  '/dirA/hist1_plus_hist2_plus_hist3'
173  >>> pathdiff(['/hist1', '/dirA/hist2'], '_minus_')
174  '/hist1_minus_hist2'
175  """
176  paths = [x.split('/') for x in paths]
177  dest = '/'
178  for i in range(len(paths[0])):
179  if allsame([p[i] for p in paths]):
180  dest = joined(dest, paths[0][i])
181  else:
182  break
183  name = joiner.join([p[-1] for p in paths])
184  if allsame([p[-1] for p in paths]):
185  for i in range(len(paths[0])):
186  if not allsame([p[i] for p in paths]):
187  name = joiner.join([p[i] for p in paths])
188  return joined(dest, name)
189 

References python.rootplot.rootmath.allsame(), and FastTimerService_cff.range.

Referenced by python.rootplot.rootmath.main().

◆ pathdiff2()

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

Definition at line 190 of file rootmath.py.

190 def pathdiff2(paths, joiner='__', truncate=False):
191  """
192  Placeholder.
193  """
194  paths = [x.split('/') for x in paths]
195  commonbeginning = ''
196  for i in range(len(paths[0])):
197  if allsame([p[i] for p in paths]):
198  commonbeginning = joined(commonbeginning, paths[0][i])
199  else:
200  break
201  commonending = ''
202  for i in range(-1, -1 * len(paths[0]), -1):
203  if allsame([p[i] for p in paths]):
204  commonending = joined(paths[0][i], commonending)
205  else:
206  break
207  #return commonbeginning, commonending
208  if truncate:
209  return commonending
210  else:
211  return joined(commonbeginning, commonending)
212 

References python.rootplot.rootmath.allsame(), and FastTimerService_cff.range.

Referenced by python.rootplot.rootmath.newadd().

◆ pathdiff3()

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 213 of file rootmath.py.

213 def pathdiff3(paths, joiner='__'):
214  """
215  Return the appropriate destination for an object.
216 
217  If the final objects in each path match, then the return value will be the
218  matching part of the paths. Otherwise, the output path will simply be those
219  names joined together with *joiner*. See the examples below.
220 
221  >>> pathdiff3(['/dirA/dirX/hist', '/dirA/dirY/hist'])
222  '/hist'
223  >>> pathdiff3(['/dirA/dirX/dirB/hist', '/dirA/dirY/dirB/hist'])
224  '/dirB/hist'
225  >>> pathdiff3(['/dirA/hist1', '/dirA/hist2', '/dirA/hist3'], '_plus_')
226  '/hist1_plus_hist2_plus_hist3'
227  >>> pathdiff3(['/hist1', '/dirA/hist2'], '_div_')
228  '/hist1_div_hist2'
229  """
230  paths = [x.split('/') for x in paths]
231  if allsame([x[-1] for x in paths]):
232  dest = paths[0][-1]
233  for i in range(-2, min([len(x) for x in paths]) * -1, -1):
234  if allsame([p[i] for p in paths]):
235  dest = joined(paths[0][i], dest)
236  else:
237  break
238  return '/' + dest
239  else:
240  return '/' + joiner.join([x[-1] for x in paths])
241 

References python.rootplot.rootmath.allsame(), min(), and FastTimerService_cff.range.

◆ scale_with_error()

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 252 of file rootmath.py.

252 def scale_with_error(hist, scale, scale_error=None):
253  '''Scale a histogram by a scale factor that has an error.
254  This takes into account the scale error to set new error bars.'''
255  hist_new = hist.Clone()
256  if scale_error:
257  for i in range(hist_new.GetNbinsX()+2):
258  hist_new.SetBinContent(i, scale)
259  hist_new.SetBinError(i, scale_error)
260  hist_new.Multiply(hist)
261  else:
262  hist_new.Scale(scale)
263  return hist_new
264 
265 @operator_func

References FastTimerService_cff.range.

Referenced by python.rootplot.rootmath.add().

◆ subtract()

def python.rootplot.rootmath.subtract (   outfile,
  dest,
  hists 
)

Definition at line 286 of file rootmath.py.

286 def subtract(outfile, dest, hists):
287  diffhist = hists[0].Clone(os.path.basename(dest))
288  for hist in hists[1:]:
289  diffhist.Add(hist, -1)
290  diffhist.Write()
291 
292 @operator_func

◆ walk_rootfile()

def python.rootplot.rootmath.walk_rootfile (   rootfile,
  path = '' 
)

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

Definition at line 130 of file rootmath.py.

130 def walk_rootfile(rootfile, path=''):
131 
132  keys = rootfile.GetDirectory(path).GetListOfKeys()
133  folders, objects = [], []
134  for key in keys:
135  name = key.GetName()
136  classname = key.GetClassName()
137  newpath = joined(path, name)
138  dimension = 0
139  if 'TDirectory' in classname:
140  folders.append(name)
141  else:
142  objects.append(name)
143  yield path, folders, objects
144  for folder in folders:
145  for x in walk_rootfile(rootfile, joined(path, folder)):
146  yield x
147 

Referenced by python.rootplot.rootmath.main().

Variable Documentation

◆ __license__

python.rootplot.rootmath.__license__
private

Definition at line 8 of file rootmath.py.

◆ ROOT

python.rootplot.rootmath.ROOT

Definition at line 46 of file rootmath.py.

FastTimerService_cff.range
range
Definition: FastTimerService_cff.py:34
python.rootplot.rootmath.newadd
def newadd(outfile, targets, dest_path="")
Definition: rootmath.py:67
min
T min(T a, T b)
Definition: MathUtil.h:58
cms::dd::split
std::vector< std::string_view > split(std::string_view, const char *)
python.rootplot.rootmath.walk_rootfile
def walk_rootfile(rootfile, path='')
Implementation ######################################################.
Definition: rootmath.py:130
python.rootplot.rootmath.pathdiff2
def pathdiff2(paths, joiner='__', truncate=False)
Definition: rootmath.py:190
python.rootplot.rootmath.main
def main()
Definition: rootmath.py:305
python.rootplot.rootmath.operator_func
def operator_func(fn)
Definition: rootmath.py:242
python.rootplot.rootmath.allsame
def allsame(iterable)
Definition: rootmath.py:148
mps_setup.append
append
Definition: mps_setup.py:85
python.rootplot.rootmath.pathdiff3
def pathdiff3(paths, joiner='__')
Definition: rootmath.py:213
edm::print
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
python.rootplot.utilities.rootglob
def rootglob(tdirectory, pathname)
Definition: utilities.py:559
python.rootplot.rootmath.alltrue
def alltrue(iterable)
Definition: rootmath.py:154
python.rootplot.rootmath.pathdiff
def pathdiff(paths, joiner)
Definition: rootmath.py:160
personalPlayback.fn
fn
Definition: personalPlayback.py:515
python.rootplot.rootmath.add
def add(outfile, dest, hists, scales=None, dest_path="", scale_errors=None)
Definition: rootmath.py:266
divide
void divide(dqm::legacy::MonitorElement *eff, const dqm::legacy::MonitorElement *numerator, const dqm::legacy::MonitorElement *denominator)
Function to fill an efficiency histograms with binomial errors.
Definition: Histograms.h:20
python.rootplot.rootmath.scale_with_error
def scale_with_error(hist, scale, scale_error=None)
Definition: rootmath.py:252
python.rootplot.rootmath.bayes_divide
def bayes_divide(outfile, dest, numer, denom)
Definition: rootmath.py:299
python.rootplot.rootmath.subtract
def subtract(outfile, dest, hists)
Definition: rootmath.py:286