ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/RootMacros/tree2hists.py
Revision: 1.5
Committed: Wed Jun 2 16:06:43 2010 UTC (14 years, 10 months ago) by anderson
Content type: text/x-python
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +168 -96 lines
Log Message:
many features added

File Contents

# Content
1 #!/usr/bin/env python
2 """
3 Create ROOT Histograms from one or more ROOT TTrees or TNtuples.
4
5 Options are specified in the given configuration file.
6 """
7 ## Created by Michael Anderson (mbanderson@wisc.edu), May 2010
8 #
9 # Create configuration file:
10 # tree2hists.py
11 # Edit, then run with config file:
12 # tree2hists.py config.py
13
14 ######## Import python libraries #############################################
15
16 import sys # For exiting program
17 try:
18 from ROOT import TFile, TTree, TH1F, TH2F, TH3F, gROOT
19 except Exception, e:
20 print e
21 print ("Use a python that has PyROOT installed.")
22 sys.exit(0)
23 from copy import deepcopy # For copying histograms
24 from math import pi # For use in histogram bounds
25 from array import array # For making Float_t array ROOT wants (for hists)
26 from datetime import datetime # For output filename
27 from os import path # For finding file
28
29 ######## Define classes and generators #######################################
30
31 class RootTree:
32 """Wrapper for TTrees and TNtuples, allowing association with
33 a scale and cuts."""
34 def __init__(self, treeName, fileName, scale=1.0, cuts=""):
35 self.fileName = fileName
36 self.treeName = treeName
37 self.scale = scale
38 self.cuts = cuts
39 self.tfile = TFile()
40 self.ttree = TTree()
41
42 class Plot:
43 """Wrapper for TH1 objects, associating TTree variables with a histogram"""
44 def __init__(self, treeVariable, histogram, cuts="", storeErrors=True):
45 self.treeVariable = treeVariable
46 self.histogram = histogram
47 self.name = histogram.GetName()
48 self.cuts = cuts
49 if storeErrors: self.histogram.Sumw2()
50
51 def join_cuts(*list_of_cuts):
52 """Joins list of cuts (strings) into something ROOT can handle.
53 Example: given ('1<2','','5>4') returns '1<2&&5>4'"""
54 list_of_nonempty_cuts = []
55 for cut in list_of_cuts:
56 if cut:
57 list_of_nonempty_cuts.append(cut)
58 return '&&'.join(list_of_nonempty_cuts)
59
60 def duration_to_string(start, end):
61 timeTaken = end - start
62 hours, remainder = divmod(timeTaken.seconds, 3600)
63 minutes, seconds = divmod(remainder, 60)
64 if hours>0:
65 return "%i hours, %i minutes" % (hours, minutes)
66 elif minutes>0:
67 return "%i minutes" % minutes
68 return "%i seconds" % seconds
69
70 def write_default_T2H_config():
71 """Writes configuration file for tree2hists"""
72 defaultConfig = '''# Configuration file for tree2hists.py
73 # Created %s.
74 from tree2hists import RootTree, Plot, array, pi, TH1F
75
76 list_of_files = [RootTree("NTuples/Analysis", fileName="photons.root", scale=1.0, cuts=""),
77 RootTree("NTuples/Analysis", fileName="photons2.root", scale=1.0, cuts="")]
78
79 output_filename = "Hists_photons.root"
80
81 cut_for_all_files = "(!TTBit[36] && !TTBit[37] && !TTBit[38] && !TTBit[39] && !vtxIsFake && vtxNdof>4 && abs(vtxZ)<=15)" + \\
82 "&&((isEB[0] && (seedSeverity[0]!=3 && seedSeverity[0]!=4 ) && (seedRecoFlag[0] != 2) ) || isEE[0])"
83
84 # All plots are made for each "cut set".
85 # A "cut set" is 3 things: folder name to store hists in, string to add to hist titles, and cuts for these hists.
86 # Let cut_sets = [] to make all plots.
87 cut_sets = [
88 ("barrel15to20", "(|#eta|<1.45, 15<E_{T}<20)", "et[0]>15&&et[0]<20&&abs(eta[0])<1.45"),
89 ("barrel20to30", "(|#eta|<1.45, 20<E_{T}<30)", "et[0]>20&&et[0]<30&&abs(eta[0])<1.45"),
90 ("endcap15to20", "(1.7<|#eta|<2.5, 15<E_{T}<20)", "et[0]>15&&et[0]<20&&abs(eta[0])>1.7&&abs(eta[0])<2.5"),
91 ("endcap20to30", "(1.7<|#eta|<2.5, 20<E_{T}<30)", "et[0]>20&&et[0]<30&&abs(eta[0])>1.7&&abs(eta[0])<2.5")
92 ]
93
94 # Define histograms to plot
95 bins_et = array("f", [15.0, 20.0, 30.0, 50.0, 80.0, 120.0])
96 bins_eta = array("f", [-2.5, -1.7, -1.45, 0.0, 1.45, 1.7, 2.5])
97 list_of_plots = [
98 Plot("et[0]" , TH1F("pho_et" , "Lead #gamma: E_{T};E_{T} (GeV);entries/bin", len(bins_et)-1, bins_et)),
99 Plot("eta[0]" , TH1F("pho_eta" , "Lead #gamma: #eta;#eta;entries/bin" , len(bins_eta)-1, bins_eta)),
100 Plot("sigmaIetaIeta[0]", TH1F("pho_sigmaIEtaIEta", "Lead #gamma: #sigma_{i#etai#eta};#sigma_{i#etai#eta};entries/bin",20, 0, 0.06)),
101 Plot("ESRatio[0]" , TH1F("pho_ESRatio" , "Lead #gamma: ESRatio (E3/E21);ESatio;entries/bin", 20, 0, 1.0),"abs(eta[0])>1.65"),
102 Plot("metEt/et[0]" , TH1F("metEt_over_phoEt" , "MET / E_{T}(#gamma);MET/E_{T}(sc);entries/bin" , 20, 0.0, 3.0)),
103 Plot("phi[0]:eta[0]" , TH2F("phoPhi_vs_phoEta" , "Lead #gamma: #phi vs #eta;#eta;#phi" , 50, -2.5, 2.5, 18, -pi, pi))
104 ]
105 ''' % datetime.now().strftime("%b %d, %Y")
106 f = open('t2h_config.py', 'w')
107 f.write(defaultConfig)
108 f.close()
109 print "Created default configuration file: t2h_config.py"
110 print "Edit it, and run with:"
111 print " tree2hists.py t2h_config.py"
112 ##############################################################################
113
114 def make_all_hists_all_files(list_of_RootTrees, list_of_Plots, cut_for_all_files, list_of_cutSets):
115 '''Open root files one at a time, make plots, then close them.'''
116 list_of_plots_to_write = []
117
118 # Create plots for each set of cuts
119 for set_of_cuts in list_of_cutSets:
120 histname_fix, title_fix, current_cut_set = set_of_cuts
121 for plot in list_of_Plots:
122 new_plot = deepcopy(plot)
123 new_title = ' '.join((plot.histogram.GetTitle(), title_fix))
124 new_plot.histogram.SetTitle(new_title)
125 list_of_plots_to_write.append((new_plot, set_of_cuts))
126
127 for j, rootTree in enumerate(list_of_RootTrees):
128 rootTree.tfile = TFile(rootTree.fileName, "read") # Open TFile
129 if rootTree.tfile.IsZombie():
130 print "Error opening %s, exiting..." % rootTree.fileName
131 sys.exit(0)
132 try: # Try to get TTree from file.
133 rootTree.tfile.GetObject(rootTree.treeName, rootTree.ttree)
134 except:
135 print "Error: %s not found in %s, exiting..." % (rootTree.treeName,
136 rootTree.fileName)
137 sys.exit(1)
138
139 print "\n%s: Opened %s %i MB" % (datetime.now().strftime("%I:%M%p"),
140 rootTree.fileName,
141 path.getsize(rootTree.fileName)/1048576)
142 print " %s has %i entries, will plot with scale=%.2e, cuts='%s'" % (rootTree.treeName,
143 rootTree.ttree.GetEntries(),
144 rootTree.scale,
145 rootTree.cuts)
146
147 # Loop over plots
148 print " # entries var >> histogram"
149 for i, (plot, set_of_cuts) in enumerate(list_of_plots_to_write):
150 histname_fix, title_fix, current_cut_set = set_of_cuts
151 tmp_hist = plot.histogram.Clone("temp") # Create temp hist
152 all_cuts = join_cuts(cut_for_all_files, rootTree.cuts,
153 current_cut_set, plot.cuts) # Set cuts
154 rootTree.ttree.Draw( "%s >> temp" % plot.treeVariable, all_cuts,
155 "goff") # Draw with graphics off
156 tmp_hist.Scale(rootTree.scale) # Scale temp
157 entries_before = plot.histogram.GetEntries()
158 plot.histogram.Add(tmp_hist) # Add temp hist to total
159 entries_after = plot.histogram.GetEntries()
160 print " %3i %7i %20s >> %s/%s" % (i, entries_after-entries_before,
161 plot.treeVariable, histname_fix,
162 plot.histogram.GetName()),
163 if plot.cuts:
164 print "\textra cuts: %s" % plot.cuts, # plot-specific cuts
165 print
166
167 rootTree.tfile.Close() # Close TFile
168 print "%s: Closed %s" % (datetime.now().strftime("%I:%M%p"),
169 rootTree.fileName)
170 return list_of_plots_to_write
171
172
173 ######## Define the main program #############################################
174 def tree2hists_main(config_file):
175 try:
176 # Import only certain variables
177 _temp = __import__(config_file, globals(), locals(),
178 ['list_of_files','output_filename',
179 'cut_for_all_files','cut_sets','list_of_plots'], -1)
180 list_of_files = _temp.list_of_files
181 output_filename = _temp.output_filename
182 cut_for_all_files = _temp.cut_for_all_files
183 cut_sets = _temp.cut_sets
184 list_of_plots = _temp.list_of_plots
185 for rootTree in list_of_files:
186 if not path.isfile(rootTree.fileName):
187 print "Error:\n %s\nnot found for input." % rootTree.fileName
188 sys.exit(1)
189 hist_names = [plot.name for plot in list_of_plots]
190 if len(hist_names)>len(set(hist_names)):
191 print hist_names
192 print "Error: Each plot needs a unique name, exiting..."
193 sys.exit(1)
194 if path.isfile(output_filename):
195 print "Warning: %s exists" % output_filename
196 except Exception, e:
197 print e
198 print "Error with %s" % config_file
199 sys.exit(1)
200
201 if path.isfile('rootlogon.C'):
202 print "Loading rootlogon.C"
203 gROOT.Macro('rootlogon.C') # Load functions from rootlogon script
204
205 if cut_sets:
206 print "\n%i defined cut sets:" % len(cut_sets)
207 for cut in cut_sets:
208 name, title_fix, current_cut_set = cut
209 print " %s\t: '%s'" % (name, current_cut_set)
210 cut_names = [name for name,num,cut in cut_sets]
211 if len(cut_names)>len(set(cut_names)):
212 print "Error: Each cut set needs a unique name, exiting..."
213 sys.exit(1)
214 else:
215 cut_sets = [("","","")] # Make all plots, no extra cuts
216
217 print "\nCuts to apply to all files:\n\t'%s'" % cut_for_all_files
218
219 start_time = datetime.now()
220 list_of_plots_to_write = make_all_hists_all_files(list_of_files,
221 list_of_plots,
222 cut_for_all_files,
223 cut_sets)
224 end_time = datetime.now()
225 print "Done drawing all plots after %s." % duration_to_string(start_time, end_time)
226
227 # Store and save/close files
228 outputFile = TFile(output_filename, "recreate")
229 if outputFile.IsZombie():
230 print "Error opening %s for output exiting..." % output_filename
231 sys.exit(1)
232 print "\nOpened output file. Saving histograms..."
233 outputFile.cd()
234 for set_of_cuts in cut_sets:
235 outputFile.mkdir(set_of_cuts[0])
236 print " # entries histogram"
237 for i, (plot, cutset) in enumerate(list_of_plots_to_write):
238 outputFile.cd(cutset[0])
239 print " %3i %7i %s/%s" % (i, plot.histogram.GetEntries(),
240 cutset[0],
241 plot.histogram.GetName())
242 plot.histogram.Write()
243 outputFile.Close()
244 print "Done saving."
245 print "\nScaled & added histograms from %i TTrees saved in\n %s" % (len(list_of_files), output_filename)
246 ##############################################################################
247
248 if __name__ == "__main__":
249 if len(sys.argv) > 1:
250 if path.isfile(sys.argv[1]):
251 config_file = sys.argv[1].split('.')[0]
252 tree2hists_main(config_file)
253 else:
254 print "%s not found." % sys.argv[1]
255 print("Create default config file by running tree2hists.py "
256 "with no argument.")
257 sys.exit(1)
258 else:
259 if path.exists('t2h_config.py'):
260 print "Specify a config file, like:"
261 print "tree2hists.py t2h_config.py"
262 sys.exit(1)
263 write_default_T2H_config()
264 sys.exit(0)
265 #import cProfile
266 #cProfile.run('main()', 'fooprof')
267 #import pstats
268 #p = pstats.Stats('fooprof')
269 #p.sort_stats('cumulative').print_stats(15)