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, 11 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

# User Rev Content
1 anderson 1.1 #!/usr/bin/env python
2 anderson 1.4 """
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 anderson 1.1 #
9 anderson 1.4 # Create configuration file:
10     # tree2hists.py
11     # Edit, then run with config file:
12     # tree2hists.py config.py
13    
14     ######## Import python libraries #############################################
15 anderson 1.1
16 anderson 1.2 import sys # For exiting program
17 anderson 1.5 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 anderson 1.2 sys.exit(0)
23 anderson 1.5 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 anderson 1.4
29     ######## Define classes and generators #######################################
30 anderson 1.1
31 anderson 1.5 class RootTree:
32 anderson 1.4 """Wrapper for TTrees and TNtuples, allowing association with
33     a scale and cuts."""
34 anderson 1.5 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 anderson 1.1
42     class Plot:
43 anderson 1.4 """Wrapper for TH1 objects, associating TTree variables with a histogram"""
44     def __init__(self, treeVariable, histogram, cuts="", storeErrors=True):
45 anderson 1.1 self.treeVariable = treeVariable
46 anderson 1.5 self.histogram = histogram
47     self.name = histogram.GetName()
48     self.cuts = cuts
49 anderson 1.4 if storeErrors: self.histogram.Sumw2()
50 anderson 1.1
51 anderson 1.5 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 anderson 1.1 if cut:
57 anderson 1.5 list_of_nonempty_cuts.append(cut)
58     return '&&'.join(list_of_nonempty_cuts)
59 anderson 1.1
60 anderson 1.5 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 anderson 1.4 """Writes configuration file for tree2hists"""
72 anderson 1.3 defaultConfig = '''# Configuration file for tree2hists.py
73 anderson 1.1 # Created %s.
74 anderson 1.5 from tree2hists import RootTree, Plot, array, pi, TH1F
75 anderson 1.1
76 anderson 1.5 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 anderson 1.1
79 anderson 1.5 output_filename = "Hists_photons.root"
80 anderson 1.1
81 anderson 1.5 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 anderson 1.1
84 anderson 1.5 # 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 anderson 1.1 ("barrel15to20", "(|#eta|<1.45, 15<E_{T}<20)", "et[0]>15&&et[0]<20&&abs(eta[0])<1.45"),
89 anderson 1.2 ("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 anderson 1.4 ]
93 anderson 1.1
94     # Define histograms to plot
95 anderson 1.3 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 anderson 1.5 list_of_plots = [
98 anderson 1.3 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 anderson 1.1 ]
105 anderson 1.3 ''' % datetime.now().strftime("%b %d, %Y")
106 anderson 1.2 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 anderson 1.4 print " tree2hists.py t2h_config.py"
112 anderson 1.5 ##############################################################################
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 anderson 1.1
172    
173 anderson 1.4 ######## Define the main program #############################################
174     def tree2hists_main(config_file):
175     try:
176     # Import only certain variables
177 anderson 1.5 _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 anderson 1.4 except Exception, e:
197     print e
198 anderson 1.5 print "Error with %s" % config_file
199 anderson 1.4 sys.exit(1)
200 anderson 1.1
201 anderson 1.2 if path.isfile('rootlogon.C'):
202 anderson 1.1 print "Loading rootlogon.C"
203 anderson 1.5 gROOT.Macro('rootlogon.C') # Load functions from rootlogon script
204 anderson 1.1
205 anderson 1.5 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 anderson 1.1 else:
215 anderson 1.5 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 anderson 1.1
219 anderson 1.5 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 anderson 1.1
227     # Store and save/close files
228 anderson 1.5 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 anderson 1.1 outputFile.cd()
234 anderson 1.5 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 anderson 1.1 plot.histogram.Write()
243     outputFile.Close()
244 anderson 1.5 print "Done saving."
245     print "\nScaled & added histograms from %i TTrees saved in\n %s" % (len(list_of_files), output_filename)
246     ##############################################################################
247 anderson 1.4
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 anderson 1.5 print("Create default config file by running tree2hists.py "
256     "with no argument.")
257 anderson 1.4 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 anderson 1.5 write_default_T2H_config()
264 anderson 1.4 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)