parameters: (histos, ratioUncertainty=False)
return_statement: return wrappers
docstring: Calculate the ratios for a list of histograms
docstring_summary: Calculate the ratios for a list of histograms
docstring_tokens: Calculate the ratios for a list of histograms
function: def _calculateRatios(histos, ratioUncertainty=False):
      """Calculate the ratios for a list of histograms"""
  
      def _divideOrZero(numerator, denominator):
          if denominator == 0:
              return 0
          return numerator/denominator
  
      def equal(a, b):
          if a == 0. and b == 0.:
              return True
          return abs(a-b)/max(abs(a),abs(b)) < 1e-3
  
      def findBins(wrap, bins_xvalues):
          ret = []
          currBin = wrap.begin()
          i = 0
          while i < len(bins_xvalues) and currBin < wrap.end():
              (xcenter, xlow, xhigh) = bins_xvalues[i]
              xlowEdge = xcenter-xlow
              xupEdge = xcenter+xhigh
  
              (curr_center, curr_low, curr_high) = wrap.xvalues(currBin)
              curr_lowEdge = curr_center-curr_low
              curr_upEdge = curr_center+curr_high
  
              if equal(xlowEdge, curr_lowEdge) and equal(xupEdge,  curr_upEdge):
                  ret.append(currBin)
                  currBin += 1
                  i += 1
              elif curr_upEdge <= xlowEdge:
                  currBin += 1
              elif curr_lowEdge >= xupEdge:
                  ret.append(None)
                  i += 1
              else:
                  ret.append(None)
                  currBin += 1
                  i += 1
          if len(ret) != len(bins_xvalues):
              ret.extend([None]*( len(bins_xvalues) - len(ret) ))
          return ret
  
      # Define wrappers for TH1/TGraph/TGraph2D to have uniform interface
      # TODO: having more global wrappers would make some things simpler also elsewhere in the code
      class WrapTH1:
          def __init__(self, th1, uncertainty):
              self._th1 = th1
              self._uncertainty = uncertainty
  
              xaxis = th1.GetXaxis()
              xaxis_arr = xaxis.GetXbins()
              if xaxis_arr.GetSize() > 0: # unequal binning
                  lst = [xaxis_arr[i] for i in range(0, xaxis_arr.GetSize())]
                  arr = array.array("d", lst)
                  self._ratio = ROOT.TH1F("foo", "foo", xaxis.GetNbins(), arr)
              else:
                  self._ratio = ROOT.TH1F("foo", "foo", xaxis.GetNbins(), xaxis.GetXmin(), xaxis.GetXmax())
              _copyStyle(th1, self._ratio)
              self._ratio.SetStats(0)
              self._ratio.SetLineColor(ROOT.kBlack)
              self._ratio.SetLineWidth(1)
          def draw(self, style=None):
              st = style
              if st is None:
                  if self._uncertainty:
                      st = "EP"
                  else:
                      st = "HIST P"
              self._ratio.Draw("same "+st)
          def begin(self):
              return 1
          def end(self):
              return self._th1.GetNbinsX()+1
          def xvalues(self, bin):
              xval = self._th1.GetBinCenter(bin)
              xlow = xval-self._th1.GetXaxis().GetBinLowEdge(bin)
              xhigh = self._th1.GetXaxis().GetBinUpEdge(bin)-xval
              return (xval, xlow, xhigh)
          def yvalues(self, bin):
              yval = self._th1.GetBinContent(bin)
              yerr = self._th1.GetBinError(bin)
              return (yval, yerr, yerr)
          def y(self, bin):
              return self._th1.GetBinContent(bin)
          def divide(self, bin, scale):
              self._ratio.SetBinContent(bin, _divideOrZero(self._th1.GetBinContent(bin), scale))
              self._ratio.SetBinError(bin, _divideOrZero(self._th1.GetBinError(bin), scale))
          def makeRatio(self):
              pass
          def getRatio(self):
              return self._ratio
  
      class WrapTGraph:
          def __init__(self, gr, uncertainty):
              self._gr = gr
              self._uncertainty = uncertainty
              self._xvalues = []
              self._xerrslow = []
              self._xerrshigh = []
              self._yvalues = []
              self._yerrshigh = []
              self._yerrslow = []
          def draw(self, style=None):
              if self._ratio is None:
                  return
              st = style
              if st is None:
                  if self._uncertainty:
                      st = "PZ"
                  else:
                      st = "PX"
              self._ratio.Draw("same "+st)
          def begin(self):
              return 0
          def end(self):
              return self._gr.GetN()
          def xvalues(self, bin):
              return (self._gr.GetX()[bin], self._gr.GetErrorXlow(bin), self._gr.GetErrorXhigh(bin))
          def yvalues(self, bin):
              return (self._gr.GetY()[bin], self._gr.GetErrorYlow(bin), self._gr.GetErrorYhigh(bin))
          def y(self, bin):
              return self._gr.GetY()[bin]
          def divide(self, bin, scale):
              # Ignore bin if denominator is zero
              if scale == 0:
                  return
              # No more items in the numerator
              if bin >= self._gr.GetN():
                  return
              # denominator is missing an item
              xvals = self.xvalues(bin)
              xval = xvals[0]
  
              self._xvalues.append(xval)
              self._xerrslow.append(xvals[1])
              self._xerrshigh.append(xvals[2])
              yvals = self.yvalues(bin)
              self._yvalues.append(yvals[0] / scale)
              if self._uncertainty:
                  self._yerrslow.append(yvals[1] / scale)
                  self._yerrshigh.append(yvals[2] / scale)
              else:
                  self._yerrslow.append(0)
                  self._yerrshigh.append(0)
          def makeRatio(self):
              if len(self._xvalues) == 0:
                  self._ratio = None
                  return
              self._ratio = ROOT.TGraphAsymmErrors(len(self._xvalues), array.array("d", self._xvalues), array.array("d", self._yvalues),
                                                   array.array("d", self._xerrslow), array.array("d", self._xerrshigh),
                                                   array.array("d", self._yerrslow), array.array("d", self._yerrshigh))
              _copyStyle(self._gr, self._ratio)
          def getRatio(self):
              return self._ratio
      class WrapTGraph2D(WrapTGraph):
          def __init__(self, gr, uncertainty):
              WrapTGraph.__init__(self, gr, uncertainty)
          def xvalues(self, bin):
              return (self._gr.GetX()[bin], self._gr.GetErrorX(bin), self._gr.GetErrorX(bin))
          def yvalues(self, bin):
              return (self._gr.GetY()[bin], self._gr.GetErrorY(bin), self._gr.GetErrorY(bin))
  
      def wrap(o):
          if isinstance(o, ROOT.TH1) and not isinstance(o, ROOT.TH2):
              return WrapTH1(o, ratioUncertainty)
          elif isinstance(o, ROOT.TGraph):
              return WrapTGraph(o, ratioUncertainty)
          elif isinstance(o, ROOT.TGraph2D):
              return WrapTGraph2D(o, ratioUncertainty)
  
      wrappers = [wrap(h) for h in histos if wrap(h) is not None]
      if len(wrappers) < 1:
          return []
      ref = wrappers[0]
  
      wrappers_bins = []
      ref_bins = [ref.xvalues(b) for b in range(ref.begin(), ref.end())]
      for w in wrappers:
          wrappers_bins.append(findBins(w, ref_bins))
  
      for i, bin in enumerate(range(ref.begin(), ref.end())):
          (scale, ylow, yhigh) = ref.yvalues(bin)
          for w, bins in zip(wrappers, wrappers_bins):
              if bins[i] is None:
                  continue
              w.divide(bins[i], scale)
  
      for w in wrappers:
          w.makeRatio()
  
      return wrappers
