ATLAS Offline Software
ChangeHistoRange.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
2 
3 import sys
4 import re
5 import array
6 from math import fabs
7 from ROOT import *
8 
9 def GetKeyNames(self,dir=""):
10  self.cd(dir)
11  return [key.GetName() for key in gDirectory.GetListOfKeys()]
12 TFile.GetKeyNames = GetKeyNames
13 
14 if 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
25 inFile = TFile.Open(sys.argv[1],"READ")
26 outFile = TFile.Open(sys.argv[2],"RECREATE")
27 histName = sys.argv[3]
28 axis = sys.argv[4]
29 lowBound = float(sys.argv[5])
30 highBound = float(sys.argv[6])
31 changeLow = not (fabs(lowBound+999) < 1.e-4)
32 changeHigh = not (fabs(highBound+999) < 1.e-4)
33 
34 # Sanity checks
35 if histName not in inFile.GetKeyNames():
36  print "The requested histogram is not in the input file:",histName
37  sys.exit(2)
38 if axis not in ["x","y","z","X","Y","Z"]:
39  print "Axis is not x, y, or z:",axis
40  sys.exit(2)
41 if (not changeLow) and (not changeHigh):
42  print "Requesting to change neither the low or high boundary, nothing to do"
43  sys.exit(2)
44 if 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
49 for 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 
224 outFile.Close()
225 inFile.Close()
226 
227 
TH3D
Definition: rootspy.cxx:505
TH2F
Definition: rootspy.cxx:420
ChangeHistoRange.GetKeyNames
def GetKeyNames(self, dir="")
Definition: ChangeHistoRange.py:9
TH1D
Definition: rootspy.cxx:342
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
TH2D
Definition: rootspy.cxx:430
TH3F
Definition: rootspy.cxx:495
TH1F
Definition: rootspy.cxx:320
readCCLHist.float
float
Definition: readCCLHist.py:83