Exemplo n.º 1
0
    def __init__(
            self,
            name,
            efficiency,  ## the function or PDF 
            cut,
            xvar=None,
            accept='accept'):

        if isinstance(efficiency, PDF):
            eff_pdf = efficiency
            xvar = efficiency.xvar
            eff_fun = None
        elif isinstance(efficiency, ROOT.RooAbsReal) and xvar and isinstance(
                xvar, ROOT.RooAbsReal):
            eff_pdf = Generic1D_pdf(efficiency, xvar, special=True)
            xvar = xvar
            eff_fun = None if isinstance(efficiency,
                                         ROOT.RooAbsPdf) else efficiency
        else:
            raise AttributeError(
                'Invalid efficiency/xvar combination  %s/%s;%s/%s' %
                (efficiency, type(efficiency), xvar, type(xvar)))

        self.__xvar = xvar
        Efficiency.__init__(self, name, eff_pdf, eff_fun, (xvar, ), cut,
                            accept)
Exemplo n.º 2
0
    def __init__  ( self              ,
                    name              ,
                    efficiency        , ## the function, FUNC or PDF 
                    cut               ,
                    xvar   = None     ,
                    accept = 'accept' ,
                    scale  = None     ) :

        self.__eff = efficiency
        
        if   isinstance   ( efficiency , PDF  ) :
            eff_pdf = efficiency
            xvar    = efficiency.xvar
            eff_fun = None
        elif isinstance   ( efficiency , FUNC ) :
            eff_fun = efficiency.fun 
            xvar    = efficiency.xvar
            eff_pdf = None  
        elif isinstance ( efficiency , ROOT.RooAbsPdf   ) and xvar and isinstance ( xvar , ROOT.RooAbsReal ) :
            eff_pdf = Generic1D_pdf ( efficiency , xvar )                
            eff_fun = None 
        elif isinstance ( efficiency , ROOT.RooAbsReal  ) and xvar and isinstance ( xvar , ROOT.RooAbsReal ) :            
            eff_pdf = Fun1D        ( efficiency , xvar =  xvar )                
            eff_fun = efficiency            
        else :
            raise AttributeError('Invalid efficiency/xvar combination  %s/%s;%s/%s'  %
                                 ( efficiency ,  type(efficiency) , xvar , type(xvar) ) )

        self.__xvar = xvar 
        Efficiency.__init__ ( self , name , eff_pdf , eff_fun ,  ( xvar,) , cut , accept , scale )
Exemplo n.º 3
0
    def __init__(
            self,
            pdf,  ## the PDF to be convoluted 
            resolution,  ## the convolution/resolution
            xvar=None,  ## the axis varable
            useFFT=True,  ## use  FastFourierTransform?
            nbins=1000000,  ## #bins for FFT
            buffer=0.25,  ## buffer fraction ## setBufferFraction
            nsigmas=6,  ## number of sigmas for setConvolutionWindow
            name=''):  ## the name

        self.__arg_pdf = pdf
        self.__arg_resolution = resolution
        self.__arg_xvar = xvar

        if isinstance(pdf, PDF):
            self.__old_pdf = pdf
            xvar = pdf.xvar
        elif isinstance(pdf, ROOT.RooAbsPdf) and xvar:
            self.__old_pdf = Generic1D_pdf(pdf, xvar)
        else:
            raise AttributeError("Convolution_pdf: invalid pdf/xvar %s/%s" %
                                 (pdf, xvar))

        name = name if name else 'Cnv_%s' % pdf.name

        ## initialize the base
        PDF.__init__(self, name, xvar)

        em = pdf.pdf.extendMode()
        if 1 == em: self.warning("PDF  ``canBeExtended''")
        elif 2 == em: self.error("PDF ``mustBeExtended''")

        ## make the actual convolution
        self.__cnv = Convolution(name=name,
                                 pdf=self.old_pdf.pdf,
                                 xvar=xvar,
                                 resolution=resolution,
                                 useFFT=useFFT,
                                 nbins=nbins,
                                 buffer=buffer,
                                 nsigmas=nsigmas)

        self.pdf = self.__cnv.pdf

        ## save configuration
        self.config = {
            'name': self.name,
            'xvar': self.xvar,
            'pdf': self.old_pdf,
            'resolution': self.cnv.resolution,
            'useFFT': self.cnv.useFFT,
            'nbins': self.cnv.nbinsFFT,
            'buffer': self.cnv.buffer,
            'nsigmas': self.cnv.nsigmas,
        }
Exemplo n.º 4
0
    def __init__(
        self,
        name,  ## the name 
        pdf,  ## the PDF to be convoluted 
        resolution,  ## the resolution
        xvar=None,  ## the axis varable
        useFFT=True,  ## use  FastFourierTransform?
        nbins=1000000,  ## #bins for FFT
        buffer=0.25,  ## buffer fraction ## setBufferFraction
        nsigmas=6):  ## number of sigmas for setConvolutionWindow

        if isinstance(pdf, PDF):
            xvar = pdf.xvar
        elif isinstance(pdf, ROOT.RooAbsPdf) and isinstance(
                xvar, ROOT.RooAbsReal):
            pdf = Generic1D_pdf(pdf, xvar)
        else:
            raise AttributeError("Convolution_pdf: invalid pdf/xvar    %s/%s" %
                                 (pdf, xvar))

        ## initialize the base
        PDF.__init__(self, name, xvar)

        ## make the actual convolution
        self.__cnv = Convolution(name=name,
                                 pdf=pdf,
                                 xvar=xvar,
                                 resolution=resolution,
                                 useFFT=useFFT,
                                 nbins=nbins,
                                 buffer=buffer,
                                 nsigmas=nsigmas)

        self.pdf = self.__cnv.pdf

        ## save configuration
        self.config = {
            'name': self.name,
            'xvar': self.xvar,
            'pdf': self.cnv.old_pdf,
            'resolution': self.cnv.resolution,
            'useFFT': self.cnv.useFFT,
            'nbins': self.cnv.nbinsFFT,
            'buffer': self.cnv.buffer,
            'nsigmas': self.cnv.nsigmas,
        }
Exemplo n.º 5
0
    def __init__(self, pdf, xvar=None, fraction=1.e-5, name=''):

        if isinstance(pdf, PDF):
            self.__old_pdf = pdf
            if xvar and not xvar is pdf.xvar: self.warning("mismatch in xvar?")
            xvar = pdf.xvar
        elif insinstance(pdf, ROOT.RooAbsPdf) and xvar:
            self.__old_pdf = Generic1D_pdf(pdf, xvar=xvar)
        else:
            raise TypeError("Unknown type of pdf %s/%s" % (pdf, type(pdf)))

        assert isinstance(xvar,
                          ROOT.RooAbsReal), "``xvar'' must be ROOT.RooAbsReal"

        name = name if name else self.generate_name('Adjust1D_' +
                                                    self.old_pdf.name)

        ## initialize the base
        PDF.__init__(self, name=name, xvar=xvar)

        em = self.old_pdf.pdf.extendMode()
        if 1 == em: self.warning("PDF  ``canBeExtended''")
        elif 2 == em: self.warning("PDF ``mustBeExtended''")

        ## make the real adjustment
        self.__adjustment = Adjust1D(name,
                                     pdf=self.old_pdf.pdf,
                                     xvar=xvar,
                                     fraction=fraction)

        self.pdf = self.adjustment.pdf

        self.config = {
            'xvar': self.xvar,
            'name': self.name,
            'pdf': self.old_pdf,
            'fraction': self.fraction
        }
