ATLAS Offline Software
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 ROOT import TGraphErrors,TGraph, TGraphAsymmErrors, Double, TCanvas, gPad
7 #import numpy
8 from math import fabs, sqrt
9 
10 
11 
12 
13 def getPlotRatio (plotNum, plotDen, doAverage) :
14 
15  DataPointsForAverage=[]
16  ErrorsForAverage=[]
17  averageDelta = 0
18  maxDelta = 0
19  nPointsNum = plotNum.GetN()
20  nPointsDen = plotDen.GetN()
21 
22  if nPointsNum!=nPointsDen :
23  print "Plots don't have the same number of points!"
24  return(0,0,0)
25 
26  plotRatio = TGraphErrors()
27 
28  plotRatio.SetName(plotNum.GetName())
29 
30  x1=Double(0)
31  y1=Double(0)
32  x2=Double(0)
33  y2=Double(0)
34  dx1=Double(0)
35  dx2=Double(0)
36  dy1=Double(0)
37  dy2=Double(0)
38  iv=int(0)
39  dx=Double(0)
40  for pointNum in xrange(0,nPointsNum) :
41  pointNum = int(pointNum)
42  matchcount = 0
43  for pointDen in xrange(0,nPointsDen) :
44  pointDen = int(pointDen)
45  plotNum.GetPoint(pointNum, x1, y1)
46  plotDen.GetPoint(pointDen, x2, y2)
47  dx1 = plotNum.GetErrorX(pointNum)
48  dx2 = plotNum.GetErrorX(pointDen)
49  emean = (dx1+dx2)/2.
50  if fabs(x1-x2)>=emean and fabs(x1-x2)>dx :
51  pass
52  #print "no idea what's going on here"
53  else :
54  matchcount=matchcount+1
55  dx1 = plotNum.GetErrorX(pointNum)
56  if y1 != 0 : dy1 = plotNum.GetErrorY(pointNum)/y1
57  if y2 != 0 : dy2 = plotNum.GetErrorY(pointDen)/y2
58 
59  if y2 != 0 :
60  plotRatio.SetPoint(iv, x1, y1/y2)
61  if doAverage : DataPointsForAverage.append(y1/y2)
62 
63  else :
64  plotRatio.SetPoint(iv, x1, y2)
65  if doAverage : DataPointsForAverage.append(y2)
66 
67  e = Double(0)
68 
69  if y1 != 0 and y2 != 0 : e=sqrt(dy1*dy1+dy2*dy2)*(y1/y2)
70  plotRatio.SetPointError(iv, dx1, e)
71  if doAverage : ErrorsForAverage.append(e)
72 
73  iv = iv+1
74 
75  if (matchcount>1) :
76  print "too many x points matched!"
77  return(0)
78 
79  if doAverage :
80 
81  averageDelta = getAverageDelta(DataPointsForAverage, ErrorsForAverage)
82  maxDelta = getMaxDelta(DataPointsForAverage, ErrorsForAverage)
83 
84 
85  return plotRatio, averageDelta-1, maxDelta
86 
87 
88 def getAverageDelta (DataPoints, ErrorsOnDataPoints) :
89  if len(DataPoints) != len(ErrorsOnDataPoints) :
90  "Data points and errors do not match"
91  return 0
92 
93  average = 0
94  skippedDataPoints = 0
95 
96  for datapoint,error in zip(DataPoints, ErrorsOnDataPoints) :
97  #don't care about the data point if the error is 0
98  if error<0.00000001 or error>0.03 :
99  skippedDataPoints = skippedDataPoints+1
100  pass
101 
102  else :
103  average += datapoint
104 
105  average = average/(len(DataPoints)-skippedDataPoints)
106  return average
107 
108 def getMaxDelta (DataPoints, ErrorsOnDataPoints) :
109  if len(DataPoints) != len(ErrorsOnDataPoints) :
110  "Data points and errors do not match"
111  return 0
112 
113  maxDelta = 0
114 
115  for datapoint,error in zip(DataPoints, ErrorsOnDataPoints) :
116  #don't care about the data point if the error is 0
117  if error<0.00000001 :
118  pass
119  #or if the error is > 3% (most likely due to a bad fit)
120  elif error>0.03 :
121  pass
122  else :
123  if fabs(datapoint-1) > fabs(maxDelta) : maxDelta = datapoint-1
124 
125  return maxDelta
126 
127 
128 def numericalInvertPlot (graph) :
129  #pick up point by point pl
130 
131  #loop on all data points
132  nPoints = graph.GetN()
133 
134  newGraph=TGraphAsymmErrors(nPoints)
135 
136  #x=array('f')
137  #y=array('f')
138  #ey=array('f')
139 
140  for iPoint in xrange(0,nPoints) :
141  #get info on data point
142  dataPointX = Double(0)
143  dataPointY = Double(0)
144  graph.GetPoint(iPoint,dataPointX,dataPointY)
145  dataErrorX = graph.GetErrorX(iPoint)
146  dataErrorY = graph.GetErrorY(iPoint)
147 
148  #numerical-invert the X
149  newDataPointX = dataPointX * dataPointY
150 
151  newErrorXLeft = fabs(newDataPointX - (dataPointX-dataErrorX))
152  newErrorXRight = fabs(newDataPointX - (dataPointX+dataErrorX))
153 
154  #setting the new graph (with asymm errors this time)
155  newGraph.SetPoint(iPoint, newDataPointX, dataPointY)
156  newGraph.SetPointEXhigh(iPoint, newErrorXRight)
157  newGraph.SetPointEXlow(iPoint, newErrorXLeft)
158  newGraph.SetPointEYhigh(iPoint, dataErrorY)
159  newGraph.SetPointEYlow(iPoint, dataErrorY)
160 
161  print dataPointY, newDataPointX
162  #check that the numerical-inverted X is still in the previous bin - otherwise, ERROR!
163  binRangeLow = dataPointX-dataErrorX
164  binRangeHigh = dataPointX+dataErrorX
165  if newDataPointX<binRangeLow or newDataPointX>binRangeHigh :
166  print "Warning! Data point should not be here!"
167  print "Old data point: ", dataPointX
168  print "New NI data point:" , newDataPointX
169  print "XLow: ", binRangeLow
170  print "XHigh: ", binRangeHigh
171  newGraph.SetPoint(iPoint, dataPointX, 0.0000000000001)
172  newGraph.SetPointEXhigh(iPoint, dataErrorX)
173  newGraph.SetPointEXlow(iPoint, dataErrorX)
174  newGraph.SetPointEYhigh(iPoint, dataErrorY)
175  newGraph.SetPointEYlow(iPoint, dataErrorY)
176 
177  return newGraph
xrange
void xrange(TH1 *h, bool symmetric)
Definition: computils.cxx:516
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
RatioUtils.getAverageDelta
def getAverageDelta(DataPoints, ErrorsOnDataPoints)
Definition: RatioUtils.py:88
RatioUtils.numericalInvertPlot
def numericalInvertPlot(graph)
Definition: RatioUtils.py:128
RatioUtils.getPlotRatio
def getPlotRatio(plotNum, plotDen, doAverage)
Division function############.
Definition: RatioUtils.py:13
RatioUtils.getMaxDelta
def getMaxDelta(DataPoints, ErrorsOnDataPoints)
Definition: RatioUtils.py:108