function_tokens: def _calculateRatios ( histos , ratioUncertainty = False ) : def _divideOrZero ( numerator , denominator ) : if denominator == 0 : return 0 return numerator / denominator def equal ( a , b ) : if a == 0. and b == 0. : return True return abs ( a - b ) / max ( abs ( a ) , abs ( b ) ) < 1e-3 def findBins ( wrap , bins_xvalues ) : ret = [ ] currBin = wrap . begin ( ) i = 0 while i < len ( bins_xvalues ) and currBin < wrap . end ( ) : ( xcenter , xlow , xhigh ) = bins_xvalues [ i ] xlowEdge = xcenter - xlow xupEdge = xcenter + xhigh ( curr_center , curr_low , curr_high ) = wrap . xvalues ( currBin ) curr_lowEdge = curr_center - curr_low curr_upEdge = curr_center + curr_high if equal ( xlowEdge , curr_lowEdge ) and equal ( xupEdge , curr_upEdge ) : ret . append ( currBin ) currBin += 1 i += 1 elif curr_upEdge <= xlowEdge : currBin += 1 elif curr_lowEdge >= xupEdge : ret . append ( None ) i += 1 else : ret . append ( None ) currBin += 1 i += 1 if len ( ret ) != len ( bins_xvalues ) : ret . extend ( [ None ] * ( len ( bins_xvalues ) - len ( ret ) ) ) return ret # Define wrappers for TH1/TGraph/TGraph2D to have uniform interface # TODO: having more global wrappers would make some things simpler also elsewhere in the code class WrapTH1 : def __init__ ( self , th1 , uncertainty ) : self . _th1 = th1 self . _uncertainty = uncertainty xaxis = th1 . GetXaxis ( ) xaxis_arr = xaxis . GetXbins ( ) if xaxis_arr . GetSize ( ) > 0 : # unequal binning lst = [ xaxis_arr [ i ] for i in range ( 0 , xaxis_arr . GetSize ( ) ) ] arr = array . array ( "d" , lst ) self . _ratio = ROOT . TH1F ( "foo" , "foo" , xaxis . GetNbins ( ) , arr ) else : self . _ratio = ROOT . TH1F ( "foo" , "foo" , xaxis . GetNbins ( ) , xaxis . GetXmin ( ) , xaxis . GetXmax ( ) ) _copyStyle ( th1 , self . _ratio ) self . _ratio . SetStats ( 0 ) self . _ratio . SetLineColor ( ROOT . kBlack ) self . _ratio . SetLineWidth ( 1 ) def draw ( self , style = None ) : st = style if st is None : if self . _uncertainty : st = "EP" else : st = "HIST P" self . _ratio . Draw ( "same " + st ) def begin ( self ) : return 1 def end ( self ) : return self . _th1 . GetNbinsX ( ) + 1 def xvalues ( self , bin ) : xval = self . _th1 . GetBinCenter ( bin ) xlow = xval - self . _th1 . GetXaxis ( ) . GetBinLowEdge ( bin ) xhigh = self . _th1 . GetXaxis ( ) . GetBinUpEdge ( bin ) - xval return ( xval , xlow , xhigh ) def yvalues ( self , bin ) : yval = self . _th1 . GetBinContent ( bin ) yerr = self . _th1 . GetBinError ( bin ) return ( yval , yerr , yerr ) def y ( self , bin ) : return self . _th1 . GetBinContent ( bin ) def divide ( self , bin , scale ) : self . _ratio . SetBinContent ( bin , _divideOrZero ( self . _th1 . GetBinContent ( bin ) , scale ) ) self . _ratio . SetBinError ( bin , _divideOrZero ( self . _th1 . GetBinError ( bin ) , scale ) ) def makeRatio ( self ) : pass def getRatio ( self ) : return self . _ratio class WrapTGraph : def __init__ ( self , gr , uncertainty ) : self . _gr = gr self . _uncertainty = uncertainty self . _xvalues = [ ] self . _xerrslow = [ ] self . _xerrshigh = [ ] self . _yvalues = [ ] self . _yerrshigh = [ ] self . _yerrslow = [ ] def draw ( self , style = None ) : if self . _ratio is None : return st = style if st is None : if self . _uncertainty : st = "PZ" else : st = "PX" self . _ratio . Draw ( "same " + st ) def begin ( self ) : return 0 def end ( self ) : return self . _gr . GetN ( ) def xvalues ( self , bin ) : return ( self . _gr . GetX ( ) [ bin ] , self . _gr . GetErrorXlow ( bin ) , self . _gr . GetErrorXhigh ( bin ) ) def yvalues ( self , bin ) : return ( self . _gr . GetY ( ) [ bin ] , self . _gr . GetErrorYlow ( bin ) , self . _gr . GetErrorYhigh ( bin ) ) def y ( self , bin ) : return self . _gr . GetY ( ) [ bin ] def divide ( self , bin , scale ) : # Ignore bin if denominator is zero if scale == 0 : return # No more items in the numerator if bin >= self . _gr . GetN ( ) : return # denominator is missing an item xvals = self . xvalues ( bin ) xval = xvals [ 0 ] self . _xvalues . append ( xval ) self . _xerrslow . append ( xvals [ 1 ] ) self . _xerrshigh . append ( xvals [ 2 ] ) yvals = self . yvalues ( bin ) self . _yvalues . append ( yvals [ 0 ] / scale ) if self . _uncertainty : self . _yerrslow . append ( yvals [ 1 ] / scale ) self . _yerrshigh . append ( yvals [ 2 ] / scale ) else : self . _yerrslow . append ( 0 ) self . _yerrshigh . append ( 0 ) def makeRatio ( self ) : if len ( self . _xvalues ) == 0 : self . _ratio = None return self . _ratio = ROOT . TGraphAsymmErrors ( len ( self . _xvalues ) , array . array ( "d" , self . _xvalues ) , array . array ( "d" , self . _yvalues ) , array . array ( "d" , self . _xerrslow ) , array . array ( "d" , self . _xerrshigh ) , array . array ( "d" , self . _yerrslow ) , array . array ( "d" , self . _yerrshigh ) ) _copyStyle ( self . _gr , self . _ratio ) def getRatio ( self ) : return self . _ratio class WrapTGraph2D ( WrapTGraph ) : def __init__ ( self , gr , uncertainty ) : WrapTGraph . __init__ ( self , gr , uncertainty ) def xvalues ( self , bin ) : return ( self . _gr . GetX ( ) [ bin ] , self . _gr . GetErrorX ( bin ) , self . _gr . GetErrorX ( bin ) ) def yvalues ( self , bin ) : return ( self . _gr . GetY ( ) [ bin ] , self . _gr . GetErrorY ( bin ) , self . _gr . GetErrorY ( bin ) ) def wrap ( o ) : if isinstance ( o , ROOT . TH1 ) and not isinstance ( o , ROOT . TH2 ) : return WrapTH1 ( o , ratioUncertainty ) elif isinstance ( o , ROOT . TGraph ) : return WrapTGraph ( o , ratioUncertainty ) elif isinstance ( o , ROOT . TGraph2D ) : return WrapTGraph2D ( o , ratioUncertainty ) wrappers = [ wrap ( h ) for h in histos if wrap ( h ) is not None ] if len ( wrappers ) < 1 : return [ ] ref = wrappers [ 0 ] wrappers_bins = [ ] ref_bins = [ ref . xvalues ( b ) for b in range ( ref . begin ( ) , ref . end ( ) ) ] for w in wrappers : wrappers_bins . append ( findBins ( w , ref_bins ) ) for i , bin in enumerate ( range ( ref . begin ( ) , ref . end ( ) ) ) : ( scale , ylow , yhigh ) = ref . yvalues ( bin ) for w , bins in zip ( wrappers , wrappers_bins ) : if bins [ i ] is None : continue w . divide ( bins [ i ] , scale ) for w in wrappers : w . makeRatio ( ) return wrappers