Exemplo n.º 6
0
    def __init__(
            self,
            pdf,
            dataset=None,
            fitresult=None,
            fast=True,  ## fast histogram filling ? (bin centers)
            nbins=100,  ## histogram bining 
            access={},  ## historgam access options 
            fitopts={}):  ## PDF.fitTo options

        assert dataset or fitresult, 'Either dataset or fitresult must be specified!'

        assert isinstance ( pdf     , PDF              ) and \
               isinstance ( pdf.pdf , ROOT.RooAddPdf   ) and \
               len ( pdf.alist1 ) ==  len ( pdf.alist2 )     , 'Invalid type of PDF!'

        cmps = pdf.alist2
        names = [c.name for c in cmps]

        ## if  datset is specified - perform the fit
        if dataset:

            vars = pdf.pdf.getParameters(dataset)

            ## make a proper (re)fit fixing everything  but yields
            with FIXVAR([v for v in vars if not v in cmps]):
                fitresult, f = pdf.fitTo(dataset,
                                         silent=True,
                                         draw=False,
                                         **fitopts)

        elif fitresult:

            pars = fitresult.floatParsFinal()
            pnames = set([p.name for p in pars])

            if set(names) != pnames:
                raise RuntimeError("Rerun fit with with only %s floating " %
                                   names)

        ## temlate historgam
        template = pdf.make_histo(nbins)

        ## dictionary of components
        hcomponents = {}

        ## the list of PDFs
        cpdfs = [Generic1D_pdf(p, xvar=pdf.xvar) for p in pdf.alist1]

        for p, n in zip(cpdfs, names):

            if fast: hc = p.roo_histo(histo=template, events=False)
            else: hc = p.histo(histo=template, errors=False)

            ## ## convert to density historgam ?
            ## hc   =  hc.density()

            hcomponents[n] = hc

        ## sum of all histograms
        hsum = template.clone()
        hsum.Reset()
        hsum.Sumw2()

        for k in hcomponents:
            hsum += hcomponents[k] * fitresult(k)[0].value()

        hweights = {}
        l = len(names)
        for i in range(l):

            cmp = template.clone()
            cmp.Reset()
            cmp.Sumw2()
            for j in range(l):
                cmp += fitresult.cov(names[i],
                                     names[j]) * hcomponents[names[j]]

            cmp /= hsum
            hweights[names[i]] = cmp

        del hsum
        del template

        components = {}
        for k in hcomponents:
            components[k] = Histo1DFun(hcomponents[k], **access)

        weights = {}
        for k in hweights:
            weights[k] = Histo1DFun(hweights[k], **access)

        self.__hcomponents = hcomponents
        self.__components = components
        self.__hweights = hweights
        self.__weights = weights
Exemplo n.º 7
0
def test_PyPdf_AI() :
    """Test pure python PDF: pyPDF
    - For *NEW* PyROOT only!
    - see Ostap.Models.PyPdf 
    """

    logger = getLogger("test_PyPdf_AI")
    
    if old_PyROOT :
        logger.warning("test enabled only for NEW PyROOT!")
        return
    
    logger.info  ("Test pure python PDF: PyPdf with analytical  integral")

    # =============================================================================
    ## @class PyGauss
    #  local ``pure-python'' PDF 
    class MyGauss(Ostap.Models.PyPdf) :
        """Local ``pure-python'' PDF
        """    
        def __init__ ( self , name , xvar , mean , sigma ) :
            
            vars = ROOT.RooArgList()
            
            vars.add ( xvar  )
            vars.add ( mean  )
            vars.add ( sigma )
            
            super(MyGauss,self).__init__ ( name , 'title' , vars )
            
        ## the  main method 
        def evaluate ( self ) :
            
            x = self.variable ( 0 ) 
            m = self.variable ( 1 )  
            s = self.variable ( 2 )
            
            dx = ( x - m ) / s        
            return math.exp ( -0.5 * dx * dx ) * NORM / s 

        def clone ( self , newname ) :

            name = newname if newname else self.name
            
            vlist = self.variables() 
            
            xvar  = vlist[0]  
            mean  = vlist[1]
            sigma = vlist[2] 

            cl = MyGauss( name , xvar , mean , sigma ) 
            ROOT.SetOwnership ( cl  , False )
            
            return cl
        
        ## declare analytical integral 
        def get_analytical_integral ( self ) :
            """Declare the analytical integral"""
            
            x  = self.variables()[0]
            
            if self.matchArgs ( x ) : return 1 ## get the integration code
            
            return 0
        
        ## calculate the analytical integral 
        def analytical_integral ( self ) :
            """Calculate the analytical integral"""
            
            assert 1 == self.intCode () , 'Invalid integration code!'
            
            vlist = self.variables() 
            
            rn    = self.rangeName()        
            xv    = vlist [ 0 ]        
            xmax  = xv.getMax ( rn )
            xmin  = xv.getMin ( rn )
            
            m     = float ( vlist [ 1 ] ) 
            s     = float ( vlist [ 2 ] )        
            
            return CDF ( xmax , m , s  ) - CDF ( xmin , m , s  )

    with timing ("Using-PyPdf+AI", logger ) :

        pdf.mean  = random.gauss ( 3.100 , 0.010 )
        pdf.sigma = random.gauss ( 0.012 , 0.001 )

        pdf_  = MyGauss ( 'MyGauss' , pdf.xvar , pdf.mean , pdf.sigma )
        gauss = Generic1D_pdf  ( pdf_ , xvar = pdf.xvar )
        
        ## build fit model 
        model = Fit1D ( signal = gauss , background = None  , name = 'M3' )
        
        ##  fit!
        r, _ = model  .fitTo ( dataset , draw = False , silent = True , ncpu=1 )
        with wait ( 1 ) , use_canvas ( "test_PyPdf_AI" ) : 
            r, f = model  .fitTo ( dataset , draw = True  , silent = True , ncpu=1 )            
            logger.info  ("Fit result for``pure python'' PDF: PyPdf with analytical integral\n%s" % r.table ( prefix = "# " ) )
