3 Create ROOT Histograms from one or more ROOT TTrees or TNtuples.
5 Options are specified in the given configuration file.
14 Copyright (c) 2010 Michael Anderson <mbanderson@wisc.edu>
16 Permission is hereby granted, free of charge, to any person obtaining a copy
17 of this software and associated documentation files (the "Software"), to deal
18 in the Software without restriction, including without limitation the rights
19 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20 copies of the Software, and to permit persons to whom the Software is
21 furnished to do so, subject to the following conditions:
23 The above copyright notice and this permission notice shall be included in
24 all copies or substantial portions of the Software.
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38 if '-h' in sys.argv
or '--help' in sys.argv:
40 Create ROOT Histograms from one or more ROOT TTrees or TNtuples.
42 Run by specifying configuration file:
45 Create default config file by running with no arguments:
49 from ROOT
import TFile, TTree, TH1F, TH2F, TH3F, gROOT
52 print (
"Use a python that has PyROOT installed.")
54 from copy
import deepcopy
56 from array
import array
57 from datetime
import datetime
63 """Wrapper for TTrees and TNtuples, allowing association with
65 def __init__(self, treeName, fileName, scale=1.0, cuts=""):
74 """Wrapper for TH1 objects, associating TTree variables with a histogram"""
75 def __init__(self, treeVariable, histogram, cuts="", storeErrors=True):
78 self.
name = histogram.GetName()
80 if storeErrors: self.histogram.Sumw2()
83 """Joins list of cuts (strings) into something ROOT can handle.
84 Example: given ('1<2','','5>4') returns '1<2&&5>4'"""
85 list_of_nonempty_cuts = []
86 for cut
in list_of_cuts:
88 list_of_nonempty_cuts.append(cut)
89 return '&&'.
join(list_of_nonempty_cuts)
92 timeTaken = end - start
93 hours, remainder = divmod(timeTaken.seconds, 3600)
94 minutes, seconds = divmod(remainder, 60)
96 return "%i hours, %i minutes" % (hours, minutes)
98 return "%i minutes" % minutes
99 return "%i seconds" % seconds
102 """Writes configuration file for tree2hists"""
103 defaultConfig =
'''# Configuration file for tree2hists
106 ## the normal way to import from rootplot
107 from rootplot.tree2hists import RootTree, Plot
109 ## special import for CMSSW installations of rootplot
110 from PhysicsTools.PythonAnalysis.rootplot.tree2hists import RootTree, Plot
111 from array import array # to allow making Float_t arrays for ROOT hists
113 from ROOT import TH1F, TH2F # import other kinds of hists as neeeded
115 list_of_files = [RootTree("Treename", fileName="photons.root", scale=1.0, cuts=""),
116 RootTree("Treename", fileName="photons2.root", scale=1.0, cuts="")]
118 output_filename = "Hists_photons.root"
120 cut_for_all_files = "(!TTBit[36] && !TTBit[37] && !TTBit[38] && !TTBit[39] && !vtxIsFake && vtxNdof>4 && abs(vtxZ)<=15)"
122 # All plots are made for each "cut set".
123 # A "cut set" is 3 things: folder name to store hists in, string to add to hist titles, and cuts for these hists.
124 # Let cut_sets = [] to make all plots.
126 ("barrel15to20", "(|#eta|<1.45, 15<E_{T}<20)", "et>15&&et<20&&abs(eta)<1.45"),
127 ("barrel20to30", "(|#eta|<1.45, 20<E_{T}<30)", "et>20&&et<30&&abs(eta)<1.45"),
128 ("endcap15to20", "(1.7<|#eta|<2.5, 15<E_{T}<20)", "et>15&&et<20&&abs(eta)>1.7&&abs(eta)<2.5"),
129 ("endcap20to30", "(1.7<|#eta|<2.5, 20<E_{T}<30)", "et>20&&et<30&&abs(eta)>1.7&&abs(eta)<2.5")
132 # Define histograms to plot
133 bins_et = array("f", [15.0, 20.0, 30.0, 50.0, 80.0, 120.0]) # example custom bins
135 Plot("et" , TH1F("pho_et" , "Lead #gamma: E_{T};E_{T} (GeV);entries/bin", 25, 0.0, 100.0)),
136 Plot("eta" , TH1F("pho_eta" , "Lead #gamma: #eta;#eta;entries/bin" , 25, -3.0, 3.0)),
137 Plot("et" , TH1F("pho_et_binned" , "Lead #gamma: E_{T};E_{T} (GeV);entries/bin", len(bins_et)-1, bins_et)),
138 Plot("sigmaIetaIeta", TH1F("pho_sigmaIEtaIEta", "Lead #gamma: #sigma_{i#etai#eta};#sigma_{i#etai#eta};entries/bin",20, 0, 0.06)),
139 Plot("metEt/et" , TH1F("metEt_over_phoEt" , "MET / E_{T}(#gamma);MET/E_{T}(sc);entries/bin" , 20, 0.0, 3.0)),
140 Plot("phi:eta" , TH2F("phoPhi_vs_phoEta" , "Lead #gamma: #phi vs #eta;#eta;#phi" , 50, -2.5, 2.5, 18, -pi, pi))
142 ''' % datetime.now().strftime(
"%b %d, %Y")
143 f = open(
't2h_config.py',
'w')
144 f.write(defaultConfig)
146 print "Created default configuration file: t2h_config.py"
147 print "Edit it, then run by typing:"
148 print " tree2hists t2h_config.py"
152 '''Open root files one at a time, make plots, then close them.'''
153 list_of_plots_to_write = []
156 for set_of_cuts
in list_of_cutSets:
157 histname_fix, title_fix, current_cut_set = set_of_cuts
158 for plot
in list_of_Plots:
159 new_plot = deepcopy(plot)
160 new_title =
' '.
join((plot.histogram.GetTitle(), title_fix))
161 new_plot.histogram.SetTitle(new_title)
162 list_of_plots_to_write.append((new_plot, set_of_cuts))
164 for j, rootTree
in enumerate(list_of_RootTrees):
165 rootTree.tfile = TFile(rootTree.fileName,
"read")
166 if rootTree.tfile.IsZombie():
167 print "Error opening %s, exiting..." % rootTree.fileName
170 rootTree.tfile.GetObject(rootTree.treeName, rootTree.ttree)
172 print "Error: %s not found in %s, exiting..." % (rootTree.treeName,
176 print "\n%s: Opened %s %i MB" % (datetime.now().strftime(
"%I:%M%p"),
178 path.getsize(rootTree.fileName)/1048576)
179 print " %s has %i entries, will plot with scale=%.2e, cuts='%s'" % (rootTree.treeName,
180 rootTree.ttree.GetEntries(),
185 print " # entries var >> histogram"
186 for i, (plot, set_of_cuts)
in enumerate(list_of_plots_to_write):
187 histname_fix, title_fix, current_cut_set = set_of_cuts
188 tmp_hist = plot.histogram.Clone(
"temp")
189 all_cuts =
join_cuts(cut_for_all_files, rootTree.cuts,
190 current_cut_set, plot.cuts)
191 rootTree.ttree.Draw(
"%s >> temp" % plot.treeVariable, all_cuts,
193 tmp_hist.Scale(rootTree.scale)
194 entries_before = plot.histogram.GetEntries()
195 plot.histogram.Add(tmp_hist)
196 entries_after = plot.histogram.GetEntries()
197 print " %3i %7i %20s >> %s/%s" % (i, entries_after-entries_before,
198 plot.treeVariable, histname_fix,
199 plot.histogram.GetName()),
201 print "\textra cuts: %s" % plot.cuts,
204 rootTree.tfile.Close()
205 print "%s: Closed %s" % (datetime.now().strftime(
"%I:%M%p"),
207 return list_of_plots_to_write
214 sys.path.insert(0,
'')
215 _temp = __import__(config_file, globals(), locals(),
216 [
'list_of_files',
'output_filename',
217 'cut_for_all_files',
'cut_sets',
'list_of_plots'], -1)
218 list_of_files = _temp.list_of_files
219 output_filename = _temp.output_filename
220 cut_for_all_files = _temp.cut_for_all_files
221 cut_sets = _temp.cut_sets
222 list_of_plots = _temp.list_of_plots
223 for rootTree
in list_of_files:
224 if not path.isfile(rootTree.fileName):
225 print "Error:\n %s\nnot found for input." % rootTree.fileName
227 hist_names = [plot.name
for plot
in list_of_plots]
228 if len(hist_names)>len(
set(hist_names)):
230 print "Error: Each plot needs a unique name, exiting..."
232 if path.isfile(output_filename):
233 print "Warning: %s exists" % output_filename
236 print "Error with %s" % config_file
239 if path.isfile(
'rootlogon.C'):
240 print "Loading rootlogon.C"
241 gROOT.Macro(
'rootlogon.C')
244 print "\n%i defined cut sets:" % len(cut_sets)
246 name, title_fix, current_cut_set = cut
247 print " %s\t: '%s'" % (name, current_cut_set)
248 cut_names = [name
for name,num,cut
in cut_sets]
249 if len(cut_names)>len(
set(cut_names)):
250 print "Error: Each cut set needs a unique name, exiting..."
253 cut_sets = [(
"",
"",
"")]
255 print "\nCuts to apply to all files:\n\t'%s'" % cut_for_all_files
257 start_time = datetime.now()
262 end_time = datetime.now()
266 outputFile = TFile(output_filename,
"recreate")
267 if outputFile.IsZombie():
268 print "Error opening %s for output exiting..." % output_filename
270 print "\nOpened output file. Saving histograms..."
272 for set_of_cuts
in cut_sets:
273 outputFile.mkdir(set_of_cuts[0])
274 print " # entries histogram"
275 for i, (plot, cutset)
in enumerate(list_of_plots_to_write):
276 outputFile.cd(cutset[0])
277 print " %3i %7i %s/%s" % (i, plot.histogram.GetEntries(),
279 plot.histogram.GetName())
280 plot.histogram.Write()
283 print "\nScaled & added histograms from %i TTrees saved in\n %s" % (len(list_of_files), output_filename)
287 if len(sys.argv) > 1:
288 if path.isfile(sys.argv[1]):
289 config_file = sys.argv[1].
split(
'.')[0]
292 print "%s not found." % sys.argv[1]
293 print(
"Create default config file by running tree2hists "
297 if path.exists(
't2h_config.py'):
298 print "Run with specific config file, like:"
299 print " tree2hists t2h_config.py"
304 if __name__ ==
"__main__":
std::string print(const Track &, edm::Verbosity=edm::Concise)
Track print utility.
def make_all_hists_all_files
static std::string join(char **cmd)
def tree2hists_main
Define the main program #############################################.
Define classes and generators #######################################.
def write_default_T2H_config
void set(const std::string &name, int value)
set the flag, with a run-time name