ATLAS Offline Software
JESUncertainty_RatioUtils.py
Go to the documentation of this file.
1 #!/bin/python
2 
3 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
4 # -*- coding: utf-8 -*-
5 
6 from numpy import isnan
7 from ROOT import Double, TGraphErrors
8 from math import sqrt
9 
10 
13 
14 def divideGraphs (numeratorGraph, denominatorGraph, warn) :
15 
16  #get number of points for the two graphs
17  nPointsNum = numeratorGraph.GetN()
18  nPointsDen = denominatorGraph.GetN()
19 
20  if nPointsNum!=nPointsDen :
21  print "ERROR in JESUncertainty_RatioUtils:: graphs don't have the same number of points"
22  return None
23 
24  #prepare the final graph
25  graphRatio = TGraphErrors()
26  graphRatio.SetName(numeratorGraph.GetName())
27 
28  #loop on points of the graphs
29  for iPoint in xrange(0,nPointsNum) :
30 
31  #retrieve the point
32  dataPointXNum = Double(0)
33  dataPointYNum = Double(0)
34  errorXNum = numeratorGraph.GetErrorX(iPoint)
35  errorYNum = numeratorGraph.GetErrorY(iPoint)
36  numeratorGraph.GetPoint(iPoint,dataPointXNum,dataPointYNum)
37 
38  dataPointXDen = Double(0)
39  dataPointYDen = Double(0)
40  errorXDen = denominatorGraph.GetErrorX(iPoint)
41  errorYDen = denominatorGraph.GetErrorY(iPoint)
42  denominatorGraph.GetPoint(iPoint,dataPointXDen,dataPointYDen)
43 
44  if abs(dataPointXNum-dataPointXDen) > 0.0001:
45  print "ERROR in JESUncertainty_RatioUtils::divideGraphs: x coordinates of data points do not match"
46  return None
47 
48  #do the ratio
49  dataPointXRatio = dataPointXNum
50  dataPointYRatio = None
51  if dataPointYDen != 0 :
52  dataPointYRatio = dataPointYNum/dataPointYDen
53  else :
54  dataPointYRatio = 0
55  if warn == True :
56  print "WARNING in JESUncertainty_RatioUtils::divideGraphs: division by zero for x point: ", dataPointXNum
57  print "numerator graph:", numeratorGraph.GetName()
58  print "denominator graph:", denominatorGraph.GetName()
59 
60  errorXRatio = errorXNum
61 
62 
63  #calculate the error (simple error propagation)
64  if errorYNum != 0 and errorYDen != 0 :
65 
66  #no correlation:
67  errorYRatioNoCorr = sqrt(
68  pow(errorYNum,2)/pow(dataPointYDen,2)+
69  pow(errorYDen,2)*pow(dataPointYNum,2)/pow(dataPointYDen,4)
70  )
71 
72  #with correlation:
73  #relativeErrorYRatioSquared = (pow((errorYNum/dataPointYNum),2)+
74  #pow((errorYDen/dataPointYDen),2)-
75  #2*(errorYNum*errorYDen)/(dataPointYNum*dataPointYDen))
76 
77  #errorYRatioCorr = sqrt(relativeErrorYRatioSquared/(pow(dataPointYRatio,2)))
78 
79  #go for no correlation:
80  errorYRatio = errorYRatioNoCorr
81 
82  #case in which the numerator is zero (should not happen), zero the error as well
83  #this is not the best approach but it should be good enough for what we are doing (we always discard points with zero response)
84  elif dataPointYNum == 0 or dataPointYDen == 0 :
85  errorYRatio = 0
86 
87  graphRatio.SetPoint(iPoint, dataPointXRatio, dataPointYRatio)
88  graphRatio.SetPointError(iPoint, errorXRatio, errorYRatio)
89 
90  return graphRatio
91 
92 
93 
96 
97 def getDeltaVarGraph (graph) :
98 
99  #get number of points for the graph
100  nPoints = graph.GetN()
101 
102  #prepare the final graph
103  deltaVarGraph = TGraphErrors()
104  deltaVarGraph.SetName(graph.GetName())
105 
106  #loop on points of the graphs
107  for iPoint in xrange(0,nPoints) :
108 
109  #retrieve the point
110  dataPointX = Double(0)
111  dataPointY = Double(0)
112  errorX = graph.GetErrorX(iPoint)
113  errorY = graph.GetErrorY(iPoint)
114  graph.GetPoint(iPoint,dataPointX,dataPointY)
115 
116  #subtract unity and do the absolute value
117  dataPointXDeltaVar = dataPointX
118  dataPointYDeltaVar = abs(1-dataPointY)
119  errorXDeltaVar = errorX
120 
121  deltaVarGraph.SetPoint(iPoint, dataPointXDeltaVar, dataPointYDeltaVar)
122 
123  #being lazy (we will truncate the error if it goes below zero anyways)
124  errorYDeltaVar = errorY
125 
126  #to calculate the error correctly
127  #if dataPointY != 0 and (dataPointY-1) > 0 :
128  #errorYDeltaVar = sqrt((dataPointY-1)/abs(dataPointY-1) * errorY) #this guarantees one does not go negative spitting an exception
129  #else
130  #one here would need to do a TGraphAsymmErrors with only the positive error in full
131 
132  deltaVarGraph.SetPointError(iPoint, errorXDeltaVar, errorYDeltaVar)
133 
134 
135  return deltaVarGraph
136 
137 
140 
141 def getMaxVariationGraph (graph1, graph2) :
142 
143  #get number of points for the two graphs
144  nPointsGraph1= graph1.GetN()
145  nPointsGraph2 = graph2.GetN()
146 
147  if nPointsGraph1!=nPointsGraph2 :
148  print "ERROR in JESUncertainty_RatioUtils::getMaxVariationGraph: graphs don't have the same number of points"
149  return None
150 
151  #prepare the final graph
152  maxVarGraph = graph1.Clone()
153  maxVarGraph.SetName(graph1.GetName()+"_Max")
154 
155  #loop on points of the graphs
156  for iPoint in xrange(0,nPointsGraph1) :
157 
158  #make the new point
159  maxPoint = Double(0)
160  maxPointError = Double(0)
161 
162  #retrieve the point
163  dataPointXGraph1 = Double(0)
164  dataPointYGraph1 = Double(0)
165  errorXGraph1= graph1.GetErrorX(iPoint)
166  errorYGraph1 = graph1.GetErrorY(iPoint)
167  graph1.GetPoint(iPoint,dataPointXGraph1,dataPointYGraph1)
168 
169  dataPointXGraph2 = Double(0)
170  dataPointYGraph2 = Double(0)
171  errorXGraph2 = graph2.GetErrorX(iPoint)
172  errorYGraph2 = graph2.GetErrorY(iPoint)
173  graph2.GetPoint(iPoint,dataPointXGraph2,dataPointYGraph2)
174 
175  if abs(dataPointXGraph1-dataPointXGraph2) > 0.0001:
176  print "ERROR in JESUncertainty_RatioUtils::getMaxVariationGraph: x coordinates of data points do not match"
177  return None
178 
179  #check for the largest (the convention of -999 for useless bins should work here)
180  if dataPointYGraph1 > dataPointYGraph2 :
181  maxPoint = dataPointYGraph1
182  maxPointError = errorYGraph1
183 
184  else :
185  maxPoint = dataPointYGraph2
186  maxPointError = errorYGraph2
187  #print dataPointXGraph1, maxPoint, maxPointError
188  maxVarGraph.SetPoint(iPoint, dataPointXGraph1, maxPoint)
189  maxVarGraph.SetPointError(iPoint, errorXGraph1, maxPointError)
190 
191  return maxVarGraph
192  #TODO: is there anything to do for the last good bin?
193 
194 
195 #Debugging material to see if it actually works
196 #c=TCanvas()
197 #deadMaterialMaxVarGraph.Draw("AP")
198 #deadMaterialMaxVarGraph.SetMarkerStyle(25)
199 #deadMaterialMaxVarGraph.SetMarkerSize(2)
200 #deadMaterialMaxVarGraph.SetMarkerColor(4)
201 #deadMaterialMaxVarGraph.SetLineStyle(2)
202 #deadMaterialMaxVarGraph.SetLineWidth(5)
203 #deadMaterialMaxVarGraph.SetLineColor(4)
204 #gPad.SetLogx()
205 #deadMaterialGraphE.SetMarkerStyle(20)
206 #deadMaterialGraphE.Draw("Psame")
207 #deadMaterialGraphPt.SetMarkerStyle(22)
208 #deadMaterialGraphPt.Draw("Psame")
209 #c.SaveAs("max.png")
210 
211 
214 
215 def getQuadratureGraph (dummyGraph, listOfGraphs) :
216 
217 
218  for graphToSum in listOfGraphs :
219  #print graphToSum
220  nPointsDummyGraph = dummyGraph.GetN()
221  nPointsGraphToSum = graphToSum.GetN()
222 
223  if nPointsDummyGraph!=nPointsGraphToSum :
224  print "ERROR in JESUncertainty_RatioUtils::getQuadratureGraph: graphs don't have the same number of points"
225  return None
226 
227  #loop on points of the graphs
228  for iPoint in xrange(0,nPointsDummyGraph) :
229 
230  #retrieve the point
231  dataPointXDummyGraph = Double(0)
232  dataPointYDummyGraph = Double(0)
233  dummyGraph.GetPoint(iPoint,dataPointXDummyGraph,dataPointYDummyGraph)
234 
235  dataPointXGraphToSum = Double(0)
236  dataPointYGraphToSum = Double(0)
237  errorXGraphToSum = graphToSum.GetErrorX(iPoint)
238  errorYGraphToSum = graphToSum.GetErrorY(iPoint)
239  graphToSum.GetPoint(iPoint,dataPointXGraphToSum,dataPointYGraphToSum)
240 
241  if abs(dataPointXDummyGraph-dataPointXGraphToSum) > 0.0001:
242  print "ERROR in JESUncertainty_RatioUtils::getQuadratureGraph: x coordinates of data points do not match"
243  return None
244 
245  #end of preliminary checks
246 
247  #prepare everything for the propagation of errors
248  #these are arrays that at the end of the loop on the graphs contain the points and errors
249  AllSquaredSums = []
250  AllErrors = []
251  #and this is the final graph that contains the quadrature of the others
252  quadratureGraph = dummyGraph.Clone()
253  quadratureGraph.SetName(listOfGraphs[0].GetName()+"_Quadrature")
254 
255  for iPoint in xrange(0,nPointsDummyGraph) :
256 
257  squaredSum = 0
258  error = 0
259  badPoint = False
260 
261  for graphToSum in listOfGraphs :
262 
263  dataPointXGraphToSum = Double(0)
264  dataPointYGraphToSum = Double(0)
265  errorXGraphToSum = graphToSum.GetErrorX(iPoint)
266  errorYGraphToSum = graphToSum.GetErrorY(iPoint)
267  graphToSum.GetPoint(iPoint,dataPointXGraphToSum,dataPointYGraphToSum)
268 
269  #check for bad points
270  if dataPointYGraphToSum < -998 :
271  badPoint = True
272 
273  #this will be the denominator of the error propagation as well
274  squaredSum += pow(dataPointYGraphToSum,2)
275 
276  #if iPoint == 0:
277  #print "toSum: ", dataPointYGraphToSum
278  #print "toSumSquared: ", pow(dataPointYGraphToSum,2)
279  #this is the numerator of the error propagation
280  error += pow(dataPointYGraphToSum*errorYGraphToSum,2)
281  #print "addingToErrorNum: ", pow(dataPointYGraphToSum*errorYGraphToSum,2)
282 
283  try :
284  sqrtSquaredSum = sqrt(squaredSum)
285  sqrtError = sqrt(error/squaredSum)
286  except :
287  sqrtSquaredSum = 0
288  sqrtError = 0
289 
290  #propagate the bad points
291  if badPoint :
292  sqrtSquaredSum = -999
293  sqrtError = 0.000000001
294 
295  #now append them (for debugging reasons only)
296  AllSquaredSums.append(sqrtSquaredSum)
297  AllErrors.append(sqrtError)
298 
299  #put them into the final plot
300  quadratureGraph.SetPoint(iPoint, dataPointXGraphToSum, sqrtSquaredSum)
301  quadratureGraph.SetPointError(iPoint, errorXGraphToSum, sqrtError)
302 
303  return quadratureGraph
304 
305 
308 
309 def getLinearSumGraph (dummyGraph, listOfGraphs) :
310 
311 
312  for graphToSum in listOfGraphs :
313  #print graphToSum
314  nPointsDummyGraph = dummyGraph.GetN()
315  nPointsGraphToSum = graphToSum.GetN()
316 
317  if nPointsDummyGraph!=nPointsGraphToSum :
318  print "ERROR in JESUncertainty_RatioUtils::getQuadratureGraph: graphs don't have the same number of points"
319  return None
320 
321  #loop on points of the graphs
322  for iPoint in xrange(0,nPointsDummyGraph) :
323 
324  #retrieve the point
325  dataPointXDummyGraph = Double(0)
326  dataPointYDummyGraph = Double(0)
327  dummyGraph.GetPoint(iPoint,dataPointXDummyGraph,dataPointYDummyGraph)
328 
329  dataPointXGraphToSum = Double(0)
330  dataPointYGraphToSum = Double(0)
331  errorXGraphToSum = graphToSum.GetErrorX(iPoint)
332  errorYGraphToSum = graphToSum.GetErrorY(iPoint)
333  graphToSum.GetPoint(iPoint,dataPointXGraphToSum,dataPointYGraphToSum)
334 
335  if abs(dataPointXDummyGraph-dataPointXGraphToSum) > 0.0001:
336  print "ERROR in JESUncertainty_RatioUtils::getQuadratureGraph: x coordinates of data points do not match"
337  return None
338 
339  #end of preliminary checks
340 
341  #prepare everything for the propagation of errors
342  #these are arrays that at the end of the loop on the graphs contain the points and errors
343  AllSquaredSums = []
344  AllErrors = []
345 
346  #this contains the errors for all data points for the propagation
347  ListOfErrors = []
348 
349  #and this is the final graph that contains the quadrature of the others
350  linearGraph = dummyGraph.Clone()
351  linearGraph.SetName(listOfGraphs[0].GetName()+"_Quadrature")
352 
353  for iPoint in xrange(0,nPointsDummyGraph) :
354 
355  theSum = 0
356  uncorrError = 0
357  corrError = 0
358  badPoint = False
359 
360  for graphToSum in listOfGraphs :
361 
362  dataPointXGraphToSum = Double(0)
363  dataPointYGraphToSum = Double(0)
364  errorXGraphToSum = graphToSum.GetErrorX(iPoint)
365  errorYGraphToSum = graphToSum.GetErrorY(iPoint)
366  graphToSum.GetPoint(iPoint,dataPointXGraphToSum,dataPointYGraphToSum)
367 
368  #check for bad points
369  if dataPointYGraphToSum < -998 :
370  badPoint = True
371 
372  #this will be the denominator of the error propagation as well
373  theSum += dataPointYGraphToSum
374 
375  #print "toSumSquared: ", pow(dataPointYGraphToSum,2)
376  #this is for the error propagation
377  uncorrError += pow(errorYGraphToSum,2)
378  ListOfErrors.append(errorYGraphToSum)
379  #print "addingToErrorNum: ", pow(dataPointYGraphToSum*errorYGraphToSum,2)
380 
381  #need to do all combination of errors
382  while len(ListOfErrors) != 0 :
383  for iError, theError in enumerate(ListOfErrors) :
384  theError = ListOfErrors.pop(iError)
385  for jError, theOtherError in enumerate(ListOfErrors) :
386  corrError =+ theError * theOtherError
387 
388  sqrtSum = theSum
389  sqrtError = sqrt(uncorrError + 2 * corrError)
390 
391  #propagate the bad points
392  if badPoint :
393  sqrtSum = -999
394  sqrtError = 0.000000001
395 
396  #now append them (for debugging reasons only)
397  AllSquaredSums.append(sqrtSum)
398  AllErrors.append(sqrtError)
399  #print AllSquaredSums
400  #print AllErrors
401 
402  #put them into the final plot
403  linearGraph.SetPoint(iPoint, dataPointXGraphToSum, sqrtSum)
404  linearGraph.SetPointError(iPoint, errorXGraphToSum, sqrtError)
405 
406  return linearGraph
JESUncertainty_RatioUtils.getDeltaVarGraph
def getDeltaVarGraph(graph)
Calculate point by point |1-graph| and put it into a TGraph.
Definition: JESUncertainty_RatioUtils.py:97
xrange
void xrange(TH1 *h, bool symmetric)
Definition: computils.cxx:515
JESUncertainty_RatioUtils.divideGraphs
def divideGraphs(numeratorGraph, denominatorGraph, warn)
Do the ratio of two TGraphs.
Definition: JESUncertainty_RatioUtils.py:14
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
JESUncertainty_RatioUtils.getMaxVariationGraph
def getMaxVariationGraph(graph1, graph2)
Get maximum variation out of two plots.
Definition: JESUncertainty_RatioUtils.py:141
JESUncertainty_RatioUtils.getLinearSumGraph
def getLinearSumGraph(dummyGraph, listOfGraphs)
Get a graph that is the linear sum of all others (they all have to look like dummygraph)
Definition: JESUncertainty_RatioUtils.py:309
JESUncertainty_RatioUtils.getQuadratureGraph
def getQuadratureGraph(dummyGraph, listOfGraphs)
Get a graph that is the sum in quadrature of all others (they all have to look like dummygraph)
Definition: JESUncertainty_RatioUtils.py:215