Exemplo n.º 8
0
def test_PyPdf() :
    """Test pure python PDF: pyPDF
    - For *NEW* PyROOT only!
    - see Ostap.Models.PyPdf 
    """

    logger = getLogger("test_PyPdf")
    
    if old_PyROOT :
        logger.warning("test enabled only for NEW PyROOT!")
        return
    
    logger.info  ("Test pure python PDF: PyPdf ")

    # =============================================================================
    ## @class PyGauss
    #  local ``pure-python'' PDF 
    class MyGauss(Ostap.Models.PyPdf) :
        """Local ``pure-python'' PDF
        """    
        def __init__ ( self , name , xvar , mean , sigma ) :
            
            vars = ROOT.RooArgList()
            
            vars.add ( xvar  )
            vars.add ( mean  )
            vars.add ( sigma )
            
            super(MyGauss,self).__init__ ( name , 'title' , vars )
            
        ## the  main method 
        def evaluate ( self ) :
            
            vlist = self.varlist
            
            x = self.variable ( 0 ) 
            m = self.variable ( 1 )  
            s = self.variable ( 2 )
            
            dx = ( x - m ) / s        
            return math.exp ( -0.5 * dx * dx ) * NORM / s 

        def clone ( self , newname ) :

            name = newname if newname else self.name
            
            vlist = self.variables() 
            
            xvar  = vlist[0]  
            mean  = vlist[1]
            sigma = vlist[2] 

            cl = MyGauss( name , xvar , mean , sigma ) 
            ROOT.SetOwnership ( cl  , False )
            
            return cl
        
    with timing ("Using-PyPdf", logger ) :

        pdf.mean  = random.gauss ( 3.100 , 0.010 )
        pdf.sigma = random.gauss ( 0.012 , 0.001 )

        pdf_  = MyGauss ( 'MyGauss' , pdf.xvar , pdf.mean , pdf.sigma )
        gauss = Generic1D_pdf  ( pdf_ , xvar = pdf.xvar )
                
        ## build fit model 
        model = Fit1D ( signal = gauss , background = None  , name = 'M3' )
        
        ##  fit!
        r, _ = model  .fitTo ( dataset , draw = False , silent = True , ncpu=1 )
        with wait ( 1 ) , use_canvas ( "test_PyPdf" ) : 
            r, f = model  .fitTo ( dataset , draw = True  , silent = True , ncpu=1 )        
            logger.info  ("Fit result for``pure python'' PDF: PyPdf \n%s" % r.table ( prefix = "# " ) )
Exemplo n.º 9
0
    def __init__(self,
                 pdf1,
                 pdf2,
                 xvar=None,
                 name='',
                 title='',
                 use_roo=True):  ## UseRooFit or Ostap for product?

        self.__pdf__1 = pdf1
        self.__pdf__2 = pdf2

        self.__pdf1 = None
        self.__pdf2 = None

        if isinstance(pdf1, PDF):
            self.__pdf1 = pdf1
            if xvar and not (xvar is pdf1.xvar):
                self.error("Mismatch in ``xvar''-observable (1) %s/%s" %
                           (xvar, pdf1.xvar))
            elif not xvar:
                xvar = pdf1.xvar
        elif isinstance(pdf1, ROOT.RooAbsPdf) and xvar:
            self.__pdf1 = Generic1D_pdf(pdf1, xvar)
        else:
            raise TypeError("Illegal setting for ``pdf1'': %s/%s" %
                            (pdf1, type(pdf1)))

        assert isinstance(self.__pdf1, PDF), 'Invalid pdf1 type'

        if isinstance(pdf2, PDF):
            self.__pdf2 = pdf2
            if xvar and not (xvar is pdf2.xvar):
                self.error("Mismatch in ``xvar''-observable (2) %s/%s" %
                           (xvar, pdf2.xvar))
            elif not xvar:
                xvar = pdf2.xvar
        elif isinstance(pdf2, ROOT.RooAbsPdf) and xvar:
            self.__pdf2 = Generic1D_pdf(pdf2, xvar)
        else:
            raise TypeError("Illegal setting for ``pdf2'': %s/%s" %
                            (pdf2, type(pdf1)))

        assert isinstance(self.__pdf2, PDF), 'Invalid pdf2 type'

        assert isinstance ( xvar , ROOT.RooAbsReal ),\
               "Invalid ``xvar'':%s/%s" % ( xvar , type  ( xvar ) )

        name = name if name else self.generate_name(
            prefix="product_%s_%s_" % (self.pdf1.name, self.pdf2.name))

        ## initialize the base class
        PDF.__init__(self, name, xvar=xvar)

        em1 = self.pdf1.pdf.extendMode()
        em2 = self.pdf2.pdf.extendMode()

        if 2 == em1: self.warning("pdf1 ``must-be-extended''")
        elif 1 == em1: self.warning("pdf1  ``can-be-extended''")

        if 2 == em2: self.warning("pdf2 ``must-be-extended''")
        elif 1 == em2: self.warning("pdf2  ``can-be-extended''")

        self.__use_roo = True if use_roo else False

        ## finally build PDF

        PDFTYPE = ROOT.RooProdPdf if self.use_roo else Ostap.MoreRooFit.ProductPdf

        self.pdf = PDFTYPE(
            self.roo_name('prod1_'),
            title if title else 'Product of two pdfs %s' % self.name,
            self.pdf1.pdf, self.pdf2.pdf)

        ## save configuration for cloning
        self.config = {
            'pdf1': self.pdf1,
            'pdf2': self.pdf2,
            'xvar': self.xvar,
            'name': self.name,
            'title': self.title,
            'use_roo': self.use_roo,
        }
Exemplo n.º 10
0
    def __init__(self,
                 pdf,
                 power=1,
                 xvar=None,
                 name='',
                 xmin=None,
                 xmax=None,
                 title='',
                 use_roo=True):

        assert isinstance ( power , int ) and 0 <= power,\
               "Invalid ``power''   %s" % power

        self.__pdf_1 = pdf

        if isinstance(pdf, PDF):
            if xvar and not (xvar is pdf.xvar):
                self.error("Mismatch in ``xvar''-observable")
            elif not xvar:
                xvar = pdf.xvar
        elif isinstance(pdf, ROOT.RooAbsPdf) and xvar:
            pdf = Generic1D_pdf(pdf, xvar)
        else:
            raise TypeError("Illegal setting for ``pdf'': %s/%s" %
                            (pdf, type(pdf)))

        assert isinstance ( xvar , ROOT.RooAbsReal ),\
               "Invalid ``xvar'':%s/%s" % ( xvar , type  ( xvar ) )

        name = name if name else self.generate_name(prefix="modify_%s_%s" %
                                                    (pdf.name, power))

        from ostap.fitting.background import PolyPos_pdf
        pdf2 = PolyPos_pdf(self.generate_name('M_%s_%s' % (pdf.name, power)),
                           xvar=xvar,
                           power=power,
                           xmin=xmin,
                           xmax=xmax)

        self.__pdf_2 = pdf2

        ## initialize the base
        Product1D_pdf.__init__(self,
                               pdf1=pdf,
                               pdf2=pdf2,
                               xvar=xvar,
                               name=name,
                               title=title,
                               use_roo=use_roo)

        ## for drawing...

        for c in self.pdf1.signals:
            self.signals.add(c)
        for c in self.pdf1.backgrounds:
            self.backgrounds.add(c)
        for c in self.pdf1.components:
            self.components.add(c)
        for c in self.pdf1.crossterms1:
            self.crossterms1.add(c)
        for c in self.pdf1.crossterms2:
            self.crossterms2.add(c)

        self.config = {
            'name': self.name,
            'pdf': self.pdf1,
            'xvar': self.xvar,
            'power': power,
            'xmin': xmin,
            'xmax': xmin,
            'title': self.title,
            'use_roo': self.use_roo
        }
