ATLAS Offline Software
runLayerRecalibration.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
4 __doc__ = "To compute corrected layer energies"
5 
6 from glob import glob
7 import os.path
8 import os
9 from array import array
10 import sys
11 from itertools import izip
12 import logging
13 logging.basicConfig(level=logging.DEBUG)
14 
15 import ROOT
16 ROOT.PyConfig.IgnoreCommandLineOptions = True
17 
18 try:
19  ROOT.gROOT.Macro("$ROOTCOREDIR/scripts/load_packages.C")
20 except RuntimeError:
21  print("""you have to compile egammaLayerRecalibTool first:
22 rc find_packages
23 rc compile
24 """)
25 
26 
27 def LayerRecalibratedGenerator(input_tree, branches):
28  ""
29  tool = ROOT.egammaLayerRecalibTool("2012_alt_with_layer2")
30 
31  def _rec(eta, e0, e1, e2, e3):
32  std_calibration_input = ROOT.StdCalibrationInputs(0, eta, e0, e1, e2, e3, 0)
33  tool.scale_inputs(std_calibration_input)
34  return std_calibration_input.E0raw, std_calibration_input.E1raw, std_calibration_input.E2raw, std_calibration_input.E3raw
35  fcn = _rec
36  entries = input_tree.GetEntries()
37  for i in range(entries):
38  input_tree.GetEntry(i)
39  # check if branch exists
40  try:
41  inputs = list(map(input_tree.__getattr__, branches))
42  except AttributeError:
43  raise AttributeError("cannot find branches %s" % branches)
44 
45  try:
46  yield fcn(*inputs) # scalar
47  except TypeError:
48  result = [fcn(*ii) for ii in izip(*inputs)] # vectors
49  yield list(zip(*result))
50 
51 if __name__ == "__main__":
52  from optparse import OptionParser
53 
54  def foo_callback(option, opt, value, parser):
55  setattr(parser.values, option.dest, value.split(','))
56 
57  parser = OptionParser()
58  parser.add_option("-i", "--input", help="input file or directory")
59  parser.add_option("--nevents", type=int, help="number of events")
60  parser.add_option("-t", "--tree", help="input tree name")
61  parser.add_option("-p", "--particle", type="choice", help="particle type (electron|photon)", choices=("electron","photon"))
62  parser.add_option("-b", "--branches-to-copy", type='string',
63  action='callback',
64  callback=foo_callback,
65  help="comma separated list of branches to copy from the input tree, you can use \*, do not use spaces")
66 
67  (options, args) = parser.parse_args()
68 
69  input_filenames = None
70  if os.path.isdir(options.input):
71  input_filenames = glob(os.path.join(options.input, "*.root*"))
72  else:
73  input_filenames = [options.input]
74  if not input_filenames:
75  print("ERROR: no files found")
76 
77  if not options.particle:
78  raise ValueError("you need to specify a value of --particle")
79 
80  logging.info("found %s files", len(input_filenames))
81 
82  try:
83  ROOT.egammaLayerRecalibTool
84  except:
85  raise AttributeError('You have to load egammaLayerRecalibTool package')
86 
87  prefix = 'el_' if options.particle == 'electron' else 'ph_'
88 
89  for filename in input_filenames:
90  print("patching file %s" % filename)
91 
92  f = ROOT.TFile.Open(filename, "update")
93  tree = f.Get(options.tree)
94  if not tree:
95  raise IOError("cannot find %s" % options.tree)
96 
97 
98  branches = [prefix + 'cl_eta'] + [prefix + 'rawcl_Es%d' % i for i in range(4)]
99  if not all(tree.GetBranch(i) for i in branches):
100  logging.info("skipping %s*", prefix)
101  continue
102 
103  branches_to_copy = options.branches_to_copy or []
104  logging.info("copying these branches: %s", ",".join(branches_to_copy) if branches_to_copy else "None")
105 
106  new_branch_names = [prefix + 'rawcl_Es%d' % i for i in range(4)]
107  if set(new_branch_names).intersection(branches_to_copy):
108  logging.warning("raw_clE* variables in the copy list -> going to rename. PROBABILY YOU DON'T WANT TO DO IT!")
109  new_branch_names = [prefix + 'rawcl_Es%d_new' % i for i in range(4)]
110 
111  tree.SetBranchStatus("*", 0)
112  for branch in branches_to_copy:
113  tree.SetBranchStatus(branch, 1)
114  newtree = tree.CloneTree(0)
115  newtree.SetName("layerRecalibratedTree")
116  newtree.SetTitle("layerRecalibratedTree")
117 
118  # Disable all branches but the needed ones
119  tree.SetBranchStatus('*', 0)
120  for br in set(branches + branches_to_copy):
121  logging.info("activating branch %s", br)
122  tree.SetBranchStatus(br, 1)
123 
124  # Create new branch, the same type as the old one
125  isVector = 'vector' in tree.GetLeaf(prefix + 'rawcl_Es0').GetTypeName()
126  new_storages = []
127  if isVector:
128  for new_branch_name in new_branch_names:
129  new_storage = ROOT.vector(float)()
130  new_storages.append(new_storage)
131  newtree.Branch(new_branch_name, new_storage)
132  else:
133  for new_branch_name in new_branch_names:
134  new_storage = array('f', [0.])
135  new_storages.append(new_storage)
136  newtree.Branch(new_branch_name, new_storage, new_branch_name + '/F')
137 
138  for i, new_value in enumerate(LayerRecalibratedGenerator(tree, branches)):
139  if i % 1000 == 0:
140  print(i)
141  if options.nevents and i >= options.nevents:
142  break
143 
144  if isVector:
145  for s, d in zip(new_storages, new_value):
146  s.clear()
147  map(s.push_back, d)
148  else:
149  for s, v in zip(new_storages, new_value):
150  s[0] = v
151  newtree.Fill()
152  print("loop ended after %d events" % i)
153 
154  logging.debug("all events done")
155  tree.SetBranchStatus('*', 1)
156  logging.debug("adding friend")
157  tree.AddFriend(newtree)
158  logging.info("updating old tree")
159  tree.GetCurrentFile().Write("", ROOT.TObject.kOverwrite)
160  logging.info("writing new tree")
161  if f.Get("layerRecalibratedTree"):
162  newtree.GetCurrentFile().Write("", ROOT.TObject.kOverwrite)
163  else:
164  newtree.GetCurrentFile().Write()
165  logging.debug("closing file")
166 
167  # this is because ROOT is stupid
168  tree.SetDirectory(0)
169  newtree.SetDirectory(0)
170 
171  f.Close()
172  logging.debug("closed")
173 
174  logging.info("creating check plots")
175  chain = ROOT.TChain(options.tree)
176  for filename in input_filenames:
177  chain.Add(filename)
178 
179  for old_branch_name, new_branch_name in zip([prefix + 'rawcl_Es%d' % i for i in range(4)], new_branch_names):
180  canvas = ROOT.TCanvas()
181  chain.Draw("layerRecalibratedTree.%s/%s:%scl_eta>>(100, -2.5, 2.5, 100, 0.9, 1.1)" % (new_branch_name, old_branch_name, prefix),
182  "abs(%scl_eta) < 2.5 && %s != 0" % (prefix, old_branch_name), "", options.nevents or 1000000000)
183  canvas.SaveAs("canvas_check_%s.png" % new_branch_name)
runLayerRecalibration.LayerRecalibratedGenerator
def LayerRecalibratedGenerator(input_tree, branches)
Definition: runLayerRecalibration.py:27
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:64
intersection
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Definition: compareFlatTrees.cxx:25
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
fcn
void fcn(int &, double *, double &result, double par[], int)
this is where we write out chi2
Definition: Chi2LJets.cxx:183
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
array
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
runLayerRecalibration.foo_callback
def foo_callback(option, opt, value, parser)
Definition: runLayerRecalibration.py:54
python.KeyStore.list
def list(self, key=None)
Definition: KeyStore.py:318
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28