ATLAS Offline Software
Loading...
Searching...
No Matches
ChangeHistoRange.py
Go to the documentation of this file.
1# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
2
3import sys
4import re
5import array
6from math import fabs
7from ROOT import *
8
9def GetKeyNames(self,dir=""):
10 self.cd(dir)
11 return [key.GetName() for key in gDirectory.GetListOfKeys()]
12TFile.GetKeyNames = GetKeyNames
13
14if len(sys.argv) < 7:
15 print "Too few arguments. Expected the following:"
16 print " 1. Input file"
17 print " 2. Output file"
18 print " 3. Name of histogram to modify"
19 print " 4. Axis (x, y, or z)"
20 print " 5. New lower value, -999 to leave unchanged"
21 print " 6. New upper value, -999 to leave unchanged"
22 sys.exit(1)
23
24# Arguments
25inFile = TFile.Open(sys.argv[1],"READ")
26outFile = TFile.Open(sys.argv[2],"RECREATE")
27histName = sys.argv[3]
28axis = sys.argv[4]
29lowBound = float(sys.argv[5])
30highBound = float(sys.argv[6])
31changeLow = not (fabs(lowBound+999) < 1.e-4)
32changeHigh = not (fabs(highBound+999) < 1.e-4)
33
34# Sanity checks
35if histName not in inFile.GetKeyNames():
36 print "The requested histogram is not in the input file:",histName
37 sys.exit(2)
38if axis not in ["x","y","z","X","Y","Z"]:
39 print "Axis is not x, y, or z:",axis
40 sys.exit(2)
41if (not changeLow) and (not changeHigh):
42 print "Requesting to change neither the low or high boundary, nothing to do"
43 sys.exit(2)
44if changeLow and changeHigh and lowBound > highBound:
45 print "Requesting a new lower boundary that is below the upper boundary"
46 sys.exit(2)
47
48# Write histograms, changing the one requested
49for aHist in inFile.GetKeyNames():
50 hist = inFile.Get(aHist)
51 if aHist != histName:
52 outFile.cd()
53 hist.Write(aHist)
54 else:
55 # Build the histogram bins
56 binsX = []
57 for xBin in range(1,hist.GetNbinsX()+2):
58 binsX.append(hist.GetXaxis().GetBinLowEdge(xBin))
59 binsY = []
60 if hist.GetDimension() > 1:
61 for yBin in range(1,hist.GetNbinsY()+2):
62 binsY.append(hist.GetYaxis().GetBinLowEdge(yBin))
63 binsZ = []
64 if hist.GetDimension() > 2:
65 for zBin in range(1,hist.GetNbinsZ()+2):
66 binsZ.append(hist.GetZaxis().GetBinLowEdge(zBin))
67
68 # Check which one we are changing
69 refBins = None
70 if axis == "x" or axis == "X":
71 refBins = binsX
72 elif axis == "y" or axis == "Y":
73 if hist.GetDimension() > 1:
74 refBins = binsY
75 else:
76 print "Requested y axis for a 1D histogram"
77 sys.exit(3)
78 elif axis == "z" or axis == "Z":
79 if hist.GetDimension() > 2:
80 refBins = binsZ
81 else:
82 print "Requested z axis for a 1D or 2D histogram"
83 sys.exit(3)
84 else:
85 print "Couldn't interpret axis request:",axis
86 sys.exit(3)
87
88 # Modify bins as needed
89 newBins = []
90 if changeLow and lowBound > refBins[-1]:
91 print "New low bin is above the upper bound of the histogram"
92 sys.exit(4)
93 if changeHigh and highBound < refBins[0]:
94 print "New high bin is below the lower bound of the histogram"
95 sys.exit(4)
96 if changeLow:
97 newBins.append(lowBound)
98 for aBin in refBins:
99 if changeLow and fabs(aBin-lowBound) < 1.e-4:
100 continue # Added before
101 elif changeLow and aBin < lowBound:
102 continue
103 elif changeHigh and fabs(aBin-highBound) < 1.e-4:
104 continue # Adding after
105 elif changeHigh and aBin > highBound:
106 continue
107 newBins.append(aBin)
108 if changeHigh:
109 newBins.append(highBound)
110
111 # Map old bins to new bins
112 # Very stupid brute force due to time constraints
113 binPairs = []
114 for aBin,aBinI in zip(refBins,range(1,len(refBins)+1)):
115 for newBin,newBinI in zip(newBins,range(1,len(newBins)+1)):
116 if fabs(aBin-newBin)<1.e-4:
117 binPairs.append([aBinI,newBinI])
118 if changeLow and binPairs[0][1] != 1:
119 if newBins[0] < refBins[0]:
120 binPairs.insert(0,[1,1]) # hold fixed to new bins
121 else:
122 binPairs.insert(0,[binPairs[0][0]-1,binPairs[0][1]-1])
123 if changeHigh and binPairs[0][-1] != len(binPairs):
124 if newBins[-1] > refBins[-1]:
125 binPairs.append([len(refBins),len(newBins)]) # hold fixed to new bins
126 else:
127 binPairs.append([binPairs[-1][0]+1,binPairs[-1][1]+1])
128 if len(binPairs) != len(newBins):
129 print "Error: mismatched numbers of bins and bin pairs"
130 sys.exit(5)
131
132
133 # Make the histogram
134 # Doing this brute-force for now...
135 newHist = None
136 if hist.GetDimension() == 1:
137 if isinstance(hist,TH1F):
138 newHist = TH1F(histName+"_mod",hist.GetTitle(),len(newBins)-1,array.array('f',newBins))
139 elif isinstance(hist,TH1D):
140 newHist = TH1D(histName+"_mod",hist.GetTitle(),len(newBins)-1,array.array('d',newBins))
141 else:
142 print "Unsupported type of 1D histogram"
143 sys.exit(5)
144 elif hist.GetDimension() == 2:
145 if isinstance(hist,TH2F):
146 if axis == "x" or axis == "X":
147 newHist = TH2F(histName+"_mod",hist.GetTitle(),len(newBins)-1,array.array('f',newBins),len(binsY)-1,array.array('f',binsY))
148 elif axis == "y" or axis == "Y":
149 newHist = TH2F(histName+"_mod",hist.GetTitle(),len(binsX)-1,array.array('f',binsX),len(newBins)-1,array.array('f',newBins))
150 elif isinstance(hist,TH2D):
151 if axis == "x" or axis == "X":
152 newHist = TH2D(histName+"_mod",hist.GetTitle(),len(newBins)-1,array.array('d',newBins),len(binsY)-1,array.array('d',binsY))
153 elif axis == "y" or axis == "Y":
154 newHist = TH2D(histName+"_mod",hist.GetTitle(),len(binsX)-1,array.array('d',binsX),len(newBins)-1,array.array('d',newBins))
155 else:
156 print "Unsupported type of 2D histogram"
157 sys.exit(5)
158 elif hist.GetDimension() == 3:
159 if isinstance(hist,TH3F):
160 if axis == "x" or axis == "X":
161 newHist = TH3F(histName+"_mod",hist.GetTitle(),len(newBins)-1,array.array('f',newBins),len(binsY)-1,array.array('f',binsY),len(binsZ)-1,array.array('f',binsZ))
162 elif axis == "y" or axis == "Y":
163 newHist = TH3F(histName+"_mod",hist.GetTitle(),len(binsX)-1,array.array('f',binsX),len(newBins)-1,array.array('f',newBins),len(binsZ)-1,array.array('f',binsZ))
164 elif axis == "z" or axis == "Z":
165 newHist = TH3F(histName+"_mod",hist.GetTitle(),len(binsX)-1,array.array('f',binsX),len(binsY)-1,array.array('f',binsY),len(newBins)-1,array.array('f',newBins))
166 elif isinstance(hist,TH3D):
167 if axis == "x" or axis == "X":
168 newHist = TH3D(histName+"_mod",hist.GetTitle(),len(newBins)-1,array.array('d',newBins),len(binsY)-1,array.array('d',binsY),len(binsZ)-1,array.array('d',binsZ))
169 elif axis == "y" or axis == "Y":
170 newHist = TH3D(histName+"_mod",hist.GetTitle(),len(binsX)-1,array.array('d',binsX),len(newBins)-1,array.array('d',newBins),len(binsZ)-1,array.array('d',binsZ))
171 elif axis == "z" or axis == "Z":
172 newHist = TH3D(histName+"_mod",hist.GetTitle(),len(binsX)-1,array.array('d',binsX),len(binsY)-1,array.array('d',binsY),len(newBins)-1,array.array('d',newBins))
173 else:
174 print "Unsupported type of 3D histogram"
175 sys.exit(5)
176 else:
177 print "Unsupported histogram dimensionality"
178 sys.exit(5)
179
180 # Now we have the histogram, let's fill it
181 # Done this way now as it runs faster (although less compact for humans...)
182 if hist.GetDimension() == 1:
183 for oldBin,newBin in binPairs:
184 newHist.SetBinContent(newBin,hist.GetBinContent(oldBin))
185 newHist.SetBinError(newBin,hist.GetBinError(oldBin))
186 if hist.GetDimension() == 2:
187 if axis == "x" or axis == "X":
188 for oldBin,newBin in binPairs:
189 for yBin in range(1,hist.GetNbinsY()+1):
190 newHist.SetBinContent(newBin,yBin,hist.GetBinContent(oldBin,yBin))
191 newHist.SetBinError(newBin,yBin,hist.GetBinError(oldBin,yBin))
192 else:
193 for xBin in range(1,hist.GetNbinsX()+1):
194 for oldBin,newBin in binPairs:
195 newHist.SetBinContent(xBin,newBin,hist.GetBinContent(xBin,oldBin))
196 newHist.SetBinError(xBin,newBin,hist.GetBinError(xBin,oldBin))
197 if hist.GetDimension() == 3:
198 if axis == "x" or axis == "X":
199 for oldBin,newBin in binPairs:
200 for yBin in range(1,hist.GetNbinsY()+1):
201 for zBin in range(1,hist.GetNbinsZ()+1):
202 newHist.SetBinContent(newBin,yBin,zBin,hist.GetBinContent(oldBin,yBin,zBin))
203 newHist.SetBinError(newBin,yBin,zBin,hist.GetBinError(oldBin,yBin,zBin))
204 elif axis == "y" or axis == "Y":
205 for xBin in range(1,hist.GetNbinsX()+1):
206 for oldBin,newBin in binPairs:
207 for zBin in range(1,hist.GetNbinsZ()+1):
208 newHist.SetBinContent(xBin,newBin,zBin,hist.GetBinContent(xBin,oldBin,zBin))
209 newHist.SetBinError(xBin,newBin,zBin,hist.GetBinError(xBin,oldBin,zBin))
210 else:
211 for xBin in range(1,hist.GetNbinsX()+1):
212 for yBin in range(1,hist.GetNbinsY()+1):
213 for oldBin,newBin in binPairs:
214 newHist.SetBinContent(xBin,yBin,newBin,hist.GetBinContent(xBin,yBin,oldBin))
215 newHist.SetBinError(xBin,yBin,newBin,hist.GetBinError(xBin,yBin,oldBin))
216
217 # Filled histogram, finally
218 # Write it out with the old name
219 outFile.cd()
220 newHist.Write(histName)
221
222
223
224outFile.Close()
225inFile.Close()
226
227