Exemplo n.º 11
0
    def __init__ ( self             ,
                   pdf              ,   ## the PDF to be convoluted 
                   resolution       ,   ## the convolution/resolution
                   xvar     = None  ,   ## the axis varable
                   useFFT   = True  ,   ## use  FastFourierTransform?
                   nbins    = 2**14 ,   ## #bins for FFT
                   buffer   = 0.25  ,   ## buffer fraction ## setBufferFraction
                   bufstrat = None  ,   ## "Buffer strategy" : (0,1,2)
                   nsigmas  = 6     ,   ## number of sigmas for setConvolutionWindow
                   name     = ''    ) : ## the name 

        self.__arg_pdf        = pdf
        self.__arg_resolution = resolution 
        self.__arg_xvar       = xvar
        
        if   isinstance ( pdf , PDF ) :
            self.__old_pdf = pdf 
            xvar           = pdf.xvar
        elif isinstance ( pdf , ROOT.RooAbsPdf ) and xvar :
            self.__old_pdf = Generic1D_pdf  ( pdf , xvar )
        else :
            raise AttributeError ("Convolution_pdf: invalid pdf/xvar %s/%s"  % ( pdf , xvar ) ) 

        em = self.old_pdf.pdf.extendMode ()
        if   1 == em : self.warning ( "PDF  ``canBeExtended''" )
        elif 2 == em : self.error   ( "PDF ``mustBeExtended''" )

        ## make the actual convolution
        if isinstance ( resolution , Convolution ) :
            assert resolution.xvar is xvar, "Mismatch in ``xvar'': %s vs %s" % ( xvar , resolution.xvar )
            self.__cnv = resolution
        else :
            self.__cnv = Convolution ( name       = ''               ,
                                       pdf        = self.old_pdf.pdf ,
                                       xvar       = xvar             ,
                                       resolution = resolution       ,
                                       useFFT     = useFFT           ,
                                       nbins      = nbins            ,
                                       buffer     = buffer           ,
                                       bufstrat   = bufstrat         ,
                                       nsigmas    = nsigmas          )

        name = name if name else self.generate_name ( prefix = 'Cnv_%s@%s_' %  ( pdf.name , self.resolution.name ) ) 
                            
        ## initialize the base 
        PDF.__init__ ( self , name , xvar )


        ## the  actual convoluted PDF 
        self.pdf = self.__cnv.pdf 

        ## save configuration 
        self.config = {
            'name'       : self.name           ,
            'xvar'       : self.xvar           ,
            'pdf'        : self.old_pdf        ,
            'resolution' : self.cnv.resolution ,
            'useFFT'     : self.cnv.useFFT     ,
            'nbins'      : self.cnv.nbinsFFT   ,
            'buffer'     : self.cnv.buffer     ,
            'bufstrat'   : self.cnv.bufstrat   ,
            'nsigmas'    : self.cnv.nsigmas    ,
            }
Exemplo n.º 12
0
    def __init__(self, sample, categories, xvar=None, name=None, title=''):

        if isinstance(sample, (tuple, list)):
            _cat = ROOT.RooCategory('sample', 'sample')
            for i in sample:
                _cat.defineType(i)
            sample = _cat

        assert isinstance ( sample , ROOT.RooCategory ),\
               'Invalid type for "sample":' % ( sample ,  type ( sample ) )

        if not name: name = 'SimFit_' + sample.GetName()
        if not title:
            title = 'Simultaneous PDF(%s,%s)' % (name, sample.GetName())

        self.__sample = sample
        self.__categories = {}

        # =====================================================================
        ## components
        # =====================================================================
        labels = sample.labels()

        _xvar = xvar
        for label in labels:

            cmp = None
            if isinstance(categories, dict): cmp = categories[label]
            else:
                for ii in categories:
                    if ii[0] == label:
                        cmp = ii[1]
                        break

            if isinstance(cmp, PDF):

                _xv = cmp.xvar
                if _xvar and not (_xvar is _xv):
                    self.error('Mismatch in XVAR!')
                elif not _xvar:
                    _xvar = _xv

                self.__categories[label] = cmp

            elif isinstance(cmp, ROOT.RooAbsPdf) and _xvar:

                self.__categories[label] = Generic1D_pdf(pdf=cmp, cmp=_xvar)

            else:

                raise TypeError('Can not find the category "%s"' % label)

        # =====================================================================
        assert _xvar, 'Unable to define "xvar"'

        ## initialize the base
        PDF.__init__(self, name, xvar=_xvar)

        self.pdf = ROOT.RooSimultaneous('sim_' + self.name, title, self.sample)

        cats = self.categories
        for key in cats:
            self.pdf.addPdf(cats[key].pdf, key)
        keys = cats.keys()
        keys.sort()
        del cats

        for k, pdf in self.categories.iteritems():

            for c in pdf.signals:
                self.signals.add(c)
            for c in pdf.backgrounds:
                self.backgrounds.add(c)
            for c in pdf.crossterms1:
                self.crossterms1.add(c)
            for c in pdf.crossterms2:
                self.crossterms2.add(c)

        self.config = {
            'name': self.name,
            'title': title,
            'sample': self.sample,
            'categories': self.categories,
            'xvar': self.xvar,
        }
Exemplo n.º 13
0
    def __init__(
        self,
        name,
        pdf,  ## the PDF to be convoluted 
        xvar,  ## the axis variable
        resolution,  ## the    resolution
        useFFT=True,  ## use FFT ? 
        nbins=1000000,  ##  #bins for FFT
        buffer=0.25,  ## buffer fraction ## setBufferFraction
        nsigmas=6):  ## number of sigmas for setConvolutionWindow

        ## the axis
        assert isinstance(xvar,
                          ROOT.RooAbsReal), "``xvar'' must be ROOT.RooAbsReal"
        self.__xvar = xvar
        self.__useFFT = True if useFFT else False

        ## pdf itself
        if isinstance(pdf, PDF): self.__old_pdf = pdf
        elif isinstance(pdf, ROOT.RooAbsPdf):
            self.__old_pdf = Generic1D_pdf(pdf, xvar=self.__xvar)
        else:
            raise AttributeError("Convolution: invalid ``pdf'' %s/%s" %
                                 (pdf, type(pdf)))

        ## resolution  function
        if isinstance(resolution, PDF): self.__resolution = resolution
        elif isinstance(resolution, ROOT.RooAbsPdf):
            self.__resolution = Generic1D_pdf(resolution, xvar=self.__xvar)
        else:
            ## use   Gaussial resolution
            import ostap.fitting.resolution as OFR
            self.__resolution = OFR.ResoGauss('ResoGauss' + name,
                                              self.__xvar,
                                              sigma=resolution,
                                              mean=None)

        self.__nbins = nbins
        self.__buffer = buffer
        self.__nsigmas = nsigmas

        if self.useFFT:  ## Use Fast Fourier transform  (fast)

            assert isinstance ( nbins  , (long,int) ) and 100  < nbins          , \
                   "Invalid ``nbins''  parameter  %s/%s for fast Fourier transform"  % ( nbins  , type ( nbins  ) )
            assert isinstance ( buffer ,  float     ) and 0.1  < buffer < 0.9   , \
                   "Invalid ``buffer'' parameter  %s/%s for ``setBufferFraction''"     % ( buffer , type ( buffer ) )

            if hasattr(self.__resolution, 'sigma') and self.__xvar.minmax():
                mn, mx = xvar.minmax()
                dm = mx - mn
                sv = self.__resolution.sigma.getVal()
                dm /= sv
                self.__nbins = max(self.__nbins, 100 * int(dm))
                logger.debug('Convolution: choose #bins %d' % self.__nbins)

            self.__xvar.setBins(self.__nbins, 'cache')

            self.__pdf = ROOT.RooFFTConvPdf('FFT' + name, 'FFT(%s)' % name,
                                            self.__xvar, self.__old_pdf.pdf,
                                            self.__resolution.pdf)
            self.__pdf.setBufferFraction(0.25)

        else:  ##  Use plain numerical integration (could be slow)


            assert isinstance ( nsigmas  , ( long , int , float ) ) and 2 < nsigmas , \
                   "Invalid ``nsigmas''  parameter  %s/%s for ``setConvolutionWindow''"  % ( nsigmas , type ( nsigmas ) )

            self.__pdf = ROOT.RooNumConvPdf('CNV' + name, 'CNV(%s)' % name,
                                            self.__xvar, self.__old_pdf.pdf,
                                            self.__resolution.pdf)

            if hasattr(self.__resolution, 'sigma'):
                if hasattr(self.__resolution, 'mean'):
                    self.__pdf.setConvolutionWindow(self.__resolution.mean,
                                                    self.__resolution.sigma,
                                                    self.__nsigmas)
                    logger.debug('Convolution: choose window of %s' %
                                 self.__nsigmas)
