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 |
< |
# Run by typing: |
10 |
< |
# ./tree2hists.py |
11 |
< |
# |
12 |
< |
# Creates histograms from TTree in one or more files. |
13 |
< |
# Different cuts & scales can be set for each file. |
14 |
< |
# |
9 |
< |
# Details are specified in a configruation file, and run with: |
10 |
< |
# ./tree2hists.py config.py |
11 |
< |
# |
12 |
< |
# Michael Anderson |
13 |
< |
# Original: Nov 4, 2009 |
14 |
< |
# Updated: May 20, 2010 |
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 |
|
if sys.version_info < (2, 6): |
18 |
|
print "Go to a CMSSW dir and type 'cmsenv' first. (this loads a modern version of python)" |
19 |
|
sys.exit(0) |
20 |
< |
from ROOT import TFile, TH1F, TH2F, TH3F, TTree, gROOT # Import any ROOT class you want |
21 |
< |
from copy import deepcopy # For copying histograms |
22 |
< |
from math import pi |
23 |
< |
from array import array # For making Float_t array ROOT wants (for hists) |
24 |
< |
from datetime import datetime # For output filename |
25 |
< |
from os import path # For finding file |
20 |
> |
from ROOT import TFile, TTree, TH1F, TH2F, TH3F, gROOT # Import any ROOT class you want |
21 |
> |
from copy import deepcopy # For copying histograms |
22 |
> |
from math import pi # For use in histogram bounds |
23 |
> |
from array import array # For making Float_t array ROOT wants (for hists) |
24 |
> |
from datetime import datetime # For output filename |
25 |
> |
from os import path # For finding file |
26 |
> |
|
27 |
> |
######## Define classes and generators ####################################### |
28 |
|
|
27 |
– |
######################################## |
28 |
– |
# Class for root files to store |
29 |
– |
# file's name, scale, cuts, etc... |
29 |
|
class rootFile: |
30 |
+ |
"""Wrapper for TTrees and TNtuples, allowing association with |
31 |
+ |
a scale and cuts.""" |
32 |
|
def __init__(self, fileName, scale=1.0, cuts="", tree=""): |
33 |
|
self.name = fileName |
34 |
|
self.scale = scale |
46 |
|
sys.exit(0) |
47 |
|
print "\t %s contains %.0f entries before cuts, %.0f after." % (tree, self.ttree.GetEntries(), self.ttree.GetEntries(cuts)) |
48 |
|
|
48 |
– |
# Class to store varibles, histograms to plot them into, and cuts |
49 |
|
class Plot: |
50 |
< |
def __init__(self, treeVariable, histogram, cuts=""): |
50 |
> |
"""Wrapper for TH1 objects, associating TTree variables with a histogram""" |
51 |
> |
def __init__(self, treeVariable, histogram, cuts="", storeErrors=True): |
52 |
|
self.treeVariable = treeVariable |
53 |
|
self.histogram = histogram |
54 |
|
self.cuts = cuts |
55 |
< |
self.histogram.Sumw2() # Store errors |
55 |
> |
if storeErrors: self.histogram.Sumw2() |
56 |
|
|
57 |
< |
# This joins a list of cuts (strings) |
58 |
< |
# into something ROOT can handle |
59 |
< |
# example: given several strings, like "1<2","","5>4" |
59 |
< |
# this returns the sting "1<2&&5>4" |
60 |
< |
def joinNonEmpty(*listOfCuts): |
57 |
> |
def joinCuts(*listOfCuts): |
58 |
> |
"""Joines list of cuts (strings) into something ROOT can handle. |
59 |
> |
Example: given ("1<2","","5>4") returns '1<2&&5>4'""" |
60 |
|
listOfNonEmptyCuts=[] |
61 |
|
for cut in listOfCuts: |
62 |
|
if cut: |
63 |
|
listOfNonEmptyCuts.append(cut) |
64 |
|
return '&&'.join(listOfNonEmptyCuts) |
65 |
|
|
66 |
< |
def writeDefaultConfig(): |
67 |
< |
if path.exists('t2h_config.py'): |
69 |
< |
print "Specify a config file, like:" |
70 |
< |
print "./tree2hists.py t2h_config.py" |
71 |
< |
sys.exit(0) |
66 |
> |
def writeDefaultT2HConfig(): |
67 |
> |
"""Writes configuration file for tree2hists""" |
68 |
|
defaultConfig = '''# Configuration file for tree2hists.py |
69 |
|
# Created %s. |
70 |
|
from tree2hists import * |
71 |
|
|
72 |
< |
listOfFiles = [rootFile("MultiPhotonAnalyzer_SDEG.root", scale=1.0, tree="NTuples/Analysis"), |
73 |
< |
rootFile("MultiPhotonAnalyzer_SD_EG_May7.root", scale=1.0, tree="NTuples/Analysis")] |
72 |
> |
listOfFiles = [rootFile("MultiPhotonAnalyzer_SDEG.root", tree="NTuples/Analysis", scale=1.0, cuts=""), |
73 |
> |
rootFile("MultiPhotonAnalyzer_SD_EG_May7.root", tree="NTuples/Analysis", scale=1.0 cuts="")] |
74 |
|
|
75 |
|
outputFilename = "Hists_Data_%%s.root" %% datetime.now().strftime("%%b%%d_%%I%%p") |
76 |
|
|
78 |
|
"&&((isEB[0] && (seedSeverity[0]!=3 && seedSeverity[0]!=4 ) && (seedRecoFlag[0] != 2) ) || isEE[0])" |
79 |
|
|
80 |
|
# All plots are made for each "cutSet". |
81 |
< |
# A cut set is 3 things: folder name to store hists in, string to add to hist titles, and actual cuts |
82 |
< |
cutSets = ( |
81 |
> |
# A "cutSet" is 3 things: folder name to store hists in, string to add to hist titles, and cuts for these hists. |
82 |
> |
# Set cutSet = [] to make all plots. |
83 |
> |
cutSets = [ |
84 |
|
("barrel15to20", "(|#eta|<1.45, 15<E_{T}<20)", "et[0]>15&&et[0]<20&&abs(eta[0])<1.45"), |
85 |
|
("barrel20to30", "(|#eta|<1.45, 20<E_{T}<30)", "et[0]>20&&et[0]<30&&abs(eta[0])<1.45"), |
86 |
|
("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"), |
87 |
|
("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") |
88 |
< |
# ("","",""), # all plots with no special cuts |
92 |
< |
) |
88 |
> |
] |
89 |
|
|
90 |
|
# Define histograms to plot |
91 |
|
bins_et = array("f", [15.0, 20.0, 30.0, 50.0, 80.0, 120.0]) |
104 |
|
f.close() |
105 |
|
print "Created default configuration file: t2h_config.py" |
106 |
|
print "Edit it, and run with:" |
107 |
< |
print " tree2hists t2h_config.py" |
107 |
> |
print " tree2hists.py t2h_config.py" |
108 |
|
######################################## |
109 |
|
|
110 |
|
|
111 |
< |
######################################## |
112 |
< |
if __name__ == '__main__': |
113 |
< |
if len(sys.argv) > 1: |
114 |
< |
if path.isfile(sys.argv[1]): |
115 |
< |
config_file = sys.argv[1].split('.')[0] |
116 |
< |
try: |
117 |
< |
exec("from " + config_file + " import *") |
118 |
< |
except Exception, e: |
119 |
< |
print e |
120 |
< |
sys.exit(1) |
121 |
< |
else: |
122 |
< |
print "%s not found." % sys.argv[1] |
123 |
< |
print "Create default config file by running tree2hists.py with no argument." |
124 |
< |
sys.exit(1) |
129 |
< |
else: |
130 |
< |
writeDefaultConfig() |
131 |
< |
sys.exit(0) |
111 |
> |
######## Define the main program ############################################# |
112 |
> |
def tree2hists_main(config_file): |
113 |
> |
try: |
114 |
> |
# Import only certain variables |
115 |
> |
_temp = __import__(config_file, globals(), locals(), ['listOfFiles','outputFilename','cutForAllFiles','cutSets','listOfPlots'], -1) |
116 |
> |
listOfFiles = _temp.listOfFiles |
117 |
> |
outputFilename = _temp.outputFilename |
118 |
> |
cutForAllFiles = _temp.cutForAllFiles |
119 |
> |
cutSets = _temp.cutSets |
120 |
> |
listOfPlots = _temp.listOfPlots |
121 |
> |
if not cutSets: cutSets = [("","","")] # Make all plots, no extra cuts |
122 |
> |
except Exception, e: |
123 |
> |
print e |
124 |
> |
sys.exit(1) |
125 |
|
|
126 |
|
if path.isfile('rootlogon.C'): |
127 |
|
print "Loading rootlogon.C" |
128 |
< |
gROOT.Macro('rootlogon.C') # Run ROOT logon script |
128 |
> |
gROOT.Macro('rootlogon.C') # Run ROOT logon script (for loading of functions) |
129 |
|
|
130 |
< |
outputFile = TFile(outputFilename, "recreate") # Open output file |
130 |
> |
outputFile = TFile(outputFilename, "recreate") |
131 |
|
if not outputFile.IsZombie(): |
132 |
|
print "Opened %s for output." % outputFilename |
133 |
|
else: |
139 |
|
print "\nCuts applied to all plots from all files:\n %s" % cutForAllFiles |
140 |
|
numberOfPlots = len(listOfPlots) |
141 |
|
print "\nCreating %i plots for each of %i cut sets..." % (numberOfPlots, len(cutSets)) |
142 |
< |
for setOfCuts in cutSets: |
142 |
> |
for setOfCuts in cutSets: # Make all plots for each cutSet |
143 |
|
histNamePostfix, titlePostfix, currentCutSet = setOfCuts |
144 |
|
print '\n Cut set "%s": %s' % (histNamePostfix, currentCutSet) |
145 |
< |
# Loop over all things to plot |
153 |
< |
for i, plot in enumerate(listOfPlots): |
145 |
> |
for i, plot in enumerate(listOfPlots): # Loop over plots |
146 |
|
newTitle = ' '.join((plot.histogram.GetTitle(), titlePostfix)) |
147 |
|
newPlot = deepcopy(plot) |
148 |
|
dir = histNamePostfix |
149 |
|
listOfPlotsToWrite.append((dir, newPlot)) |
150 |
|
newPlot.histogram.SetTitle(newTitle) |
151 |
< |
# Print plot being made |
152 |
< |
print " %i %s >> %s/%s" % (i, newPlot.treeVariable, dir, newPlot.histogram.GetName()), |
151 |
> |
for aFile in listOfFiles: # Loop over all TTrees |
152 |
> |
tempHist = newPlot.histogram.Clone("temp") # Create temp histogram |
153 |
> |
cuts = joinCuts(cutForAllFiles, aFile.cuts, currentCutSet, newPlot.cuts) # Set cuts for temp |
154 |
> |
aFile.ttree.Draw( "%s >> temp" % newPlot.treeVariable, cuts, "goff") # Draw into temp; graphics off |
155 |
> |
tempHist.Scale(aFile.scale) # Scale temp |
156 |
> |
newPlot.histogram.Add(tempHist) # Add temp to total histogram |
157 |
> |
print " %3i %7i %s >> %s/%s" % (i, newPlot.histogram.GetEntries(), newPlot.treeVariable, dir, newPlot.histogram.GetName()), |
158 |
|
if newPlot.cuts: |
159 |
< |
print "\textra cuts: %s" % newPlot.cuts, # Plot-specific cuts |
160 |
< |
# Loop over all TTrees (from the different files) |
164 |
< |
for aFile in listOfFiles: |
165 |
< |
tempHist = newPlot.histogram.Clone("temp") # Create temp histogram |
166 |
< |
cuts = joinNonEmpty(cutForAllFiles, aFile.cuts, currentCutSet, newPlot.cuts) # Set cuts for temp |
167 |
< |
aFile.ttree.Draw( "%s >> temp" % newPlot.treeVariable, cuts, "goff") # Draw into temp; graphics off |
168 |
< |
tempHist.Scale(aFile.scale) # Scale temp |
169 |
< |
newPlot.histogram.Add(tempHist) # Add temp to total histogram |
170 |
< |
print "%i" % newPlot.histogram.GetEntries() |
159 |
> |
print "\textra cuts: %s" % newPlot.cuts, # plot-specific cuts |
160 |
> |
print |
161 |
|
print "done." |
162 |
|
|
163 |
|
# Store and save/close files |
168 |
|
outputFile.cd(dir) |
169 |
|
plot.histogram.Write() |
170 |
|
|
181 |
– |
print "Closing files...", |
171 |
|
outputFile.Close() |
172 |
|
for aFile in listOfFiles: |
173 |
|
aFile.file.Close() |
174 |
< |
print "done.\n\nHistograms stored in\n %s" % outputFilename |
174 |
> |
print "\n\nHistograms stored in\n %s" % outputFilename |
175 |
|
######################################## |
176 |
+ |
|
177 |
+ |
if __name__ == "__main__": |
178 |
+ |
if len(sys.argv) > 1: |
179 |
+ |
if path.isfile(sys.argv[1]): |
180 |
+ |
config_file = sys.argv[1].split('.')[0] |
181 |
+ |
tree2hists_main(config_file) |
182 |
+ |
else: |
183 |
+ |
print "%s not found." % sys.argv[1] |
184 |
+ |
print "Create default config file by running tree2hists.py with no argument." |
185 |
+ |
sys.exit(1) |
186 |
+ |
else: |
187 |
+ |
if path.exists('t2h_config.py'): |
188 |
+ |
print "Specify a config file, like:" |
189 |
+ |
print "tree2hists.py t2h_config.py" |
190 |
+ |
sys.exit(1) |
191 |
+ |
writeDefaultT2HConfig() |
192 |
+ |
sys.exit(0) |
193 |
+ |
#import cProfile |
194 |
+ |
#cProfile.run('main()', 'fooprof') |
195 |
+ |
#import pstats |
196 |
+ |
#p = pstats.Stats('fooprof') |
197 |
+ |
#p.sort_stats('cumulative').print_stats(15) |