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)
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 )
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, }
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, }
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 }
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
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 = "# " ) )
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 = "# " ) )
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, }
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 }
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 , }
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, }
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)
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, }
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 , }
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 , }
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 ) , }
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
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 )
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), }