Exemplo n.º 14
0
    def __init__(self, pdf1, pdf2, xvar=None, name='', title=''):

        self.__pdf__1 = pdf1
        self.__pdf__2 = pdf2

        self.__pdf1 = None
        self.__pdf2 = None

        if isinstance(pdf1, PDF):
            self.__pdf1 = pdf1
            if xvar and not (xvar is pdf1.xvar):
                self.error("Mismatch in ``xvar''-observable")
            elif not xvar:
                xvar = pdf1.xvar
        elif isinstance(pdf1, ROOT.RooAbsPdf) and xvar:
            self.__pdf1 = Generic1D_pdf(pdf1, xvar)
        else:
            raise TypeError("Illegal setting for ``pdf1'': %s/%s" %
                            (pdf1, type(pdf1)))

        assert isinstance(self.__pdf1, PDF), 'Invalid pdf1 type'

        if isinstance(pdf2, PDF):
            self.__pdf2 = pdf2
            if xvar and not (xvar is pdf2.xvar):
                self.error("Mismatch in ``xvar''-observable")
            elif not xvar:
                xvar = pdf2.xvar
        elif isinstance(pdf2, ROOT.RooAbsPdf) and xvar:
            self.__pdf2 = Generic1D_pdf(pdf2, xvar)
        else:
            raise TypeError("Illegal setting for ``pdf2'': %s/%s" %
                            (pdf2, type(pdf1)))

        assert isinstance(self.__pdf2, PDF), 'Invalid pdf2 type'

        assert isinstance ( xvar , ROOT.RooAbsReal ),\
               "Invalid ``xvar'':%s/%s" % ( xvar , type  ( xvar ) )

        if not name: name = "product_%s_%s" % (self.pdf1.name, self.pdf2.name)
        if not title:
            title = "Product(%s,%s)" % (self.pdf1.name, self.pdf2.name)

        ## initialize the base class
        PDF.__init__(self, name, xvar=xvar)

        em1 = self.pdf1.pdf.extendMode()
        em2 = self.pdf2.pdf.extendMode()

        if 2 == em1: self.warning("pdf1 ``must-be-extended''")
        elif 1 == em1: self.warning("pdf1  ``can-be-extended''")

        if 2 == em2: self.warning("pdf2 ``must-be-extended''")
        elif 1 == em2: self.warning("pdf2  ``can-be-extended''")

        ## finally build PDF
        self.pdf = ROOT.RooProdPdf(name, title, self.pdf1.pdf, self.pdf2.pdf)

        ## save configuration for cloning
        self.config = {
            'pdf1': self.pdf1,
            'pdf2': self.pdf2,
            'xvar': self.xvar,
            'name': self.name,
            'title': self.title,
        }
Exemplo n.º 15
0
    def __init__ ( self              ,
                   sample            , 
                   categories        ,
                   name       = None , 
                   title      = ''   ) :
        """Helper pdf-like class to simplify the creation and usage of simultaneous PDF
        
        >>> sample = ROOT.RooCategory( 'sample', 'fitting sample' , 'A' , 'B' )
        >>> pdfA   = ... ## pdf for the sample 'A'
        >>> pdfB   = ... ## pdf for the sample 'B'
        >>> simfit = SimFit (  sample , { 'A' : pdfA , 'B' : pdfB } )
        """
        
        if isinstance ( sample , ( tuple , list ) ) :
            _cat = ROOT.RooCategory ( 'sample' , 'sample' )
            for i in sample : _cat.defineType ( i ) 
            sample =  _cat
            
        assert isinstance ( sample , ROOT.RooCategory ),\
               'Invalid type for "sample":' % ( sample ,  type ( sample ) )
        
        if not name  : name  = 'SimFit_'                 +          sample.GetName()
        if not title : title = 'Simultaneous PDF(%s,%s)' % ( name , sample.GetName() )

        ## propagatethe name 
        self.name = name
        
        self.__sample       = sample 
        self.__categories   = {}

        # =====================================================================
        ## components
        # =====================================================================
        labels = sample.labels()

        from ostap.fitting.basic import PDF 
        from ostap.fitting.fit2d import PDF2
        from ostap.fitting.fit3d import PDF3

        _xv = None 
        for label in labels :
            
            cmp   = None 
            if isinstance ( categories , dict ) : cmp = categories [ label ]
            else :
                for ii in categories :
                    if ii[0] == label :
                        cmp = ii[1]
                        break

            if not isinstance  ( cmp , PDF  ) :
                raise TypeError ( 'Can not find the proper category component: "%s"' % label ) 
            
            self.__categories [ label ] = cmp
            _xv = cmp.xvar
            
        sim_pdf     = PDF ( self.name , xvar = _xv )
        sim_pdf.pdf = ROOT.RooSimultaneous ( 'Sim_' + self.name , title , self.sample )
        
        keys = self.categories.keys()
        for key in sorted ( keys ) :
            sim_pdf.pdf.addPdf ( self.categories[key].pdf , key )

        self.__pdf = sim_pdf 
        
        for k , cmp in items_loop ( self.categories ) :
            
            for c in cmp.signals      : self.pdf.signals    .add ( c ) 
            for c in cmp.backgrounds  : self.pdf.backgrounds.add ( c ) 
            for c in cmp.crossterms1  : self.pdf.crossterms1.add ( c ) 
            for c in cmp.crossterms2  : self.pdf.crossterms2.add ( c )
            
            self.pdf.draw_options.update ( cmp.draw_options )
            
        # =====================================================================
        ##  drawing helpers
        # =====================================================================
        
        self.__drawpdfs   = {}
        for key in sorted ( keys ) :

            cmp = self.categories [ key ] 
            if isinstance  ( cmp , PDF3 ) :
                from ostap.fitting.fit3d import Generic3D_pdf                
                dpdf = Generic3D_pdf ( sim_pdf.pdf ,
                                       cmp.xvar    ,
                                       cmp.yvar    ,
                                       cmp.zvar    ,
                                       add_to_signals = False )
            elif isinstance  ( cmp , PDF2 ) :
                from ostap.fitting.fit2d import Generic2D_pdf                                
                dpdf = Generic2D_pdf ( sim_pdf.pdf ,
                                       cmp.xvar    ,
                                       cmp.yvar    ,
                                       add_to_signals = False )
            elif isinstance  ( cmp , PDF  ) :
                from ostap.fitting.basic import Generic1D_pdf   
                dpdf = Generic1D_pdf ( sim_pdf.pdf ,
                                       cmp.xvar    ,
                                       add_to_signals = False )
                
            for c in cmp.signals     : dpdf.signals    .add ( c ) 
            for c in cmp.backgrounds : dpdf.backgrounds.add ( c ) 
            for c in cmp.crossterms1 : dpdf.crossterms1.add ( c ) 
            for c in cmp.crossterms2 : dpdf.crossterms2.add ( c )


            dpdf.draw_options.update ( cmp.draw_options )
                        
            self.__drawpdfs [ key ]  = dpdf

        self.config = {
            'name'       : self.name       ,
            'title'      : title           ,            
            'sample'     : self.sample     ,
            'categories' : self.categories ,
            }
