From bd32d22e7a9aefd6ef2d2b7c0f6bf1cea7627c74 Mon Sep 17 00:00:00 2001 From: KaTung Lau Date: Sat, 25 Jul 2020 23:48:23 +0200 Subject: [PATCH 01/13] a fitter class to handle mass fit --- .gitignore | 4 + fitter.py | 441 +++++++++++++++++++++++++++++++++++ helper.py | 105 ++++++++- makePlot_fitPeak_unbinned.py | 414 -------------------------------- 4 files changed, 543 insertions(+), 421 deletions(-) create mode 100644 .gitignore create mode 100644 fitter.py delete mode 100644 makePlot_fitPeak_unbinned.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..19fae23 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.root +*.pyc +*.pdf +*.png diff --git a/fitter.py b/fitter.py new file mode 100644 index 0000000..f3a2b8b --- /dev/null +++ b/fitter.py @@ -0,0 +1,441 @@ +#!/usr/bin/env python +from collections import OrderedDict +import root_numpy +import ROOT +from ROOT import RooFit +import numpy as np +ROOT.gROOT.ProcessLine(open('models.cc').read()) +from ROOT import DoubleCBFast +from helper import * +#ROOT.gErrorIgnoreLevel=ROOT.kError +#ROOT.RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) +import matplotlib as mpl +mpl.use('agg') +from matplotlib import pyplot as plt +import atexit + +class fitter(object): + def __init__(self): + self.sig_low = BLIND_LOW + self.sig_up = BLIND_UP + self.fom_low = B_FOM_LOW + self.fom_up = B_FOM_UP + self.fit_low = FIT_LOW + self.fit_up = FIT_UP + self.nbin_data = 50 + self.fit_init = False + + def init_fit_mc(self, drawSNR=False, + sigName="B^{+}#rightarrow K^{+} J/#psi(#rightarrow e^{+}e^{-})", + fit_var='BToKEE_fit_mass', paramOn=True, **kwargs): + + init_dict = {} + init_dict['isMC'] = True + init_dict['drawSNR'] = drawSNR + init_dict['mvaCut'] = None + init_dict['sigName'] = sigName + init_dict['fit_var'] = fit_var + init_dict['paramOn'] = paramOn + init_dict['fit_init'] = True + init_dict['var'] = {} + init_dict['pdf'] = {} + kwargs.update(init_dict) + self.__dict__.update(**kwargs) + + def init_fit_data(self, drawSNR=False, params={}, blinded=False, expS=0.0, + sigName="B^{+}#rightarrow K^{+} J/#psi(#rightarrow e^{+}e^{-})", + fit_var='BToKEE_fit_mass', partialfit={}, mvaCut=0.0, plotBkgUnc=False, **kwargs): + + init_dict = {} + init_dict['isMC'] = False + init_dict['drawSNR'] = drawSNR + init_dict['params'] = params + init_dict['blinded'] = blinded + init_dict['expS'] = expS + init_dict['sigName'] = sigName + init_dict['fit_var'] = fit_var + init_dict['partialfit'] = partialfit + init_dict['mvaCut'] = mvaCut + init_dict['plotBkgUnc'] = plotBkgUnc + init_dict['fit_init'] = True + init_dict['var'] = {} + init_dict['pdf'] = {} + kwargs.update(init_dict) + self.__dict__.update(**kwargs) + + def init_fit_kde(self, pdfname="partial", fit_var='BToKEE_fit_mass', **kwargs): + init_dict = {} + init_dict['isMC'] = True + init_dict['pdfname'] = pdfname + init_dict['fit_var'] = fit_var + init_dict['paramOn'] = False + init_dict['drawSNR'] = False + init_dict['fit_init'] = True + init_dict['var'] = {} + init_dict['pdf'] = {} + kwargs.update(init_dict) + self.__dict__.update(**kwargs) + + def load_tree(self, tree): + self.wspace = ROOT.RooWorkspace('myWorkSpace') + thevars = ROOT.RooArgSet() + Mass = ROOT.RooRealVar(self.fit_var, "m(K^{+}e^{+}e^{-})", self.fit_low, self.fit_up, "GeV") + + thevars.add(Mass) + + self.fulldata = ROOT.RooDataSet('fulldata', 'fulldata', tree, ROOT.RooArgSet(thevars)) + theMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(Mass)) + self.mass = self.fulldata.addColumn(theMassfunc) + self.mass.setRange(self.fit_low, self.fit_up) + thevars.add(self.mass) + + cut = '' + + self.data = self.fulldata.reduce(thevars, cut) + getattr(self.wspace,'import')(self.data, RooFit.Rename("data")) + # When a RooWorkspace is set as an attribute of a class, it can trigger a memory error + # This is solved in the latest ROOT version > 6.14.08 + atexit.register(self.wspace.Delete) + + def setup_model_sig(self): + self.wspace.factory('nsig[5000.0, 0.0, 1000000.0]' ) + + # Double-sided Crystal-ball + self.wspace.factory('mean[{}, {}, {}]'.format((self.fit_up+self.fit_low)/2.0, self.fit_low, self.fit_up)) + self.wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') + self.wspace.factory('alpha1[1.0, 0.0, 10.0]') + self.wspace.factory('n1[1.0, 1.0, 20.0]') + self.wspace.factory('alpha2[1.0, 0.0, 10.0]') + self.wspace.factory('n2[1.0, 1.0, 20.0]') + self.wspace.factory('GenericPdf::sig("DoubleCBFast(x,mean,width,alpha1,n1,alpha2,n2)", {x,mean,width,alpha1,n1,alpha2,n2})') + + self.var['mean'] = self.wspace.var('mean') + self.var['width'] = self.wspace.var('width') + self.var['alpha1'] = self.wspace.var('alpha1') + self.var['n1'] = self.wspace.var('n1') + self.var['alpha2'] = self.wspace.var('alpha2') + self.var['n2'] = self.wspace.var('n2') + self.var['nsig'] = self.wspace.var('nsig') + self.pdf['sig'] = self.wspace.pdf('sig') + + def setup_model_bkg(self): + self.wspace.factory('nbkg[10000.0, 0.0, 1000000.0]') + + # Exponential + self.wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') + self.wspace.factory('Exponential::bkg(x,exp_alpha)') + + # Partially reconstructed bkg + for name, info in self.partialfit.items(): + wpf = ROOT.TFile(info['filename'], "READ") + wp = wpf.Get("myPartialWorkSpace") + partialPDF = wp.pdf(name) + self.wspace.factory('n{}[{}, {}, {}]'.format(name, info['expected_yield'], \ + info['expected_yield'] - 4.0*np.sqrt(info['expected_yield']), \ + info['expected_yield'] + 4.0*np.sqrt(info['expected_yield'])) \ + if 'expected_yield' in info else 'n{}[10.0, 0.0, 100000.0]'.format(name)) + getattr(self.wspace, "import")(partialPDF, RooFit.Rename(name)) + self.var[name] = self.wspace.var('n'+name) + + self.var['exp_alpha'] = self.wspace.var('exp_alpha') + self.var['nbkg'] = self.wspace.var('nbkg') + self.pdf['bkg'] = self.wspace.pdf('bkg') + for name in self.partialfit.keys(): + self.pdf[name] = self.wspace.pdf(name) + + def bkg_unc_propagation(self, outputfile): + # define the set obs = (x) + self.wspace.defineSet('obs', 'x') + # make the set obs known to Python + obs = self.wspace.set('obs') + + nsig_interested_pdf = self.pdf['sig'].createIntegral(obs,obs,"fom_window") ; + nsig_interested_pdf_err = nsig_interested_pdf.getPropagatedError(self.results, obs) + self.nsig_interested = self.var['nsig'].getVal() * nsig_interested_pdf.getVal() + self.nsig_interested_err = self.nsig_interested * np.sqrt(pow(self.var['nsig'].getError()/self.var['nsig'].getVal(), 2) + pow(nsig_interested_pdf_err/nsig_interested_pdf.getVal(), 2)) if self.var['nsig'].getVal() != 0.0 else 0.0 + nbkg_comb_pdf = self.pdf['bkg'].createIntegral(obs,obs,"fom_window") + nbkg_comb_pdf_err = nbkg_comb_pdf.getPropagatedError(self.results, obs) + nbkg_comb = self.var['nbkg'].getVal() * nbkg_comb_pdf.getVal() + nbkg_comb_err = nbkg_comb * np.sqrt(pow(self.var['nbkg'].getError()/self.var['nbkg'].getVal(), 2) + pow(nbkg_comb_pdf_err/nbkg_comb_pdf.getVal(), 2)) if self.var['nbkg'].getVal() != 0.0 else 0.0 + self.nbkg_total = nbkg_comb + print("*"*80) + print("MVA Cut: {}".format(self.mvaCut)) + if not self.fitConverged: + print("*"*20 + "NOT COVERGE" + "*"*20) + print("Number of signals: {}".format(self.var['nsig'].getVal())) + print("Number of signals in 3.0 sigma: {}, uncertainty: {}".format(self.nsig_interested, self.nsig_interested_err)) + print("Number of background - combinatorial: {}, uncertainty: {}".format(nbkg_comb, nbkg_comb_err)) + for name in partialfit.keys(): + nbkg_pdf_pdf = self.pdf[name].createIntegral(obs,obs,"fom_window") + nbkg_partial = self.var[name].getVal() * nbkg_pdf_pdf.getVal() + self.nbkg_total += nbkg_partial + print("Number of background - {}: {}".format(name, nbkg_partial)) + + # Calculate 1-sigma error band of the total bkg through linear error propagation + bkgframe = self.mass.frame() + self.data.plotOn(bkgframe, RooFit.Binning(self.nbin_data)) + + nbinx = 1000 + xvar = np.linspace(self.fom_low, self.fom_up, nbinx) + self.fit_params = self.pdf['model'].getVariables() + ordered_fit_params = ['exp_alpha', 'nbkg'] + ['n'+name for name in self.partialfit.keys()] + if not self.blinded: + ordered_fit_params += ['nsig',] + full_bkg = ['bkg',] + [name for name in self.partialfit.keys()] + fit_params_info = OrderedDict() + for name in ordered_fit_params: + fit_params_info[name] = {'mean': self.fit_params.find(name).getVal(), 'error': self.fit_params.find(name).getError()} + self.pdf['model'].plotOn(bkgframe,RooFit.Components(",".join(full_bkg))) + model_curve = bkgframe.getCurve() + model_cen = np.array([model_curve.interpolate(x) for x in xvar]) + bkgframe.remove(str(0),False) + #self.results.covarianceMatrix().Print() + #self.results.correlationMatrix().Print() + covMatrix = root_numpy.matrix(self.results.covarianceMatrix()) + exp_event = self.pdf['model'].expectedEvents(self.fit_params) + fa = [] + for name, info in fit_params_info.items(): + adjust_norm = info['error'] if (name in (['nsig', 'nbkg',] + ['n'+p for p in self.partialfit.keys()])) else 0.0 + self.fit_params.setRealValue(name, info['mean']+info['error']) + + self.pdf['model'].plotOn(bkgframe,RooFit.Components(",".join(full_bkg)),RooFit.Normalization(exp_event+adjust_norm, ROOT.RooAbsReal.NumEvent)) + model_curve = bkgframe.getCurve() + fa_plus = np.array([model_curve.interpolate(x) for x in xvar]) + bkgframe.remove(str(0),False) + self.fit_params.setRealValue(name, info['mean']-2.0*info['error']) + + self.pdf['model'].plotOn(bkgframe,RooFit.Components(",".join(full_bkg)),RooFit.Normalization(exp_event-adjust_norm, ROOT.RooAbsReal.NumEvent)) + model_curve = bkgframe.getCurve() + fa_minus = np.array([model_curve.interpolate(x) for x in xvar]) + bkgframe.remove(str(0),False) + if name == 'nsig': + fa.append(np.zeros(nbinx)) + else: + fa.append((fa_plus - fa_minus) / (2.0*info['error'])) + # reset the params matrix + self.fit_params.setRealValue(name, info['mean']) + + fa = np.array(fa).T + tmp = np.array([np.asarray(np.matmul(FA, covMatrix)).flatten() for FA in fa]) + bkg_unc = np.sqrt(np.array([np.dot(t, FA) for t, FA in zip(tmp, fa)])) + self.nbkg_total_err = np.sqrt(np.trapz(bkg_unc*bkg_unc, x=xvar)) / ((self.fit_up-self.fit_low)/self.nbin_data) + + if self.plotBkgUnc: + fig, ax = plt.subplots() + ax.plot(xvar, model_cen, 'b-', label=r'$N_{{\rm bkg}}={0:.1f}\pm{1:.1f}$'.format(self.nbkg_total, self.nbkg_total_err)) + ax.fill_between(xvar, model_cen-bkg_unc, model_cen+bkg_unc, facecolor='red', alpha=0.5, linewidth=0.0, label=r'$1\sigma$') + ax.set_xlabel(r'$m(K^{+}e^{+}e^{-}) [{\rm GeV}]$') + ax.set_ylabel(r'a.u.') + ax.set_ylim(bottom=0) + ax.legend(loc='upper right') + fig.savefig(outputfile.replace('.pdf','')+'_totalbkg_1sigma.pdf', bbox_inches='tight') + + self.SNR = self.nsig_interested/np.sqrt(self.nsig_interested + self.nbkg_total) + + print("Total number of background: {}, uncertainty: {}".format(self.nbkg_total, self.nbkg_total_err)) + print("S/sqrt(S+B): {}".format(self.SNR)) + print("*"*80) + + def plot(self, outputfile): + ROOT.gStyle.SetOptFit(0000); + ROOT.gROOT.SetBatch(True); + ROOT.gROOT.SetStyle("Plain"); + ROOT.gStyle.SetGridStyle(3); + ROOT.gStyle.SetOptStat(000000); + ROOT.gStyle.SetOptTitle(0) + #ROOT.TH1.AddDirectory(False) + + #xframe = wspace.var('x').frame(RooFit.Title("PF electron")) + xframe = self.mass.frame() + + if self.isMC: + self.data.plotOn(xframe, RooFit.Binning(self.nbin_data), RooFit.Name("datapoint")) + self.pdf['model'].plotOn(xframe,RooFit.Name("global"),RooFit.Range("Full"),RooFit.LineColor(2),RooFit.MoveToBack()) + if self.paramOn: + self.pdf['model'].paramOn(xframe,RooFit.Layout(0.60,0.92,0.73)) + #self.pdf['model'].paramOn(xframe,RooFit.Layout(0.15,0.45,0.73)) + xframe.getAttText().SetTextSize(0.03) + legend = ROOT.TLegend(0.65,0.75,0.92,0.85); + pt = ROOT.TPaveText(0.72,0.38,0.92,0.50,"brNDC") + #legend = ROOT.TLegend(0.15,0.75,0.42,0.85) + #pt = ROOT.TPaveText(0.15,0.38,0.45,0.50,"brNDC") + legend.AddEntry(xframe.findObject("global"),"Total Fit","l") + + else: + if self.blinded: + self.data.plotOn(xframe, RooFit.Binning(self.nbin_data), RooFit.CutRange("SB1,SB2"), RooFit.Name("datapoint")) + else: + self.data.plotOn(xframe, RooFit.Binning(self.nbin_data), RooFit.Name("datapoint")) + self.pdf['model'].plotOn(xframe,RooFit.Name("global"),RooFit.Range("Full"),RooFit.LineColor(2),RooFit.MoveToBack()) + self.pdf['model'].plotOn(xframe,RooFit.Name("bkg"),RooFit.Components("bkg"),RooFit.Range("Full"),RooFit.DrawOption("F"),RooFit.VLines(),RooFit.FillColor(42),RooFit.LineColor(42),RooFit.LineWidth(1),RooFit.MoveToBack()) + plotted_partial = [] + for name, info in self.partialfit.items(): + self.pdf['model'].plotOn(xframe,RooFit.Name(name),RooFit.Components("bkg,"+",".join(plotted_partial)+",{}".format(name)),RooFit.Range("Full"),RooFit.DrawOption("F"),RooFit.VLines(),RooFit.FillColor(info['color']),RooFit.LineColor(info['color']),RooFit.LineWidth(1),RooFit.MoveToBack()) + plotted_partial.append(name) + self.pdf['model'].plotOn(xframe,RooFit.Name("sig"),RooFit.Components("sig"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(1)) + legend = ROOT.TLegend(0.56,0.65,0.92,0.85) #if prefix == 'BToKEE' else ROOT.TLegend(0.46,0.70,0.92,0.85) + legend.AddEntry(xframe.findObject("bkg"),"Combinatorial","f") + for name, info in self.partialfit.items(): + legend.AddEntry(xframe.findObject(name),info['label'],"f") + legend.AddEntry(xframe.findObject("sig"),self.sigName,"l") + + xframe.GetYaxis().SetTitleOffset(0.9) + xframe.GetYaxis().SetTitleFont(42) + xframe.GetYaxis().SetTitleSize(0.05) + xframe.GetYaxis().SetLabelSize(0.04) + xframe.GetYaxis().SetLabelFont(42) + xframe.GetXaxis().SetTitleOffset(0.9) + xframe.GetXaxis().SetTitleFont(42) + xframe.GetXaxis().SetTitleSize(0.05) + xframe.GetXaxis().SetLabelSize(0.04) + xframe.GetXaxis().SetLabelFont(42) + + xframe.GetYaxis().SetTitle("Events / {0:.0f} MeV".format((self.fit_up - self.fit_low)/self.nbin_data*1000.)) + xtitle = "m(K^{+}e^{+}e^{-}) [GeV]" #if prefix == 'BToKEE' else "m(K^{+}K^{-}e^{+}e^{-}) [GeV]" + xframe.GetXaxis().SetTitle(xtitle) + xframe.SetStats(0) + xframe.SetMinimum(0) + + + legend.SetTextFont(42) + legend.SetTextSize(0.04) + legend.AddEntry(xframe.findObject("datapoint"),"Data","lpe") + + if self.drawSNR: + pt = ROOT.TPaveText(0.7,0.35,0.92,0.63,"brNDC") + #pt = ROOT.TPaveText(0.72,0.30,0.92,0.63,"brNDC") + pt.SetFillColor(0) + pt.SetBorderSize(1) + pt.SetTextFont(42); + pt.SetTextSize(0.04); + pt.SetTextAlign(12) + if self.mvaCut: + pt.AddText("MVA cut: {0:.2f}".format(self.mvaCut)) + pt.AddText("S_{{total}}: {0:.0f}#pm{1:.0f}".format(self.nsig_total, self.nsig_total_err)) + pt.AddText("S: {0:.0f}#pm{1:.0f}".format(self.nsig_interested, self.nsig_interested_err)) + if not self.isMC: + pt.AddText("B: {0:.0f}#pm{1:.0f}".format(self.nbkg_total, self.nbkg_total_err)) + pt.AddText("S/#sqrt{{S+B}}: {0:.1f}".format(self.SNR)) + #pt.AddText("Punzi: {0:.1f}".format(Punzi(nbkgWindow, 2.0, 5.0))) + if not self.fitConverged: + pt.AddText("Fit is not converged") + + + # Plot results of fit on a different frame + c2 = ROOT.TCanvas('canvas', 'canvas', 800, 600) + c2.SetGrid() + c2.cd() + ROOT.gPad.SetLeftMargin(0.10) + ROOT.gPad.SetRightMargin(0.05) + xframe.Draw() + legend.Draw() + if self.drawSNR: pt.Draw() + CMS_lumi(self.isMC) + c2.cd() + c2.Update() + c2.SaveAs(outputfile.replace('.pdf','')+'.pdf') + print("="*80) + + + def fit(self, tree, outputfile): + if not self.fit_init: return + msgservice = ROOT.RooMsgService.instance() + msgservice.setGlobalKillBelow(RooFit.FATAL) + self.load_tree(tree) + self.setup_model_sig() + if self.isMC: + self.wspace.factory('ExtendPdf::model(sig,nsig)') + else: + self.setup_model_bkg() + self.wspace.factory('SUM::model(nsig*sig,nbkg*bkg{})'.format(','+','.join(['n'+name+'*'+name for name in self.partialfit.keys()]))) + + self.var['mean'].setVal(self.params['mean']); self.var['mean'].setConstant(True) + self.var['width'].setVal(self.params['width']); self.var['width'].setConstant(True) + self.var['alpha1'].setVal(self.params['alpha1']); self.var['alpha1'].setConstant(True) + self.var['n1'].setVal(self.params['n1']); self.var['n1'].setConstant(True) + self.var['alpha2'].setVal(self.params['alpha2']); self.var['alpha2'].setConstant(True) + self.var['n2'].setVal(self.params['n2']); self.var['n2'].setConstant(True) + if self.blinded: + self.var['nsig'].setVal(self.expS); self.var['nsig'].setConstant(True) + + self.pdf['model'] = self.wspace.pdf('model') + + self.mass.setRange("window",self.sig_low,self.sig_up) + self.mass.setRange("fom_window",self.fom_low,self.fom_up) + self.mass.setRange("SB1",self.fit_low,self.sig_low) + self.mass.setRange("SB2",self.sig_up,self.fit_up) + + ## fit the model to the data. + print('Fitting data...') + if (not self.isMC) and self.blinded: + self.results = self.pdf['model'].fitTo(self.data, RooFit.Extended(True), RooFit.Save(), RooFit.Range("SB1,SB2"), RooFit.SplitRange(True), RooFit.PrintLevel(-1)) + else: + self.results = self.pdf['model'].fitTo(self.data, RooFit.Extended(True), RooFit.Save(), RooFit.Range(self.fit_low, self.fit_up), RooFit.PrintLevel(-1)) + + self.results.Print() + self.fitConverged = True if self.results.status() == 0 else False + self.nsig_total = self.var['nsig'].getVal() + self.nsig_total_err = self.var['nsig'].getError() + + if not self.isMC: + self.bkg_unc_propagation(outputfile) + self.plot(outputfile) + + if self.isMC: + return 0.0 + else: + output = {} + output['Stot'] = self.nsig_total + output['StotErr'] = self.nsig_total_err + output['S'] = self.nsig_interested + output['SErr'] = self.nsig_interested_err + output['B'] = self.nbkg_total + output['BErr'] = self.nbkg_total_err + output['exp_alpha'] = self.fit_params.find('exp_alpha').getVal() + output['fitConverged'] = self.fitConverged + return output + + + def fit_kde(self, tree, outputfile): + if not self.fit_init: return + msgservice = ROOT.RooMsgService.instance() + msgservice.setGlobalKillBelow(RooFit.FATAL) + self.load_tree(tree) + print('Fitting KDE...') + self.wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(self.pdfname)) + self.pdf['model'] = self.wspace.pdf(self.pdfname) + self.plot(outputfile) + + wf = ROOT.TFile(outputfile.replace('.pdf','').replace('.root','')+'.root', "RECREATE") + self.wspace.Write() + wf.Close() + print("Created a RooWorkspace file - {}, with a KeysPdf named - {}".format(outputfile.replace('.pdf','').replace('.root','')+'.root', self.pdfname)) + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser(description='Unbinned likelihood fit') + parser.add_argument("-i", "--inputfile", dest="inputfile", default="", help="Input file") + parser.add_argument("-o", "--outputfile", dest="outputfile", default="", help="Output file") + parser.add_argument("-p", "--partial", dest="partial", action="store_true", help="Fit partially reconstructed background") + parser.add_argument("-n", "--pdfname", dest="pdfname", default="partial", help="PDF name of the Partially reconstructed background") + args = parser.parse_args() + + params = params_jpsi_pf + partialfit = OrderedDict() + partialfit['partial'] = {'filename': 'part_workspace_jpsi_pf.root', 'label': 'Partially Reco.', 'color': 40} + #partialfit['partial'] = {'filename': 'part_workspace_nonresonant_lowq2_pf.root', 'label': 'Partially Reco.', 'color': 40} + #partialfit['jpsi'] = {'filename': 'jpsi_workspace_lowq2_pf.root', 'label': 'B^{+}#rightarrow K^{+} J/#psi(#rightarrow e^{+}e^{-})', 'color': 46, 'expected_yield': 150} + + tree = ROOT.TChain('tree') + tree.AddFile(args.inputfile) + b_fitter = fitter() + if args.partial: + b_fitter.init_fit_kde(pdfname=args.pdfname) + b_fitter.fit_kde(tree, args.outputfile) + else: + b_fitter.init_fit_mc() + #b_fitter.init_fit_data(params=params, partialfit=partialfit, drawSNR=True) + b_fitter.fit(tree, args.outputfile) + + diff --git a/helper.py b/helper.py index 39b58e9..6d7bda3 100644 --- a/helper.py +++ b/helper.py @@ -1,21 +1,33 @@ import numpy as np +import uproot +import pandas as pd +import ROOT ELECTRON_MASS = 0.000511 K_MASS = 0.493677 PI_MASS = 0.139570 -NR_LOW = np.sqrt(1.1) +NR_LOW = np.sqrt(0.045) JPSI_MC = 3.08991 JPSI_SIGMA_MC = 0.04205 -JPSI_LOW = np.sqrt(6.0) -JPSI_UP = JPSI_MC + 3.0*JPSI_SIGMA_MC -B_MC = 5.2694 -B_SIGMA_MC = 0.06187 -B_LOW = B_MC - 3.0*B_SIGMA_MC -B_UP = B_MC + 3.0*B_SIGMA_MC +JPSI_LOW = np.sqrt(6.5) +JPSI_UP = 3.25 +PSI2S_UP = 3.85 +NR_UP = np.sqrt(25.0) +PHI_SIGMA_MC = 0.0026836 +PHI_LOW = 1.01957 - 4.0*PHI_SIGMA_MC +PHI_UP = 1.01957 + 4.0*PHI_SIGMA_MC +B_MC = 5.2676 +B_SIGMA_MC = 0.06070 +B_LOW = 5.05 +B_UP = 5.45 +BS_LOW = 5.15 +BS_UP = 5.55 B_SB_LOW = B_MC - 6.0*B_SIGMA_MC B_SB_UP = B_MC + 6.0*B_SIGMA_MC BLIND_LOW = B_LOW BLIND_UP = B_UP +B_FOM_LOW = 5.05 +B_FOM_UP = 5.45 B_MIN = 4.5 B_MAX = 6.0 FIT_LOW = 4.7 @@ -24,4 +36,83 @@ BR_BToKJpsi = 1.01e-3 BR_JpsiToLL = 0.0597 BR_BToKLL = 4.51e-7 +BR_BToPhiJpsi = 1.08e-3 +BR_PhiToKK = 0.492 +BR_BToPhiLL = 8.2e-7 + +params_jpsitri_pf = {'mean': 5.2671, 'width': 0.0637, 'alpha1': 0.683, 'n1': 2.02, 'alpha2': 1.692, 'n2': 10.0} +params_jpsi_pf = {'mean': 5.2676, 'width': 0.06070, 'alpha1': 0.677, 'n1': 1.56, 'alpha2': 1.440, 'n2': 8.9} +params_jpsi_mix = {'mean': 5.2660, 'width': 0.0636, 'alpha1': 0.60, 'n1': 2.20, 'alpha2': 1.387, 'n2': 20.0} +params_jpsi_low = {'mean': 5.2654, 'width': 0.0638, 'alpha1': 0.655, 'n1': 1.75, 'alpha2': 1.509, 'n2': 9.85} +params_psi2stri_pf = {'mean': 5.2628, 'width': 0.0753, 'alpha1': 0.642, 'n1': 10.0, 'alpha2': 4.6, 'n2': 6.4} +params_psi2s_pf = {'mean': 5.2646, 'width': 0.0726, 'alpha1': 0.591, 'n1': 10.0, 'alpha2': 1.87, 'n2': 10.0} +params_psi2s_mix = {'mean': 5.2544, 'width': 0.0838, 'alpha1': 0.577, 'n1': 20, 'alpha2': 9.93, 'n2': 9.7} +params_psi2s_low = {'mean': 5.25464, 'width': 0.0822, 'alpha1': 0.642, 'n1': 9.76, 'alpha2': 6.0, 'n2': 2.94} +params_jpsi_cutbased_pf = {'mean': 5.2621, 'width': 0.0658, 'alpha1': 0.945, 'n1': 1.065, 'alpha2': 1.59704, 'n2': 9.962} + +params_rphi_jpsi_pf = {'mean': 5.35897, 'width': 0.05558, 'alpha1': 0.5363, 'n1': 2.76, 'alpha2': 1.269, 'n2': 20} +params_rphi_jpsi_low = {'mean': 5.3546, 'width': 0.0609, 'alpha1': 0.560, 'n1': 2.98, 'alpha2': 1.400, 'n2': 20} + +triCut_jpsi_mll_mean_pf = 3.00233244896 +triCut_jpsi_mKee_mean_pf = 5.17609024048 +triCut_jpsi_rotMatrix_pf = np.array([[0.74743241, -0.66433786], [0.66433786, 0.74743241]]) +triCut_jpsi_lower_bound_pf = -0.0977517530843 +triCut_jpsi_upper_bound_pf = 0.0824238599635 + +triCut_psi2s_mll_mean_pf = 3.58506560326 +triCut_psi2s_mKee_mean_pf = 5.17640161514 +triCut_psi2s_rotMatrix_pf = np.array([[0.72047561, -0.69348028], [0.69348028, 0.72047561]]) +triCut_psi2s_lower_bound_pf = -0.0704979038994 +triCut_psi2s_upper_bound_pf = 0.059937465045 + +def Punzi(B, a, b): + return (b*b)/2.0 + a*np.sqrt(B) + (b/2.0)*np.sqrt(b*b + 4.0*a*np.sqrt(B) + 4.0*B) + +def Punzi_simplify(eff, B, dB, a): + return eff / ((a/2.0) + np.sqrt(B + dB*dB)) + +def Significance(S, B, dB): + return S / np.sqrt(S + B + dB*dB) + +def get_df(root_file_name, tree='tree', branches=['*']): + print('Opening file {}...'.format(root_file_name)) + f = uproot.open(root_file_name) + if len(f.allkeys()) == 0: + return pd.DataFrame() + print('Not an null file') + #df = uproot.open(root_file_name)["tree"].pandas.df() + #df = pd.DataFrame(uproot.open(root_file_name)["tree"].arrays(namedecode="utf-8")) + df = pd.DataFrame(f[tree].arrays(branches=branches)) + print('Finished opening file {}...'.format(root_file_name)) + return df + +def get_diagonalCut_var(branches, mll_mean, fit_mass_mean, diagCut_lower_bound, diagCut_jpsi_upper_bound, eigVecs): + branches['BToKEE_mll_fullfit_centered'] = branches['BToKEE_mll_fullfit'] - mll_mean + branches['BToKEE_fit_mass_centered'] = branches['BToKEE_fit_mass'] - fit_mass_mean + data_centered = np.array([branches['BToKEE_fit_mass_centered'],branches['BToKEE_mll_fullfit_centered']]).T + eigVecs_jpsi = triCut_jpsi_rotMatrix_pf + data_decorr = data_centered.dot(eigVecs) + return data_decorr[:,0], data_decorr[:,1] + +def CMS_lumi(isMC): + mark = ROOT.TLatex() + mark.SetNDC() + lumistamp = '2018 (13 TeV)' + fontScale = 1.0 + cmsTextSize = 0.042 * fontScale * 1.25 + extraOverCmsTextSize = 0.76 + extraTextSize = extraOverCmsTextSize*cmsTextSize + + mark.SetTextAlign(11) + mark.SetTextSize(cmsTextSize) + mark.SetTextFont(61) + mark.DrawLatex(ROOT.gPad.GetLeftMargin(), 1 - (ROOT.gPad.GetTopMargin() - 0.017), "CMS") + mark.SetTextSize(0.042 * fontScale) + mark.SetTextFont(52) + mark.DrawLatex(ROOT.gPad.GetLeftMargin() + 0.09, 1 - (ROOT.gPad.GetTopMargin() - 0.017), "Simulation Preliminary" if isMC else "Preliminary") + mark.SetTextSize(extraTextSize) + mark.SetTextFont(42) + mark.SetTextAlign(31) + mark.DrawLatex(1 - ROOT.gPad.GetRightMargin(), 1 - (ROOT.gPad.GetTopMargin() - 0.017), lumistamp) + diff --git a/makePlot_fitPeak_unbinned.py b/makePlot_fitPeak_unbinned.py deleted file mode 100644 index 9922054..0000000 --- a/makePlot_fitPeak_unbinned.py +++ /dev/null @@ -1,414 +0,0 @@ -#!/usr/bin/env python -import os -from time import sleep -import math -import ROOT -from ROOT import RooFit -import numpy as np -ROOT.gROOT.ProcessLine(open('models.cc').read()) -from ROOT import DoubleCBFast -from helper import * -ROOT.gErrorIgnoreLevel=ROOT.kError -ROOT.RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) - -def CMS_lumi(isMC): - mark = ROOT.TLatex() - mark.SetNDC() - lumistamp = '2018 (13 TeV)' - fontScale = 1.0 - cmsTextSize = 0.042 * fontScale * 1.25 - extraOverCmsTextSize = 0.76 - extraTextSize = extraOverCmsTextSize*cmsTextSize - - mark.SetTextAlign(11) - mark.SetTextSize(cmsTextSize) - mark.SetTextFont(61) - mark.DrawLatex(ROOT.gPad.GetLeftMargin(), 1 - (ROOT.gPad.GetTopMargin() - 0.017), "CMS") - mark.SetTextSize(0.042 * fontScale) - mark.SetTextFont(52) - mark.DrawLatex(ROOT.gPad.GetLeftMargin() + 0.09, 1 - (ROOT.gPad.GetTopMargin() - 0.017), "Simulation Preliminary" if isMC else "Preliminary") - mark.SetTextSize(extraTextSize) - mark.SetTextFont(42) - mark.SetTextAlign(31) - mark.DrawLatex(1 - ROOT.gPad.GetRightMargin(), 1 - (ROOT.gPad.GetTopMargin() - 0.017), lumistamp) - - -def fit(tree, outputfile, sigPDF=3, bkgPDF=2, fitJpsi=False, isMC=False, doPartial=False, partialinputfile='part_workspace.root', drawSNR=False, mvaCut=0.0, blinded=False, expS=100): - msgservice = ROOT.RooMsgService.instance() - msgservice.setGlobalKillBelow(RooFit.FATAL) - wspace = ROOT.RooWorkspace('myWorkSpace') - ROOT.gStyle.SetOptFit(0000); - ROOT.gROOT.SetBatch(True); - ROOT.gROOT.SetStyle("Plain"); - ROOT.gStyle.SetGridStyle(3); - ROOT.gStyle.SetOptStat(000000); - ROOT.gStyle.SetOptTitle(0) - - thevars = ROOT.RooArgSet() - - if fitJpsi: - xmin, xmax = 2.5, 3.5 - bMass = ROOT.RooRealVar("BToKEE_mll_fullfit", "m(e^{+}e^{-})", 2.0, 4.0, "GeV") - wspace.factory('mean[3.096916, 2.9, 3.3]') - - else: - bMass = ROOT.RooRealVar("BToKEE_fit_mass", "m(K^{+}e^{+}e^{-})", 4.0, 6.0, "GeV") - dieleMass = ROOT.RooRealVar("BToKEE_mll_fullfit", "m(e^{+}e^{-})", 2.0, 4.0, "GeV") - if isMC: - xmin, xmax = 4.5, 6.0 - wspace.factory('mean[5.272e+00, 5.22e+00, 5.3e+00]') - else: - xmin, xmax = FIT_LOW, FIT_UP - wspace.factory('mean[5.2694, 5.2694, 5.2694]') - #wspace.factory('mean[5.2681, 5.2681, 5.2681]') - thevars.add(dieleMass) - - thevars.add(bMass) - - fulldata = ROOT.RooDataSet('fulldata', 'fulldata', tree, ROOT.RooArgSet(thevars)) - theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) - theBMass = fulldata.addColumn(theBMassfunc) ; - theBMass.setRange(xmin,xmax); - thevars.add(theBMass) - - cut = '' - - #print cut - data = fulldata.reduce(thevars, cut) - getattr(wspace,'import')(data, RooFit.Rename("data")) - - if not blinded: - wspace.factory('nsig[5000.0, 0.0, 1000000.0]') - else: - wspace.factory('nsig[{0}, {0}, {0}]'.format(expS)) - wspace.factory('nbkg[10000.0, 0.0, 1000000.0]') - wspace.factory('npartial[1000.0, 0.0, 100000.0]') - - if sigPDF == 0: - # Voigtian - wspace.factory('width[1.000e-02, 1.000e-04, 1.000e-01]') - wspace.factory('sigma[7.1858e-02, 1.e-3, 1.e-1]') - wspace.factory('Voigtian::sig(x,mean,width,sigma)') - - if sigPDF == 1: - # Gaussian - wspace.factory('sigma[7.1858e-02, 1.0e-3, 5.0e-1]') - wspace.factory('Gaussian::sig(x,mean,sigma)') - - if sigPDF == 2: - # Crystal-ball - wspace.factory('sigma[7.1858e-02, 1.0e-6, 5.0e-1]') - wspace.factory('alpha[1.0, 0.0, 10.0]') - wspace.factory('n[2, 1, 10]') - wspace.factory('CBShape::sig(x,mean,sigma,alpha,n)') - - if sigPDF == 3: - # Double-sided Crystal-ball - if isMC: - wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') - wspace.factory('alpha1[1.0, 0.0, 10.0]') - wspace.factory('n1[1.0, 1.0, 10.0]') - wspace.factory('alpha2[1.0, 0.0, 10.0]') - wspace.factory('n2[1.0, 1.0, 10.0]') - else: - # PF - wspace.factory('width[0.06187, 0.06187, 0.06187]') - wspace.factory('alpha1[0.667, 0.667, 0.667]') - wspace.factory('n1[2.39, 2.39, 2.39]') - wspace.factory('alpha2[2.442, 2.442, 2.442]') - wspace.factory('n2[3.09, 3.09, 3.09]') - - # Mix - #wspace.factory('width[0.0561, 0.0561, 0.0561]') - #wspace.factory('alpha1[0.642, 0.642, 0.642]') - #wspace.factory('n1[2.31, 2.31, 2.31]') - #wspace.factory('alpha2[1.700, 1.700, 1.700]') - #wspace.factory('n2[10.0, 10.0, 10.0]') - - wspace.factory('GenericPdf::sig("DoubleCBFast(x,mean,width,alpha1,n1,alpha2,n2)", {x,mean,width,alpha1,n1,alpha2,n2})') - - if sigPDF == 4: - # Two Double-sided Crystal-ball - wspace.factory('width[7.1858e-02, 1.0e-6, 5.0e-1]') - wspace.factory('alpha1[1.0, 0.0, 10.0]') - wspace.factory('n1[2.0, 1.0, 10.0]') - wspace.factory('alpha2[1.0, 0.0, 10.0]') - wspace.factory('n2[2.0, 1.0, 10.0]') - wspace.factory('GenericPdf::cb("DoubleCBFast(x,mean,width,alpha1,n1,alpha2,n2)", {x,mean,width,alpha1,n1,alpha2,n2})') - wspace.factory('sigma[7.1858e-03, 1.0e-6, 5.0e-1]') - wspace.factory('Gaussian::gaus(x,mean,sigma)') - wspace.factory('f1[0.5, 0.0, 1.0]') - wspace.factory('SUM::sig(f1*cb, gaus)') - - if bkgPDF == 0: - # Polynomial - wspace.factory('c0[1.0, -1.0, 1.0]') - wspace.factory('c1[-0.1, -1.0, 1.0]') - wspace.factory('c2[-0.1, -1.0, 1.0]') - wspace.factory('Chebychev::bkg(x,{c0,c1,c2})') - - if bkgPDF == 1: - wspace.factory('c1[0.0, -100.0, 100.0]') - wspace.factory('Polynomial::bkg(x,{c1})') - - if bkgPDF == 2: - # Exponential - wspace.factory('exp_alpha[-3.0, -100.0, -1.0e-5]') - alpha = wspace.var('alpha') - wspace.factory('Exponential::bkg(x,exp_alpha)') - - if not isMC: - if doPartial: - wpf = ROOT.TFile(partialinputfile,"READ") - wp = wpf.Get("myPartialWorkSpace") - partial = wp.pdf("partial") - getattr(wspace, "import")(partial, RooFit.Rename("partial")) - wspace.factory('SUM::model1(f1[0.5,0.0,1.0]*partial,bkg)') - print('Finished loading KDE!') - wspace.factory('SUM::model(nsig*sig,nbkg*model1)') - - else: - wspace.factory('SUM::model(nsig*sig,nbkg*bkg)') - else: - wspace.factory('ExtendPdf::model(sig,nsig)') - - model = wspace.pdf('model') - bkg = wspace.pdf('model1') - sig = wspace.pdf('sig') - nsig = wspace.var('nsig') - nbkg = wspace.var('nbkg') - - # define the set obs = (x) - wspace.defineSet('obs', 'x') - - # make the set obs known to Python - obs = wspace.set('obs') - - theBMass.setRange("window",B_LOW,B_UP) - theBMass.setRange("SB1",FIT_LOW,BLIND_LOW) - theBMass.setRange("SB2",BLIND_UP,FIT_UP) - - ## fit the model to the data. - print('Fitting data...') - if not blinded: - results = model.fitTo(data, RooFit.Extended(True), RooFit.Save(), RooFit.Range(xmin,xmax), RooFit.PrintLevel(-1)) - else: - results = model.fitTo(data, RooFit.Extended(True), RooFit.Save(), RooFit.Range("SB1,SB2"), RooFit.PrintLevel(-1)) - - results.Print() - - if not isMC: - fracBkgRange = bkg.createIntegral(obs,obs,"window") ; - fracBkgRangeErr = fracBkgRange.getPropagatedError(results, obs) - nbkgWindow = nbkg.getVal() * fracBkgRange.getVal() - #print(nbkg.getVal(), fracBkgRange.getVal()) - #print(fracBkgRange.getVal(), fracBkgRange.getPropagatedError(results, obs)) - fb = fracBkgRange.getVal() - dfb = fracBkgRangeErr - nb = nbkg.getVal() - dnb = nbkg.getError() - #print(nb*fb*np.sqrt(pow(dfb/fb,2)+pow(dnb/nb,2))) - print("Number of signals: %f, Number of background: %f, S/sqrt(S+B): %f"%(nsig.getVal(), nbkgWindow, nsig.getVal()/np.sqrt(nsig.getVal() + nbkgWindow))) - else: - fracSigRange = sig.createIntegral(obs,obs,"window") ; - print(data.sumEntries(),fracSigRange.getVal()) - - # Plot results of fit on a different frame - c2 = ROOT.TCanvas('fig_binnedFit', 'fit', 800, 600) - c2.SetGrid() - c2.cd() - ROOT.gPad.SetLeftMargin(0.10) - ROOT.gPad.SetRightMargin(0.05) - - #xframe = wspace.var('x').frame(RooFit.Title("PF electron")) - xframe = theBMass.frame() - nbin_data = 30 if blinded else 50 - - if isMC: - data.plotOn(xframe, RooFit.Binning(nbin_data), RooFit.Name("data")) - model.plotOn(xframe,RooFit.Name("global"),RooFit.Range("Full"),RooFit.LineColor(2),RooFit.MoveToBack()) # this will show fit overlay on canvas - model.paramOn(xframe,RooFit.Layout(0.15,0.45,0.85)) - xframe.getAttText().SetTextSize(0.03) - - else: - if blinded: - nd = data.reduce('((BToKEE_fit_mass > {}) & (BToKEE_fit_mass < {})) | ((BToKEE_fit_mass > {}) & (BToKEE_fit_mass < {}))'.format(FIT_LOW, BLIND_LOW, BLIND_UP, FIT_UP)).sumEntries() / data.reduce('(BToKEE_fit_mass > {}) & (BToKEE_fit_mass < {})'.format(FIT_LOW, FIT_UP)).sumEntries() - data.plotOn(xframe, RooFit.Binning(nbin_data), RooFit.CutRange("SB1,SB2"), RooFit.Name("data")) - else: - nd = 1.0 - data.plotOn(xframe, RooFit.Binning(nbin_data), RooFit.Name("data")) - model.plotOn(xframe,RooFit.Name("global"),RooFit.Range("Full"),RooFit.Normalization(nd, ROOT.RooAbsReal.Relative),RooFit.LineColor(2),RooFit.MoveToBack()) # this will show fit overlay on canvas - model.plotOn(xframe,RooFit.Name("bkg"),RooFit.Components("bkg"),RooFit.Range("Full"),RooFit.Normalization(nd, ROOT.RooAbsReal.Relative),RooFit.DrawOption("F"),RooFit.VLines(),RooFit.FillColor(42),RooFit.LineColor(42),RooFit.LineWidth(1),RooFit.MoveToBack()) - if doPartial: - model.plotOn(xframe,RooFit.Name("partial"),RooFit.Components("bkg,partial"),RooFit.Range("Full"),RooFit.Normalization(nd, ROOT.RooAbsReal.Relative),RooFit.DrawOption("F"),RooFit.VLines(),RooFit.FillColor(40),RooFit.LineColor(40),RooFit.LineWidth(1),RooFit.MoveToBack()) ; - model.plotOn(xframe,RooFit.Name("sig"),RooFit.Components("sig"),RooFit.Range("Full"),RooFit.Normalization(nd, ROOT.RooAbsReal.Relative),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(1)) ; - - - xframe.GetYaxis().SetTitleOffset(0.9) - xframe.GetYaxis().SetTitleFont(42) - xframe.GetYaxis().SetTitleSize(0.05) - xframe.GetYaxis().SetLabelSize(0.04) - xframe.GetYaxis().SetLabelFont(42) - xframe.GetXaxis().SetTitleOffset(0.9) - xframe.GetXaxis().SetTitleFont(42) - xframe.GetXaxis().SetTitleSize(0.05) - xframe.GetXaxis().SetLabelSize(0.04) - xframe.GetXaxis().SetLabelFont(42) - - xframe.GetYaxis().SetTitle("Events") - xframe.GetXaxis().SetTitle("m(e^{+}e^{-}) [GeV]" if fitJpsi else "m(K^{+}e^{+}e^{-}) [GeV]") - xframe.SetStats(0) - xframe.SetMinimum(0) - xframe.Draw() - - CMS_lumi(isMC) - - if isMC: - legend = ROOT.TLegend(0.65,0.75,0.92,0.85); - legend.AddEntry(xframe.findObject("global"),"Total Fit","l"); - pt = ROOT.TPaveText(0.72,0.38,0.92,0.50,"brNDC") - - else: - legend = ROOT.TLegend(0.60,0.65,0.92,0.85); - legend.AddEntry(xframe.findObject("bkg"),"Combinatorial","f"); - pt = ROOT.TPaveText(0.72,0.38,0.92,0.63,"brNDC") - if doPartial: - legend.AddEntry(xframe.findObject("partial"),"Partially Reco.","f"); - legend.AddEntry(xframe.findObject("sig"),"B^{+}#rightarrow K^{+} J/#psi(#rightarrow e^{+}e^{-})","l"); - - legend.SetTextFont(42); - legend.SetTextSize(0.04); - legend.AddEntry(xframe.findObject("data"),"Data","lpe"); - legend.Draw(); - - if drawSNR: - pt.SetFillColor(0) - pt.SetBorderSize(1) - pt.SetTextFont(42); - pt.SetTextSize(0.04); - pt.SetTextAlign(12) - pt.AddText("MVA cut: {0:.2f}".format(mvaCut)) - pt.AddText("S: {0:.0f}#pm{1:.0f}".format(nsig.getVal(),nsig.getError())) - if not isMC: - pt.AddText("B: {0:.0f}".format(nbkgWindow)) - pt.AddText("S/#sqrt{{S+B}}: {0:.1f}".format(nsig.getVal()/np.sqrt(nsig.getVal() + nbkgWindow))) - pt.Draw() - - - c2.cd() - c2.Update() - - c2.SaveAs(outputfile) - print("="*80) - if not isMC: - return nsig.getVal(), nsig.getError(), nbkgWindow - else: - return 0.0, 0.0, 0.0 - -def fit_kde(tree, outputfile, isMC=True): - #msgservice = ROOT.RooMsgService.instance() - #msgservice.setGlobalKillBelow(RooFit.FATAL) - wspace = ROOT.RooWorkspace('myPartialWorkSpace') - ROOT.gStyle.SetOptFit(0000); - #ROOT.gStyle.SetOptFit(1); - ROOT.gROOT.SetBatch(True); - ROOT.gROOT.SetStyle("Plain"); - ROOT.gStyle.SetGridStyle(3); - ROOT.gStyle.SetOptStat(000000); - ROOT.gStyle.SetOptTitle(0) - - xmin, xmax = 4.5, 6.0 - bMass = ROOT.RooRealVar("BToKEE_fit_mass", "m(K^{+}e^{+}e^{-})", 4.0, 6.0, "GeV") - - thevars = ROOT.RooArgSet() - thevars.add(bMass) - - fulldata = ROOT.RooDataSet('fulldata', 'fulldata', tree, ROOT.RooArgSet(thevars)) - theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) - theBMass = fulldata.addColumn(theBMassfunc) ; - theBMass.setRange(xmin,xmax); - thevars.add(theBMass) - - cut = '' - print cut - data = fulldata.reduce(thevars, cut) - getattr(wspace,'import')(data, RooFit.Rename("data")) - - - # define the set obs = (x) - wspace.defineSet('obs', 'x') - - # make the set obs known to Python - obs = wspace.set('obs') - #wspace.factory('KeysPdf::partial(x,data,MirrorBoth,2.0)') - wspace.factory('KeysPdf::partial(x,data,MirrorLeft,2.0)') - model = wspace.pdf('partial') - - # Plot results of fit on a different frame - c2 = ROOT.TCanvas('fig_binnedFit', 'fit', 800, 600) - c2.SetGrid() - c2.cd() - ROOT.gPad.SetLeftMargin(0.10) - ROOT.gPad.SetRightMargin(0.05) - - #xframe = wspace.var('x').frame(RooFit.Title("PF electron")) - xframe = theBMass.frame() - data.plotOn(xframe, RooFit.Binning(50), RooFit.Name("data")) - model.plotOn(xframe,RooFit.Name("global"),RooFit.LineColor(2),RooFit.MoveToBack()) # this will show fit overlay on canvas - - xframe.GetYaxis().SetTitleOffset(0.9) - xframe.GetYaxis().SetTitleFont(42) - xframe.GetYaxis().SetTitleSize(0.05) - xframe.GetYaxis().SetLabelSize(0.04) - xframe.GetYaxis().SetLabelFont(42) - xframe.GetXaxis().SetTitleOffset(0.9) - xframe.GetXaxis().SetTitleFont(42) - xframe.GetXaxis().SetTitleSize(0.05) - xframe.GetXaxis().SetLabelSize(0.04) - xframe.GetXaxis().SetLabelFont(42) - - xframe.GetYaxis().SetTitle("Events") - xframe.GetXaxis().SetTitle("m(K^{+}e^{+}e^{-}) [GeV]") - xframe.SetStats(0) - xframe.SetMinimum(0) - xframe.Draw() - - CMS_lumi(isMC) - - legend = ROOT.TLegend(0.65,0.75,0.92,0.85); - #legend = ROOT.TLegend(0.65,0.15,0.92,0.35); - legend.SetTextFont(72); - legend.SetTextSize(0.04); - legend.AddEntry(xframe.findObject("data"),"Data","lpe"); - legend.AddEntry(xframe.findObject("global"),"Global Fit","l"); - legend.Draw(); - - c2.cd() - c2.Update() - - c2.SaveAs(outputfile.replace('.root','')+'.pdf') - #wf = ROOT.TFile("part_workspace.root", "RECREATE") - wf = ROOT.TFile(outputfile.replace('.root','')+'.root', "RECREATE") - wspace.Write() - wf.Close() - - print("="*80) - -if __name__ == "__main__": - import argparse - parser = argparse.ArgumentParser(description='Unbinned likelihood fit') - parser.add_argument("-i", "--inputfile", dest="inputfile", default="", help="Input file") - parser.add_argument("-o", "--outputfile", dest="outputfile", default="", help="Output file") - parser.add_argument("-p", "--partial", dest="partial", action="store_true", help="Fit partially reconstructed background") - args = parser.parse_args() - - tree = ROOT.TChain('tree') - tree.AddFile(args.inputfile) - if not args.partial: - fit(tree, args.outputfile, fitJpsi=False, isMC=True) - #fit(tree, args.outputfile, doPartial=True) - #fit(tree, args.outputfile, doPartial=True, drawSNR=True, mvaCut=2.0) - else: - fit_kde(tree, args.outputfile) - - From fee514dce22ca2888d8e9fd5d4350a21d091dc34 Mon Sep 17 00:00:00 2001 From: ottolau Date: Sun, 12 Dec 2021 22:04:29 +0100 Subject: [PATCH 02/13] script to do fit r_k --- maximum_likelihood_singleChannel.py | 221 +++++++++++++++++++++ plotting.py | 294 ++++++++++++++++++++++++++++ 2 files changed, 515 insertions(+) create mode 100644 maximum_likelihood_singleChannel.py create mode 100644 plotting.py diff --git a/maximum_likelihood_singleChannel.py b/maximum_likelihood_singleChannel.py new file mode 100644 index 0000000..2f8febb --- /dev/null +++ b/maximum_likelihood_singleChannel.py @@ -0,0 +1,221 @@ +import os,sys,re +from time import sleep +import math +import ROOT as rt +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from plotting import * + +def createWorkspace(wsname, wsfilename, N=0.0, n_norm=0.0, dn_norm=0.0, eff_tar=0.0, deff_tar=0.0, eff_norm=0.0, deff_norm=0.0): + wspace = rt.RooWorkspace(wsname) + + ### Create parameters + # observations + params = [('N', N, 0, 20000), + # number of signal in normalization channel estimate + ('n_hat_norm', n_norm, 0, 20000), + ('dn_norm', dn_norm, 0, 5000), + # efficiency of target channel estimate + ('eff_hat_tar', eff_tar, 0, 1), + ('deff_tar', deff_tar, 0, 1), + # efficiency of normalization channel estimate + ('eff_hat_norm', eff_norm, 0, 1), + ('deff_norm', deff_norm, 0, 1), + # nuisance parameters + ('n_norm', n_norm, 0, 20000), + ('eff_tar', eff_tar, 0, 1), + ('eff_norm', eff_norm, 0, 1), + # parameter of interest + ('R', 0.08, 0, 1)] + + for t in params: + cmd = '%s[%f, %f, %f]' % t + wspace.factory(cmd) + wspace.var('R').SetTitle('R') + + # fix all background and signal parameters + for t in params[1:-4]: + name = t[0] + print '=> make %8s = %5.5f constant' % (name, + wspace.var(name).getVal()) + wspace.var(name).setConstant() + + ### Create expressions + express = ['M_norm("(n_hat_norm/dn_norm)^2", n_hat_norm, dn_norm)', + 'tau_norm("n_hat_norm/dn_norm^2", n_hat_norm, dn_norm)', + 'tau_norm_n("tau_norm*n_norm", tau_norm, n_norm)', + 'n("R*n_norm*(eff_tar/eff_norm)", R, n_norm, eff_tar, eff_norm)'] + + for t in express: + cmd = 'expr::%s' % t + wspace.factory(cmd) + + ### Create pdfs + pdfs = [('Poisson', 'pN', '(N, n)'), + ('Poisson', 'pM_norm', '(M_norm, tau_norm_n, 1)'), + ('Gaussian','peff_tar', '(eff_hat_tar, eff_tar, deff_tar)'), + ('Gaussian','peff_norm', '(eff_hat_norm, eff_norm, deff_norm)'), + ] + + prodpdf = '' + for t in pdfs: + wspace.factory('%s::%s%s' % t) + name = t[1] + prodpdf += "%s, " % name + prodpdf = prodpdf[:-2] # remove last ", " + + # multiply the pdfs together. use upper case PROD to + # do this + wspace.factory('PROD::model(%s)' % prodpdf) + + sets = [('obs', 'N'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', 'n_norm,eff_tar,eff_norm')] # nuisance parameters (leave no spaces) + for t in sets: + name, parlist = t + wspace.defineSet(name, parlist) + + #----------------------------------------------------- + # create a dataset + #----------------------------------------------------- + data = rt.RooDataSet('data', 'data', wspace.set('obs')) + data.add(wspace.set('obs')) + # import dataset into workspace + # need last argument to workaround a PyROOT "feature". + # the last argument ensures the correct version of + # the import method is called. + getattr(wspace, 'import')(data, rt.RooCmdArg()) + + #----------------------------------------------------- + # Create model configuration. This is needed for the + # statistical analyses + #----------------------------------------------------- + cfg = rt.RooStats.ModelConfig('cfg') + cfg.SetWorkspace(wspace) + cfg.SetPdf(wspace.pdf('model')) + cfg.SetParametersOfInterest(wspace.set('poi')) + cfg.SetNuisanceParameters(wspace.set('nuis')) + + # import model configuration into workspace + getattr(wspace, 'import')(cfg) + + wspace.Print() + + # write out workspace + wspace.writeToFile(wsfilename) + +def analyzeWorkspace(wsname, wsfilename, R_SM=None): + + # Open workspace file + wsfile = rt.TFile.Open(wsfilename) + + # Get workspace + wspace = wsfile.Get(wsname) + + # Get data + data = wspace.data('data') + + # Get model configuration + cfg = wspace.obj('cfg') + + #----------------------------------------------------- + # Fit model to data + #----------------------------------------------------- + results = wspace.pdf('model').fitTo(data, rt.RooFit.Save()) + results.Print() + + #----------------------------------------------------- + # Compute interval based on profile likelihood + #----------------------------------------------------- + # suppress some (apparently) innocuous warnings + msgservice = rt.RooMsgService.instance() + msgservice.setGlobalKillBelow(rt.RooFit.FATAL) + + R_min, R_max = 0.07, 0.12 + xlabel = 'R_{#psi (2S)}^{e}' + + print 'compute interval using profile likelihood' + plc = rt.RooStats.ProfileLikelihoodCalculator(data, cfg) + CL = 0.683 + plc.SetConfidenceLevel(CL) + plcInterval= plc.GetInterval() + lowerLimit = plcInterval.LowerLimit(wspace.var('R')) + upperLimit = plcInterval.UpperLimit(wspace.var('R')) + + print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ + (100*CL, '%', lowerLimit, upperLimit) + + plcplot = rt.RooStats.LikelihoodIntervalPlot(plcInterval) + plccanvas = rt.TCanvas('fig_PL', 'PL', 800, 600) + plccanvas.cd() + pad = setup_pad() + pad.Draw() + pad.cd() + + plcplot.SetRange(R_min, R_max) + plcplot.SetMaximum(10) + plcplot.SetLineColor(9) + plcplot.Draw() + + # compute an 95% limit on mu by + CL = 0.95 + plc.SetConfidenceLevel(CL) + plcInterval = plc.GetInterval() + lowerLimit = plcInterval.LowerLimit(wspace.var('R')) + upperLimit = plcInterval.UpperLimit(wspace.var('R')) + + print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ + (100*CL, '%', lowerLimit, upperLimit) + + pad.cd() + plcplot2 = rt.RooStats.LikelihoodIntervalPlot(plcInterval) + plcplot2.SetRange(R_min, R_max) + plcplot2.SetMaximum(10) + plcplot2.SetLineColor(8) + plcplot2.Draw("same") + + frame = plcplot.GetPlottedObject() + frame.GetYaxis().SetTitle('Profile of -log(L/L_{min})') + frame.GetXaxis().SetTitle(xlabel) + frame.GetYaxis().SetTitleOffset(0.9) + frame.GetYaxis().SetTitleFont(42) + frame.GetYaxis().SetTitleSize(0.04) + frame.GetYaxis().SetLabelSize(0.04) + frame.GetYaxis().SetLabelFont(42) + frame.GetXaxis().SetTitleOffset(0.9) + frame.GetXaxis().SetTitleFont(42) + frame.GetXaxis().SetTitleSize(0.04) + frame.GetXaxis().SetLabelSize(0.04) + frame.GetXaxis().SetLabelFont(42) + + if R_SM is not None: + pad.cd() + l = rt.TLine(R_SM, 0, R_SM, 10) + l.SetLineColor(2) + l.SetLineWidth(2) + l.Draw("same") + + pad.cd() + CMS_lumi(False) + plccanvas.cd() + plccanvas.Update() + + # save canvases + plccanvas.Draw() + plccanvas.SaveAs('.pdf') + return plccanvas + +if __name__ == "__main__": + + N = 753.36 + n_norm, dn_norm = 8616.26, 147.97 + eff_tar, deff_tar = 0.03430, 0.00024 + eff_norm, deff_norm = 0.03680, 0.00023 + R_SM = 0.0812 + + wsfilename = 'wspace_rpsi2s_electron.root' + + createWorkspace('R_psi2s', wsfilename, N=N, n_norm=n_norm, dn_norm=dn_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, R_SM=R_SM) + + diff --git a/plotting.py b/plotting.py new file mode 100644 index 0000000..d324fa1 --- /dev/null +++ b/plotting.py @@ -0,0 +1,294 @@ +import uproot +import pandas as pd +import numpy as np +from collections import OrderedDict +from scipy import interp +from rootpy.io import root_open +from rootpy.plotting import Hist, Hist2D +from root_numpy import fill_hist, array2root, array2tree +from root_pandas import to_root +import ROOT +from ROOT import RooFit +import itertools +import PyPDF2 +import os, sys, copy +from helper import * + +#ROOT.gErrorIgnoreLevel=ROOT.kError +#ROOT.RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) +ROOT.gROOT.SetBatch(ROOT.kTRUE) +ROOT.gStyle.SetOptStat(0) + +''' +import matplotlib as mpl +mpl.use('agg') +import matplotlib.font_manager +from matplotlib import pyplot as plt +from matplotlib import rc +#.Allow for using TeX mode in matplotlib Figures +rc('font',**{'family':'sans-serif','sans-serif':['Computer Modern Roman']}) +rc('text', usetex=True) +plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern}"] + +ratio=5.0/7.0 +fig_width_pt = 3*246.0 # Get this from LaTeX using \showthe\columnwidth +inches_per_pt = 1.0/72.27 # Convert pt to inch +golden_mean = ratio if ratio != 0.0 else (np.sqrt(5)-1.0)/2.0 # Aesthetic ratio +fig_width = fig_width_pt*inches_per_pt # width in inches +fig_height = fig_width*golden_mean # height in inches +fig_size = [fig_width,fig_height] + +params = {'text.usetex' : True, + 'axes.labelsize': 24, + 'font.size': 24, + 'legend.fontsize': 20, + 'xtick.labelsize': 24, + 'ytick.labelsize': 24, + 'font.family' : 'lmodern', + 'text.latex.unicode': True, + 'axes.grid' : True, + 'text.usetex': True, + 'figure.figsize': fig_size} +plt.rcParams.update(params) +''' + +def pdf_combine(pdf_list, outputfile): + merger = PyPDF2.PdfFileMerger() + for pdf in pdf_list: + merger.append(pdf) + merger.write(outputfile) + +def pdf_sidebyside(out, inputfile): + output = PyPDF2.PdfFileWriter() + reader = [PyPDF2.PdfFileReader(file(in1, "rb")) for in1 in inputfile] + m = min([in1.getNumPages() for in1 in reader]) + print("common pages",m) + for i in range(0,m): + print "adding page common",i + p = [in1.getPage(i) for in1 in reader] + nPages = len(p) + p1 = p[0] + offset_x = 0.0 + for i, p2 in enumerate(p[1:]): + offset_y = -(i+1)*p1.cropBox[1] + (i+1)*p1.cropBox[3] + p1.mergeTranslatedPage(p2, offset_x, offset_y, expand=True) + bounding_box = copy.deepcopy(p1.cropBox) + p1.trimBox.lowerLeft = (bounding_box[0], bounding_box[1]) + p1.trimBox.upperRight = (bounding_box[2], bounding_box[1] + nPages*(bounding_box[3] - bounding_box[1])) + p1.cropBox.lowerLeft = (bounding_box[0], bounding_box[1]) + p1.cropBox.upperRight = (bounding_box[2], bounding_box[1] + nPages*(bounding_box[3] - bounding_box[1])) + output.addPage(p1) + outputStream = file(out, "wb") + output.write(outputStream) + outputStream.close() + +def setup_pad(): + pad = ROOT.TPad("pad", "pad", 0.0, 0.0, 1.0, 1.0) + pad.SetTopMargin(0.08) + pad.SetBottomMargin(0.12) + pad.SetLeftMargin(0.11) + pad.SetRightMargin(0.06) + return pad + +def CMS_lumi(isMC=False): + mark = ROOT.TLatex() + mark.SetNDC() + lumistamp = '2018 (13 TeV)' + fontScale = 1.0 + cmsTextSize = 0.042 * fontScale * 1.25 + extraOverCmsTextSize = 0.76 + extraTextSize = extraOverCmsTextSize*cmsTextSize + mark.SetTextAlign(11) + mark.SetTextSize(cmsTextSize) + mark.SetTextFont(61) + mark.DrawLatex(ROOT.gPad.GetLeftMargin(), 1 - (ROOT.gPad.GetTopMargin() - 0.017), "CMS") + mark.SetTextSize(0.042 * fontScale) + mark.SetTextFont(52) + mark.DrawLatex(ROOT.gPad.GetLeftMargin() + 0.09, 1 - (ROOT.gPad.GetTopMargin() - 0.017), "Simulation Preliminary" if isMC else "Preliminary") + mark.SetTextSize(extraTextSize) + mark.SetTextFont(42) + mark.SetTextAlign(31) + mark.DrawLatex(1 - ROOT.gPad.GetRightMargin(), 1 - (ROOT.gPad.GetTopMargin() - 0.017), lumistamp) + + +def draw_hist(histo, histo_name, x_label, y_label, draw_option='E'): + #histo.SetTitle(histo_name) + histo.GetYaxis().SetTitle(y_label) + histo.GetXaxis().SetTitle(x_label) + histo.SetTitleFont(42) + histo.SetTitleSize(0.05) + histo.GetYaxis().SetTitleOffset(0.9) + histo.GetYaxis().SetTitleFont(42) + histo.GetYaxis().SetTitleSize(0.04) + histo.GetYaxis().SetLabelSize(0.04) + histo.GetYaxis().SetLabelFont(42) + histo.GetXaxis().SetTitleOffset(0.9) + histo.GetXaxis().SetTitleFont(42) + histo.GetXaxis().SetTitleSize(0.04) + histo.GetXaxis().SetLabelSize(0.04) + histo.GetXaxis().SetLabelFont(42) + #histo.Draw(draw_option) + if (histo.GetEntries() > 0): + #histo.DrawNormalized(draw_option) + histo.Draw(draw_option) + else: + histo.Draw(draw_option) + + +def plot_hist(selected_branches, name, color, x_label, hist_bins, outputfile, draw_option='E', logScale=False, xlogScale=False, isMC=False, overflow=False, underflow=False, weights=None): + if not (len(selected_branches) == len(name) == len(color)): + print('lengths do not match') + return + + hist = [Hist(hist_bins['nbins'], hist_bins['xmin'], hist_bins['xmax'], name=n, title='', type='F') for n in name] + _ = [fill_hist(h, branch) for h, branch in zip(hist, selected_branches)] if weights is None else [fill_hist(h, branch, weights=w) for h, branch, w in zip(hist, selected_branches, weights)] + + canvas_name = "c_{}".format(outputfile) + ylabel = 'Events' if len(hist) < 2 else 'Fraction' + + c = ROOT.TCanvas(canvas_name, canvas_name, 800, 600) + c.cd() + pad = setup_pad() + pad.Draw() + pad.cd() + + if logScale: pad.SetLogy() + if xlogScale: pad.SetLogx() + + #l1 = ROOT.TLegend(0.6,0.8,0.92,0.9) + #l1 = ROOT.TLegend(0.7,0.7,0.92,0.9) + l1 = ROOT.TLegend(0.6,0.7,0.92,0.9) + #l1 = ROOT.TLegend(0.6,0.2,0.92,0.4) + l1.SetTextFont(42) + l1.SetTextSize(0.03) + + for h in hist: + x_min = 1 + x_max = h.GetNbinsX() + if overflow: + x_max += 1 + if underflow: + x_min = 0 + h.GetXaxis().SetRange(x_min, x_max) + + y_max = hist[0].GetMaximum() + first_hist = True + for h, n, co in zip(hist, name, color): + h.SetMarkerStyle(0) + h.SetFillStyle(0) + h.SetLineColor(co) + if first_hist: + if len(hist) > 1: + h.SetMaximum(1.3*y_max) + #h.SetMaximum(2.0*y_max) + #h.SetMaximum(1) + draw_hist(h, n, x_label, ylabel, draw_option=draw_option) + first_hist = False + else: + draw_hist(h, n, x_label, ylabel, draw_option='{} SAME'.format(draw_option)) + l1.AddEntry(h, n) + + if len(hist) > 1: l1.Draw("same") + + pad.cd() + CMS_lumi(isMC) + c.cd() + c.Update() + c.SaveAs(outputfile) + c.Close() + +def plot_hist_from_hist(hist, name, color, x_label, y_label, outputfile, draw_option='E', logScale=False, xlogScale=False, isMC=False, overflow=False, underflow=False, weights=None): + if not (len(hist) == len(name) == len(color)): + print('lengths do not match') + return + + canvas_name = "c_{}".format(outputfile) + + c = ROOT.TCanvas(canvas_name, canvas_name, 800, 600) + c.cd() + pad = setup_pad() + pad.Draw() + pad.cd() + + if logScale: pad.SetLogy() + if xlogScale: pad.SetLogx() + + #l1 = ROOT.TLegend(0.6,0.8,0.92,0.9) + #l1 = ROOT.TLegend(0.7,0.7,0.92,0.9) + l1 = ROOT.TLegend(0.6,0.7,0.92,0.9) + #l1 = ROOT.TLegend(0.6,0.2,0.92,0.4) + l1.SetTextFont(42) + l1.SetTextSize(0.03) + + for h in hist: + x_min = 1 + x_max = h.GetNbinsX() + if overflow: + x_max += 1 + if underflow: + x_min = 0 + h.GetXaxis().SetRange(x_min, x_max) + + y_max = hist[0].GetMaximum() + first_hist = True + for h, n, co in zip(hist, name, color): + h.SetMarkerStyle(0) + h.SetFillStyle(0) + h.SetLineColor(co) + if first_hist: + if len(hist) > 1: + h.SetMaximum(1.3*y_max) + #h.SetMaximum(2.0*y_max) + #h.SetMaximum(1) + draw_hist(h, n, x_label, y_label, draw_option=draw_option) + first_hist = False + else: + draw_hist(h, n, x_label, y_label, draw_option='{} SAME'.format(draw_option)) + l1.AddEntry(h, n) + + if len(hist) > 1: l1.Draw("same") + + pad.cd() + CMS_lumi(isMC) + c.cd() + c.Update() + c.SaveAs(outputfile) + c.Close() + +def plot_hist2d(xvar_np, yvar_np, x_label, y_label, hist_bins, outputfile, logScale=False, isMC=False): + hist = Hist2D(hist_bins['nbinx'], hist_bins['xmin'], hist_bins['xmax'], hist_bins['nbiny'], hist_bins['ymin'], hist_bins['ymax'], title='', type='F') + fill_hist(hist, np.vstack((xvar_np[np.isfinite(xvar_np)], yvar_np[np.isfinite(yvar_np)])).T) + + ROOT.gStyle.SetPalette(ROOT.kDarkBodyRadiator) + c = ROOT.TCanvas('c1', 'c1', 800, 600) + pad = setup_pad() + pad.SetLeftMargin(0.08) + pad.SetRightMargin(0.11) + pad.Draw() + pad.cd() + + hist.SetContour(100) + hist.GetYaxis().SetTitle(y_label) + hist.GetXaxis().SetTitle(x_label) + hist.SetTitleFont(42) + hist.SetTitleSize(0.05) + hist.GetYaxis().SetTitleOffset(0.9) + hist.GetYaxis().SetTitleFont(42) + hist.GetYaxis().SetTitleSize(0.04) + hist.GetYaxis().SetLabelSize(0.04) + hist.GetYaxis().SetLabelFont(42) + hist.GetXaxis().SetTitleOffset(0.9) + hist.GetXaxis().SetTitleFont(42) + hist.GetXaxis().SetTitleSize(0.04) + hist.GetXaxis().SetLabelSize(0.04) + hist.GetXaxis().SetLabelFont(42) + if logScale: ROOT.gPad.SetLogz(1) + hist.Draw("colz") + + pad.cd() + CMS_lumi(isMC) + c.cd() + c.Update() + c.SaveAs(outputfile) + c.Close() + From e5c891838e6b200bf73dab08f432d65204c387c7 Mon Sep 17 00:00:00 2001 From: ottolau Date: Fri, 17 Dec 2021 06:26:15 +0100 Subject: [PATCH 03/13] use likelihood from fit --- maximum_likelihood_singleChannel.py | 89 ++++++++++++++++++----------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/maximum_likelihood_singleChannel.py b/maximum_likelihood_singleChannel.py index 2f8febb..665e8cd 100644 --- a/maximum_likelihood_singleChannel.py +++ b/maximum_likelihood_singleChannel.py @@ -6,15 +6,29 @@ rt.gROOT.SetStyle("Plain"); from plotting import * -def createWorkspace(wsname, wsfilename, N=0.0, n_norm=0.0, dn_norm=0.0, eff_tar=0.0, deff_tar=0.0, eff_norm=0.0, deff_norm=0.0): +def importWorkspace(wspace, wsfilename_import, rename): + wsfile_import = rt.TFile.Open(wsfilename_import) + wspace_import = wsfile_import.Get('wspace') + data_import = wspace_import.data('data') + getattr(wspace, 'import')(data_import, rt.RooCmdArg(RooFit.Rename('data_{}'.format(rename)))) + model_import = wspace_import.pdf('model') + getattr(wspace, 'import')(model_import, RooFit.RenameAllVariablesExcept(rename, 'x'), RooFit.RenameAllNodes(rename)) + return wspace + +def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, n_norm=0.0, dn_norm=0.0, eff_tar=0.0, deff_tar=0.0, eff_norm=0.0, deff_norm=0.0): wspace = rt.RooWorkspace(wsname) + wspace = importWorkspace(wspace, wsfilename_tar, 'tar') + wspace = importWorkspace(wspace, wsfilename_norm, 'norm') + + wspace.factory('cat[tar,norm]') + x = wspace.var("x") + data = ROOT.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), RooFit.Import('tar', wspace.data('data_tar')), RooFit.Import('norm', wspace.data('data_norm'))) + getattr(wspace, 'import')(data, rt.RooCmdArg()) + ### Create parameters # observations - params = [('N', N, 0, 20000), - # number of signal in normalization channel estimate - ('n_hat_norm', n_norm, 0, 20000), - ('dn_norm', dn_norm, 0, 5000), + params = [ # efficiency of target channel estimate ('eff_hat_tar', eff_tar, 0, 1), ('deff_tar', deff_tar, 0, 1), @@ -26,7 +40,7 @@ def createWorkspace(wsname, wsfilename, N=0.0, n_norm=0.0, dn_norm=0.0, eff_tar= ('eff_tar', eff_tar, 0, 1), ('eff_norm', eff_norm, 0, 1), # parameter of interest - ('R', 0.08, 0, 1)] + ('R', 0.09, 0.06, 0.15)] for t in params: cmd = '%s[%f, %f, %f]' % t @@ -34,26 +48,33 @@ def createWorkspace(wsname, wsfilename, N=0.0, n_norm=0.0, dn_norm=0.0, eff_tar= wspace.var('R').SetTitle('R') # fix all background and signal parameters - for t in params[1:-4]: + for t in params[0:-4]: name = t[0] print '=> make %8s = %5.5f constant' % (name, wspace.var(name).getVal()) wspace.var(name).setConstant() ### Create expressions - express = ['M_norm("(n_hat_norm/dn_norm)^2", n_hat_norm, dn_norm)', - 'tau_norm("n_hat_norm/dn_norm^2", n_hat_norm, dn_norm)', - 'tau_norm_n("tau_norm*n_norm", tau_norm, n_norm)', - 'n("R*n_norm*(eff_tar/eff_norm)", R, n_norm, eff_tar, eff_norm)'] + express = ['n_tar("R*n_norm*(eff_tar/eff_norm)", R, n_norm, eff_tar, eff_norm)', + 'nKstarPsi2S_tar_modified("frac_partial_tar*n_tar", frac_partial_tar, n_tar)', + 'nKstarJpsi_norm_modified("frac_partial_norm*n_norm", frac_partial_norm, n_norm)', + ] for t in express: cmd = 'expr::%s' % t wspace.factory(cmd) + edit = ['model_tar_modified(model_tar, nsignal_tar=n_tar, nKstarPsi2S_tar=nKstarPsi2S_tar_modified)', + 'model_norm_modified(model_norm, nsignal_norm=n_norm, nKstarJpsi_norm=nKstarJpsi_norm_modified)', + ] + + for t in edit: + cmd = 'EDIT::%s' % t + wspace.factory(cmd) + + wspace.Print("V") ### Create pdfs - pdfs = [('Poisson', 'pN', '(N, n)'), - ('Poisson', 'pM_norm', '(M_norm, tau_norm_n, 1)'), - ('Gaussian','peff_tar', '(eff_hat_tar, eff_tar, deff_tar)'), + pdfs = [('Gaussian','peff_tar', '(eff_hat_tar, eff_tar, deff_tar)'), ('Gaussian','peff_norm', '(eff_hat_norm, eff_norm, deff_norm)'), ] @@ -64,28 +85,20 @@ def createWorkspace(wsname, wsfilename, N=0.0, n_norm=0.0, dn_norm=0.0, eff_tar= prodpdf += "%s, " % name prodpdf = prodpdf[:-2] # remove last ", " + # multiply the pdfs together. use upper case PROD to # do this - wspace.factory('PROD::model(%s)' % prodpdf) + wspace.factory("SIMUL:jointModel(cat,tar=model_tar_modified,norm=model_norm_modified)") + wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) - sets = [('obs', 'N'), # observations + sets = [('obs', 'x'), # observations ('poi', 'R'), # parameter of interest ('nuis', 'n_norm,eff_tar,eff_norm')] # nuisance parameters (leave no spaces) for t in sets: name, parlist = t wspace.defineSet(name, parlist) - #----------------------------------------------------- - # create a dataset - #----------------------------------------------------- - data = rt.RooDataSet('data', 'data', wspace.set('obs')) - data.add(wspace.set('obs')) - # import dataset into workspace - # need last argument to workaround a PyROOT "feature". - # the last argument ensures the correct version of - # the import method is called. - getattr(wspace, 'import')(data, rt.RooCmdArg()) - + #----------------------------------------------------- # Create model configuration. This is needed for the # statistical analyses @@ -121,17 +134,18 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): #----------------------------------------------------- # Fit model to data #----------------------------------------------------- - results = wspace.pdf('model').fitTo(data, rt.RooFit.Save()) + results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save()) results.Print() #----------------------------------------------------- # Compute interval based on profile likelihood #----------------------------------------------------- # suppress some (apparently) innocuous warnings - msgservice = rt.RooMsgService.instance() - msgservice.setGlobalKillBelow(rt.RooFit.FATAL) + #msgservice = rt.RooMsgService.instance() + #msgservice.setGlobalKillBelow(rt.RooFit.FATAL) R_min, R_max = 0.07, 0.12 + NPoints = 20 xlabel = 'R_{#psi (2S)}^{e}' print 'compute interval using profile likelihood' @@ -155,7 +169,8 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): plcplot.SetRange(R_min, R_max) plcplot.SetMaximum(10) plcplot.SetLineColor(9) - plcplot.Draw() + plcplot.SetNPoints(NPoints) + plcplot.Draw("tf1") # compute an 95% limit on mu by CL = 0.95 @@ -172,7 +187,8 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): plcplot2.SetRange(R_min, R_max) plcplot2.SetMaximum(10) plcplot2.SetLineColor(8) - plcplot2.Draw("same") + plcplot2.SetNPoints(NPoints) + plcplot2.Draw("tf1 same") frame = plcplot.GetPlottedObject() frame.GetYaxis().SetTitle('Profile of -log(L/L_{min})') @@ -188,9 +204,12 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): frame.GetXaxis().SetLabelSize(0.04) frame.GetXaxis().SetLabelFont(42) + pad.Update() + uymax = rt.gPad.GetUymax() + uymin = rt.gPad.GetUymin() if R_SM is not None: pad.cd() - l = rt.TLine(R_SM, 0, R_SM, 10) + l = rt.TLine(R_SM, uymin, R_SM, uymax) l.SetLineColor(2) l.SetLineWidth(2) l.Draw("same") @@ -213,9 +232,11 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): eff_norm, deff_norm = 0.03680, 0.00023 R_SM = 0.0812 + wsfilename_tar = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' + wsfilename_norm = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' wsfilename = 'wspace_rpsi2s_electron.root' - createWorkspace('R_psi2s', wsfilename, N=N, n_norm=n_norm, dn_norm=dn_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) + createWorkspace('R_psi2s', wsfilename, wsfilename_tar, wsfilename_norm, n_norm=n_norm, dn_norm=dn_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) plccanvas = analyzeWorkspace('R_psi2s', wsfilename, R_SM=R_SM) From 745a778554b3c2521592228fee3e092c00c92344 Mon Sep 17 00:00:00 2001 From: ottolau Date: Sat, 18 Dec 2021 20:21:26 +0100 Subject: [PATCH 04/13] added max likelihood for double ratio --- maximum_likelihood_rpsi2s.py | 319 ++++++++++++++++++++++++++++ maximum_likelihood_singleChannel.py | 25 ++- 2 files changed, 337 insertions(+), 7 deletions(-) create mode 100644 maximum_likelihood_rpsi2s.py diff --git a/maximum_likelihood_rpsi2s.py b/maximum_likelihood_rpsi2s.py new file mode 100644 index 0000000..756628b --- /dev/null +++ b/maximum_likelihood_rpsi2s.py @@ -0,0 +1,319 @@ +import os,sys,re +from time import sleep +import math +import ROOT as rt +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from plotting import * + +def importWorkspace(wspace, wsfilename_import, rename): + wsfile_import = rt.TFile.Open(wsfilename_import) + wspace_import = wsfile_import.Get('wspace') + data_import = wspace_import.data('data') + getattr(wspace, 'import')(data_import, rt.RooCmdArg(RooFit.Rename('data_{}'.format(rename)))) + model_import = wspace_import.pdf('model') + getattr(wspace, 'import')(model_import, RooFit.RenameAllVariablesExcept(rename, 'x'), RooFit.RenameAllNodes(rename)) + return wspace + +def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, + eff_ele_psi2s=0.0, deff_ele_psi2s=0.0, eff_ele_jpsi=0.0, deff_ele_jpsi=0.0, + eff_mu_psi2s=0.0, deff_mu_psi2s=0.0, eff_mu_jpsi=0.0, deff_mu_jpsi=0.0, + ): + + wspace = rt.RooWorkspace(wsname) + wspace = importWorkspace(wspace, wsfilename_ele_psi2s, 'ele_psi2s') + wspace = importWorkspace(wspace, wsfilename_ele_jpsi, 'ele_jpsi') + wspace = importWorkspace(wspace, wsfilename_mu_psi2s, 'mu_psi2s') + wspace = importWorkspace(wspace, wsfilename_mu_jpsi, 'mu_jpsi') + + wspace.factory('cat[ele_psi2s,ele_jpsi,mu_psi2s,mu_jpsi]') + x = wspace.var("x") + data = ROOT.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), + RooFit.Import('ele_psi2s', wspace.data('data_ele_psi2s')), RooFit.Import('ele_jpsi', wspace.data('data_ele_jpsi')), + RooFit.Import('mu_psi2s', wspace.data('data_mu_psi2s')), RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), + ) + getattr(wspace, 'import')(data, rt.RooCmdArg()) + + br_jpsi_ee, dbr_jpsi_ee= 0.05971, 0.00032 + br_psi2s_ee, dbr_psi2s_ee = 7.93e-3, 0.17e-3 + br_jpsi_mumu, dbr_jpsi_mumu= 0.05961, 0.00033 + br_psi2s_mumu, dbr_psi2s_mumu = 8.0e-3, 0.6e-3 + + + ### Create parameters + # observations + params = [ + # efficiency of electron psi(2S) estimate + ('eff_hat_ele_psi2s', eff_ele_psi2s, 1.e-6, 1), + ('deff_ele_psi2s', deff_ele_psi2s, 1.e-6, 1), + # efficiency of electron J/psi channel estimate + ('eff_hat_ele_jpsi', eff_ele_jpsi, 1.e-6, 1), + ('deff_ele_jpsi', deff_ele_jpsi, 1.e-6, 1), + # branching fraction of J/psi -> ee + ('br_hat_jpsi_ee', br_jpsi_ee, 1.e-6, 1), + ('dbr_jpsi_ee', dbr_jpsi_ee, 1.e-6, 1), + # branching fraction of psi(2S) -> ee + ('br_hat_psi2s_ee', br_psi2s_ee, 1.e-6, 1), + ('dbr_psi2s_ee', dbr_psi2s_ee, 1.e-6, 1), + # efficiency of muon psi(2S) estimate + ('eff_hat_mu_psi2s', eff_mu_psi2s, 1.e-6, 1), + ('deff_mu_psi2s', deff_mu_psi2s, 1.e-6, 1), + # efficiency of muon J/psi channel estimate + ('eff_hat_mu_jpsi', eff_mu_jpsi, 1.e-6, 1), + ('deff_mu_jpsi', deff_mu_jpsi, 1.e-6, 1), + # branching fraction of J/psi -> mu mu + ('br_hat_jpsi_mumu', br_jpsi_mumu, 1.e-6, 1), + ('dbr_jpsi_mumu', dbr_jpsi_mumu, 1.e-6, 1), + # branching fraction of psi(2S) -> mu mu + ('br_hat_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), + ('dbr_psi2s_mumu', dbr_psi2s_mumu, 1.e-6, 1), + # nuisance parameters + ('n_ele_jpsi', 9000, 1.e-6, 20000), + ('eff_ele_psi2s', eff_ele_psi2s, 1.e-6, 1), + ('eff_ele_jpsi', eff_ele_jpsi, 1.e-6, 1), + ('br_psi2s_ee', br_psi2s_ee, 1.e-6, 1), + ('br_jpsi_ee', br_jpsi_ee, 1.e-6, 1), + ('n_mu_jpsi', 9000, 1.e-6, 20000), + ('eff_mu_psi2s', eff_mu_psi2s, 1.e-6, 1), + ('eff_mu_jpsi', eff_mu_jpsi, 1.e-6, 1), + ('br_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), + ('br_jpsi_mumu', br_jpsi_mumu, 1.e-6, 1), + # parameter of interest + ('r_br', 0.7, 0.5, 1.1), + ('R', 1.0, 0.5, 2), + ] + + for t in params: + cmd = '%s[%f, %f, %f]' % t + wspace.factory(cmd) + wspace.var('R').SetTitle('R') + + # fix all background and signal parameters + for t in params[0:-12]: + name = t[0] + print '=> make %8s = %5.5f constant' % (name, + wspace.var(name).getVal()) + wspace.var(name).setConstant() + + ### Create expressions + express = ['n_ele_psi2s("(r_br/R)*n_ele_jpsi*(br_psi2s_ee/br_jpsi_ee)*(eff_ele_psi2s/eff_ele_jpsi)", r_br, R, n_ele_jpsi, br_psi2s_ee, br_jpsi_ee, eff_ele_psi2s, eff_ele_jpsi)', + 'nKstarPsi2S_ele_psi2s_modified("frac_partial_ele_psi2s*n_ele_psi2s", frac_partial_ele_psi2s, n_ele_psi2s)', + 'nKstarJpsi_ele_jpsi_modified("frac_partial_ele_jpsi*n_ele_jpsi", frac_partial_ele_jpsi, n_ele_jpsi)', + 'n_mu_psi2s("r_br*n_mu_jpsi*(br_psi2s_mumu/br_jpsi_mumu)*(eff_mu_psi2s/eff_mu_jpsi)", r_br, n_mu_jpsi, br_psi2s_mumu, br_jpsi_mumu, eff_mu_psi2s, eff_mu_jpsi)', + 'nKstarPsi2S_mu_psi2s_modified("frac_partial_mu_psi2s*n_mu_psi2s", frac_partial_mu_psi2s, n_mu_psi2s)', + 'nKstarJpsi_mu_jpsi_modified("frac_partial_mu_jpsi*n_mu_jpsi", frac_partial_mu_jpsi, n_mu_jpsi)', + ] + + for t in express: + cmd = 'expr::%s' % t + wspace.factory(cmd) + + edit = ['model_ele_psi2s_modified(model_ele_psi2s, nsignal_ele_psi2s=n_ele_psi2s, nKstarPsi2S_ele_psi2s=nKstarPsi2S_ele_psi2s_modified)', + 'model_ele_jpsi_modified(model_ele_jpsi, nsignal_ele_jpsi=n_ele_jpsi, nKstarJpsi_ele_jpsi=nKstarJpsi_ele_jpsi_modified)', + 'model_mu_psi2s_modified(model_mu_psi2s, nsignal_mu_psi2s=n_mu_psi2s, nKstarPsi2S_mu_psi2s=nKstarPsi2S_mu_psi2s_modified)', + 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi, nKstarJpsi_mu_jpsi=nKstarJpsi_mu_jpsi_modified)', + ] + + for t in edit: + cmd = 'EDIT::%s' % t + wspace.factory(cmd) + + wspace.Print("V") + ### Create pdfs + pdfs = [('Gaussian','peff_ele_psi2s', '(eff_hat_ele_psi2s, eff_ele_psi2s, deff_ele_psi2s)'), + ('Gaussian','peff_ele_jpsi', '(eff_hat_ele_jpsi, eff_ele_jpsi, deff_ele_jpsi)'), + ('Gaussian','peff_br_psi2s_ee', '(br_hat_psi2s_ee, br_psi2s_ee, dbr_psi2s_ee)'), + ('Gaussian','peff_br_jpsi_ee', '(br_hat_jpsi_ee, br_jpsi_ee, dbr_jpsi_ee)'), + ('Gaussian','peff_mu_psi2s', '(eff_hat_mu_psi2s, eff_mu_psi2s, deff_mu_psi2s)'), + ('Gaussian','peff_mu_jpsi', '(eff_hat_mu_jpsi, eff_mu_jpsi, deff_mu_jpsi)'), + ('Gaussian','peff_br_psi2s_mumu', '(br_hat_psi2s_mumu, br_psi2s_mumu, dbr_psi2s_mumu)'), + ('Gaussian','peff_br_jpsi_mumu', '(br_hat_jpsi_mumu, br_jpsi_mumu, dbr_jpsi_mumu)'), + ] + + prodpdf = '' + for t in pdfs: + wspace.factory('%s::%s%s' % t) + name = t[1] + prodpdf += "%s, " % name + prodpdf = prodpdf[:-2] # remove last ", " + + + # multiply the pdfs together. use upper case PROD to + # do this + wspace.factory("SIMUL:jointModel(cat,ele_psi2s=model_ele_psi2s_modified,ele_jpsi=model_ele_jpsi_modified,mu_psi2s=model_mu_psi2s_modified,mu_jpsi=model_mu_jpsi_modified)") + wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) + + nuis_excluded = ['x', 'R', 'cat', + 'deff_ele_jpsi', 'deff_ele_psi2s', 'eff_hat_ele_jpsi', 'eff_hat_ele_psi2s', + 'dbr_jpsi_ee', 'dbr_psi2s_ee', 'br_hat_jpsi_ee', 'br_hat_psi2s_ee' + 'deff_mu_jpsi', 'deff_mu_psi2s', 'eff_hat_mu_jpsi', 'eff_hat_mu_psi2s', + 'dbr_jpsi_mumu', 'dbr_psi2s_mumu', 'br_hat_jpsi_mumu', 'br_hat_psi2s_mumu' + ] + nuis = [] + params = wspace.pdf('model').getVariables() + params_iter = params.createIterator() + param = params_iter.Next() + while param : + if param.GetName() not in nuis_excluded: + nuis.append(param.GetName()) + param = params_iter.Next() + nuis = ','.join(nuis) + + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis)] # nuisance parameters (leave no spaces) + #('nuis', 'n_ele_jpsi,eff_ele_psi2s,eff_ele_jpsi')] # nuisance parameters (leave no spaces) + + for t in sets: + name, parlist = t + wspace.defineSet(name, parlist) + + + #----------------------------------------------------- + # Create model configuration. This is needed for the + # statistical analyses + #----------------------------------------------------- + cfg = rt.RooStats.ModelConfig('cfg') + cfg.SetWorkspace(wspace) + cfg.SetPdf(wspace.pdf('model')) + cfg.SetParametersOfInterest(wspace.set('poi')) + cfg.SetNuisanceParameters(wspace.set('nuis')) + + # import model configuration into workspace + getattr(wspace, 'import')(cfg) + + wspace.Print() + + # write out workspace + wspace.writeToFile(wsfilename) + +def analyzeWorkspace(wsname, wsfilename, R_SM=None): + + # Open workspace file + wsfile = rt.TFile.Open(wsfilename) + + # Get workspace + wspace = wsfile.Get(wsname) + + # Get data + data = wspace.data('data') + + # Get model configuration + cfg = wspace.obj('cfg') + + #----------------------------------------------------- + # Fit model to data + #----------------------------------------------------- + results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save(), RooFit.NumCPU(8)) + results.Print() + + #----------------------------------------------------- + # Compute interval based on profile likelihood + #----------------------------------------------------- + # suppress some (apparently) innocuous warnings + #msgservice = rt.RooMsgService.instance() + #msgservice.setGlobalKillBelow(rt.RooFit.FATAL) + + R_min, R_max = 0.7, 1.1 + NPoints = 20 + xlabel = 'R_{#psi(2S)}' + + print 'compute interval using profile likelihood' + plc = rt.RooStats.ProfileLikelihoodCalculator(data, cfg) + CL = 0.683 + plc.SetConfidenceLevel(CL) + plcInterval= plc.GetInterval() + lowerLimit = plcInterval.LowerLimit(wspace.var('R')) + upperLimit = plcInterval.UpperLimit(wspace.var('R')) + + print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ + (100*CL, '%', lowerLimit, upperLimit) + + plcplot = rt.RooStats.LikelihoodIntervalPlot(plcInterval) + plccanvas = rt.TCanvas('fig_PL', 'PL', 800, 600) + plccanvas.cd() + pad = setup_pad() + pad.Draw() + pad.cd() + + plcplot.SetRange(R_min, R_max) + plcplot.SetMaximum(10) + plcplot.SetLineColor(9) + plcplot.SetNPoints(NPoints) + plcplot.Draw("tf1") + + # compute an 95% limit on mu by + CL = 0.95 + plc.SetConfidenceLevel(CL) + plcInterval = plc.GetInterval() + lowerLimit = plcInterval.LowerLimit(wspace.var('R')) + upperLimit = plcInterval.UpperLimit(wspace.var('R')) + + print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ + (100*CL, '%', lowerLimit, upperLimit) + + + pad.cd() + plcplot2 = rt.RooStats.LikelihoodIntervalPlot(plcInterval) + plcplot2.SetRange(R_min, R_max) + plcplot2.SetMaximum(10) + plcplot2.SetLineColor(8) + plcplot2.SetNPoints(NPoints) + plcplot2.Draw("tf1 same") + + frame = plcplot.GetPlottedObject() + frame.GetYaxis().SetTitle('Profile of -log(L/L_{min})') + frame.GetXaxis().SetTitle(xlabel) + frame.GetYaxis().SetTitleOffset(0.9) + frame.GetYaxis().SetTitleFont(42) + frame.GetYaxis().SetTitleSize(0.04) + frame.GetYaxis().SetLabelSize(0.04) + frame.GetYaxis().SetLabelFont(42) + frame.GetXaxis().SetTitleOffset(0.9) + frame.GetXaxis().SetTitleFont(42) + frame.GetXaxis().SetTitleSize(0.04) + frame.GetXaxis().SetLabelSize(0.04) + frame.GetXaxis().SetLabelFont(42) + + pad.Update() + uymax = rt.gPad.GetUymax() + uymin = rt.gPad.GetUymin() + if R_SM is not None: + pad.cd() + l = rt.TLine(R_SM, uymin, R_SM, uymax) + l.SetLineColor(2) + l.SetLineWidth(2) + l.Draw("same") + + pad.cd() + CMS_lumi(False) + plccanvas.cd() + plccanvas.Update() + + # save canvases + plccanvas.Draw() + plccanvas.SaveAs('.pdf') + return plccanvas + + +if __name__ == "__main__": + + eff_ele_psi2s, deff_ele_psi2s = 0.03430, 0.00024 + eff_ele_jpsi, deff_ele_jpsi = 0.03680, 0.00023 + eff_mu_psi2s, deff_mu_psi2s = 0.03430, 0.00024 + eff_mu_jpsi, deff_mu_jpsi = 0.03680, 0.00023 + R_SM = 1.0 + + wsfilename_ele_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' + wsfilename_ele_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' + wsfilename_mu_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' + wsfilename_mu_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' + wsfilename = 'wspace_rpsi2s.root' + + createWorkspace('R_psi2s', wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, + eff_ele_psi2s=eff_ele_psi2s, deff_ele_psi2s=deff_ele_psi2s, eff_ele_jpsi=eff_ele_jpsi, deff_ele_jpsi=deff_ele_jpsi, + eff_mu_psi2s=eff_mu_psi2s, deff_mu_psi2s=deff_mu_psi2s, eff_mu_jpsi=eff_mu_jpsi, deff_mu_jpsi=deff_mu_jpsi, + ) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, R_SM=R_SM) + + diff --git a/maximum_likelihood_singleChannel.py b/maximum_likelihood_singleChannel.py index 665e8cd..b9fa209 100644 --- a/maximum_likelihood_singleChannel.py +++ b/maximum_likelihood_singleChannel.py @@ -15,7 +15,7 @@ def importWorkspace(wspace, wsfilename_import, rename): getattr(wspace, 'import')(model_import, RooFit.RenameAllVariablesExcept(rename, 'x'), RooFit.RenameAllNodes(rename)) return wspace -def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, n_norm=0.0, dn_norm=0.0, eff_tar=0.0, deff_tar=0.0, eff_norm=0.0, deff_norm=0.0): +def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar=0.0, deff_tar=0.0, eff_norm=0.0, deff_norm=0.0): wspace = rt.RooWorkspace(wsname) wspace = importWorkspace(wspace, wsfilename_tar, 'tar') wspace = importWorkspace(wspace, wsfilename_norm, 'norm') @@ -36,7 +36,7 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, n_norm= ('eff_hat_norm', eff_norm, 0, 1), ('deff_norm', deff_norm, 0, 1), # nuisance parameters - ('n_norm', n_norm, 0, 20000), + ('n_norm', 9000, 0, 20000), ('eff_tar', eff_tar, 0, 1), ('eff_norm', eff_norm, 0, 1), # parameter of interest @@ -91,9 +91,22 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, n_norm= wspace.factory("SIMUL:jointModel(cat,tar=model_tar_modified,norm=model_norm_modified)") wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) + nuis_excluded = ['x', 'R', 'cat', 'deff_norm', 'deff_tar', 'eff_hat_norm', 'eff_hat_tar'] + nuis = [] + params = wspace.pdf('model').getVariables() + params_iter = params.createIterator() + param = params_iter.Next() + while param : + if param.GetName() not in nuis_excluded: + nuis.append(param.GetName()) + param = params_iter.Next() + nuis = ','.join(nuis) + sets = [('obs', 'x'), # observations ('poi', 'R'), # parameter of interest - ('nuis', 'n_norm,eff_tar,eff_norm')] # nuisance parameters (leave no spaces) + ('nuis', nuis)] # nuisance parameters (leave no spaces) + #('nuis', 'n_norm,eff_tar,eff_norm')] # nuisance parameters (leave no spaces) + for t in sets: name, parlist = t wspace.defineSet(name, parlist) @@ -134,7 +147,7 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): #----------------------------------------------------- # Fit model to data #----------------------------------------------------- - results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save()) + results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save(), RooFit.NumCPU(8)) results.Print() #----------------------------------------------------- @@ -226,8 +239,6 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): if __name__ == "__main__": - N = 753.36 - n_norm, dn_norm = 8616.26, 147.97 eff_tar, deff_tar = 0.03430, 0.00024 eff_norm, deff_norm = 0.03680, 0.00023 R_SM = 0.0812 @@ -236,7 +247,7 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): wsfilename_norm = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' wsfilename = 'wspace_rpsi2s_electron.root' - createWorkspace('R_psi2s', wsfilename, wsfilename_tar, wsfilename_norm, n_norm=n_norm, dn_norm=dn_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) + createWorkspace('R_psi2s', wsfilename, wsfilename_tar, wsfilename_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) plccanvas = analyzeWorkspace('R_psi2s', wsfilename, R_SM=R_SM) From 6b488b67645600c58532e17a0ea9bae36521d2b1 Mon Sep 17 00:00:00 2001 From: ottolau Date: Sun, 2 Jan 2022 23:52:28 +0100 Subject: [PATCH 05/13] added code for PF-LP --- maximum_likelihood_rpsi2s.py | 178 +++----------- maximum_likelihood_rpsi2s_combinedEleCh.py | 261 +++++++++++++++++++++ maximum_likelihood_singleChannel.py | 153 ++---------- utils_likelihood.py | 199 ++++++++++++++++ 4 files changed, 525 insertions(+), 266 deletions(-) create mode 100644 maximum_likelihood_rpsi2s_combinedEleCh.py create mode 100644 utils_likelihood.py diff --git a/maximum_likelihood_rpsi2s.py b/maximum_likelihood_rpsi2s.py index 756628b..21a987b 100644 --- a/maximum_likelihood_rpsi2s.py +++ b/maximum_likelihood_rpsi2s.py @@ -2,18 +2,10 @@ from time import sleep import math import ROOT as rt +from ROOT import RooFit rt.gROOT.SetBatch(True); rt.gROOT.SetStyle("Plain"); -from plotting import * - -def importWorkspace(wspace, wsfilename_import, rename): - wsfile_import = rt.TFile.Open(wsfilename_import) - wspace_import = wsfile_import.Get('wspace') - data_import = wspace_import.data('data') - getattr(wspace, 'import')(data_import, rt.RooCmdArg(RooFit.Rename('data_{}'.format(rename)))) - model_import = wspace_import.pdf('model') - getattr(wspace, 'import')(model_import, RooFit.RenameAllVariablesExcept(rename, 'x'), RooFit.RenameAllNodes(rename)) - return wspace +from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, eff_ele_psi2s=0.0, deff_ele_psi2s=0.0, eff_ele_jpsi=0.0, deff_ele_jpsi=0.0, @@ -28,10 +20,10 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps wspace.factory('cat[ele_psi2s,ele_jpsi,mu_psi2s,mu_jpsi]') x = wspace.var("x") - data = ROOT.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), - RooFit.Import('ele_psi2s', wspace.data('data_ele_psi2s')), RooFit.Import('ele_jpsi', wspace.data('data_ele_jpsi')), - RooFit.Import('mu_psi2s', wspace.data('data_mu_psi2s')), RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), - ) + data = rt.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), + RooFit.Import('ele_psi2s', wspace.data('data_ele_psi2s')), RooFit.Import('ele_jpsi', wspace.data('data_ele_jpsi')), + RooFit.Import('mu_psi2s', wspace.data('data_mu_psi2s')), RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), + ) getattr(wspace, 'import')(data, rt.RooCmdArg()) br_jpsi_ee, dbr_jpsi_ee= 0.05971, 0.00032 @@ -68,19 +60,19 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps ('br_hat_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), ('dbr_psi2s_mumu', dbr_psi2s_mumu, 1.e-6, 1), # nuisance parameters - ('n_ele_jpsi', 9000, 1.e-6, 20000), - ('eff_ele_psi2s', eff_ele_psi2s, 1.e-6, 1), - ('eff_ele_jpsi', eff_ele_jpsi, 1.e-6, 1), - ('br_psi2s_ee', br_psi2s_ee, 1.e-6, 1), - ('br_jpsi_ee', br_jpsi_ee, 1.e-6, 1), - ('n_mu_jpsi', 9000, 1.e-6, 20000), - ('eff_mu_psi2s', eff_mu_psi2s, 1.e-6, 1), - ('eff_mu_jpsi', eff_mu_jpsi, 1.e-6, 1), - ('br_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), - ('br_jpsi_mumu', br_jpsi_mumu, 1.e-6, 1), + ('n_ele_jpsi', 8617, 8000, 10000), + ('eff_ele_psi2s', eff_ele_psi2s, eff_ele_psi2s-5.0*deff_ele_psi2s, eff_ele_psi2s+5.0*deff_ele_psi2s), + ('eff_ele_jpsi', eff_ele_jpsi, eff_ele_jpsi-5.0*deff_ele_jpsi, eff_ele_jpsi+5.0*deff_ele_jpsi), + ('br_psi2s_ee', br_psi2s_ee, br_psi2s_ee-5.0*dbr_psi2s_ee, br_psi2s_ee+5.0*dbr_psi2s_ee), + ('br_jpsi_ee', br_jpsi_ee, br_jpsi_ee-5.0*dbr_jpsi_ee, br_jpsi_ee+5.0*dbr_jpsi_ee), + ('n_mu_jpsi', 8617, 8000, 10000), + ('eff_mu_psi2s', eff_mu_psi2s, eff_mu_psi2s-5.0*deff_mu_psi2s, eff_mu_psi2s+5.0*deff_mu_psi2s), + ('eff_mu_jpsi', eff_mu_jpsi, eff_mu_jpsi-5.0*deff_mu_jpsi, eff_mu_jpsi+5.0*deff_mu_jpsi), + ('br_psi2s_mumu', br_psi2s_mumu, br_psi2s_mumu-5.0*dbr_psi2s_mumu, br_psi2s_mumu+5.0*dbr_psi2s_mumu), + ('br_jpsi_mumu', br_jpsi_mumu, br_jpsi_mumu-5.0*dbr_jpsi_mumu, br_jpsi_mumu+5.0*dbr_jpsi_mumu), # parameter of interest - ('r_br', 0.7, 0.5, 1.1), - ('R', 1.0, 0.5, 2), + ('r_br', 0.7, 0.3, 1.5), + ('R', 1.0, 0.5, 1.5), ] for t in params: @@ -149,19 +141,31 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps 'deff_mu_jpsi', 'deff_mu_psi2s', 'eff_hat_mu_jpsi', 'eff_hat_mu_psi2s', 'dbr_jpsi_mumu', 'dbr_psi2s_mumu', 'br_hat_jpsi_mumu', 'br_hat_psi2s_mumu' ] + + ### Define global observables + ### they are not being fitted and they are not loaded from a dataset, + ### but some knowledge exists that allows to set them to a specific value + ### Global Observables are generated once per toy + globs = ['eff_ele_psi2s', 'eff_ele_jpsi', 'br_psi2s_ee', 'br_jpsi_ee', + 'eff_mu_psi2s', 'eff_mu_jpsi', 'br_psi2s_mumu', 'br_jpsi_mumu', + ] + nuis = [] params = wspace.pdf('model').getVariables() params_iter = params.createIterator() param = params_iter.Next() while param : - if param.GetName() not in nuis_excluded: + if param.GetName() not in (nuis_excluded+globs): nuis.append(param.GetName()) param = params_iter.Next() nuis = ','.join(nuis) + globs = ','.join(globs) - sets = [('obs', 'x'), # observations - ('poi', 'R'), # parameter of interest - ('nuis', nuis)] # nuisance parameters (leave no spaces) + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis), # nuisance parameters (leave no spaces) + ('globs', globs), + ] #('nuis', 'n_ele_jpsi,eff_ele_psi2s,eff_ele_jpsi')] # nuisance parameters (leave no spaces) for t in sets: @@ -178,6 +182,7 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps cfg.SetPdf(wspace.pdf('model')) cfg.SetParametersOfInterest(wspace.set('poi')) cfg.SetNuisanceParameters(wspace.set('nuis')) + cfg.SetGlobalObservables(wspace.set('globs')) # import model configuration into workspace getattr(wspace, 'import')(cfg) @@ -187,113 +192,6 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps # write out workspace wspace.writeToFile(wsfilename) -def analyzeWorkspace(wsname, wsfilename, R_SM=None): - - # Open workspace file - wsfile = rt.TFile.Open(wsfilename) - - # Get workspace - wspace = wsfile.Get(wsname) - - # Get data - data = wspace.data('data') - - # Get model configuration - cfg = wspace.obj('cfg') - - #----------------------------------------------------- - # Fit model to data - #----------------------------------------------------- - results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save(), RooFit.NumCPU(8)) - results.Print() - - #----------------------------------------------------- - # Compute interval based on profile likelihood - #----------------------------------------------------- - # suppress some (apparently) innocuous warnings - #msgservice = rt.RooMsgService.instance() - #msgservice.setGlobalKillBelow(rt.RooFit.FATAL) - - R_min, R_max = 0.7, 1.1 - NPoints = 20 - xlabel = 'R_{#psi(2S)}' - - print 'compute interval using profile likelihood' - plc = rt.RooStats.ProfileLikelihoodCalculator(data, cfg) - CL = 0.683 - plc.SetConfidenceLevel(CL) - plcInterval= plc.GetInterval() - lowerLimit = plcInterval.LowerLimit(wspace.var('R')) - upperLimit = plcInterval.UpperLimit(wspace.var('R')) - - print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ - (100*CL, '%', lowerLimit, upperLimit) - - plcplot = rt.RooStats.LikelihoodIntervalPlot(plcInterval) - plccanvas = rt.TCanvas('fig_PL', 'PL', 800, 600) - plccanvas.cd() - pad = setup_pad() - pad.Draw() - pad.cd() - - plcplot.SetRange(R_min, R_max) - plcplot.SetMaximum(10) - plcplot.SetLineColor(9) - plcplot.SetNPoints(NPoints) - plcplot.Draw("tf1") - - # compute an 95% limit on mu by - CL = 0.95 - plc.SetConfidenceLevel(CL) - plcInterval = plc.GetInterval() - lowerLimit = plcInterval.LowerLimit(wspace.var('R')) - upperLimit = plcInterval.UpperLimit(wspace.var('R')) - - print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ - (100*CL, '%', lowerLimit, upperLimit) - - - pad.cd() - plcplot2 = rt.RooStats.LikelihoodIntervalPlot(plcInterval) - plcplot2.SetRange(R_min, R_max) - plcplot2.SetMaximum(10) - plcplot2.SetLineColor(8) - plcplot2.SetNPoints(NPoints) - plcplot2.Draw("tf1 same") - - frame = plcplot.GetPlottedObject() - frame.GetYaxis().SetTitle('Profile of -log(L/L_{min})') - frame.GetXaxis().SetTitle(xlabel) - frame.GetYaxis().SetTitleOffset(0.9) - frame.GetYaxis().SetTitleFont(42) - frame.GetYaxis().SetTitleSize(0.04) - frame.GetYaxis().SetLabelSize(0.04) - frame.GetYaxis().SetLabelFont(42) - frame.GetXaxis().SetTitleOffset(0.9) - frame.GetXaxis().SetTitleFont(42) - frame.GetXaxis().SetTitleSize(0.04) - frame.GetXaxis().SetLabelSize(0.04) - frame.GetXaxis().SetLabelFont(42) - - pad.Update() - uymax = rt.gPad.GetUymax() - uymin = rt.gPad.GetUymin() - if R_SM is not None: - pad.cd() - l = rt.TLine(R_SM, uymin, R_SM, uymax) - l.SetLineColor(2) - l.SetLineWidth(2) - l.Draw("same") - - pad.cd() - CMS_lumi(False) - plccanvas.cd() - plccanvas.Update() - - # save canvases - plccanvas.Draw() - plccanvas.SaveAs('.pdf') - return plccanvas if __name__ == "__main__": @@ -303,7 +201,9 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): eff_mu_psi2s, deff_mu_psi2s = 0.03430, 0.00024 eff_mu_jpsi, deff_mu_jpsi = 0.03680, 0.00023 R_SM = 1.0 - + R_min, R_max = 0.8, 1.2 + xlabel = 'R_{#psi(2S)}' + wsfilename_ele_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' wsfilename_ele_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' wsfilename_mu_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' @@ -314,6 +214,6 @@ def analyzeWorkspace(wsname, wsfilename, R_SM=None): eff_ele_psi2s=eff_ele_psi2s, deff_ele_psi2s=deff_ele_psi2s, eff_ele_jpsi=eff_ele_jpsi, deff_ele_jpsi=deff_ele_jpsi, eff_mu_psi2s=eff_mu_psi2s, deff_mu_psi2s=deff_mu_psi2s, eff_mu_jpsi=eff_mu_jpsi, deff_mu_jpsi=deff_mu_jpsi, ) - plccanvas = analyzeWorkspace('R_psi2s', wsfilename, R_SM=R_SM) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True) diff --git a/maximum_likelihood_rpsi2s_combinedEleCh.py b/maximum_likelihood_rpsi2s_combinedEleCh.py new file mode 100644 index 0000000..7fcb73d --- /dev/null +++ b/maximum_likelihood_rpsi2s_combinedEleCh.py @@ -0,0 +1,261 @@ +import os,sys,re +import time +from time import sleep +import math +import ROOT as rt +from ROOT import RooFit +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace + +def createWorkspace(wsname, wsfilename, + wsfilename_pfe_psi2s, wsfilename_pfe_jpsi, + wsfilename_mixe_psi2s, wsfilename_mixe_jpsi, + wsfilename_mu_psi2s, wsfilename_mu_jpsi, + eff_pfe_psi2s=0.0, deff_pfe_psi2s=0.0, eff_pfe_jpsi=0.0, deff_pfe_jpsi=0.0, + eff_mixe_psi2s=0.0, deff_mixe_psi2s=0.0, eff_mixe_jpsi=0.0, deff_mixe_jpsi=0.0, + eff_mu_psi2s=0.0, deff_mu_psi2s=0.0, eff_mu_jpsi=0.0, deff_mu_jpsi=0.0, + ): + + wspace = rt.RooWorkspace(wsname) + wspace = importWorkspace(wspace, wsfilename_pfe_psi2s, 'pfe_psi2s') + wspace = importWorkspace(wspace, wsfilename_pfe_jpsi, 'pfe_jpsi') + wspace = importWorkspace(wspace, wsfilename_mixe_psi2s, 'mixe_psi2s') + wspace = importWorkspace(wspace, wsfilename_mixe_jpsi, 'mixe_jpsi') + wspace = importWorkspace(wspace, wsfilename_mu_psi2s, 'mu_psi2s') + wspace = importWorkspace(wspace, wsfilename_mu_jpsi, 'mu_jpsi') + + wspace.factory('cat[pfe_psi2s,pfe_jpsi,mixe_psi2s,mixe_jpsi,mu_psi2s,mu_jpsi]') + x = wspace.var("x") + data = rt.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), + RooFit.Import('pfe_psi2s', wspace.data('data_pfe_psi2s')), RooFit.Import('pfe_jpsi', wspace.data('data_pfe_jpsi')), + RooFit.Import('mixe_psi2s', wspace.data('data_mixe_psi2s')), RooFit.Import('mixe_jpsi', wspace.data('data_mixe_jpsi')), + RooFit.Import('mu_psi2s', wspace.data('data_mu_psi2s')), RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), + ) + getattr(wspace, 'import')(data, rt.RooCmdArg()) + + br_jpsi_ee, dbr_jpsi_ee= 0.05971, 0.00032 + br_psi2s_ee, dbr_psi2s_ee = 7.93e-3, 0.17e-3 + br_jpsi_mumu, dbr_jpsi_mumu= 0.05961, 0.00033 + br_psi2s_mumu, dbr_psi2s_mumu = 8.0e-3, 0.6e-3 + + + ### Create parameters + # observations + params = [ + # efficiency of PF-PF electron psi(2S) estimate + ('eff_hat_pfe_psi2s', eff_pfe_psi2s, 1.e-6, 1), + ('deff_pfe_psi2s', deff_pfe_psi2s, 1.e-6, 1), + # efficiency of PF-PF electron J/psi channel estimate + ('eff_hat_pfe_jpsi', eff_pfe_jpsi, 1.e-6, 1), + ('deff_pfe_jpsi', deff_pfe_jpsi, 1.e-6, 1), + # efficiency of PF-LP electron psi(2S) estimate + ('eff_hat_mixe_psi2s', eff_mixe_psi2s, 1.e-6, 1), + ('deff_mixe_psi2s', deff_mixe_psi2s, 1.e-6, 1), + # efficiency of PF-LP electron J/psi channel estimate + ('eff_hat_mixe_jpsi', eff_mixe_jpsi, 1.e-6, 1), + ('deff_mixe_jpsi', deff_mixe_jpsi, 1.e-6, 1), + # branching fraction of J/psi -> ee + ('br_hat_jpsi_ee', br_jpsi_ee, 1.e-6, 1), + ('dbr_jpsi_ee', dbr_jpsi_ee, 1.e-6, 1), + # branching fraction of psi(2S) -> ee + ('br_hat_psi2s_ee', br_psi2s_ee, 1.e-6, 1), + ('dbr_psi2s_ee', dbr_psi2s_ee, 1.e-6, 1), + # efficiency of muon psi(2S) estimate + ('eff_hat_mu_psi2s', eff_mu_psi2s, 1.e-6, 1), + ('deff_mu_psi2s', deff_mu_psi2s, 1.e-6, 1), + # efficiency of muon J/psi channel estimate + ('eff_hat_mu_jpsi', eff_mu_jpsi, 1.e-6, 1), + ('deff_mu_jpsi', deff_mu_jpsi, 1.e-6, 1), + # branching fraction of J/psi -> mu mu + ('br_hat_jpsi_mumu', br_jpsi_mumu, 1.e-6, 1), + ('dbr_jpsi_mumu', dbr_jpsi_mumu, 1.e-6, 1), + # branching fraction of psi(2S) -> mu mu + ('br_hat_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), + ('dbr_psi2s_mumu', dbr_psi2s_mumu, 1.e-6, 1), + # nuisance parameters + ('n_pfe_jpsi', 8617, 7000, 10000), + ('eff_pfe_psi2s', eff_pfe_psi2s, eff_pfe_psi2s-5.0*deff_pfe_psi2s, eff_pfe_psi2s+5.0*deff_pfe_psi2s), + ('eff_pfe_jpsi', eff_pfe_jpsi, eff_pfe_jpsi-5.0*deff_pfe_jpsi, eff_pfe_jpsi+5.0*deff_pfe_jpsi), + ('n_mixe_jpsi', 8617, 7000, 10000), + ('eff_mixe_psi2s', eff_mixe_psi2s, eff_mixe_psi2s-5.0*deff_mixe_psi2s, eff_mixe_psi2s+5.0*deff_mixe_psi2s), + ('eff_mixe_jpsi', eff_mixe_jpsi, eff_mixe_jpsi-5.0*deff_mixe_jpsi, eff_mixe_jpsi+5.0*deff_mixe_jpsi), + ('br_psi2s_ee', br_psi2s_ee, br_psi2s_ee-5.0*dbr_psi2s_ee, br_psi2s_ee+5.0*dbr_psi2s_ee), + ('br_jpsi_ee', br_jpsi_ee, br_jpsi_ee-5.0*dbr_jpsi_ee, br_jpsi_ee+5.0*dbr_jpsi_ee), + ('n_mu_jpsi', 8617, 7000, 10000), + ('eff_mu_psi2s', eff_mu_psi2s, eff_mu_psi2s-5.0*deff_mu_psi2s, eff_mu_psi2s+5.0*deff_mu_psi2s), + ('eff_mu_jpsi', eff_mu_jpsi, eff_mu_jpsi-5.0*deff_mu_jpsi, eff_mu_jpsi+5.0*deff_mu_jpsi), + ('br_psi2s_mumu', br_psi2s_mumu, br_psi2s_mumu-5.0*dbr_psi2s_mumu, br_psi2s_mumu+5.0*dbr_psi2s_mumu), + ('br_jpsi_mumu', br_jpsi_mumu, br_jpsi_mumu-5.0*dbr_jpsi_mumu, br_jpsi_mumu+5.0*dbr_jpsi_mumu), + # parameter of interest + ('r_br', 0.7, 0.6, 0.8), + ('R', 1.0, 0.5, 1.5), + ] + + for t in params: + cmd = '%s[%f, %f, %f]' % t + wspace.factory(cmd) + wspace.var('R').SetTitle('R') + + # fix all background and signal parameters + for t in params[0:-15]: + name = t[0] + print '=> make %8s = %5.5f constant' % (name, + wspace.var(name).getVal()) + wspace.var(name).setConstant() + + ### Create expressions + express = [ + # PF-PF electron + 'n_pfe_psi2s("(r_br/R)*n_pfe_jpsi*(br_psi2s_ee/br_jpsi_ee)*(eff_pfe_psi2s/eff_pfe_jpsi)", r_br, R, n_pfe_jpsi, br_psi2s_ee, br_jpsi_ee, eff_pfe_psi2s, eff_pfe_jpsi)', + 'nKstarPsi2S_pfe_psi2s_modified("frac_partial_pfe_psi2s*n_pfe_psi2s", frac_partial_pfe_psi2s, n_pfe_psi2s)', + 'nKstarJpsi_pfe_jpsi_modified("frac_partial_pfe_jpsi*n_pfe_jpsi", frac_partial_pfe_jpsi, n_pfe_jpsi)', + # PF-LP electron + 'n_mixe_psi2s("(r_br/R)*n_mixe_jpsi*(br_psi2s_ee/br_jpsi_ee)*(eff_mixe_psi2s/eff_mixe_jpsi)", r_br, R, n_mixe_jpsi, br_psi2s_ee, br_jpsi_ee, eff_mixe_psi2s, eff_mixe_jpsi)', + 'nKstarPsi2S_mixe_psi2s_modified("frac_partial_mixe_psi2s*n_mixe_psi2s", frac_partial_mixe_psi2s, n_mixe_psi2s)', + 'nKstarJpsi_mixe_jpsi_modified("frac_partial_mixe_jpsi*n_mixe_jpsi", frac_partial_mixe_jpsi, n_mixe_jpsi)', + # muon + 'n_mu_psi2s("r_br*n_mu_jpsi*(br_psi2s_mumu/br_jpsi_mumu)*(eff_mu_psi2s/eff_mu_jpsi)", r_br, n_mu_jpsi, br_psi2s_mumu, br_jpsi_mumu, eff_mu_psi2s, eff_mu_jpsi)', + 'nKstarPsi2S_mu_psi2s_modified("frac_partial_mu_psi2s*n_mu_psi2s", frac_partial_mu_psi2s, n_mu_psi2s)', + 'nKstarJpsi_mu_jpsi_modified("frac_partial_mu_jpsi*n_mu_jpsi", frac_partial_mu_jpsi, n_mu_jpsi)', + ] + + for t in express: + cmd = 'expr::%s' % t + wspace.factory(cmd) + + edit = [ + # PF-PF electron + 'model_pfe_psi2s_modified(model_pfe_psi2s, nsignal_pfe_psi2s=n_pfe_psi2s, nKstarPsi2S_pfe_psi2s=nKstarPsi2S_pfe_psi2s_modified)', + 'model_pfe_jpsi_modified(model_pfe_jpsi, nsignal_pfe_jpsi=n_pfe_jpsi, nKstarJpsi_pfe_jpsi=nKstarJpsi_pfe_jpsi_modified)', + # PF-LP electron + 'model_mixe_psi2s_modified(model_mixe_psi2s, nsignal_mixe_psi2s=n_mixe_psi2s, nKstarPsi2S_mixe_psi2s=nKstarPsi2S_mixe_psi2s_modified)', + 'model_mixe_jpsi_modified(model_mixe_jpsi, nsignal_mixe_jpsi=n_mixe_jpsi, nKstarJpsi_mixe_jpsi=nKstarJpsi_mixe_jpsi_modified)', + # muon + 'model_mu_psi2s_modified(model_mu_psi2s, nsignal_mu_psi2s=n_mu_psi2s, nKstarPsi2S_mu_psi2s=nKstarPsi2S_mu_psi2s_modified)', + 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi, nKstarJpsi_mu_jpsi=nKstarJpsi_mu_jpsi_modified)', + ] + + for t in edit: + cmd = 'EDIT::%s' % t + wspace.factory(cmd) + + wspace.Print("V") + ### Create pdfs + pdfs = [ + # PF-PF electron + ('Gaussian','peff_pfe_psi2s', '(eff_hat_pfe_psi2s, eff_pfe_psi2s, deff_pfe_psi2s)'), + ('Gaussian','peff_pfe_jpsi', '(eff_hat_pfe_jpsi, eff_pfe_jpsi, deff_pfe_jpsi)'), + # PF-LP electron + ('Gaussian','peff_mixe_psi2s', '(eff_hat_mixe_psi2s, eff_mixe_psi2s, deff_mixe_psi2s)'), + ('Gaussian','peff_mixe_jpsi', '(eff_hat_mixe_jpsi, eff_mixe_jpsi, deff_mixe_jpsi)'), + ('Gaussian','peff_br_psi2s_ee', '(br_hat_psi2s_ee, br_psi2s_ee, dbr_psi2s_ee)'), + ('Gaussian','peff_br_jpsi_ee', '(br_hat_jpsi_ee, br_jpsi_ee, dbr_jpsi_ee)'), + # muon + ('Gaussian','peff_mu_psi2s', '(eff_hat_mu_psi2s, eff_mu_psi2s, deff_mu_psi2s)'), + ('Gaussian','peff_mu_jpsi', '(eff_hat_mu_jpsi, eff_mu_jpsi, deff_mu_jpsi)'), + ('Gaussian','peff_br_psi2s_mumu', '(br_hat_psi2s_mumu, br_psi2s_mumu, dbr_psi2s_mumu)'), + ('Gaussian','peff_br_jpsi_mumu', '(br_hat_jpsi_mumu, br_jpsi_mumu, dbr_jpsi_mumu)'), + ] + + prodpdf = '' + for t in pdfs: + wspace.factory('%s::%s%s' % t) + name = t[1] + prodpdf += "%s, " % name + prodpdf = prodpdf[:-2] # remove last ", " + + + # multiply the pdfs together. use upper case PROD to + # do this + wspace.factory("SIMUL:jointModel(cat,pfe_psi2s=model_pfe_psi2s_modified,pfe_jpsi=model_pfe_jpsi_modified,mixe_psi2s=model_mixe_psi2s_modified,mixe_jpsi=model_mixe_jpsi_modified,mu_psi2s=model_mu_psi2s_modified,mu_jpsi=model_mu_jpsi_modified)") + wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) + + nuis_excluded = ['x', 'R', 'cat', + 'deff_pfe_jpsi', 'deff_pfe_psi2s', 'eff_hat_pfe_jpsi', 'eff_hat_pfe_psi2s', + 'deff_mixe_jpsi', 'deff_mixe_psi2s', 'eff_hat_mixe_jpsi', 'eff_hat_mixe_psi2s', + 'dbr_jpsi_ee', 'dbr_psi2s_ee', 'br_hat_jpsi_ee', 'br_hat_psi2s_ee' + 'deff_mu_jpsi', 'deff_mu_psi2s', 'eff_hat_mu_jpsi', 'eff_hat_mu_psi2s', + 'dbr_jpsi_mumu', 'dbr_psi2s_mumu', 'br_hat_jpsi_mumu', 'br_hat_psi2s_mumu' + ] + + ### Define global observables + ### they are not being fitted and they are not loaded from a dataset, + ### but some knowledge exists that allows to set them to a specific value + ### Global Observables are generated once per toy + globs = ['eff_pfe_psi2s', 'eff_pfe_jpsi', 'br_psi2s_ee', 'br_jpsi_ee', + 'eff_mixe_psi2s', 'eff_mixe_jpsi', + 'eff_mu_psi2s', 'eff_mu_jpsi', 'br_psi2s_mumu', 'br_jpsi_mumu', + ] + + nuis = [] + params = wspace.pdf('model').getVariables() + params_iter = params.createIterator() + param = params_iter.Next() + while param : + if param.GetName() not in (nuis_excluded+globs): + nuis.append(param.GetName()) + param = params_iter.Next() + nuis = ','.join(nuis) + globs = ','.join(globs) + + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis), + ('globs', globs), + ] # nuisance parameters (leave no spaces) + #('nuis', 'n_pfe_jpsi,eff_pfe_psi2s,eff_pfe_jpsi')] # nuisance parameters (leave no spaces) + + for t in sets: + name, parlist = t + wspace.defineSet(name, parlist) + + + #----------------------------------------------------- + # Create model configuration. This is needed for the + # statistical analyses + #----------------------------------------------------- + cfg = rt.RooStats.ModelConfig('cfg') + cfg.SetWorkspace(wspace) + cfg.SetPdf(wspace.pdf('model')) + cfg.SetParametersOfInterest(wspace.set('poi')) + cfg.SetNuisanceParameters(wspace.set('nuis')) + cfg.SetGlobalObservables(wspace.set('globs')) + + # import model configuration into workspace + getattr(wspace, 'import')(cfg) + + wspace.Print() + + # write out workspace + wspace.writeToFile(wsfilename) + + +if __name__ == "__main__": + + eff_pfe_psi2s, deff_pfe_psi2s = 0.03430, 0.00024 + eff_pfe_jpsi, deff_pfe_jpsi = 0.03680, 0.00023 + eff_mixe_psi2s, deff_mixe_psi2s = 0.03430, 0.00024 + eff_mixe_jpsi, deff_mixe_jpsi = 0.03680, 0.00023 + eff_mu_psi2s, deff_mu_psi2s = 0.03430, 0.00024 + eff_mu_jpsi, deff_mu_jpsi = 0.03680, 0.00023 + R_SM = 1.0 + R_min, R_max = 0.8, 1.2 + xlabel = 'R_{#psi(2S)}' + + wsfilename_pfe_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' + wsfilename_pfe_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' + wsfilename_mixe_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' + wsfilename_mixe_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' + wsfilename_mu_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' + wsfilename_mu_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' + wsfilename = 'wspace_rpsi2s_combinedEleCh.root' + + createWorkspace('R_psi2s', wsfilename, wsfilename_pfe_psi2s, wsfilename_pfe_jpsi, wsfilename_mixe_psi2s, wsfilename_mixe_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, + eff_pfe_psi2s=eff_pfe_psi2s, deff_pfe_psi2s=deff_pfe_psi2s, eff_pfe_jpsi=eff_pfe_jpsi, deff_pfe_jpsi=deff_pfe_jpsi, + eff_mixe_psi2s=eff_mixe_psi2s, deff_mixe_psi2s=deff_mixe_psi2s, eff_mixe_jpsi=eff_mixe_jpsi, deff_mixe_jpsi=deff_mixe_jpsi, + eff_mu_psi2s=eff_mu_psi2s, deff_mu_psi2s=deff_mu_psi2s, eff_mu_jpsi=eff_mu_jpsi, deff_mu_jpsi=deff_mu_jpsi, + ) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True) + + diff --git a/maximum_likelihood_singleChannel.py b/maximum_likelihood_singleChannel.py index b9fa209..e2fb3d3 100644 --- a/maximum_likelihood_singleChannel.py +++ b/maximum_likelihood_singleChannel.py @@ -2,18 +2,10 @@ from time import sleep import math import ROOT as rt +from ROOT import RooFit rt.gROOT.SetBatch(True); rt.gROOT.SetStyle("Plain"); -from plotting import * - -def importWorkspace(wspace, wsfilename_import, rename): - wsfile_import = rt.TFile.Open(wsfilename_import) - wspace_import = wsfile_import.Get('wspace') - data_import = wspace_import.data('data') - getattr(wspace, 'import')(data_import, rt.RooCmdArg(RooFit.Rename('data_{}'.format(rename)))) - model_import = wspace_import.pdf('model') - getattr(wspace, 'import')(model_import, RooFit.RenameAllVariablesExcept(rename, 'x'), RooFit.RenameAllNodes(rename)) - return wspace +from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar=0.0, deff_tar=0.0, eff_norm=0.0, deff_norm=0.0): wspace = rt.RooWorkspace(wsname) @@ -22,7 +14,7 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar wspace.factory('cat[tar,norm]') x = wspace.var("x") - data = ROOT.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), RooFit.Import('tar', wspace.data('data_tar')), RooFit.Import('norm', wspace.data('data_norm'))) + data = rt.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), RooFit.Import('tar', wspace.data('data_tar')), RooFit.Import('norm', wspace.data('data_norm'))) getattr(wspace, 'import')(data, rt.RooCmdArg()) @@ -36,11 +28,11 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar ('eff_hat_norm', eff_norm, 0, 1), ('deff_norm', deff_norm, 0, 1), # nuisance parameters - ('n_norm', 9000, 0, 20000), - ('eff_tar', eff_tar, 0, 1), - ('eff_norm', eff_norm, 0, 1), + ('n_norm', 8617, 7000, 10000), + ('eff_tar', eff_tar, eff_tar-5.0*deff_tar, eff_tar+5.0*deff_tar), + ('eff_norm', eff_norm, eff_norm-5.0*deff_norm, eff_norm+5.0*deff_norm), # parameter of interest - ('R', 0.09, 0.06, 0.15)] + ('R', 0.09, 0.01, 0.2)] for t in params: cmd = '%s[%f, %f, %f]' % t @@ -92,19 +84,29 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) nuis_excluded = ['x', 'R', 'cat', 'deff_norm', 'deff_tar', 'eff_hat_norm', 'eff_hat_tar'] + + ### Define global observables + ### they are not being fitted and they are not loaded from a dataset, + ### but some knowledge exists that allows to set them to a specific value + ### Global Observables are generated once per toy + globs = ['eff_tar', 'eff_norm'] + nuis = [] params = wspace.pdf('model').getVariables() params_iter = params.createIterator() param = params_iter.Next() while param : - if param.GetName() not in nuis_excluded: + if param.GetName() not in (nuis_excluded+globs): nuis.append(param.GetName()) param = params_iter.Next() nuis = ','.join(nuis) + globs = ','.join(globs) - sets = [('obs', 'x'), # observations - ('poi', 'R'), # parameter of interest - ('nuis', nuis)] # nuisance parameters (leave no spaces) + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis), # nuisance parameters (leave no spaces) + ('globs', globs), + ] #('nuis', 'n_norm,eff_tar,eff_norm')] # nuisance parameters (leave no spaces) for t in sets: @@ -121,6 +123,7 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar cfg.SetPdf(wspace.pdf('model')) cfg.SetParametersOfInterest(wspace.set('poi')) cfg.SetNuisanceParameters(wspace.set('nuis')) + cfg.SetGlobalObservables(wspace.set('globs')) # import model configuration into workspace getattr(wspace, 'import')(cfg) @@ -130,124 +133,20 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar # write out workspace wspace.writeToFile(wsfilename) -def analyzeWorkspace(wsname, wsfilename, R_SM=None): - - # Open workspace file - wsfile = rt.TFile.Open(wsfilename) - - # Get workspace - wspace = wsfile.Get(wsname) - - # Get data - data = wspace.data('data') - - # Get model configuration - cfg = wspace.obj('cfg') - - #----------------------------------------------------- - # Fit model to data - #----------------------------------------------------- - results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save(), RooFit.NumCPU(8)) - results.Print() - - #----------------------------------------------------- - # Compute interval based on profile likelihood - #----------------------------------------------------- - # suppress some (apparently) innocuous warnings - #msgservice = rt.RooMsgService.instance() - #msgservice.setGlobalKillBelow(rt.RooFit.FATAL) - - R_min, R_max = 0.07, 0.12 - NPoints = 20 - xlabel = 'R_{#psi (2S)}^{e}' - - print 'compute interval using profile likelihood' - plc = rt.RooStats.ProfileLikelihoodCalculator(data, cfg) - CL = 0.683 - plc.SetConfidenceLevel(CL) - plcInterval= plc.GetInterval() - lowerLimit = plcInterval.LowerLimit(wspace.var('R')) - upperLimit = plcInterval.UpperLimit(wspace.var('R')) - - print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ - (100*CL, '%', lowerLimit, upperLimit) - - plcplot = rt.RooStats.LikelihoodIntervalPlot(plcInterval) - plccanvas = rt.TCanvas('fig_PL', 'PL', 800, 600) - plccanvas.cd() - pad = setup_pad() - pad.Draw() - pad.cd() - - plcplot.SetRange(R_min, R_max) - plcplot.SetMaximum(10) - plcplot.SetLineColor(9) - plcplot.SetNPoints(NPoints) - plcplot.Draw("tf1") - - # compute an 95% limit on mu by - CL = 0.95 - plc.SetConfidenceLevel(CL) - plcInterval = plc.GetInterval() - lowerLimit = plcInterval.LowerLimit(wspace.var('R')) - upperLimit = plcInterval.UpperLimit(wspace.var('R')) - - print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ - (100*CL, '%', lowerLimit, upperLimit) - - pad.cd() - plcplot2 = rt.RooStats.LikelihoodIntervalPlot(plcInterval) - plcplot2.SetRange(R_min, R_max) - plcplot2.SetMaximum(10) - plcplot2.SetLineColor(8) - plcplot2.SetNPoints(NPoints) - plcplot2.Draw("tf1 same") - - frame = plcplot.GetPlottedObject() - frame.GetYaxis().SetTitle('Profile of -log(L/L_{min})') - frame.GetXaxis().SetTitle(xlabel) - frame.GetYaxis().SetTitleOffset(0.9) - frame.GetYaxis().SetTitleFont(42) - frame.GetYaxis().SetTitleSize(0.04) - frame.GetYaxis().SetLabelSize(0.04) - frame.GetYaxis().SetLabelFont(42) - frame.GetXaxis().SetTitleOffset(0.9) - frame.GetXaxis().SetTitleFont(42) - frame.GetXaxis().SetTitleSize(0.04) - frame.GetXaxis().SetLabelSize(0.04) - frame.GetXaxis().SetLabelFont(42) - - pad.Update() - uymax = rt.gPad.GetUymax() - uymin = rt.gPad.GetUymin() - if R_SM is not None: - pad.cd() - l = rt.TLine(R_SM, uymin, R_SM, uymax) - l.SetLineColor(2) - l.SetLineWidth(2) - l.Draw("same") - - pad.cd() - CMS_lumi(False) - plccanvas.cd() - plccanvas.Update() - - # save canvases - plccanvas.Draw() - plccanvas.SaveAs('.pdf') - return plccanvas if __name__ == "__main__": eff_tar, deff_tar = 0.03430, 0.00024 eff_norm, deff_norm = 0.03680, 0.00023 R_SM = 0.0812 - + R_min, R_max = 0.07, 0.12 + xlabel = 'R_{#psi (2S)}^{e}' + wsfilename_tar = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' wsfilename_norm = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' wsfilename = 'wspace_rpsi2s_electron.root' createWorkspace('R_psi2s', wsfilename, wsfilename_tar, wsfilename_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) - plccanvas = analyzeWorkspace('R_psi2s', wsfilename, R_SM=R_SM) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True) diff --git a/utils_likelihood.py b/utils_likelihood.py new file mode 100644 index 0000000..a6e0d5d --- /dev/null +++ b/utils_likelihood.py @@ -0,0 +1,199 @@ +import os,sys,re +import time +from time import sleep +import math +import ROOT as rt +import root_numpy +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from plotting import * + +def importWorkspace(wspace, wsfilename_import, rename): + wsfile_import = rt.TFile.Open(wsfilename_import) + wspace_import = wsfile_import.Get('wspace') + data_import = wspace_import.data('data') + getattr(wspace, 'import')(data_import, rt.RooCmdArg(RooFit.Rename('data_{}'.format(rename)))) + model_import = wspace_import.pdf('model') + getattr(wspace, 'import')(model_import, RooFit.RenameAllVariablesExcept(rename, 'x'), RooFit.RenameAllNodes(rename)) + return wspace + +def analyzeWorkspace(wsname, wsfilename, x_SM=None, x_min=0.8, x_max=1.2, NPoints=20, xlabel='R', plot=False): + rt.Math.MinimizerOptions.SetDefaultMinimizer("Minuit") + #rt.Math.MinimizerOptions.SetDefaultPrintLevel(1) + + # Open workspace file + wsfile = rt.TFile.Open(wsfilename) + + # Get workspace + wspace = wsfile.Get(wsname) + + # Get data + data = wspace.data('data') + + # Get model configuration + cfg = wspace.obj('cfg') + + #----------------------------------------------------- + # Fit model to data + #----------------------------------------------------- + ts_start = time.time() + results = wspace.pdf('model').fitTo(data, RooFit.Extended(True), rt.RooFit.Save(), RooFit.NumCPU(8)) + results.Print() + print("Time for fit: {} s".format(time.time() - ts_start)) + + #----------------------------------------------------- + # Compute interval based on profile likelihood + #----------------------------------------------------- + # suppress some (apparently) innocuous warnings + #msgservice = rt.RooMsgService.instance() + #msgservice.setGlobalKillBelow(rt.RooFit.FATAL) + + print 'compute interval using profile likelihood' + + # compute an 68.3% limit + ts_start = time.time() + plc = rt.RooStats.ProfileLikelihoodCalculator(data, cfg) + CL = 0.683 + plc.SetConfidenceLevel(CL) + plcInterval_1sd= plc.GetInterval() + lowerLimit_1sd = plcInterval_1sd.LowerLimit(wspace.var('R')) + upperLimit_1sd = plcInterval_1sd.UpperLimit(wspace.var('R')) + + print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ + (100*CL, '%', lowerLimit_1sd, upperLimit_1sd) + + print("Time for profile likelihood 1 sigma: {} s".format(time.time() - ts_start)) + + + # compute an 95% limit + ts_start = time.time() + CL = 0.95 + plc.SetConfidenceLevel(CL) + plcInterval_2sd = plc.GetInterval() + lowerLimit_2sd = plcInterval_2sd.LowerLimit(wspace.var('R')) + upperLimit_2sd = plcInterval_2sd.UpperLimit(wspace.var('R')) + + print '\tPL %4.1f%s CL interval = [%5.5f, %5.5f]' % \ + (100*CL, '%', lowerLimit_2sd, upperLimit_2sd) + + print("Time for profile likelihood 2 sigma: {} s".format(time.time() - ts_start)) + + if plot: + ts_start = time.time() + Yat_Xmax_1sd = 0.5*rt.Math.chisquared_quantile(plcInterval_1sd.ConfidenceLevel(),1); + Yat_Xmax_2sd = 0.5*rt.Math.chisquared_quantile(plcInterval_2sd.ConfidenceLevel(),1); + plccanvas = plot_likelihood(plcInterval_1sd, Yat_Xmax_1sd, lowerLimit_1sd, upperLimit_1sd, Yat_Xmax_2sd, lowerLimit_2sd, upperLimit_2sd, x_min=x_min, x_max=x_max, x_SM=x_SM, NPoints=NPoints, xlabel=xlabel) + print("Time for plotting: {} s".format(time.time() - ts_start)) + return plccanvas + else: + return None + +def plot_likelihood(plcInterval_1sd, Yat_Xmax_1sd, min_1sd, max_1sd, Yat_Xmax_2sd, min_2sd, max_2sd, x_min=0.8, x_max=1.2, x_SM=1.0, NPoints=20, xlabel='R'): + plccanvas = rt.TCanvas('fig_PL', 'PL', 800, 600) + plcplot = rt.RooStats.LikelihoodIntervalPlot(plcInterval_1sd) + plccanvas.cd() + pad = setup_pad() + pad.Draw() + pad.cd() + + plcplot.SetRange(x_min, x_max) + plcplot.SetMaximum(10) + plcplot.SetLineColor(0) + plcplot.SetNPoints(NPoints) + plcplot.Draw("tf1") + + pad.cd() + + ''' + Yline_cutoff = rt.TLine(x_min,Yat_Xmax,x_max,Yat_Xmax); + Yline_min = rt.TLine(min_2sd,0.,min_2sd,Yat_Xmax); + Yline_max = rt.TLine(max_2sd,0.,max_2sd,Yat_Xmax); + + Yline_cutoff.SetLineColor(8) + Yline_min.SetLineColor(8) + Yline_max.SetLineColor(8) + + Yline_cutoff.Draw("same"); + Yline_min.Draw("same"); + Yline_max.Draw("same"); + ''' + + hist = plcplot.GetPlottedObject() + frame = rt.TGraph(hist) + frame.GetYaxis().SetTitle('Profile of -log(L/L_{min})') + frame.GetXaxis().SetTitle(xlabel) + frame.GetYaxis().SetTitleOffset(0.9) + frame.GetYaxis().SetTitleFont(42) + frame.GetYaxis().SetTitleSize(0.04) + frame.GetYaxis().SetLabelSize(0.04) + frame.GetYaxis().SetLabelFont(42) + frame.GetXaxis().SetTitleOffset(0.9) + frame.GetXaxis().SetTitleFont(42) + frame.GetXaxis().SetTitleSize(0.04) + frame.GetXaxis().SetLabelSize(0.04) + frame.GetXaxis().SetLabelFont(42) + frame.SetMinimum(0) + frame.Draw() + + pad.Update() + + # plot 95% limit + hist_2sd = hist.Clone() + y_2sd, edge_2sd = root_numpy.hist2array(hist_2sd, return_edges=True) + edge_2sd = np.array(edge_2sd).flatten() + x_2sd = np.convolve(edge_2sd, np.ones(2), 'valid') / 2.0 + tofill_2sd = [(x, y) for x, y in zip(x_2sd, y_2sd) if min_2sd < x < max_2sd] + tg_2sd = rt.TGraph() + root_numpy.fill_graph(tg_2sd, tofill_2sd) + tg_2sd.SetPoint(tg_2sd.GetN(), min_2sd, Yat_Xmax_2sd) + tg_2sd.SetPoint(tg_2sd.GetN(), min_2sd, 0) + tg_2sd.SetPoint(tg_2sd.GetN(), max_2sd, 0) + tg_2sd.SetPoint(tg_2sd.GetN(), max_2sd, Yat_Xmax_2sd) + tg_2sd.Sort() + tg_2sd.SetFillColor(16) + tg_2sd.SetFillStyle(1001) + tg_2sd.Draw("F2 SAME") + + pad.Update() + + # plot 68.3% limit + hist_1sd = hist.Clone() + y_1sd, edge_1sd = root_numpy.hist2array(hist_1sd, return_edges=True) + edge_1sd = np.array(edge_1sd).flatten() + x_1sd = np.convolve(edge_1sd, np.ones(2), 'valid') / 2.0 + tofill_1sd = [(x, y) for x, y in zip(x_1sd, y_1sd) if min_1sd < x < max_1sd] + tg_1sd = rt.TGraph() + root_numpy.fill_graph(tg_1sd, tofill_1sd) + tg_1sd.SetPoint(tg_1sd.GetN(), min_1sd, Yat_Xmax_1sd) + tg_1sd.SetPoint(tg_1sd.GetN(), min_1sd, 0) + tg_1sd.SetPoint(tg_1sd.GetN(), max_1sd, 0) + tg_1sd.SetPoint(tg_1sd.GetN(), max_1sd, Yat_Xmax_1sd) + tg_1sd.Sort() + tg_1sd.SetFillColor(14) + tg_1sd.SetFillStyle(1001) + tg_1sd.Draw("F2 SAME") + + pad.Update() + + frame.Draw("same") + pad.Update() + + uymax = rt.gPad.GetUymax() + uymin = rt.gPad.GetUymin() + if x_SM is not None: + pad.cd() + l = rt.TLine(x_SM, uymin, x_SM, uymax) + l.SetLineColor(2) + l.SetLineWidth(2) + l.Draw("same") + + pad.cd() + CMS_lumi(False) + plccanvas.cd() + plccanvas.Update() + + # save canvases + plccanvas.Draw() + plccanvas.SaveAs('.pdf') + return plccanvas + From b5ff8e4e0b3087c929b4ccfb761cee52b8c0149a Mon Sep 17 00:00:00 2001 From: ottolau Date: Mon, 10 Jan 2022 19:01:51 +0100 Subject: [PATCH 06/13] added fitting code and restructed the directory --- fitter.py => archive/fitter.py | 0 helper.py => archive/helper.py | 0 models.cc => archive/models.cc | 0 models.h => archive/models.h | 0 fit/KEE_lowq2_roofit_plb_pull_modified.py | 499 ++++++++++++++++++ ...si_roofit_plb_modified_kde_fixedPartial.py | 445 ++++++++++++++++ ...2S_roofit_plb_modified_kde_fixedPartial.py | 481 +++++++++++++++++ fit/roofit_helper.py | 61 +++ fit/roofit_models.py | 23 + fit/run_fit_KEE_lowq2_bparkPU.py | 127 +++++ fit/run_fit_KJpsi_fixedPartial.py | 85 +++ fit/run_fit_KPsi2S_fixedPartial.py | 85 +++ .../maximum_likelihood_rpsi2s.py | 0 ...maximum_likelihood_rpsi2s_combinedEleCh.py | 0 .../maximum_likelihood_singleChannel.py | 0 plotting.py => measurement/plotting.py | 0 .../utils_likelihood.py | 0 17 files changed, 1806 insertions(+) rename fitter.py => archive/fitter.py (100%) rename helper.py => archive/helper.py (100%) rename models.cc => archive/models.cc (100%) rename models.h => archive/models.h (100%) create mode 100644 fit/KEE_lowq2_roofit_plb_pull_modified.py create mode 100644 fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py create mode 100644 fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py create mode 100644 fit/roofit_helper.py create mode 100644 fit/roofit_models.py create mode 100644 fit/run_fit_KEE_lowq2_bparkPU.py create mode 100644 fit/run_fit_KJpsi_fixedPartial.py create mode 100644 fit/run_fit_KPsi2S_fixedPartial.py rename maximum_likelihood_rpsi2s.py => measurement/maximum_likelihood_rpsi2s.py (100%) rename maximum_likelihood_rpsi2s_combinedEleCh.py => measurement/maximum_likelihood_rpsi2s_combinedEleCh.py (100%) rename maximum_likelihood_singleChannel.py => measurement/maximum_likelihood_singleChannel.py (100%) rename plotting.py => measurement/plotting.py (100%) rename utils_likelihood.py => measurement/utils_likelihood.py (100%) diff --git a/fitter.py b/archive/fitter.py similarity index 100% rename from fitter.py rename to archive/fitter.py diff --git a/helper.py b/archive/helper.py similarity index 100% rename from helper.py rename to archive/helper.py diff --git a/models.cc b/archive/models.cc similarity index 100% rename from models.cc rename to archive/models.cc diff --git a/models.h b/archive/models.h similarity index 100% rename from models.h rename to archive/models.h diff --git a/fit/KEE_lowq2_roofit_plb_pull_modified.py b/fit/KEE_lowq2_roofit_plb_pull_modified.py new file mode 100644 index 0000000..4252147 --- /dev/null +++ b/fit/KEE_lowq2_roofit_plb_pull_modified.py @@ -0,0 +1,499 @@ +import ROOT +from ROOT import RooFit +import math +from roofit_helper import * +#ROOT.gROOT.ProcessLine(open('roofit_models.h').read()) +#from ROOT import DoubleSidedCB +#from ROOT import ROOT_DoubleSidedCB +#from XGBweight import XGBweight +#rt.gInterpreter.Declare(XGBweight) +#from PUweight import PUweight +#rt.gInterpreter.Declare(PUweight) +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +#ROOT.gStyle.SetOptFit(0000); +ROOT.gROOT.SetBatch(True); +ROOT.gROOT.SetStyle("Plain"); +msgservice = ROOT.RooMsgService.instance() +msgservice.setGlobalKillBelow(RooFit.FATAL) +import csv +import os.path +import numpy as np +import matplotlib as mpl +mpl.use('agg') +import matplotlib.font_manager +from matplotlib import pyplot as plt +from matplotlib import rc +#.Allow for using TeX mode in matplotlib Figures +rc('font',**{'family':'sans-serif','sans-serif':['Computer Modern Roman']}) +rc('text', usetex=True) +plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern}"] + +ratio=5.0/7.0 +fig_width_pt = 3*246.0 # Get this from LaTeX using \showthe\columnwidth +inches_per_pt = 1.0/72.27 # Convert pt to inch +golden_mean = ratio if ratio != 0.0 else (np.sqrt(5)-1.0)/2.0 # Aesthetic ratio +fig_width = fig_width_pt*inches_per_pt # width in inches +fig_height = fig_width*golden_mean # height in inches +fig_size = [fig_width,fig_height] + +params = {'text.usetex' : True, + 'axes.labelsize': 24, + 'font.size': 24, + 'legend.fontsize': 20, + 'xtick.labelsize': 24, + 'ytick.labelsize': 24, + 'font.family' : 'lmodern', + 'text.latex.unicode': True, + 'axes.grid' : True, + 'text.usetex': True, + 'figure.figsize': fig_size} +plt.rcParams.update(params) + +nbin_data = 20 + +def residuals(xframe, var,name): + hresid = xframe.residHist() + xframe2 = var.frame() + xframe2.addPlotable(hresid,"P") + c2=canvas_create(xframe2,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c2.SaveAs(name+'_residual.pdf') + hpull = xframe.pullHist() + xframe3 = var.frame() + xframe3.addPlotable(hpull,"P") + c3=canvas_create(xframe3,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c3.SaveAs(name+'_pull.pdf') + + + +def define_workspace_bmass_data(wspace_name,mB_branch,tree): + wspace = ROOT.RooWorkspace(wspace_name) + fitvars = ROOT.RooArgSet() + bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") + fitvars.add(bMass) + dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) + theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) + theBMass = dataset.addColumn(theBMassfunc) ; + theBMass.setRange(4.7,5.7); + fitvars.add(theBMass) + getattr(wspace, "import")(dataset, RooFit.Rename('data')) + return wspace,dataset,bMass,theBMass + + +def get_visible_yield_error(obs, results, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + intgral_pdf_err = intgral_pdf.getPropagatedError(results, obs) + visible = amplitude.getVal() * intgral_pdf.getVal() + if intgral_pdf.getVal()==0: + visible_err =0 + else: + visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 + return visible, visible_err + +def get_visible_yield(obs, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + visible = amplitude * intgral_pdf.getVal() + return visible + + +##################### signal fit == Double sided CB ###################### +def signal_fit(tree, outputfile, branches): + print "Signal" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) + # signal + wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') + wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.0, 0.0, 10.0]') + wspace.factory('n1[1.0, 1.0, 20.0]') + wspace.factory('alpha2[1.0, 0.0, 10.0]') + wspace.factory('n2[1.0, 1.0, 20.0]') + wspace.factory('GenericPdf::sig( "DoubleSidedCB2(x,mean,width,alpha1,n1,alpha2,n2)",{x,mean,width,alpha1,n1,alpha2,n2})') + + sgnframe=theBMass.frame() + wspace.factory('nsig[1000,0,100000000]') + wspace.factory('RooExtendPdf::esig(sig,nsig)') + sig=wspace.pdf('sig') + nsig=wspace.var('nsig') + esig=wspace.pdf('esig') + results = esig.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + + results.Print() + dataset.plotOn(sgnframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + esig.plotOn(sgnframe, RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected), RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + n_param = results.floatParsFinal().getSize() + print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + c1.SaveAs('sgn_eek_'+outputfile+'.pdf') + residuals(sgnframe,theBMass,'sgn_eek_'+outputfile) + params=esig.getParameters(ROOT.RooArgSet(bMass)) + return {"mean":params.getRealValue('mean'),"width": params.getRealValue('width'),"alpha1":params.getRealValue('alpha1'),"n1":params.getRealValue('n1'),"alpha2":params.getRealValue('alpha2'),"n2":params.getRealValue('n2')} + + +############################### B->KJpsi fit ############################## +def kjpsi_fit(tree, outputfile, branches): + print "kjpsi" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kjpsi_bkg",branches[0],tree) + wspace.factory('mean_kjpsi[4.7, 1.0, 5.0]') + wspace.factory('width_kjpsi[0.1, 0.001, 5.0]') + wspace.factory("RooGaussian::kjpsi(x,mean_kjpsi,width_kjpsi)") + wspace.factory('nkjpsi[1000,0,10e+6]') + wspace.factory('RooExtendPdf::ekjpsi(kjpsi,nkjpsi)') + nkjpsi=wspace.var('nkjpsi') + ekjpsi=wspace.pdf('ekjpsi') + results = ekjpsi.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + results.Print() + kjpframe=theBMass.frame() + dataset.plotOn(kjpframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + ekjpsi.plotOn(kjpframe,RooFit.Name("ekjpsi"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + c1=canvas_create(kjpframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + c1.SaveAs('bkg_jpsik_'+outputfile+'.pdf') + residuals(kjpframe,theBMass,'bkg_jpsik_'+outputfile) + params=ekjpsi.getParameters(ROOT.RooArgSet(bMass)) + n_param = results.floatParsFinal().getSize() + print "chi2",kjpframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + return {"mean_kjpsi":params.getRealValue('mean_kjpsi'),"width_kjpsi":params.getRealValue('width_kjpsi')} + + +############################ BKG fit ################################# +def bkg_fit(tree, outputfile, branches): + print "combinatorial" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_comb_bkg",branches[0],tree) + wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') + wspace.factory('Exponential::bkg(x,exp_alpha)') + wspace.factory('nbkg[1000,0,10e+6]') + wspace.factory('RooExtendPdf::ebkg(bkg,nbkg)') + nbkg=wspace.var('nbkg') + ebkg=wspace.pdf('ebkg') + + results = ebkg.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) ) + results.Print() + bkgframe=theBMass.frame() + dataset.plotOn(bkgframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + ebkg.plotOn(bkgframe,RooFit.Name("ebkg"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + params=ebkg.getParameters(ROOT.RooArgSet(bMass)) + c1=canvas_create(bkgframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + CMS_lumi() + c1.SaveAs('bkg_comb_'+outputfile+'.pdf') + n_param = results.floatParsFinal().getSize() + print "chi2",bkgframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + residuals(bkgframe,theBMass,'bkg_comb_'+outputfile) + + return {"exp_alpha":params.getRealValue('exp_alpha')} + + + +############################# total fit ############################## +def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_parameters=None, bkg_parameters=None, set_sgn_yield=None,Blind_range={"min":4.7,"max":5.7} , number_of_mctoys=None,mva=None,log='log.csv'): + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) + print "Total" + #amplitudes + wspace.factory('nsig[100.0, 0.0, 1000000.0]' ) + wspace.factory('nbkg[10000.0, 0.0, 100000000.0]') + wspace.factory('nkjpsi[10000.0, 0.0, 1000000.0]') + + # signal + wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') + wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.0, 0.0, 10.0]') + wspace.factory('n1[1.0, 1.0, 20.0]') + wspace.factory('alpha2[1.0, 0.0, 10.0]') + wspace.factory('n2[1.0, 1.0, 20.0]') + wspace.factory('GenericPdf::sig( "DoubleSidedCB2(x,mean,width,alpha1,n1,alpha2,n2)",{x,mean,width,alpha1,n1,alpha2,n2})') + + # Exponential - bkg + wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') + alpha = wspace.var('alpha') + wspace.factory('Exponential::bkg(x,exp_alpha)') + + # Gaussian - bkg + wspace.factory('mean_kjpsi[4.7, 1.0, 5.0]') + wspace.factory('width_kjpsi[0.1, 0.001, 5.0]') + wspace.factory("RooGaussian::kjpsi(x,mean_kjpsi,width_kjpsi)") + + #sum + wspace.factory('SUM::model(nsig*sig,nbkg*bkg,nkjpsi*kjpsi)') + + model = wspace.pdf('model'); bkg = wspace.pdf('bkg') + sig = wspace.pdf('sig'); kjpsi = wspace.pdf('kjpsi'); + nsig = wspace.var('nsig'); nbkg = wspace.var('nbkg') + nkjpsi = wspace.var('nkjpsi') + mean = wspace.var('mean') + + if set_sgn_yield!=None: + nsig.setVal(set_sgn_yield) + nsig.setConstant(True) + for par in sgn_parameters.keys(): + (wspace.var(par)).setVal(sgn_parameters[par]) + (wspace.var(par)).setConstant(True) + for par in kjpsi_parameters.keys(): + (wspace.var(par)).setVal(kjpsi_parameters[par]) + (wspace.var(par)).setConstant(True) + for par in bkg_parameters.keys(): + (wspace.var(par)).setVal(bkg_parameters[par]) + + results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + print results.Print() + xframe=theBMass.frame(RooFit.Title("")) + + + if Blind_range["min"]>4.7 and Blind_range["max"]<5.7: + norm = dataset.reduce('(({0} > {1}) & ({0} < {2})) | (({0}> {3}) & ({0} < {4}))'.format(branches[0],"4.7", str(Blind_range["min"]),str(Blind_range["max"]), "5.7")).sumEntries() / dataset.reduce('({0} > {1}) & ({0} < {2})'.format(branches[0],"4.7", "5.7")).sumEntries() +# blind= ROOT.RooRealVar("blind","blind",Blind_range["min"],Blind_range["max"]) + # blind.setRange("left",4.7,Blind_range["min"]) + # blind.setRange("right",Blind_range["max"],5.7) + theBMass.setRange("left",4.7,Blind_range["min"]) + theBMass.setRange("right",Blind_range["max"],5.7) + norm=1.0 + dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas"),RooFit.CutRange("left,right")) + else: + norm=1. + dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + + + #norm=1. + #dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + + model.plotOn(xframe,RooFit.Name("bkg"),RooFit.Components("bkg"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("sig"),RooFit.Components("sig"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) + model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) + + wspace.defineSet('obs', 'x') + obs = wspace.set('obs') + theBMass.setRange("window",Blind_range["min"],Blind_range["max"]) + + #theBMass.setRange("window",5.0,5.4) + obs2= ROOT.RooRealVar("obs2","obs2",Blind_range["min"],Blind_range["max"]) + nset = ROOT.RooArgSet(obs2) + print sig.getVal(), sig.getVal(nset) + print Blind_range + print nbkg.getVal(),nkjpsi.getVal(),nsig.getVal() + nbkg_visible, nbkg_visible_err = get_visible_yield_error(obs, results, bkg, nbkg) + nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, sig, nsig) + nkjpsi_visible, nkjpsi_visible_err = get_visible_yield_error(obs, results, kjpsi, nkjpsi) + print "hereee",nbkg_visible,nsig_visible,nkjpsi_visible +# c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + n_param = results.floatParsFinal().getSize() + print "chi2",xframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + + legend = ROOT.TLegend(0.65,0.65,0.92,0.85) + legend.AddEntry(xframe.findObject("bkg"),"Combinatorial","l"); + legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); + legend.AddEntry(xframe.findObject("sig"),"B -> eeK","l"); + legend.SetLineColor(ROOT.kWhite) + legend.SetTextFont(42); + legend.SetTextSize(0.04); + legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); + legend.Draw(); + pt=pt_create(mva,nsig_visible,nsig_visible_err,nkjpsi_visible+nbkg_visible) + pt.Draw() + CMS_lumi() + c1.cd() + c1.Update() + c1.SaveAs('total_fit_'+outputfile+'.pdf') + print nsig_visible, nsig_visible_err, nbkg_visible_err, nkjpsi_visible_err + residuals(xframe,theBMass,"poutana") + if number_of_mctoys!=None: + nsig.setConstant(False) + mctoys = ROOT.RooMCStudy(model, ROOT.RooArgSet(theBMass), + RooFit.Binned( ROOT.kTRUE), + #RooFit.Binned( ROOT.kFALSE), + ROOT.RooFit.Silence(), + RooFit.Extended(), + RooFit.FitOptions( + RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) + ) + ) + mctoys.generateAndFit(number_of_mctoys) + + frame1 = mctoys.plotParam(nsig, ROOT.RooFit.Bins(40)) + frame2 = mctoys.plotError(nsig, ROOT.RooFit.Bins(40)) + frame3 = mctoys.plotPull(nsig, ROOT.RooFit.Bins(40), + ROOT.RooFit.FitGauss(ROOT.kTRUE) + ) + # Plot distribution of minimized likelihood + frame4 = mctoys.plotNLL(ROOT.RooFit.Bins(40)) + cpr=canvas_create(frame1,4.7,5.7,1,'Distribution of the fitted value of N_{sgn}',False) + cpr.SaveAs("cpr_"+outputfile+".pdf") + cerr=canvas_create(frame2,0,1,1,'Distribution of the fitted error of N_{sgn}',False) + cerr.SaveAs("cerr_"+outputfile+".pdf") + cpull=canvas_create(frame3,4.7,5.7,1,' Pull of N_{sgn}',False) + cpull.SaveAs("cpull_"+outputfile+".pdf") + clog=canvas_create(frame4,4.7,5.7,1,'- log (L)') + clog.SaveAs("clog_"+outputfile+".pdf") + + postfit_data = mctoys.fitParDataSet() + postfit_nsig = np.array([postfit_data.get(i).getRealValue("nsig") for i in range(int(postfit_data.sumEntries()))]) + #postfit_nsig = np.array([get_visible_yield(obs, sig, postfit_data.get(i).getRealValue("nsig")) for i in range(int(postfit_data.sumEntries()))]) + #postfit_mu = np.array([s/nsig_visible for s in postfit_nsig]) + postfit_mu = np.array([s/set_sgn_yield for s in postfit_nsig]) + rms_mu = np.std(postfit_mu) + fig, ax = plt.subplots() + ax.hist(postfit_mu, bins=50, normed=True, histtype='step', label='MVA={}, RMS={}'.format(mva, rms_mu)) + ax.set_xlabel(r'$\mu$') + ax.set_ylabel('a.u.') + ax.legend(loc='best') + fig.savefig('cmu_{}.pdf'.format(outputfile), bbox_inches='tight') + + csv_header = ['cut', 'nsig', 'nbkg', 'njpsi', 'snr', 'rms_mu'] + df = {} + df['cut'] = mva + df['nsig'] = nsig_visible + df['nbkg'] = nbkg_visible + df['njpsi'] = nkjpsi_visible + df['snr'] = nsig_visible / np.sqrt(nsig_visible + nbkg_visible + nkjpsi_visible) + df['rms_mu'] = 0.0 if number_of_mctoys == None else rms_mu_ + csv_outputfile = log + file_exists = os.path.isfile(csv_outputfile) + with open (csv_outputfile, 'a+') as filedata: + writer = csv.DictWriter(filedata, delimiter=',', fieldnames=csv_header) + if not file_exists: + writer.writeheader() + writer.writerow(df) + + + return (nsig_visible,nbkg_visible,nkjpsi_visible) + + +def kee_yield_from_kjpsi(kjpsi_yield,tree_kee,tree_kjpsi,total_kee,total_kjpsi,xgb): + print "\nWARNING!!!!!",total_kee,"will be used as denominsator for kee eff. and ",total_kjpsi,"for kjpsi. Is this correct ?; code hypothesizes that cross validation is in 8 parts (hardcoded, change if different)\n" + hkee = ROOT.TH1F("hkee","",50,4.7,5.7) + hkjpsi = ROOT.TH1F("hkjpsi","",50,4.7,5.7) + #tree_kee.Draw("Bmass>>hkee","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>1.05 && Mll<2.45 && xgb>"+xgb+")") + #tree_kjpsi.Draw("Bmass>>hkjpsi","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>2.8 && Mll<3.25 && xgb>"+xgb+")") + tree_kee.Draw("Bmass>>hkee","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>1.05 && Mll<2.45 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) ))") + tree_kjpsi.Draw("Bmass>>hkjpsi","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>2.8 && Mll<3.25 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) ))") + + eff_kee=float(hkee.Integral()) / total_kee + eff_kjpsi=float(hkjpsi.Integral()) / total_kjpsi + result = kjpsi_yield / eff_kjpsi * 4.43*0.01/(1.026*5.93) *eff_kee + print "expect",result,"eff rare",eff_kee,"eff res",eff_kjpsi,"res data",kjpsi_yield + print "rare eff num",float(hkee.Integral()),"den",total_kee + return result + +################################### for scan ############################ +def FitForScan(inputfile, mva, isgnfile, ikspiBkg, ibkg, kjpsi_yield_for_kee,total_nsgn, total_nkjpsi, name ): + branches=["Bmass","Mll","xgb"] + cuts = "xgb>"+str(mva)+" && 1.05"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45"+" && "+branches[3]+">2.0" #+" && {} > 10 && {} > 10".format(branches[4], branches[5]) + print "cut: ", cuts + #cuts = " 1.05<"+branches[1]+" && "+branches[1]+"<2.45 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) )" + args.outputfile+="_wp"+str(args.mva) + + bkg_parameters={'exp_alpha':-1.98} + + print "start" + if args.fit_primtv: + if args.sel_primtv!= None: + args.sel_primtv = args.sel_primtv.split(",") + else: + args.sel_primtv = ["sgn","bkg_comb","bkg_kjpsi"] + print "primitive params" + if "sgn" in args.sel_primtv: + tree_sgn = ROOT.TChain('mytreefit') + tree_sgn.Add(args.isgnfile) + tree_sgn_cut=tree_sgn.CopyTree(cuts) + signal_parameters = signal_fit(tree_sgn_cut, args.outputfile+"_sgnMC", branches) + print "parameters SGN", signal_parameters['mean'], signal_parameters['width'],signal_parameters['alpha1'],signal_parameters['n1'],signal_parameters['alpha2'],signal_parameters['n2'] + + if "bkg_kjpsi" in args.sel_primtv: + tree_kjpsi = ROOT.TChain('mytreefit') + tree_kjpsi.Add(args.ikspiBkg) + tree_kjpsi_cut=tree_kjpsi.CopyTree(cuts) + kjpsi_parameters = kjpsi_fit(tree_kjpsi_cut, args.outputfile+"_kjpsiMC", branches) + print "parameters KJpsi BKG", kjpsi_parameters['mean_kjpsi'], kjpsi_parameters['width_kjpsi'] + + if "bkg_comb" in args.sel_primtv: + #cuts = branches[2]+">8 && "+branches[1]+"<5." + #cuts = branches[2]+">"+str(args.mva)+" && "+branches[1]+"<5" + tree_bkg = ROOT.TChain('mytreefit') + tree_bkg.Add(args.ibkg) + tree_bkg_cut=tree_bkg.CopyTree(cuts) + bkg_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) + print "parameters Combinatorial BKG", bkg_parameters['exp_alpha'] + + else: + signal_parameters={'mean': 5.272, 'width': 0.057, 'alpha1': 0.652, 'n1': 3.3, 'alpha2': 1.32, 'n2': 2.01} + kjpsi_parameters={'mean_kjpsi':4.72,'width_kjpsi':1.06} + bkg_parameters={'exp_alpha':-1.98} + + if args.kjpsi_yield_for_kee!=None: + tree_sgn = ROOT.TChain('mytreefit') + tree_sgn.Add(args.isgnfile) + tree_kjpsi = ROOT.TChain('mytreefit') + tree_kjpsi.Add(args.ikspiBkg) + args.set_expected_sgn = kee_yield_from_kjpsi(args.kjpsi_yield_for_kee,tree_sgn,tree_kjpsi,args.total_nsgn,args.total_nkjpsi,str(args.mva)) + print "WARNING expected signal set and FIXED to ",args.set_expected_sgn,"in all q^2" + + #args.set_expected_sgn = None + if not args.skip_realfit: + #cuts = branches[2]+">"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45"+" && "+branches[3]+">2.0 &&"+branches[4]+">2.0" + tree = ROOT.TChain('mytreefit') + tree.Add(args.inputfile) + tree_cut=tree.CopyTree(cuts) + nsig, nbkg, nkjpsi =total_fit(tree_cut, args.outputfile, branches, signal_parameters, kjpsi_parameters, bkg_parameters, args.set_expected_sgn, {"min":5.0,"max":5.4}, args.number_of_mctoys, str(args.mva), args.log) + # combinatorial BKG parameters set but not fixed. + print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) diff --git a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py new file mode 100644 index 0000000..5733315 --- /dev/null +++ b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py @@ -0,0 +1,445 @@ +import ROOT +from ROOT import RooFit +import math +from roofit_helper import * +#ROOT.gROOT.ProcessLine(open('roofit_models.h').read()) +#from ROOT import DoubleSidedCB +#from ROOT import ROOT_DoubleSidedCB +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +#ROOT.gStyle.SetOptFit(0000); +ROOT.gROOT.SetBatch(True); +ROOT.gROOT.SetStyle("Plain"); +msgservice = ROOT.RooMsgService.instance() +msgservice.setGlobalKillBelow(RooFit.FATAL) +import numpy as np +import csv +import os.path +import atexit + +nbin_data = 50 + +def residuals(xframe, var,name): + hresid = xframe.residHist() + xframe2 = var.frame() + xframe2.addPlotable(hresid,"P") + c2=canvas_create(xframe2,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c2.SaveAs(name+'_residual.pdf') + hpull = xframe.pullHist() + xframe3 = var.frame() + xframe3.addPlotable(hpull,"P") + c3=canvas_create(xframe3,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c3.SaveAs(name+'_pull.pdf') + + + +def define_workspace_bmass_data(wspace_name,mB_branch,tree): + wspace = ROOT.RooWorkspace(wspace_name) + fitvars = ROOT.RooArgSet() + bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") + fitvars.add(bMass) + dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) + theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) + theBMass = dataset.addColumn(theBMassfunc) ; + theBMass.setRange(4.7,5.7); + fitvars.add(theBMass) + getattr(wspace, "import")(dataset, RooFit.Rename('data')) + # When a RooWorkspace is set as an attribute of a class, it can trigger a memory error + # This is solved in the latest ROOT version > 6.14.08 + atexit.register(wspace.Delete) + return wspace,dataset,bMass,theBMass + + +def get_visible_yield(obs, results, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + visible = amplitude.getVal() * intgral_pdf.getVal() + return visible + +def get_visible_yield_error(obs, results, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + intgral_pdf_err = intgral_pdf.getPropagatedError(results, obs) + visible = amplitude.getVal() * intgral_pdf.getVal() + visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 + return visible, visible_err + + + +##################### signal fit == Double sided CB ###################### +def signal_fit(tree, outputfile, branches, SavePlot=True): + print "Signal" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) + # signal + wspace.factory('mean[5.278e+00, 5.25e+00, 5.3e+00]') + wspace.factory('width[5.8851e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.85, 0.0, 10.0]') + wspace.factory('n1[19.9999, 0.0, 100.0]') + wspace.factory('CBShape::sigcb(x,mean,width,alpha1,n1)') + wspace.factory('mean2[5.19e+00, 5.0e+00, 5.30e+00]') + wspace.factory('width2[1.3367e-01, 1.0e-6, 5.0e-1]') + wspace.factory('RooGaussian::sigg(x,mean2,width2)') + wspace.factory('frac[0.5, 0, 1.0]') + wspace.factory('SUM::sig(sigcb,frac*sigg)') + + sgnframe=theBMass.frame() + wspace.factory('nsig[1000,0,100000000]') + wspace.factory('RooExtendPdf::esig(sig,nsig)') + sig=wspace.pdf('sig') + nsig=wspace.var('nsig') + esig=wspace.pdf('esig') + results = esig.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + + results.Print() + dataset.plotOn(sgnframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + esig.plotOn(sgnframe, RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected), RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + n_param = results.floatParsFinal().getSize() + print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('sgn_eek_'+outputfile+'.pdf') + residuals(sgnframe,theBMass,'sgn_eek_'+outputfile) + params=esig.getParameters(ROOT.RooArgSet(bMass)) + #return {"mean":1} + return {"mean":params.getRealValue('mean'),"width": params.getRealValue('width'),"alpha1":params.getRealValue('alpha1'),"n1":params.getRealValue('n1'),"frac":params.getRealValue('frac'),"gauss_mean":params.getRealValue('mean2'),"gauss_width":params.getRealValue('width2')} + +############################ BKG fit ################################# + +############################### other B fit==Expo ############################## +def otherB_fit(tree, outputfile, branches, SavePlot=True): + print "otherB" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_otherB_bkg",branches[0],tree) + wspace.factory('exp_alpha_otherb[-6.7, -100.0, -1.e-4]') + exp_alpha_otherb = wspace.var('exp_alpha_otherb') + wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') + wspace.factory('notherB[1000,0,10e+6]') + wspace.factory('RooExtendPdf::eexp_otherb(exp_otherb,notherB)') + notherB=wspace.var('notherB') + eexp_otherb=wspace.pdf('eexp_otherb') + results = eexp_otherb.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + results.Print() + otherb_frame=theBMass.frame() + dataset.plotOn(otherb_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) + eexp_otherb.plotOn(otherb_frame,RooFit.Name("eexpOB"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + c1=canvas_create(otherb_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_otherB_'+outputfile+'.pdf') + residuals(otherb_frame,theBMass,'bkg_otherB_'+outputfile) + params=eexp_otherb.getParameters(ROOT.RooArgSet(bMass)) + n_param = results.floatParsFinal().getSize() + print "chi2",otherb_frame.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + return {"exp_alpha_otherb":params.getRealValue('exp_alpha_otherb')} + +############################ KDE fit ####################### +def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): + print "KDE - {}".format(pdfname) + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree) + kde_frame=theBMass.frame() + wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(pdfname)) + kde = wspace.pdf(pdfname) + + dataset.plotOn(kde_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) + kde.plotOn(kde_frame, RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + + #wf = ROOT.TFile('ws_bkg_kde_'+outputfile+'_{}.root'.format(pdfname), "RECREATE") + #wspace.Write() + #wf.Close() + + c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_kde_'+outputfile+'_{}.pdf'.format(pdfname)) + residuals(kde_frame,theBMass,'bkg_kde_'+outputfile+'_'+pdfname) + return kde + + +############################ Combinatorial fit =Expo ########################### +def bkg_fit(tree, outputfile, branches, SavePlot=True): + print "combinatorial" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_comb_bkg",branches[0],tree) + wspace.factory('exp_alpha_comb[-1.5, -100.0, -1.e-4]') + wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') + wspace.factory('ncomb[1000,0,10e+6]') + wspace.factory('RooExtendPdf::eexp_comb(exp_comb,ncomb)') + ncomb=wspace.var('ncomb') + eexp_comb=wspace.pdf('eexp_comb') + + results = eexp_comb.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) ) + results.Print() + combframe=theBMass.frame() + dataset.plotOn(combframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + eexp_comb.plotOn(combframe,RooFit.Name("eexp_comb"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + params=eexp_comb.getParameters(ROOT.RooArgSet(bMass)) + c1=canvas_create(combframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_comb_'+outputfile+'.pdf') + n_param = results.floatParsFinal().getSize() + print "chi2",combframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + if SavePlot: + residuals(combframe,theBMass,'bkg_comb_'+outputfile) + + return {"exp_alpha_comb":params.getRealValue('exp_alpha_comb')} + + + +############################# total fit ############################## +def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarJpsi_pdf=None,comb_parameters=None,Significance_range=None, partial_ratio=None, mvacut="",log='log.csv'): + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) + print "Total" + #amplitudes + wspace.factory('nsignal[100.0, 0.0, 1000000.0]' ) + wspace.factory('ncomb[10000.0, 0.0, 1000000.0]') + wspace.factory('notherB[10000.0, 0.0, 1000000.0]') + wspace.factory('frac_partial[1.0, 0.0, 10.0]') + wspace.factory('prod::nKstarJpsi(frac_partial,nsignal)') + + #wspace.factory('nKstarJpsi[10000.0, 0.0, 1000000.0]') + + # signal + wspace.factory('mean[5.278e+00, 5.22e+00, 5.5e+00]') + wspace.factory('width[5.8851e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.85, 0.0, 10.0]') + wspace.factory('n1[19.9999, 0.0, 2000.0]') + wspace.factory('CBShape::cb_signal(x,mean,width,alpha1,n1)') + wspace.factory('gauss_mean[5.19e+00, 5.0e+00, 5.30e+00]') + wspace.factory('gauss_width[1.3367e-01, 1.0e-6, 5.0e-1]') + wspace.factory('RooGaussian::g_signal(x,gauss_mean,gauss_width)') + wspace.factory('frac[0.5, 0, 1.0]') + wspace.factory('SUM::signal(cb_signal,frac*g_signal)') + + # other B - bkg + wspace.factory('exp_alpha_otherb[-1.0, -100.0, -1.e-4]') + wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') + + # K*Jpsi - bkg + getattr(wspace, "import")(KstarJpsi_pdf, RooFit.Rename('kstarjpsi')) + + # combinatorial - bkg + wspace.factory('exp_alpha_comb[-1.0, -100.0, -1.e-4]') + wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') + + #sum + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarJpsi*kstarjpsi,notherB*exp_otherb)') + + model = wspace.pdf('model'); + signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') + exp_otherb = wspace.pdf('exp_otherb') + kstarjpsi = wspace.pdf('kstarjpsi') + nsignal = wspace.var('nsignal'); ncomb = wspace.var('ncomb') + nKstarJpsi = wspace.obj('nKstarJpsi') + notherB = wspace.var('notherB') + frac_partial = wspace.var('frac_partial') + + for par in signal_parameters.keys(): + (wspace.var(par)).setVal(signal_parameters[par]) + (wspace.var(par)).setConstant(True) + for par in otherB_parameters.keys(): + (wspace.var(par)).setVal(otherB_parameters[par]) + #(wspace.var(par)).setConstant(True) + for par in comb_parameters.keys(): + (wspace.var(par)).setVal(comb_parameters[par]) + (wspace.var(par)).setConstant(True) + + if partial_ratio is not None: + wspace.var('frac_partial').setVal(partial_ratio) + wspace.var('frac_partial').setConstant(True) + + results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + print results.Print() + xframe=theBMass.frame(RooFit.Title("")) + + norm=1. + dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + + model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("signal"),RooFit.Components("signal"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) + model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) + # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + # c1.SaveAs('total_fit_'+outputfile+'.pdf') + wspace.defineSet('obs', 'x') + obs = wspace.set('obs') + + params=model.getParameters(ROOT.RooArgSet(bMass)) + if Significance_range==None: + Significance_range={"min":params["mean"]-2*params["width"],"max":params["mean"]+2*params["width"]} + theBMass.setRange("window",Significance_range["min"],Significance_range["max"]) + + #theBMass.setRange("window",5.0,5.4) + obs2= ROOT.RooRealVar("obs2","obs2",Significance_range["min"],Significance_range["max"]) + nset = ROOT.RooArgSet(obs2) + print nsignal.getVal(), nsignal.getVal(nset) + print Significance_range + ncomb_visible, ncomb_visible_err = get_visible_yield_error(obs, results, exp_comb, ncomb) + nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, signal, nsignal) + nKstarJpsi_visible = get_visible_yield(obs, results, kstarjpsi , nKstarJpsi) + nKstarJpsi_visible_err = 0.0 + notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) + nbkg_visible = nKstarJpsi_visible+ncomb_visible+notherB_visible + +# c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + n_param = results.floatParsFinal().getSize() + print "chi2",xframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + + legend = ROOT.TLegend(0.65,0.65,0.92,0.85) + legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); + legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); + legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); + legend.AddEntry(xframe.findObject("sig"),"B -> J/#psiK","l"); + legend.SetLineColor(ROOT.kWhite) + legend.SetTextFont(42); + legend.SetTextSize(0.04); + legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); + legend.Draw(); + pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nKstarJpsi_visible+ncomb_visible+notherB_visible) + pt.Draw() + CMS_lumi() + c1.cd() + c1.Update() + c1.SaveAs('total_fit_'+outputfile+'.pdf') + print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err,"otherB", notherB_visible, "+/-",notherB_visible_err + residuals(xframe,theBMass,"poutana") + + # get likelihood + + nll = model.createNLL(dataset) + ROOT.RooMinuit(nll).migrad() + nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(7500.0,10000.0),RooFit.Title("LL and profileLL in nsignal")) ; + #nll.plotOn(nll_frame,RooFit.ShiftToZero()) + pll = nll.createProfile(ROOT.RooArgSet(nsignal)) + pll.plotOn(nll_frame,RooFit.LineColor(2),RooFit.ShiftToZero()) + nll_frame.SetMinimum(0); + nll_frame.SetMaximum(10) + c2 = canvas_create(nll_frame,0.0,0.0,0.0,'nsig') + CMS_lumi() + c2.cd() + c2.Update() + c2.SaveAs('nll_'+outputfile+'.pdf') + + wspace_output = ROOT.RooWorkspace('wspace') + getattr(wspace_output, "import")(model) + getattr(wspace_output, "import")(dataset) + params = model.getParameters(dataset) + wspace_output.saveSnapshot("nominal_values",params) + wspace_output.Print("V") + wspace_output.writeToFile('wspace_'+outputfile+'.root') + + + csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarJpsi_total', 'nKstarJpsi_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarJpsi', 'notherB', 'snr', 'chi2'] + df = {} + df['cut'] = mvacut + df['nsig_total'] = nsignal.getVal() + df['nsig_total_unc'] = nsignal.getError() + df['nKstarJpsi_total'] = nKstarJpsi.getVal() + df['nKstarJpsi_total_unc'] = 0.0 + df['nsig'] = nsig_visible + df['nbkg'] = nbkg_visible + df['ncomb'] = ncomb_visible + df['nKstarJpsi'] = nKstarJpsi_visible + df['notherB'] = notherB_visible + df['snr'] = nsig_visible / np.sqrt(nsig_visible + nbkg_visible) + df['chi2'] = xframe.chiSquare(n_param) + csv_outputfile = log + file_exists = os.path.isfile(csv_outputfile) + with open (csv_outputfile, 'a+') as filedata: + writer = csv.DictWriter(filedata, delimiter=',', fieldnames=csv_header) + if not file_exists: + writer.writeheader() + writer.writerow(df) + + return (nsig_visible, ncomb_visible, nKstarJpsi_visible, notherB_visible, nsignal.getVal() ) + + + +#################################### main ################################ +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser(description='Unbinned likelihood fit') + parser.add_argument("-i", "--inputfile", dest="inputfile", default="../BDT/TrainingCore/forMeas_xgbmodel_kee_v5.1_12B_Mu9_*_data.root", help="Input data file") + parser.add_argument("-o", "--outputfile", dest="outputfile", default="test", help="Output name") + parser.add_argument("--mvacut", dest="mva",default=6.2,type=float) + parser.add_argument("--isgn", "--isgnfile", dest="isgnfile", default="mc_files/reg/BParkingNANO_2021Mar05_BuToKJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_mva_pf.root", help="Input signal file") + parser.add_argument("--ibkg", dest="ibkg", default="../BDT/TrainingCore/forMeas_xgbmodel_kee_v5.1_12B_Mu9_*_samesign.root", help="Input combinatorial BKG file") + parser.add_argument("--iotherB", dest="iotherB_BKG", default="OtherB_BKGtree_KJpsiEE.root", help="Input combinatorial BKG file") + parser.add_argument("--iKstarJpsi_BKG", dest="iKstarJpsi_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input combinatorial BKG file") + parser.add_argument("--fit_primitive", dest="fit_primtv", default=False, action='store_true', help="primitive fits for fixing params or use defaults") + parser.add_argument("--skip_realfit", dest="skip_realfit", default=False, action='store_true', help="does not perform the final fit. useful for defining parameters, tests on pdfs") + parser.add_argument("--sel_primitive", dest="sel_primtv", default=None, help="runs only the selected primitive fits. Options: sgn bkg_comb bkg_otherb bkg_kstar_kee bkg_kstar_piee. they can be combined with ',' in strings. No spaces") + parser.add_argument("--minx", dest="minx", default=-1.0,type=float, help="minx for integral") + parser.add_argument("--maxx", dest="maxx", default=-1.0,type=float, help="maxx for integral") + parser.add_argument("--log", dest="log", default="log.csv", help="log of the fitting results") + parser.add_argument("--partial_ratio", dest="partial_ratio", default=None, type=float, help="fixing the partially reco. yield") + args = parser.parse_args() + + branches=["Bmass","Mll","xgb","KLmassD0"] + cuts = branches[2]+">"+str(args.mva)+" && 2.8<"+branches[1]+" && "+branches[1]+"<3.25" + #cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.25" + #cuts = branches[2]+">"+str(args.mva)+" && 2.8<"+branches[1]+" && "+branches[1]+"<3.25" + " && " + branches[3] + ">2.0" + + args.outputfile+="_wp"+str(args.mva) + + otherB_parameters={'exp_alpha_otherb':-5.099} + comb_parameters={'exp_alpha_comb':-1.50615} + + print "start" + if args.fit_primtv: + if args.sel_primtv!= None: + args.sel_primtv = args.sel_primtv.split(",") + else: + args.sel_primtv = ["sgn","bkg_comb","bkg_otherb","bkg_kstarjpsi"] + print "primitive params" + if "sgn" in args.sel_primtv: + tree_sgn = ROOT.TChain('mytreefit') + tree_sgn.Add(args.isgnfile) + tree_sgn_cut=tree_sgn.CopyTree(cuts) + print tree_sgn_cut.GetEntries() + signal_parameters = signal_fit(tree_sgn_cut, args.outputfile+"_sgnMC", branches) + print "parameters SGN", signal_parameters['mean'], signal_parameters['width'],signal_parameters['alpha1'],signal_parameters['n1'],signal_parameters['frac'],signal_parameters['gauss_mean'],signal_parameters['gauss_width'] + + if "bkg_otherb" in args.sel_primtv: + tree_otherB = ROOT.TChain('mytreefit') + tree_otherB.Add(args.iotherB_BKG) + tree_otherB_cut=tree_otherB.CopyTree(cuts) + otherB_parameters = otherB_fit(tree_otherB_cut, args.outputfile+"_otherBMC", branches) + print "parameters otherB BKG", otherB_parameters['exp_alpha_otherb'] + + if "bkg_comb" in args.sel_primtv: + tree_bkg = ROOT.TChain('mytreefit') + tree_bkg.Add(args.ibkg) + tree_bkg_cut=tree_bkg.CopyTree(cuts) + comb_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) + print "parameters Combinatorial BKG", comb_parameters['exp_alpha_comb'] + + if "bkg_kstarjpsi" in args.sel_primtv: + tree_KstarJpsi = ROOT.TChain('mytreefit') + tree_KstarJpsi.Add(args.iKstarJpsi_BKG) + tree_KstarJpsi_cut=tree_KstarJpsi.CopyTree(cuts) + KstarJpsi_pdf = kde_fit(tree_KstarJpsi_cut, args.outputfile+"_KstarJpsiMC", branches, 'kstarjpsi') + print "finished kde fit for K* J/psi" + + else: + print "Need to provide MC template" + + if not args.skip_realfit: + tree = ROOT.TChain('mytreefit') + tree.Add(args.inputfile) + tree_cut=tree.CopyTree(cuts) + if args.minx==-1: args.minx=signal_parameters["mean"]-2*signal_parameters["width"] + if args.maxx==-1: args.maxx=signal_parameters["mean"]+2*signal_parameters["width"] + + nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarJpsi_pdf,comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, str(args.mva), args.log) + print "sig",nsig,"comb", nbkg,"K* J/psi", nKstarJpsi,"otherB", notherB,"all sig", nsig_total + # combinatorial BKG parameters set but not fixed. +# print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) + + + diff --git a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py new file mode 100644 index 0000000..2b47136 --- /dev/null +++ b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py @@ -0,0 +1,481 @@ +import ROOT +from ROOT import RooFit +import math +from roofit_helper import * +#ROOT.gROOT.ProcessLine(open('roofit_models.h').read()) +#from ROOT import DoubleSidedCB +#from ROOT import ROOT_DoubleSidedCB +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +#ROOT.gStyle.SetOptFit(0000); +ROOT.gROOT.SetBatch(True); +ROOT.gROOT.SetStyle("Plain"); +msgservice = ROOT.RooMsgService.instance() +msgservice.setGlobalKillBelow(RooFit.FATAL) +import numpy as np +import csv +import os.path +import atexit + +nbin_data = 50 + +def residuals(xframe, var,name): + hresid = xframe.residHist() + xframe2 = var.frame() + xframe2.addPlotable(hresid,"P") + c2=canvas_create(xframe2,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c2.SaveAs(name+'_residual.pdf') + hpull = xframe.pullHist() + xframe3 = var.frame() + xframe3.addPlotable(hpull,"P") + c3=canvas_create(xframe3,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c3.SaveAs(name+'_pull.pdf') + + + +def define_workspace_bmass_data(wspace_name,mB_branch,tree): + wspace = ROOT.RooWorkspace(wspace_name) + fitvars = ROOT.RooArgSet() + bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") + fitvars.add(bMass) + dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) + theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) + theBMass = dataset.addColumn(theBMassfunc) ; + theBMass.setRange(4.7,5.7); + fitvars.add(theBMass) + getattr(wspace, "import")(dataset, RooFit.Rename('data')) + # When a RooWorkspace is set as an attribute of a class, it can trigger a memory error + # This is solved in the latest ROOT version > 6.14.08 + atexit.register(wspace.Delete) + return wspace,dataset,bMass,theBMass + +def get_visible_yield(obs, results, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + visible = amplitude.getVal() * intgral_pdf.getVal() + return visible + +def get_visible_yield_error(obs, results, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + intgral_pdf_err = intgral_pdf.getPropagatedError(results, obs) + visible = amplitude.getVal() * intgral_pdf.getVal() + visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 + return visible, visible_err + + + +##################### signal fit == Double sided CB ###################### +def signal_fit(tree, outputfile, branches, SavePlot=True): + print "Signal" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) + # signal + wspace.factory('mean[5.278e+00, 5.25e+00, 5.3e+00]') + wspace.factory('width[5.8851e-03, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.85, 0.0, 10.0]') + wspace.factory('n1[1.9999, 1.0, 100.0]') + wspace.factory('CBShape::sigcb(x,mean,width,alpha1,n1)') + wspace.factory('mean2[5.19e+00, 5.0e+00, 5.30e+00]') + wspace.factory('width2[1.3367e-01, 1.0e-6, 5.0e-1]') + wspace.factory('RooGaussian::sigg(x,mean2,width2)') + wspace.factory('frac[0.7, 0, 1.0]') + wspace.factory('SUM::sig(sigcb,frac*sigg)') + + sgnframe=theBMass.frame() + wspace.factory('nsig[1000,0,100000000]') + wspace.factory('RooExtendPdf::esig(sig,nsig)') + sig=wspace.pdf('sig') + nsig=wspace.var('nsig') + esig=wspace.pdf('esig') + results = esig.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + + results.Print() + dataset.plotOn(sgnframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + esig.plotOn(sgnframe, RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected), RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + n_param = results.floatParsFinal().getSize() + print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('sgn_eek_'+outputfile+'.pdf') + residuals(sgnframe,theBMass,'sgn_eek_'+outputfile) + params=esig.getParameters(ROOT.RooArgSet(bMass)) + #return {"mean":1} + return {"mean":params.getRealValue('mean'),"width": params.getRealValue('width'),"alpha1":params.getRealValue('alpha1'),"n1":params.getRealValue('n1'),"frac":params.getRealValue('frac'),"gauss_mean":params.getRealValue('mean2'),"gauss_width":params.getRealValue('width2')} + +############################ BKG fit ################################# + +############################### other B fit==Expo ############################## +def otherB_fit(tree, outputfile, branches, SavePlot=True): + print "otherB" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_otherB_bkg",branches[0],tree) + wspace.factory('exp_alpha_otherb[-6.7, -100.0, -1.e-4]') + exp_alpha_otherb = wspace.var('exp_alpha_otherb') + wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') + wspace.factory('notherB[1000,0,10e+6]') + wspace.factory('RooExtendPdf::eexp_otherb(exp_otherb,notherB)') + notherB=wspace.var('notherB') + eexp_otherb=wspace.pdf('eexp_otherb') + results = eexp_otherb.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + results.Print() + otherb_frame=theBMass.frame() + dataset.plotOn(otherb_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) + eexp_otherb.plotOn(otherb_frame,RooFit.Name("eexpOB"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + c1=canvas_create(otherb_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_otherB_'+outputfile+'.pdf') + residuals(otherb_frame,theBMass,'bkg_otherB_'+outputfile) + params=eexp_otherb.getParameters(ROOT.RooArgSet(bMass)) + n_param = results.floatParsFinal().getSize() + print "chi2",otherb_frame.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + return {"exp_alpha_otherb":params.getRealValue('exp_alpha_otherb')} + + +############################ KDE fit ####################### +def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): + print "KDE - {}".format(pdfname) + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree) + kde_frame=theBMass.frame() + #wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(pdfname)) + wspace.factory('KeysPdf::{0}(x,data,MirrorBoth,2.0)'.format(pdfname)) + kde = wspace.pdf(pdfname) + + dataset.plotOn(kde_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) + kde.plotOn(kde_frame, RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + + #wf = ROOT.TFile('ws_bkg_kde_'+outputfile+'_{}.root'.format(pdfname), "RECREATE") + #wspace.Write() + #wf.Close() + + c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_kde_'+outputfile+'_{}.pdf'.format(pdfname)) + residuals(kde_frame,theBMass,'bkg_kde_'+outputfile+'_'+pdfname) + return kde + +############################ Combinatorial fit =Expo ########################### +def bkg_fit(tree, outputfile, branches, SavePlot=True): + print "combinatorial" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_comb_bkg",branches[0],tree) + wspace.factory('exp_alpha_comb[-1.5, -100.0, -1.e-4]') + wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') + wspace.factory('ncomb[1000,0,10e+6]') + wspace.factory('RooExtendPdf::eexp_comb(exp_comb,ncomb)') + ncomb=wspace.var('ncomb') + eexp_comb=wspace.pdf('eexp_comb') + + results = eexp_comb.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) ) + results.Print() + combframe=theBMass.frame() + dataset.plotOn(combframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + eexp_comb.plotOn(combframe,RooFit.Name("eexp_comb"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + params=eexp_comb.getParameters(ROOT.RooArgSet(bMass)) + c1=canvas_create(combframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_comb_'+outputfile+'.pdf') + n_param = results.floatParsFinal().getSize() + print "chi2",combframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + if SavePlot: + residuals(combframe,theBMass,'bkg_comb_'+outputfile) + + return {"exp_alpha_comb":params.getRealValue('exp_alpha_comb')} + + + +############################# total fit ############################## +def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarPsi2S_pdf=None , KstarJpsi_pdf=None , KJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, mvacut="",log='log.csv'): + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) + print "Total" + #amplitudes + wspace.factory('nsignal[100.0, 0.0, 1000000.0]' ) + wspace.factory('ncomb[10000.0, 0.0, 1000000.0]') + wspace.factory('notherB[10000.0, 0.0, 1000000.0]') + wspace.factory('nKstarJpsi[10000.0, 0.0, 1000000.0]') + wspace.factory('nkjpsi[10000.0, 0.0, 1000000.0]') + + wspace.factory('frac_partial[1.0, 0.0, 10.0]') + wspace.factory('prod::nKstarPsi2S(frac_partial,nsignal)') + + + # signal + wspace.factory('mean[5.278e+00, 5.22e+00, 5.5e+00]') + wspace.factory('width[5.8851e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.85, 0.0, 10.0]') + wspace.factory('n1[19.9999, 0.0, 2000.0]') + wspace.factory('CBShape::cb_signal(x,mean,width,alpha1,n1)') + wspace.factory('gauss_mean[5.19e+00, 5.0e+00, 5.30e+00]') + wspace.factory('gauss_width[1.3367e-01, 1.0e-6, 5.0e-1]') + wspace.factory('RooGaussian::g_signal(x,gauss_mean,gauss_width)') + wspace.factory('frac[0.5, 0, 1.0]') + wspace.factory('SUM::signal(cb_signal,frac*g_signal)') + + # other B - bkg + wspace.factory('exp_alpha_otherb[-1.0, -100.0, -1.e-4]') + wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') + + # K*Psi2S - bkg + getattr(wspace, "import")(KstarPsi2S_pdf, RooFit.Rename('kstarpsi2s')) + + # K*Jpsi - bkg + getattr(wspace, "import")(KstarJpsi_pdf, RooFit.Rename('kstarjpsi')) + + # KJpsi - bkg + getattr(wspace, "import")(KJpsi_pdf, RooFit.Rename('kjpsi')) + + # combinatorial - bkg + wspace.factory('exp_alpha_comb[-1.0, -100.0, -1.e-4]') + wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') + + #sum + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,nkjpsi*kjpsi,notherB*exp_otherb)') + + model = wspace.pdf('model'); + signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') + exp_otherb = wspace.pdf('exp_otherb') + kjpsi = wspace.pdf('kjpsi') + kstarpsi2s = wspace.pdf('kstarpsi2s'); kstarjpsi = wspace.pdf('kstarjpsi') + nsignal = wspace.var('nsignal'); ncomb = wspace.var('ncomb') + nKstarPsi2S = wspace.obj('nKstarPsi2S'); nKstarJpsi = wspace.var('nKstarJpsi') + nKJpsi = wspace.var('nkjpsi') + notherB = wspace.var('notherB') + frac_partial = wspace.var('frac_partial') + + for par in signal_parameters.keys(): + (wspace.var(par)).setVal(signal_parameters[par]) + (wspace.var(par)).setConstant(True) + for par in otherB_parameters.keys(): + (wspace.var(par)).setVal(otherB_parameters[par]) + #(wspace.var(par)).setConstant(True) + for par in comb_parameters.keys(): + (wspace.var(par)).setVal(comb_parameters[par]) + (wspace.var(par)).setConstant(True) + + if partial_ratio is not None: + wspace.var('frac_partial').setVal(partial_ratio) + wspace.var('frac_partial').setConstant(True) + + #wspace.var('nKstarJpsi').setVal(0) + #wspace.var('nKstarJpsi').setConstant(True) + + results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + print results.Print() + xframe=theBMass.frame(RooFit.Title("")) + + norm=1. + dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + + model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(43),RooFit.LineColor(43),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("kstarpsi2s"),RooFit.Components("kstarpsi2s"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(15),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("signal"),RooFit.Components("signal"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) + model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) + # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + # c1.SaveAs('total_fit_'+outputfile+'.pdf') + wspace.defineSet('obs', 'x') + obs = wspace.set('obs') + + params=model.getParameters(ROOT.RooArgSet(bMass)) + if Significance_range==None: + Significance_range={"min":params["mean"]-2*params["width"],"max":params["mean"]+2*params["width"]} + theBMass.setRange("window",Significance_range["min"],Significance_range["max"]) + + #theBMass.setRange("window",5.0,5.4) + obs2= ROOT.RooRealVar("obs2","obs2",Significance_range["min"],Significance_range["max"]) + nset = ROOT.RooArgSet(obs2) + print nsignal.getVal(), nsignal.getVal(nset) + print Significance_range + ncomb_visible, ncomb_visible_err = get_visible_yield_error(obs, results, exp_comb, ncomb) + nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, signal, nsignal) + nKstarPsi2S_visible = get_visible_yield(obs, results, kstarpsi2s , nKstarPsi2S) + nKstarPsi2S_visible_err = 0.0 + nKstarJpsi_visible, nKstarJpsi_visible_err = get_visible_yield_error(obs, results, kstarjpsi , nKstarJpsi) + nKJpsi_visible, nKJpsi_visible_err = get_visible_yield_error(obs, results,kjpsi , nKJpsi) + notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) + nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+nKJpsi_visible+notherB_visible + +# c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + n_param = results.floatParsFinal().getSize() + print "chi2",xframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + + legend = ROOT.TLegend(0.65,0.65,0.92,0.85) + legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); + legend.AddEntry(xframe.findObject("kstarpsi2s"),"B -> #psi(2S)K*","l"); + legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); + legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); + legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); + legend.AddEntry(xframe.findObject("sig"),"B -> #psi(2S)K","l"); + legend.SetLineColor(ROOT.kWhite) + legend.SetTextFont(42); + legend.SetTextSize(0.04); + legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); + legend.Draw(); + pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nKstarPsi2S_visible+nKstarJpsi_visible+ncomb_visible+nKJpsi_visible+notherB_visible) + pt.Draw() + CMS_lumi() + c1.cd() + c1.Update() + c1.SaveAs('total_fit_'+outputfile+'.pdf') + print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* Psi2S", nKstarPsi2S_visible, "+/-",nKstarPsi2S_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err, "K J/psi", nKJpsi_visible, "+/-", nKJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err + residuals(xframe,theBMass,"poutana") + + # get likelihood + + nll = model.createNLL(dataset) + ROOT.RooMinuit(nll).migrad() + nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(500,1000),RooFit.Title("LL and profileLL in nsignal")) ; + #nll.plotOn(nll_frame,RooFit.ShiftToZero()) + pll = nll.createProfile(ROOT.RooArgSet(nsignal)) + pll.plotOn(nll_frame,RooFit.LineColor(2),RooFit.ShiftToZero()) + nll_frame.SetMinimum(0); + nll_frame.SetMaximum(10) + c2 = canvas_create(nll_frame,0.0,0.0,0.0,'nsig') + CMS_lumi() + c2.cd() + c2.Update() + c2.SaveAs('nll_'+outputfile+'.pdf') + + wspace_output = ROOT.RooWorkspace('wspace') + getattr(wspace_output, "import")(model) + getattr(wspace_output, "import")(dataset) + params = model.getParameters(dataset) + wspace_output.saveSnapshot("nominal_values",params) + wspace_output.Print("V") + wspace_output.writeToFile('wspace_'+outputfile+'.root') + + csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarPsi2S_total', 'nKstarPsi2S_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarPsi2S', 'nKstarJpsi', 'nKJpsi', 'notherB', 'snr', 'chi2'] + df = {} + df['cut'] = mvacut + df['nsig_total'] = nsignal.getVal() + df['nsig_total_unc'] = nsignal.getError() + df['nKstarPsi2S_total'] = nKstarPsi2S.getVal() + df['nKstarPsi2S_total_unc'] = 0.0 + df['nsig'] = nsig_visible + df['nbkg'] = nbkg_visible + df['ncomb'] = ncomb_visible + df['nKstarPsi2S'] = nKstarPsi2S_visible + df['nKstarJpsi'] = nKstarJpsi_visible + df['nKJpsi'] = nKJpsi_visible + df['notherB'] = notherB_visible + df['snr'] = nsig_visible / np.sqrt(nsig_visible + nbkg_visible) + df['chi2'] = xframe.chiSquare(n_param) + csv_outputfile = log + file_exists = os.path.isfile(csv_outputfile) + with open (csv_outputfile, 'a+') as filedata: + writer = csv.DictWriter(filedata, delimiter=',', fieldnames=csv_header) + if not file_exists: + writer.writeheader() + writer.writerow(df) + + return (nsig_visible, ncomb_visible, nKstarPsi2S_visible, nKstarJpsi_visible, nKJpsi_visible, notherB_visible, nsignal.getVal() ) + + + +#################################### main ################################ +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser(description='Unbinned likelihood fit') + parser.add_argument("-i", "--inputfile", dest="inputfile", default="../BDT/TrainingCore/forMeas_xgbmodel_kee_v5.1_12B_Mu9_*_data.root", help="Input data file") + parser.add_argument("-o", "--outputfile", dest="outputfile", default="test", help="Output name") + parser.add_argument("--mvacut", dest="mva",default=6.2,type=float) + parser.add_argument("--isgn", "--isgnfile", dest="isgnfile", default="mc_files/reg/BParkingNANO_2021Mar05_BuToKJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_mva_pf.root", help="Input signal file") + parser.add_argument("--ibkg", dest="ibkg", default="../BDT/TrainingCore/forMeas_xgbmodel_kee_v5.1_12B_Mu9_*_samesign.root", help="Input combinatorial BKG file") + parser.add_argument("--iotherB", dest="iotherB_BKG", default="OtherB_BKGtree_KJpsiEE.root", help="Input combinatorial BKG file") + parser.add_argument("--iKstarPsi2S_BKG", dest="iKstarPsi2S_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input B->K*Psi(2S) BKG file") + parser.add_argument("--iKstarJpsi_BKG", dest="iKstarJpsi_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input B->K*J/psi BKG file") + parser.add_argument("--iKJpsiee_BKG", dest="iKJpsiee_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_pion_mva_pf.root", help="Input B->KJ/psi BKG file") + parser.add_argument("--fit_primitive", dest="fit_primtv", default=False, action='store_true', help="primitive fits for fixing params or use defaults") + parser.add_argument("--skip_realfit", dest="skip_realfit", default=False, action='store_true', help="does not perform the final fit. useful for defining parameters, tests on pdfs") + parser.add_argument("--sel_primitive", dest="sel_primtv", default=None, help="runs only the selected primitive fits. Options: sgn bkg_comb bkg_otherb bkg_kstar_kee bkg_kstar_piee. they can be combined with ',' in strings. No spaces") + parser.add_argument("--partial_ratio", dest="partial_ratio", default=None, type=float, help="fixing the partially reco. yield") + parser.add_argument("--minx", dest="minx", default=-1.0,type=float, help="minx for integral") + parser.add_argument("--maxx", dest="maxx", default=-1.0,type=float, help="maxx for integral") + parser.add_argument("--log", dest="log", default="log.csv", help="log of the fitting results") + args = parser.parse_args() + + branches=["Bmass","Mll","xgb","KLmassD0"] + cuts = branches[2]+">"+str(args.mva)+" && 3.45<"+branches[1]+" && "+branches[1]+"<3.8" + #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" + args.outputfile+="_wp"+str(args.mva) + + otherB_parameters={'exp_alpha_otherb':-5.099} + #otherB_parameters={'exp_alpha_otherb':-7.099} + comb_parameters={'exp_alpha_comb':-1.50615} + + print "start" + if args.fit_primtv: + if args.sel_primtv!= None: + args.sel_primtv = args.sel_primtv.split(",") + else: + args.sel_primtv = ["sgn","bkg_comb","bkg_otherb","bkg_kstarjpsi","bkg_kstarpsi2s","bkg_kjpsi_ee"] + print "primitive params" + if "sgn" in args.sel_primtv: + tree_sgn = ROOT.TChain('mytreefit') + tree_sgn.Add(args.isgnfile) + tree_sgn_cut=tree_sgn.CopyTree(cuts) + print tree_sgn_cut.GetEntries() + signal_parameters = signal_fit(tree_sgn_cut, args.outputfile+"_sgnMC", branches) + print "parameters SGN", signal_parameters['mean'], signal_parameters['width'],signal_parameters['alpha1'],signal_parameters['n1'],signal_parameters['frac'],signal_parameters['gauss_mean'],signal_parameters['gauss_width'] + + if "bkg_otherb" in args.sel_primtv: + tree_otherB = ROOT.TChain('mytreefit') + tree_otherB.Add(args.iotherB_BKG) + tree_otherB_cut=tree_otherB.CopyTree(cuts) + otherB_parameters = otherB_fit(tree_otherB_cut, args.outputfile+"_otherBMC", branches) + print "parameters otherB BKG", otherB_parameters['exp_alpha_otherb'] + + if "bkg_comb" in args.sel_primtv: + tree_bkg = ROOT.TChain('mytreefit') + tree_bkg.Add(args.ibkg) + tree_bkg_cut=tree_bkg.CopyTree(cuts) + comb_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) + print "parameters Combinatorial BKG", comb_parameters['exp_alpha_comb'] + + if "bkg_kstarpsi2s" in args.sel_primtv: + tree_KstarPsi2S = ROOT.TChain('mytreefit') + tree_KstarPsi2S.Add(args.iKstarPsi2S_BKG) + tree_KstarPsi2S_cut=tree_KstarPsi2S.CopyTree(cuts) + KstarPsi2S_pdf = kde_fit(tree_KstarPsi2S_cut, args.outputfile+"_KstarPsi2SMC", branches, 'kstarpsi2s') + print "finished kde fit for K* psi(2S)" + + if "bkg_kstarjpsi" in args.sel_primtv: + tree_KstarJpsi = ROOT.TChain('mytreefit') + tree_KstarJpsi.Add(args.iKstarJpsi_BKG) + tree_KstarJpsi_cut=tree_KstarJpsi.CopyTree(cuts) + KstarJpsi_pdf = kde_fit(tree_KstarJpsi_cut, args.outputfile+"_KstarJpsiMC", branches, 'kstarjpsi') + print "finished kde fit for K* J/psi" + + if "bkg_kjpsi_ee" in args.sel_primtv: + tree_KJpsiee = ROOT.TChain('mytreefit') + tree_KJpsiee.Add(args.iKJpsiee_BKG) + tree_KJpsiee_cut=tree_KJpsiee.CopyTree(cuts) + KJpsiee_pdf = kde_fit(tree_KJpsiee_cut, args.outputfile+"_KJpsieeMC", branches, 'kjpsi') + print "finished kde fit for K J/psi" + + else: + print "Need to provide MC template" + + if not args.skip_realfit: + tree = ROOT.TChain('mytreefit') + tree.Add(args.inputfile) + tree_cut=tree.CopyTree(cuts) + if args.minx==-1: args.minx=signal_parameters["mean"]-2*signal_parameters["width"] + if args.maxx==-1: args.maxx=signal_parameters["mean"]+2*signal_parameters["width"] + + nsig, nbkg, nKstarPsi2S, nKstarJpsi, nKJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarPsi2S_pdf, KstarJpsi_pdf ,KJpsiee_pdf, comb_parameters, {"min":args.minx,"max":args.maxx},args.partial_ratio, str(args.mva), args.log) + print "sig",nsig,"comb", nbkg,"K* Psi2S", nKstarPsi2S,"K* J/psi", nKstarJpsi,"K J/psi", nKJpsi, "otherB", notherB,"all sig", nsig_total + # combinatorial BKG parameters set but not fixed. +# print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) + + + diff --git a/fit/roofit_helper.py b/fit/roofit_helper.py new file mode 100644 index 0000000..4161953 --- /dev/null +++ b/fit/roofit_helper.py @@ -0,0 +1,61 @@ +import ROOT as rt +from math import sqrt + + +def CMS_lumi(): + mark = rt.TLatex() + mark.SetNDC() + lumistamp = '2018 (13 TeV)' + fontScale = 1.0 + cmsTextSize = 0.042 * fontScale * 1.25 + extraOverCmsTextSize = 0.76 + extraTextSize = extraOverCmsTextSize*cmsTextSize + + mark.SetTextAlign(11) + mark.SetTextSize(cmsTextSize) + mark.SetTextFont(61) + mark.DrawLatex(rt.gPad.GetLeftMargin(), 1 - (rt.gPad.GetTopMargin() - 0.017), "CMS") + mark.SetTextSize(0.042 * fontScale) + mark.SetTextFont(52) + mark.DrawLatex(rt.gPad.GetLeftMargin() + 0.09, 1 - (rt.gPad.GetTopMargin() - 0.017), "Preliminary") + mark.SetTextSize(extraTextSize) + mark.SetTextFont(42) + mark.SetTextAlign(31) + mark.DrawLatex(1 - rt.gPad.GetRightMargin(), 1 - ( rt.gPad.GetTopMargin() - 0.017), lumistamp) + return mark + + +def canvas_create(xframe,xmin,xmax,nbin,xtitle,boundYto0=True): + c2 = rt.TCanvas('fig_binnedFit', 'fit', 800, 600) + c2.SetGrid() + rt.gPad.SetLeftMargin(0.12) + rt.gPad.SetRightMargin(0.05) + rt.gPad.SetBottomMargin(0.15) + #xframe.GetYaxis().SetTitle("Events / {0:.0f} MeV".format((xmax - xmin)/nbin*1000.)) + xframe.GetXaxis().SetTitle(xtitle) + xframe.SetStats(0) + if (boundYto0): xframe.SetMinimum(0) + xframe.GetYaxis().SetLabelSize(0.045) + xframe.GetYaxis().SetLabelOffset(0.007) + xframe.GetYaxis().SetTitleSize(0.06) + xframe.GetYaxis().SetTitleOffset(0.90) + xframe.GetXaxis().SetLabelSize(0.045) + xframe.GetXaxis().SetLabelOffset(0.007) + xframe.GetXaxis().SetTitleSize(0.06) + xframe.GetXaxis().SetTitleOffset(0.95) + xframe.SetTitle("") + xframe.Draw() + return c2 + +def pt_create(mva,nsig,nsigError,nbkg): + pt = rt.TPaveText(0.72,0.37,0.92,0.63,"brNDC") + pt.SetFillColor(0) + pt.SetBorderSize(1) + pt.SetTextFont(42); + pt.SetTextSize(0.04); + pt.SetTextAlign(12) + pt.AddText("MVA cut: {0}".format(mva)) + pt.AddText("S: {0:.1f}#pm{1:.1f}".format(nsig,nsigError)) + pt.AddText("B: {0:.1f}".format(nbkg)) + pt.AddText("S/#sqrt{{S+B}}: {0:.2f}".format(nsig/sqrt(nsig + nbkg))) + return pt diff --git a/fit/roofit_models.py b/fit/roofit_models.py new file mode 100644 index 0000000..e24ac2e --- /dev/null +++ b/fit/roofit_models.py @@ -0,0 +1,23 @@ +root_function_DoubleSidedCB=""" + +double DoubleSidedCB2(double x, double mu, double width, double a1, double p1, double a2, double p2) +{ + double u = (x-mu)/width; + double A1 = TMath::Power(p1/TMath::Abs(a1),p1)*TMath::Exp(-a1*a1/2); + double A2 = TMath::Power(p2/TMath::Abs(a2),p2)*TMath::Exp(-a2*a2/2); + double B1 = p1/TMath::Abs(a1) - TMath::Abs(a1); + double B2 = p2/TMath::Abs(a2) - TMath::Abs(a2); + + double result(1); + if (u<-a1) result *= A1*TMath::Power(B1-u,-p1); + else if (u {})'.format(jpsi_mva_wp)])).shape[0]) / float(jpsi_mc_branches[i].query(selection['jpsi']).shape[0]) for i in nparts]) + + if eleType == 'pf': + mvaCut = np.linspace(7.0, 9.0, 20) + else: + mvaCut = np.linspace(8.0, 10.0, 20) + + for cut in mvaCut: + eff_lowq2_bdt = np.mean([float(nonresonant_mc_branches[i].query(' and '.join([selection['lowq2'], '(xgb > @cut)', selection['Dmass']])).shape[0]) / float(nonresonant_mc_branches[i].query(selection['lowq2']).shape[0]) for i in nparts]) + + expected_signal = rk_electron * n_data_jpsi * eff['lowq2_presel'] * eff['lowq2_q2'] * eff_lowq2_bdt / (eff['jpsi_presel'] * eff['jpsi_q2'] * eff['jpsi_bdt']) + + if num_mctoys is not None: + com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --number_of_mctoys={6} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) + else: + com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) + + os.system(com) + print('cut: {} \n \t expected signal: {} \n \t lowq2 bdt eff: {}'.format(cut, expected_signal, eff_lowq2_bdt)) + + for key, value in eff.items(): + print('{}: {}'.format(key, value)) + + + + diff --git a/fit/run_fit_KJpsi_fixedPartial.py b/fit/run_fit_KJpsi_fixedPartial.py new file mode 100644 index 0000000..d345d37 --- /dev/null +++ b/fit/run_fit_KJpsi_fixedPartial.py @@ -0,0 +1,85 @@ +import uproot +import pandas as pd +import numpy as np +from collections import OrderedDict, defaultdict +from scipy import interp +from rootpy.io import root_open +from rootpy.plotting import Hist +from root_numpy import fill_hist, array2root, array2tree +from root_pandas import to_root +import itertools +import PyPDF2 +#import makePlot_fitPeak_unbinned as fit_unbinned +import os, sys, copy +import xgboost as xgb + +LOWQ2_LOW = 1.05 +LOWQ2_UP = 2.45 +JPSI_LOW = 2.8 +JPSI_UP = 3.25 +PSI2S_LOW = 3.45 +PSI2S_UP = 3.8 +HIGHQ2_LOW = 4.0 +HIGHQ2_UP = 4.87 + +def get_df(root_file_name, tree='mytreefit', branches=['*']): + print('Opening file {}...'.format(root_file_name)) + f = uproot.open(root_file_name) + if len(f.allkeys()) == 0: + return pd.DataFrame() + print('Not an null file') + #df = uproot.open(root_file_name)["tree"].pandas.df() + #df = pd.DataFrame(uproot.open(root_file_name)["tree"].arrays(namedecode="utf-8")) + df = pd.DataFrame(f[tree].arrays(branches=branches)) + print('Finished opening file {}...'.format(root_file_name)) + return df + +if __name__ == "__main__": + eleType = 'pf' + log = 'log_jpsi_bparkPU_v7.2_{}_kstarplus.csv'.format(eleType) + info = defaultdict(dict) + + br_b2jpsi = 1.02e-3 + br_b2kstarjpsi = 1.27e-3 * 2./3. + + nparts = range(8) + + info['pf']['inputfile'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_data_mvaCut0.root' + info['pf']['jpsi_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MCres.root'.format('marker') + info['pf']['partial_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MC_kstarjpsi_combined.root'.format('marker') + info['pf']['isgn'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCres.root' + info['pf']['ibkg'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_samesign_mvaCut0.root' + info['pf']['iKstarJpsi_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarjpsi_combined.root' + info['pf']['iKstarPlusJpsi_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarplusjpsi_kee.root' + info['pf']['n_mc_jpsi'] = 563421.0 + info['pf']['n_mc_partial'] = 1023330.0 + + selection = {} + + selection['jpsi'] = '(Mll > @JPSI_LOW) and (Mll < @JPSI_UP)' + selection['psi2s'] = '(Mll > @PSI2S_LOW) and (Mll < @PSI2S_UP)' + + mc_branches = ['Bmass', 'Mll', 'xgb'] + + jpsi_mc_branches = [get_df(info[eleType]['jpsi_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] + partial_mc_branches = [get_df(info[eleType]['partial_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] + + + if eleType == 'pf': + mvaCut = np.linspace(3.0, 5.0, 11) + else: + mvaCut = np.linspace(8.0, 10.0, 20) + + for cut in mvaCut: + eff_sig_bdt = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_jpsi'] for i in nparts]) + eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['jpsi'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) + + frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarjpsi / br_b2jpsi) + + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_kstarPlus.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + + os.system(com) + + + diff --git a/fit/run_fit_KPsi2S_fixedPartial.py b/fit/run_fit_KPsi2S_fixedPartial.py new file mode 100644 index 0000000..9a12a9d --- /dev/null +++ b/fit/run_fit_KPsi2S_fixedPartial.py @@ -0,0 +1,85 @@ +import uproot +import pandas as pd +import numpy as np +from collections import OrderedDict, defaultdict +from scipy import interp +from rootpy.io import root_open +from rootpy.plotting import Hist +from root_numpy import fill_hist, array2root, array2tree +from root_pandas import to_root +import itertools +import PyPDF2 +#import makePlot_fitPeak_unbinned as fit_unbinned +import os, sys, copy +import xgboost as xgb + +LOWQ2_LOW = 1.05 +LOWQ2_UP = 2.45 +JPSI_LOW = 2.8 +JPSI_UP = 3.25 +PSI2S_LOW = 3.45 +PSI2S_UP = 3.8 +HIGHQ2_LOW = 4.0 +HIGHQ2_UP = 4.87 + +def get_df(root_file_name, tree='mytreefit', branches=['*']): + print('Opening file {}...'.format(root_file_name)) + f = uproot.open(root_file_name) + if len(f.allkeys()) == 0: + return pd.DataFrame() + print('Not an null file') + #df = uproot.open(root_file_name)["tree"].pandas.df() + #df = pd.DataFrame(uproot.open(root_file_name)["tree"].arrays(namedecode="utf-8")) + df = pd.DataFrame(f[tree].arrays(branches=branches)) + print('Finished opening file {}...'.format(root_file_name)) + return df + +if __name__ == "__main__": + eleType = 'pf' + log = 'log_psi2s_bparkPU_v7.2_{}_fixedPartial_narrowQ2Window.csv'.format(eleType) + info = defaultdict(dict) + + br_b2psi2s = 6.24e-4 + br_b2kstarpsi2s = 5.9e-4 * 2./3. + + nparts = range(8) + + info['pf']['inputfile'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_data_mvaCut0.root' + info['pf']['psi2s_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MCPsi2S.root'.format('marker') + info['pf']['partial_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MC_kstarpsi2s_combined.root'.format('marker') + info['pf']['isgn'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCPsi2S.root' + info['pf']['ibkg'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_samesign_mvaCut0.root' + info['pf']['iKstarPsi2S_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarpsi2s_combined.root' + info['pf']['iKstarJpsi_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarjpsi_combined.root' + info['pf']['iKJpsiee_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCres.root' + info['pf']['n_mc_psi2s'] = 483443.0 + info['pf']['n_mc_partial'] = 439520.0 + + selection = {} + + selection['jpsi'] = '(Mll > @JPSI_LOW) and (Mll < @JPSI_UP)' + selection['psi2s'] = '(Mll > @PSI2S_LOW) and (Mll < @PSI2S_UP)' + + mc_branches = ['Bmass', 'Mll', 'xgb'] + + psi2s_mc_branches = [get_df(info[eleType]['psi2s_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] + partial_mc_branches = [get_df(info[eleType]['partial_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] + + + if eleType == 'pf': + mvaCut = np.linspace(4.0, 6.0, 11) + else: + mvaCut = np.linspace(8.0, 10.0, 20) + + for cut in mvaCut: + eff_sig_bdt = np.mean([float(psi2s_mc_branches[i].query(' and '.join([selection['psi2s'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_psi2s'] for i in nparts]) + eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['psi2s'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) + + frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarpsi2s / br_b2psi2s) + + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + + os.system(com) + + + diff --git a/maximum_likelihood_rpsi2s.py b/measurement/maximum_likelihood_rpsi2s.py similarity index 100% rename from maximum_likelihood_rpsi2s.py rename to measurement/maximum_likelihood_rpsi2s.py diff --git a/maximum_likelihood_rpsi2s_combinedEleCh.py b/measurement/maximum_likelihood_rpsi2s_combinedEleCh.py similarity index 100% rename from maximum_likelihood_rpsi2s_combinedEleCh.py rename to measurement/maximum_likelihood_rpsi2s_combinedEleCh.py diff --git a/maximum_likelihood_singleChannel.py b/measurement/maximum_likelihood_singleChannel.py similarity index 100% rename from maximum_likelihood_singleChannel.py rename to measurement/maximum_likelihood_singleChannel.py diff --git a/plotting.py b/measurement/plotting.py similarity index 100% rename from plotting.py rename to measurement/plotting.py diff --git a/utils_likelihood.py b/measurement/utils_likelihood.py similarity index 100% rename from utils_likelihood.py rename to measurement/utils_likelihood.py From 7d87f8ae3db56848c14b9c026c682033ea9c3c88 Mon Sep 17 00:00:00 2001 From: ottolau Date: Sun, 23 Jan 2022 23:12:02 +0100 Subject: [PATCH 07/13] updated for CMG v7.3 --- fit/KEE_lowq2_roofit_plb_pull_modified_kde.py | 547 ++++++++++++++++++ ...si_roofit_plb_modified_kde_fixedPartial.py | 76 +-- ...2S_roofit_plb_modified_kde_fixedPartial.py | 114 ++-- fit/run_fit_KEE_lowq2_bparkPU.py | 47 +- fit/run_fit_KJpsi_fixedPartial.py | 32 +- fit/run_fit_KPsi2S_fixedPartial.py | 41 +- {archive => measurement}/helper.py | 0 7 files changed, 709 insertions(+), 148 deletions(-) create mode 100644 fit/KEE_lowq2_roofit_plb_pull_modified_kde.py rename {archive => measurement}/helper.py (100%) diff --git a/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py b/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py new file mode 100644 index 0000000..0b365e5 --- /dev/null +++ b/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py @@ -0,0 +1,547 @@ +import ROOT +from ROOT import RooFit +import math +from roofit_helper import * +#ROOT.gROOT.ProcessLine(open('roofit_models.h').read()) +#from ROOT import DoubleSidedCB +#from ROOT import ROOT_DoubleSidedCB +#from XGBweight import XGBweight +#rt.gInterpreter.Declare(XGBweight) +#from PUweight import PUweight +#rt.gInterpreter.Declare(PUweight) +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +#ROOT.gStyle.SetOptFit(0000); +ROOT.gROOT.SetBatch(True); +ROOT.gROOT.SetStyle("Plain"); +msgservice = ROOT.RooMsgService.instance() +msgservice.setGlobalKillBelow(RooFit.FATAL) +import csv +import os.path +import atexit + +import numpy as np +import matplotlib as mpl +mpl.use('agg') +import matplotlib.font_manager +from matplotlib import pyplot as plt +from matplotlib import rc +#.Allow for using TeX mode in matplotlib Figures +rc('font',**{'family':'sans-serif','sans-serif':['Computer Modern Roman']}) +rc('text', usetex=True) +plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern}"] + +ratio=5.0/7.0 +fig_width_pt = 3*246.0 # Get this from LaTeX using \showthe\columnwidth +inches_per_pt = 1.0/72.27 # Convert pt to inch +golden_mean = ratio if ratio != 0.0 else (np.sqrt(5)-1.0)/2.0 # Aesthetic ratio +fig_width = fig_width_pt*inches_per_pt # width in inches +fig_height = fig_width*golden_mean # height in inches +fig_size = [fig_width,fig_height] + +params = {'text.usetex' : True, + 'axes.labelsize': 24, + 'font.size': 24, + 'legend.fontsize': 20, + 'xtick.labelsize': 24, + 'ytick.labelsize': 24, + 'font.family' : 'lmodern', + 'text.latex.unicode': True, + 'axes.grid' : True, + 'text.usetex': True, + 'figure.figsize': fig_size} +plt.rcParams.update(params) + +nbin_data = 20 + +def residuals(xframe, var,name): + hresid = xframe.residHist() + xframe2 = var.frame() + xframe2.addPlotable(hresid,"P") + c2=canvas_create(xframe2,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c2.SaveAs(name+'_residual.pdf') + hpull = xframe.pullHist() + xframe3 = var.frame() + xframe3.addPlotable(hpull,"P") + c3=canvas_create(xframe3,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) + c3.SaveAs(name+'_pull.pdf') + + + +def define_workspace_bmass_data(wspace_name,mB_branch,tree): + wspace = ROOT.RooWorkspace(wspace_name) + fitvars = ROOT.RooArgSet() + bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") + fitvars.add(bMass) + dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) + theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) + theBMass = dataset.addColumn(theBMassfunc) ; + theBMass.setRange(4.7,5.7); + fitvars.add(theBMass) + getattr(wspace, "import")(dataset, RooFit.Rename('data')) + # When a RooWorkspace is set as an attribute of a class, it can trigger a memory error + # This is solved in the latest ROOT version > 6.14.08 + atexit.register(wspace.Delete) + return wspace,dataset,bMass,theBMass + + +def get_visible_yield_error(obs, results, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + intgral_pdf_err = intgral_pdf.getPropagatedError(results, obs) + visible = amplitude.getVal() * intgral_pdf.getVal() + if intgral_pdf.getVal()==0: + visible_err =0 + else: + visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 + return visible, visible_err + +def get_visible_yield(obs, pdf, amplitude): + intgral_pdf = pdf.createIntegral(obs,obs,"window") + visible = amplitude * intgral_pdf.getVal() + return visible + + +##################### signal fit == Double sided CB ###################### +def signal_fit(tree, outputfile, branches): + print "Signal" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) + # signal + wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') + wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.0, 0.0, 10.0]') + wspace.factory('n1[1.0, 1.0, 20.0]') + wspace.factory('alpha2[1.0, 0.0, 10.0]') + wspace.factory('n2[1.0, 1.0, 20.0]') + wspace.factory('GenericPdf::sig( "DoubleSidedCB2(x,mean,width,alpha1,n1,alpha2,n2)",{x,mean,width,alpha1,n1,alpha2,n2})') + + sgnframe=theBMass.frame() + wspace.factory('nsig[1000,0,100000000]') + wspace.factory('RooExtendPdf::esig(sig,nsig)') + sig=wspace.pdf('sig') + nsig=wspace.var('nsig') + esig=wspace.pdf('esig') + results = esig.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + + results.Print() + dataset.plotOn(sgnframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + esig.plotOn(sgnframe, RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected), RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + n_param = results.floatParsFinal().getSize() + print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + c1.SaveAs('sgn_eek_'+outputfile+'.pdf') + residuals(sgnframe,theBMass,'sgn_eek_'+outputfile) + params=esig.getParameters(ROOT.RooArgSet(bMass)) + return {"mean":params.getRealValue('mean'),"width": params.getRealValue('width'),"alpha1":params.getRealValue('alpha1'),"n1":params.getRealValue('n1'),"alpha2":params.getRealValue('alpha2'),"n2":params.getRealValue('n2')} + + +############################### B->KJpsi fit ############################## +def kjpsi_fit(tree, outputfile, branches): + print "kjpsi" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kjpsi_bkg",branches[0],tree) + wspace.factory('mean_kjpsi[4.7, 1.0, 5.0]') + wspace.factory('width_kjpsi[0.1, 0.001, 5.0]') + wspace.factory("RooGaussian::kjpsi(x,mean_kjpsi,width_kjpsi)") + wspace.factory('nkjpsi[1000,0,10e+6]') + wspace.factory('RooExtendPdf::ekjpsi(kjpsi,nkjpsi)') + nkjpsi=wspace.var('nkjpsi') + ekjpsi=wspace.pdf('ekjpsi') + results = ekjpsi.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + results.Print() + kjpframe=theBMass.frame() + dataset.plotOn(kjpframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + ekjpsi.plotOn(kjpframe,RooFit.Name("ekjpsi"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + c1=canvas_create(kjpframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + c1.SaveAs('bkg_jpsik_'+outputfile+'.pdf') + residuals(kjpframe,theBMass,'bkg_jpsik_'+outputfile) + params=ekjpsi.getParameters(ROOT.RooArgSet(bMass)) + n_param = results.floatParsFinal().getSize() + print "chi2",kjpframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + + return {"mean_kjpsi":params.getRealValue('mean_kjpsi'),"width_kjpsi":params.getRealValue('width_kjpsi')} + + +############################ BKG fit ################################# +def bkg_fit(tree, outputfile, branches): + print "combinatorial" + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_comb_bkg",branches[0],tree) + wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') + wspace.factory('Exponential::bkg(x,exp_alpha)') + wspace.factory('nbkg[1000,0,10e+6]') + wspace.factory('RooExtendPdf::ebkg(bkg,nbkg)') + nbkg=wspace.var('nbkg') + ebkg=wspace.pdf('ebkg') + + results = ebkg.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) ) + results.Print() + bkgframe=theBMass.frame() + dataset.plotOn(bkgframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + ebkg.plotOn(bkgframe,RooFit.Name("ebkg"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + params=ebkg.getParameters(ROOT.RooArgSet(bMass)) + c1=canvas_create(bkgframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + CMS_lumi() + c1.SaveAs('bkg_comb_'+outputfile+'.pdf') + n_param = results.floatParsFinal().getSize() + print "chi2",bkgframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + residuals(bkgframe,theBMass,'bkg_comb_'+outputfile) + + return {"exp_alpha":params.getRealValue('exp_alpha')} + + +############################ KDE fit ####################### +def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): + print "KDE - {}".format(pdfname) + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree) + kde_frame=theBMass.frame() + wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(pdfname)) + kde = wspace.pdf(pdfname) + + dataset.plotOn(kde_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) + kde.plotOn(kde_frame, RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) + + #wf = ROOT.TFile('ws_bkg_kde_'+outputfile+'_{}.root'.format(pdfname), "RECREATE") + #wspace.Write() + #wf.Close() + + c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + CMS_lumi() + if SavePlot: + c1.SaveAs('bkg_kde_'+outputfile+'_{}.pdf'.format(pdfname)) + residuals(kde_frame,theBMass,'bkg_kde_'+outputfile+'_'+pdfname) + return kde + + +############################# total fit ############################## +def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_pdf=None, kstaree_pdf=None, bkg_parameters=None, set_sgn_yield=None,Blind_range={"min":4.7,"max":5.7} , number_of_mctoys=None,mva=None,log='log.csv'): + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) + print "Total" + #amplitudes + wspace.factory('nsig[100.0, 0.0, 1000000.0]' ) + wspace.factory('nbkg[10000.0, 0.0, 100000000.0]') + wspace.factory('nkjpsi[10000.0, 0.0, 1000000.0]') + wspace.factory('nkstaree[10000.0, 0.0, 1000000.0]') + + # signal + wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') + wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[1.0, 0.0, 10.0]') + wspace.factory('n1[1.0, 1.0, 20.0]') + wspace.factory('alpha2[1.0, 0.0, 10.0]') + wspace.factory('n2[1.0, 1.0, 20.0]') + wspace.factory('GenericPdf::sig( "DoubleSidedCB2(x,mean,width,alpha1,n1,alpha2,n2)",{x,mean,width,alpha1,n1,alpha2,n2})') + + # Exponential - bkg + wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') + alpha = wspace.var('alpha') + wspace.factory('Exponential::bkg(x,exp_alpha)') + + # Gaussian - bkg + #wspace.factory('mean_kjpsi[4.7, 1.0, 5.0]') + #wspace.factory('width_kjpsi[0.1, 0.001, 5.0]') + #wspace.factory("RooGaussian::kjpsi(x,mean_kjpsi,width_kjpsi)") + + # KJpsi - bkg + getattr(wspace, "import")(kjpsi_pdf, RooFit.Rename('kjpsi')) + + # K* ee - bkg + getattr(wspace, "import")(kstaree_pdf, RooFit.Rename('kstaree')) + + #sum + #wspace.factory('SUM::model(nsig*sig,nbkg*bkg,nkjpsi*kjpsi,nkstaree*kstaree)') + wspace.factory('SUM::model(nsig*sig,nbkg*bkg,nkjpsi*kjpsi)') + + model = wspace.pdf('model'); bkg = wspace.pdf('bkg') + sig = wspace.pdf('sig'); kjpsi = wspace.pdf('kjpsi'); + nsig = wspace.var('nsig'); nbkg = wspace.var('nbkg') + nkjpsi = wspace.var('nkjpsi') + #mean = wspace.var('mean') + nkstaree = wspace.var('nkstaree') + kstaree = wspace.pdf('kstaree') + + if set_sgn_yield!=None: + nsig.setVal(set_sgn_yield) + nsig.setConstant(True) + for par in sgn_parameters.keys(): + (wspace.var(par)).setVal(sgn_parameters[par]) + (wspace.var(par)).setConstant(True) + #for par in kjpsi_parameters.keys(): + # (wspace.var(par)).setVal(kjpsi_parameters[par]) + # (wspace.var(par)).setConstant(True) + for par in bkg_parameters.keys(): + (wspace.var(par)).setVal(bkg_parameters[par]) + + results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) + print results.Print() + xframe=theBMass.frame(RooFit.Title("")) + + + if Blind_range["min"]>4.7 and Blind_range["max"]<5.7: + norm = dataset.reduce('(({0} > {1}) & ({0} < {2})) | (({0}> {3}) & ({0} < {4}))'.format(branches[0],"4.7", str(Blind_range["min"]),str(Blind_range["max"]), "5.7")).sumEntries() / dataset.reduce('({0} > {1}) & ({0} < {2})'.format(branches[0],"4.7", "5.7")).sumEntries() +# blind= ROOT.RooRealVar("blind","blind",Blind_range["min"],Blind_range["max"]) + # blind.setRange("left",4.7,Blind_range["min"]) + # blind.setRange("right",Blind_range["max"],5.7) + theBMass.setRange("left",4.7,Blind_range["min"]) + theBMass.setRange("right",Blind_range["max"],5.7) + norm=1.0 + dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas"),RooFit.CutRange("left,right")) + else: + norm=1. + dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + + + #norm=1. + #dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) + + model.plotOn(xframe,RooFit.Name("bkg"),RooFit.Components("bkg"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) + model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + #model.plotOn(xframe,RooFit.Name("kstaree"),RooFit.Components("kstaree"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("sig"),RooFit.Components("sig"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) + model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) + + wspace.defineSet('obs', 'x') + obs = wspace.set('obs') + theBMass.setRange("window",Blind_range["min"],Blind_range["max"]) + + #theBMass.setRange("window",5.0,5.4) + obs2= ROOT.RooRealVar("obs2","obs2",Blind_range["min"],Blind_range["max"]) + nset = ROOT.RooArgSet(obs2) + print sig.getVal(), sig.getVal(nset) + print Blind_range + print nbkg.getVal(),nkjpsi.getVal(),nsig.getVal() + nbkg_visible, nbkg_visible_err = get_visible_yield_error(obs, results, bkg, nbkg) + nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, sig, nsig) + nkjpsi_visible, nkjpsi_visible_err = get_visible_yield_error(obs, results, kjpsi, nkjpsi) + print "hereee",nbkg_visible,nsig_visible,nkjpsi_visible +# c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + n_param = results.floatParsFinal().getSize() + print "chi2",xframe.chiSquare(n_param),"ndof",n_param + print "edm",results.edm(),"log",results.minNll() + c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + + legend = ROOT.TLegend(0.65,0.65,0.92,0.85) + legend.AddEntry(xframe.findObject("bkg"),"Combinatorial","l"); + legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); + #legend.AddEntry(xframe.findObject("kstaree"),"B -> eeK*","l"); + legend.AddEntry(xframe.findObject("sig"),"B -> eeK","l"); + legend.SetLineColor(ROOT.kWhite) + legend.SetTextFont(42); + legend.SetTextSize(0.04); + legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); + legend.Draw(); + pt=pt_create(mva,nsig_visible,nsig_visible_err,nkjpsi_visible+nbkg_visible) + pt.Draw() + CMS_lumi() + c1.cd() + c1.Update() + c1.SaveAs('total_fit_'+outputfile+'.pdf') + print nsig_visible, nsig_visible_err, nbkg_visible_err, nkjpsi_visible_err + residuals(xframe,theBMass,"poutana") + if number_of_mctoys!=None: + nsig.setConstant(False) + mctoys = ROOT.RooMCStudy(model, ROOT.RooArgSet(theBMass), + RooFit.Binned( ROOT.kTRUE), + #RooFit.Binned( ROOT.kFALSE), + ROOT.RooFit.Silence(), + RooFit.Extended(), + RooFit.FitOptions( + RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) + ) + ) + mctoys.generateAndFit(number_of_mctoys) + + frame1 = mctoys.plotParam(nsig, ROOT.RooFit.Bins(40)) + frame2 = mctoys.plotError(nsig, ROOT.RooFit.Bins(40)) + frame3 = mctoys.plotPull(nsig, ROOT.RooFit.Bins(40), + ROOT.RooFit.FitGauss(ROOT.kTRUE) + ) + # Plot distribution of minimized likelihood + frame4 = mctoys.plotNLL(ROOT.RooFit.Bins(40)) + cpr=canvas_create(frame1,4.7,5.7,1,'Distribution of the fitted value of N_{sgn}',False) + cpr.SaveAs("cpr_"+outputfile+".pdf") + cerr=canvas_create(frame2,0,1,1,'Distribution of the fitted error of N_{sgn}',False) + cerr.SaveAs("cerr_"+outputfile+".pdf") + cpull=canvas_create(frame3,4.7,5.7,1,' Pull of N_{sgn}',False) + cpull.SaveAs("cpull_"+outputfile+".pdf") + clog=canvas_create(frame4,4.7,5.7,1,'- log (L)') + clog.SaveAs("clog_"+outputfile+".pdf") + + postfit_data = mctoys.fitParDataSet() + postfit_nsig = np.array([postfit_data.get(i).getRealValue("nsig") for i in range(int(postfit_data.sumEntries()))]) + #postfit_nsig = np.array([get_visible_yield(obs, sig, postfit_data.get(i).getRealValue("nsig")) for i in range(int(postfit_data.sumEntries()))]) + #postfit_mu = np.array([s/nsig_visible for s in postfit_nsig]) + postfit_mu = np.array([s/set_sgn_yield for s in postfit_nsig]) + rms_mu = np.std(postfit_mu) + fig, ax = plt.subplots() + ax.hist(postfit_mu, bins=50, normed=True, histtype='step', label='MVA={}, RMS={}'.format(mva, rms_mu)) + ax.set_xlabel(r'$\mu$') + ax.set_ylabel('a.u.') + ax.legend(loc='best') + fig.savefig('cmu_{}.pdf'.format(outputfile), bbox_inches='tight') + + csv_header = ['cut', 'nsig', 'nbkg', 'njpsi', 'snr', 'rms_mu'] + df = {} + df['cut'] = mva + df['nsig'] = nsig_visible + df['nbkg'] = nbkg_visible + df['njpsi'] = nkjpsi_visible + df['snr'] = nsig_visible / np.sqrt(nsig_visible + nbkg_visible + nkjpsi_visible) + df['rms_mu'] = 0.0 if number_of_mctoys == None else rms_mu_ + csv_outputfile = log + file_exists = os.path.isfile(csv_outputfile) + with open (csv_outputfile, 'a+') as filedata: + writer = csv.DictWriter(filedata, delimiter=',', fieldnames=csv_header) + if not file_exists: + writer.writeheader() + writer.writerow(df) + + + return (nsig_visible,nbkg_visible,nkjpsi_visible) + + +def kee_yield_from_kjpsi(kjpsi_yield,tree_kee,tree_kjpsi,total_kee,total_kjpsi,xgb): + print "\nWARNING!!!!!",total_kee,"will be used as denominsator for kee eff. and ",total_kjpsi,"for kjpsi. Is this correct ?; code hypothesizes that cross validation is in 8 parts (hardcoded, change if different)\n" + hkee = ROOT.TH1F("hkee","",50,4.7,5.7) + hkjpsi = ROOT.TH1F("hkjpsi","",50,4.7,5.7) + #tree_kee.Draw("Bmass>>hkee","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>1.05 && Mll<2.45 && xgb>"+xgb+")") + #tree_kjpsi.Draw("Bmass>>hkjpsi","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>2.8 && Mll<3.25 && xgb>"+xgb+")") + tree_kee.Draw("Bmass>>hkee","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>1.05 && Mll<2.45 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) ))") + tree_kjpsi.Draw("Bmass>>hkjpsi","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>2.8 && Mll<3.25 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) ))") + + eff_kee=float(hkee.Integral()) / total_kee + eff_kjpsi=float(hkjpsi.Integral()) / total_kjpsi + result = kjpsi_yield / eff_kjpsi * 4.43*0.01/(1.026*5.93) *eff_kee + print "expect",result,"eff rare",eff_kee,"eff res",eff_kjpsi,"res data",kjpsi_yield + print "rare eff num",float(hkee.Integral()),"den",total_kee + return result + +################################### for scan ############################ +def FitForScan(inputfile, mva, isgnfile, ikspiBkg, ibkg, kjpsi_yield_for_kee,total_nsgn, total_nkjpsi, name ): + branches=["Bmass","Mll","xgb"] + cuts = "xgb>"+str(mva)+" && 1.05"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45"+" && "+branches[3]+">2.0" #+" && {} > 10 && {} > 10".format(branches[4], branches[5]) + cuts_samesign = branches[2]+">"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45" + print "cut: ", cuts + #cuts = " 1.05<"+branches[1]+" && "+branches[1]+"<2.45 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) )" + args.outputfile+="_wp"+str(args.mva) + + bkg_parameters={'exp_alpha':-1.98} + + print "start" + if args.fit_primtv: + if args.sel_primtv!= None: + args.sel_primtv = args.sel_primtv.split(",") + else: + args.sel_primtv = ["sgn","bkg_comb","bkg_kjpsi"] + print "primitive params" + if "sgn" in args.sel_primtv: + tree_sgn = ROOT.TChain('mytreefit') + tree_sgn.Add(args.isgnfile) + tree_sgn_cut=tree_sgn.CopyTree(cuts) + signal_parameters = signal_fit(tree_sgn_cut, args.outputfile+"_sgnMC", branches) + print "parameters SGN", signal_parameters['mean'], signal_parameters['width'],signal_parameters['alpha1'],signal_parameters['n1'],signal_parameters['alpha2'],signal_parameters['n2'] + + if "bkg_kjpsi" in args.sel_primtv: + tree_kjpsi = ROOT.TChain('mytreefit') + tree_kjpsi.Add(args.ikjpsiBkg) + tree_kjpsi_cut=tree_kjpsi.CopyTree(cuts) + kjpsi_pdf = kde_fit(tree_kjpsi_cut, args.outputfile+"_kjpsiMC", branches, 'kjpsi') + print "finished kde fit for K J/psi" + + if "bkg_kstaree" in args.sel_primtv: + tree_kstaree = ROOT.TChain('mytreefit') + tree_kstaree.Add(args.ikstareeBkg) + tree_kstaree_cut=tree_kstaree.CopyTree(cuts) + kstaree_pdf = kde_fit(tree_kstaree_cut, args.outputfile+"_kstareeMC", branches, 'kstaree') + print "finished kde fit for K* ee" + + if "bkg_comb" in args.sel_primtv: + #cuts = branches[2]+">8 && "+branches[1]+"<5." + #cuts = branches[2]+">"+str(args.mva)+" && "+branches[1]+"<5" + tree_bkg = ROOT.TChain('mytreefit') + tree_bkg.Add(args.ibkg) + tree_bkg_cut=tree_bkg.CopyTree(cuts_samesign) + bkg_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) + print "parameters Combinatorial BKG", bkg_parameters['exp_alpha'] + + else: + signal_parameters={'mean': 5.272, 'width': 0.057, 'alpha1': 0.652, 'n1': 3.3, 'alpha2': 1.32, 'n2': 2.01} + kjpsi_parameters={'mean_kjpsi':4.72,'width_kjpsi':1.06} + bkg_parameters={'exp_alpha':-1.98} + + if args.kjpsi_yield_for_kee!=None: + tree_sgn = ROOT.TChain('mytreefit') + tree_sgn.Add(args.isgnfile) + tree_kjpsi = ROOT.TChain('mytreefit') + tree_kjpsi.Add(args.ikspiBkg) + args.set_expected_sgn = kee_yield_from_kjpsi(args.kjpsi_yield_for_kee,tree_sgn,tree_kjpsi,args.total_nsgn,args.total_nkjpsi,str(args.mva)) + print "WARNING expected signal set and FIXED to ",args.set_expected_sgn,"in all q^2" + + #args.set_expected_sgn = None + if not args.skip_realfit: + #cuts = branches[2]+">"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45"+" && "+branches[3]+">2.0 &&"+branches[4]+">2.0" + tree = ROOT.TChain('mytreefit') + tree.Add(args.inputfile) + tree_cut=tree.CopyTree(cuts) + nsig, nbkg, nkjpsi =total_fit(tree_cut, args.outputfile, branches, signal_parameters, kjpsi_pdf, kstaree_pdf, bkg_parameters, args.set_expected_sgn, {"min":5.0,"max":5.4}, args.number_of_mctoys, str(args.mva), args.log) + # combinatorial BKG parameters set but not fixed. + print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) diff --git a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py index 5733315..74317f2 100644 --- a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py @@ -69,15 +69,15 @@ def signal_fit(tree, outputfile, branches, SavePlot=True): print "Signal" wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) # signal - wspace.factory('mean[5.278e+00, 5.25e+00, 5.3e+00]') - wspace.factory('width[5.8851e-02, 1.0e-6, 5.0e-1]') - wspace.factory('alpha1[1.85, 0.0, 10.0]') - wspace.factory('n1[19.9999, 0.0, 100.0]') + wspace.factory('mean[5.2873e+00, 5.25e+00, 5.3e+00]') + wspace.factory('width[5.0642e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[8.1430e-01, 0.0, 10.0]') + wspace.factory('n1[9.8615e+01, 0.0, 100.0]') wspace.factory('CBShape::sigcb(x,mean,width,alpha1,n1)') - wspace.factory('mean2[5.19e+00, 5.0e+00, 5.30e+00]') - wspace.factory('width2[1.3367e-01, 1.0e-6, 5.0e-1]') + wspace.factory('mean2[5.2274e+00, 5.0e+00, 5.30e+00]') + wspace.factory('width2[9.3738e-02, 1.0e-6, 5.0e-1]') wspace.factory('RooGaussian::sigg(x,mean2,width2)') - wspace.factory('frac[0.5, 0, 1.0]') + wspace.factory('frac[4.4875e-01, 0, 1.0]') wspace.factory('SUM::sig(sigcb,frac*sigg)') sgnframe=theBMass.frame() @@ -214,7 +214,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('SUM::signal(cb_signal,frac*g_signal)') # other B - bkg - wspace.factory('exp_alpha_otherb[-1.0, -100.0, -1.e-4]') + wspace.factory('exp_alpha_otherb[-15.0, -100.0, -5.0]') wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') # K*Jpsi - bkg @@ -244,11 +244,11 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame #(wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) - (wspace.var(par)).setConstant(True) + #(wspace.var(par)).setConstant(True) if partial_ratio is not None: wspace.var('frac_partial').setVal(partial_ratio) - wspace.var('frac_partial').setConstant(True) + #wspace.var('frac_partial').setConstant(True) results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) print results.Print() @@ -294,7 +294,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); - legend.AddEntry(xframe.findObject("sig"),"B -> J/#psiK","l"); + legend.AddEntry(xframe.findObject("signal"),"B -> J/#psiK","l"); legend.SetLineColor(ROOT.kWhite) legend.SetTextFont(42); legend.SetTextSize(0.04); @@ -309,29 +309,32 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err,"otherB", notherB_visible, "+/-",notherB_visible_err residuals(xframe,theBMass,"poutana") - # get likelihood - - nll = model.createNLL(dataset) - ROOT.RooMinuit(nll).migrad() - nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(7500.0,10000.0),RooFit.Title("LL and profileLL in nsignal")) ; - #nll.plotOn(nll_frame,RooFit.ShiftToZero()) - pll = nll.createProfile(ROOT.RooArgSet(nsignal)) - pll.plotOn(nll_frame,RooFit.LineColor(2),RooFit.ShiftToZero()) - nll_frame.SetMinimum(0); - nll_frame.SetMaximum(10) - c2 = canvas_create(nll_frame,0.0,0.0,0.0,'nsig') - CMS_lumi() - c2.cd() - c2.Update() - c2.SaveAs('nll_'+outputfile+'.pdf') - - wspace_output = ROOT.RooWorkspace('wspace') - getattr(wspace_output, "import")(model) - getattr(wspace_output, "import")(dataset) - params = model.getParameters(dataset) - wspace_output.saveSnapshot("nominal_values",params) - wspace_output.Print("V") - wspace_output.writeToFile('wspace_'+outputfile+'.root') + saveWS = False + + if saveWS: + # get likelihood + + nll = model.createNLL(dataset) + ROOT.RooMinuit(nll).migrad() + nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(7500.0,10000.0),RooFit.Title("LL and profileLL in nsignal")) ; + #nll.plotOn(nll_frame,RooFit.ShiftToZero()) + pll = nll.createProfile(ROOT.RooArgSet(nsignal)) + pll.plotOn(nll_frame,RooFit.LineColor(2),RooFit.ShiftToZero()) + nll_frame.SetMinimum(0); + nll_frame.SetMaximum(10) + c2 = canvas_create(nll_frame,0.0,0.0,0.0,'nsig') + CMS_lumi() + c2.cd() + c2.Update() + c2.SaveAs('nll_'+outputfile+'.pdf') + + wspace_output = ROOT.RooWorkspace('wspace') + getattr(wspace_output, "import")(model) + getattr(wspace_output, "import")(dataset) + params = model.getParameters(dataset) + wspace_output.saveSnapshot("nominal_values",params) + wspace_output.Print("V") + wspace_output.writeToFile('wspace_'+outputfile+'.root') csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarJpsi_total', 'nKstarJpsi_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarJpsi', 'notherB', 'snr', 'chi2'] @@ -381,7 +384,8 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame args = parser.parse_args() branches=["Bmass","Mll","xgb","KLmassD0"] - cuts = branches[2]+">"+str(args.mva)+" && 2.8<"+branches[1]+" && "+branches[1]+"<3.25" + cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + " && " + branches[3] + ">2.0" + cuts_samesign = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" #cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.25" #cuts = branches[2]+">"+str(args.mva)+" && 2.8<"+branches[1]+" && "+branches[1]+"<3.25" + " && " + branches[3] + ">2.0" @@ -415,7 +419,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if "bkg_comb" in args.sel_primtv: tree_bkg = ROOT.TChain('mytreefit') tree_bkg.Add(args.ibkg) - tree_bkg_cut=tree_bkg.CopyTree(cuts) + tree_bkg_cut=tree_bkg.CopyTree(cuts_samesign) comb_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) print "parameters Combinatorial BKG", comb_parameters['exp_alpha_comb'] diff --git a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py index 2b47136..303268f 100644 --- a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py @@ -68,15 +68,15 @@ def signal_fit(tree, outputfile, branches, SavePlot=True): print "Signal" wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) # signal - wspace.factory('mean[5.278e+00, 5.25e+00, 5.3e+00]') - wspace.factory('width[5.8851e-03, 1.0e-6, 5.0e-1]') - wspace.factory('alpha1[1.85, 0.0, 10.0]') - wspace.factory('n1[1.9999, 1.0, 100.0]') + wspace.factory('mean[5.2873e+00, 5.25e+00, 5.3e+00]') + wspace.factory('width[5.0642e-02, 1.0e-6, 5.0e-1]') + wspace.factory('alpha1[8.1430e-01, 0.0, 10.0]') + wspace.factory('n1[9.8615e+01, 0.0, 100.0]') wspace.factory('CBShape::sigcb(x,mean,width,alpha1,n1)') - wspace.factory('mean2[5.19e+00, 5.0e+00, 5.30e+00]') - wspace.factory('width2[1.3367e-01, 1.0e-6, 5.0e-1]') + wspace.factory('mean2[5.2274e+00, 5.0e+00, 5.30e+00]') + wspace.factory('width2[9.3738e-02, 1.0e-6, 5.0e-1]') wspace.factory('RooGaussian::sigg(x,mean2,width2)') - wspace.factory('frac[0.7, 0, 1.0]') + wspace.factory('frac[4.4875e-01, 0, 1.0]') wspace.factory('SUM::sig(sigcb,frac*sigg)') sgnframe=theBMass.frame() @@ -109,7 +109,8 @@ def signal_fit(tree, outputfile, branches, SavePlot=True): def otherB_fit(tree, outputfile, branches, SavePlot=True): print "otherB" wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_otherB_bkg",branches[0],tree) - wspace.factory('exp_alpha_otherb[-6.7, -100.0, -1.e-4]') + #wspace.factory('exp_alpha_otherb[-15.7, -100.0, -1.e-4]') + wspace.factory('exp_alpha_otherb[-15.7, -100.0, -5.0]') exp_alpha_otherb = wspace.var('exp_alpha_otherb') wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') wspace.factory('notherB[1000,0,10e+6]') @@ -193,11 +194,11 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) print "Total" #amplitudes - wspace.factory('nsignal[100.0, 0.0, 1000000.0]' ) - wspace.factory('ncomb[10000.0, 0.0, 1000000.0]') - wspace.factory('notherB[10000.0, 0.0, 1000000.0]') - wspace.factory('nKstarJpsi[10000.0, 0.0, 1000000.0]') - wspace.factory('nkjpsi[10000.0, 0.0, 1000000.0]') + wspace.factory('nsignal[600.0, 0.0, 1000000.0]' ) + wspace.factory('ncomb[1000.0, 0.0, 1000000.0]') + wspace.factory('notherB[500.0, 0.0, 1000000.0]') + wspace.factory('nKstarJpsi[100.0, 0.0, 1000000.0]') + wspace.factory('nkjpsi[100.0, 0.0, 1000000.0]') wspace.factory('frac_partial[1.0, 0.0, 10.0]') wspace.factory('prod::nKstarPsi2S(frac_partial,nsignal)') @@ -216,7 +217,8 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('SUM::signal(cb_signal,frac*g_signal)') # other B - bkg - wspace.factory('exp_alpha_otherb[-1.0, -100.0, -1.e-4]') + #wspace.factory('exp_alpha_otherb[-1.0, -100.0, -1.e-4]') + wspace.factory('exp_alpha_otherb[-15.0, -100.0, -5.0]') wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') # K*Psi2S - bkg @@ -233,8 +235,11 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') #sum - wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,nkjpsi*kjpsi,notherB*exp_otherb)') - + #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,nkjpsi*kjpsi,notherB*exp_otherb)') + #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nkjpsi*kjpsi,notherB*exp_otherb)') + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,notherB*exp_otherb)') + #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,notherB*exp_otherb)') + model = wspace.pdf('model'); signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') exp_otherb = wspace.pdf('exp_otherb') @@ -254,13 +259,13 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame #(wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) - (wspace.var(par)).setConstant(True) + #(wspace.var(par)).setConstant(True) if partial_ratio is not None: wspace.var('frac_partial').setVal(partial_ratio) - wspace.var('frac_partial').setConstant(True) + #wspace.var('frac_partial').setConstant(True) - #wspace.var('nKstarJpsi').setVal(0) + #wspace.var('nKstarJpsi').setVal(267) #wspace.var('nKstarJpsi').setConstant(True) results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) @@ -272,9 +277,9 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) - model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(43),RooFit.LineColor(43),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + #model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(43),RooFit.LineColor(43),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarpsi2s"),RooFit.Components("kstarpsi2s"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) - model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(15),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + #model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(15),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("signal"),RooFit.Components("signal"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') @@ -299,7 +304,10 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame nKstarJpsi_visible, nKstarJpsi_visible_err = get_visible_yield_error(obs, results, kstarjpsi , nKstarJpsi) nKJpsi_visible, nKJpsi_visible_err = get_visible_yield_error(obs, results,kjpsi , nKJpsi) notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) - nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+nKJpsi_visible+notherB_visible + #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+nKJpsi_visible+notherB_visible + #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKJpsi_visible+notherB_visible + nbkg_visible = ncomb_visible+nKstarPsi2S_visible+notherB_visible + #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+notherB_visible # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') n_param = results.floatParsFinal().getSize() @@ -310,16 +318,17 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend = ROOT.TLegend(0.65,0.65,0.92,0.85) legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); legend.AddEntry(xframe.findObject("kstarpsi2s"),"B -> #psi(2S)K*","l"); - legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); - legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); + #legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); + #legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); - legend.AddEntry(xframe.findObject("sig"),"B -> #psi(2S)K","l"); + legend.AddEntry(xframe.findObject("signal"),"B -> #psi(2S)K","l"); legend.SetLineColor(ROOT.kWhite) legend.SetTextFont(42); legend.SetTextSize(0.04); legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); legend.Draw(); - pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nKstarPsi2S_visible+nKstarJpsi_visible+ncomb_visible+nKJpsi_visible+notherB_visible) + #pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nKstarPsi2S_visible+nKstarJpsi_visible+ncomb_visible+nKJpsi_visible+notherB_visible) + pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nbkg_visible) pt.Draw() CMS_lumi() c1.cd() @@ -328,29 +337,31 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* Psi2S", nKstarPsi2S_visible, "+/-",nKstarPsi2S_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err, "K J/psi", nKJpsi_visible, "+/-", nKJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err residuals(xframe,theBMass,"poutana") - # get likelihood - - nll = model.createNLL(dataset) - ROOT.RooMinuit(nll).migrad() - nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(500,1000),RooFit.Title("LL and profileLL in nsignal")) ; - #nll.plotOn(nll_frame,RooFit.ShiftToZero()) - pll = nll.createProfile(ROOT.RooArgSet(nsignal)) - pll.plotOn(nll_frame,RooFit.LineColor(2),RooFit.ShiftToZero()) - nll_frame.SetMinimum(0); - nll_frame.SetMaximum(10) - c2 = canvas_create(nll_frame,0.0,0.0,0.0,'nsig') - CMS_lumi() - c2.cd() - c2.Update() - c2.SaveAs('nll_'+outputfile+'.pdf') - - wspace_output = ROOT.RooWorkspace('wspace') - getattr(wspace_output, "import")(model) - getattr(wspace_output, "import")(dataset) - params = model.getParameters(dataset) - wspace_output.saveSnapshot("nominal_values",params) - wspace_output.Print("V") - wspace_output.writeToFile('wspace_'+outputfile+'.root') + saveWS = False + if saveWS: + # get likelihood + + nll = model.createNLL(dataset) + ROOT.RooMinuit(nll).migrad() + nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(500,1000),RooFit.Title("LL and profileLL in nsignal")) ; + #nll.plotOn(nll_frame,RooFit.ShiftToZero()) + pll = nll.createProfile(ROOT.RooArgSet(nsignal)) + pll.plotOn(nll_frame,RooFit.LineColor(2),RooFit.ShiftToZero()) + nll_frame.SetMinimum(0); + nll_frame.SetMaximum(10) + c2 = canvas_create(nll_frame,0.0,0.0,0.0,'nsig') + CMS_lumi() + c2.cd() + c2.Update() + c2.SaveAs('nll_'+outputfile+'.pdf') + + wspace_output = ROOT.RooWorkspace('wspace') + getattr(wspace_output, "import")(model) + getattr(wspace_output, "import")(dataset) + params = model.getParameters(dataset) + wspace_output.saveSnapshot("nominal_values",params) + wspace_output.Print("V") + wspace_output.writeToFile('wspace_'+outputfile+'.root') csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarPsi2S_total', 'nKstarPsi2S_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarPsi2S', 'nKstarJpsi', 'nKJpsi', 'notherB', 'snr', 'chi2'] df = {} @@ -403,7 +414,8 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame args = parser.parse_args() branches=["Bmass","Mll","xgb","KLmassD0"] - cuts = branches[2]+">"+str(args.mva)+" && 3.45<"+branches[1]+" && "+branches[1]+"<3.8" + cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" + cuts_samesign = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" args.outputfile+="_wp"+str(args.mva) @@ -437,7 +449,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if "bkg_comb" in args.sel_primtv: tree_bkg = ROOT.TChain('mytreefit') tree_bkg.Add(args.ibkg) - tree_bkg_cut=tree_bkg.CopyTree(cuts) + tree_bkg_cut=tree_bkg.CopyTree(cuts_samesign) comb_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) print "parameters Combinatorial BKG", comb_parameters['exp_alpha_comb'] diff --git a/fit/run_fit_KEE_lowq2_bparkPU.py b/fit/run_fit_KEE_lowq2_bparkPU.py index 02c99ee..d7fc352 100644 --- a/fit/run_fit_KEE_lowq2_bparkPU.py +++ b/fit/run_fit_KEE_lowq2_bparkPU.py @@ -36,38 +36,23 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'pf' - log = 'log_kee_bparkPU_v7.2_{}.csv'.format(eleType) + log = 'log_kee_bparkPU_v7.3_{}.csv'.format(eleType) info = defaultdict(dict) nparts = range(8) - info['pf']['inputfile'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_data_mvaCut0.root' - info['pf']['nonresonant_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MC.root'.format('marker') - info['pf']['jpsi_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MCres.root'.format('marker') - info['pf']['isgn'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC.root' - info['pf']['ikjpsi'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCres.root' - info['pf']['jpsi_mva_wp'] = 4.4 - info['pf']['n_data_jpsi'] = 9424.52633491936 + info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' + info['pf']['nonresonant_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC.root'.format('marker') + info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCres.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC.root' + info['pf']['ikjpsi'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' + info['pf']['ikstaree'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstaree.root' + #info['pf']['ikstaree'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' + info['pf']['jpsi_mva_wp'] = 6.0 + info['pf']['n_data_jpsi'] = 7069.5 info['pf']['n_mc_jpsi'] = 563421.0 info['pf']['n_mc_lowq2'] = 617615.0 - #info['pf']['inputfile'] = 'data_PFe_v7.2_run3_elePt5/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_elePt5_v7.2_data.root' - #info['pf']['isgn'] = 'data_PFe_v7.2_run3_elePt5/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_elePt5_v7.2_0_MC.root' - #info['pf']['ikjpsi'] = 'data_PFe_v7.2_run3_elePt5/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_elePt5_v7.2_0_MCres.root' - - #info['pf']['inputfile'] = 'data_PFe_v7.2_run3_elePt10/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_elePt10_v7.2_data.root' - #info['pf']['isgn'] = 'data_PFe_v7.2_run3_elePt10/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_elePt10_v7.2_0_MC.root' - #info['pf']['ikjpsi'] = 'data_PFe_v7.2_run3_elePt10/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_elePt10_v7.2_0_MCres.root' - - info['mix']['inputfile'] = 'data_LowPtPF_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.2_data_mvaCut3.root' - info['mix']['nonresonant_mc'] = 'data_LowPtPF_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.2_{}_MC.root'.format('marker') - info['mix']['jpsi_mc'] = 'data_LowPtPF_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.2_{}_MCres.root'.format('marker') - info['mix']['isgn'] = 'data_LowPtPF_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.2_0_MC.root' - info['mix']['ikjpsi'] = 'data_LowPtPF_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.2_0_MCres.root' - info['mix']['jpsi_mva_wp'] = 5.2 - info['mix']['n_data_jpsi'] = 6710.791959557816 - info['mix']['n_mc_jpsi'] = 563421.0 - info['mix']['n_mc_lowq2'] = 617615.0 num_mctoys = None #5000 @@ -78,9 +63,9 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): selection = {} - selection['jpsi'] = '(Mll > @JPSI_LOW) and (Mll < @JPSI_UP)' - selection['psi2s'] = '(Mll > @PSI2S_LOW) and (Mll < @PSI2S_UP)' - selection['lowq2'] = '(Mll > @LOWQ2_LOW) and (Mll < @LOWQ2_UP)' + selection['jpsi'] = '(Mll > 2.9) and (Mll < 3.2)' + selection['psi2s'] = '(Mll > 3.55) and (Mll < 3.8)' + selection['lowq2'] = '(Mll > 1.05) and (Mll < 2.45)' selection['highq2'] = '(Mll > @PSI2S_LOW) and (Mll < @PSI2S_UP)' selection['Dmass'] = '(KLmassD0 > 2.0)' @@ -99,10 +84,11 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): eff['jpsi_q2'] = float(jpsi_mc_branches[0].query(selection['jpsi']).shape[0]) / float(jpsi_mc_branches[0].shape[0]) eff['lowq2_q2'] = float(nonresonant_mc_branches[0].query(selection['lowq2']).shape[0]) / float(nonresonant_mc_branches[0].shape[0]) # efficiency of bdt of jpsi - eff['jpsi_bdt'] = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], '(xgb > {})'.format(jpsi_mva_wp)])).shape[0]) / float(jpsi_mc_branches[i].query(selection['jpsi']).shape[0]) for i in nparts]) + eff['jpsi_bdt'] = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > {})'.format(jpsi_mva_wp)])).shape[0]) / float(jpsi_mc_branches[i].query(selection['jpsi']).shape[0]) for i in nparts]) if eleType == 'pf': mvaCut = np.linspace(7.0, 9.0, 20) + #mvaCut = np.array([8.0, ]) else: mvaCut = np.linspace(8.0, 10.0, 20) @@ -114,7 +100,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if num_mctoys is not None: com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --number_of_mctoys={6} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) else: - com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) + #com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) + com = 'python KEE_lowq2_roofit_plb_pull_modified_kde.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --ikstaree={4} --sel_primitive="sgn,bkg_kjpsi,bkg_kstaree" --fit_primitive --mvacut={5} --set_expected_sgn={6} --log={8}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], info[eleType]['ikstaree'], cut, expected_signal, num_mctoys, log) os.system(com) print('cut: {} \n \t expected signal: {} \n \t lowq2 bdt eff: {}'.format(cut, expected_signal, eff_lowq2_bdt)) diff --git a/fit/run_fit_KJpsi_fixedPartial.py b/fit/run_fit_KJpsi_fixedPartial.py index d345d37..c4ca7ec 100644 --- a/fit/run_fit_KJpsi_fixedPartial.py +++ b/fit/run_fit_KJpsi_fixedPartial.py @@ -36,7 +36,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'pf' - log = 'log_jpsi_bparkPU_v7.2_{}_kstarplus.csv'.format(eleType) + log = 'log_jpsi_bparkPU_v7.3_{}.csv'.format(eleType) info = defaultdict(dict) br_b2jpsi = 1.02e-3 @@ -44,35 +44,37 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): nparts = range(8) - info['pf']['inputfile'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_data_mvaCut0.root' - info['pf']['jpsi_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MCres.root'.format('marker') - info['pf']['partial_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MC_kstarjpsi_combined.root'.format('marker') - info['pf']['isgn'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCres.root' - info['pf']['ibkg'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_samesign_mvaCut0.root' - info['pf']['iKstarJpsi_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarjpsi_combined.root' - info['pf']['iKstarPlusJpsi_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarplusjpsi_kee.root' + info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' + info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCres.root'.format('marker') + info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' + info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' + info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' + #info['pf']['iKstarPlusJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarplusjpsi_kee.root' info['pf']['n_mc_jpsi'] = 563421.0 - info['pf']['n_mc_partial'] = 1023330.0 + info['pf']['n_mc_partial'] = 373882.0 selection = {} - selection['jpsi'] = '(Mll > @JPSI_LOW) and (Mll < @JPSI_UP)' - selection['psi2s'] = '(Mll > @PSI2S_LOW) and (Mll < @PSI2S_UP)' + selection['jpsi'] = '(Mll > 2.9) and (Mll < 3.2)' + selection['psi2s'] = '(Mll > 3.55) and (Mll < 3.8)' + selection['Dmass'] = '(KLmassD0 > 2.0)' - mc_branches = ['Bmass', 'Mll', 'xgb'] + mc_branches = ['Bmass', 'Mll', 'xgb', 'KLmassD0'] jpsi_mc_branches = [get_df(info[eleType]['jpsi_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] partial_mc_branches = [get_df(info[eleType]['partial_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] if eleType == 'pf': - mvaCut = np.linspace(3.0, 5.0, 11) + mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.array([5.0, ]) else: mvaCut = np.linspace(8.0, 10.0, 20) for cut in mvaCut: - eff_sig_bdt = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_jpsi'] for i in nparts]) - eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['jpsi'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) + eff_sig_bdt = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_jpsi'] for i in nparts]) + eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarjpsi / br_b2jpsi) diff --git a/fit/run_fit_KPsi2S_fixedPartial.py b/fit/run_fit_KPsi2S_fixedPartial.py index 9a12a9d..0b040ee 100644 --- a/fit/run_fit_KPsi2S_fixedPartial.py +++ b/fit/run_fit_KPsi2S_fixedPartial.py @@ -36,31 +36,37 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'pf' - log = 'log_psi2s_bparkPU_v7.2_{}_fixedPartial_narrowQ2Window.csv'.format(eleType) + log = 'log_psi2s_bparkPU_v7.3_{}.csv'.format(eleType) info = defaultdict(dict) br_b2psi2s = 6.24e-4 br_b2kstarpsi2s = 5.9e-4 * 2./3. + br_b2kstarjpsi = 1.27e-3 * 2./3. + br_psi2s2ee = 7.93e-3 + br_jpsi2ee = 0.05971 nparts = range(8) - info['pf']['inputfile'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_data_mvaCut0.root' - info['pf']['psi2s_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MCPsi2S.root'.format('marker') - info['pf']['partial_mc'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_{}_MC_kstarpsi2s_combined.root'.format('marker') - info['pf']['isgn'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCPsi2S.root' - info['pf']['ibkg'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_samesign_mvaCut0.root' - info['pf']['iKstarPsi2S_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarpsi2s_combined.root' - info['pf']['iKstarJpsi_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarjpsi_combined.root' - info['pf']['iKJpsiee_BKG'] = 'data_PFe_v7.2/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MCres.root' + info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' + info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCPsi2S.root'.format('marker') + #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarpsi2s.root'.format('marker') + info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCPsi2S.root' + info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' + info['pf']['iKstarPsi2S_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarpsi2s.root' + info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' + info['pf']['iKJpsiee_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' info['pf']['n_mc_psi2s'] = 483443.0 - info['pf']['n_mc_partial'] = 439520.0 + #info['pf']['n_mc_partial'] = 439520.0 + info['pf']['n_mc_partial'] = 373882.0 selection = {} - selection['jpsi'] = '(Mll > @JPSI_LOW) and (Mll < @JPSI_UP)' - selection['psi2s'] = '(Mll > @PSI2S_LOW) and (Mll < @PSI2S_UP)' + selection['jpsi'] = '(Mll > 2.9) and (Mll < 3.2)' + selection['psi2s'] = '(Mll > 3.55) and (Mll < 3.8)' + selection['Dmass'] = '(KLmassD0 > 2.0)' - mc_branches = ['Bmass', 'Mll', 'xgb'] + mc_branches = ['Bmass', 'Mll', 'xgb', 'KLmassD0'] psi2s_mc_branches = [get_df(info[eleType]['psi2s_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] partial_mc_branches = [get_df(info[eleType]['partial_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] @@ -68,14 +74,17 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if eleType == 'pf': mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.array([5.0,]) else: mvaCut = np.linspace(8.0, 10.0, 20) for cut in mvaCut: - eff_sig_bdt = np.mean([float(psi2s_mc_branches[i].query(' and '.join([selection['psi2s'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_psi2s'] for i in nparts]) - eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['psi2s'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) + eff_sig_bdt = np.mean([float(psi2s_mc_branches[i].query(' and '.join([selection['psi2s'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_psi2s'] for i in nparts]) + eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['psi2s'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) - frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarpsi2s / br_b2psi2s) + #frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarpsi2s / br_b2psi2s) + frac_ratio = (eff_partial_bdt / eff_sig_bdt) * ((br_b2kstarjpsi*br_jpsi2ee) / (br_b2psi2s*br_psi2s2ee)) + print(frac_ratio, eff_partial_bdt, eff_sig_bdt) com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) diff --git a/archive/helper.py b/measurement/helper.py similarity index 100% rename from archive/helper.py rename to measurement/helper.py From 7e8354854cc550ec2c29c403db93f61fccbfa647 Mon Sep 17 00:00:00 2001 From: ottolau Date: Wed, 26 Jan 2022 05:18:54 +0100 Subject: [PATCH 08/13] updated for PF-LP --- fit/run_fit_KEE_lowq2_bparkPU.py | 15 +++++++++++++-- fit/run_fit_KJpsi_fixedPartial.py | 21 +++++++++++++++++---- fit/run_fit_KPsi2S_fixedPartial.py | 29 ++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/fit/run_fit_KEE_lowq2_bparkPU.py b/fit/run_fit_KEE_lowq2_bparkPU.py index d7fc352..90b8bcf 100644 --- a/fit/run_fit_KEE_lowq2_bparkPU.py +++ b/fit/run_fit_KEE_lowq2_bparkPU.py @@ -35,7 +35,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): return df if __name__ == "__main__": - eleType = 'pf' + eleType = 'mix' log = 'log_kee_bparkPU_v7.3_{}.csv'.format(eleType) info = defaultdict(dict) @@ -53,6 +53,16 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['n_mc_jpsi'] = 563421.0 info['pf']['n_mc_lowq2'] = 617615.0 + info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' + info['mix']['nonresonant_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC.root'.format('marker') + info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCres.root'.format('marker') + info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC.root' + info['mix']['ikjpsi'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' + info['mix']['ikstaree'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstaree.root' + info['mix']['jpsi_mva_wp'] = 5.0 + info['mix']['n_data_jpsi'] = 5533.45 + info['mix']['n_mc_jpsi'] = 563421.0 + info['mix']['n_mc_lowq2'] = 617615.0 num_mctoys = None #5000 @@ -90,7 +100,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): mvaCut = np.linspace(7.0, 9.0, 20) #mvaCut = np.array([8.0, ]) else: - mvaCut = np.linspace(8.0, 10.0, 20) + mvaCut = np.linspace(8.5, 9.5, 20) + #mvaCut = np.array([9.0, ]) for cut in mvaCut: eff_lowq2_bdt = np.mean([float(nonresonant_mc_branches[i].query(' and '.join([selection['lowq2'], '(xgb > @cut)', selection['Dmass']])).shape[0]) / float(nonresonant_mc_branches[i].query(selection['lowq2']).shape[0]) for i in nparts]) diff --git a/fit/run_fit_KJpsi_fixedPartial.py b/fit/run_fit_KJpsi_fixedPartial.py index c4ca7ec..1c7611f 100644 --- a/fit/run_fit_KJpsi_fixedPartial.py +++ b/fit/run_fit_KJpsi_fixedPartial.py @@ -35,7 +35,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): return df if __name__ == "__main__": - eleType = 'pf' + eleType = 'mix' log = 'log_jpsi_bparkPU_v7.3_{}.csv'.format(eleType) info = defaultdict(dict) @@ -54,6 +54,14 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['n_mc_jpsi'] = 563421.0 info['pf']['n_mc_partial'] = 373882.0 + info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' + info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCres.root'.format('marker') + info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarjpsi.root'.format('marker') + info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' + info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' + info['mix']['n_mc_jpsi'] = 563421.0 + info['mix']['n_mc_partial'] = 373882.0 + selection = {} selection['jpsi'] = '(Mll > 2.9) and (Mll < 3.2)' @@ -70,7 +78,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): mvaCut = np.linspace(4.0, 6.0, 11) #mvaCut = np.array([5.0, ]) else: - mvaCut = np.linspace(8.0, 10.0, 20) + mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.array([8.0, ]) for cut in mvaCut: eff_sig_bdt = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_jpsi'] for i in nparts]) @@ -78,8 +87,12 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarjpsi / br_b2jpsi) - com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) - #com = 'python KJpsi_roofit_plb_modified_kde_kstarPlus.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + if eleType == 'pf': + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_kstarPlus.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + + else: + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --sel_primitive="sgn,bkg_kstarjpsi" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], frac_ratio, cut, log) os.system(com) diff --git a/fit/run_fit_KPsi2S_fixedPartial.py b/fit/run_fit_KPsi2S_fixedPartial.py index 0b040ee..70ba0ed 100644 --- a/fit/run_fit_KPsi2S_fixedPartial.py +++ b/fit/run_fit_KPsi2S_fixedPartial.py @@ -35,7 +35,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): return df if __name__ == "__main__": - eleType = 'pf' + eleType = 'mix' log = 'log_psi2s_bparkPU_v7.3_{}.csv'.format(eleType) info = defaultdict(dict) @@ -49,16 +49,26 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCPsi2S.root'.format('marker') - #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarpsi2s.root'.format('marker') - info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') + info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarpsi2s.root'.format('marker') + #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCPsi2S.root' info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' info['pf']['iKstarPsi2S_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarpsi2s.root' info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' info['pf']['iKJpsiee_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' info['pf']['n_mc_psi2s'] = 483443.0 - #info['pf']['n_mc_partial'] = 439520.0 - info['pf']['n_mc_partial'] = 373882.0 + info['pf']['n_mc_partial'] = 439520.0 + #info['pf']['n_mc_partial'] = 373882.0 + + info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' + info['mix']['psi2s_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCPsi2S.root'.format('marker') + info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarpsi2s.root'.format('marker') + info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCPsi2S.root' + info['mix']['iKstarPsi2S_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarpsi2s.root' + info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' + info['mix']['iKJpsiee_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' + info['mix']['n_mc_psi2s'] = 483443.0 + info['mix']['n_mc_partial'] = 439520.0 selection = {} @@ -76,7 +86,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): mvaCut = np.linspace(4.0, 6.0, 11) #mvaCut = np.array([5.0,]) else: - mvaCut = np.linspace(8.0, 10.0, 20) + mvaCut = np.linspace(6.0, 8.0, 11) + #mvaCut = np.array([7.0,]) for cut in mvaCut: eff_sig_bdt = np.mean([float(psi2s_mc_branches[i].query(' and '.join([selection['psi2s'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_psi2s'] for i in nparts]) @@ -86,7 +97,11 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): frac_ratio = (eff_partial_bdt / eff_sig_bdt) * ((br_b2kstarjpsi*br_jpsi2ee) / (br_b2psi2s*br_psi2s2ee)) print(frac_ratio, eff_partial_bdt, eff_sig_bdt) - com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + if eleType == 'pf': + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + else: + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], frac_ratio, cut, log) + os.system(com) From cfb59213dae51b2b88daf0ccf7e69f7e10ffc547 Mon Sep 17 00:00:00 2001 From: ottolau Date: Wed, 30 Mar 2022 03:32:04 +0200 Subject: [PATCH 09/13] updated to include kstar plus bkg in the fit --- fit/KEE_lowq2_roofit_plb_pull_modified.py | 499 ------------------ fit/KEE_lowq2_roofit_plb_pull_modified_kde.py | 15 +- ...si_roofit_plb_modified_kde_fixedPartial.py | 83 ++- ...2S_roofit_plb_modified_kde_fixedPartial.py | 82 ++- fit/run_fit_KEE_lowq2_bparkPU.py | 64 ++- fit/run_fit_KJpsi_fixedPartial.py | 101 +++- fit/run_fit_KPsi2S_fixedPartial.py | 112 ++-- 7 files changed, 344 insertions(+), 612 deletions(-) delete mode 100644 fit/KEE_lowq2_roofit_plb_pull_modified.py diff --git a/fit/KEE_lowq2_roofit_plb_pull_modified.py b/fit/KEE_lowq2_roofit_plb_pull_modified.py deleted file mode 100644 index 4252147..0000000 --- a/fit/KEE_lowq2_roofit_plb_pull_modified.py +++ /dev/null @@ -1,499 +0,0 @@ -import ROOT -from ROOT import RooFit -import math -from roofit_helper import * -#ROOT.gROOT.ProcessLine(open('roofit_models.h').read()) -#from ROOT import DoubleSidedCB -#from ROOT import ROOT_DoubleSidedCB -#from XGBweight import XGBweight -#rt.gInterpreter.Declare(XGBweight) -#from PUweight import PUweight -#rt.gInterpreter.Declare(PUweight) -from roofit_models import root_function_DoubleSidedCB -ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) -#ROOT.gStyle.SetOptFit(0000); -ROOT.gROOT.SetBatch(True); -ROOT.gROOT.SetStyle("Plain"); -msgservice = ROOT.RooMsgService.instance() -msgservice.setGlobalKillBelow(RooFit.FATAL) -import csv -import os.path -import numpy as np -import matplotlib as mpl -mpl.use('agg') -import matplotlib.font_manager -from matplotlib import pyplot as plt -from matplotlib import rc -#.Allow for using TeX mode in matplotlib Figures -rc('font',**{'family':'sans-serif','sans-serif':['Computer Modern Roman']}) -rc('text', usetex=True) -plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern}"] - -ratio=5.0/7.0 -fig_width_pt = 3*246.0 # Get this from LaTeX using \showthe\columnwidth -inches_per_pt = 1.0/72.27 # Convert pt to inch -golden_mean = ratio if ratio != 0.0 else (np.sqrt(5)-1.0)/2.0 # Aesthetic ratio -fig_width = fig_width_pt*inches_per_pt # width in inches -fig_height = fig_width*golden_mean # height in inches -fig_size = [fig_width,fig_height] - -params = {'text.usetex' : True, - 'axes.labelsize': 24, - 'font.size': 24, - 'legend.fontsize': 20, - 'xtick.labelsize': 24, - 'ytick.labelsize': 24, - 'font.family' : 'lmodern', - 'text.latex.unicode': True, - 'axes.grid' : True, - 'text.usetex': True, - 'figure.figsize': fig_size} -plt.rcParams.update(params) - -nbin_data = 20 - -def residuals(xframe, var,name): - hresid = xframe.residHist() - xframe2 = var.frame() - xframe2.addPlotable(hresid,"P") - c2=canvas_create(xframe2,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) - c2.SaveAs(name+'_residual.pdf') - hpull = xframe.pullHist() - xframe3 = var.frame() - xframe3.addPlotable(hpull,"P") - c3=canvas_create(xframe3,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) - c3.SaveAs(name+'_pull.pdf') - - - -def define_workspace_bmass_data(wspace_name,mB_branch,tree): - wspace = ROOT.RooWorkspace(wspace_name) - fitvars = ROOT.RooArgSet() - bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") - fitvars.add(bMass) - dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) - theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) - theBMass = dataset.addColumn(theBMassfunc) ; - theBMass.setRange(4.7,5.7); - fitvars.add(theBMass) - getattr(wspace, "import")(dataset, RooFit.Rename('data')) - return wspace,dataset,bMass,theBMass - - -def get_visible_yield_error(obs, results, pdf, amplitude): - intgral_pdf = pdf.createIntegral(obs,obs,"window") - intgral_pdf_err = intgral_pdf.getPropagatedError(results, obs) - visible = amplitude.getVal() * intgral_pdf.getVal() - if intgral_pdf.getVal()==0: - visible_err =0 - else: - visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 - return visible, visible_err - -def get_visible_yield(obs, pdf, amplitude): - intgral_pdf = pdf.createIntegral(obs,obs,"window") - visible = amplitude * intgral_pdf.getVal() - return visible - - -##################### signal fit == Double sided CB ###################### -def signal_fit(tree, outputfile, branches): - print "Signal" - wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_signal",branches[0],tree) - # signal - wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') - wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') - wspace.factory('alpha1[1.0, 0.0, 10.0]') - wspace.factory('n1[1.0, 1.0, 20.0]') - wspace.factory('alpha2[1.0, 0.0, 10.0]') - wspace.factory('n2[1.0, 1.0, 20.0]') - wspace.factory('GenericPdf::sig( "DoubleSidedCB2(x,mean,width,alpha1,n1,alpha2,n2)",{x,mean,width,alpha1,n1,alpha2,n2})') - - sgnframe=theBMass.frame() - wspace.factory('nsig[1000,0,100000000]') - wspace.factory('RooExtendPdf::esig(sig,nsig)') - sig=wspace.pdf('sig') - nsig=wspace.var('nsig') - esig=wspace.pdf('esig') - results = esig.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) - - results.Print() - dataset.plotOn(sgnframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) - esig.plotOn(sgnframe, RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected), RooFit.LineColor(ROOT.kBlue), RooFit.LineWidth(2) ) - n_param = results.floatParsFinal().getSize() - print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param - print "edm",results.edm(),"log",results.minNll() - - c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') - CMS_lumi() - c1.SaveAs('sgn_eek_'+outputfile+'.pdf') - residuals(sgnframe,theBMass,'sgn_eek_'+outputfile) - params=esig.getParameters(ROOT.RooArgSet(bMass)) - return {"mean":params.getRealValue('mean'),"width": params.getRealValue('width'),"alpha1":params.getRealValue('alpha1'),"n1":params.getRealValue('n1'),"alpha2":params.getRealValue('alpha2'),"n2":params.getRealValue('n2')} - - -############################### B->KJpsi fit ############################## -def kjpsi_fit(tree, outputfile, branches): - print "kjpsi" - wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kjpsi_bkg",branches[0],tree) - wspace.factory('mean_kjpsi[4.7, 1.0, 5.0]') - wspace.factory('width_kjpsi[0.1, 0.001, 5.0]') - wspace.factory("RooGaussian::kjpsi(x,mean_kjpsi,width_kjpsi)") - wspace.factory('nkjpsi[1000,0,10e+6]') - wspace.factory('RooExtendPdf::ekjpsi(kjpsi,nkjpsi)') - nkjpsi=wspace.var('nkjpsi') - ekjpsi=wspace.pdf('ekjpsi') - results = ekjpsi.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) - results.Print() - kjpframe=theBMass.frame() - dataset.plotOn(kjpframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) - ekjpsi.plotOn(kjpframe,RooFit.Name("ekjpsi"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - c1=canvas_create(kjpframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') - CMS_lumi() - c1.SaveAs('bkg_jpsik_'+outputfile+'.pdf') - residuals(kjpframe,theBMass,'bkg_jpsik_'+outputfile) - params=ekjpsi.getParameters(ROOT.RooArgSet(bMass)) - n_param = results.floatParsFinal().getSize() - print "chi2",kjpframe.chiSquare(n_param),"ndof",n_param - print "edm",results.edm(),"log",results.minNll() - - return {"mean_kjpsi":params.getRealValue('mean_kjpsi'),"width_kjpsi":params.getRealValue('width_kjpsi')} - - -############################ BKG fit ################################# -def bkg_fit(tree, outputfile, branches): - print "combinatorial" - wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_comb_bkg",branches[0],tree) - wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') - wspace.factory('Exponential::bkg(x,exp_alpha)') - wspace.factory('nbkg[1000,0,10e+6]') - wspace.factory('RooExtendPdf::ebkg(bkg,nbkg)') - nbkg=wspace.var('nbkg') - ebkg=wspace.pdf('ebkg') - - results = ebkg.fitTo(dataset,RooFit.Extended(True),RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) ) - results.Print() - bkgframe=theBMass.frame() - dataset.plotOn(bkgframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) - ebkg.plotOn(bkgframe,RooFit.Name("ebkg"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - params=ebkg.getParameters(ROOT.RooArgSet(bMass)) - c1=canvas_create(bkgframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') - CMS_lumi() - c1.SaveAs('bkg_comb_'+outputfile+'.pdf') - n_param = results.floatParsFinal().getSize() - print "chi2",bkgframe.chiSquare(n_param),"ndof",n_param - print "edm",results.edm(),"log",results.minNll() - residuals(bkgframe,theBMass,'bkg_comb_'+outputfile) - - return {"exp_alpha":params.getRealValue('exp_alpha')} - - - -############################# total fit ############################## -def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_parameters=None, bkg_parameters=None, set_sgn_yield=None,Blind_range={"min":4.7,"max":5.7} , number_of_mctoys=None,mva=None,log='log.csv'): - wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) - print "Total" - #amplitudes - wspace.factory('nsig[100.0, 0.0, 1000000.0]' ) - wspace.factory('nbkg[10000.0, 0.0, 100000000.0]') - wspace.factory('nkjpsi[10000.0, 0.0, 1000000.0]') - - # signal - wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') - wspace.factory('width[4.1858e-02, 1.0e-6, 5.0e-1]') - wspace.factory('alpha1[1.0, 0.0, 10.0]') - wspace.factory('n1[1.0, 1.0, 20.0]') - wspace.factory('alpha2[1.0, 0.0, 10.0]') - wspace.factory('n2[1.0, 1.0, 20.0]') - wspace.factory('GenericPdf::sig( "DoubleSidedCB2(x,mean,width,alpha1,n1,alpha2,n2)",{x,mean,width,alpha1,n1,alpha2,n2})') - - # Exponential - bkg - wspace.factory('exp_alpha[-1.0, -100.0, -1.e-4]') - alpha = wspace.var('alpha') - wspace.factory('Exponential::bkg(x,exp_alpha)') - - # Gaussian - bkg - wspace.factory('mean_kjpsi[4.7, 1.0, 5.0]') - wspace.factory('width_kjpsi[0.1, 0.001, 5.0]') - wspace.factory("RooGaussian::kjpsi(x,mean_kjpsi,width_kjpsi)") - - #sum - wspace.factory('SUM::model(nsig*sig,nbkg*bkg,nkjpsi*kjpsi)') - - model = wspace.pdf('model'); bkg = wspace.pdf('bkg') - sig = wspace.pdf('sig'); kjpsi = wspace.pdf('kjpsi'); - nsig = wspace.var('nsig'); nbkg = wspace.var('nbkg') - nkjpsi = wspace.var('nkjpsi') - mean = wspace.var('mean') - - if set_sgn_yield!=None: - nsig.setVal(set_sgn_yield) - nsig.setConstant(True) - for par in sgn_parameters.keys(): - (wspace.var(par)).setVal(sgn_parameters[par]) - (wspace.var(par)).setConstant(True) - for par in kjpsi_parameters.keys(): - (wspace.var(par)).setVal(kjpsi_parameters[par]) - (wspace.var(par)).setConstant(True) - for par in bkg_parameters.keys(): - (wspace.var(par)).setVal(bkg_parameters[par]) - - results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) - print results.Print() - xframe=theBMass.frame(RooFit.Title("")) - - - if Blind_range["min"]>4.7 and Blind_range["max"]<5.7: - norm = dataset.reduce('(({0} > {1}) & ({0} < {2})) | (({0}> {3}) & ({0} < {4}))'.format(branches[0],"4.7", str(Blind_range["min"]),str(Blind_range["max"]), "5.7")).sumEntries() / dataset.reduce('({0} > {1}) & ({0} < {2})'.format(branches[0],"4.7", "5.7")).sumEntries() -# blind= ROOT.RooRealVar("blind","blind",Blind_range["min"],Blind_range["max"]) - # blind.setRange("left",4.7,Blind_range["min"]) - # blind.setRange("right",Blind_range["max"],5.7) - theBMass.setRange("left",4.7,Blind_range["min"]) - theBMass.setRange("right",Blind_range["max"],5.7) - norm=1.0 - dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas"),RooFit.CutRange("left,right")) - else: - norm=1. - dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) - - - #norm=1. - #dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) - - model.plotOn(xframe,RooFit.Name("bkg"),RooFit.Components("bkg"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) - model.plotOn(xframe,RooFit.Name("sig"),RooFit.Components("sig"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) - model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) - - wspace.defineSet('obs', 'x') - obs = wspace.set('obs') - theBMass.setRange("window",Blind_range["min"],Blind_range["max"]) - - #theBMass.setRange("window",5.0,5.4) - obs2= ROOT.RooRealVar("obs2","obs2",Blind_range["min"],Blind_range["max"]) - nset = ROOT.RooArgSet(obs2) - print sig.getVal(), sig.getVal(nset) - print Blind_range - print nbkg.getVal(),nkjpsi.getVal(),nsig.getVal() - nbkg_visible, nbkg_visible_err = get_visible_yield_error(obs, results, bkg, nbkg) - nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, sig, nsig) - nkjpsi_visible, nkjpsi_visible_err = get_visible_yield_error(obs, results, kjpsi, nkjpsi) - print "hereee",nbkg_visible,nsig_visible,nkjpsi_visible -# c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') - n_param = results.floatParsFinal().getSize() - print "chi2",xframe.chiSquare(n_param),"ndof",n_param - print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') - - legend = ROOT.TLegend(0.65,0.65,0.92,0.85) - legend.AddEntry(xframe.findObject("bkg"),"Combinatorial","l"); - legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); - legend.AddEntry(xframe.findObject("sig"),"B -> eeK","l"); - legend.SetLineColor(ROOT.kWhite) - legend.SetTextFont(42); - legend.SetTextSize(0.04); - legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); - legend.Draw(); - pt=pt_create(mva,nsig_visible,nsig_visible_err,nkjpsi_visible+nbkg_visible) - pt.Draw() - CMS_lumi() - c1.cd() - c1.Update() - c1.SaveAs('total_fit_'+outputfile+'.pdf') - print nsig_visible, nsig_visible_err, nbkg_visible_err, nkjpsi_visible_err - residuals(xframe,theBMass,"poutana") - if number_of_mctoys!=None: - nsig.setConstant(False) - mctoys = ROOT.RooMCStudy(model, ROOT.RooArgSet(theBMass), - RooFit.Binned( ROOT.kTRUE), - #RooFit.Binned( ROOT.kFALSE), - ROOT.RooFit.Silence(), - RooFit.Extended(), - RooFit.FitOptions( - RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1) - ) - ) - mctoys.generateAndFit(number_of_mctoys) - - frame1 = mctoys.plotParam(nsig, ROOT.RooFit.Bins(40)) - frame2 = mctoys.plotError(nsig, ROOT.RooFit.Bins(40)) - frame3 = mctoys.plotPull(nsig, ROOT.RooFit.Bins(40), - ROOT.RooFit.FitGauss(ROOT.kTRUE) - ) - # Plot distribution of minimized likelihood - frame4 = mctoys.plotNLL(ROOT.RooFit.Bins(40)) - cpr=canvas_create(frame1,4.7,5.7,1,'Distribution of the fitted value of N_{sgn}',False) - cpr.SaveAs("cpr_"+outputfile+".pdf") - cerr=canvas_create(frame2,0,1,1,'Distribution of the fitted error of N_{sgn}',False) - cerr.SaveAs("cerr_"+outputfile+".pdf") - cpull=canvas_create(frame3,4.7,5.7,1,' Pull of N_{sgn}',False) - cpull.SaveAs("cpull_"+outputfile+".pdf") - clog=canvas_create(frame4,4.7,5.7,1,'- log (L)') - clog.SaveAs("clog_"+outputfile+".pdf") - - postfit_data = mctoys.fitParDataSet() - postfit_nsig = np.array([postfit_data.get(i).getRealValue("nsig") for i in range(int(postfit_data.sumEntries()))]) - #postfit_nsig = np.array([get_visible_yield(obs, sig, postfit_data.get(i).getRealValue("nsig")) for i in range(int(postfit_data.sumEntries()))]) - #postfit_mu = np.array([s/nsig_visible for s in postfit_nsig]) - postfit_mu = np.array([s/set_sgn_yield for s in postfit_nsig]) - rms_mu = np.std(postfit_mu) - fig, ax = plt.subplots() - ax.hist(postfit_mu, bins=50, normed=True, histtype='step', label='MVA={}, RMS={}'.format(mva, rms_mu)) - ax.set_xlabel(r'$\mu$') - ax.set_ylabel('a.u.') - ax.legend(loc='best') - fig.savefig('cmu_{}.pdf'.format(outputfile), bbox_inches='tight') - - csv_header = ['cut', 'nsig', 'nbkg', 'njpsi', 'snr', 'rms_mu'] - df = {} - df['cut'] = mva - df['nsig'] = nsig_visible - df['nbkg'] = nbkg_visible - df['njpsi'] = nkjpsi_visible - df['snr'] = nsig_visible / np.sqrt(nsig_visible + nbkg_visible + nkjpsi_visible) - df['rms_mu'] = 0.0 if number_of_mctoys == None else rms_mu_ - csv_outputfile = log - file_exists = os.path.isfile(csv_outputfile) - with open (csv_outputfile, 'a+') as filedata: - writer = csv.DictWriter(filedata, delimiter=',', fieldnames=csv_header) - if not file_exists: - writer.writeheader() - writer.writerow(df) - - - return (nsig_visible,nbkg_visible,nkjpsi_visible) - - -def kee_yield_from_kjpsi(kjpsi_yield,tree_kee,tree_kjpsi,total_kee,total_kjpsi,xgb): - print "\nWARNING!!!!!",total_kee,"will be used as denominsator for kee eff. and ",total_kjpsi,"for kjpsi. Is this correct ?; code hypothesizes that cross validation is in 8 parts (hardcoded, change if different)\n" - hkee = ROOT.TH1F("hkee","",50,4.7,5.7) - hkjpsi = ROOT.TH1F("hkjpsi","",50,4.7,5.7) - #tree_kee.Draw("Bmass>>hkee","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>1.05 && Mll<2.45 && xgb>"+xgb+")") - #tree_kjpsi.Draw("Bmass>>hkjpsi","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>2.8 && Mll<3.25 && xgb>"+xgb+")") - tree_kee.Draw("Bmass>>hkee","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>1.05 && Mll<2.45 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) ))") - tree_kjpsi.Draw("Bmass>>hkjpsi","1./8.*(Bmass>4.7 && Bmass<5.7 && Mll>2.8 && Mll<3.25 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) ))") - - eff_kee=float(hkee.Integral()) / total_kee - eff_kjpsi=float(hkjpsi.Integral()) / total_kjpsi - result = kjpsi_yield / eff_kjpsi * 4.43*0.01/(1.026*5.93) *eff_kee - print "expect",result,"eff rare",eff_kee,"eff res",eff_kjpsi,"res data",kjpsi_yield - print "rare eff num",float(hkee.Integral()),"den",total_kee - return result - -################################### for scan ############################ -def FitForScan(inputfile, mva, isgnfile, ikspiBkg, ibkg, kjpsi_yield_for_kee,total_nsgn, total_nkjpsi, name ): - branches=["Bmass","Mll","xgb"] - cuts = "xgb>"+str(mva)+" && 1.05"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45"+" && "+branches[3]+">2.0" #+" && {} > 10 && {} > 10".format(branches[4], branches[5]) - print "cut: ", cuts - #cuts = " 1.05<"+branches[1]+" && "+branches[1]+"<2.45 && ( (Npv<15 && xgb>8) || (Npv>14 && xgb>8.5 ) )" - args.outputfile+="_wp"+str(args.mva) - - bkg_parameters={'exp_alpha':-1.98} - - print "start" - if args.fit_primtv: - if args.sel_primtv!= None: - args.sel_primtv = args.sel_primtv.split(",") - else: - args.sel_primtv = ["sgn","bkg_comb","bkg_kjpsi"] - print "primitive params" - if "sgn" in args.sel_primtv: - tree_sgn = ROOT.TChain('mytreefit') - tree_sgn.Add(args.isgnfile) - tree_sgn_cut=tree_sgn.CopyTree(cuts) - signal_parameters = signal_fit(tree_sgn_cut, args.outputfile+"_sgnMC", branches) - print "parameters SGN", signal_parameters['mean'], signal_parameters['width'],signal_parameters['alpha1'],signal_parameters['n1'],signal_parameters['alpha2'],signal_parameters['n2'] - - if "bkg_kjpsi" in args.sel_primtv: - tree_kjpsi = ROOT.TChain('mytreefit') - tree_kjpsi.Add(args.ikspiBkg) - tree_kjpsi_cut=tree_kjpsi.CopyTree(cuts) - kjpsi_parameters = kjpsi_fit(tree_kjpsi_cut, args.outputfile+"_kjpsiMC", branches) - print "parameters KJpsi BKG", kjpsi_parameters['mean_kjpsi'], kjpsi_parameters['width_kjpsi'] - - if "bkg_comb" in args.sel_primtv: - #cuts = branches[2]+">8 && "+branches[1]+"<5." - #cuts = branches[2]+">"+str(args.mva)+" && "+branches[1]+"<5" - tree_bkg = ROOT.TChain('mytreefit') - tree_bkg.Add(args.ibkg) - tree_bkg_cut=tree_bkg.CopyTree(cuts) - bkg_parameters = bkg_fit(tree_bkg_cut, args.outputfile+"_SameSign", branches) - print "parameters Combinatorial BKG", bkg_parameters['exp_alpha'] - - else: - signal_parameters={'mean': 5.272, 'width': 0.057, 'alpha1': 0.652, 'n1': 3.3, 'alpha2': 1.32, 'n2': 2.01} - kjpsi_parameters={'mean_kjpsi':4.72,'width_kjpsi':1.06} - bkg_parameters={'exp_alpha':-1.98} - - if args.kjpsi_yield_for_kee!=None: - tree_sgn = ROOT.TChain('mytreefit') - tree_sgn.Add(args.isgnfile) - tree_kjpsi = ROOT.TChain('mytreefit') - tree_kjpsi.Add(args.ikspiBkg) - args.set_expected_sgn = kee_yield_from_kjpsi(args.kjpsi_yield_for_kee,tree_sgn,tree_kjpsi,args.total_nsgn,args.total_nkjpsi,str(args.mva)) - print "WARNING expected signal set and FIXED to ",args.set_expected_sgn,"in all q^2" - - #args.set_expected_sgn = None - if not args.skip_realfit: - #cuts = branches[2]+">"+str(args.mva)+" && 1.05<"+branches[1]+" && "+branches[1]+"<2.45"+" && "+branches[3]+">2.0 &&"+branches[4]+">2.0" - tree = ROOT.TChain('mytreefit') - tree.Add(args.inputfile) - tree_cut=tree.CopyTree(cuts) - nsig, nbkg, nkjpsi =total_fit(tree_cut, args.outputfile, branches, signal_parameters, kjpsi_parameters, bkg_parameters, args.set_expected_sgn, {"min":5.0,"max":5.4}, args.number_of_mctoys, str(args.mva), args.log) - # combinatorial BKG parameters set but not fixed. - print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) diff --git a/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py b/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py index 0b365e5..8bca99a 100644 --- a/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py +++ b/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py @@ -93,6 +93,10 @@ def get_visible_yield_error(obs, results, pdf, amplitude): visible_err =0 else: visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 + if np.isnan(visible): + visible = 0.0 + if np.isnan(visible_err): + visible_err = 0.0 return visible, visible_err def get_visible_yield(obs, pdf, amplitude): @@ -221,10 +225,10 @@ def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_pdf=None, k wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) print "Total" #amplitudes - wspace.factory('nsig[100.0, 0.0, 1000000.0]' ) - wspace.factory('nbkg[10000.0, 0.0, 100000000.0]') - wspace.factory('nkjpsi[10000.0, 0.0, 1000000.0]') - wspace.factory('nkstaree[10000.0, 0.0, 1000000.0]') + wspace.factory('nsig[10.0, 0.0, 1000000.0]' ) + wspace.factory('nbkg[100.0, 0.0, 100000000.0]') + wspace.factory('nkjpsi[10.0, 0.0, 1000000.0]') + wspace.factory('nkstaree[10.0, 0.0, 1000000.0]') # signal wspace.factory('mean[5.272e+00, 5.22e+00, 5.5e+00]') @@ -289,6 +293,7 @@ def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_pdf=None, k theBMass.setRange("right",Blind_range["max"],5.7) norm=1.0 dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas"),RooFit.CutRange("left,right")) + else: norm=1. dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) @@ -340,7 +345,7 @@ def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_pdf=None, k c1.Update() c1.SaveAs('total_fit_'+outputfile+'.pdf') print nsig_visible, nsig_visible_err, nbkg_visible_err, nkjpsi_visible_err - residuals(xframe,theBMass,"poutana") + residuals(xframe,theBMass,outputfile+"_poutana") if number_of_mctoys!=None: nsig.setConstant(False) mctoys = ROOT.RooMCStudy(model, ROOT.RooArgSet(theBMass), diff --git a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py index 74317f2..5dfecd7 100644 --- a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py @@ -189,15 +189,19 @@ def bkg_fit(tree, outputfile, branches, SavePlot=True): ############################# total fit ############################## -def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarJpsi_pdf=None,comb_parameters=None,Significance_range=None, partial_ratio=None, mvacut="",log='log.csv'): +def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarJpsi_pdf=None, KstarPlusJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, partial_ratio_kstarplus=None, mvacut="",log='log.csv'): + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) print "Total" #amplitudes - wspace.factory('nsignal[100.0, 0.0, 1000000.0]' ) - wspace.factory('ncomb[10000.0, 0.0, 1000000.0]') - wspace.factory('notherB[10000.0, 0.0, 1000000.0]') - wspace.factory('frac_partial[1.0, 0.0, 10.0]') + wspace.factory('nsignal[10000.0, 0.0, 1000000.0]' ) + wspace.factory('ncomb[50000.0, 0.0, 1000000.0]') + wspace.factory('notherB[1000.0, 0.0, 1000000.0]') + wspace.factory('frac_partial[0.3, 0.0, 10.0]') wspace.factory('prod::nKstarJpsi(frac_partial,nsignal)') + wspace.factory('frac_kstarplus[0.1, 0.0, 10.0]') + #wspace.factory('prod::nKstarPlusJpsi(frac_kstarplus,nsignal)') + wspace.factory('prod::nKstarPlusJpsi(frac_kstarplus,nKstarJpsi)') #wspace.factory('nKstarJpsi[10000.0, 0.0, 1000000.0]') @@ -214,41 +218,53 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('SUM::signal(cb_signal,frac*g_signal)') # other B - bkg - wspace.factory('exp_alpha_otherb[-15.0, -100.0, -5.0]') + wspace.factory('exp_alpha_otherb[-6.0, -100.0, -1.e-4]') wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') # K*Jpsi - bkg getattr(wspace, "import")(KstarJpsi_pdf, RooFit.Rename('kstarjpsi')) + # K*+Jpsi - bkg + getattr(wspace, "import")(KstarPlusJpsi_pdf, RooFit.Rename('kstarplusjpsi')) + # combinatorial - bkg wspace.factory('exp_alpha_comb[-1.0, -100.0, -1.e-4]') wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') #sum - wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarJpsi*kstarjpsi,notherB*exp_otherb)') + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarJpsi*kstarjpsi,nKstarPlusJpsi*kstarplusjpsi,notherB*exp_otherb)') + model = wspace.pdf('model'); signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') exp_otherb = wspace.pdf('exp_otherb') kstarjpsi = wspace.pdf('kstarjpsi') + kstarplusjpsi = wspace.pdf('kstarplusjpsi') nsignal = wspace.var('nsignal'); ncomb = wspace.var('ncomb') nKstarJpsi = wspace.obj('nKstarJpsi') + nKstarPlusJpsi = wspace.obj('nKstarPlusJpsi') notherB = wspace.var('notherB') frac_partial = wspace.var('frac_partial') + frac_kstarplus = wspace.var('frac_kstarplus') for par in signal_parameters.keys(): (wspace.var(par)).setVal(signal_parameters[par]) - (wspace.var(par)).setConstant(True) + if par not in ['mean', 'gauss_mean']: + (wspace.var(par)).setConstant(True) for par in otherB_parameters.keys(): (wspace.var(par)).setVal(otherB_parameters[par]) #(wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) - #(wspace.var(par)).setConstant(True) + (wspace.var(par)).setConstant(True) if partial_ratio is not None: wspace.var('frac_partial').setVal(partial_ratio) - #wspace.var('frac_partial').setConstant(True) + wspace.var('frac_partial').setConstant(True) + + if partial_ratio_kstarplus is not None: + wspace.var('frac_kstarplus').setVal(partial_ratio_kstarplus) + wspace.var('frac_kstarplus').setConstant(True) results = model.fitTo(dataset, RooFit.Extended(True), RooFit.Save(), RooFit.Range(4.7,5.7), RooFit.PrintLevel(-1)) print results.Print() @@ -260,6 +276,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("kstarplusjpsi"),RooFit.Components("kstarplusjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(46),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("signal"),RooFit.Components("signal"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') @@ -281,8 +298,10 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, signal, nsignal) nKstarJpsi_visible = get_visible_yield(obs, results, kstarjpsi , nKstarJpsi) nKstarJpsi_visible_err = 0.0 + nKstarPlusJpsi_visible = get_visible_yield(obs, results, kstarplusjpsi , nKstarPlusJpsi) + nKstarPlusJpsi_visible_err = 0.0 notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) - nbkg_visible = nKstarJpsi_visible+ncomb_visible+notherB_visible + nbkg_visible = nKstarJpsi_visible+nKstarPlusJpsi_visible+ncomb_visible+notherB_visible # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') n_param = results.floatParsFinal().getSize() @@ -293,6 +312,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend = ROOT.TLegend(0.65,0.65,0.92,0.85) legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); + legend.AddEntry(xframe.findObject("kstarplusjpsi"),"B -> J/#psiK*+","l"); legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); legend.AddEntry(xframe.findObject("signal"),"B -> J/#psiK","l"); legend.SetLineColor(ROOT.kWhite) @@ -300,20 +320,21 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend.SetTextSize(0.04); legend.AddEntry(xframe.findObject("datas"),"Data","lpe"); legend.Draw(); - pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nKstarJpsi_visible+ncomb_visible+notherB_visible) + pt=pt_create(mvacut,nsig_visible,nsig_visible_err,nbkg_visible) pt.Draw() CMS_lumi() c1.cd() c1.Update() c1.SaveAs('total_fit_'+outputfile+'.pdf') - print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err,"otherB", notherB_visible, "+/-",notherB_visible_err - residuals(xframe,theBMass,"poutana") + print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-", nKstarJpsi_visible_err, "K*+ J/psi", nKstarPlusJpsi_visible, "+/-", nKstarPlusJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err - saveWS = False + residuals(xframe,theBMass,outputfile+"_poutana") + + saveWS = True if saveWS: # get likelihood - + ''' nll = model.createNLL(dataset) ROOT.RooMinuit(nll).migrad() nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(7500.0,10000.0),RooFit.Title("LL and profileLL in nsignal")) ; @@ -327,7 +348,8 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame c2.cd() c2.Update() c2.SaveAs('nll_'+outputfile+'.pdf') - + ''' + wspace_output = ROOT.RooWorkspace('wspace') getattr(wspace_output, "import")(model) getattr(wspace_output, "import")(dataset) @@ -337,17 +359,20 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace_output.writeToFile('wspace_'+outputfile+'.root') - csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarJpsi_total', 'nKstarJpsi_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarJpsi', 'notherB', 'snr', 'chi2'] + csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarJpsi_total', 'nKstarJpsi_total_unc', 'nKstarPlusJpsi_total', 'nKstarPlusJpsi_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarJpsi', 'nKstarPlusJpsi', 'notherB', 'snr', 'chi2'] df = {} df['cut'] = mvacut df['nsig_total'] = nsignal.getVal() df['nsig_total_unc'] = nsignal.getError() df['nKstarJpsi_total'] = nKstarJpsi.getVal() - df['nKstarJpsi_total_unc'] = 0.0 + df['nKstarJpsi_total_unc'] = np.sqrt(nKstarJpsi.getVal()) + df['nKstarPlusJpsi_total'] = nKstarPlusJpsi.getVal() + df['nKstarPlusJpsi_total_unc'] = np.sqrt(nKstarPlusJpsi.getVal()) df['nsig'] = nsig_visible df['nbkg'] = nbkg_visible df['ncomb'] = ncomb_visible df['nKstarJpsi'] = nKstarJpsi_visible + df['nKstarPlusJpsi'] = nKstarPlusJpsi_visible df['notherB'] = notherB_visible df['snr'] = nsig_visible / np.sqrt(nsig_visible + nbkg_visible) df['chi2'] = xframe.chiSquare(n_param) @@ -374,6 +399,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame parser.add_argument("--ibkg", dest="ibkg", default="../BDT/TrainingCore/forMeas_xgbmodel_kee_v5.1_12B_Mu9_*_samesign.root", help="Input combinatorial BKG file") parser.add_argument("--iotherB", dest="iotherB_BKG", default="OtherB_BKGtree_KJpsiEE.root", help="Input combinatorial BKG file") parser.add_argument("--iKstarJpsi_BKG", dest="iKstarJpsi_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input combinatorial BKG file") + parser.add_argument("--iKstarPlusJpsi_BKG", dest="iKstarPlusJpsi_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input combinatorial BKG file") parser.add_argument("--fit_primitive", dest="fit_primtv", default=False, action='store_true', help="primitive fits for fixing params or use defaults") parser.add_argument("--skip_realfit", dest="skip_realfit", default=False, action='store_true', help="does not perform the final fit. useful for defining parameters, tests on pdfs") parser.add_argument("--sel_primitive", dest="sel_primtv", default=None, help="runs only the selected primitive fits. Options: sgn bkg_comb bkg_otherb bkg_kstar_kee bkg_kstar_piee. they can be combined with ',' in strings. No spaces") @@ -381,11 +407,15 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame parser.add_argument("--maxx", dest="maxx", default=-1.0,type=float, help="maxx for integral") parser.add_argument("--log", dest="log", default="log.csv", help="log of the fitting results") parser.add_argument("--partial_ratio", dest="partial_ratio", default=None, type=float, help="fixing the partially reco. yield") + parser.add_argument("--partial_ratio_kstarplus", dest="partial_ratio_kstarplus", default=None, type=float, help="fixing the partially reco. yield") args = parser.parse_args() branches=["Bmass","Mll","xgb","KLmassD0"] cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + " && " + branches[3] + ">2.0" - cuts_samesign = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + if args.mva < 7.0: + cuts_samesign = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + else: + cuts_samesign = branches[2]+"> 7.0 "+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" #cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.25" #cuts = branches[2]+">"+str(args.mva)+" && 2.8<"+branches[1]+" && "+branches[1]+"<3.25" + " && " + branches[3] + ">2.0" @@ -399,7 +429,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if args.sel_primtv!= None: args.sel_primtv = args.sel_primtv.split(",") else: - args.sel_primtv = ["sgn","bkg_comb","bkg_otherb","bkg_kstarjpsi"] + args.sel_primtv = ["sgn","bkg_comb","bkg_otherb","bkg_kstarjpsi","bkg_kstarplusjpsi"] print "primitive params" if "sgn" in args.sel_primtv: tree_sgn = ROOT.TChain('mytreefit') @@ -430,6 +460,13 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame KstarJpsi_pdf = kde_fit(tree_KstarJpsi_cut, args.outputfile+"_KstarJpsiMC", branches, 'kstarjpsi') print "finished kde fit for K* J/psi" + if "bkg_kstarplusjpsi" in args.sel_primtv: + tree_KstarPlusJpsi = ROOT.TChain('mytreefit') + tree_KstarPlusJpsi.Add(args.iKstarPlusJpsi_BKG) + tree_KstarPlusJpsi_cut=tree_KstarPlusJpsi.CopyTree(cuts) + KstarPlusJpsi_pdf = kde_fit(tree_KstarPlusJpsi_cut, args.outputfile+"_KstarPlusJpsiMC", branches, 'kstarplusjpsi') + print "finished kde fit for K*+ J/psi" + else: print "Need to provide MC template" @@ -440,7 +477,9 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if args.minx==-1: args.minx=signal_parameters["mean"]-2*signal_parameters["width"] if args.maxx==-1: args.maxx=signal_parameters["mean"]+2*signal_parameters["width"] - nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarJpsi_pdf,comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, str(args.mva), args.log) + #nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarJpsi_pdf,comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, str(args.mva), args.log) + nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarJpsi_pdf, KstarPlusJpsi_pdf, comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, args.partial_ratio_kstarplus, str(args.mva), args.log) + print "sig",nsig,"comb", nbkg,"K* J/psi", nKstarJpsi,"otherB", notherB,"all sig", nsig_total # combinatorial BKG parameters set but not fixed. # print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) diff --git a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py index 303268f..9ecd4dc 100644 --- a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py @@ -58,7 +58,7 @@ def get_visible_yield_error(obs, results, pdf, amplitude): intgral_pdf = pdf.createIntegral(obs,obs,"window") intgral_pdf_err = intgral_pdf.getPropagatedError(results, obs) visible = amplitude.getVal() * intgral_pdf.getVal() - visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if amplitude.getVal() != 0.0 else 0.0 + visible_err = visible * math.sqrt(pow(amplitude.getError()/amplitude.getVal(), 2) + pow(intgral_pdf_err/intgral_pdf.getVal(), 2)) if (amplitude.getVal() != 0.0 and intgral_pdf.getVal() != 0) else 0.0 return visible, visible_err @@ -190,19 +190,24 @@ def bkg_fit(tree, outputfile, branches, SavePlot=True): ############################# total fit ############################## -def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarPsi2S_pdf=None , KstarJpsi_pdf=None , KJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, mvacut="",log='log.csv'): +def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarPsi2S_pdf=None , KstarPlusPsi2S_pdf=None, KstarJpsi_pdf=None , KJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, partial_ratio_kstarplus=None, mvacut="",log='log.csv'): wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) print "Total" #amplitudes wspace.factory('nsignal[600.0, 0.0, 1000000.0]' ) wspace.factory('ncomb[1000.0, 0.0, 1000000.0]') - wspace.factory('notherB[500.0, 0.0, 1000000.0]') + wspace.factory('notherB[100.0, 0.0, 1000000.0]') + #wspace.factory('notherB[0.0, 0.0, 0.0]') wspace.factory('nKstarJpsi[100.0, 0.0, 1000000.0]') wspace.factory('nkjpsi[100.0, 0.0, 1000000.0]') wspace.factory('frac_partial[1.0, 0.0, 10.0]') wspace.factory('prod::nKstarPsi2S(frac_partial,nsignal)') + wspace.factory('frac_kstarplus[0.1, 0.0, 10.0]') + #wspace.factory('prod::nKstarPlusPsi2S(frac_kstarplus,nsignal)') + wspace.factory('prod::nKstarPlusPsi2S(frac_kstarplus,nKstarPsi2S)') + # signal wspace.factory('mean[5.278e+00, 5.22e+00, 5.5e+00]') @@ -217,13 +222,16 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('SUM::signal(cb_signal,frac*g_signal)') # other B - bkg - #wspace.factory('exp_alpha_otherb[-1.0, -100.0, -1.e-4]') - wspace.factory('exp_alpha_otherb[-15.0, -100.0, -5.0]') + wspace.factory('exp_alpha_otherb[-5.0, -100.0, -1.e-4]') + #wspace.factory('exp_alpha_otherb[-15.0, -100.0, -1.0]') wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') # K*Psi2S - bkg getattr(wspace, "import")(KstarPsi2S_pdf, RooFit.Rename('kstarpsi2s')) + # K*+Psi2S - bkg + getattr(wspace, "import")(KstarPlusPsi2S_pdf, RooFit.Rename('kstarpluspsi2s')) + # K*Jpsi - bkg getattr(wspace, "import")(KstarJpsi_pdf, RooFit.Rename('kstarjpsi')) @@ -237,19 +245,24 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame #sum #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,nkjpsi*kjpsi,notherB*exp_otherb)') #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nkjpsi*kjpsi,notherB*exp_otherb)') - wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,notherB*exp_otherb)') + #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,notherB*exp_otherb)') #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,notherB*exp_otherb)') + #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarPlusPsi2S*kstarpluspsi2s,notherB*exp_otherb)') + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarPlusPsi2S*kstarpluspsi2s)') model = wspace.pdf('model'); signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') exp_otherb = wspace.pdf('exp_otherb') kjpsi = wspace.pdf('kjpsi') kstarpsi2s = wspace.pdf('kstarpsi2s'); kstarjpsi = wspace.pdf('kstarjpsi') + kstarpluspsi2s = wspace.pdf('kstarpluspsi2s') nsignal = wspace.var('nsignal'); ncomb = wspace.var('ncomb') nKstarPsi2S = wspace.obj('nKstarPsi2S'); nKstarJpsi = wspace.var('nKstarJpsi') + nKstarPlusPsi2S = wspace.obj('nKstarPlusPsi2S') nKJpsi = wspace.var('nkjpsi') notherB = wspace.var('notherB') frac_partial = wspace.var('frac_partial') + frac_kstarplus = wspace.var('frac_kstarplus') for par in signal_parameters.keys(): (wspace.var(par)).setVal(signal_parameters[par]) @@ -259,11 +272,16 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame #(wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) - #(wspace.var(par)).setConstant(True) + (wspace.var(par)).setConstant(True) if partial_ratio is not None: wspace.var('frac_partial').setVal(partial_ratio) - #wspace.var('frac_partial').setConstant(True) + wspace.var('frac_partial').setConstant(True) + + if partial_ratio_kstarplus is not None: + wspace.var('frac_kstarplus').setVal(partial_ratio_kstarplus) + wspace.var('frac_kstarplus').setConstant(True) + #wspace.var('nKstarJpsi').setVal(267) #wspace.var('nKstarJpsi').setConstant(True) @@ -276,9 +294,10 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + #model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) #model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(43),RooFit.LineColor(43),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarpsi2s"),RooFit.Components("kstarpsi2s"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("kstarpluspsi2s"),RooFit.Components("kstarpluspsi2s"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(46),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) #model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(15),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("signal"),RooFit.Components("signal"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) model.plotOn(xframe, RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineColor(ROOT.kRed) ) @@ -301,13 +320,17 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame nsig_visible, nsig_visible_err = get_visible_yield_error(obs, results, signal, nsignal) nKstarPsi2S_visible = get_visible_yield(obs, results, kstarpsi2s , nKstarPsi2S) nKstarPsi2S_visible_err = 0.0 + nKstarPlusPsi2S_visible = get_visible_yield(obs, results, kstarpluspsi2s , nKstarPlusPsi2S) + nKstarPlusPsi2S_visible_err = 0.0 nKstarJpsi_visible, nKstarJpsi_visible_err = get_visible_yield_error(obs, results, kstarjpsi , nKstarJpsi) nKJpsi_visible, nKJpsi_visible_err = get_visible_yield_error(obs, results,kjpsi , nKJpsi) notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+nKJpsi_visible+notherB_visible #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKJpsi_visible+notherB_visible - nbkg_visible = ncomb_visible+nKstarPsi2S_visible+notherB_visible + #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+notherB_visible #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+notherB_visible + #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+notherB_visible+nKstarPlusPsi2S_visible + nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarPlusPsi2S_visible # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') n_param = results.floatParsFinal().getSize() @@ -318,9 +341,10 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend = ROOT.TLegend(0.65,0.65,0.92,0.85) legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); legend.AddEntry(xframe.findObject("kstarpsi2s"),"B -> #psi(2S)K*","l"); + legend.AddEntry(xframe.findObject("kstarpluspsi2s"),"B -> #psi(2S)K*+","l"); #legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); #legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); - legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); + #legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); legend.AddEntry(xframe.findObject("signal"),"B -> #psi(2S)K","l"); legend.SetLineColor(ROOT.kWhite) legend.SetTextFont(42); @@ -334,13 +358,13 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame c1.cd() c1.Update() c1.SaveAs('total_fit_'+outputfile+'.pdf') - print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* Psi2S", nKstarPsi2S_visible, "+/-",nKstarPsi2S_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err, "K J/psi", nKJpsi_visible, "+/-", nKJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err - residuals(xframe,theBMass,"poutana") + print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* Psi2S", nKstarPsi2S_visible, "+/-",nKstarPsi2S_visible_err,"K*+ Psi2S", nKstarPlusPsi2S_visible, "+/-",nKstarPlusPsi2S_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err, "K J/psi", nKJpsi_visible, "+/-", nKJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err + residuals(xframe,theBMass,outputfile+"_poutana") - saveWS = False + saveWS = True if saveWS: # get likelihood - + ''' nll = model.createNLL(dataset) ROOT.RooMinuit(nll).migrad() nll_frame = nsignal.frame(RooFit.Bins(30),RooFit.Range(500,1000),RooFit.Title("LL and profileLL in nsignal")) ; @@ -354,6 +378,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame c2.cd() c2.Update() c2.SaveAs('nll_'+outputfile+'.pdf') + ''' wspace_output = ROOT.RooWorkspace('wspace') getattr(wspace_output, "import")(model) @@ -363,17 +388,20 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace_output.Print("V") wspace_output.writeToFile('wspace_'+outputfile+'.root') - csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarPsi2S_total', 'nKstarPsi2S_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarPsi2S', 'nKstarJpsi', 'nKJpsi', 'notherB', 'snr', 'chi2'] + csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarPsi2S_total', 'nKstarPsi2S_total_unc', 'nKstarPlusPsi2S_total', 'nKstarPlusPsi2S_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarPsi2S', 'nKstarPlusPsi2S', 'nKstarJpsi', 'nKJpsi', 'notherB', 'snr', 'chi2'] df = {} df['cut'] = mvacut df['nsig_total'] = nsignal.getVal() df['nsig_total_unc'] = nsignal.getError() df['nKstarPsi2S_total'] = nKstarPsi2S.getVal() - df['nKstarPsi2S_total_unc'] = 0.0 + df['nKstarPsi2S_total_unc'] = np.sqrt(nKstarPsi2S.getVal()) + df['nKstarPlusPsi2S_total'] = nKstarPlusPsi2S.getVal() + df['nKstarPlusPsi2S_total_unc'] = np.sqrt(nKstarPlusPsi2S.getVal()) df['nsig'] = nsig_visible df['nbkg'] = nbkg_visible df['ncomb'] = ncomb_visible df['nKstarPsi2S'] = nKstarPsi2S_visible + df['nKstarPlusPsi2S'] = nKstarPlusPsi2S_visible df['nKstarJpsi'] = nKstarJpsi_visible df['nKJpsi'] = nKJpsi_visible df['notherB'] = notherB_visible @@ -402,12 +430,14 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame parser.add_argument("--ibkg", dest="ibkg", default="../BDT/TrainingCore/forMeas_xgbmodel_kee_v5.1_12B_Mu9_*_samesign.root", help="Input combinatorial BKG file") parser.add_argument("--iotherB", dest="iotherB_BKG", default="OtherB_BKGtree_KJpsiEE.root", help="Input combinatorial BKG file") parser.add_argument("--iKstarPsi2S_BKG", dest="iKstarPsi2S_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input B->K*Psi(2S) BKG file") + parser.add_argument("--iKstarPlusPsi2S_BKG", dest="iKstarPlusPsi2S_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input combinatorial BKG file") parser.add_argument("--iKstarJpsi_BKG", dest="iKstarJpsi_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_kaon_mva_pf.root", help="Input B->K*J/psi BKG file") parser.add_argument("--iKJpsiee_BKG", dest="iKJpsiee_BKG", default="mc_files/reg/BParkingNANO_2021Mar05_BdToKstarJpsi_Toee_v2_BToKEEAnalyzer_2021Mar12_HLTMu9IP6_mc_tighterPreselectionWODmass_pion_mva_pf.root", help="Input B->KJ/psi BKG file") parser.add_argument("--fit_primitive", dest="fit_primtv", default=False, action='store_true', help="primitive fits for fixing params or use defaults") parser.add_argument("--skip_realfit", dest="skip_realfit", default=False, action='store_true', help="does not perform the final fit. useful for defining parameters, tests on pdfs") parser.add_argument("--sel_primitive", dest="sel_primtv", default=None, help="runs only the selected primitive fits. Options: sgn bkg_comb bkg_otherb bkg_kstar_kee bkg_kstar_piee. they can be combined with ',' in strings. No spaces") parser.add_argument("--partial_ratio", dest="partial_ratio", default=None, type=float, help="fixing the partially reco. yield") + parser.add_argument("--partial_ratio_kstarplus", dest="partial_ratio_kstarplus", default=None, type=float, help="fixing the partially reco. yield") parser.add_argument("--minx", dest="minx", default=-1.0,type=float, help="minx for integral") parser.add_argument("--maxx", dest="maxx", default=-1.0,type=float, help="maxx for integral") parser.add_argument("--log", dest="log", default="log.csv", help="log of the fitting results") @@ -415,7 +445,12 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame branches=["Bmass","Mll","xgb","KLmassD0"] cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" - cuts_samesign = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + #cuts = branches[2]+">"+str(args.mva)+" && 0<"+branches[1]+" && "+branches[1]+"<5" + " && " + branches[3] + ">2.0" + + if args.mva < 7.0: + cuts_samesign = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + else: + cuts_samesign = branches[2]+"> 7.0 "+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" args.outputfile+="_wp"+str(args.mva) @@ -429,7 +464,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if args.sel_primtv!= None: args.sel_primtv = args.sel_primtv.split(",") else: - args.sel_primtv = ["sgn","bkg_comb","bkg_otherb","bkg_kstarjpsi","bkg_kstarpsi2s","bkg_kjpsi_ee"] + args.sel_primtv = ["sgn","bkg_comb","bkg_otherb","bkg_kstarjpsi","bkg_kstarpsi2s","bkg_kjpsi_ee","bkg_kstarpluspsi2s"] print "primitive params" if "sgn" in args.sel_primtv: tree_sgn = ROOT.TChain('mytreefit') @@ -474,6 +509,13 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame KJpsiee_pdf = kde_fit(tree_KJpsiee_cut, args.outputfile+"_KJpsieeMC", branches, 'kjpsi') print "finished kde fit for K J/psi" + if "bkg_kstarpluspsi2s" in args.sel_primtv: + tree_KstarPlusPsi2S = ROOT.TChain('mytreefit') + tree_KstarPlusPsi2S.Add(args.iKstarPlusPsi2S_BKG) + tree_KstarPlusPsi2S_cut=tree_KstarPlusPsi2S.CopyTree(cuts) + KstarPlusPsi2S_pdf = kde_fit(tree_KstarPlusPsi2S_cut, args.outputfile+"_KstarPlusPsi2SMC", branches, 'kstarpluspsi2s') + print "finished kde fit for K*+ J psi(2S)" + else: print "Need to provide MC template" @@ -484,7 +526,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if args.minx==-1: args.minx=signal_parameters["mean"]-2*signal_parameters["width"] if args.maxx==-1: args.maxx=signal_parameters["mean"]+2*signal_parameters["width"] - nsig, nbkg, nKstarPsi2S, nKstarJpsi, nKJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarPsi2S_pdf, KstarJpsi_pdf ,KJpsiee_pdf, comb_parameters, {"min":args.minx,"max":args.maxx},args.partial_ratio, str(args.mva), args.log) + nsig, nbkg, nKstarPsi2S, nKstarJpsi, nKJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarPsi2S_pdf, KstarPlusPsi2S_pdf, KstarJpsi_pdf ,KJpsiee_pdf, comb_parameters, {"min":args.minx,"max":args.maxx},args.partial_ratio, args.partial_ratio_kstarplus, str(args.mva), args.log) print "sig",nsig,"comb", nbkg,"K* Psi2S", nKstarPsi2S,"K* J/psi", nKstarJpsi,"K J/psi", nKJpsi, "otherB", notherB,"all sig", nsig_total # combinatorial BKG parameters set but not fixed. # print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) diff --git a/fit/run_fit_KEE_lowq2_bparkPU.py b/fit/run_fit_KEE_lowq2_bparkPU.py index 90b8bcf..ed4e8b3 100644 --- a/fit/run_fit_KEE_lowq2_bparkPU.py +++ b/fit/run_fit_KEE_lowq2_bparkPU.py @@ -36,11 +36,12 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'mix' - log = 'log_kee_bparkPU_v7.3_{}.csv'.format(eleType) + log = 'log_kee_bparkPU_v7.3_{}_nonreg.csv'.format(eleType) info = defaultdict(dict) nparts = range(8) + ''' info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' info['pf']['nonresonant_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC.root'.format('marker') info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCres.root'.format('marker') @@ -52,7 +53,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['n_data_jpsi'] = 7069.5 info['pf']['n_mc_jpsi'] = 563421.0 info['pf']['n_mc_lowq2'] = 617615.0 - + ''' + ''' info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' info['mix']['nonresonant_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC.root'.format('marker') info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCres.root'.format('marker') @@ -63,6 +65,49 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['mix']['n_data_jpsi'] = 5533.45 info['mix']['n_mc_jpsi'] = 563421.0 info['mix']['n_mc_lowq2'] = 617615.0 + ''' + ''' + info['pf']['inputfile'] = '../data/data_PFe_v7.3_nonreg_rmVar/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_rmVar_data_mvaCut0.root' + info['pf']['nonresonant_mc'] = '../data/data_PFe_v7.3_nonreg_rmVar/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_rmVar_{}_MC.root'.format('marker') + info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3_nonreg_rmVar/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_rmVar_{}_MCres.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3_nonreg_rmVar/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_rmVar_0_MC.root' + info['pf']['ikjpsi'] = '../data/data_PFe_v7.3_nonreg_rmVar/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_rmVar_0_MCres.root' + info['pf']['ikstaree'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstaree.root' + #info['pf']['jpsi_mva_wp'] = 5.0 + #info['pf']['n_data_jpsi'] = 6853.0 + info['pf']['jpsi_mva_wp'] = 6.5 + info['pf']['n_data_jpsi'] = 5611.69 + + #info['pf']['n_mc_jpsi'] = 563421.0 + #info['pf']['n_mc_lowq2'] = 617615.0 + info['pf']['n_mc_jpsi'] = 209954.0 + info['pf']['n_mc_lowq2'] = 231498.0 + ''' + + info['pf']['inputfile'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_data_mvaCut0.root' + info['pf']['nonresonant_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MC.root'.format('marker') + info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MCres.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC.root' + info['pf']['ikjpsi'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MCres.root' + info['pf']['ikstaree'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstaree.root' + #info['pf']['jpsi_mva_wp'] = 4.8 + #info['pf']['n_data_jpsi'] = 7951.28 + info['pf']['jpsi_mva_wp'] = 8.3 + info['pf']['n_data_jpsi'] = 4779.12 + info['pf']['n_mc_jpsi'] = 211912.0 + info['pf']['n_mc_lowq2'] = 232115.0 + + info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_data_mvaCut0.root' + info['mix']['nonresonant_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MC.root'.format('marker') + info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MCres.root'.format('marker') + info['mix']['isgn'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC.root' + info['mix']['ikjpsi'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MCres.root' + info['mix']['ikstaree'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_kstaree.root' + info['mix']['jpsi_mva_wp'] = 8.6 + info['mix']['n_data_jpsi'] = 2084.77 + info['mix']['n_mc_jpsi'] = 211912.0 + info['mix']['n_mc_lowq2'] = 232115.0 + info['mix']['ikstaree'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstaree.root' num_mctoys = None #5000 @@ -80,8 +125,9 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): selection['Dmass'] = '(KLmassD0 > 2.0)' #selection['elePt'] = '(L1pt > 10) and (L2pt > 10)' + #selection['hlt'] = '(Mu9_IP6 == True)' - mc_branches = ['Bmass', 'Mll', 'KLmassD0', 'xgb'] #+ ['L1pt', 'L2pt'] + mc_branches = ['Bmass', 'Mll', 'KLmassD0', 'xgb'] #+['Mu9_IP6']#+ ['L1pt', 'L2pt'] jpsi_mc_branches = [get_df(info[eleType]['jpsi_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] nonresonant_mc_branches = [get_df(info[eleType]['nonresonant_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] @@ -95,27 +141,31 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): eff['lowq2_q2'] = float(nonresonant_mc_branches[0].query(selection['lowq2']).shape[0]) / float(nonresonant_mc_branches[0].shape[0]) # efficiency of bdt of jpsi eff['jpsi_bdt'] = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > {})'.format(jpsi_mva_wp)])).shape[0]) / float(jpsi_mc_branches[i].query(selection['jpsi']).shape[0]) for i in nparts]) + #eff['jpsi_bdt'] = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], selection['hlt'], '(xgb > {})'.format(jpsi_mva_wp)])).shape[0]) / float(jpsi_mc_branches[i].query(selection['jpsi']).shape[0]) for i in nparts]) if eleType == 'pf': - mvaCut = np.linspace(7.0, 9.0, 20) - #mvaCut = np.array([8.0, ]) + mvaCut = np.linspace(8.0, 8.7, 8) + #mvaCut = np.array([8.8, ]) else: - mvaCut = np.linspace(8.5, 9.5, 20) + mvaCut = np.linspace(8.3, 9.0, 8) #mvaCut = np.array([9.0, ]) for cut in mvaCut: eff_lowq2_bdt = np.mean([float(nonresonant_mc_branches[i].query(' and '.join([selection['lowq2'], '(xgb > @cut)', selection['Dmass']])).shape[0]) / float(nonresonant_mc_branches[i].query(selection['lowq2']).shape[0]) for i in nparts]) + #eff_lowq2_bdt = np.mean([float(nonresonant_mc_branches[i].query(' and '.join([selection['lowq2'], selection['hlt'], '(xgb > @cut)', selection['Dmass']])).shape[0]) / float(nonresonant_mc_branches[i].query(selection['lowq2']).shape[0]) for i in nparts]) expected_signal = rk_electron * n_data_jpsi * eff['lowq2_presel'] * eff['lowq2_q2'] * eff_lowq2_bdt / (eff['jpsi_presel'] * eff['jpsi_q2'] * eff['jpsi_bdt']) if num_mctoys is not None: com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --number_of_mctoys={6} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) else: - #com = 'python KEE_lowq2_roofit_plb_pull_modified.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) com = 'python KEE_lowq2_roofit_plb_pull_modified_kde.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --ikstaree={4} --sel_primitive="sgn,bkg_kjpsi,bkg_kstaree" --fit_primitive --mvacut={5} --set_expected_sgn={6} --log={8}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], info[eleType]['ikstaree'], cut, expected_signal, num_mctoys, log) + #com = 'python KEE_lowq2_roofit_plb_pull_modified_kde.py -i {0} -o lowq2_{1} --isgn={2} --ikjpsi={3} --sel_primitive="sgn,bkg_kjpsi" --fit_primitive --mvacut={4} --set_expected_sgn={5} --log={7}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['ikjpsi'], cut, expected_signal, num_mctoys, log) os.system(com) print('cut: {} \n \t expected signal: {} \n \t lowq2 bdt eff: {}'.format(cut, expected_signal, eff_lowq2_bdt)) + print('\t {}, {}'.format(eff['lowq2_presel'], eff['lowq2_q2'])) + print('\t overall eff: {}'.format(eff['lowq2_presel'] * eff['lowq2_q2'] * eff_lowq2_bdt)) for key, value in eff.items(): print('{}: {}'.format(key, value)) diff --git a/fit/run_fit_KJpsi_fixedPartial.py b/fit/run_fit_KJpsi_fixedPartial.py index 1c7611f..2a5fcbf 100644 --- a/fit/run_fit_KJpsi_fixedPartial.py +++ b/fit/run_fit_KJpsi_fixedPartial.py @@ -36,31 +36,60 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'mix' - log = 'log_jpsi_bparkPU_v7.3_{}.csv'.format(eleType) + log = 'log_jpsi_bparkPU_v7.3_{}_nonreg_floating_mean_tightWP_fixedpartial.csv'.format(eleType) info = defaultdict(dict) - br_b2jpsi = 1.02e-3 + br_b2kjpsi = 1.02e-3 br_b2kstarjpsi = 1.27e-3 * 2./3. + br_b2kstarplusjpsi = 1.43e-3 nparts = range(8) - info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' - info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCres.root'.format('marker') - info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') - info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' - info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' - info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' - #info['pf']['iKstarPlusJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarplusjpsi_kee.root' - info['pf']['n_mc_jpsi'] = 563421.0 - info['pf']['n_mc_partial'] = 373882.0 - - info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' - info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCres.root'.format('marker') - info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarjpsi.root'.format('marker') - info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' - info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' - info['mix']['n_mc_jpsi'] = 563421.0 - info['mix']['n_mc_partial'] = 373882.0 + # PF-PF + #info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' + #info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCres.root'.format('marker') + #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') + #info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' + #info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' + #info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' + ##info['pf']['iKstarPlusJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarplusjpsi_kee.root' + #info['pf']['n_mc_jpsi'] = 563421.0 + #info['pf']['n_mc_partial'] = 373882.0 + + # PF-LP + #info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' + #info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCres.root'.format('marker') + #info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarjpsi.root'.format('marker') + #info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' + #info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' + #info['mix']['n_mc_jpsi'] = 563421.0 + #info['mix']['n_mc_partial'] = 373882.0 + + # PF-PF nonreg + info['pf']['inputfile'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_data_mvaCut0.root' + info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MCres.root'.format('marker') + info['pf']['partial_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MC_kstarjpsi.root'.format('marker') + info['pf']['kstarplus_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MC_kstarplusjpsi.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MCres.root' + info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_kstarjpsi.root' + info['pf']['iKstarPlusJpsi_BKG'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_kstarplusjpsi.root' + info['pf']['n_mc_jpsi'] = 211912.0 + info['pf']['n_mc_partial'] = 379086.0 + info['pf']['n_mc_kstarplus'] = 314672.0 + info['pf']['ibkg'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_samesign_mvaCut0.root' + + # PF-LP + info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_data_mvaCut0.root' + info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MCres.root'.format('marker') + info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MC_kstarjpsi.root'.format('marker') + info['mix']['kstarplus_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MC_kstarplusjpsi.root'.format('marker') + info['mix']['isgn'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MCres.root' + info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_kstarjpsi.root' + info['mix']['iKstarPlusJpsi_BKG'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_kstarplusjpsi.root' + info['mix']['n_mc_jpsi'] = 211912.0 + info['mix']['n_mc_partial'] = 379086.0 + info['mix']['n_mc_kstarplus'] = 314672.0 + info['mix']['ibkg'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_samesign_mvaCut0.root' selection = {} @@ -72,27 +101,47 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): jpsi_mc_branches = [get_df(info[eleType]['jpsi_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] partial_mc_branches = [get_df(info[eleType]['partial_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] + kstarplus_mc_branches = [get_df(info[eleType]['kstarplus_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] if eleType == 'pf': - mvaCut = np.linspace(4.0, 6.0, 11) - #mvaCut = np.array([5.0, ]) + #mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.linspace(8.0, 8.7, 8) + mvaCut = np.array([8.3, ]) else: - mvaCut = np.linspace(4.0, 6.0, 11) - #mvaCut = np.array([8.0, ]) + #mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.linspace(8.3, 9.0, 8) + mvaCut = np.array([8.6, ]) for cut in mvaCut: eff_sig_bdt = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_jpsi'] for i in nparts]) eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) + eff_kstarplus_bdt = np.mean([float(kstarplus_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_kstarplus'] for i in nparts]) - frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarjpsi / br_b2jpsi) + frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarjpsi / br_b2kjpsi) + #frac_ratio_kstarplus = (eff_kstarplus_bdt / eff_sig_bdt) * (br_b2kstarplusjpsi / br_b2kjpsi) + frac_ratio_kstarplus = (eff_kstarplus_bdt / eff_partial_bdt) * (br_b2kstarplusjpsi / br_b2kstarjpsi) + total_ratio = ((eff_partial_bdt + eff_kstarplus_bdt) / eff_sig_bdt) * ((br_b2kstarjpsi + br_b2kstarplusjpsi) / br_b2kjpsi) + + print(frac_ratio, frac_ratio_kstarplus) + #print(total_ratio) if eleType == 'pf': - com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + # fixed partial ratio #com = 'python KJpsi_roofit_plb_modified_kde_kstarPlus.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + # not fixing partial ratio + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + + # without same-sign + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --sel_primitive="sgn,bkg_kstarjpsi" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], frac_ratio, cut, log) + else: - com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --sel_primitive="sgn,bkg_kstarjpsi" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], frac_ratio, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --sel_primitive="sgn,bkg_kstarjpsi" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], frac_ratio, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + os.system(com) diff --git a/fit/run_fit_KPsi2S_fixedPartial.py b/fit/run_fit_KPsi2S_fixedPartial.py index 70ba0ed..bfa3f8c 100644 --- a/fit/run_fit_KPsi2S_fixedPartial.py +++ b/fit/run_fit_KPsi2S_fixedPartial.py @@ -36,39 +36,72 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'mix' - log = 'log_psi2s_bparkPU_v7.3_{}.csv'.format(eleType) + log = 'log_psi2s_bparkPU_v7.3_{}_nonreg_tightWP_fixedpartial.csv'.format(eleType) info = defaultdict(dict) - br_b2psi2s = 6.24e-4 + br_b2kpsi2s = 6.24e-4 br_b2kstarpsi2s = 5.9e-4 * 2./3. + br_b2kstarpluspsi2s = 6.7e-4 br_b2kstarjpsi = 1.27e-3 * 2./3. br_psi2s2ee = 7.93e-3 br_jpsi2ee = 0.05971 nparts = range(8) - info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' - info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCPsi2S.root'.format('marker') - info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarpsi2s.root'.format('marker') - #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') - info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCPsi2S.root' - info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' - info['pf']['iKstarPsi2S_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarpsi2s.root' - info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' - info['pf']['iKJpsiee_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' - info['pf']['n_mc_psi2s'] = 483443.0 - info['pf']['n_mc_partial'] = 439520.0 - #info['pf']['n_mc_partial'] = 373882.0 - - info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' - info['mix']['psi2s_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCPsi2S.root'.format('marker') - info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarpsi2s.root'.format('marker') - info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCPsi2S.root' - info['mix']['iKstarPsi2S_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarpsi2s.root' - info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' - info['mix']['iKJpsiee_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' - info['mix']['n_mc_psi2s'] = 483443.0 - info['mix']['n_mc_partial'] = 439520.0 + # PF-PF + #info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' + #info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCPsi2S.root'.format('marker') + #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarpsi2s.root'.format('marker') + ##info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') + #info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCPsi2S.root' + #info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' + #info['pf']['iKstarPsi2S_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarpsi2s.root' + #info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' + #info['pf']['iKJpsiee_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' + #info['pf']['n_mc_psi2s'] = 483443.0 + #info['pf']['n_mc_partial'] = 439520.0 + ##info['pf']['n_mc_partial'] = 373882.0 + + # PF-LP + #info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' + #info['mix']['psi2s_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCPsi2S.root'.format('marker') + #info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarpsi2s.root'.format('marker') + #info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCPsi2S.root' + #info['mix']['iKstarPsi2S_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarpsi2s.root' + #info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' + #info['mix']['iKJpsiee_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' + #info['mix']['n_mc_psi2s'] = 483443.0 + #info['mix']['n_mc_partial'] = 439520.0 + + # PF-PF nonreg + info['pf']['inputfile'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_data_mvaCut0.root' + info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MCPsi2S.root'.format('marker') + info['pf']['partial_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MC_kstarpsi2s.root'.format('marker') + info['pf']['kstarplus_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MC_kstarpluspsi2s.root'.format('marker') + info['pf']['isgn'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MCPsi2S.root' + info['pf']['iKstarPsi2S_BKG'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_kstarpsi2s.root' + info['pf']['iKstarPlusPsi2S_BKG'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_kstarpluspsi2s.root' + info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_kstarjpsi.root' + info['pf']['iKJpsiee_BKG'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MCres.root' + info['pf']['n_mc_psi2s'] = 180840.0 + info['pf']['n_mc_partial'] = 443318.0 + info['pf']['n_mc_kstarplus'] = 395456.0 + info['pf']['ibkg'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_samesign_mvaCut0.root' + + # PF-LP nonreg + info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_data_mvaCut0.root' + info['mix']['psi2s_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MCPsi2S.root'.format('marker') + info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MC_kstarpsi2s.root'.format('marker') + info['mix']['kstarplus_mc'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_{}_MC_kstarpluspsi2s.root'.format('marker') + info['mix']['isgn'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MCPsi2S.root' + info['mix']['iKstarPsi2S_BKG'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_kstarpsi2s.root' + info['mix']['iKstarPlusPsi2S_BKG'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_kstarpluspsi2s.root' + info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_kstarjpsi.root' + info['mix']['iKJpsiee_BKG'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MCres.root' + info['mix']['n_mc_psi2s'] = 180840.0 + info['mix']['n_mc_partial'] = 443318.0 + info['mix']['n_mc_kstarplus'] = 395456.0 + info['mix']['ibkg'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_samesign_mvaCut0.root' selection = {} @@ -80,27 +113,40 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): psi2s_mc_branches = [get_df(info[eleType]['psi2s_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] partial_mc_branches = [get_df(info[eleType]['partial_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] + kstarplus_mc_branches = [get_df(info[eleType]['kstarplus_mc'].replace('marker', str(i)), branches=mc_branches) for i in nparts] if eleType == 'pf': - mvaCut = np.linspace(4.0, 6.0, 11) - #mvaCut = np.array([5.0,]) + #mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.linspace(8.0, 8.7, 8) + mvaCut = np.array([8.3,]) else: - mvaCut = np.linspace(6.0, 8.0, 11) - #mvaCut = np.array([7.0,]) + #mvaCut = np.linspace(4.0, 6.0, 11) + #mvaCut = np.linspace(8.3, 9.0, 8) + mvaCut = np.array([8.6,]) for cut in mvaCut: eff_sig_bdt = np.mean([float(psi2s_mc_branches[i].query(' and '.join([selection['psi2s'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_psi2s'] for i in nparts]) eff_partial_bdt = np.mean([float(partial_mc_branches[i].query(' and '.join([selection['psi2s'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_partial'] for i in nparts]) + eff_kstarplus_bdt = np.mean([float(kstarplus_mc_branches[i].query(' and '.join([selection['psi2s'], selection['Dmass'], '(xgb > @cut)'])).shape[0]) / info[eleType]['n_mc_kstarplus'] for i in nparts]) - #frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarpsi2s / br_b2psi2s) - frac_ratio = (eff_partial_bdt / eff_sig_bdt) * ((br_b2kstarjpsi*br_jpsi2ee) / (br_b2psi2s*br_psi2s2ee)) - print(frac_ratio, eff_partial_bdt, eff_sig_bdt) + frac_ratio = (eff_partial_bdt / eff_sig_bdt) * (br_b2kstarpsi2s / br_b2kpsi2s) + #frac_ratio = (eff_partial_bdt / eff_sig_bdt) * ((br_b2kstarjpsi*br_jpsi2ee) / (br_b2psi2s*br_psi2s2ee)) + #frac_ratio_kstarplus = (eff_kstarplus_bdt / eff_sig_bdt) * (br_b2kstarpluspsi2s / br_b2kpsi2s) + frac_ratio_kstarplus = (eff_kstarplus_bdt / eff_partial_bdt) * (br_b2kstarpluspsi2s / br_b2kstarpsi2s) + + print(frac_ratio, frac_ratio_kstarplus, eff_partial_bdt, eff_kstarplus_bdt, eff_sig_bdt) if eleType == 'pf': - com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], frac_ratio, cut, log) + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + else: - com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], frac_ratio, cut, log) + #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], frac_ratio, cut, log) + #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + os.system(com) From 0b0414ecfc778cf4d8b3cdd7cb69c977ca6ac7e1 Mon Sep 17 00:00:00 2001 From: ottolau Date: Thu, 28 Apr 2022 20:48:30 +0200 Subject: [PATCH 10/13] updated version --- fit/KEE_lowq2_roofit_plb_pull_modified_kde.py | 24 ++++++-- ...si_roofit_plb_modified_kde_fixedPartial.py | 32 +++++++--- ...2S_roofit_plb_modified_kde_fixedPartial.py | 29 ++++++--- fit/roofit_helper.py | 59 +++++++++++++++++++ fit/run_fit_KEE_lowq2_bparkPU.py | 12 ++-- fit/run_fit_KJpsi_fixedPartial.py | 4 +- fit/run_fit_KPsi2S_fixedPartial.py | 4 +- 7 files changed, 133 insertions(+), 31 deletions(-) diff --git a/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py b/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py index 8bca99a..770dd06 100644 --- a/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py +++ b/fit/KEE_lowq2_roofit_plb_pull_modified_kde.py @@ -133,7 +133,10 @@ def signal_fit(tree, outputfile, branches): print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(sgnframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() c1.SaveAs('sgn_eek_'+outputfile+'.pdf') residuals(sgnframe,theBMass,'sgn_eek_'+outputfile) @@ -157,7 +160,10 @@ def kjpsi_fit(tree, outputfile, branches): kjpframe=theBMass.frame() dataset.plotOn(kjpframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) ekjpsi.plotOn(kjpframe,RooFit.Name("ekjpsi"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - c1=canvas_create(kjpframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(kjpframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(kjpframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() c1.SaveAs('bkg_jpsik_'+outputfile+'.pdf') residuals(kjpframe,theBMass,'bkg_jpsik_'+outputfile) @@ -186,7 +192,10 @@ def bkg_fit(tree, outputfile, branches): dataset.plotOn(bkgframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) ebkg.plotOn(bkgframe,RooFit.Name("ebkg"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) params=ebkg.getParameters(ROOT.RooArgSet(bMass)) - c1=canvas_create(bkgframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + #c1=canvas_create(bkgframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + c1, top, bottom =canvas_create_pull(bkgframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() c1.SaveAs('bkg_comb_'+outputfile+'.pdf') n_param = results.floatParsFinal().getSize() @@ -212,7 +221,10 @@ def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): #wspace.Write() #wf.Close() - c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(kde_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_kde_'+outputfile+'_{}.pdf'.format(pdfname)) @@ -326,7 +338,9 @@ def total_fit(tree, outputfile, branches, sgn_parameters=None, kjpsi_pdf=None, k n_param = results.floatParsFinal().getSize() print "chi2",xframe.chiSquare(n_param),"ndof",n_param print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + #c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + c1, top, bottom =canvas_create_pull(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() legend = ROOT.TLegend(0.65,0.65,0.92,0.85) legend.AddEntry(xframe.findObject("bkg"),"Combinatorial","l"); diff --git a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py index 5dfecd7..afdd894 100644 --- a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py @@ -95,7 +95,10 @@ def signal_fit(tree, outputfile, branches, SavePlot=True): print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(sgnframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('sgn_eek_'+outputfile+'.pdf') @@ -122,7 +125,10 @@ def otherB_fit(tree, outputfile, branches, SavePlot=True): otherb_frame=theBMass.frame() dataset.plotOn(otherb_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) eexp_otherb.plotOn(otherb_frame,RooFit.Name("eexpOB"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - c1=canvas_create(otherb_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(otherb_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(otherb_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_otherB_'+outputfile+'.pdf') @@ -149,7 +155,10 @@ def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): #wspace.Write() #wf.Close() - c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(kde_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_kde_'+outputfile+'_{}.pdf'.format(pdfname)) @@ -174,7 +183,10 @@ def bkg_fit(tree, outputfile, branches, SavePlot=True): dataset.plotOn(combframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) eexp_comb.plotOn(combframe,RooFit.Name("eexp_comb"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) params=eexp_comb.getParameters(ROOT.RooArgSet(bMass)) - c1=canvas_create(combframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + #c1=canvas_create(combframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + c1, top, bottom =canvas_create_pull(combframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_comb_'+outputfile+'.pdf') @@ -253,14 +265,14 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame (wspace.var(par)).setConstant(True) for par in otherB_parameters.keys(): (wspace.var(par)).setVal(otherB_parameters[par]) - #(wspace.var(par)).setConstant(True) + (wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) (wspace.var(par)).setConstant(True) if partial_ratio is not None: wspace.var('frac_partial').setVal(partial_ratio) - wspace.var('frac_partial').setConstant(True) + #wspace.var('frac_partial').setConstant(True) if partial_ratio_kstarplus is not None: wspace.var('frac_kstarplus').setVal(partial_ratio_kstarplus) @@ -307,8 +319,11 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame n_param = results.floatParsFinal().getSize() print "chi2",xframe.chiSquare(n_param),"ndof",n_param print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + + #c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + c1, top, bottom =canvas_create_pull(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() legend = ROOT.TLegend(0.65,0.65,0.92,0.85) legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); @@ -325,12 +340,13 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame CMS_lumi() c1.cd() c1.Update() + c1.SaveAs('total_fit_'+outputfile+'.pdf') print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-", nKstarJpsi_visible_err, "K*+ J/psi", nKstarPlusJpsi_visible, "+/-", nKstarPlusJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err residuals(xframe,theBMass,outputfile+"_poutana") - saveWS = True + saveWS = False if saveWS: # get likelihood diff --git a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py index 9ecd4dc..0ce8cfd 100644 --- a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py @@ -94,7 +94,10 @@ def signal_fit(tree, outputfile, branches, SavePlot=True): print "chi2",sgnframe.chiSquare(n_param),"ndof",n_param print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(sgnframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(sgnframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('sgn_eek_'+outputfile+'.pdf') @@ -122,7 +125,10 @@ def otherB_fit(tree, outputfile, branches, SavePlot=True): otherb_frame=theBMass.frame() dataset.plotOn(otherb_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) eexp_otherb.plotOn(otherb_frame,RooFit.Name("eexpOB"),RooFit.LineColor(30),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - c1=canvas_create(otherb_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(otherb_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(otherb_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_otherB_'+outputfile+'.pdf') @@ -151,7 +157,10 @@ def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): #wspace.Write() #wf.Close() - c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + #c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') + c1, top, bottom =canvas_create_pull(kde_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_kde_'+outputfile+'_{}.pdf'.format(pdfname)) @@ -175,7 +184,10 @@ def bkg_fit(tree, outputfile, branches, SavePlot=True): dataset.plotOn(combframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) eexp_comb.plotOn(combframe,RooFit.Name("eexp_comb"), RooFit.LineColor(49),RooFit.Normalization(1.0, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) params=eexp_comb.getParameters(ROOT.RooArgSet(bMass)) - c1=canvas_create(combframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + #c1=canvas_create(combframe,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV]') + c1, top, bottom =canvas_create_pull(combframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + CMS_lumi() if SavePlot: c1.SaveAs('bkg_comb_'+outputfile+'.pdf') @@ -276,7 +288,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if partial_ratio is not None: wspace.var('frac_partial').setVal(partial_ratio) - wspace.var('frac_partial').setConstant(True) + #wspace.var('frac_partial').setConstant(True) if partial_ratio_kstarplus is not None: wspace.var('frac_kstarplus').setVal(partial_ratio_kstarplus) @@ -336,7 +348,10 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame n_param = results.floatParsFinal().getSize() print "chi2",xframe.chiSquare(n_param),"ndof",n_param print "edm",results.edm(),"log",results.minNll() - c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + #c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') + c1, top, bottom =canvas_create_pull(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + top.cd() + legend = ROOT.TLegend(0.65,0.65,0.92,0.85) legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); @@ -361,7 +376,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* Psi2S", nKstarPsi2S_visible, "+/-",nKstarPsi2S_visible_err,"K*+ Psi2S", nKstarPlusPsi2S_visible, "+/-",nKstarPlusPsi2S_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err, "K J/psi", nKJpsi_visible, "+/-", nKJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err residuals(xframe,theBMass,outputfile+"_poutana") - saveWS = True + saveWS = False if saveWS: # get likelihood ''' diff --git a/fit/roofit_helper.py b/fit/roofit_helper.py index 4161953..0e3d332 100644 --- a/fit/roofit_helper.py +++ b/fit/roofit_helper.py @@ -47,6 +47,65 @@ def canvas_create(xframe,xmin,xmax,nbin,xtitle,boundYto0=True): xframe.Draw() return c2 +def canvas_create_pull(xframe,xmin,xmax,nbin,xtitle,var,boundYto0=True): + c2 = rt.TCanvas('fig_binnedFit', 'fit', 800, 800) + c2.cd() + c2.SetGrid() + top = rt.TPad("top", "top", 0., 0.25, 1., 1.) + top.SetGrid() + top.SetLeftMargin(0.12) + top.SetRightMargin(0.05) + top.SetBottomMargin(0.0) + top.Draw() + top.cd() + #xframe.GetYaxis().SetTitle("Events / {0:.0f} MeV".format((xmax - xmin)/nbin*1000.)) + #xframe.GetXaxis().SetTitle(xtitle) + xframe.SetStats(0) + if (boundYto0): xframe.SetMinimum(0) + xframe.GetYaxis().SetLabelSize(0.045) + xframe.GetYaxis().SetLabelOffset(0.007) + xframe.GetYaxis().SetTitleSize(0.06) + xframe.GetYaxis().SetTitleOffset(0.90) + xframe.GetXaxis().SetLabelSize(0.045) + xframe.GetXaxis().SetLabelOffset(0.007) + xframe.GetXaxis().SetTitleSize(0.06) + xframe.GetXaxis().SetTitleOffset(0.95) + xframe.SetTitle("") + xframe.Draw() + + hpull = xframe.pullHist() + xframe3 = var.frame() + xframe3.addPlotable(hpull,"P") + + scale = 3.0 + c2.cd() + bottom = rt.TPad("bottom", "bottom", 0., 0., 1., 0.25) + bottom.SetGrid() + bottom.SetLeftMargin(0.12) + bottom.SetRightMargin(0.05) + bottom.SetBottomMargin(0.4) + bottom.SetTopMargin(0.03) + bottom.Draw() + bottom.cd() + xframe3.GetXaxis().SetTitle(xtitle) + xframe3.SetStats(0) + xframe3.GetYaxis().SetLabelSize(0.045*scale) + xframe3.GetYaxis().SetLabelOffset(0.007) + xframe3.GetYaxis().SetTitleSize(0.06*scale) + xframe3.GetYaxis().SetTitleOffset(0.90/scale) + xframe3.GetXaxis().SetLabelSize(0.045*scale) + xframe3.GetXaxis().SetLabelOffset(0.007) + xframe3.GetXaxis().SetTitleSize(0.06*scale) + xframe3.GetXaxis().SetTitleOffset(0.95) + xframe3.SetTitle("") + xframe3.GetYaxis().SetTitle("Pull") + xframe3.SetMinimum(-3.5) + xframe3.SetMaximum(3.5) + + xframe3.Draw() + + return c2, top, bottom + def pt_create(mva,nsig,nsigError,nbkg): pt = rt.TPaveText(0.72,0.37,0.92,0.63,"brNDC") pt.SetFillColor(0) diff --git a/fit/run_fit_KEE_lowq2_bparkPU.py b/fit/run_fit_KEE_lowq2_bparkPU.py index ed4e8b3..ec88c96 100644 --- a/fit/run_fit_KEE_lowq2_bparkPU.py +++ b/fit/run_fit_KEE_lowq2_bparkPU.py @@ -35,7 +35,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): return df if __name__ == "__main__": - eleType = 'mix' + eleType = 'pf' log = 'log_kee_bparkPU_v7.3_{}_nonreg.csv'.format(eleType) info = defaultdict(dict) @@ -90,8 +90,6 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['isgn'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC.root' info['pf']['ikjpsi'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MCres.root' info['pf']['ikstaree'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstaree.root' - #info['pf']['jpsi_mva_wp'] = 4.8 - #info['pf']['n_data_jpsi'] = 7951.28 info['pf']['jpsi_mva_wp'] = 8.3 info['pf']['n_data_jpsi'] = 4779.12 info['pf']['n_mc_jpsi'] = 211912.0 @@ -144,11 +142,11 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): #eff['jpsi_bdt'] = np.mean([float(jpsi_mc_branches[i].query(' and '.join([selection['jpsi'], selection['Dmass'], selection['hlt'], '(xgb > {})'.format(jpsi_mva_wp)])).shape[0]) / float(jpsi_mc_branches[i].query(selection['jpsi']).shape[0]) for i in nparts]) if eleType == 'pf': - mvaCut = np.linspace(8.0, 8.7, 8) - #mvaCut = np.array([8.8, ]) + #mvaCut = np.linspace(8.0, 8.7, 8) + mvaCut = np.array([8.3, ]) else: - mvaCut = np.linspace(8.3, 9.0, 8) - #mvaCut = np.array([9.0, ]) + #mvaCut = np.linspace(8.3, 9.0, 8) + mvaCut = np.array([8.6, ]) for cut in mvaCut: eff_lowq2_bdt = np.mean([float(nonresonant_mc_branches[i].query(' and '.join([selection['lowq2'], '(xgb > @cut)', selection['Dmass']])).shape[0]) / float(nonresonant_mc_branches[i].query(selection['lowq2']).shape[0]) for i in nparts]) diff --git a/fit/run_fit_KJpsi_fixedPartial.py b/fit/run_fit_KJpsi_fixedPartial.py index 2a5fcbf..21f19dd 100644 --- a/fit/run_fit_KJpsi_fixedPartial.py +++ b/fit/run_fit_KJpsi_fixedPartial.py @@ -35,8 +35,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): return df if __name__ == "__main__": - eleType = 'mix' - log = 'log_jpsi_bparkPU_v7.3_{}_nonreg_floating_mean_tightWP_fixedpartial.csv'.format(eleType) + eleType = 'pf' + log = 'log_jpsi_bparkPU_v7.3_{}_nonreg_floating_mean_tightWP.csv'.format(eleType) info = defaultdict(dict) br_b2kjpsi = 1.02e-3 diff --git a/fit/run_fit_KPsi2S_fixedPartial.py b/fit/run_fit_KPsi2S_fixedPartial.py index bfa3f8c..ec3f662 100644 --- a/fit/run_fit_KPsi2S_fixedPartial.py +++ b/fit/run_fit_KPsi2S_fixedPartial.py @@ -35,8 +35,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): return df if __name__ == "__main__": - eleType = 'mix' - log = 'log_psi2s_bparkPU_v7.3_{}_nonreg_tightWP_fixedpartial.csv'.format(eleType) + eleType = 'pf' + log = 'log_psi2s_bparkPU_v7.3_{}_nonreg_tightWP.csv'.format(eleType) info = defaultdict(dict) br_b2kpsi2s = 6.24e-4 From 6b4b93c6a7865cc22f9144f1f9cb2721e58f778a Mon Sep 17 00:00:00 2001 From: ottolau Date: Wed, 11 May 2022 23:15:46 +0200 Subject: [PATCH 11/13] included latest likelihood fits for R_psi(2S) and R_J/psi --- ...likelihood_rjpsi_combinedEleCh_effRatio.py | 218 +++++++++++++++++ measurement/maximum_likelihood_rpsi2s.py | 14 +- ...maximum_likelihood_rpsi2s_combinedEleCh.py | 124 ++++++---- .../maximum_likelihood_singleChannel.py | 31 ++- ..._likelihood_singleChannel_combinedEleCh.py | 196 ++++++++++++++++ ...ingle_ratio_rpsi_combinedEleCh_effRatio.py | 221 ++++++++++++++++++ measurement/roofit_models.py | 74 ++++++ measurement/utils_likelihood.py | 16 +- 8 files changed, 834 insertions(+), 60 deletions(-) create mode 100644 measurement/maximum_likelihood_rjpsi_combinedEleCh_effRatio.py create mode 100644 measurement/maximum_likelihood_singleChannel_combinedEleCh.py create mode 100644 measurement/maximum_likelihood_single_ratio_rpsi_combinedEleCh_effRatio.py create mode 100644 measurement/roofit_models.py diff --git a/measurement/maximum_likelihood_rjpsi_combinedEleCh_effRatio.py b/measurement/maximum_likelihood_rjpsi_combinedEleCh_effRatio.py new file mode 100644 index 0000000..381d2fb --- /dev/null +++ b/measurement/maximum_likelihood_rjpsi_combinedEleCh_effRatio.py @@ -0,0 +1,218 @@ +import os,sys,re +import time +from time import sleep +import math +from uncertainties import ufloat +import ROOT as rt +import ROOT +from ROOT import RooFit +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +from roofit_models import root_function_RightSidedCB +ROOT.gInterpreter.Declare(root_function_RightSidedCB) +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace + +def createWorkspace(wsname, wsfilename, + wsfilename_pfe_jpsi, + wsfilename_mixe_jpsi, + wsfilename_mu_jpsi, + eff_pfe_to_mu_jpsi=0.0, deff_pfe_to_mu_jpsi=0.0, + eff_mixe_to_mu_jpsi=0.0, deff_mixe_to_mu_jpsi=0.0, + ): + + wspace = rt.RooWorkspace(wsname) + wspace = importWorkspace(wspace, wsfilename_pfe_jpsi, 'pfe_jpsi') + wspace = importWorkspace(wspace, wsfilename_mixe_jpsi, 'mixe_jpsi') + wspace = importWorkspace(wspace, wsfilename_mu_jpsi, 'mu_jpsi') + + wspace.factory('cat[pfe_jpsi,mixe_jpsi,mu_jpsi]') + x = wspace.var("x") + data = rt.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), + RooFit.Import('pfe_jpsi', wspace.data('data_pfe_jpsi')), + RooFit.Import('mixe_jpsi', wspace.data('data_mixe_jpsi')), + RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), + ) + getattr(wspace, 'import')(data, rt.RooCmdArg()) + + br_jpsi_ee, dbr_jpsi_ee= 0.05971, 0.00032 + br_psi2s_ee, dbr_psi2s_ee = 7.93e-3, 0.17e-3 + br_jpsi_mumu, dbr_jpsi_mumu= 0.05961, 0.00033 + br_psi2s_mumu, dbr_psi2s_mumu = 8.0e-3, 0.6e-3 + r_br, dr_br = 0.6117647, 0.022678 + + ### Create parameters + # observations + params = [ + # efficiency of PF-PF electron J/psi channel estimate + ('eff_hat_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, 1.e-6, 1), + ('deff_pfe_to_mu_jpsi', deff_pfe_to_mu_jpsi, 1.e-6, 1), + # efficiency of PF-LP electron J/psi channel estimate + ('eff_hat_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, 1.e-6, 1), + ('deff_mixe_to_mu_jpsi', deff_mixe_to_mu_jpsi, 1.e-6, 1), + # nuisance parameters + #('eff_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi-5.0*deff_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi+5.0*deff_pfe_to_mu_jpsi), + #('eff_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi-5.0*deff_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi+5.0*deff_mixe_to_mu_jpsi), + ('eff_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi-5.0*deff_pfe_to_mu_jpsi, 1), + ('eff_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi-5.0*deff_mixe_to_mu_jpsi, 1), + ('n_mu_jpsi', 7.7399e+05, 0, 10000000), + # parameter of interest + ('R', 1.00, 0.5, 1.5), + ] + + for t in params: + cmd = '%s[%f, %f, %f]' % t + wspace.factory(cmd) + wspace.var('R').SetTitle('R') + + # fix all background and signal parameters + for t in params[0:-4]: + name = t[0] + print '=> make %8s = %5.5f constant' % (name, + wspace.var(name).getVal()) + wspace.var(name).setConstant() + + wspace.var('ncomb_mixe_jpsi').setConstant() + wspace.var('ncomb_pfe_jpsi').setConstant() + wspace.var('ncomb_mu_jpsi').setConstant() + #wspace.var('notherB_pfe_jpsi').setConstant() + #wspace.var('notherB_mixe_jpsi').setConstant() + + + ### Create expressions + express = [ + # PF-PF electron + 'n_pfe_jpsi("(n_mu_jpsi/R)*(eff_pfe_to_mu_jpsi)", n_mu_jpsi, R, eff_pfe_to_mu_jpsi)', + 'nKstarJpsi_pfe_jpsi_modified("frac_partial_pfe_jpsi*n_pfe_jpsi", frac_partial_pfe_jpsi, n_pfe_jpsi)', + 'nKstarPlusJpsi_pfe_jpsi_modified("frac_kstarplus_pfe_jpsi*nKstarJpsi_pfe_jpsi_modified", frac_kstarplus_pfe_jpsi, nKstarJpsi_pfe_jpsi_modified)', + # PF-LP electron + 'n_mixe_jpsi("(n_mu_jpsi/R)*(eff_mixe_to_mu_jpsi)", n_mu_jpsi, R, eff_mixe_to_mu_jpsi)', + 'nKstarJpsi_mixe_jpsi_modified("frac_partial_mixe_jpsi*n_mixe_jpsi", frac_partial_mixe_jpsi, n_mixe_jpsi)', + 'nKstarPlusJpsi_mixe_jpsi_modified("frac_kstarplus_mixe_jpsi*nKstarJpsi_mixe_jpsi_modified", frac_kstarplus_mixe_jpsi, nKstarJpsi_mixe_jpsi_modified)', + ] + + for t in express: + cmd = 'expr::%s' % t + wspace.factory(cmd) + + edit = [ + # PF-PF electron + 'model_pfe_jpsi_modified(model_pfe_jpsi, nsignal_pfe_jpsi=n_pfe_jpsi, nKstarJpsi_pfe_jpsi=nKstarJpsi_pfe_jpsi_modified, nKstarPlusJpsi_pfe_jpsi=nKstarPlusJpsi_pfe_jpsi_modified)', + # PF-LP electron + 'model_mixe_jpsi_modified(model_mixe_jpsi, nsignal_mixe_jpsi=n_mixe_jpsi, nKstarJpsi_mixe_jpsi=nKstarJpsi_mixe_jpsi_modified, nKstarPlusJpsi_mixe_jpsi=nKstarPlusJpsi_mixe_jpsi_modified)', + # muon + 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi)', + ] + + for t in edit: + cmd = 'EDIT::%s' % t + wspace.factory(cmd) + + wspace.Print("V") + ### Create pdfs + pdfs = [ + # PF-PF electron + ('Gaussian','peff_pfe_to_mu_jpsi', '(eff_hat_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi, deff_pfe_to_mu_jpsi)'), + # PF-LP electron + ('Gaussian','peff_mixe_to_mu_jpsi', '(eff_hat_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi, deff_mixe_to_mu_jpsi)'), + ] + + prodpdf = '' + for t in pdfs: + wspace.factory('%s::%s%s' % t) + name = t[1] + prodpdf += "%s, " % name + prodpdf = prodpdf[:-2] # remove last ", " + + + # multiply the pdfs together. use upper case PROD to + # do this + wspace.factory("SIMUL:jointModel(cat,pfe_jpsi=model_pfe_jpsi_modified,mixe_jpsi=model_mixe_jpsi_modified,mu_jpsi=model_mu_jpsi_modified)") + wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) + + nuis_excluded = ['x', 'R', 'cat', + 'deff_pfe_to_mu_jpsi', 'eff_hat_pfe_to_mu_jpsi', + 'deff_mixe_to_mu_jpsi', 'eff_hat_mixe_to_mu_jpsi', + ] + + ### Define global observables + ### they are not being fitted and they are not loaded from a dataset, + ### but some knowledge exists that allows to set them to a specific value + ### Global Observables are generated once per toy + #globs = ['eff_pfe_to_mu_jpsi', 'eff_mixe_to_mu_jpsi' + globs = ['eff_hat_pfe_to_mu_jpsi', 'eff_hat_mixe_to_mu_jpsi' + ] + + nuis = [] + params = wspace.pdf('model').getVariables() + params_iter = params.createIterator() + param = params_iter.Next() + while param : + if param.GetName() not in (nuis_excluded+globs): + nuis.append(param.GetName()) + param = params_iter.Next() + nuis = ','.join(nuis) + globs = ','.join(globs) + + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis), + ('globs', globs), + ] # nuisance parameters (leave no spaces) + #('nuis', 'n_pfe_jpsi,eff_pfe_psi2s,eff_pfe_jpsi')] # nuisance parameters (leave no spaces) + + for t in sets: + name, parlist = t + wspace.defineSet(name, parlist) + + + #----------------------------------------------------- + # Create model configuration. This is needed for the + # statistical analyses + #----------------------------------------------------- + cfg = rt.RooStats.ModelConfig('cfg') + cfg.SetWorkspace(wspace) + cfg.SetPdf(wspace.pdf('model')) + cfg.SetParametersOfInterest(wspace.set('poi')) + cfg.SetNuisanceParameters(wspace.set('nuis')) + #cfg.SetGlobalObservables(wspace.set('globs')) + + # import model configuration into workspace + getattr(wspace, 'import')(cfg) + + wspace.Print() + + # write out workspace + wspace.writeToFile(wsfilename) + + +if __name__ == "__main__": + + eff_pfe_jpsi, deff_pfe_jpsi = 5.3779e-6, 2.90e-7 + eff_mixe_jpsi, deff_mixe_jpsi = 2.3538e-6, 1.28e-7 + eff_mu_jpsi, deff_mu_jpsi = 12.69e-4, 0.1e-4 + R_SM = 1.0 + R_min, R_max = 0.88, 1.2 + xlabel = 'R_{J/#psi}' + + wsfilename_pfe_jpsi = 'wspace_jpsi_fixedPartial_pf_wp8.3_HLT_Mu9_IP6.root' + wsfilename_mixe_jpsi = 'wspace_jpsi_fixedPartial_mix_wp8.6_HLT_Mu9_IP6.root' + wsfilename_mu_jpsi = 'wspace_jpsi_muon.root' + wsfilename = 'wspace_rjpsi_combinedEleCh.root' + + u_eff_pfe_jpsi = ufloat(eff_pfe_jpsi, deff_pfe_jpsi) + u_eff_mixe_jpsi = ufloat(eff_mixe_jpsi, deff_mixe_jpsi) + u_eff_mu_jpsi = ufloat(eff_mu_jpsi, deff_mu_jpsi) + u_eff_pfe_to_mu_jpsi = u_eff_pfe_jpsi / u_eff_mu_jpsi + u_eff_mixe_to_mu_jpsi = u_eff_mixe_jpsi / u_eff_mu_jpsi + print(u_eff_pfe_to_mu_jpsi, u_eff_mixe_to_mu_jpsi) + print(u_eff_pfe_to_mu_jpsi.n, u_eff_pfe_to_mu_jpsi.s, u_eff_mixe_to_mu_jpsi.n, u_eff_mixe_to_mu_jpsi.s) + + createWorkspace('R_jpsi', wsfilename, wsfilename_pfe_jpsi, wsfilename_mixe_jpsi, wsfilename_mu_jpsi, + eff_pfe_to_mu_jpsi=u_eff_pfe_to_mu_jpsi.n, deff_pfe_to_mu_jpsi=u_eff_pfe_to_mu_jpsi.s, + eff_mixe_to_mu_jpsi=u_eff_mixe_to_mu_jpsi.n, deff_mixe_to_mu_jpsi=u_eff_mixe_to_mu_jpsi.s, + ) + plccanvas = analyzeWorkspace('R_jpsi', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True, unbinned=False, NPoints=50) + + diff --git a/measurement/maximum_likelihood_rpsi2s.py b/measurement/maximum_likelihood_rpsi2s.py index 21a987b..2429fd9 100644 --- a/measurement/maximum_likelihood_rpsi2s.py +++ b/measurement/maximum_likelihood_rpsi2s.py @@ -60,18 +60,18 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps ('br_hat_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), ('dbr_psi2s_mumu', dbr_psi2s_mumu, 1.e-6, 1), # nuisance parameters - ('n_ele_jpsi', 8617, 8000, 10000), + ('n_ele_jpsi', 9117, 8000, 11000), ('eff_ele_psi2s', eff_ele_psi2s, eff_ele_psi2s-5.0*deff_ele_psi2s, eff_ele_psi2s+5.0*deff_ele_psi2s), ('eff_ele_jpsi', eff_ele_jpsi, eff_ele_jpsi-5.0*deff_ele_jpsi, eff_ele_jpsi+5.0*deff_ele_jpsi), ('br_psi2s_ee', br_psi2s_ee, br_psi2s_ee-5.0*dbr_psi2s_ee, br_psi2s_ee+5.0*dbr_psi2s_ee), ('br_jpsi_ee', br_jpsi_ee, br_jpsi_ee-5.0*dbr_jpsi_ee, br_jpsi_ee+5.0*dbr_jpsi_ee), - ('n_mu_jpsi', 8617, 8000, 10000), + ('n_mu_jpsi', 9117, 8000, 11000), ('eff_mu_psi2s', eff_mu_psi2s, eff_mu_psi2s-5.0*deff_mu_psi2s, eff_mu_psi2s+5.0*deff_mu_psi2s), ('eff_mu_jpsi', eff_mu_jpsi, eff_mu_jpsi-5.0*deff_mu_jpsi, eff_mu_jpsi+5.0*deff_mu_jpsi), ('br_psi2s_mumu', br_psi2s_mumu, br_psi2s_mumu-5.0*dbr_psi2s_mumu, br_psi2s_mumu+5.0*dbr_psi2s_mumu), ('br_jpsi_mumu', br_jpsi_mumu, br_jpsi_mumu-5.0*dbr_jpsi_mumu, br_jpsi_mumu+5.0*dbr_jpsi_mumu), # parameter of interest - ('r_br', 0.7, 0.3, 1.5), + ('r_br', 0.8, 0.3, 1.5), ('R', 1.0, 0.5, 1.5), ] @@ -196,10 +196,10 @@ def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jps if __name__ == "__main__": - eff_ele_psi2s, deff_ele_psi2s = 0.03430, 0.00024 - eff_ele_jpsi, deff_ele_jpsi = 0.03680, 0.00023 - eff_mu_psi2s, deff_mu_psi2s = 0.03430, 0.00024 - eff_mu_jpsi, deff_mu_jpsi = 0.03680, 0.00023 + eff_ele_psi2s, deff_ele_psi2s = 0.034559096817, 0.000245498985637 + eff_ele_jpsi, deff_ele_jpsi = 0.0387281944237, 0.000242298195912 + eff_mu_psi2s, deff_mu_psi2s = 0.034559096817, 0.000245498985637 + eff_mu_jpsi, deff_mu_jpsi = 0.0387281944237, 0.000242298195912 R_SM = 1.0 R_min, R_max = 0.8, 1.2 xlabel = 'R_{#psi(2S)}' diff --git a/measurement/maximum_likelihood_rpsi2s_combinedEleCh.py b/measurement/maximum_likelihood_rpsi2s_combinedEleCh.py index 7fcb73d..3ba33f3 100644 --- a/measurement/maximum_likelihood_rpsi2s_combinedEleCh.py +++ b/measurement/maximum_likelihood_rpsi2s_combinedEleCh.py @@ -3,7 +3,12 @@ from time import sleep import math import ROOT as rt +import ROOT from ROOT import RooFit +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +from roofit_models import root_function_RightSidedCB +ROOT.gInterpreter.Declare(root_function_RightSidedCB) rt.gROOT.SetBatch(True); rt.gROOT.SetStyle("Plain"); from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace @@ -38,7 +43,7 @@ def createWorkspace(wsname, wsfilename, br_psi2s_ee, dbr_psi2s_ee = 7.93e-3, 0.17e-3 br_jpsi_mumu, dbr_jpsi_mumu= 0.05961, 0.00033 br_psi2s_mumu, dbr_psi2s_mumu = 8.0e-3, 0.6e-3 - + r_br, dr_br = 0.6117647, 0.022678 ### Create parameters # observations @@ -73,23 +78,40 @@ def createWorkspace(wsname, wsfilename, # branching fraction of psi(2S) -> mu mu ('br_hat_psi2s_mumu', br_psi2s_mumu, 1.e-6, 1), ('dbr_psi2s_mumu', dbr_psi2s_mumu, 1.e-6, 1), + # branching fraction of B -> psi(2S) / B -> J/psi + ('r_br_hat', r_br, 1.e-6, 1), + ('dr_br', dr_br, 1.e-6, 1), # nuisance parameters - ('n_pfe_jpsi', 8617, 7000, 10000), - ('eff_pfe_psi2s', eff_pfe_psi2s, eff_pfe_psi2s-5.0*deff_pfe_psi2s, eff_pfe_psi2s+5.0*deff_pfe_psi2s), - ('eff_pfe_jpsi', eff_pfe_jpsi, eff_pfe_jpsi-5.0*deff_pfe_jpsi, eff_pfe_jpsi+5.0*deff_pfe_jpsi), - ('n_mixe_jpsi', 8617, 7000, 10000), - ('eff_mixe_psi2s', eff_mixe_psi2s, eff_mixe_psi2s-5.0*deff_mixe_psi2s, eff_mixe_psi2s+5.0*deff_mixe_psi2s), - ('eff_mixe_jpsi', eff_mixe_jpsi, eff_mixe_jpsi-5.0*deff_mixe_jpsi, eff_mixe_jpsi+5.0*deff_mixe_jpsi), - ('br_psi2s_ee', br_psi2s_ee, br_psi2s_ee-5.0*dbr_psi2s_ee, br_psi2s_ee+5.0*dbr_psi2s_ee), - ('br_jpsi_ee', br_jpsi_ee, br_jpsi_ee-5.0*dbr_jpsi_ee, br_jpsi_ee+5.0*dbr_jpsi_ee), - ('n_mu_jpsi', 8617, 7000, 10000), - ('eff_mu_psi2s', eff_mu_psi2s, eff_mu_psi2s-5.0*deff_mu_psi2s, eff_mu_psi2s+5.0*deff_mu_psi2s), - ('eff_mu_jpsi', eff_mu_jpsi, eff_mu_jpsi-5.0*deff_mu_jpsi, eff_mu_jpsi+5.0*deff_mu_jpsi), - ('br_psi2s_mumu', br_psi2s_mumu, br_psi2s_mumu-5.0*dbr_psi2s_mumu, br_psi2s_mumu+5.0*dbr_psi2s_mumu), - ('br_jpsi_mumu', br_jpsi_mumu, br_jpsi_mumu-5.0*dbr_jpsi_mumu, br_jpsi_mumu+5.0*dbr_jpsi_mumu), + #('n_pfe_jpsi', 4.7656e+03 , 0, 10000), + #('eff_pfe_psi2s', eff_pfe_psi2s, eff_pfe_psi2s-5.0*deff_pfe_psi2s, eff_pfe_psi2s+5.0*deff_pfe_psi2s), + #('eff_pfe_jpsi', eff_pfe_jpsi, eff_pfe_jpsi-5.0*deff_pfe_jpsi, eff_pfe_jpsi+5.0*deff_pfe_jpsi), + #('n_mixe_jpsi', 2.0379e+03, 0, 10000), + #('eff_mixe_psi2s', eff_mixe_psi2s, eff_mixe_psi2s-5.0*deff_mixe_psi2s, eff_mixe_psi2s+5.0*deff_mixe_psi2s), + #('eff_mixe_jpsi', eff_mixe_jpsi, eff_mixe_jpsi-5.0*deff_mixe_jpsi, eff_mixe_jpsi+5.0*deff_mixe_jpsi), + #('br_psi2s_ee', br_psi2s_ee, br_psi2s_ee-5.0*dbr_psi2s_ee, br_psi2s_ee+5.0*dbr_psi2s_ee), + #('br_jpsi_ee', br_jpsi_ee, br_jpsi_ee-5.0*dbr_jpsi_ee, br_jpsi_ee+5.0*dbr_jpsi_ee), + #('n_mu_jpsi', 7.7098e+05, 0, 5000000), + #('eff_mu_psi2s', eff_mu_psi2s, eff_mu_psi2s-5.0*deff_mu_psi2s, eff_mu_psi2s+5.0*deff_mu_psi2s), + #('eff_mu_jpsi', eff_mu_jpsi, eff_mu_jpsi-5.0*deff_mu_jpsi, eff_mu_jpsi+5.0*deff_mu_jpsi), + #('br_psi2s_mumu', br_psi2s_mumu, br_psi2s_mumu-5.0*dbr_psi2s_mumu, br_psi2s_mumu+5.0*dbr_psi2s_mumu), + #('br_jpsi_mumu', br_jpsi_mumu, br_jpsi_mumu-5.0*dbr_jpsi_mumu, br_jpsi_mumu+5.0*dbr_jpsi_mumu), + ('n_pfe_jpsi', 4.7656e+03 , 0, 10000), + ('eff_pfe_psi2s', eff_pfe_psi2s, -1.0, 1.0), + ('eff_pfe_jpsi', eff_pfe_jpsi, -1.0, 1.0), + ('n_mixe_jpsi', 2.0379e+03, 0, 10000), + ('eff_mixe_psi2s', eff_mixe_psi2s, -1.0, 1.0), + ('eff_mixe_jpsi', eff_mixe_jpsi, -1.0, 1.0), + ('br_psi2s_ee', br_psi2s_ee, br_psi2s_ee-50.0*dbr_psi2s_ee, br_psi2s_ee+50.0*dbr_psi2s_ee), + ('br_jpsi_ee', br_jpsi_ee, br_jpsi_ee-50.0*dbr_jpsi_ee, br_jpsi_ee+50.0*dbr_jpsi_ee), + ('n_mu_jpsi', 7.7098e+05, 0, 5000000), + ('eff_mu_psi2s', eff_mu_psi2s, -1.0, 1.0), + ('eff_mu_jpsi', eff_mu_jpsi, -1.0, 1.0), + ('br_psi2s_mumu', br_psi2s_mumu, br_psi2s_mumu-50.0*dbr_psi2s_mumu, br_psi2s_mumu+50.0*dbr_psi2s_mumu), + ('br_jpsi_mumu', br_jpsi_mumu, br_jpsi_mumu-50.0*dbr_jpsi_mumu, br_jpsi_mumu+50.0*dbr_jpsi_mumu), + # parameter of interest - ('r_br', 0.7, 0.6, 0.8), - ('R', 1.0, 0.5, 1.5), + ('r_br', r_br, r_br-50.0*dr_br, r_br+50.0*dr_br), + ('R', 1.0, 0.1, 2.0), ] for t in params: @@ -104,20 +126,29 @@ def createWorkspace(wsname, wsfilename, wspace.var(name).getVal()) wspace.var(name).setConstant() + wspace.var("ncomb_pfe_jpsi").setConstant() + wspace.var("ncomb_mixe_jpsi").setConstant() + wspace.var("ncomb_mu_jpsi").setConstant() + + ### Create expressions express = [ # PF-PF electron 'n_pfe_psi2s("(r_br/R)*n_pfe_jpsi*(br_psi2s_ee/br_jpsi_ee)*(eff_pfe_psi2s/eff_pfe_jpsi)", r_br, R, n_pfe_jpsi, br_psi2s_ee, br_jpsi_ee, eff_pfe_psi2s, eff_pfe_jpsi)', 'nKstarPsi2S_pfe_psi2s_modified("frac_partial_pfe_psi2s*n_pfe_psi2s", frac_partial_pfe_psi2s, n_pfe_psi2s)', 'nKstarJpsi_pfe_jpsi_modified("frac_partial_pfe_jpsi*n_pfe_jpsi", frac_partial_pfe_jpsi, n_pfe_jpsi)', + 'nKstarPlusPsi2S_pfe_psi2s_modified("frac_kstarplus_pfe_psi2s*nKstarPsi2S_pfe_psi2s_modified", frac_kstarplus_pfe_psi2s, nKstarPsi2S_pfe_psi2s_modified)', + 'nKstarPlusJpsi_pfe_jpsi_modified("frac_kstarplus_pfe_jpsi*nKstarJpsi_pfe_jpsi_modified", frac_kstarplus_pfe_jpsi, nKstarJpsi_pfe_jpsi_modified)', # PF-LP electron 'n_mixe_psi2s("(r_br/R)*n_mixe_jpsi*(br_psi2s_ee/br_jpsi_ee)*(eff_mixe_psi2s/eff_mixe_jpsi)", r_br, R, n_mixe_jpsi, br_psi2s_ee, br_jpsi_ee, eff_mixe_psi2s, eff_mixe_jpsi)', 'nKstarPsi2S_mixe_psi2s_modified("frac_partial_mixe_psi2s*n_mixe_psi2s", frac_partial_mixe_psi2s, n_mixe_psi2s)', 'nKstarJpsi_mixe_jpsi_modified("frac_partial_mixe_jpsi*n_mixe_jpsi", frac_partial_mixe_jpsi, n_mixe_jpsi)', + 'nKstarPlusPsi2S_mixe_psi2s_modified("frac_kstarplus_mixe_psi2s*nKstarPsi2S_mixe_psi2s_modified", frac_kstarplus_mixe_psi2s, nKstarPsi2S_mixe_psi2s_modified)', + 'nKstarPlusJpsi_mixe_jpsi_modified("frac_kstarplus_mixe_jpsi*nKstarJpsi_mixe_jpsi_modified", frac_kstarplus_mixe_jpsi, nKstarJpsi_mixe_jpsi_modified)', # muon 'n_mu_psi2s("r_br*n_mu_jpsi*(br_psi2s_mumu/br_jpsi_mumu)*(eff_mu_psi2s/eff_mu_jpsi)", r_br, n_mu_jpsi, br_psi2s_mumu, br_jpsi_mumu, eff_mu_psi2s, eff_mu_jpsi)', - 'nKstarPsi2S_mu_psi2s_modified("frac_partial_mu_psi2s*n_mu_psi2s", frac_partial_mu_psi2s, n_mu_psi2s)', - 'nKstarJpsi_mu_jpsi_modified("frac_partial_mu_jpsi*n_mu_jpsi", frac_partial_mu_jpsi, n_mu_jpsi)', + #'nKstarPsi2S_mu_psi2s_modified("frac_partial_mu_psi2s*n_mu_psi2s", frac_partial_mu_psi2s, n_mu_psi2s)', + #'nKstarJpsi_mu_jpsi_modified("frac_partial_mu_jpsi*n_mu_jpsi", frac_partial_mu_jpsi, n_mu_jpsi)', ] for t in express: @@ -126,14 +157,14 @@ def createWorkspace(wsname, wsfilename, edit = [ # PF-PF electron - 'model_pfe_psi2s_modified(model_pfe_psi2s, nsignal_pfe_psi2s=n_pfe_psi2s, nKstarPsi2S_pfe_psi2s=nKstarPsi2S_pfe_psi2s_modified)', - 'model_pfe_jpsi_modified(model_pfe_jpsi, nsignal_pfe_jpsi=n_pfe_jpsi, nKstarJpsi_pfe_jpsi=nKstarJpsi_pfe_jpsi_modified)', + 'model_pfe_psi2s_modified(model_pfe_psi2s, nsignal_pfe_psi2s=n_pfe_psi2s, nKstarPsi2S_pfe_psi2s=nKstarPsi2S_pfe_psi2s_modified, nKstarPlusPsi2S_pfe_psi2s=nKstarPlusPsi2S_pfe_psi2s_modified)', + 'model_pfe_jpsi_modified(model_pfe_jpsi, nsignal_pfe_jpsi=n_pfe_jpsi, nKstarJpsi_pfe_jpsi=nKstarJpsi_pfe_jpsi_modified, nKstarPlusJpsi_pfe_jpsi=nKstarPlusJpsi_pfe_jpsi_modified)', # PF-LP electron - 'model_mixe_psi2s_modified(model_mixe_psi2s, nsignal_mixe_psi2s=n_mixe_psi2s, nKstarPsi2S_mixe_psi2s=nKstarPsi2S_mixe_psi2s_modified)', - 'model_mixe_jpsi_modified(model_mixe_jpsi, nsignal_mixe_jpsi=n_mixe_jpsi, nKstarJpsi_mixe_jpsi=nKstarJpsi_mixe_jpsi_modified)', + 'model_mixe_psi2s_modified(model_mixe_psi2s, nsignal_mixe_psi2s=n_mixe_psi2s, nKstarPsi2S_mixe_psi2s=nKstarPsi2S_mixe_psi2s_modified, nKstarPlusPsi2S_mixe_psi2s=nKstarPlusPsi2S_mixe_psi2s_modified)', + 'model_mixe_jpsi_modified(model_mixe_jpsi, nsignal_mixe_jpsi=n_mixe_jpsi, nKstarJpsi_mixe_jpsi=nKstarJpsi_mixe_jpsi_modified, nKstarPlusJpsi_mixe_jpsi=nKstarPlusJpsi_mixe_jpsi_modified)', # muon - 'model_mu_psi2s_modified(model_mu_psi2s, nsignal_mu_psi2s=n_mu_psi2s, nKstarPsi2S_mu_psi2s=nKstarPsi2S_mu_psi2s_modified)', - 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi, nKstarJpsi_mu_jpsi=nKstarJpsi_mu_jpsi_modified)', + 'model_mu_psi2s_modified(model_mu_psi2s, nsignal_mu_psi2s=n_mu_psi2s)', + 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi)', ] for t in edit: @@ -156,6 +187,8 @@ def createWorkspace(wsname, wsfilename, ('Gaussian','peff_mu_jpsi', '(eff_hat_mu_jpsi, eff_mu_jpsi, deff_mu_jpsi)'), ('Gaussian','peff_br_psi2s_mumu', '(br_hat_psi2s_mumu, br_psi2s_mumu, dbr_psi2s_mumu)'), ('Gaussian','peff_br_jpsi_mumu', '(br_hat_jpsi_mumu, br_jpsi_mumu, dbr_jpsi_mumu)'), + # r_br + ('Gaussian','pr_br', '(r_br_hat, r_br, dr_br)'), ] prodpdf = '' @@ -177,17 +210,24 @@ def createWorkspace(wsname, wsfilename, 'dbr_jpsi_ee', 'dbr_psi2s_ee', 'br_hat_jpsi_ee', 'br_hat_psi2s_ee' 'deff_mu_jpsi', 'deff_mu_psi2s', 'eff_hat_mu_jpsi', 'eff_hat_mu_psi2s', 'dbr_jpsi_mumu', 'dbr_psi2s_mumu', 'br_hat_jpsi_mumu', 'br_hat_psi2s_mumu' + 'dr_br', 'r_br_hat' ] ### Define global observables ### they are not being fitted and they are not loaded from a dataset, ### but some knowledge exists that allows to set them to a specific value ### Global Observables are generated once per toy - globs = ['eff_pfe_psi2s', 'eff_pfe_jpsi', 'br_psi2s_ee', 'br_jpsi_ee', - 'eff_mixe_psi2s', 'eff_mixe_jpsi', - 'eff_mu_psi2s', 'eff_mu_jpsi', 'br_psi2s_mumu', 'br_jpsi_mumu', + #globs = ['eff_pfe_psi2s', 'eff_pfe_jpsi', 'br_psi2s_ee', 'br_jpsi_ee', + # 'eff_mixe_psi2s', 'eff_mixe_jpsi', + # 'eff_mu_psi2s', 'eff_mu_jpsi', 'br_psi2s_mumu', 'br_jpsi_mumu', + # 'r_br' + # ] + globs = ['eff_hat_pfe_psi2s', 'eff_hat_pfe_jpsi', 'br_hat_psi2s_ee', 'br_hat_jpsi_ee', + 'eff_hat_mixe_psi2s', 'eff_hat_mixe_jpsi', + 'eff_hat_mu_psi2s', 'eff_hat_mu_jpsi', 'br_hat_psi2s_mumu', 'br_hat_jpsi_mumu', ] + nuis = [] params = wspace.pdf('model').getVariables() params_iter = params.createIterator() @@ -220,7 +260,7 @@ def createWorkspace(wsname, wsfilename, cfg.SetPdf(wspace.pdf('model')) cfg.SetParametersOfInterest(wspace.set('poi')) cfg.SetNuisanceParameters(wspace.set('nuis')) - cfg.SetGlobalObservables(wspace.set('globs')) + #cfg.SetGlobalObservables(wspace.set('globs')) # import model configuration into workspace getattr(wspace, 'import')(cfg) @@ -233,22 +273,22 @@ def createWorkspace(wsname, wsfilename, if __name__ == "__main__": - eff_pfe_psi2s, deff_pfe_psi2s = 0.03430, 0.00024 - eff_pfe_jpsi, deff_pfe_jpsi = 0.03680, 0.00023 - eff_mixe_psi2s, deff_mixe_psi2s = 0.03430, 0.00024 - eff_mixe_jpsi, deff_mixe_jpsi = 0.03680, 0.00023 - eff_mu_psi2s, deff_mu_psi2s = 0.03430, 0.00024 - eff_mu_jpsi, deff_mu_jpsi = 0.03680, 0.00023 + eff_pfe_psi2s, deff_pfe_psi2s = 0.01822, 0.00023 + eff_pfe_jpsi, deff_pfe_jpsi = 0.02479, 0.00025 + eff_mixe_psi2s, deff_mixe_psi2s = 0.00680, 0.00011 + eff_mixe_jpsi, deff_mixe_jpsi = 0.01085, 0.00014 + eff_mu_psi2s, deff_mu_psi2s = 14.81e-4, 0.11e-4 + eff_mu_jpsi, deff_mu_jpsi = 12.69e-4, 0.1e-4 R_SM = 1.0 - R_min, R_max = 0.8, 1.2 + R_min, R_max = 0.75, 1.25 xlabel = 'R_{#psi(2S)}' - wsfilename_pfe_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' - wsfilename_pfe_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' - wsfilename_mixe_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' - wsfilename_mixe_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' - wsfilename_mu_psi2s = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' - wsfilename_mu_jpsi = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' + wsfilename_pfe_psi2s = 'wspace_psi2s_fixedPartial_pf_wp8.3_fixedpartial.root' + wsfilename_pfe_jpsi = 'wspace_jpsi_fixedPartial_pf_wp8.3_fixedpartial.root' + wsfilename_mixe_psi2s = 'wspace_psi2s_fixedPartial_mix_wp8.6_fixedpartial.root' + wsfilename_mixe_jpsi = 'wspace_jpsi_fixedPartial_mix_wp8.6_fixedpartial.root' + wsfilename_mu_psi2s = 'wspace_psi2s_muon.root' + wsfilename_mu_jpsi = 'wspace_jpsi_muon.root' wsfilename = 'wspace_rpsi2s_combinedEleCh.root' createWorkspace('R_psi2s', wsfilename, wsfilename_pfe_psi2s, wsfilename_pfe_jpsi, wsfilename_mixe_psi2s, wsfilename_mixe_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, @@ -256,6 +296,6 @@ def createWorkspace(wsname, wsfilename, eff_mixe_psi2s=eff_mixe_psi2s, deff_mixe_psi2s=deff_mixe_psi2s, eff_mixe_jpsi=eff_mixe_jpsi, deff_mixe_jpsi=deff_mixe_jpsi, eff_mu_psi2s=eff_mu_psi2s, deff_mu_psi2s=deff_mu_psi2s, eff_mu_jpsi=eff_mu_jpsi, deff_mu_jpsi=deff_mu_jpsi, ) - plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=False, unbinned=False, NPoints=50) diff --git a/measurement/maximum_likelihood_singleChannel.py b/measurement/maximum_likelihood_singleChannel.py index e2fb3d3..c90a7aa 100644 --- a/measurement/maximum_likelihood_singleChannel.py +++ b/measurement/maximum_likelihood_singleChannel.py @@ -28,11 +28,12 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar ('eff_hat_norm', eff_norm, 0, 1), ('deff_norm', deff_norm, 0, 1), # nuisance parameters - ('n_norm', 8617, 7000, 10000), + #('n_norm', 4779.12, 0, 10000), + ('n_norm', 2084.77, 0, 10000), ('eff_tar', eff_tar, eff_tar-5.0*deff_tar, eff_tar+5.0*deff_tar), ('eff_norm', eff_norm, eff_norm-5.0*deff_norm, eff_norm+5.0*deff_norm), # parameter of interest - ('R', 0.09, 0.01, 0.2)] + ('R', 7.2486e-02, 0.01, 0.15)] for t in params: cmd = '%s[%f, %f, %f]' % t @@ -50,14 +51,16 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar express = ['n_tar("R*n_norm*(eff_tar/eff_norm)", R, n_norm, eff_tar, eff_norm)', 'nKstarPsi2S_tar_modified("frac_partial_tar*n_tar", frac_partial_tar, n_tar)', 'nKstarJpsi_norm_modified("frac_partial_norm*n_norm", frac_partial_norm, n_norm)', + 'nKstarPlusPsi2S_tar_modified("frac_kstarplus_tar*nKstarPsi2S_tar_modified", frac_kstarplus_tar, nKstarPsi2S_tar_modified)', + 'nKstarPlusJpsi_norm_modified("frac_kstarplus_norm*nKstarJpsi_norm_modified", frac_kstarplus_norm, nKstarJpsi_norm_modified)', ] for t in express: cmd = 'expr::%s' % t wspace.factory(cmd) - edit = ['model_tar_modified(model_tar, nsignal_tar=n_tar, nKstarPsi2S_tar=nKstarPsi2S_tar_modified)', - 'model_norm_modified(model_norm, nsignal_norm=n_norm, nKstarJpsi_norm=nKstarJpsi_norm_modified)', + edit = ['model_tar_modified(model_tar, nsignal_tar=n_tar, nKstarPsi2S_tar=nKstarPsi2S_tar_modified, nKstarPlusPsi2S_tar=nKstarPlusPsi2S_tar_modified)', + 'model_norm_modified(model_norm, nsignal_norm=n_norm, nKstarJpsi_norm=nKstarJpsi_norm_modified, nKstarPlusJpsi_norm=nKstarPlusJpsi_norm_modified)', ] for t in edit: @@ -135,15 +138,25 @@ def createWorkspace(wsname, wsfilename, wsfilename_tar, wsfilename_norm, eff_tar if __name__ == "__main__": + + # pf + #eff_tar, deff_tar = 0.01822, 0.00023 + #eff_norm, deff_norm = 0.02479, 0.00025 + #R_min, R_max = 0.075, 0.105 + #wsfilename_tar = 'wspace_psi2s_fixedPartial_pf_wp8.3_fixedpartial.root' + #wsfilename_norm = 'wspace_jpsi_fixedPartial_pf_wp8.3_fixedpartial.root' + + # mix + eff_tar, deff_tar = 0.00680, 0.00011 + eff_norm, deff_norm = 0.01085, 0.00014 + R_min, R_max = 0.05, 0.095 + wsfilename_tar = 'wspace_psi2s_fixedPartial_mix_wp8.6_fixedpartial.root' + wsfilename_norm = 'wspace_jpsi_fixedPartial_mix_wp8.6_fixedpartial.root' - eff_tar, deff_tar = 0.03430, 0.00024 - eff_norm, deff_norm = 0.03680, 0.00023 R_SM = 0.0812 - R_min, R_max = 0.07, 0.12 + xlabel = 'R_{#psi (2S)}^{e}' - wsfilename_tar = 'wspace_psi2s_fixedPartial_pf_wp5.0.root' - wsfilename_norm = 'wspace_jpsi_fixedPartial_pf_wp5.0.root' wsfilename = 'wspace_rpsi2s_electron.root' createWorkspace('R_psi2s', wsfilename, wsfilename_tar, wsfilename_norm, eff_tar=eff_tar, deff_tar=deff_tar, eff_norm=eff_norm, deff_norm=deff_norm) diff --git a/measurement/maximum_likelihood_singleChannel_combinedEleCh.py b/measurement/maximum_likelihood_singleChannel_combinedEleCh.py new file mode 100644 index 0000000..484f2c0 --- /dev/null +++ b/measurement/maximum_likelihood_singleChannel_combinedEleCh.py @@ -0,0 +1,196 @@ +import os,sys,re +from time import sleep +import math +import ROOT as rt +from ROOT import RooFit +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace + +def createWorkspace(wsname, wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, + eff_ele_psi2s=0.0, deff_ele_psi2s=0.0, eff_ele_jpsi=0.0, deff_ele_jpsi=0.0, + eff_mu_psi2s=0.0, deff_mu_psi2s=0.0, eff_mu_jpsi=0.0, deff_mu_jpsi=0.0, + ): + + wspace = rt.RooWorkspace(wsname) + wspace = importWorkspace(wspace, wsfilename_ele_psi2s, 'ele_psi2s') + wspace = importWorkspace(wspace, wsfilename_ele_jpsi, 'ele_jpsi') + wspace = importWorkspace(wspace, wsfilename_mu_psi2s, 'mu_psi2s') + wspace = importWorkspace(wspace, wsfilename_mu_jpsi, 'mu_jpsi') + + wspace.factory('cat[ele_psi2s,ele_jpsi,mu_psi2s,mu_jpsi]') + x = wspace.var("x") + data = rt.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), + RooFit.Import('ele_psi2s', wspace.data('data_ele_psi2s')), RooFit.Import('ele_jpsi', wspace.data('data_ele_jpsi')), + RooFit.Import('mu_psi2s', wspace.data('data_mu_psi2s')), RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), + ) + getattr(wspace, 'import')(data, rt.RooCmdArg()) + + + ### Create parameters + # observations + params = [ + # efficiency of electron psi(2S) estimate + ('eff_hat_ele_psi2s', eff_ele_psi2s, 1.e-6, 1), + ('deff_ele_psi2s', deff_ele_psi2s, 1.e-6, 1), + # efficiency of electron J/psi channel estimate + ('eff_hat_ele_jpsi', eff_ele_jpsi, 1.e-6, 1), + ('deff_ele_jpsi', deff_ele_jpsi, 1.e-6, 1), + # efficiency of muon psi(2S) estimate + ('eff_hat_mu_psi2s', eff_mu_psi2s, 1.e-6, 1), + ('deff_mu_psi2s', deff_mu_psi2s, 1.e-6, 1), + # efficiency of muon J/psi channel estimate + ('eff_hat_mu_jpsi', eff_mu_jpsi, 1.e-6, 1), + ('deff_mu_jpsi', deff_mu_jpsi, 1.e-6, 1), + # nuisance parameters + ('n_ele_jpsi', 9117, 0, 11000), + ('eff_ele_psi2s', eff_ele_psi2s, eff_ele_psi2s-5.0*deff_ele_psi2s, eff_ele_psi2s+5.0*deff_ele_psi2s), + ('eff_ele_jpsi', eff_ele_jpsi, eff_ele_jpsi-5.0*deff_ele_jpsi, eff_ele_jpsi+5.0*deff_ele_jpsi), + ('n_mu_jpsi', 9117, 0, 11000), + ('eff_mu_psi2s', eff_mu_psi2s, eff_mu_psi2s-5.0*deff_mu_psi2s, eff_mu_psi2s+5.0*deff_mu_psi2s), + ('eff_mu_jpsi', eff_mu_jpsi, eff_mu_jpsi-5.0*deff_mu_jpsi, eff_mu_jpsi+5.0*deff_mu_jpsi), + # parameter of interest + ('R', 7.2486e-02, 0.01, 0.15)] + + for t in params: + cmd = '%s[%f, %f, %f]' % t + wspace.factory(cmd) + wspace.var('R').SetTitle('R') + + # fix all background and signal parameters + for t in params[0:-7]: + name = t[0] + print '=> make %8s = %5.5f constant' % (name, + wspace.var(name).getVal()) + wspace.var(name).setConstant() + + ### Create expressions + express = ['n_ele_psi2s("R*n_ele_jpsi*(eff_ele_psi2s/eff_ele_jpsi)", R, n_ele_jpsi, eff_ele_psi2s, eff_ele_jpsi)', + 'nKstarPsi2S_ele_psi2s_modified("frac_partial_ele_psi2s*n_ele_psi2s", frac_partial_ele_psi2s, n_ele_psi2s)', + 'nKstarJpsi_ele_jpsi_modified("frac_partial_ele_jpsi*n_ele_jpsi", frac_partial_ele_jpsi, n_ele_jpsi)', + 'nKstarPlusPsi2S_ele_psi2s_modified("frac_kstarplus_ele_psi2s*nKstarPsi2S_ele_psi2s_modified", frac_kstarplus_ele_psi2s, nKstarPsi2S_ele_psi2s_modified)', + 'nKstarPlusJpsi_ele_jpsi_modified("frac_kstarplus_ele_jpsi*nKstarJpsi_ele_jpsi_modified", frac_kstarplus_ele_jpsi, nKstarJpsi_ele_jpsi_modified)', + 'n_mu_psi2s("R*n_mu_jpsi*(eff_mu_psi2s/eff_mu_jpsi)", R, n_mu_jpsi, eff_mu_psi2s, eff_mu_jpsi)', + 'nKstarPsi2S_mu_psi2s_modified("frac_partial_mu_psi2s*n_mu_psi2s", frac_partial_mu_psi2s, n_mu_psi2s)', + 'nKstarJpsi_mu_jpsi_modified("frac_partial_mu_jpsi*n_mu_jpsi", frac_partial_mu_jpsi, n_mu_jpsi)', + 'nKstarPlusPsi2S_mu_psi2s_modified("frac_kstarplus_mu_psi2s*nKstarPsi2S_mu_psi2s_modified", frac_kstarplus_mu_psi2s, nKstarPsi2S_mu_psi2s_modified)', + 'nKstarPlusJpsi_mu_jpsi_modified("frac_kstarplus_mu_jpsi*nKstarJpsi_mu_jpsi_modified", frac_kstarplus_mu_jpsi, nKstarJpsi_mu_jpsi_modified)', + ] + + for t in express: + cmd = 'expr::%s' % t + wspace.factory(cmd) + + edit = ['model_ele_psi2s_modified(model_ele_psi2s, nsignal_ele_psi2s=n_ele_psi2s, nKstarPsi2S_ele_psi2s=nKstarPsi2S_ele_psi2s_modified, nKstarPlusPsi2S_ele_psi2s=nKstarPlusPsi2S_ele_psi2s_modified)', + 'model_ele_jpsi_modified(model_ele_jpsi, nsignal_ele_jpsi=n_ele_jpsi, nKstarJpsi_ele_jpsi=nKstarJpsi_ele_jpsi_modified, nKstarPlusJpsi_ele_jpsi=nKstarPlusJpsi_ele_jpsi_modified)', + 'model_mu_psi2s_modified(model_mu_psi2s, nsignal_mu_psi2s=n_mu_psi2s, nKstarPsi2S_mu_psi2s=nKstarPsi2S_mu_psi2s_modified, nKstarPlusPsi2S_mu_psi2s=nKstarPlusPsi2S_mu_psi2s_modified)', + 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi, nKstarJpsi_mu_jpsi=nKstarJpsi_mu_jpsi_modified, nKstarPlusJpsi_mu_jpsi=nKstarPlusJpsi_mu_jpsi_modified)', + ] + + for t in edit: + cmd = 'EDIT::%s' % t + wspace.factory(cmd) + + wspace.Print("V") + ### Create pdfs + pdfs = [('Gaussian','peff_ele_psi2s', '(eff_hat_ele_psi2s, eff_ele_psi2s, deff_ele_psi2s)'), + ('Gaussian','peff_ele_jpsi', '(eff_hat_ele_jpsi, eff_ele_jpsi, deff_ele_jpsi)'), + ('Gaussian','peff_mu_psi2s', '(eff_hat_mu_psi2s, eff_mu_psi2s, deff_mu_psi2s)'), + ('Gaussian','peff_mu_jpsi', '(eff_hat_mu_jpsi, eff_mu_jpsi, deff_mu_jpsi)'), + ] + + prodpdf = '' + for t in pdfs: + wspace.factory('%s::%s%s' % t) + name = t[1] + prodpdf += "%s, " % name + prodpdf = prodpdf[:-2] # remove last ", " + + + # multiply the pdfs together. use upper case PROD to + # do this + wspace.factory("SIMUL:jointModel(cat,ele_psi2s=model_ele_psi2s_modified,ele_jpsi=model_ele_jpsi_modified,mu_psi2s=model_mu_psi2s_modified,mu_jpsi=model_mu_jpsi_modified)") + wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) + + nuis_excluded = ['x', 'R', 'cat', + 'deff_ele_jpsi', 'deff_ele_psi2s', 'eff_hat_ele_jpsi', 'eff_hat_ele_psi2s', + 'deff_mu_jpsi', 'deff_mu_psi2s', 'eff_hat_mu_jpsi', 'eff_hat_mu_psi2s', + ] + + ### Define global observables + ### they are not being fitted and they are not loaded from a dataset, + ### but some knowledge exists that allows to set them to a specific value + ### Global Observables are generated once per toy + globs = ['eff_ele_psi2s', 'eff_ele_jpsi', + 'eff_mu_psi2s', 'eff_mu_jpsi', + ] + + nuis = [] + params = wspace.pdf('model').getVariables() + params_iter = params.createIterator() + param = params_iter.Next() + while param : + if param.GetName() not in (nuis_excluded+globs): + nuis.append(param.GetName()) + param = params_iter.Next() + nuis = ','.join(nuis) + globs = ','.join(globs) + + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis), # nuisance parameters (leave no spaces) + ('globs', globs), + ] + #('nuis', 'n_ele_jpsi,eff_ele_psi2s,eff_ele_jpsi')] # nuisance parameters (leave no spaces) + + for t in sets: + name, parlist = t + wspace.defineSet(name, parlist) + + + #----------------------------------------------------- + # Create model configuration. This is needed for the + # statistical analyses + #----------------------------------------------------- + cfg = rt.RooStats.ModelConfig('cfg') + cfg.SetWorkspace(wspace) + cfg.SetPdf(wspace.pdf('model')) + cfg.SetParametersOfInterest(wspace.set('poi')) + cfg.SetNuisanceParameters(wspace.set('nuis')) + cfg.SetGlobalObservables(wspace.set('globs')) + + # import model configuration into workspace + getattr(wspace, 'import')(cfg) + + wspace.Print() + + # write out workspace + wspace.writeToFile(wsfilename) + + + +if __name__ == "__main__": + + eff_ele_psi2s, deff_ele_psi2s = 0.01822, 0.00023 + eff_ele_jpsi, deff_ele_jpsi = 0.02479, 0.00025 + + eff_mu_psi2s, deff_mu_psi2s = 0.00680, 0.00011 + eff_mu_jpsi, deff_mu_jpsi = 0.01085, 0.00014 + + R_SM = 0.0812 + R_min, R_max = 0.07, 0.10 + xlabel = 'R_{#psi(2S)}^{e}' + + wsfilename_ele_psi2s = 'wspace_psi2s_fixedPartial_pf_wp8.3_fixedpartial.root' + wsfilename_ele_jpsi = 'wspace_jpsi_fixedPartial_pf_wp8.3_fixedpartial.root' + wsfilename_mu_psi2s = 'wspace_psi2s_fixedPartial_mix_wp8.6_fixedpartial.root' + wsfilename_mu_jpsi = 'wspace_jpsi_fixedPartial_mix_wp8.6_fixedpartial.root' + wsfilename = 'wspace_rpsi2s.root' + + createWorkspace('R_psi2s', wsfilename, wsfilename_ele_psi2s, wsfilename_ele_jpsi, wsfilename_mu_psi2s, wsfilename_mu_jpsi, + eff_ele_psi2s=eff_ele_psi2s, deff_ele_psi2s=deff_ele_psi2s, eff_ele_jpsi=eff_ele_jpsi, deff_ele_jpsi=deff_ele_jpsi, + eff_mu_psi2s=eff_mu_psi2s, deff_mu_psi2s=deff_mu_psi2s, eff_mu_jpsi=eff_mu_jpsi, deff_mu_jpsi=deff_mu_jpsi, + ) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True) + + diff --git a/measurement/maximum_likelihood_single_ratio_rpsi_combinedEleCh_effRatio.py b/measurement/maximum_likelihood_single_ratio_rpsi_combinedEleCh_effRatio.py new file mode 100644 index 0000000..eb570e3 --- /dev/null +++ b/measurement/maximum_likelihood_single_ratio_rpsi_combinedEleCh_effRatio.py @@ -0,0 +1,221 @@ +import os,sys,re +import time +from time import sleep +import math +from uncertainties import ufloat +import ROOT as rt +import ROOT +from ROOT import RooFit +from roofit_models import root_function_DoubleSidedCB +ROOT.gInterpreter.Declare(root_function_DoubleSidedCB) +from roofit_models import root_function_RightSidedCB +ROOT.gInterpreter.Declare(root_function_RightSidedCB) +rt.gROOT.SetBatch(True); +rt.gROOT.SetStyle("Plain"); +from utils_likelihood import analyzeWorkspace, plot_likelihood, importWorkspace + +def createWorkspace(wsname, wsfilename, + wsfilename_pfe_jpsi, + wsfilename_mixe_jpsi, + wsfilename_mu_jpsi, + eff_pfe_to_mu_jpsi=0.0, deff_pfe_to_mu_jpsi=0.0, + eff_mixe_to_mu_jpsi=0.0, deff_mixe_to_mu_jpsi=0.0, + ): + + wspace = rt.RooWorkspace(wsname) + wspace = importWorkspace(wspace, wsfilename_pfe_jpsi, 'pfe_jpsi') + wspace = importWorkspace(wspace, wsfilename_mixe_jpsi, 'mixe_jpsi') + wspace = importWorkspace(wspace, wsfilename_mu_jpsi, 'mu_jpsi') + + wspace.factory('cat[pfe_jpsi,mixe_jpsi,mu_jpsi]') + x = wspace.var("x") + data = rt.RooDataSet('data', 'data', rt.RooArgSet(x), RooFit.Index(wspace.cat('cat')), + RooFit.Import('pfe_jpsi', wspace.data('data_pfe_jpsi')), + RooFit.Import('mixe_jpsi', wspace.data('data_mixe_jpsi')), + RooFit.Import('mu_jpsi', wspace.data('data_mu_jpsi')), + ) + getattr(wspace, 'import')(data, rt.RooCmdArg()) + + br_jpsi_ee, dbr_jpsi_ee= 0.05971, 0.00032 + br_psi2s_ee, dbr_psi2s_ee = 7.93e-3, 0.17e-3 + br_jpsi_mumu, dbr_jpsi_mumu= 0.05961, 0.00033 + br_psi2s_mumu, dbr_psi2s_mumu = 8.0e-3, 0.6e-3 + r_br, dr_br = 0.6117647, 0.022678 + + ### Create parameters + # observations + params = [ + # efficiency of PF-PF electron J/psi channel estimate + ('eff_hat_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, 1.e-6, 1), + ('deff_pfe_to_mu_jpsi', deff_pfe_to_mu_jpsi, 1.e-6, 1), + # efficiency of PF-LP electron J/psi channel estimate + ('eff_hat_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, 1.e-6, 1), + ('deff_mixe_to_mu_jpsi', deff_mixe_to_mu_jpsi, 1.e-6, 1), + # nuisance parameters + #('eff_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi-5.0*deff_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi+5.0*deff_pfe_to_mu_jpsi), + #('eff_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi-5.0*deff_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi+5.0*deff_mixe_to_mu_jpsi), + #('eff_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi-20.0*deff_pfe_to_mu_jpsi, 1), + #('eff_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi-20.0*deff_mixe_to_mu_jpsi, 1), + ('eff_pfe_to_mu_jpsi', eff_pfe_to_mu_jpsi, -1, 1), + ('eff_mixe_to_mu_jpsi', eff_mixe_to_mu_jpsi, -1, 1), + + ('n_mu_jpsi', 68329, 0, 1000000), + # parameter of interest + ('R', 0.91, 0.0, 1.2), + ] + + for t in params: + cmd = '%s[%f, %f, %f]' % t + wspace.factory(cmd) + wspace.var('R').SetTitle('R') + + # fix all background and signal parameters + for t in params[0:-4]: + name = t[0] + print '=> make %8s = %5.5f constant' % (name, + wspace.var(name).getVal()) + wspace.var(name).setConstant() + + #wspace.var('ncomb_mixe_jpsi').setConstant() + #wspace.var('ncomb_pfe_jpsi').setConstant() + #wspace.var('ncomb_mu_jpsi').setConstant() + #wspace.var('npartial_pfe_jpsi').setConstant() + #wspace.var('npartial_mixe_jpsi').setConstant() + + + ### Create expressions + express = [ + # PF-PF electron + 'n_pfe_jpsi("(n_mu_jpsi/R)*(eff_pfe_to_mu_jpsi)", n_mu_jpsi, R, eff_pfe_to_mu_jpsi)', + 'nKstarPsi2S_pfe_jpsi_modified("frac_partial_pfe_jpsi*n_pfe_jpsi", frac_partial_pfe_jpsi, n_pfe_jpsi)', + 'nKstarPlusPsi2S_pfe_jpsi_modified("frac_kstarplus_pfe_jpsi*nKstarPsi2S_pfe_jpsi_modified", frac_kstarplus_pfe_jpsi, nKstarPsi2S_pfe_jpsi_modified)', + # PF-LP electron + 'n_mixe_jpsi("(n_mu_jpsi/R)*(eff_mixe_to_mu_jpsi)", n_mu_jpsi, R, eff_mixe_to_mu_jpsi)', + 'nKstarPsi2S_mixe_jpsi_modified("frac_partial_mixe_jpsi*n_mixe_jpsi", frac_partial_mixe_jpsi, n_mixe_jpsi)', + 'nKstarPlusPsi2S_mixe_jpsi_modified("frac_kstarplus_mixe_jpsi*nKstarPsi2S_mixe_jpsi_modified", frac_kstarplus_mixe_jpsi, nKstarPsi2S_mixe_jpsi_modified)', + ] + + for t in express: + cmd = 'expr::%s' % t + wspace.factory(cmd) + + edit = [ + # PF-PF electron + 'model_pfe_jpsi_modified(model_pfe_jpsi, nsignal_pfe_jpsi=n_pfe_jpsi, nKstarPsi2S_pfe_jpsi=nKstarPsi2S_pfe_jpsi_modified, nKstarPlusPsi2S_pfe_jpsi=nKstarPlusPsi2S_pfe_jpsi_modified)', + # PF-LP electron + 'model_mixe_jpsi_modified(model_mixe_jpsi, nsignal_mixe_jpsi=n_mixe_jpsi, nKstarPsi2S_mixe_jpsi=nKstarPsi2S_mixe_jpsi_modified, nKstarPlusPsi2S_mixe_jpsi=nKstarPlusPsi2S_mixe_jpsi_modified)', + # muon + 'model_mu_jpsi_modified(model_mu_jpsi, nsignal_mu_jpsi=n_mu_jpsi)', + ] + + for t in edit: + cmd = 'EDIT::%s' % t + wspace.factory(cmd) + + wspace.Print("V") + ### Create pdfs + pdfs = [ + # PF-PF electron + ('Gaussian','peff_pfe_to_mu_jpsi', '(eff_hat_pfe_to_mu_jpsi, eff_pfe_to_mu_jpsi, deff_pfe_to_mu_jpsi)'), + # PF-LP electron + ('Gaussian','peff_mixe_to_mu_jpsi', '(eff_hat_mixe_to_mu_jpsi, eff_mixe_to_mu_jpsi, deff_mixe_to_mu_jpsi)'), + ] + + prodpdf = '' + for t in pdfs: + wspace.factory('%s::%s%s' % t) + name = t[1] + prodpdf += "%s, " % name + prodpdf = prodpdf[:-2] # remove last ", " + + + # multiply the pdfs together. use upper case PROD to + # do this + wspace.factory("SIMUL:jointModel(cat,pfe_jpsi=model_pfe_jpsi_modified,mixe_jpsi=model_mixe_jpsi_modified,mu_jpsi=model_mu_jpsi_modified)") + wspace.factory('PROD::model({},{})'.format(prodpdf, 'jointModel')) + + nuis_excluded = ['x', 'R', 'cat', + 'deff_pfe_to_mu_jpsi', 'eff_hat_pfe_to_mu_jpsi', + 'deff_mixe_to_mu_jpsi', 'eff_hat_mixe_to_mu_jpsi', + ] + + ### Define global observables + ### they are not being fitted and they are not loaded from a dataset, + ### but some knowledge exists that allows to set them to a specific value + ### Global Observables are generated once per toy + #globs = ['eff_pfe_to_mu_jpsi', 'eff_mixe_to_mu_jpsi' + globs = ['eff_hat_pfe_to_mu_jpsi', 'eff_hat_mixe_to_mu_jpsi' + ] + + nuis = [] + params = wspace.pdf('model').getVariables() + params_iter = params.createIterator() + param = params_iter.Next() + while param : + if param.GetName() not in (nuis_excluded+globs): + nuis.append(param.GetName()) + param = params_iter.Next() + nuis = ','.join(nuis) + globs = ','.join(globs) + + sets = [('obs', 'x'), # observations + ('poi', 'R'), # parameter of interest + ('nuis', nuis), + ('globs', globs), + ] # nuisance parameters (leave no spaces) + #('nuis', 'n_pfe_jpsi,eff_pfe_psi2s,eff_pfe_jpsi')] # nuisance parameters (leave no spaces) + + for t in sets: + name, parlist = t + wspace.defineSet(name, parlist) + + + #----------------------------------------------------- + # Create model configuration. This is needed for the + # statistical analyses + #----------------------------------------------------- + cfg = rt.RooStats.ModelConfig('cfg') + cfg.SetWorkspace(wspace) + cfg.SetPdf(wspace.pdf('model')) + cfg.SetParametersOfInterest(wspace.set('poi')) + cfg.SetNuisanceParameters(wspace.set('nuis')) + #cfg.SetGlobalObservables(wspace.set('globs')) + + # import model configuration into workspace + getattr(wspace, 'import')(cfg) + + wspace.Print() + + # write out workspace + wspace.writeToFile(wsfilename) + + +if __name__ == "__main__": + + eff_pfe_jpsi, deff_pfe_jpsi = 3.9526e-6, 2.15e-7 + eff_mixe_jpsi, deff_mixe_jpsi = 1.4752e-6, 8.18e-8 + eff_mu_jpsi, deff_mu_jpsi = 14.81e-4, 0.11e-4 + R_SM = 1.0 + R_min, R_max = 0.7, 1.2 + xlabel = 'R_{#psi(2S)}^{signle ratio}' + + wsfilename_pfe_jpsi = 'wspace_psi2s_fixedPartial_pf_wp8.3_HLT_Mu9_IP6.root' + wsfilename_mixe_jpsi = 'wspace_psi2s_fixedPartial_mix_wp8.6_HLT_Mu9_IP6.root' + wsfilename_mu_jpsi = 'wspace_psi2s_muon.root' + wsfilename = 'wspace_single_ratio_rpsi2s_combinedEleCh.root' + + u_eff_pfe_jpsi = ufloat(eff_pfe_jpsi, deff_pfe_jpsi) + u_eff_mixe_jpsi = ufloat(eff_mixe_jpsi, deff_mixe_jpsi) + u_eff_mu_jpsi = ufloat(eff_mu_jpsi, deff_mu_jpsi) + u_eff_pfe_to_mu_jpsi = u_eff_pfe_jpsi / u_eff_mu_jpsi + u_eff_mixe_to_mu_jpsi = u_eff_mixe_jpsi / u_eff_mu_jpsi + print(u_eff_pfe_to_mu_jpsi, u_eff_mixe_to_mu_jpsi) + print(u_eff_pfe_to_mu_jpsi.n, u_eff_pfe_to_mu_jpsi.s, u_eff_mixe_to_mu_jpsi.n, u_eff_mixe_to_mu_jpsi.s) + + createWorkspace('R_psi2s', wsfilename, wsfilename_pfe_jpsi, wsfilename_mixe_jpsi, wsfilename_mu_jpsi, + eff_pfe_to_mu_jpsi=u_eff_pfe_to_mu_jpsi.n, deff_pfe_to_mu_jpsi=u_eff_pfe_to_mu_jpsi.s, + eff_mixe_to_mu_jpsi=u_eff_mixe_to_mu_jpsi.n, deff_mixe_to_mu_jpsi=u_eff_mixe_to_mu_jpsi.s, + ) + plccanvas = analyzeWorkspace('R_psi2s', wsfilename, x_SM=R_SM, x_min=R_min, x_max=R_max, xlabel=xlabel, plot=True, unbinned=False, NPoints=50) + + diff --git a/measurement/roofit_models.py b/measurement/roofit_models.py new file mode 100644 index 0000000..bc179ca --- /dev/null +++ b/measurement/roofit_models.py @@ -0,0 +1,74 @@ +root_function_DoubleSidedCB=""" + +double DoubleSidedCB2(double x, double mu, double width, double a1, double p1, double a2, double p2) +{ + double u = (x-mu)/width; + double A1 = TMath::Power(p1/TMath::Abs(a1),p1)*TMath::Exp(-a1*a1/2); + double A2 = TMath::Power(p2/TMath::Abs(a2),p2)*TMath::Exp(-a2*a2/2); + double B1 = p1/TMath::Abs(a1) - TMath::Abs(a1); + double B2 = p2/TMath::Abs(a2) - TMath::Abs(a2); + + double result(1); + if (u<-a1) result *= A1*TMath::Power(B1-u,-p1); + else if (u Date: Wed, 25 May 2022 03:14:06 +0200 Subject: [PATCH 12/13] updated fit with other b bkg included --- ...si_roofit_plb_modified_kde_fixedPartial.py | 70 +++++++++---------- ...2S_roofit_plb_modified_kde_fixedPartial.py | 63 ++++++++--------- fit/run_fit_KJpsi_fixedPartial.py | 34 +++------ fit/run_fit_KPsi2S_fixedPartial.py | 37 +++------- 4 files changed, 85 insertions(+), 119 deletions(-) diff --git a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py index afdd894..31e0801 100644 --- a/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KJpsi_roofit_plb_modified_kde_fixedPartial.py @@ -33,15 +33,15 @@ def residuals(xframe, var,name): -def define_workspace_bmass_data(wspace_name,mB_branch,tree): +def define_workspace_bmass_data(wspace_name,mB_branch,tree,Bmass_min=4.7): wspace = ROOT.RooWorkspace(wspace_name) fitvars = ROOT.RooArgSet() - bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") + bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", Bmass_min, 5.7, "GeV") fitvars.add(bMass) dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) theBMass = dataset.addColumn(theBMassfunc) ; - theBMass.setRange(4.7,5.7); + theBMass.setRange(Bmass_min,5.7); fitvars.add(theBMass) getattr(wspace, "import")(dataset, RooFit.Rename('data')) # When a RooWorkspace is set as an attribute of a class, it can trigger a memory error @@ -141,11 +141,12 @@ def otherB_fit(tree, outputfile, branches, SavePlot=True): return {"exp_alpha_otherb":params.getRealValue('exp_alpha_otherb')} ############################ KDE fit ####################### -def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): +def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True, par=1.5, Bmass_min=4.7): print "KDE - {}".format(pdfname) - wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree) + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree, Bmass_min=Bmass_min) kde_frame=theBMass.frame() - wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(pdfname)) + #wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(pdfname)) + wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,{1})'.format(pdfname, par)) kde = wspace.pdf(pdfname) dataset.plotOn(kde_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) @@ -156,7 +157,7 @@ def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): #wf.Close() #c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') - c1, top, bottom =canvas_create_pull(kde_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + c1, top, bottom =canvas_create_pull(kde_frame,Bmass_min,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) top.cd() CMS_lumi() @@ -201,15 +202,15 @@ def bkg_fit(tree, outputfile, branches, SavePlot=True): ############################# total fit ############################## -def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarJpsi_pdf=None, KstarPlusJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, partial_ratio_kstarplus=None, mvacut="",log='log.csv'): +def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_pdf=None, KstarJpsi_pdf=None, KstarPlusJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, partial_ratio_kstarplus=None, mvacut="",log='log.csv'): wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) print "Total" #amplitudes wspace.factory('nsignal[10000.0, 0.0, 1000000.0]' ) - wspace.factory('ncomb[50000.0, 0.0, 1000000.0]') + wspace.factory('ncomb[500.0, 0.0, 1000000.0]') wspace.factory('notherB[1000.0, 0.0, 1000000.0]') - wspace.factory('frac_partial[0.3, 0.0, 10.0]') + wspace.factory('frac_partial[0.35, 0.0, 10.0]') wspace.factory('prod::nKstarJpsi(frac_partial,nsignal)') wspace.factory('frac_kstarplus[0.1, 0.0, 10.0]') #wspace.factory('prod::nKstarPlusJpsi(frac_kstarplus,nsignal)') @@ -230,8 +231,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('SUM::signal(cb_signal,frac*g_signal)') # other B - bkg - wspace.factory('exp_alpha_otherb[-6.0, -100.0, -1.e-4]') - wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') + getattr(wspace, "import")(otherB_pdf, RooFit.Rename('otherb')) # K*Jpsi - bkg getattr(wspace, "import")(KstarJpsi_pdf, RooFit.Rename('kstarjpsi')) @@ -240,16 +240,15 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame getattr(wspace, "import")(KstarPlusJpsi_pdf, RooFit.Rename('kstarplusjpsi')) # combinatorial - bkg - wspace.factory('exp_alpha_comb[-1.0, -100.0, -1.e-4]') + wspace.factory('exp_alpha_comb[-1.0, -10.0, -1.e-4]') wspace.factory('Exponential::exp_comb(x,exp_alpha_comb)') #sum - wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarJpsi*kstarjpsi,nKstarPlusJpsi*kstarplusjpsi,notherB*exp_otherb)') + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarJpsi*kstarjpsi,nKstarPlusJpsi*kstarplusjpsi,notherB*otherb)') - model = wspace.pdf('model'); signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') - exp_otherb = wspace.pdf('exp_otherb') + otherb = wspace.pdf('otherb') kstarjpsi = wspace.pdf('kstarjpsi') kstarplusjpsi = wspace.pdf('kstarplusjpsi') nsignal = wspace.var('nsignal'); ncomb = wspace.var('ncomb') @@ -263,9 +262,6 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame (wspace.var(par)).setVal(signal_parameters[par]) if par not in ['mean', 'gauss_mean']: (wspace.var(par)).setConstant(True) - for par in otherB_parameters.keys(): - (wspace.var(par)).setVal(otherB_parameters[par]) - (wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) (wspace.var(par)).setConstant(True) @@ -286,7 +282,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("otherb"),RooFit.Components("otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarjpsi"),RooFit.Components("kstarjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarplusjpsi"),RooFit.Components("kstarplusjpsi"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(46),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("signal"),RooFit.Components("signal"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.LineStyle(2),RooFit.LineColor(ROOT.kBlue),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected), RooFit.LineWidth(3)) @@ -312,7 +308,9 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame nKstarJpsi_visible_err = 0.0 nKstarPlusJpsi_visible = get_visible_yield(obs, results, kstarplusjpsi , nKstarPlusJpsi) nKstarPlusJpsi_visible_err = 0.0 - notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) + notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results, otherb , notherB) + #notherB_visible = get_visible_yield(obs, results, otherb , notherB) + #notherB_visible_err = 0.0 nbkg_visible = nKstarJpsi_visible+nKstarPlusJpsi_visible+ncomb_visible+notherB_visible # c1=canvas_create(xframe,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]') @@ -328,7 +326,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend.AddEntry(xframe.findObject("exp_comb"),"Combinatorial","l"); legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); legend.AddEntry(xframe.findObject("kstarplusjpsi"),"B -> J/#psiK*+","l"); - legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); + legend.AddEntry(xframe.findObject("otherb"),"Other B","l"); legend.AddEntry(xframe.findObject("signal"),"B -> J/#psiK","l"); legend.SetLineColor(ROOT.kWhite) legend.SetTextFont(42); @@ -346,7 +344,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame residuals(xframe,theBMass,outputfile+"_poutana") - saveWS = False + saveWS = True if saveWS: # get likelihood @@ -375,15 +373,16 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace_output.writeToFile('wspace_'+outputfile+'.root') + csv_header = ['cut', 'nsig_total', 'nsig_total_unc', 'nKstarJpsi_total', 'nKstarJpsi_total_unc', 'nKstarPlusJpsi_total', 'nKstarPlusJpsi_total_unc', 'nsig', 'nbkg', 'ncomb', 'nKstarJpsi', 'nKstarPlusJpsi', 'notherB', 'snr', 'chi2'] df = {} df['cut'] = mvacut df['nsig_total'] = nsignal.getVal() df['nsig_total_unc'] = nsignal.getError() df['nKstarJpsi_total'] = nKstarJpsi.getVal() - df['nKstarJpsi_total_unc'] = np.sqrt(nKstarJpsi.getVal()) + df['nKstarJpsi_total_unc'] = nKstarJpsi.getPropagatedError(results) df['nKstarPlusJpsi_total'] = nKstarPlusJpsi.getVal() - df['nKstarPlusJpsi_total_unc'] = np.sqrt(nKstarPlusJpsi.getVal()) + df['nKstarPlusJpsi_total_unc'] = nKstarPlusJpsi.getPropagatedError(results) df['nsig'] = nsig_visible df['nbkg'] = nbkg_visible df['ncomb'] = ncomb_visible @@ -426,18 +425,19 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame parser.add_argument("--partial_ratio_kstarplus", dest="partial_ratio_kstarplus", default=None, type=float, help="fixing the partially reco. yield") args = parser.parse_args() - branches=["Bmass","Mll","xgb","KLmassD0"] - cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + " && " + branches[3] + ">2.0" - if args.mva < 7.0: + branches=["Bmass","Mll","xgb","KLmassD0","Mu9_IP6"] + cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + " && " + branches[3] + ">2.0" #+ " && " + branches[4] + cuts_otherb = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + " && " + branches[3] + ">2.0" #+ " && " + branches[0] + " < 5.2" + + if args.mva < 6.0: cuts_samesign = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" else: - cuts_samesign = branches[2]+"> 7.0 "+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" + cuts_samesign = branches[2]+"> 6.0 "+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.2" #cuts = branches[2]+">"+str(args.mva)+" && 2.9<"+branches[1]+" && "+branches[1]+"<3.25" #cuts = branches[2]+">"+str(args.mva)+" && 2.8<"+branches[1]+" && "+branches[1]+"<3.25" + " && " + branches[3] + ">2.0" args.outputfile+="_wp"+str(args.mva) - otherB_parameters={'exp_alpha_otherb':-5.099} comb_parameters={'exp_alpha_comb':-1.50615} print "start" @@ -458,9 +458,9 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if "bkg_otherb" in args.sel_primtv: tree_otherB = ROOT.TChain('mytreefit') tree_otherB.Add(args.iotherB_BKG) - tree_otherB_cut=tree_otherB.CopyTree(cuts) - otherB_parameters = otherB_fit(tree_otherB_cut, args.outputfile+"_otherBMC", branches) - print "parameters otherB BKG", otherB_parameters['exp_alpha_otherb'] + tree_otherB_cut=tree_otherB.CopyTree(cuts_otherb) + otherB_pdf = kde_fit(tree_otherB_cut, args.outputfile+"_otherBMC", branches, 'otherb', par=2.0, Bmass_min=4.5) + print "finished kde fit for other B" if "bkg_comb" in args.sel_primtv: tree_bkg = ROOT.TChain('mytreefit') @@ -480,7 +480,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame tree_KstarPlusJpsi = ROOT.TChain('mytreefit') tree_KstarPlusJpsi.Add(args.iKstarPlusJpsi_BKG) tree_KstarPlusJpsi_cut=tree_KstarPlusJpsi.CopyTree(cuts) - KstarPlusJpsi_pdf = kde_fit(tree_KstarPlusJpsi_cut, args.outputfile+"_KstarPlusJpsiMC", branches, 'kstarplusjpsi') + KstarPlusJpsi_pdf = kde_fit(tree_KstarPlusJpsi_cut, args.outputfile+"_KstarPlusJpsiMC", branches, 'kstarplusjpsi', par=2.0) print "finished kde fit for K*+ J/psi" else: @@ -494,7 +494,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if args.maxx==-1: args.maxx=signal_parameters["mean"]+2*signal_parameters["width"] #nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarJpsi_pdf,comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, str(args.mva), args.log) - nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarJpsi_pdf, KstarPlusJpsi_pdf, comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, args.partial_ratio_kstarplus, str(args.mva), args.log) + nsig, nbkg, nKstarJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_pdf, KstarJpsi_pdf, KstarPlusJpsi_pdf, comb_parameters, {"min":args.minx,"max":args.maxx}, args.partial_ratio, args.partial_ratio_kstarplus, str(args.mva), args.log) print "sig",nsig,"comb", nbkg,"K* J/psi", nKstarJpsi,"otherB", notherB,"all sig", nsig_total # combinatorial BKG parameters set but not fixed. diff --git a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py index 0ce8cfd..a36daa8 100644 --- a/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py +++ b/fit/KPsi2S_roofit_plb_modified_kde_fixedPartial.py @@ -31,17 +31,15 @@ def residuals(xframe, var,name): c3=canvas_create(xframe3,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',False) c3.SaveAs(name+'_pull.pdf') - - -def define_workspace_bmass_data(wspace_name,mB_branch,tree): +def define_workspace_bmass_data(wspace_name,mB_branch,tree,Bmass_min=4.7): wspace = ROOT.RooWorkspace(wspace_name) fitvars = ROOT.RooArgSet() - bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", 4.7, 5.7, "GeV") + bMass = ROOT.RooRealVar(mB_branch, "m(K^{+}e^{+}e^{-})", Bmass_min, 5.7, "GeV") fitvars.add(bMass) dataset = ROOT.RooDataSet('data','data',tree, ROOT.RooArgSet(fitvars)) theBMassfunc = ROOT.RooFormulaVar("x", "x", "@0", ROOT.RooArgList(bMass) ) theBMass = dataset.addColumn(theBMassfunc) ; - theBMass.setRange(4.7,5.7); + theBMass.setRange(Bmass_min,5.7); fitvars.add(theBMass) getattr(wspace, "import")(dataset, RooFit.Rename('data')) # When a RooWorkspace is set as an attribute of a class, it can trigger a memory error @@ -142,12 +140,12 @@ def otherB_fit(tree, outputfile, branches, SavePlot=True): ############################ KDE fit ####################### -def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): +def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True, par=1.5, Bmass_min=4.7): print "KDE - {}".format(pdfname) - wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree) + wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_kde",branches[0],tree, Bmass_min=Bmass_min) kde_frame=theBMass.frame() #wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,2.0)'.format(pdfname)) - wspace.factory('KeysPdf::{0}(x,data,MirrorBoth,2.0)'.format(pdfname)) + wspace.factory('KeysPdf::{0}(x,data,MirrorLeft,{1})'.format(pdfname, par)) kde = wspace.pdf(pdfname) dataset.plotOn(kde_frame,RooFit.Binning(nbin_data), RooFit.Name("datas")) @@ -158,7 +156,7 @@ def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): #wf.Close() #c1=canvas_create(kde_frame,4.7,5.7,nbin_data,'m (e^{+}e^{-}K) [GeV] ') - c1, top, bottom =canvas_create_pull(kde_frame,4.7,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) + c1, top, bottom =canvas_create_pull(kde_frame,Bmass_min,5.7,nbin_data,'m(e^{+}e^{-}K) [GeV]',theBMass) top.cd() CMS_lumi() @@ -167,6 +165,7 @@ def kde_fit(tree, outputfile, branches, pdfname, SavePlot=True): residuals(kde_frame,theBMass,'bkg_kde_'+outputfile+'_'+pdfname) return kde + ############################ Combinatorial fit =Expo ########################### def bkg_fit(tree, outputfile, branches, SavePlot=True): print "combinatorial" @@ -202,7 +201,7 @@ def bkg_fit(tree, outputfile, branches, SavePlot=True): ############################# total fit ############################## -def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parameters=None, KstarPsi2S_pdf=None , KstarPlusPsi2S_pdf=None, KstarJpsi_pdf=None , KJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, partial_ratio_kstarplus=None, mvacut="",log='log.csv'): +def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_pdf=None, KstarPsi2S_pdf=None , KstarPlusPsi2S_pdf=None, KstarJpsi_pdf=None , KJpsi_pdf=None, comb_parameters=None,Significance_range=None, partial_ratio=None, partial_ratio_kstarplus=None, mvacut="",log='log.csv'): wspace,dataset,bMass,theBMass = define_workspace_bmass_data("wspace_total",branches[0],tree) print "Total" #amplitudes @@ -234,9 +233,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame wspace.factory('SUM::signal(cb_signal,frac*g_signal)') # other B - bkg - wspace.factory('exp_alpha_otherb[-5.0, -100.0, -1.e-4]') - #wspace.factory('exp_alpha_otherb[-15.0, -100.0, -1.0]') - wspace.factory('Exponential::exp_otherb(x,exp_alpha_otherb)') + getattr(wspace, "import")(otherB_pdf, RooFit.Rename('otherb')) # K*Psi2S - bkg getattr(wspace, "import")(KstarPsi2S_pdf, RooFit.Rename('kstarpsi2s')) @@ -260,11 +257,12 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,notherB*exp_otherb)') #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarJpsi*kstarjpsi,notherB*exp_otherb)') #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarPlusPsi2S*kstarpluspsi2s,notherB*exp_otherb)') - wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarPlusPsi2S*kstarpluspsi2s)') + #wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarPlusPsi2S*kstarpluspsi2s)') + wspace.factory('SUM::model(nsignal*signal,ncomb*exp_comb,nKstarPsi2S*kstarpsi2s,nKstarPlusPsi2S*kstarpluspsi2s,notherB*otherb)') model = wspace.pdf('model'); signal = wspace.pdf('signal'); exp_comb = wspace.pdf('exp_comb') - exp_otherb = wspace.pdf('exp_otherb') + otherb = wspace.pdf('otherb') kjpsi = wspace.pdf('kjpsi') kstarpsi2s = wspace.pdf('kstarpsi2s'); kstarjpsi = wspace.pdf('kstarjpsi') kstarpluspsi2s = wspace.pdf('kstarpluspsi2s') @@ -279,9 +277,6 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame for par in signal_parameters.keys(): (wspace.var(par)).setVal(signal_parameters[par]) (wspace.var(par)).setConstant(True) - for par in otherB_parameters.keys(): - (wspace.var(par)).setVal(otherB_parameters[par]) - #(wspace.var(par)).setConstant(True) for par in comb_parameters.keys(): (wspace.var(par)).setVal(comb_parameters[par]) (wspace.var(par)).setConstant(True) @@ -306,7 +301,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame dataset.plotOn(xframe,RooFit.Binning(nbin_data), RooFit.Name("datas")) model.plotOn(xframe,RooFit.Name("exp_comb"),RooFit.Components("exp_comb"),RooFit.Range("Full"),RooFit.DrawOption("L"),RooFit.VLines(),RooFit.FillColor(49),RooFit.LineColor(49),RooFit.LineStyle(2),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineWidth(3)) - #model.plotOn(xframe,RooFit.Name("exp_otherb"),RooFit.Components("exp_otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) + model.plotOn(xframe,RooFit.Name("otherb"),RooFit.Components("otherb"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(30),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) #model.plotOn(xframe,RooFit.Name("kjpsi"),RooFit.Components("kjpsi"),RooFit.Range("Full"),RooFit.FillColor(43),RooFit.LineColor(43),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarpsi2s"),RooFit.Components("kstarpsi2s"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(12),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) model.plotOn(xframe,RooFit.Name("kstarpluspsi2s"),RooFit.Components("kstarpluspsi2s"),RooFit.Range("Full"),RooFit.FillColor(30),RooFit.LineColor(46),RooFit.Normalization(norm, ROOT.RooAbsReal.RelativeExpected),RooFit.LineStyle(2), RooFit.LineWidth(3),RooFit.DrawOption("L"),RooFit.MoveToBack()) @@ -336,7 +331,8 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame nKstarPlusPsi2S_visible_err = 0.0 nKstarJpsi_visible, nKstarJpsi_visible_err = get_visible_yield_error(obs, results, kstarjpsi , nKstarJpsi) nKJpsi_visible, nKJpsi_visible_err = get_visible_yield_error(obs, results,kjpsi , nKJpsi) - notherB_visible, notherB_visible_err = get_visible_yield_error(obs, results,exp_otherb , notherB) + notherB_visible = get_visible_yield(obs, results, otherb , notherB) + notherB_visible_err = 0.0 #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKstarJpsi_visible+nKJpsi_visible+notherB_visible #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+nKJpsi_visible+notherB_visible #nbkg_visible = ncomb_visible+nKstarPsi2S_visible+notherB_visible @@ -359,7 +355,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame legend.AddEntry(xframe.findObject("kstarpluspsi2s"),"B -> #psi(2S)K*+","l"); #legend.AddEntry(xframe.findObject("kstarjpsi"),"B -> J/#psiK*","l"); #legend.AddEntry(xframe.findObject("kjpsi"),"B -> J/#psiK","l"); - #legend.AddEntry(xframe.findObject("exp_otherb"),"Other B","l"); + legend.AddEntry(xframe.findObject("otherb"),"Other B","l"); legend.AddEntry(xframe.findObject("signal"),"B -> #psi(2S)K","l"); legend.SetLineColor(ROOT.kWhite) legend.SetTextFont(42); @@ -376,7 +372,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame print "signal",nsig_visible,"+/-", nsig_visible_err,"comb",ncomb_visible,"+/-", ncomb_visible_err,"K* Psi2S", nKstarPsi2S_visible, "+/-",nKstarPsi2S_visible_err,"K*+ Psi2S", nKstarPlusPsi2S_visible, "+/-",nKstarPlusPsi2S_visible_err,"K* J/psi", nKstarJpsi_visible, "+/-",nKstarJpsi_visible_err, "K J/psi", nKJpsi_visible, "+/-", nKJpsi_visible_err, "otherB", notherB_visible, "+/-",notherB_visible_err residuals(xframe,theBMass,outputfile+"_poutana") - saveWS = False + saveWS = True if saveWS: # get likelihood ''' @@ -409,9 +405,9 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame df['nsig_total'] = nsignal.getVal() df['nsig_total_unc'] = nsignal.getError() df['nKstarPsi2S_total'] = nKstarPsi2S.getVal() - df['nKstarPsi2S_total_unc'] = np.sqrt(nKstarPsi2S.getVal()) + df['nKstarPsi2S_total_unc'] = nKstarPsi2S.getPropagatedError(results) df['nKstarPlusPsi2S_total'] = nKstarPlusPsi2S.getVal() - df['nKstarPlusPsi2S_total_unc'] = np.sqrt(nKstarPlusPsi2S.getVal()) + df['nKstarPlusPsi2S_total_unc'] = nKstarPlusPsi2S.getPropagatedError(results) df['nsig'] = nsig_visible df['nbkg'] = nbkg_visible df['ncomb'] = ncomb_visible @@ -458,14 +454,15 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame parser.add_argument("--log", dest="log", default="log.csv", help="log of the fitting results") args = parser.parse_args() - branches=["Bmass","Mll","xgb","KLmassD0"] - cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" + branches=["Bmass","Mll","xgb","KLmassD0","Mu9_IP6"] + cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" #+ " && " + branches[4] #cuts = branches[2]+">"+str(args.mva)+" && 0<"+branches[1]+" && "+branches[1]+"<5" + " && " + branches[3] + ">2.0" + cuts_otherb = branches[2]+">"+str(min(args.mva, 4.0))+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" #+ " && " + branches[4] - if args.mva < 7.0: + if args.mva < 6.0: cuts_samesign = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" else: - cuts_samesign = branches[2]+"> 7.0 "+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + cuts_samesign = branches[2]+"> 6.0 "+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" #cuts = branches[2]+">"+str(args.mva)+" && 3.55<"+branches[1]+" && "+branches[1]+"<3.8" + " && " + branches[3] + ">2.0" args.outputfile+="_wp"+str(args.mva) @@ -492,10 +489,10 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if "bkg_otherb" in args.sel_primtv: tree_otherB = ROOT.TChain('mytreefit') tree_otherB.Add(args.iotherB_BKG) - tree_otherB_cut=tree_otherB.CopyTree(cuts) - otherB_parameters = otherB_fit(tree_otherB_cut, args.outputfile+"_otherBMC", branches) - print "parameters otherB BKG", otherB_parameters['exp_alpha_otherb'] - + tree_otherB_cut=tree_otherB.CopyTree(cuts_otherb) + otherB_pdf = kde_fit(tree_otherB_cut, args.outputfile+"_otherBMC", branches, 'otherb', Bmass_min=4.5) + print "finished kde fit for other B" + if "bkg_comb" in args.sel_primtv: tree_bkg = ROOT.TChain('mytreefit') tree_bkg.Add(args.ibkg) @@ -541,7 +538,7 @@ def total_fit(tree, outputfile, branches, signal_parameters=None, otherB_parame if args.minx==-1: args.minx=signal_parameters["mean"]-2*signal_parameters["width"] if args.maxx==-1: args.maxx=signal_parameters["mean"]+2*signal_parameters["width"] - nsig, nbkg, nKstarPsi2S, nKstarJpsi, nKJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_parameters, KstarPsi2S_pdf, KstarPlusPsi2S_pdf, KstarJpsi_pdf ,KJpsiee_pdf, comb_parameters, {"min":args.minx,"max":args.maxx},args.partial_ratio, args.partial_ratio_kstarplus, str(args.mva), args.log) + nsig, nbkg, nKstarPsi2S, nKstarJpsi, nKJpsi, notherB, nsig_total =total_fit(tree_cut, args.outputfile, branches, signal_parameters, otherB_pdf, KstarPsi2S_pdf, KstarPlusPsi2S_pdf, KstarJpsi_pdf ,KJpsiee_pdf, comb_parameters, {"min":args.minx,"max":args.maxx},args.partial_ratio, args.partial_ratio_kstarplus, str(args.mva), args.log) print "sig",nsig,"comb", nbkg,"K* Psi2S", nKstarPsi2S,"K* J/psi", nKstarJpsi,"K J/psi", nKJpsi, "otherB", notherB,"all sig", nsig_total # combinatorial BKG parameters set but not fixed. # print "sigma",float(nsig)/math.sqrt(nsig+nkjpsi+nbkg),"nsig",float(nsig),"nbkg",float(nbkg),"Kjpsi leak",float(nkjpsi) diff --git a/fit/run_fit_KJpsi_fixedPartial.py b/fit/run_fit_KJpsi_fixedPartial.py index 21f19dd..6c8cfe2 100644 --- a/fit/run_fit_KJpsi_fixedPartial.py +++ b/fit/run_fit_KJpsi_fixedPartial.py @@ -36,7 +36,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'pf' - log = 'log_jpsi_bparkPU_v7.3_{}_nonreg_floating_mean_tightWP.csv'.format(eleType) + log = 'log_jpsi_bparkPU_v7.3_{}_nonreg_floating_mean_tightWP_otherB.csv'.format(eleType) info = defaultdict(dict) br_b2kjpsi = 1.02e-3 @@ -45,26 +45,6 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): nparts = range(8) - # PF-PF - #info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' - #info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCres.root'.format('marker') - #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') - #info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' - #info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' - #info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' - ##info['pf']['iKstarPlusJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.2_0_MC_kstarplusjpsi_kee.root' - #info['pf']['n_mc_jpsi'] = 563421.0 - #info['pf']['n_mc_partial'] = 373882.0 - - # PF-LP - #info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' - #info['mix']['jpsi_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCres.root'.format('marker') - #info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarjpsi.root'.format('marker') - #info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' - #info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' - #info['mix']['n_mc_jpsi'] = 563421.0 - #info['mix']['n_mc_partial'] = 373882.0 - # PF-PF nonreg info['pf']['inputfile'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_data_mvaCut0.root' info['pf']['jpsi_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MCres.root'.format('marker') @@ -77,6 +57,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['n_mc_partial'] = 379086.0 info['pf']['n_mc_kstarplus'] = 314672.0 info['pf']['ibkg'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_samesign_mvaCut0.root' + info['pf']['iotherB'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_otherb.root' # PF-LP info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_data_mvaCut0.root' @@ -90,6 +71,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['mix']['n_mc_partial'] = 379086.0 info['mix']['n_mc_kstarplus'] = 314672.0 info['mix']['ibkg'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_samesign_mvaCut0.root' + info['mix']['iotherB'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_otherb.root' selection = {} @@ -108,6 +90,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): #mvaCut = np.linspace(4.0, 6.0, 11) #mvaCut = np.linspace(8.0, 8.7, 8) mvaCut = np.array([8.3, ]) + else: #mvaCut = np.linspace(4.0, 6.0, 11) #mvaCut = np.linspace(8.3, 9.0, 8) @@ -131,7 +114,10 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): #com = 'python KJpsi_roofit_plb_modified_kde_kstarPlus.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) # not fixing partial ratio #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) - com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iotherB={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_otherb,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iotherB'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial_v1.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iotherB={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_otherb,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iotherB'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + # without same-sign #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --sel_primitive="sgn,bkg_kstarjpsi" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], frac_ratio, cut, log) @@ -140,7 +126,9 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): else: #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --sel_primitive="sgn,bkg_kstarjpsi" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], frac_ratio, cut, log) #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) - com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iotherB={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_otherb,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iotherB'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + #com = 'python KJpsi_roofit_plb_modified_kde_fixedPartial_v1.py -i {} -o jpsi_fixedPartial_{} --isgn={} --iotherB={} --iKstarJpsi_BKG={} --iKstarPlusJpsi_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarjpsi,bkg_kstarplusjpsi,bkg_otherb,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iotherB'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKstarPlusJpsi_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) os.system(com) diff --git a/fit/run_fit_KPsi2S_fixedPartial.py b/fit/run_fit_KPsi2S_fixedPartial.py index ec3f662..626e173 100644 --- a/fit/run_fit_KPsi2S_fixedPartial.py +++ b/fit/run_fit_KPsi2S_fixedPartial.py @@ -36,7 +36,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if __name__ == "__main__": eleType = 'pf' - log = 'log_psi2s_bparkPU_v7.3_{}_nonreg_tightWP.csv'.format(eleType) + log = 'log_psi2s_bparkPU_v7.3_{}_nonreg_tightWP_otherB.csv'.format(eleType) info = defaultdict(dict) br_b2kpsi2s = 6.24e-4 @@ -48,31 +48,6 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): nparts = range(8) - # PF-PF - #info['pf']['inputfile'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_data_mvaCut0.root' - #info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MCPsi2S.root'.format('marker') - #info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarpsi2s.root'.format('marker') - ##info['pf']['partial_mc'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_{}_MC_kstarjpsi.root'.format('marker') - #info['pf']['isgn'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCPsi2S.root' - #info['pf']['ibkg'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_samesign_mvaCut0.root' - #info['pf']['iKstarPsi2S_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarpsi2s.root' - #info['pf']['iKstarJpsi_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MC_kstarjpsi.root' - #info['pf']['iKJpsiee_BKG'] = '../data/data_PFe_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_0_MCres.root' - #info['pf']['n_mc_psi2s'] = 483443.0 - #info['pf']['n_mc_partial'] = 439520.0 - ##info['pf']['n_mc_partial'] = 373882.0 - - # PF-LP - #info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_data_mvaCut0.root' - #info['mix']['psi2s_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MCPsi2S.root'.format('marker') - #info['mix']['partial_mc'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_{}_MC_kstarpsi2s.root'.format('marker') - #info['mix']['isgn'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCPsi2S.root' - #info['mix']['iKstarPsi2S_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarpsi2s.root' - #info['mix']['iKstarJpsi_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MC_kstarjpsi.root' - #info['mix']['iKJpsiee_BKG'] = '../data/data_LowPtPF_v7.3/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_0_MCres.root' - #info['mix']['n_mc_psi2s'] = 483443.0 - #info['mix']['n_mc_partial'] = 439520.0 - # PF-PF nonreg info['pf']['inputfile'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_data_mvaCut0.root' info['pf']['psi2s_mc'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_{}_MCPsi2S.root'.format('marker') @@ -87,6 +62,8 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['pf']['n_mc_partial'] = 443318.0 info['pf']['n_mc_kstarplus'] = 395456.0 info['pf']['ibkg'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_samesign_mvaCut0.root' + info['pf']['iotherB'] = '../data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC_otherb.root' + # PF-LP nonreg info['mix']['inputfile'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_data_mvaCut0.root' @@ -102,6 +79,7 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): info['mix']['n_mc_partial'] = 443318.0 info['mix']['n_mc_kstarplus'] = 395456.0 info['mix']['ibkg'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_samesign_mvaCut0.root' + info['mix']['iotherB'] = '../data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC_otherb.root' selection = {} @@ -140,12 +118,15 @@ def get_df(root_file_name, tree='mytreefit', branches=['*']): if eleType == 'pf': #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], frac_ratio, cut, log) - com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iotherB={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb,bkg_otherb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iotherB'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + else: #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kjpsi_ee" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], frac_ratio, cut, log) #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, cut, log) - com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + #com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) + com = 'python KPsi2S_roofit_plb_modified_kde_fixedPartial.py -i {} -o psi2s_fixedPartial_{} --isgn={} --iotherB={} --iKstarPsi2S_BKG={} --iKstarPlusPsi2S_BKG={} --iKstarJpsi_BKG={} --iKJpsiee_BKG={} --ibkg={} --sel_primitive="sgn,bkg_kstarpsi2s,bkg_kstarjpsi,bkg_kstarpluspsi2s,bkg_kjpsi_ee,bkg_comb,bkg_otherb" --fit_primitive --partial_ratio={} --partial_ratio_kstarplus={} --mvacut={} --log={}'.format(info[eleType]['inputfile'], eleType, info[eleType]['isgn'], info[eleType]['iotherB'], info[eleType]['iKstarPsi2S_BKG'], info[eleType]['iKstarPlusPsi2S_BKG'], info[eleType]['iKstarJpsi_BKG'], info[eleType]['iKJpsiee_BKG'], info[eleType]['ibkg'], frac_ratio, frac_ratio_kstarplus, cut, log) From 41fce2dc5f81d079deca1da0195c8a76e5612002 Mon Sep 17 00:00:00 2001 From: ottolau Date: Fri, 2 Sep 2022 18:38:58 +0200 Subject: [PATCH 13/13] added plotting scripts --- plotting/CMS_lumi.py | 126 +++++++++++++++++++ plotting/compare_sig_bkg_distribution.py | 43 +++++++ plotting/helper.py | 144 +++++++++++++++++++++ plotting/plotting_tdr.py | 134 ++++++++++++++++++++ plotting/tdrstyle.py | 152 +++++++++++++++++++++++ 5 files changed, 599 insertions(+) create mode 100644 plotting/CMS_lumi.py create mode 100644 plotting/compare_sig_bkg_distribution.py create mode 100644 plotting/helper.py create mode 100644 plotting/plotting_tdr.py create mode 100644 plotting/tdrstyle.py diff --git a/plotting/CMS_lumi.py b/plotting/CMS_lumi.py new file mode 100644 index 0000000..b82906e --- /dev/null +++ b/plotting/CMS_lumi.py @@ -0,0 +1,126 @@ +import ROOT as rt + +# CMS_lumi +# Initiated by: Gautier Hamel de Monchenault (Saclay) +# Translated in Python by: Joshua Hardenbrook (Princeton) +# Updated by: Dinko Ferencek (Rutgers) +# + +cmsText = "CMS"; +cmsTextFont = 61 + +writeExtraText = True +extraText = "Preliminary" +extraTextFont = 52 + +lumiTextSize = 0.6 +lumiTextOffset = 0.2 + +cmsTextSize = 0.75 +cmsTextOffset = 0.1 + +relPosX = 0.045 +relPosY = 0.035 +relExtraDY = 1.2 + +extraOverCmsTextSize = 0.76 + +lumi_13TeV = "20.1 fb^{-1}" +lumi_8TeV = "19.7 fb^{-1}" +lumi_7TeV = "5.1 fb^{-1}" +lumi_sqrtS = "" + +drawLogo = False + +def CMS_lumi(pad, lumiText, iPosX): + outOfFrame = False + if(iPosX/10==0 ): outOfFrame = True + + alignY_=3 + alignX_=2 + if( iPosX/10==0 ): alignX_=1 + if( iPosX==0 ): alignY_=1 + if( iPosX/10==1 ): alignX_=1 + if( iPosX/10==2 ): alignX_=2 + if( iPosX/10==3 ): alignX_=3 + align_ = 10*alignX_ + alignY_ + + H = pad.GetWh() + W = pad.GetWw() + l = pad.GetLeftMargin() + t = pad.GetTopMargin() + r = pad.GetRightMargin() + b = pad.GetBottomMargin() + e = 0.025 + + pad.cd() + + print lumiText + + latex = rt.TLatex() + latex.SetNDC() + latex.SetTextAngle(0) + latex.SetTextColor(rt.kBlack) + + extraTextSize = extraOverCmsTextSize*cmsTextSize + + latex.SetTextFont(42) + latex.SetTextAlign(31) + latex.SetTextSize(lumiTextSize*t) + + latex.DrawLatex(1-r,1-t+lumiTextOffset*t,lumiText) + + if( outOfFrame ): + latex.SetTextFont(cmsTextFont) + latex.SetTextAlign(11) + latex.SetTextSize(cmsTextSize*t) + latex.DrawLatex(l,1-t+lumiTextOffset*t,cmsText) + + pad.cd() + + posX_ = 0 + if( iPosX%10<=1 ): + posX_ = l + relPosX*(1-l-r) + elif( iPosX%10==2 ): + posX_ = l + 0.5*(1-l-r) + elif( iPosX%10==3 ): + posX_ = 1-r - relPosX*(1-l-r) + + posY_ = 1-t - relPosY*(1-t-b) + + if( not outOfFrame ): + if( drawLogo ): + posX_ = l + 0.045*(1-l-r)*W/H + posY_ = 1-t - 0.045*(1-t-b) + xl_0 = posX_ + yl_0 = posY_ - 0.15 + xl_1 = posX_ + 0.15*H/W + yl_1 = posY_ + CMS_logo = rt.TASImage("CMS-BW-label.png") + pad_logo = rt.TPad("logo","logo", xl_0, yl_0, xl_1, yl_1 ) + pad_logo.Draw() + pad_logo.cd() + CMS_logo.Draw("X") + pad_logo.Modified() + pad.cd() + else: + latex.SetTextFont(cmsTextFont) + latex.SetTextSize(cmsTextSize*t) + latex.SetTextAlign(align_) + latex.DrawLatex(posX_, posY_, cmsText) + if( writeExtraText ) : + latex.SetTextFont(extraTextFont) + latex.SetTextAlign(align_) + latex.SetTextSize(extraTextSize*t) + latex.DrawLatex(posX_, posY_- relExtraDY*cmsTextSize*t, extraText) + elif( writeExtraText ): + if( iPosX==0): + posX_ = l + relPosX*(1-l-r) + posY_ = 1-t+lumiTextOffset*t + + latex.SetTextFont(extraTextFont) + latex.SetTextSize(extraTextSize*t) + latex.SetTextAlign(align_) + latex.DrawLatex(posX_, posY_, extraText) + + pad.Update() diff --git a/plotting/compare_sig_bkg_distribution.py b/plotting/compare_sig_bkg_distribution.py new file mode 100644 index 0000000..2858afe --- /dev/null +++ b/plotting/compare_sig_bkg_distribution.py @@ -0,0 +1,43 @@ +import pandas as pd +import numpy as np +from collections import OrderedDict +import itertools +import os, sys, copy +from helper import get_df +from plotting_tdr import plot_hist + +if __name__ == "__main__": + #inputfile_sig = '/afs/cern.ch/user/k/klau/myWorkspace/private/GeorgeCode/Fit/CMSSW_10_4_0/src/Fit/data/data_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_MC.root' + #inputfile_bkg = '/eos/user/k/klau/RK_ntuples/with_BDT_PFe_v7.3_nonreg_ottoCut/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_PFe_v7.3_nonreg_ottoCut_0_samesign.root' + inputfile_sig = '/afs/cern.ch/user/k/klau/myWorkspace/private/GeorgeCode/Fit/CMSSW_10_4_0/src/Fit/data/data_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_MC.root' + inputfile_bkg = '/eos/user/k/klau/RK_ntuples/with_BDT_LowPtPF_v7.3_nonreg/forMeas_xgbmodel_kee_12B_kee_correct_pu_Depth17_LowPtPF_v7.3_nonreg_0_samesign.root' + + outputfile = 'test' + + config = {} + config['xlabel'] = 'BDT' + config['nbins'] = 50 + config['xmin'] = -13.0 + config['xmax'] = 13.0 + config['SetLogy'] = True + config['draw_options'] = 'HIST' + + sig_df = get_df(inputfile_sig, tree='mytreefit') + bkg_df = get_df(inputfile_bkg, tree='mytreefit') + + bkg_df = bkg_df.sample(n=1000000) + + + branches_dict = OrderedDict() + branches_dict['Data'] = {} + branches_dict['Data']['branches'] = bkg_df['xgb'].values + branches_dict['Data']['color'] = 1 + + branches_dict['MC'] = {} + branches_dict['MC']['branches'] = sig_df['xgb'].values + branches_dict['MC']['color'] = 2 + + plot_hist(branches_dict, config, outputfile) + + + diff --git a/plotting/helper.py b/plotting/helper.py new file mode 100644 index 0000000..234af33 --- /dev/null +++ b/plotting/helper.py @@ -0,0 +1,144 @@ +import numpy as np +import uproot +import pandas as pd +import ROOT + +ELECTRON_MASS = 0.000511 +K_MASS = 0.493677 +PI_MASS = 0.139570 +#NR_LOW = np.sqrt(1.1) +LOWQ2_LOW = np.sqrt(0.045) +LOWQ2_UP = 2.5 +JPSI_MC = 3.08991 +JPSI_SIGMA_MC = 0.04205 +JPSI_LOW = 2.8 +#JPSI_UP = JPSI_MC + 3.0*JPSI_SIGMA_MC +JPSI_UP = 3.25 +PSI2S_LOW = 3.4 +PSI2S_UP = 3.85 +HIGHQ2_UP = np.sqrt(25.0) +PHI_SIGMA_MC = 0.0026836 +PHI_LOW = 1.01957 - 4.0*PHI_SIGMA_MC +PHI_UP = 1.01957 + 4.0*PHI_SIGMA_MC +B_MC = 5.2676 +B_SIGMA_MC = 0.06070 +#B_LOW = B_MC - 3.0*B_SIGMA_MC +#B_UP = B_MC + 3.0*B_SIGMA_MC +#B_LOW = 5.05 +B_LOW = 5.05 +B_UP = 5.45 +BS_LOW = 5.15 +BS_UP = 5.55 +B_SB_LOW = B_MC - 6.0*B_SIGMA_MC +B_SB_UP = B_MC + 6.0*B_SIGMA_MC +BLIND_LOW = 5.05 +BLIND_UP = 5.4 +B_FOM_LOW = 5.05 +B_FOM_UP = 5.4 +#B_FOM_LOW = 5.183 +#B_FOM_UP = 5.353 +B_MIN = 4.7 +B_MAX = 6.0 +FIT_LOW = 4.7 +FIT_UP = 6.0 +D_MASS_CUT = 1.9 +BR_BToKJpsi = 1.01e-3 +BR_JpsiToLL = 0.0597 +BR_BToKLL = 4.51e-7 +BR_BToPhiJpsi = 1.08e-3 +BR_PhiToKK = 0.492 +BR_BToPhiLL = 8.2e-7 + +#params_lowq2_pf = {'mean': 5.27116, 'width': 0.05432, 'alpha1': 0.662, 'n1': 3.05, 'alpha2': 2.71, 'n2': 2.71, 'mean_gaus': 5.249, 'sigma': 0.223, 'f1': 0.928} +#params_lowq2_mix = {'mean': 5.268012, 'width': 0.057381, 'alpha1': 0.59669, 'n1': 1.8979, 'alpha2': 1.3315, 'n2': 1.7794, 'mean_gaus': 5.18, 'sigma': 0.26, 'f1': 1.0} +#params_jpsi_pf = {'mean': 5.2761, 'width': 0.0613, 'alpha1': 1.255, 'n1': 8.6, 'alpha2': 1.284, 'n2': 27.0, 'mean_gaus': 5.159, 'sigma': 0.1220, 'f1': 0.678} +#params_jpsi_mix = {'mean': 5.2733, 'width': 0.0608, 'alpha1': 1.17, 'n1': 9.1, 'alpha2': 1.239, 'n2': 18.2, 'mean_gaus': 5.151, 'sigma': 0.1249, 'f1': 0.626} +#params_psi2s_pf = {'mean': 5.2703, 'width': 0.07803, 'alpha1': 0.912, 'n1': 30.0, 'alpha2': 3.13, 'n2': 2.6, 'mean_gaus': 5.013, 'sigma': 0.1103, 'f1': 0.891} +#params_psi2s_mix = {'mean': 5.26297, 'width': 0.08076, 'alpha1': 0.785, 'n1': 30.0, 'alpha2': 2.457, 'n2': 8.1, 'mean_gaus': 4.9803, 'sigma': 0.1036, 'f1': 0.885} +#params_highq2_pf = {'mean': 5.27876, 'width': 0.0703, 'alpha1': 0.716, 'n1': 30.0, 'alpha2': 1.108, 'n2': 2.05, 'mean_gaus': 5.231, 'sigma': 0.270, 'f1': 0.906} +#params_highq2_mix = {'mean': 5.275092, 'width': 0.0716, 'alpha1': 0.729, 'n1': 6.0, 'alpha2': 1.157, 'n2': 1.815, 'mean_gaus': 5.182, 'sigma': 0.217, 'f1': 0.900} + +#params_lowq2_pf = {'mean': 5.27128, 'width': 0.05426, 'alpha1': 0.661, 'n1': 3.11, 'alpha2': 1.338, 'n2': 2.71, 'mean_gaus': 5.262, 'sigma': 0.222, 'f1': 0.928} +#params_lowq2_mix = {'mean': 5.26813, 'width': 0.05712, 'alpha1': 0.597, 'n1': 1.969, 'alpha2': 1.335, 'n2': 1.754, 'mean_gaus': 5.16, 'sigma': 0.16, 'f1': 1.0} +#params_jpsi_pf = {'mean': 5.2772384, 'width': 0.0606701, 'alpha1': 1.847, 'n1': 6.072, 'alpha2': 1.45, 'n2': 12.793, 'mean_gaus': 5.175703, 'sigma': 0.124347, 'f1': 0.58505} +#params_jpsi_mix = {'mean': 5.2746, 'width': 0.0599, 'alpha1': 1.59, 'n1': 30.0, 'alpha2': 1.327, 'n2': 12.0, 'mean_gaus': 5.1595, 'sigma': 0.1265, 'f1': 0.549} +#params_psi2s_pf = {'mean': 5.2711, 'width': 0.07851, 'alpha1': 1.030, 'n1': 30.0, 'alpha2': 3.39, 'n2': 1.58, 'mean_gaus': 5.027, 'sigma': 0.1146, 'f1': 0.866} +#params_psi2s_mix = {'mean': 5.2634, 'width': 0.08132, 'alpha1': 0.805, 'n1': 30.0, 'alpha2': 2.9, 'n2': 3.7, 'mean_gaus': 4.9796, 'sigma': 0.1008, 'f1': 0.887} +#params_highq2_pf = {'mean': 5.28204, 'width': 0.0688, 'alpha1': 0.838, 'n1': 30.0, 'alpha2': 1.104, 'n2': 1.55, 'mean_gaus': 5.250, 'sigma': 0.213, 'f1': 0.880} +#params_highq2_mix = {'mean': 5.27963, 'width': 0.0708, 'alpha1': 0.834, 'n1': 30.0, 'alpha2': 1.055, 'n2': 1.73, 'mean_gaus': 5.126, 'sigma': 0.174, 'f1': 0.896} + +# tightPreselectionWODmass +#params_lowq2_pf = {'mean': 5.2725, 'width': 0.0565, 'alpha1': 0.642, 'n1': 4.4, 'alpha2': 1.54, 'n2': 2.53, 'mean_gaus': 5.42, 'sigma': 0.173, 'f1': 0.95} +#params_lowq2_mix = {'mean': 5.2733, 'width': 0.0466, 'alpha1': 0.511, 'n1': 1.559, 'alpha2': 1.71, 'n2': 1.0, 'mean_gaus': 5.2639, 'sigma': 0.1070, 'f1': 0.748} +#params_jpsi_pf = {'mean': 5.2769, 'width': 0.0585, 'alpha1': 1.3, 'n1': 7.1, 'alpha2': 1.354, 'n2': 21.0, 'mean_gaus': 5.17, 'sigma': 0.122, 'f1': 0.659} +#params_jpsi_mix = {'mean': 5.2757, 'width': 0.0576, 'alpha1': 1.67, 'n1': 30.0, 'alpha2': 1.35, 'n2': 9.7, 'mean_gaus': 5.168, 'sigma': 0.1256, 'f1': 0.524} +#params_psi2s_pf = {'mean': 5.2708, 'width': 0.07621, 'alpha1': 2.022, 'n1': 7.2, 'alpha2': 3.22, 'n2': 1.9, 'mean_gaus': 5.0789, 'sigma': 0.0648, 'f1': 0.8637} +#params_psi2s_mix = {'mean': 5.2799, 'width': 0.0488, 'alpha1': 1.065, 'n1': 7.69, 'alpha2': 1.8, 'n2': 27.35, 'mean_gaus': 5.2102, 'sigma': 0.1169, 'f1': 0.347} +#params_highq2_pf = {'mean': 5.2826, 'width': 0.0656, 'alpha1': 0.86, 'n1': 30.0, 'alpha2': 1.12, 'n2': 1.92, 'mean_gaus': 5.223, 'sigma': 0.227, 'f1': 0.859} +#params_highq2_mix = {'mean': 5.2648, 'width': 0.0745, 'alpha1': 0.656, 'n1': 15.59, 'alpha2': 1.2621, 'n2': 1.614, 'mean_gaus': 5.348, 'sigma': 0.0659, 'f1': 0.893} + +# tightPreselectionWODmass nonreg +#params_lowq2_pf = {'mean': 5.2717, 'width': 0.0464, 'alpha1': 0.76, 'n1': 1.1, 'alpha2': 1.098, 'n2': 5.2, 'mean_gaus': 5.191, 'sigma': 0.082, 'f1': 0.919} +#params_lowq2_mix = {'mean': 5.2648, 'width': 0.057, 'alpha1': 0.767, 'n1': 1.22, 'alpha2': 1.56, 'n2': 2.92, 'mean_gaus': 5.167, 'sigma': 0.025, 'f1': 0.985} +#params_jpsi_pf = {'mean': 5.2749, 'width': 0.0566, 'alpha1': 0.935, 'n1': 24.0, 'alpha2': 1.306, 'n2': 29.0, 'mean_gaus': 5.131, 'sigma': 0.1155, 'f1': 0.703} +#params_jpsi_mix = {'mean': 5.2769, 'width': 0.0561, 'alpha1': 1.001, 'n1': 11.0, 'alpha2': 1.41, 'n2': 11.0, 'mean_gaus': 5.151, 'sigma': 0.1223, 'f1': 0.592} +#params_psi2s_pf = {'mean': 5.2734, 'width': 0.0675, 'alpha1': 4.8, 'n1': 15.1, 'alpha2': 1.852, 'n2': 29.9, 'mean_gaus': 5.1056, 'sigma': 0.0811, 'f1': 0.737} +#params_psi2s_mix = {'mean': 5.2683, 'width': 0.0739, 'alpha1': 2.69, 'n1': 1.41, 'alpha2': 1.75, 'n2': 30.0, 'mean_gaus': 5.087, 'sigma': 0.0739, 'f1': 0.767} +#params_highq2_pf = {'mean': 5.2723, 'width': 0.078, 'alpha1': 0.96, 'n1': 30.0, 'alpha2': 1.285, 'n2': 2.87, 'mean_gaus': 4.99, 'sigma': 0.16, 'f1': 0.91} +#params_highq2_mix = {'mean': 5.2787, 'width': 0.0692, 'alpha1': 0.88, 'n1': 23.0, 'alpha2': 3.2, 'n2': 3.0, 'mean_gaus': 5.239, 'sigma': 0.256, 'f1': 0.687} + +params_lowq2_pf = {'alpha2': 1.1009629692754412, 'f1': 0.9024023925809488, 'alpha1': 0.6125476120721379, 'mean_gaus': 5.232442102930074, 'width': 0.04478072470496805, 'n1': 1.313315209606845, 'n2': 4.6791152129047795, 'sigma': 0.07850480733068979, 'mean': 5.273613144244443} +params_lowq2_mix = {'alpha2': 1.5633821745110361, 'f1': 0.9999983033024756, 'alpha1': 0.6595605707175484, 'mean_gaus': 5.163602514498214, 'width': 0.05795398037173986, 'n1': 1.6225771280823784, 'n2': 2.8043809663297496, 'sigma': 0.09563886922175906, 'mean': 5.262448809774765} +params_jpsi_pf = {'alpha2': 1.7247947277951603, 'f1': 0.5811592325326095, 'alpha1': 1.035619091676923, 'mean_gaus': 5.164726533231734, 'width': 0.0545747228456563, 'n1': 29.93033333968999, 'n2': 7.228887909976842, 'sigma': 0.12802718642895833, 'mean': 5.276448500620768} +params_jpsi_mix = {'alpha2': 1.6083796772096242, 'f1': 0.5311608015245698, 'alpha1': 1.3662238553761452, 'mean_gaus': 5.155162045844273, 'width': 0.05696883661032993, 'n1': 29.999504152126843, 'n2': 6.544290276185018, 'sigma': 0.12468711893037616, 'mean': 5.277066466381268} +params_psi2s_pf = {'alpha2': 1.723321968636255, 'f1': 0.709845978183554, 'alpha1': 8.020735529311047, 'mean_gaus': 5.114272999717782, 'width': 0.06554152474945321, 'n1': 1.4047550026690212, 'n2': 29.99999424488338, 'sigma': 0.08451287399941626, 'mean': 5.275642452606478} +params_psi2s_mix = {'alpha2': 1.5889562441123883, 'f1': 0.695885714731663, 'alpha1': 6.627001540702466, 'mean_gaus': 5.103283983600971, 'width': 0.06610984494078814, 'n1': 1.0247071771070635, 'n2': 29.99999996457806, 'sigma': 0.08382031834714915, 'mean': 5.274927387185121} +params_highq2_pf = {'alpha2': 1.2901789002834358, 'f1': 0.9577902237044736, 'alpha1': 0.7585639271468392, 'mean_gaus': 4.922194776705961, 'width': 0.07384048036920975, 'n1': 29.9816119947674, 'n2': 2.5193114913087995, 'sigma': 0.13126249086032934, 'mean': 5.274240597686103} +params_highq2_mix = {'alpha2': 1.206924931962066, 'f1': 0.9685226252186525, 'alpha1': 0.5588227698078552, 'mean_gaus': 5.642030902646728, 'width': 0.071028580856529, 'n1': 16.86024978567461, 'n2': 29.8134081146057, 'sigma': 0.10419592078139599, 'mean': 5.291886503661944} + +params_rphi_jpsi_pf = {'mean': 5.35897, 'width': 0.05558, 'alpha1': 0.5363, 'n1': 2.76, 'alpha2': 1.269, 'n2': 20} +params_rphi_jpsi_low = {'mean': 5.3546, 'width': 0.0609, 'alpha1': 0.560, 'n1': 2.98, 'alpha2': 1.400, 'n2': 20} + +triCut_jpsi_mll_mean_pf = 3.00233244896 +triCut_jpsi_mKee_mean_pf = 5.17609024048 +triCut_jpsi_rotMatrix_pf = np.array([[0.74743241, -0.66433786], [0.66433786, 0.74743241]]) +triCut_jpsi_lower_bound_pf = -0.0977517530843 +triCut_jpsi_upper_bound_pf = 0.0824238599635 + +triCut_psi2s_mll_mean_pf = 3.58506560326 +triCut_psi2s_mKee_mean_pf = 5.17640161514 +triCut_psi2s_rotMatrix_pf = np.array([[0.72047561, -0.69348028], [0.69348028, 0.72047561]]) +triCut_psi2s_lower_bound_pf = -0.0704979038994 +triCut_psi2s_upper_bound_pf = 0.059937465045 + +def Punzi(B, a, b): + return (b*b)/2.0 + a*np.sqrt(B) + (b/2.0)*np.sqrt(b*b + 4.0*a*np.sqrt(B) + 4.0*B) + +def Punzi_simplify(eff, B, dB, a): + return eff / ((a/2.0) + np.sqrt(B + dB*dB)) + +def Significance(S, B, dB): + return S / np.sqrt(S + B + dB*dB) + +def get_df(root_file_name, tree='tree', branches=['*']): + print('Opening file {}...'.format(root_file_name)) + f = uproot.open(root_file_name) + if len(f.allkeys()) == 0: + return pd.DataFrame() + print('Not an null file') + #df = uproot.open(root_file_name)["tree"].pandas.df() + #df = pd.DataFrame(uproot.open(root_file_name)["tree"].arrays(namedecode="utf-8")) + df = pd.DataFrame(f[tree].arrays(branches=branches)) + print('Finished opening file {}...'.format(root_file_name)) + return df + +def get_diagonalCut_var(branches, mll_mean, fit_mass_mean, diagCut_lower_bound, diagCut_jpsi_upper_bound, eigVecs): + branches['BToKEE_mll_fullfit_centered'] = branches['BToKEE_mll_fullfit'] - mll_mean + branches['BToKEE_fit_mass_centered'] = branches['BToKEE_fit_mass'] - fit_mass_mean + data_centered = np.array([branches['BToKEE_fit_mass_centered'],branches['BToKEE_mll_fullfit_centered']]).T + eigVecs_jpsi = triCut_jpsi_rotMatrix_pf + data_decorr = data_centered.dot(eigVecs) + return data_decorr[:,0], data_decorr[:,1] + + + diff --git a/plotting/plotting_tdr.py b/plotting/plotting_tdr.py new file mode 100644 index 0000000..2a4d03b --- /dev/null +++ b/plotting/plotting_tdr.py @@ -0,0 +1,134 @@ +import ROOT as rt +import CMS_lumi, tdrstyle +import pandas as pd +import numpy as np +from collections import OrderedDict +from rootpy.plotting import Hist, Hist2D +from root_numpy import fill_hist, array2root, array2tree +from root_pandas import to_root +import itertools +import os, sys, copy + +#set the tdr style +tdrstyle.setTDRStyle() + +#change the CMS_lumi variables (see CMS_lumi.py) +CMS_lumi.lumi_7TeV = "4.8 fb^{-1}" +CMS_lumi.lumi_8TeV = "18.3 fb^{-1}" +CMS_lumi.writeExtraText = 1 +CMS_lumi.extraText = "Preliminary" +CMS_lumi.lumi_sqrtS = "13 TeV" # used with iPeriod = 0, e.g. for simulation-only plots (default is an empty string) +lumiText = '2018 (13 TeV)' + +iPos = 0 +#if( iPos==0 ): CMS_lumi.relPosX = 0.12 +if( iPos==0 ): CMS_lumi.relPosX = 0.16 + +H_ref = 600; +W_ref = 600; +W = W_ref +H = H_ref + +# references for T, B, L, R +T = 0.08*H_ref +B = 0.12*H_ref +#L = 0.12*W_ref +L = 0.15*W_ref +R = 0.04*W_ref + +def get_canvas(): + canvas = rt.TCanvas("c2","c2",50,50,W,H) + canvas.SetFillColor(0) + canvas.SetBorderMode(0) + canvas.SetFrameFillStyle(0) + canvas.SetFrameBorderMode(0) + canvas.SetLeftMargin( L/W ) + canvas.SetRightMargin( R/W ) + canvas.SetTopMargin( T/H ) + canvas.SetBottomMargin( B/H ) + canvas.SetTickx(0) + canvas.SetTicky(0) + return canvas + +def draw_hist(histo, xlabel, ylabel, draw_options='E'): + histo.GetYaxis().SetTitle(ylabel) + histo.GetXaxis().SetTitle(xlabel) + if (histo.GetEntries() > 0): + histo.DrawNormalized(draw_options) + #histo.Draw(draw_options) + else: + histo.Draw(draw_options) + +def plot_hist(branches_dict, config, outputfile, weights=None): + _config = { + 'xlabel': 'x', + 'nbins': 50, + 'xmin': 0.0, + 'xmax': 1.0, + 'overflow': False, + 'underflow': False, + 'SetLogy': False, + 'SetLogx': False, + 'draw_options': 'E', + } + + _config.update(config) + + for i, (name, branch_info) in enumerate(branches_dict.items()): + hist = Hist(_config['nbins'], _config['xmin'], _config['xmax'], name=name, title='', type='F') + if weights is None: + fill_hist(hist, branch_info['branches']) + else: + fill_hist(hist, branch_info['branches'], weights=weights[i]) + + branches_dict[name]['hist'] = hist + + canvas = get_canvas() + canvas.cd() + + l1 = rt.TLegend(0.4,0.2,0.92,0.4) + l1.SetTextSize(0.035) + l1.SetFillStyle(0) + l1.SetBorderSize(0) + + hists = [branch_info['hist'] for branch_info in branches_dict.values()] + for hist in hists: + x_min = 1 + x_max = hist.GetNbinsX() + if _config['overflow']: x_max += 1 + if _config['underflow']: x_min = 0 + hist.GetXaxis().SetRange(x_min, x_max) + + ylabel = 'Events' if len(branches_dict) < 2 else 'a.u.' + + first_hist = True + for name, branch_info in branches_dict.items(): + hist, color = branch_info['hist'], branch_info['color'] + hist.SetMarkerStyle(0) + #hist.SetFillStyle(0) + hist.SetLineColor(color) + if first_hist: + y_max = hist.GetMaximum() + if len(branches_dict) > 1: + hist.SetMaximum(1.3*y_max) + draw_hist(hist, _config['xlabel'], ylabel, draw_options=_config['draw_options']) + first_hist = False + else: + draw_hist(hist, _config['xlabel'], ylabel, draw_options='{} SAME'.format(_config['draw_options'])) + + l1.AddEntry(hist, name) + + if len(hist) > 1: l1.Draw("same") + + CMS_lumi.CMS_lumi(canvas, lumiText, iPos) + + if _config['SetLogy']: rt.gPad.SetLogy() + if _config['SetLogx']: rt.gPad.SetLogx() + + canvas.cd() + canvas.Update() + canvas.RedrawAxis() + canvas.SaveAs(outputfile+'.pdf') + canvas.Close() + + diff --git a/plotting/tdrstyle.py b/plotting/tdrstyle.py new file mode 100644 index 0000000..3b5dc11 --- /dev/null +++ b/plotting/tdrstyle.py @@ -0,0 +1,152 @@ +import ROOT as rt + +def tdrGrid( gridOn): + tdrStyle.SetPadGridX(gridOn) + tdrStyle.SetPadGridY(gridOn) + +#fixOverlay: Redraws the axis +def fixOverlay(): gPad.RedrawAxis() + +def setTDRStyle(): + tdrStyle = rt.TStyle("tdrStyle","Style for P-TDR") + + #for the canvas: + tdrStyle.SetCanvasBorderMode(0) + tdrStyle.SetCanvasColor(rt.kWhite) + tdrStyle.SetCanvasDefH(600) #Height of canvas + tdrStyle.SetCanvasDefW(600) #Width of canvas + tdrStyle.SetCanvasDefX(0) #POsition on screen + tdrStyle.SetCanvasDefY(0) + + + tdrStyle.SetPadBorderMode(0) + #tdrStyle.SetPadBorderSize(Width_t size = 1) + tdrStyle.SetPadColor(rt.kWhite) + tdrStyle.SetPadGridX(False) + tdrStyle.SetPadGridY(False) + tdrStyle.SetGridColor(0) + tdrStyle.SetGridStyle(3) + tdrStyle.SetGridWidth(1) + +#For the frame: + tdrStyle.SetFrameBorderMode(0) + tdrStyle.SetFrameBorderSize(1) + tdrStyle.SetFrameFillColor(0) + tdrStyle.SetFrameFillStyle(0) + tdrStyle.SetFrameLineColor(1) + tdrStyle.SetFrameLineStyle(1) + tdrStyle.SetFrameLineWidth(1) + +#For the histo: + #tdrStyle.SetHistFillColor(1) + #tdrStyle.SetHistFillStyle(0) + tdrStyle.SetHistLineColor(1) + tdrStyle.SetHistLineStyle(0) + tdrStyle.SetHistLineWidth(1) + #tdrStyle.SetLegoInnerR(Float_t rad = 0.5) + #tdrStyle.SetNumberContours(Int_t number = 20) + + tdrStyle.SetEndErrorSize(2) + #tdrStyle.SetErrorMarker(20) + #tdrStyle.SetErrorX(0.) + + tdrStyle.SetMarkerStyle(20) + +#For the fit/function: + tdrStyle.SetOptFit(1) + tdrStyle.SetFitFormat("5.4g") + tdrStyle.SetFuncColor(2) + tdrStyle.SetFuncStyle(1) + tdrStyle.SetFuncWidth(1) + +#For the date: + tdrStyle.SetOptDate(0) + # tdrStyle.SetDateX(Float_t x = 0.01) + # tdrStyle.SetDateY(Float_t y = 0.01) + +# For the statistics box: + tdrStyle.SetOptFile(0) + tdrStyle.SetOptStat(0) # To display the mean and RMS: SetOptStat("mr") + tdrStyle.SetStatColor(rt.kWhite) + tdrStyle.SetStatFont(42) + tdrStyle.SetStatFontSize(0.025) + tdrStyle.SetStatTextColor(1) + tdrStyle.SetStatFormat("6.4g") + tdrStyle.SetStatBorderSize(1) + tdrStyle.SetStatH(0.1) + tdrStyle.SetStatW(0.15) + # tdrStyle.SetStatStyle(Style_t style = 1001) + # tdrStyle.SetStatX(Float_t x = 0) + # tdrStyle.SetStatY(Float_t y = 0) + +# Margins: + tdrStyle.SetPadTopMargin(0.05) + tdrStyle.SetPadBottomMargin(0.13) + tdrStyle.SetPadLeftMargin(0.16) + tdrStyle.SetPadRightMargin(0.02) + +# For the Global title: + + tdrStyle.SetOptTitle(0) + tdrStyle.SetTitleFont(42) + tdrStyle.SetTitleColor(1) + tdrStyle.SetTitleTextColor(1) + tdrStyle.SetTitleFillColor(10) + tdrStyle.SetTitleFontSize(0.05) + # tdrStyle.SetTitleH(0) # Set the height of the title box + # tdrStyle.SetTitleW(0) # Set the width of the title box + # tdrStyle.SetTitleX(0) # Set the position of the title box + # tdrStyle.SetTitleY(0.985) # Set the position of the title box + # tdrStyle.SetTitleStyle(Style_t style = 1001) + # tdrStyle.SetTitleBorderSize(2) + +# For the axis titles: + + tdrStyle.SetTitleColor(1, "XYZ") + tdrStyle.SetTitleFont(42, "XYZ") + tdrStyle.SetTitleSize(0.06, "XYZ") + # tdrStyle.SetTitleXSize(Float_t size = 0.02) # Another way to set the size? + # tdrStyle.SetTitleYSize(Float_t size = 0.02) + tdrStyle.SetTitleXOffset(0.9) + tdrStyle.SetTitleYOffset(1.25) + # tdrStyle.SetTitleOffset(1.1, "Y") # Another way to set the Offset + +# For the axis labels: + + tdrStyle.SetLabelColor(1, "XYZ") + tdrStyle.SetLabelFont(42, "XYZ") + tdrStyle.SetLabelOffset(0.007, "XYZ") + tdrStyle.SetLabelSize(0.05, "XYZ") + +# For the axis: + + tdrStyle.SetAxisColor(1, "XYZ") + tdrStyle.SetStripDecimals(True) + tdrStyle.SetTickLength(0.03, "XYZ") + tdrStyle.SetNdivisions(510, "XYZ") + tdrStyle.SetPadTickX(1) # To get tick marks on the opposite side of the frame + tdrStyle.SetPadTickY(1) + +# Change for log plots: + tdrStyle.SetOptLogx(0) + tdrStyle.SetOptLogy(0) + tdrStyle.SetOptLogz(0) + +# Postscript options: + tdrStyle.SetPaperSize(20.,20.) + # tdrStyle.SetLineScalePS(Float_t scale = 3) + # tdrStyle.SetLineStyleString(Int_t i, const char* text) + # tdrStyle.SetHeaderPS(const char* header) + # tdrStyle.SetTitlePS(const char* pstitle) + + # tdrStyle.SetBarOffset(Float_t baroff = 0.5) + # tdrStyle.SetBarWidth(Float_t barwidth = 0.5) + # tdrStyle.SetPaintTextFormat(const char* format = "g") + # tdrStyle.SetPalette(Int_t ncolors = 0, Int_t* colors = 0) + # tdrStyle.SetTimeOffset(Double_t toffset) + # tdrStyle.SetHistMinimumZero(kTRUE) + + tdrStyle.SetHatchesLineWidth(5) + tdrStyle.SetHatchesSpacing(0.05) + + tdrStyle.cd()