def __init__( self, nbins, arg, **kwargs ): ''' To initialize the class one has to provide the number of bins that will be used in the transformed distribution < nbins > and an argument, that can be a set of values or a histogram. If it is a set of values, the option to use the adaptive binning technique is set by the < adaptbin > parameter. If no such technique is used, one can control the number of bin for the input sample with the input parameter < ntrbins >. ''' verbose = kwargs.get( 'verbose', True ) self.AdaptBin = kwargs.get( 'adaptbin', False ) if isinstance( arg, TH1 ): if verbose: print ( 'INFO: After the transformation, all the values greater than one will be ' + 'attached to the last bin' ) if self.AdaptBin: print 'WARNING: Adaptive binned method not available with a TH1 object as input' self.AdaptBin = False self.MainHist = arg self.Nbins = nbins else: if self.AdaptBin: if verbose: print ( 'INFO: The output histogram comes from an adaptive binned transformation. ' + 'Is constructed as: x in bin if x > min and x <= max.' ) length = len( arg ) self.MainHist = MakeAdaptiveBinnedHist( '', length/nbins, arg ) self.Nbins = nbins for val in arg: self.MainHist.Fill( val ) else: ntrbins = kwargs.get( 'ntrbins', 100 ) self.__init__( nbins, MakeHistogram( arg, nbins = ntrbins ) ) self.CumulativeHist = MakeCumulative( self.MainHist )
class IntegralTransformer: def __init__( self, nbins, arg, **kwargs ): ''' To initialize the class one has to provide the number of bins that will be used in the transformed distribution < nbins > and an argument, that can be a set of values or a histogram. If it is a set of values, the option to use the adaptive binning technique is set by the < adaptbin > parameter. If no such technique is used, one can control the number of bin for the input sample with the input parameter < ntrbins >. ''' verbose = kwargs.get( 'verbose', True ) self.AdaptBin = kwargs.get( 'adaptbin', False ) if isinstance( arg, TH1 ): if verbose: print ( 'INFO: After the transformation, all the values greater than one will be ' + 'attached to the last bin' ) if self.AdaptBin: print 'WARNING: Adaptive binned method not available with a TH1 object as input' self.AdaptBin = False self.MainHist = arg self.Nbins = nbins else: if self.AdaptBin: if verbose: print ( 'INFO: The output histogram comes from an adaptive binned transformation. ' + 'Is constructed as: x in bin if x > min and x <= max.' ) length = len( arg ) self.MainHist = MakeAdaptiveBinnedHist( '', length/nbins, arg ) self.Nbins = nbins for val in arg: self.MainHist.Fill( val ) else: ntrbins = kwargs.get( 'ntrbins', 100 ) self.__init__( nbins, MakeHistogram( arg, nbins = ntrbins ) ) self.CumulativeHist = MakeCumulative( self.MainHist ) def Transform( self, name, arg, **kwargs ): ''' Transforms the distribution from the given set of values using the class distribution. One must provide the name of the output histogram and an argument. This argument can be a histogram or an iterable. The title and the type of histogram are set using the < title > and < htype > parameters. ''' title = kwargs.get( 'title', name ) histcall = HistFromType( kwargs.get( 'htype', 'double' ) ) transf = histcall( name, title, self.Nbins, 0, 1 ) ''' If the argument is an histogram, it creates the list with the values and associated weights. ''' if isinstance( arg, TH1 ): values = [ ( arg.GetBinCenter( ib ), arg.GetBinContent( ib ) ) for ib in xrange( 1, arg.GetNbinsX() + 1 ) ] else: values = zip( arg, len( arg )*[ 1. ] ) if self.AdaptBin: nbins = self.MainHist.GetNbinsX() blist = [ self.MainHist.GetBinLowEdge( ib ) for ib in xrange( 1, nbins + 2 ) ] bins = array( 'd', blist ) abhist = self.MainHist.__class__( '', '', nbins, bins ) for val, wgt in values: abhist.Fill( val, wgt ) sw = abhist.GetSumOfWeights() for ib in xrange( 1, self.MainHist.GetNbinsX() + 1 ): cont = abhist.GetBinContent( ib ) transf.SetBinContent( ib, cont/sw ) transf.SetBinError( ib, sqrt( cont/sw**2 + sw*cont**2/sw**4 ) ) else: addifone = 1 - transf.GetBinWidth( 1 )/2. for val, wgt in values: fval = self.CumulativeHist.Interpolate( val ) if fval != 1: transf.Fill( fval, wgt ) else: transf.Fill( addifone, wgt ) return transf def DeTransfValue( self, value, retallinfo = False ): ''' Returns the de-transformated value associated to that given. If the option < retallinfo > is set to True, it will return the bin center and the bin width associated with that value. ''' hist = self.CumulativeHist binvals = [ hist.GetBinContent( ib ) for ib in xrange( 1, hist.GetNbinsX() + 1 ) ] pos = bisect( binvals, value ) - 1 if retallinfo: return hist.GetBinCenter( pos ), hist.GetBinWidth( pos ) else: return hist.GetBinCenter( pos )