Exemplo n.º 16
0
    def __init__ ( self                ,
                   name                , ## PDF name 
                   pdfs                , ## dictionary {mu1,mu2 -> pdf }
                   setting    = None   , ## morphing setting 
                   morph_var1 = None   , ## morphing variable mu1 
                   morph_var2 = None   , ## morphing variable mu1 
                   xvar       = None ) : ## observable (1D) 

        assert pdfs and 2 <= len ( pdfs ) , \
               "Invalid dictionary of morphing PDFs!"
        
        if setting is None : setting = ROOT.RooMomentMorphND.Linear 

        assert isinstance ( setting , integer_types ) and 0 <= setting < 5,\
               'Invalid value for the setting %s/%s' %  ( setting , type ( setting ) )

        v1ps = set ()
        v2ps = set () 
        
        for k in pdfs :
            v1 , v2 = k
            v1ps.add ( v1 )
            v2ps.add ( v2 )
            p = pdfs [ k ]
            if not xvar and isinstance ( p , PDF ) :
                xvar = p.xvar

        assert xvar and isinstance ( xvar , ROOT.RooAbsReal ) , 'Cannot deduce xvar!'

        assert 2 <= len ( v1ps ) and 2 <= len ( v2ps ) , 'Invalid number of bins!'

        v1ps = list ( v1ps ) 
        v2ps = list ( v2ps )

        v1ps.sort ()
        v2ps.sort ()

        assert  len ( pdfs ) ==  len ( v1ps ) * len ( v2ps ) ,\
               'Invalid table/dict structure!'
        
        ## initialize the base class 
        PDF.__init__ ( self , name , xvar )

        ## create morphing variables 
        self.__mu1 = self.make_var (
            morph_var1                ,
            "mu1_%s"           % name ,
            "morphing mu1(%s)" % name , morph_var1 , v1ps[0] , v1ps[-1] )
        
        ## create morphing variables 
        self.__mu2 = self.make_var (
            morph_var2                ,
            "mu2_%s"           % name ,
            "morphing mu2(%s)" % name , morph_var2 , v2ps[0] , v2ps[-1] )
        
        self.__pdfdict = {}
        for k in sorted ( pdfs.keys()  ) :

            v1 , v2 = k
            
            pdfk = pdfs [ k ] 
            if   isinstance ( pdfk , PDF            ) and pdfk.xvar is self.xvar : pass 
            elif isinstance ( pdfk , ROOT.RooAbsPdf ) : 
                pdfk = Generic1D_pdf ( pdfk , xvar = self.xvar ) 
            else :
                raise TypeError( "Invalid component type: %s/%s" % ( pdfk , type ( pdfk ) ) ) 

            pair = k , pdfk 
            self.pdfdict[ ( v1, v2 ) ] = pdfk
            
        ## save setting 
        self.__setting = setting

        
        ## fill morphing grid
        from ostap.fitting.variables import binning
        
        bins_v1     = binning ( v1ps , name = 'morph1' ) 
        bins_v2     = binning ( v2ps , name = 'morph2' ) 
        self.__grid = ROOT.RooMomentMorphND.Grid ( bins_v1 , bins_v2 ) 
        
        for k in self.pdfdict :

            p       = self.pdfdict [ k ]
            
            v1 , v2 = k

            assert v1 in v1ps , 'Morphing2D_pdf: Invalid v1 value %s' % v1 
            assert v2 in v2ps , 'Morphing2D_pdf: Invalid v2 value %s' % v2 
            
            ib1 = v1ps.index ( v1 ) 
            ib2 = v2ps.index ( v2 )
            
            ## ib1 = bins_v1.binNumber ( v1 )
            ## ib2 = bins_v2.binNumber ( v2 )

            self.__grid.addPdf ( p.pdf , ib1 , ib2 )

        morph_vars  = ROOT.RooArgList ( self.mu1 , self.mu2 )
        observables = ROOT.RooArgList ( self.xvar )

        self.aux_keep.append  ( morph_vars  )
        self.aux_keep.append  ( observables )
        
        ## create the PDF  
        self.pdf = ROOT.RooMomentMorphND (
            self.roo_name ( 'morph2_' )   ,
            "Morphing 2D %s" % self.name  , 
            morph_vars              , ## morphing variables 
            observables             , ## observables 
            self.grid               , ## morphing grid 
            self.setting            ) ## morphing setting 

        #
        self.config = {
            'name'       : self.name    ,
            'setting'    : self.setting ,
            'xvar'       : self.xvar    ,
            'morph_var1' : self.mu1     ,
            'morph_var2' : self.mu2     ,
            'pdfs'       : self.pdfdict ,
            }
Exemplo n.º 17
0
    def __init__ ( self                ,
                   name                , ## PDF name 
                   pdfs                , ## dictionary {mu1,mu2 -> pdf }
                   setting    = None   , ## morphing setting 
                   morph_var  = None   , ## morphing variable mu 
                   xvar       = None ) : ## observable (1D) 

        assert pdfs and 2 <= len ( pdfs ) , \
               "Invalid dictionary of morphing PDFs!"

        if setting is None : setting = ROOT.RooMomentMorph.Linear 
            
        assert isinstance ( setting , integer_types ) and 0 <= setting < 5,\
               'Invalid value for the setting %s/%s' %  ( setting , type ( setting ) )

        for k in pdfs :
            if xvar : break
            p = pdfs [ k ]
            if isinstance ( p , PDF ) :
                xvar = p.xvar
                break
        else :
            raise TypeError("Morphing_pdf: cannot identify xvar!")
                
        ## initialize the base class 
        PDF.__init__ ( self , name , xvar )

        ## convert the dictionary of PDFs into  ordered list/tuple of pairs (mu,pdf)        
        self.__pdflist = []
        for k in sorted ( pdfs.keys()  ) :
            
            pdfk = pdfs [ k ]

            if   isinstance ( pdfk , PDF            ) and pdfk.xvar is self.xvar : pass 
            elif isinstance ( pdfk , ROOT.RooAbsPdf ) : 
                pdfk = Generic1D_pdf ( pdfk , xvar = self.xvar ) 
            else :
                pass 

            pair = k , pdfk 
            self.pdflist.append ( pair )
            
        ## convert to tuple 
        self.__pdflist = tuple ( self.__pdflist ) 

        ## save setting 
        self.__setting = setting
        
        ## min and maximal value of morhing parameter
        mu_min = self.pdflist[ 0][0]
        mu_max = self.pdflist[-1][0]

        ## create morphing variable 
        self.__mu = self.make_var (
            morph_var                ,
            "mu_%s"           % name ,
            "morphing mu(%s)" % name , morph_var , mu_min , mu_max )

        ## vector of morphing values 
        muvct  = ROOT.TVectorD ( len ( self.pdflist ) )
        pdflst = ROOT.RooArgList()
        for i , p in enumerate ( self.pdflist ) :
            muvct [ i ] = p [ 0 ]
            pdflst.add (  p [ 1 ].pdf ) 

        observables = ROOT.RooArgList (  self.xvar )
        self.aux_keep.append  ( observables )
        
        ## create the PDF  
        self.pdf = ROOT.RooMomentMorph (
            self.roo_name ( 'morph_' ) ,
            "Morphing %s" % self.name  , 
            self.mu               , ## morphing variable
            observables           , ## observables 
            pdflst                , ## ordered list of PDFs  
            muvct                 , ## values of morhing parameter 
            self.setting          ) ## morphing setting 

        #
        self.config = {
            'name'      : self.name             ,
            'setting'   : self.setting          ,
            'xvar'      : self.xvar             ,
            'morph_var' : self.mu               ,
            'pdfs'      : dict ( self.pdflist ) ,
            }
Exemplo n.º 18
0
    def __init__  ( self              ,
                    name              ,
                    eff_pdf           ,                    
                    eff_fun           ,
                    vars              ,
                    cut               ,
                    accept = 'accept' ,
                    scale  = None     ) :

        self.__name   = str(name)
        self.__cut    = cut
        self.__accept = str(accept) 

        assert eff_pdf or eff_fun ,'Function or PDF must be specified!'
        
        assert isinstance ( cut , ROOT.RooCategory ) , "``Cut'' is not RooCategory!"

        self.__eff_pdf = eff_pdf
        self.__eff_fun = eff_fun
        self.__vars    = ROOT.RooArgSet( *vars )
        
        self.__scale   = 1
        
        if not self.eff_fun :

            if scale is None :
                scale = 0.001 , 1.e-10 , 1.e+5 
                mnmx  = self.eff_pdf.minmax ()
                if mnmx :
                    mn , mx = mnmx
                    scale   = 0.25 / mx , 1.e-9 / mx , 10 / mx
                    
            if   isinstance ( scale , ROOT.RooAbsReal ) :
                self.__scale = scale
            else : 
                self.__scale = ROOT.RooRealVar ( 'effscale_%s' % self.name , 'scale factor for efficiency (%s)' % self.name , *scale )

            self.__lst     = ROOT.RooArgList ( self.__scale , self.__eff_pdf.pdf )
            _s = self.scale.GetName()
            _p = self.eff_pdf.pdf.GetName() 
            self.__eff_fun = ROOT.RooFormulaVar (
                'Eff_%s' % self.name , '%s*%s'  % ( _s , _p ) , self.__lst )

        ## create the main PDF: RooEfficiency 
        self.__pdf =  ROOT.RooEfficiency (
            PDF.roo_name ( 'eff_' )       ,
            "Efficiency  %s"  % self.name ,
            self.eff_fun                  ,
            self.cut                      ,
            self.accept                   )

        if 3 == len ( vars ) : 
            ## pdf-object for fit 
            self.__pdf_fit = Generic3D_pdf ( pdf   = self.pdf ,
                                             xvar  = vars[0]  ,
                                             yvar  = vars[1]  ,
                                             zvar  = vars[2]  ,
                                             name  = PDF.generate_name ( 'eff_fit_%s'   % self.name ) ,
                                             special        = True  ,
                                             add_to_signals = False )
            ## pdf-object for drawing
            self.__pdf_draw = Generic3D_pdf ( pdf   = self.eff_fun   ,
                                              xvar  = vars[0]        ,
                                              yvar  = vars[1]        ,
                                              zvar  = vars[2]        ,
                                              name  = PDF.generate_name ( 'eff_draw_%s'  % self.name ) ,
                                              special        = True  ,
                                              add_to_signals = False )
        elif 2 == len (  vars ) :
            ## pdf-object for fit 
            self.__pdf_fit  = Generic2D_pdf ( pdf   = self.pdf ,
                                              xvar  = vars[0]  ,
                                              yvar  = vars[1]  ,
                                              name  = PDF.generate_name ( 'eff_fit_%s'   % self.name ) ,
                                              special        = True  ,
                                              add_to_signals = False )
            ## pdf-object for drawing
            self.__pdf_draw = Generic2D_pdf ( pdf   = self.eff_fun   ,
                                              xvar  = vars[0]        ,
                                              yvar  = vars[1]        ,
                                              name  = PDF.generate_name ( 'eff_draw_%s'  % self.name ) ,
                                              special        = True  ,
                                              add_to_signals = False )
        elif 1 == len (  vars ) :
            ## pdf-object for fit 
            self.__pdf_fit  = Generic1D_pdf ( pdf   = self.pdf ,
                                              xvar  = vars[0]  ,
                                              name  = PDF.generate_name ( 'eff_fit_%s'   % self.name ) ,
                                              special        = True  ,
                                              add_to_signals = False )
            ## pdf-object for drawing
            self.__pdf_draw = Generic1D_pdf ( pdf   = self.eff_fun   ,
                                              xvar  = vars[0]        ,
                                              name  = PDF.generate_name ( 'eff_draw_%s'  % self.name ) ,
                                              special        = True  ,
                                              add_to_signals = False )
        else :
            raise AttributeError("Invalid length of vars: %s" % str( vars ) )
        
        ## th fit results from the last fit
        self.__fit_result = None
Exemplo n.º 19
0
    def __init__ ( self              ,
                   name              ,
                   pdf               ,   ## the PDF to be convoluted 
                   xvar              ,   ## the axis variable
                   resolution        ,   ## the resolution
                   useFFT   = True   ,   ## use FFT ? 
                   nbins    = 10000  ,   ## number of bins for FFT
                   buffer   = 0.25   ,   ## buffer fraction use for setBufferFraction
                   bufstrat = None   ,   ## "Buffer strategy" : (0,1,2)
                   nsigmas  = 6      ) : ## number of sigmas for setConvolutionWindow

        ## the axis 
        assert isinstance ( xvar , ROOT.RooAbsReal ) , "``xvar'' must be ROOT.RooAbsReal"
        
        self.__xvar   = xvar
        self.__useFFT = True if useFFT else False

        self.__arg_pdf        = pdf
        self.__arg_resolution = resolution
        self.__arg_xvar       = xvar
        
        ## pdf itself 
        if   isinstance ( pdf , PDF            ) : self.__old_pdf = pdf
        elif isinstance ( pdf , ROOT.RooAbsPdf ) :
            self.__old_pdf = Generic1D_pdf ( pdf , xvar = self.__xvar )
        else :
            raise AttributeError("Convolution: invalid ``pdf'' %s/%s"  % ( pdf , type ( pdf ) ) )
        
        ## resolution  function 
        if   isinstance ( resolution , PDF            ) :
            self.__resolution = resolution
        elif isinstance ( resolution , ROOT.RooAbsPdf ) :
            self.__resolution = Generic1D_pdf ( resolution , xvar = self.__xvar ) 
        else :
            ## use   Gaussian resolution
            import ostap.fitting.resolution as OFR
            rname  = ( 'Reso%s_' % name ) if name else 'ResoGauss_'
            rname  = PDF.generate_name ( prefix = rname ) 
            self.__resolution = OFR.ResoGauss ( rname              ,
                                                self.__xvar        ,
                                                sigma = resolution ,
                                                mean  = None       )
        self.__nbins    = nbins
        self.__buffer   = buffer
        self.__bufstrat = bufstrat 
        self.__nsigmas  = nsigmas

        name = name if name else PDF.generate_name ( prefix = 'cnv_%s@%s' % ( pdf.name , self.resolution.name ) )
        
        if self.useFFT : ## Use Fast Fourier transform  (fast)
            
            assert isinstance ( nbins  , integer_types ) and 500   <  abs ( nbins  )  , \
                   "Invalid ``nbins''  parameter %s/%s for fast Fourier transform"  % ( nbins  , type ( nbins  ) )
            assert isinstance ( buffer ,  float        ) and 0.03  <= buffer <=0.9    , \
                   "Invalid ``buffer'' parameter %s/%s for ``setBufferFraction''"   % ( buffer , type ( buffer ) )

            ## adjust #bins if positive. keep it as it is if negavtive 
            if hasattr ( self.__resolution , 'sigma' ) and self.__xvar.minmax() and  self.__nbins > 0 :
                mn , mx = self.xvar.minmax()
                dm  = mx - mn
                sv  = self.__resolution.sigma.getVal() 
                dm /= sv
                nb  = min ( 50 * ( int ( dm ) + 1  ) , 2**14 )
                nb  = 2**math.frexp(nb)[1]
                if nb > self.nbinsFFT : 
                    self.__nbins  = nb       
                    logger.info('Convolution: choose #bins %d' % self.__nbins )

            self.__xvar.setBins ( self.nbinsFFT , 'cache' )

            self.__pdf = ROOT.RooFFTConvPdf (
                PDF.roo_name ( 'fft_' ) ,
                'FFT convolution: %s (*) %s' %  ( pdf.name , self.resolution.name ) ,
                self.__xvar              ,
                self.__old_pdf    .pdf   ,
                self.__resolution .pdf   )            
            self.__pdf.setBufferFraction ( self.buffer )
            
            if isinstance ( self.bufstrat , int ) and 0 <= self.bufstrat <= 2 : 
                self.__pdf.setBufferStrategy ( self.bufstrat )
                
        else :           ##  Use plain numerical integration (could be slow)
            
            assert isinstance ( nsigmas  , num_types ) and 2.5 <= nsigmas , \
                   "Invalid ``nsigmas''  parameter  %s/%s for ``setConvolutionWindow''"  % ( nsigmas , type ( nsigmas ) )
            
            self.__pdf = ROOT.RooNumConvPdf (
                PDF.roo_name ( 'numcnv_' ) ,
                'NUM convolution: %s (*) %s' %  ( pdf.name , self.resolution.name ) ,
                self.__xvar            ,
                self.__old_pdf    .pdf ,
                self.__resolution .pdf )
            
            if hasattr ( self.__resolution , 'sigma' ) :                
                if hasattr ( self.__resolution , 'mean' ) :
                    self.__pdf.setConvolutionWindow ( self.__resolution.mean  ,
                                                      self.__resolution.sigma , self.__nsigmas  )
                    logger.debug('Convolution: choose window of %s' % self.__nsigmas ) 
Exemplo n.º 20
0
    def __init__(
            self,
            name,  ## PDF name 
            pdfs,  ## dictionary {mu1,mu2 -> pdf }
            setting=None,  ## morphing setting 
            morph_var1=None,  ## morphing variable mu1 
            morph_var2=None,  ## morphing variable mu1 
            xvar=None):  ## observable (1D)

        assert pdfs and 2 <= len ( pdfs ) , \
               "Invalid dictionary of morphing PDFs!"

        if setting is None: setting = ROOT.RooMomentMorphND.Linear

        assert isinstance ( setting , integer_types ) and 0 <= setting < 5,\
               'Invalid value for the setting %s/%s' %  ( setting , type ( setting ) )

        v1bins = []
        v2bins = []

        for k in pdfs:
            v1, v2 = k
            v1bins.append(v1)
            v2bins.append(v1)
            p = pdfs[k]
            if not xvar and isinstance(p, PDF):
                xvar = p.xvar

        assert xvar and isinstance(xvar,
                                   ROOT.RooAbsReal), 'Cannot deduce xvar!'

        v1bins.sort()
        v2bins.sort()

        ## initialize the base class
        PDF.__init__(self, name, xvar)

        ## create morphing variables
        self.__mu1 = self.make_var(morph_var1, "mu1_%s" % name,
                                   "morphing mu1(%s)" % name, morph_var1,
                                   v1bins[0], v1bins[-1])

        ## create morphing variables
        self.__mu2 = self.make_var(morph_var2, "mu2_%s" % name,
                                   "morphing mu2(%s)" % name, morph_var2,
                                   v2bins[0], v2bins[-1])

        self.__pdflist = []
        for k in sorted(pdfs.keys()):

            v1, v2 = k

            pdfk = pdfs[k]
            if isinstance(pdfk, PDF) and pdfk.xvar is self.xvar: pass
            elif isinstance(pdfk, ROOT.RooAbsPdf):
                pdfk = Generic1D_pdf(pdfk, xvar=self.xvar)
            else:
                pass

            pair = k, pdfk
            self.pdflist.append(pair)

        ## convert to tuple
        self.__pdflist.sort()
        self.__pdflist = tuple(self.__pdflist)

        ## save setting
        self.__setting = setting

        ## fill morphing grid
        from ostap.fitting.variables import binning

        bins_v1 = binning(v1bins)
        bins_v2 = binning(v2bins)
        self.__grid = ROOT.RooMomentMorphND.Grid(bins_v1, bins_v2)

        for k, p in self.pdflist:

            v1, v2 = k
            ib1 = bins_v1.binNumber(v1)
            ib2 = bins_v2.binNumber(v2)

            self.__grid.addPdf(p.pdf, ib1, ib2)

        morph_vars = ROOT.RooArgList(self.mu1, self.mu2)
        observables = ROOT.RooArgList(self.xvar)

        self.aux_keep.append(morph_vars)
        self.aux_keep.append(observables)

        ## create the PDF
        self.pdf = ROOT.RooMomentMorphND(
            "morph2_%s" % name,
            "morphing2(%s)" % name,
            morph_vars,  ## morphing variables 
            observables,  ## observables 
            self.grid,  ## morphing grid 
            self.setting)  ## morphing setting

        #
        self.config = {
            'name': self.name,
            'setting': self.setting,
            'xvar': self.xvar,
            'morph_var1': self.mu1,
            'morph_var2': self.mu2,
            'pdfs': dict(self.pdflist),
        }