linelow.SetLineWidth(2) lineup.SetLineWidth(2) #linelow.Draw() #lineup.Draw() #tot.paramOn(phiFrame,RooFit.Layout(0.57,0.99,0.65)) sigevents = () masskk.setRange("phiregion_five",phimass-0.005,phimass+0.005) masskk.setRange("phiregion_ten",phimass-0.01,phimass+0.01) masskk.setRange("totrange",phimin,phimax) totIntegralSig = signal.createIntegral(RooArgSet(masskk),"totrange").getVal() totIntegralBkg = bkg.analyticalIntegral(bkg.getAnalyticalIntegral(RooArgSet(masskk),RooArgSet(masskk)),"totrange") totIntegralTot = tot.createIntegral(RooArgSet(masskk),"totrange").getVal() fiveIntegralSig = signal.createIntegral(RooArgSet(masskk),"phiregion_five").getVal() tenIntegralSig = signal.createIntegral(RooArgSet(masskk),"phiregion_ten").getVal() fiveIntegralBkg = bkg.analyticalIntegral(bkg.getAnalyticalIntegral(RooArgSet(masskk),RooArgSet(masskk)),"phiregion_five") tenIntegralBkg = bkg.analyticalIntegral(bkg.getAnalyticalIntegral(RooArgSet(masskk),RooArgSet(masskk)),"phiregion_ten") fiveIntegralTot = tot.createIntegral(RooArgSet(masskk),"phiregion_five").getVal() tenIntegralTot = tot.createIntegral(RooArgSet(masskk),"phiregion_ten").getVal() fiveIntegralSig = fiveIntegralSig * nSig.getValV() / totIntegralSig tenIntegralSig = tenIntegralSig * nSig.getValV() / totIntegralSig
def doDataFit(Chib1_parameters,Chib2_parameters, cuts, inputfile_name = None, RooDataSet = None, ptBin_label='', plotTitle = "#chi_{b}",fittedVariable='qValue', printSigReso = False, noPlots = False, useOtherSignalParametrization = False, useOtherBackgroundParametrization = False, massFreeToChange = False, sigmaFreeToChange = False, legendOnPlot=True, drawPulls=False, titleOnPlot=False, cmsOnPlot=True, printLegend=True): if RooDataSet != None: dataSet = RooDataSet elif inputfile_name != None: print "Creating DataSet from file "+str(inputfile_name) dataSet = makeRooDataset(inputfile_name) else: raise ValueError('No dataset and no inputfile passed to function doDataFit') if(fittedVariable == 'refittedMass'): x_var = 'rf1S_chib_mass' output_suffix = '_refit' x_axis_label= 'm_{#mu^{+} #mu^{-} #gamma} [GeV]' else: x_var = 'invm1S' output_suffix = '_qValue' x_axis_label = 'm_{#gamma #mu^{+} #mu^{-}} - m_{#mu^{+} #mu^{-}} + m^{PDG}_{#Upsilon} [GeV]' cuts_str = str(cuts) #cuts_str = quality_cut + "photon_pt > 0.5 && abs(photon_eta) < 1.0 && ctpv < 0.01 && abs(dimuon_rapidity) < 1.3 && pi0_abs_mass > 0.025 && abs(dz) < 0.5" data = dataSet.reduce( RooFit.Cut(cuts_str) ) print 'Creating pdf' x=RooRealVar(x_var, 'm(#mu #mu #gamma) - m(#mu #mu) + m_{#Upsilon}',9.7,10.1,'GeV') numBins = 80 # define here so that if I change it also the ndof change accordingly x.setBins(numBins) # cristal balls mean_1 = RooRealVar("mean_1","mean ChiB1",Chib1_parameters.mean,"GeV") sigma_1 = RooRealVar("sigma_1","sigma ChiB1",Chib1_parameters.sigma,'GeV') a1_1 = RooRealVar('#alpha1_1', '#alpha1_1', Chib1_parameters.a1) n1_1 = RooRealVar('n1_1', 'n1_1', Chib1_parameters.n1) a2_1 = RooRealVar('#alpha2_1', '#alpha2_1',Chib1_parameters.a2) n2_1 = RooRealVar('n2_1', 'n2_1', Chib1_parameters.n2) parameters = RooArgSet(a1_1, a2_1, n1_1, n2_1) mean_2 = RooRealVar("mean_2","mean ChiB2",Chib2_parameters.mean,"GeV") sigma_2 = RooRealVar("sigma_2","sigma ChiB2",Chib2_parameters.sigma,'GeV') a1_2 = RooRealVar('#alpha1_2', '#alpha1_2', Chib2_parameters.a1) n1_2 = RooRealVar('n1_2', 'n1_2', Chib2_parameters.n1) a2_2 = RooRealVar('#alpha2_2', '#alpha2_2', Chib2_parameters.a2) n2_2 = RooRealVar('n2_2', 'n2_2', Chib2_parameters.n2) parameters.add(RooArgSet( a1_2, a2_2, n1_2, n2_2)) if massFreeToChange: # scale_mean = RooRealVar('scale_mean', 'Scale that multiplies masses found with MC', 0.8,1.2) # mean_1_fixed = RooRealVar("mean_1_fixed","mean ChiB1",Chib1_parameters.mean,"GeV") # mean_2_fixed = RooRealVar("mean_2_fixed","mean ChiB2",Chib2_parameters.mean,"GeV") # mean_1 = RooFormulaVar("mean_1",'@0*@1', RooArgList(scale_mean, mean_1_fixed)) # mean_2 = RooFormulaVar("mean_2",'@0*@1', RooArgList(scale_mean, mean_2_fixed)) variazione_m = 0.05 # 50 MeV diff_m_12 = RooRealVar('diff_m_12', 'Difference between masses chib1 and chib2',0.0194,'GeV') # 19.4 MeV from PDG mean_1=RooRealVar("mean_1","mean ChiB1",Chib1_parameters.mean,Chib1_parameters.mean-variazione_m,Chib1_parameters.mean+variazione_m ,"GeV") mean_2=RooFormulaVar('mean_2', '@0+@1',RooArgList(mean_1, diff_m_12)) # mean_2=RooRealVar("mean_2","mean ChiB2",Chib2_parameters.mean,Chib2_parameters.mean-variazione_m,Chib2_parameters.mean+variazione_m ,"GeV") parameters.add(mean_1) else: parameters.add(RooArgSet(mean_1, mean_2)) chib1_pdf = My_double_CB('chib1', 'chib1', x, mean_1, sigma_1, a1_1, n1_1, a2_1, n2_1) chib2_pdf = My_double_CB('chib2', 'chib2', x, mean_2, sigma_2, a1_2, n1_2, a2_2, n2_2) if sigmaFreeToChange: scale_sigma = RooRealVar('scale_sigma', 'Scale that multiplies sigmases found with MC', 1, 1.1)#1.01 sigma_1_fixed = RooRealVar("sigma_1","sigma ChiB1",Chib1_parameters.sigma,'GeV') sigma_2_fixed = RooRealVar("sigma_2","sigma ChiB2",Chib2_parameters.sigma,'GeV') sigma_1 = RooFormulaVar("sigma_1",'@0*@1', RooArgList(scale_sigma, sigma_1_fixed)) sigma_2 = RooFormulaVar("sigma_2",'@0*@1', RooArgList(scale_sigma, sigma_2_fixed)) parameters.add(scale_sigma) else: parameters.add(RooArgSet(sigma_1, sigma_2)) chib1_pdf = My_double_CB('chib1', 'chib1', x, mean_1, sigma_1, a1_1, n1_1, a2_1, n2_1) chib2_pdf = My_double_CB('chib2', 'chib2', x, mean_2, sigma_2, a1_2, n1_2, a2_2, n2_2) if useOtherSignalParametrization: # In this case I redefine cb_pdf cb1 = RooCBShape('cb1', 'cb1', x, mean_1, sigma_1, a1_1, n1_1) cb2 = RooCBShape('cb2', 'cb2', x, mean_2, sigma_2, a1_2, n1_2) # I use a2 as the sigma of my gaussian gauss1 = RooCBShape('gauss1', 'gauss1',x, mean_1, a2_1, a1_1, n1_1) gauss2 = RooCBShape('gauss2', 'gauss2',x, mean_2, a2_2, a1_2, n1_2) # I use n2 as the ratio of cb with respect to gauss chib1_pdf = RooAddPdf('chib1','chib1',RooArgList(cb1, gauss1),RooArgList(n2_1)) chib2_pdf = RooAddPdf('chib2','chib2',RooArgList(cb2, gauss2),RooArgList(n2_2)) #background q01S_Start = 9.5 alpha = RooRealVar("#alpha","#alpha",1.5,-1,3.5)#0.2 anziche' 1 beta = RooRealVar("#beta","#beta",-2.5,-7.,0.) q0 = RooRealVar("q0","q0",q01S_Start)#,9.5,9.7) delta = RooFormulaVar("delta","TMath::Abs(@0-@1)",RooArgList(x,q0)) b1 = RooFormulaVar("b1","@0*(@1-@2)",RooArgList(beta,x,q0)) signum1 = RooFormulaVar( "signum1","( TMath::Sign( -1.,@0-@1 )+1 )/2.", RooArgList(x,q0) ) background = RooGenericPdf("background","Background", "signum1*pow(delta,#alpha)*exp(b1)", RooArgList(signum1,delta,alpha,b1) ) if useOtherBackgroundParametrization: # in thies case I redefine background a0 = RooRealVar('a0','a0',1.,-1.,1.) #,0.5,0.,1.) a1 = RooRealVar('a1','a1',0.1,-1.,1.) #-0.2,0.,1.) #a2 = RooRealVar('a2','a2',-0.1,1.,-1.) background = RooChebychev('background','Background',x,RooArgList(a0,a1)) parameters.add(RooArgSet(a0, a1)) else: parameters.add(RooArgSet(alpha, beta, q0)) #together chibs = RooArgList(chib1_pdf,chib2_pdf,background) # ndof floatPars = parameters.selectByAttrib("Constant",ROOT.kFALSE) ndof = numBins - floatPars.getSize() - 1 # # Here I have as parameters N1, N2, and N_background # n_chib1 = RooRealVar("n_chib1","n_chib1",1250, 0, 50000) # n_chib2 = RooRealVar("n_chib2","n_chib2",825, 0, 50000) # n_background = RooRealVar('n_background','n_background',4550, 0, 50000) # ratio_list = RooArgList(n_chib1, n_chib2, n_background) # modelPdf = RooAddPdf('ModelPdf', 'ModelPdf', chibs, ratio_list) # Here I have as parameters N_12, ratio_12, N_background n_chib = RooRealVar("n_chib","n_chib",2075, 0, 100000) ratio_21 = RooRealVar("ratio_21","ratio_21",0.6, 0, 1) n_chib1 = RooFormulaVar("n_chib1","@0/(1+@1)",RooArgList(n_chib, ratio_21)) n_chib2 = RooFormulaVar("n_chib2","@0/(1+1/@1)",RooArgList(n_chib, ratio_21)) n_background = RooRealVar('n_background','n_background',4550, 0, 50000) ratio_list = RooArgList(n_chib1, n_chib2, n_background) parameters.add(RooArgSet(n_chib1, n_chib2, n_background)) modelPdf = RooAddPdf('ModelPdf', 'ModelPdf', chibs, ratio_list) print 'Fitting to data' fit_region = x.setRange("fit_region",9.7,10.1) result=modelPdf.fitTo(data,RooFit.Save(), RooFit.Range("fit_region")) # define frame frame = x.frame() frame.SetNameTitle("fit_resonance","Fit Resonanace") frame.GetXaxis().SetTitle(x_axis_label ) frame.GetYaxis().SetTitle( "Events/5 MeV " ) frame.GetXaxis().SetTitleSize(0.04) frame.GetYaxis().SetTitleSize(0.04) frame.GetXaxis().SetTitleOffset(1.1) frame.GetXaxis().SetLabelSize(0.04) frame.GetYaxis().SetLabelSize(0.04) frame.SetLineWidth(1) frame.SetTitle(plotTitle) # plot things on frame data.plotOn(frame, RooFit.MarkerSize(0.7)) chib1P_set = RooArgSet(chib1_pdf) modelPdf.plotOn(frame,RooFit.Components(chib1P_set), RooFit.LineColor(ROOT.kGreen+2), RooFit.LineStyle(2), RooFit.LineWidth(1)) chib2P_set = RooArgSet(chib2_pdf) modelPdf.plotOn(frame, RooFit.Components(chib2P_set),RooFit.LineColor(ROOT.kRed), RooFit.LineStyle(2), RooFit.LineWidth(1)) background_set = RooArgSet(background) modelPdf.plotOn(frame,RooFit.Components(background_set), RooFit.LineColor(ROOT.kBlack), RooFit.LineStyle(2), RooFit.LineWidth(1)) modelPdf.plotOn(frame, RooFit.LineWidth(2)) frame.SetName("fit_resonance") # Make numChib object numChib = NumChib(numChib=n_chib.getVal(), s_numChib=n_chib.getError(), ratio_21=ratio_21.getVal(), s_ratio_21=ratio_21.getError(), numBkg=n_background.getVal(), s_numBkg=n_background.getError(), corr_NB=result.correlation(n_chib, n_background),corr_NR=result.correlation(n_chib, ratio_21) , name='numChib'+output_suffix+ptBin_label,q0=q0.getVal(),s_q0=q0.getError(),alpha=alpha.getVal(),s_alpha=alpha.getError(), beta=beta.getVal(), s_beta=beta.getError(), chiSquare=frame.chiSquare()) #numChib.saveToFile('numChib'+output_suffix+'.txt') if noPlots: chi2 = frame.chiSquare() del frame return numChib, chi2 # Legend parameters_on_legend = RooArgSet()#n_chib, ratio_21, n_background) if massFreeToChange: #parameters_on_legend.add(scale_mean) parameters_on_legend.add(mean_1) #parameters_on_legend.add(mean_2) if sigmaFreeToChange: parameters_on_legend.add(scale_sigma) if massFreeToChange or sigmaFreeToChange: modelPdf.paramOn(frame, RooFit.Layout(0.1,0.6,0.2),RooFit.Parameters(parameters_on_legend)) if printLegend: #chiquadro, prob, numchib... leg = TLegend(0.48,0.75,0.97,0.95) leg.SetBorderSize(0) #leg.SetTextSize(0.04) leg.SetFillStyle(0) chi2 = frame.chiSquare() probChi2 = TMath.Prob(chi2*ndof, ndof) chi2 = round(chi2,2) probChi2 = round(probChi2,2) leg.AddEntry(0,'#chi^{2} = '+str(chi2),'') leg.AddEntry(0,'Prob #chi^{2} = '+str(probChi2),'') N_bkg, s_N_bkg = roundPair(numChib.numBkg, numChib.s_numBkg) leg.AddEntry(0,'N_{bkg} = '+str(N_bkg)+' #pm '+str(s_N_bkg),'') N_chib12, s_N_chib12 = roundPair(numChib.numChib, numChib.s_numChib) leg.AddEntry(0,'N_{#chi_{b}} = '+str(N_chib12)+' #pm '+str(s_N_chib12),'') Ratio = numChib.calcRatio() s_Ratio = numChib.calcRatioError() Ratio, s_Ratio = roundPair(Ratio, s_Ratio) leg.AddEntry(0,'N_{2}/N_{1} = '+str(Ratio)+' #pm '+str(s_Ratio),'') if printSigReso: # Add Significance Sig = numChib.calcSignificance() s_Sig = numChib.calcSignificanceError() Sig, s_Sig = roundPair(Sig, s_Sig) leg.AddEntry(0,'Sig = '+str(Sig)+' #pm '+str(s_Sig),'') if(Chib1_parameters.sigma>Chib2_parameters.sigma): Reso = Chib1_parameters.sigma * 1000 # So it's in MeV and not in GeV s_Reso = Chib1_parameters.s_sigma * 1000 # So it's in MeV and not in GeV else: Reso = Chib2_parameters.sigma * 1000 # So it's in MeV and not in GeV s_Reso = Chib2_parameters.s_sigma * 1000 # So it's in MeV and not in GeV Reso, s_Reso =roundPair(Reso, s_Reso) leg.AddEntry(0,'Reso = '+str(Reso)+' #pm '+str(s_Reso)+' MeV','') #N1 = numChib.numChib1 #s_N1 = numChib.s_numChib1 #N1, s_N1 = roundPair(N1, s_N1) #leg.AddEntry(0,'N_{1} = '+str(N1)+' #pm '+str(s_N1),'') #N2 = numChib.numChib2 #s_N2 = numChib.s_numChib2 #N2, s_N2 = roundPair(N2, s_N2) #leg.AddEntry(0,'N_{2} = '+str(N2)+' #pm '+str(s_N2),'') frame.addObject(leg) if legendOnPlot: # < pT < legend = TLegend(.06,.75,.53,.93) legend.SetFillStyle(0) legend.SetBorderSize(0) #legend.AddEntry(0,'CMS','') legend.AddEntry(0,str(cuts.upsilon_pt_lcut)+' GeV < p_{T}(#Upsilon) < '+str(cuts.upsilon_pt_hcut)+' GeV','') #legend.AddEntry(0,'p_{T}(#Upsilon)<'+str(cuts.upsilon_pt_hcut),'') frame.addObject(legend) if titleOnPlot: titleLegend = TLegend(.06,.4,.55,.73) #titleLegend.SetTextSize(0.03) titleLegend.SetFillStyle(0) titleLegend.SetBorderSize(0) titleLegend.AddEntry(0,plotTitle,'') frame.addObject(titleLegend) if cmsOnPlot: if printLegend: pvtxt = TPaveText(.1,.55,.55,.73,"NDC") else: pvtxt = TPaveText(0.5,0.75,0.97,0.9,"NDC") #(.06,.4,.55,.73) pvtxt.AddText('CMS Preliminary') pvtxt.AddText('pp, #sqrt{s} = 8 TeV') pvtxt.AddText('L = 20.7 fb^{-1}') pvtxt.SetFillStyle(0) pvtxt.SetBorderSize(0) pvtxt.SetTextSize(0.04) frame.addObject(pvtxt) # Canvas c1=TCanvas('Chib12_1P'+output_suffix+ptBin_label,'Chib12_1P'+output_suffix+ptBin_label) frame.Draw() if drawPulls: #c1=TCanvas(output_name+output_suffix,output_name+output_suffix,700, 625) hpull = frame.pullHist() framePulls = x.frame() framePulls.SetTitle(';;Pulls') framePulls.GetYaxis().SetLabelSize(0.18) framePulls.GetYaxis().SetTitle('Pulls') framePulls.GetYaxis().SetTitleSize(0.18) framePulls.GetYaxis().SetTitleOffset(0.15) framePulls.GetYaxis().SetNdivisions(005) framePulls.GetXaxis().SetLabelSize(0.16) framePulls.GetXaxis().SetTitle('') line0 = TLine(9.7, 0, 10.1, 0) line0.SetLineColor(ROOT.kBlue) line0.SetLineWidth(2) framePulls.addObject(line0) framePulls.addPlotable(hpull,"P") framePulls.SetMaximum(5) framePulls.SetMinimum(-5) pad1 = TPad("pad1", "The pad 80% of the height",0.0,0.2,1.0,1.0) pad1.cd() frame.Draw() pad2 = TPad("pad2", "The pad 20% of the height",0.0,0.01,1.0,0.2) pad2.cd() framePulls.Draw() c1.cd() pad1.Draw() pad2.Draw() #c1.SaveAs('Chib12_1P'+output_suffix+'.png') print 'Chi2 = '+str(frame.chiSquare()) # print ratio background/all in the signal refion signal_region = x.setRange("signal_region",9.87,9.92) pdf_integral = modelPdf.createIntegral(RooArgSet(x), RooFit.Range('signal_region')).getVal() * (n_chib.getVal() + n_background.getVal()) bkg_integral = background.createIntegral(RooArgSet(x), RooFit.Range('signal_region')).getVal() * n_background.getVal() print 'Ratio bkg/all in signal region = '+str(bkg_integral/pdf_integral) return numChib, c1
def alpha(channel): nElec = channel.count('e') nMuon = channel.count('m') nLept = nElec + nMuon nBtag = channel.count('b') # Channel-dependent settings # Background function. Semi-working options are: EXP, EXP2, EXPN, EXPTAIL if nLept == 0: treeName = 'SR' signName = 'XZh' colorVjet = sample['DYJetsToNuNu']['linecolor'] triName = "HLT_PFMET" leptCut = "0==0" topVeto = selection["TopVetocut"] massVar = "X_cmass" binFact = 1 #fitFunc = "EXP" #fitFunc = "EXP2" #fitFunc = "EXPN" #fitFunc = "EXPTAIL" fitFunc = "EXPN" if nBtag < 2 else "EXP" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "ERFEXP" fitFuncVV = "EXPGAUS" fitFuncTop = "GAUS2" elif nLept == 1: treeName = 'WCR' signName = 'XWh' colorVjet = sample['WJetsToLNu']['linecolor'] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isWtoEN" if nElec > 0 else "isWtoMN" topVeto = selection["TopVetocut"] massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" else: fitFunc = "EXPTAIL" if nBtag < 2 else "EXP" fitAltFunc = "EXPN" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "ERFEXP" fitFuncVV = "EXPGAUS" fitFuncTop = "GAUS3" if nBtag < 2 else "GAUS2" else: treeName = 'XZh' signName = 'XZh' colorVjet = sample['DYJetsToLL']['linecolor'] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isZtoEE" if nElec > 0 else "isZtoMM" topVeto = "0==0" massVar = "X_mass" binFact = 5 if nElec > 0: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "POW" if nBtag < 2 else "POW" else: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "POW" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitFuncVV = "EXPGAUS2" fitFuncTop = "GAUS" btagCut = selection["2Btag"] if nBtag == 2 else selection["1Btag"] print "--- Channel", channel, "---" print " number of electrons:", nElec, " muons:", nMuon, " b-tags:", nBtag print " read tree:", treeName, "and trigger:", triName if ALTERNATIVE: print " using ALTERNATIVE fit functions" print "-"*11*2 # Silent RooFit RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) #*******************************************************# # # # Variables and selections # # # #*******************************************************# # Define all the variables from the trees that will be used in the cuts and fits # this steps actually perform a "projection" of the entire tree on the variables in thei ranges, so be careful once setting the limits X_mass = RooRealVar( massVar, "m_{X}" if nLept > 0 else "m_{T}^{X}", XBINMIN, XBINMAX, "GeV") J_mass = RooRealVar( "fatjet1_prunedMassCorr", "corrected pruned mass", HBINMIN, HBINMAX, "GeV") CSV1 = RooRealVar( "fatjet1_CSVR1", "", -1.e99, 1.e4 ) CSV2 = RooRealVar( "fatjet1_CSVR2", "", -1.e99, 1.e4 ) nBtag = RooRealVar( "fatjet1_nBtag", "", 0., 4 ) CSVTop = RooRealVar( "bjet1_CSVR", "", -1.e99, 1.e4 ) isZtoEE = RooRealVar("isZtoEE", "", 0., 2 ) isZtoMM = RooRealVar("isZtoMM", "", 0., 2 ) isWtoEN = RooRealVar("isWtoEN", "", 0., 2 ) isWtoMN = RooRealVar("isWtoMN", "", 0., 2 ) weight = RooRealVar( "eventWeightLumi", "", -1.e9, 1. ) # Define the RooArgSet which will include all the variables defined before # there is a maximum of 9 variables in the declaration, so the others need to be added with 'add' variables = RooArgSet(X_mass, J_mass, CSV1, CSV2, nBtag, CSVTop) variables.add(RooArgSet(isZtoEE, isZtoMM, isWtoEN, isWtoMN, weight)) # Define the ranges in fatJetMass - these will be used to define SB and SR J_mass.setRange("LSBrange", LOWMIN, LOWMAX) J_mass.setRange("HSBrange", HIGMIN, HIGMAX) J_mass.setRange("VRrange", LOWMAX, SIGMIN) J_mass.setRange("SRrange", SIGMIN, SIGMAX) J_mass.setBins(54) # Define the selection for the various categories (base + SR / LSBcut / HSBcut ) baseCut = leptCut + " && " + btagCut + "&&" + topVeto massCut = massVar + ">%d" % XBINMIN baseCut += " && " + massCut # Cuts SRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), SIGMIN, J_mass.GetName(), SIGMAX) LSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX) HSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) SBcut = baseCut + " && ((%s>%d && %s<%d) || (%s>%d && %s<%d))" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX, J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) VRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMAX, J_mass.GetName(), SIGMIN) # Binning binsJmass = RooBinning(HBINMIN, HBINMAX) binsJmass.addUniform(HBINS, HBINMIN, HBINMAX) binsXmass = RooBinning(XBINMIN, XBINMAX) binsXmass.addUniform(binFact*XBINS, XBINMIN, XBINMAX) #*******************************************************# # # # Input files # # # #*******************************************************# # Import the files using TChains (separately for the bkg "classes" that we want to describe: here DY and VV+ST+TT) treeData = TChain(treeName) treeMC = TChain(treeName) treeVjet = TChain(treeName) treeVV = TChain(treeName) treeTop = TChain(treeName) # treeSign = {} # nevtSign = {} # Read data pd = getPrimaryDataset(triName) if len(pd)==0: raw_input("Warning: Primary Dataset not recognized, continue?") for i, s in enumerate(pd): treeData.Add(NTUPLEDIR + s + ".root") # Read V+jets backgrounds for i, s in enumerate(["WJetsToLNu_HT", "DYJetsToNuNu_HT", "DYJetsToLL_HT"]): for j, ss in enumerate(sample[s]['files']): treeVjet.Add(NTUPLEDIR + ss + ".root") # Read VV backgrounds for i, s in enumerate(["VV"]): for j, ss in enumerate(sample[s]['files']): treeVV.Add(NTUPLEDIR + ss + ".root") # Read Top backgrounds for i, s in enumerate(["ST", "TTbar"]): for j, ss in enumerate(sample[s]['files']): treeTop.Add(NTUPLEDIR + ss + ".root") # Sum all background MC treeMC.Add(treeVjet) treeMC.Add(treeVV) treeMC.Add(treeTop) # create a dataset to host data in sideband (using this dataset we are automatically blind in the SR!) setDataSB = RooDataSet("setDataSB", "setDataSB", variables, RooFit.Cut(SBcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) setDataLSB = RooDataSet("setDataLSB", "setDataLSB", variables, RooFit.Import(setDataSB), RooFit.Cut(LSBcut), RooFit.WeightVar(weight)) setDataHSB = RooDataSet("setDataHSB", "setDataHSB", variables, RooFit.Import(setDataSB), RooFit.Cut(HSBcut), RooFit.WeightVar(weight)) # Observed data (WARNING, BLIND!) setDataSR = RooDataSet("setDataSR", "setDataSR", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) setDataVR = RooDataSet("setDataVR", "setDataVR", variables, RooFit.Cut(VRcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) # Observed in the VV mass, just for plotting purposes # same for the bkg datasets from MC, where we just apply the base selections (not blind) setVjet = RooDataSet("setVjet", "setVjet", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVjet)) setVjetSB = RooDataSet("setVjetSB", "setVjetSB", variables, RooFit.Import(setVjet), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setVjetSR = RooDataSet("setVjetSR", "setVjetSR", variables, RooFit.Import(setVjet), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) setVV = RooDataSet("setVV", "setVV", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVV)) setVVSB = RooDataSet("setVVSB", "setVVSB", variables, RooFit.Import(setVV), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setVVSR = RooDataSet("setVVSR", "setVVSR", variables, RooFit.Import(setVV), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) setTop = RooDataSet("setTop", "setTop", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeTop)) setTopSB = RooDataSet("setTopSB", "setTopSB", variables, RooFit.Import(setTop), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setTopSR = RooDataSet("setTopSR", "setTopSR", variables, RooFit.Import(setTop), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) print " Data events SB: %.2f" % setDataSB.sumEntries() print " V+jets entries: %.2f" % setVjet.sumEntries() print " VV, VH entries: %.2f" % setVV.sumEntries() print " Top,ST entries: %.2f" % setTop.sumEntries() # the relative normalization of the varius bkg is taken from MC by counting all the events in the full fatJetMass range #coef = RooRealVar("coef", "coef", setVV.sumEntries()/setVjet.sumEntries(),0.,1.) coef_VV_Vjet = RooRealVar("coef2_1", "coef2_1", setVV.sumEntries()/setVjet.sumEntries(), 0., 1.) coef_Top_VVVjet = RooRealVar("coef3_21", "coef3_21", setTop.sumEntries()/(setVjet.sumEntries()+setVV.sumEntries()),0.,1.); coef_VV_Vjet.setConstant(True) coef_Top_VVVjet.setConstant(True) # Define entries entryVjet = RooRealVar("entryVjets", "V+jets normalization", setVjet.sumEntries(), 0., 1.e6) entryVV = RooRealVar("entryVV", "VV normalization", setVV.sumEntries(), 0., 1.e6) entryTop = RooRealVar("entryTop", "Top normalization", setTop.sumEntries(), 0., 1.e6) entrySB = RooRealVar("entrySB", "Data SB normalization", setDataSB.sumEntries(SBcut), 0., 1.e6) entrySB.setError(math.sqrt(entrySB.getVal())) entryLSB = RooRealVar("entryLSB", "Data LSB normalization", setDataSB.sumEntries(LSBcut), 0., 1.e6) entryLSB.setError(math.sqrt(entryLSB.getVal())) entryHSB = RooRealVar("entryHSB", "Data HSB normalization", setDataSB.sumEntries(HSBcut), 0., 1.e6) entryHSB.setError(math.sqrt(entryHSB.getVal())) #*******************************************************# # # # NORMALIZATION # # # #*******************************************************# # set reasonable ranges for J_mass and X_mass # these are used in the fit in order to avoid ROOFIT to look in regions very far away from where we are fitting J_mass.setRange("h_reasonable_range", LOWMIN, HIGMAX) X_mass.setRange("X_reasonable_range", XBINMIN, XBINMAX) # Set RooArgSets once for all, see https://root.cern.ch/phpBB3/viewtopic.php?t=11758 jetMassArg = RooArgSet(J_mass) #*******************************************************# # # # V+jets normalization # # # #*******************************************************# # Variables for V+jets constVjet = RooRealVar("constVjet", "slope of the exp", -0.020, -1., 0.) offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 30., -50., 200.) widthVjet = RooRealVar("widthVjet", "width of the erf", 100., 1., 200.) offsetVjet.setConstant(True) a0Vjet = RooRealVar("a0Vjet", "width of the erf", -0.1, -5, 0) a1Vjet = RooRealVar("a1Vjet", "width of the erf", 0.6, 0, 5) a2Vjet = RooRealVar("a2Vjet", "width of the erf", -0.1, -1, 1) # Define V+jets model if fitFuncVjet == "ERFEXP": modelVjet = RooErfExpPdf("modelVjet", "error function for V+jets mass", J_mass, constVjet, offsetVjet, widthVjet) elif fitFuncVjet == "EXP": modelVjet = RooExponential("modelVjet", "exp for V+jets mass", J_mass, constVjet) elif fitFuncVjet == "POL": modelVjet = RooChebychev("modelVjet", "polynomial for V+jets mass", J_mass, RooArgList(a0Vjet, a1Vjet, a2Vjet)) elif fitFuncVjet == "POW": modelVjet = RooGenericPdf("modelVjet", "powerlaw for X mass", "@0^@1", RooArgList(J_mass, a0Vjet)) else: print " ERROR! Pdf", fitFuncVjet, "is not implemented for Vjets" exit() # fit to main bkg in MC (whole range) frVjet = modelVjet.fitTo(setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # integrals and number of events iSBVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iLSBVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) iHSBVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) iSRVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iVRVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # Do not remove the following lines, integrals are computed here iALVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg)) nSBVjet = iSBVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(SBcut) nLSBVjet = iLSBVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(LSBcut) nHSBVjet = iHSBVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(HSBcut) nSRVjet = iSRVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(SRcut) drawPlot("JetMass_Vjet", channel, J_mass, modelVjet, setVjet, binsJmass, frVjet) if VERBOSE: print "********** Fit result [JET MASS Vjets] *"+"*"*40, "\n", frVjet.Print(), "\n", "*"*80 #*******************************************************# # # # VV, VH normalization # # # #*******************************************************# # Variables for VV # Error function and exponential to model the bulk constVV = RooRealVar("constVV", "slope of the exp", -0.030, -0.1, 0.) offsetVV = RooRealVar("offsetVV", "offset of the erf", 90., 1., 300.) widthVV = RooRealVar("widthVV", "width of the erf", 50., 1., 100.) erfrVV = RooErfExpPdf("baseVV", "error function for VV jet mass", J_mass, constVV, offsetVV, widthVV) expoVV = RooExponential("baseVV", "error function for VV jet mass", J_mass, constVV) # gaussian for the V mass peak meanVV = RooRealVar("meanVV", "mean of the gaussian", 90., 60., 100.) sigmaVV = RooRealVar("sigmaVV", "sigma of the gaussian", 10., 6., 30.) fracVV = RooRealVar("fracVV", "fraction of gaussian wrt erfexp", 3.2e-1, 0., 1.) gausVV = RooGaussian("gausVV", "gaus for VV jet mass", J_mass, meanVV, sigmaVV) # gaussian for the H mass peak meanVH = RooRealVar("meanVH", "mean of the gaussian", 125., 100., 150.) sigmaVH = RooRealVar("sigmaVH", "sigma of the gaussian", 30., 5., 40.) fracVH = RooRealVar("fracVH", "fraction of gaussian wrt erfexp", 1.5e-2, 0., 1.) gausVH = RooGaussian("gausVH", "gaus for VH jet mass", J_mass, meanVH, sigmaVH) # Define VV model if fitFuncVV == "ERFEXPGAUS": modelVV = RooAddPdf("modelVV", "error function + gaus for VV jet mass", RooArgList(gausVV, erfrVV), RooArgList(fracVV)) elif fitFuncVV == "ERFEXPGAUS2": modelVV = RooAddPdf("modelVV", "error function + gaus + gaus for VV jet mass", RooArgList(gausVH, gausVV, erfrVV), RooArgList(fracVH, fracVV)) elif fitFuncVV == "EXPGAUS": modelVV = RooAddPdf("modelVV", "error function + gaus for VV jet mass", RooArgList(gausVV, expoVV), RooArgList(fracVV)) elif fitFuncVV == "EXPGAUS2": modelVV = RooAddPdf("modelVV", "error function + gaus + gaus for VV jet mass", RooArgList(gausVH, gausVV, expoVV), RooArgList(fracVH, fracVV)) else: print " ERROR! Pdf", fitFuncVV, "is not implemented for VV" exit() # fit to secondary bkg in MC (whole range) frVV = modelVV.fitTo(setVV, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # integrals and number of events iSBVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iLSBVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) iHSBVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) iSRVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iVRVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # Do not remove the following lines, integrals are computed here iALVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg)) nSBVV = iSBVV.getVal()/iALVV.getVal()*setVV.sumEntries(SBcut) nLSBVV = iLSBVV.getVal()/iALVV.getVal()*setVV.sumEntries(LSBcut) nHSBVV = iHSBVV.getVal()/iALVV.getVal()*setVV.sumEntries(HSBcut) nSRVV = iSRVV.getVal()/iALVV.getVal()*setVV.sumEntries(SRcut) rSBSRVV = nSRVV/nSBVV drawPlot("JetMass_VV", channel, J_mass, modelVV, setVV, binsJmass, frVV) if VERBOSE: print "********** Fit result [JET MASS VV] ****"+"*"*40, "\n", frVV.Print(), "\n", "*"*80 #*******************************************************# # # # Top, ST normalization # # # #*******************************************************# # Variables for Top # Error Function * Exponential to model the bulk constTop = RooRealVar("constTop", "slope of the exp", -0.030, -1., 0.) offsetTop = RooRealVar("offsetTop", "offset of the erf", 175.0, 50., 250.) widthTop = RooRealVar("widthTop", "width of the erf", 100.0, 1., 300.) gausTop = RooGaussian("baseTop", "gaus for Top jet mass", J_mass, offsetTop, widthTop) erfrTop = RooErfExpPdf("baseTop", "error function for Top jet mass", J_mass, constTop, offsetTop, widthTop) # gaussian for the W mass peak meanW = RooRealVar("meanW", "mean of the gaussian", 80., 70., 90.) sigmaW = RooRealVar("sigmaW", "sigma of the gaussian", 10., 2., 20.) fracW = RooRealVar("fracW", "fraction of gaussian wrt erfexp", 0.1, 0., 1.) gausW = RooGaussian("gausW", "gaus for W jet mass", J_mass, meanW, sigmaW) # gaussian for the Top mass peak meanT = RooRealVar("meanT", "mean of the gaussian", 175., 150., 200.) sigmaT = RooRealVar("sigmaT", "sigma of the gaussian", 12., 5., 50.) fracT = RooRealVar("fracT", "fraction of gaussian wrt erfexp", 0.1, 0., 1.) gausT = RooGaussian("gausT", "gaus for T jet mass", J_mass, meanT, sigmaT) # Define Top model if fitFuncTop == "ERFEXPGAUS2": modelTop = RooAddPdf("modelTop", "error function + gaus + gaus for Top jet mass", RooArgList(gausW, gausT, erfrTop), RooArgList(fracW, fracT)) elif fitFuncTop == "ERFEXPGAUS": modelTop = RooAddPdf("modelTop", "error function + gaus for Top jet mass", RooArgList(gausT, erfrTop), RooArgList(fracT)) elif fitFuncTop == "GAUS3": modelTop = RooAddPdf("modelTop", "gaus + gaus + gaus for Top jet mass", RooArgList(gausW, gausT, gausTop), RooArgList(fracW, fracT)) elif fitFuncTop == "GAUS2": modelTop = RooAddPdf("modelTop", "gaus + gaus for Top jet mass", RooArgList(gausT, gausTop), RooArgList(fracT)) elif fitFuncTop == "GAUS": modelTop = RooGaussian("modelTop", "gaus for Top jet mass", J_mass, offsetTop, widthTop) else: print " ERROR! Pdf", fitFuncTop, "is not implemented for Top" exit() # fit to secondary bkg in MC (whole range) frTop = modelTop.fitTo(setTop, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # integrals and number of events iSBTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iLSBTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) iHSBTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) iSRTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iVRTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # Do not remove the following lines, integrals are computed here iALTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg)) nSBTop = iSBTop.getVal()/iALTop.getVal()*setTop.sumEntries(SBcut) nLSBTop = iLSBTop.getVal()/iALTop.getVal()*setTop.sumEntries(LSBcut) nHSBTop = iHSBTop.getVal()/iALTop.getVal()*setTop.sumEntries(HSBcut) nSRTop = iSRTop.getVal()/iALTop.getVal()*setTop.sumEntries(SRcut) drawPlot("JetMass_Top", channel, J_mass, modelTop, setTop, binsJmass, frTop) if VERBOSE: print "********** Fit result [JET MASS TOP] ***"+"*"*40, "\n", frTop.Print(), "\n", "*"*80 #*******************************************************# # # # All bkg normalization # # # #*******************************************************# constVjet.setConstant(True) offsetVjet.setConstant(True) widthVjet.setConstant(True) a0Vjet.setConstant(True) a1Vjet.setConstant(True) a2Vjet.setConstant(True) constVV.setConstant(True) offsetVV.setConstant(True) widthVV.setConstant(True) meanVV.setConstant(True) sigmaVV.setConstant(True) fracVV.setConstant(True) meanVH.setConstant(True) sigmaVH.setConstant(True) fracVH.setConstant(True) constTop.setConstant(True) offsetTop.setConstant(True) widthTop.setConstant(True) meanW.setConstant(True) sigmaW.setConstant(True) fracW.setConstant(True) meanT.setConstant(True) sigmaT.setConstant(True) fracT.setConstant(True) # Final background model by adding the main+secondary pdfs (using 'coef': ratio of the secondary/main, from MC) model = RooAddPdf("model", "model", RooArgList(modelTop, modelVV, modelVjet), RooArgList(coef_Top_VVVjet, coef_VV_Vjet))#FIXME model.fixAddCoefRange("h_reasonable_range") # Extended fit model to data in SB # all the 3 sidebands (Low / High / the 2 combined) could be used # currently using the LOW+HIGH (the others are commented out) yieldLSB = RooRealVar("yieldLSB", "Lower SB normalization", 10, 0., 1.e6) yieldHSB = RooRealVar("yieldHSB", "Higher SB normalization", 10, 0., 1.e6) yieldSB = RooRealVar("yieldSB", "All SB normalization", 10, 0., 1.e6) #model_ext = RooExtendPdf("model_ext", "extended p.d.f", model, yieldLSB) #model_ext = RooExtendPdf("model_ext", "extended p.d.f", model, yieldHSB) model_ext = RooExtendPdf("model_ext", "extended p.d.f", model, yieldSB) #frMass = model_ext.fitTo(setDataSB, RooFit.ConditionalObservables(RooArgSet(J_mass)),RooFit.SumW2Error(True),RooFit.Extended(True),RooFit.Range("LSBrange"),RooFit.PrintLevel(-1)) #frMass = model_ext.fitTo(setDataSB, RooFit.ConditionalObservables(RooArgSet(J_mass)),RooFit.SumW2Error(True),RooFit.Extended(True),RooFit.Range("HSBrange"),RooFit.PrintLevel(-1)) #frMass = model_ext.fitTo(setDataSB, RooFit.ConditionalObservables(RooArgSet(J_mass)), RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.PrintLevel(1 if VERBOSE else -1)) #print "********** Fit result [JET MASS DATA] **"+"*"*40 #print frMass.Print() #print "*"*80 # Calculate integral of the model obtained from the fit to data (fraction of PDF that is within a given region) #nSB = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) #nSB = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) #nSB = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) #nSR = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) #nVR = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # scale the yieldSB from SB to SR using the ratio of the PDFs defined by the two integrals SRyield = RooFormulaVar("SRyield", "extrapolation to SR","(@0-@1*@3-@2*@4) * @5/@6 +@1*@7+@2*@8", RooArgList(entrySB, entryVV, entryTop, iSBVV, iSBTop, iSRVjet, iSBVjet, iSRVV, iSRTop)) VRyield = RooFormulaVar("VRyield", "extrapolation to VR","(@0-@1*@3-@2*@4) * @5/@6 +@1*@7+@2*@8", RooArgList(entrySB, entryVV, entryTop, iSBVV, iSBTop, iVRVjet, iSBVjet, iVRVV, iVRTop)) HSByield = RooFormulaVar("SRyield", "extrapolation to SR","(@0-@1*@3-@2*@4) * @5/@6 +@1*@7+@2*@8", RooArgList(entryLSB, entryVV, entryTop, iLSBVV, iLSBTop, iHSBVjet, iLSBVjet, iHSBVV, iHSBTop)) # RooFormulaVar SRyield("SRyield","extrapolation to SR","(@0/@1)*@2",RooArgList(*nSR,*nSB,yieldLowerSB)) # RooFormulaVar SRyield("SRyield","extrapolation to SR","(@0/@1)*@2",RooArgList(*nSR,*nSB,yieldHigherSB)) #SRyield = RooFormulaVar("SRyield", "extrapolation to SR","(@0/@1)*@2", RooArgList(nSR, nSB, entrySB)) bkgYield = SRyield.getVal() bkgYield_error = math.sqrt(SRyield.getPropagatedError(frVjet)**2 + SRyield.getPropagatedError(frVV)**2 + SRyield.getPropagatedError(frTop)**2 + (entrySB.getError()*rSBSRVV)**2) bkgNorm = entrySB.getVal() + SRyield.getVal() + VRyield.getVal() bkgYield_eig_norm = RooRealVar("predSR_eig_norm", "expected yield in SR", bkgYield, 0., 1.e6) bkgYieldExt = HSByield.getVal() drawPlot("JetMass", channel, J_mass, model, setDataSB, binsJmass, None, None, "", bkgNorm, True) print channel, "normalization = %.3f +/- %.3f, observed = %.0f" % (bkgYield, bkgYield_error, setDataSR.sumEntries() if not BLIND else -1) if VERBOSE: raw_input("Press Enter to continue...")
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2" # input parameters parser = ArgumentParser(description='Script that creates combine datacards and corresponding RooFit workspaces',epilog=usage) parser.add_argument("--inputData", dest="inputData", required=True, help="Input data spectrum", metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", required=True, help="Data histogram name", metavar="DATA_HISTNAME") parser.add_argument("--inputSig", dest="inputSig", required=True, help="Input signal shapes", metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", required=True, help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)") parser.add_argument("-o", "--output_path", dest="output_path", required=True, help="Output path where datacards and workspaces will be stored", metavar="OUTPUT_PATH") parser.add_argument("-l", "--lumi", dest="lumi", required=True, default=1000., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument("--massMin", dest="massMin", default=500, type=int, help="Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument("--massMax", dest="massMax", default=1200, type=int, help="Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument("--p1", dest="p1", default=5.0000e-03, type=float, help="Fit function p1 parameter (default: %(default)e)", metavar="P1") parser.add_argument("--p2", dest="p2", default=9.1000e+00, type=float, help="Fit function p2 parameter (default: %(default)e)", metavar="P2") parser.add_argument("--p3", dest="p3", default=5.0000e-01, type=float, help="Fit function p3 parameter (default: %(default)e)", metavar="P3") parser.add_argument("--lumiUnc", dest="lumiUnc", required=True, type=float, help="Relative uncertainty in the integrated luminosity", metavar="LUMI_UNC") parser.add_argument("--jesUnc", dest="jesUnc", type=float, help="Relative uncertainty in the jet energy scale", metavar="JES_UNC") parser.add_argument("--jerUnc", dest="jerUnc", type=float, help="Relative uncertainty in the jet energy resolution", metavar="JER_UNC") parser.add_argument("--sqrtS", dest="sqrtS", default=13000., type=float, help="Collision center-of-mass energy (default: %(default).1f)", metavar="SQRTS") parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters") parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") parser.add_argument("--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)") parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots") parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots") parser.add_argument("--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)") parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared") parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument("--mass", type=int, nargs = '*', default = 1000, help="Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument("--massrange", type=int, nargs = 3, help="Define a range of masses to be produced. Format: min max step", metavar = ('MIN', 'MAX', 'STEP') ) mass_group.add_argument("--masslist", help = "List containing mass information" ) args = parser.parse_args() if args.atype == 'hG': fstr = "bbhGGBB" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'hR': fstr = "bbhRS" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'lG': fstr = "bblGGBB" in2 = 'bcorrbin/binmodl.root' else: fstr = "bblRS" in2 = 'bcorrbin/binmodl.root' # check if the output directory exists if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ): os.mkdir( os.path.join(os.getcwd(),args.output_path) ) # mass points for which resonance shapes will be produced masses = [] if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX+STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py","")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0,kFALSE) RooMsgService.instance().setStreamStatus(1,kFALSE) # input data file inputData = TFile(args.inputData) # input data histogram hData = inputData.Get(args.dataHistname) inData2 = TFile(in2) hData2 = inData2.Get('h_data') # input sig file inputSig = TFile(args.inputSig) sqrtS = args.sqrtS # mass variable mjj = RooRealVar('mjj','mjj',float(args.massMin),float(args.massMax)) # integrated luminosity and signal cross section lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..."%(args.final_state, int(mass)) # get signal shape hSig = inputSig.Get( "h_" + args.final_state + "_" + str(int(mass)) ) # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity) hSig.Scale(signalCrossSection*lumi/hSig.Integral()) # divide by a number that provides roughly an r value of 1-10 rooSigHist = RooDataHist('rooSigHist','rooSigHist',RooArgList(mjj),hSig) print 'Signal acceptance:', (rooSigHist.sumEntries()/hSig.Integral()) signal = RooHistPdf('signal','signal',RooArgSet(mjj),rooSigHist) signal_norm = RooRealVar('signal_norm','signal_norm',0,-1e+05,1e+05) if args.fitBonly: signal_norm.setConstant() p1 = RooRealVar('p1','p1',args.p1,0.,100.) p2 = RooRealVar('p2','p2',args.p2,0.,60.) p3 = RooRealVar('p3','p3',args.p3,-10.,10.) p4 = RooRealVar('p4','p4',5.6,-50.,50.) p5 = RooRealVar('p5','p5',10.,-50.,50.) p6 = RooRealVar('p6','p6',.016,-50.,50.) p7 = RooRealVar('p7','p7',8.,-50.,50.) p8 = RooRealVar('p8','p8',.22,-50.,50.) p9 = RooRealVar('p9','p9',14.1,-50.,50.) p10 = RooRealVar('p10','p10',8.,-50.,50.) p11 = RooRealVar('p11','p11',4.8,-50.,50.) p12 = RooRealVar('p12','p12',7.,-50.,50.) p13 = RooRealVar('p13','p13',7.,-50.,50.) p14 = RooRealVar('p14','p14',7.,-50.,50.) p15 = RooRealVar('p15','p15',1.,-50.,50.) p16 = RooRealVar('p16','p16',9.,-50.,50.) p17 = RooRealVar('p17','p17',0.6,-50.,50.) if args.fixP3: p3.setConstant() background = RooGenericPdf('background','(pow(1-@0/%.1f,@1)/pow(@0/%.1f,@2+@3*log(@0/%.1f)))'%(sqrtS,sqrtS,sqrtS),RooArgList(mjj,p1,p2,p3)) dataInt = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm = RooRealVar('background_norm','background_norm',dataInt,0.,1e+08) background2 = RooGenericPdf('background2','(pow(@0/%.1f,-@1)*pow(1-@0/%.1f,@2))'%(sqrtS,sqrtS),RooArgList(mjj,p4,p5)) dataInt2 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm2 = RooRealVar('background_norm2','background_norm2',dataInt2,0.,1e+08) background3 = RooGenericPdf('background3','(1/pow(@1+@0/%.1f,@2))'%(sqrtS),RooArgList(mjj,p6,p7)) dataInt3 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm3 = RooRealVar('background_norm3','background_norm3',dataInt3,0.,1e+08) background4 = RooGenericPdf('background4','(1/pow(@1+@2*@0/%.1f+pow(@0/%.1f,2),@3))'%(sqrtS,sqrtS),RooArgList(mjj,p8,p9,p10)) dataInt4 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm4 = RooRealVar('background_norm4','background_norm4',dataInt4,0.,1e+08) background5 = RooGenericPdf('background5','(pow(@0/%.1f,-@1)*pow(1-pow(@0/%.1f,1/3),@2))'%(sqrtS,sqrtS),RooArgList(mjj,p11,p12)) dataInt5 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm5 = RooRealVar('background_norm5','background_norm5',dataInt5,0.,1e+08) background6 = RooGenericPdf('background6','(pow(@0/%.1f,2)+@1*@0/%.1f+@2)'%(sqrtS,sqrtS),RooArgList(mjj,p13,p14)) dataInt6 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm6 = RooRealVar('background_norm6','background_norm6',dataInt6,0.,1e+08) background7 = RooGenericPdf('background7','((-1+@1*@0/%.1f)*pow(@0/%.1f,@2+@3*log(@0/%.1f)))'%(sqrtS,sqrtS,sqrtS),RooArgList(mjj,p15,p16,p17)) dataInt7 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm7 = RooRealVar('background_norm7','background_norm7',dataInt7,0.,1e+08) # S+B model model = RooAddPdf("model","s+b",RooArgList(background,signal),RooArgList(background_norm,signal_norm)) model2 = RooAddPdf("model2","s+b2",RooArgList(background2,signal),RooArgList(background_norm2,signal_norm)) model3 = RooAddPdf("model3","s+b3",RooArgList(background3,signal),RooArgList(background_norm3,signal_norm)) model4 = RooAddPdf("model4","s+b4",RooArgList(background4,signal),RooArgList(background_norm4,signal_norm)) model5 = RooAddPdf("model5","s+b5",RooArgList(background5,signal),RooArgList(background_norm5,signal_norm)) model6 = RooAddPdf("model6","s+b6",RooArgList(background6,signal),RooArgList(background_norm6,signal_norm)) model7 = RooAddPdf("model7","s+b7",RooArgList(background7,signal),RooArgList(background_norm7,signal_norm)) rooDataHist = RooDataHist('rooDatahist','rooDathist',RooArgList(mjj),hData) if args.runFit: mframe = mjj.frame() rooDataHist.plotOn(mframe, ROOT.RooFit.Name("setonedata"), ROOT.RooFit.Invisible()) res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframe, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res2 = model2.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model2.plotOn(mframe, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res3 = model3.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model3.plotOn(mframe, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res4 = model4.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model4.plotOn(mframe, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res5 = model5.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model5.plotOn(mframe, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) res6 = model6.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model6.plotOn(mframe, ROOT.RooFit.Name("model6"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kPink)) res7 = model7.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model7.plotOn(mframe, ROOT.RooFit.Name("model7"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kAzure)) rooDataHist2 = RooDataHist('rooDatahist2','rooDathist2',RooArgList(mjj),hData2) rooDataHist2.plotOn(mframe, ROOT.RooFit.Name("data")) canvas = TCanvas("cdouble", "cdouble", 800, 1000) gStyle.SetOptStat(0); gStyle.SetOptTitle(0); top = TPad("top", "top", 0., 0.5, 1., 1.) top.SetBottomMargin(0.03) top.Draw() top.SetLogy() bottom = TPad("bottom", "bottom", 0., 0., 1., 0.5) bottom.SetTopMargin(0.02) bottom.SetBottomMargin(0.2) bottom.Draw() top.cd() frame_top = TH1D("frame_top", "frame_top", 100, 526, 1500) frame_top.GetXaxis().SetTitleSize(0) frame_top.GetXaxis().SetLabelSize(0) frame_top.GetYaxis().SetLabelSize(0.04) frame_top.GetYaxis().SetTitleSize(0.04) frame_top.GetYaxis().SetTitle("Events") frame_top.SetMaximum(1000.) frame_top.SetMinimum(0.1) frame_top.Draw("axis") mframe.Draw("p e1 same") bottom.cd() frame_bottom = TH1D("frame_bottom", "frame_bottom", 100, 526, 1500) frame_bottom.GetXaxis().SetTitle("m_{jj} [GeV]") frame_bottom.GetYaxis().SetTitle("Pull") frame_bottom.GetXaxis().SetLabelSize(0.04) frame_bottom.GetXaxis().SetTitleSize(0.06) frame_bottom.GetXaxis().SetLabelOffset(0.01) frame_bottom.GetXaxis().SetTitleOffset(1.1) frame_bottom.GetYaxis().SetLabelSize(0.04) frame_bottom.GetYaxis().SetTitleSize(0.04) frame_bottom.GetYaxis().SetTitleOffset(0.85) frame_bottom.SetMaximum(4.) frame_bottom.SetMinimum(-3.) frame_bottom.Draw("axis") zero = TLine(526., 0., 1500., 0.) zero.SetLineColor(ROOT.EColor.kBlack) zero.SetLineStyle(1) zero.SetLineWidth(2) zero.Draw("same") # Ratio histogram with no errors (not so well defined, since this isn't a well-defined efficiency) newHist = mframe.getHist("data") curve = mframe.getObject(1) hresid = newHist.makePullHist(curve,kTRUE) resframe = mjj.frame() mframe.SetAxisRange(526.,1500.) resframe.addPlotable(hresid,"B X") resframe.Draw("same") canvas.cd() canvas.SaveAs("testdouble.pdf") if args.pyes: c = TCanvas("c","c",800,800) mframe.SetAxisRange(300.,1300.) c.SetLogy() # mframe.SetMaximum(10) # mframe.SetMinimum(1) mframe.Draw() fitname = args.pdir+'/5funcfit_m'+str(mass)+fstr+'.pdf' c.SaveAs(fitname) cpull = TCanvas("cpull","cpull",800,800) pulls = mframe.pullHist("data","model3") pulls.Draw("ABX") pullname = args.pdir+'/pull_m'+str(mass)+fstr+'.pdf' cpull.SaveAs(pullname) cpull2 = TCanvas("cpull2","cpull2",800,800) pulls2 = mframe.pullHist("setonedata","model1") pulls2.Draw("ABX") pull2name = args.pdir+'/pull2_m'+str(mass)+fstr+'.pdf' cpull2.SaveAs(pull2name) if args.widefit: mframew = mjj.frame() rooDataHist2.plotOn(mframew, ROOT.RooFit.Name("data")) res6 = model.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframew, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res7 = model2.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model2.plotOn(mframew, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res8 = model3.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model3.plotOn(mframew, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res9 = model4.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model4.plotOn(mframew, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res10 = model5.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model5.plotOn(mframew, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) if args.pyes: c = TCanvas("c","c",800,800) mframew.SetAxisRange(300.,1300.) c.SetLogy() # mframew.SetMaximum(10) # mframew.SetMinimum(1) mframew.Draw() fitname = args.pdir+'/5funcfittowide_m'+str(mass)+fstr+'.pdf' c.SaveAs(fitname) cpull = TCanvas("cpull","cpull",800,800) pulls = mframew.pullHist("data","model1") pulls.Draw("ABX") pullname = args.pdir+'/pullwidefit_m'+str(mass)+fstr+'.pdf' cpull.SaveAs(pullname) if args.chi2: fullInt = model.createIntegral(RooArgSet(mjj)) norm = dataInt/fullInt.getVal() chi1 = 0. fullInt2 = model2.createIntegral(RooArgSet(mjj)) norm2 = dataInt2/fullInt2.getVal() chi2 = 0. fullInt3 = model3.createIntegral(RooArgSet(mjj)) norm3 = dataInt3/fullInt3.getVal() chi3 = 0. fullInt4 = model4.createIntegral(RooArgSet(mjj)) norm4 = dataInt4/fullInt4.getVal() chi4 = 0. fullInt5 = model5.createIntegral(RooArgSet(mjj)) norm5 = dataInt5/fullInt5.getVal() chi5 = 0. for i in range(args.massMin, args.massMax): new = 0 new2 = 0 new3 = 0 new4 = 0 new5 = 0 height = hData.GetBinContent(i) xLow = hData.GetXaxis().GetBinLowEdge(i) xUp = hData.GetXaxis().GetBinLowEdge(i+1) obs = height*(xUp-xLow) mjj.setRange("intrange",xLow,xUp) integ = model.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp = integ.getVal()*norm new = pow(exp-obs,2)/exp chi1 = chi1 + new integ2 = model2.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp2 = integ2.getVal()*norm2 new2 = pow(exp2-obs,2)/exp2 chi2 = chi2 + new2 integ3 = model3.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp3 = integ3.getVal()*norm3 new3 = pow(exp3-obs,2)/exp3 chi3 = chi3 + new3 integ4 = model4.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp4 = integ4.getVal()*norm4 if exp4 != 0: new4 = pow(exp4-obs,2)/exp4 else: new4 = 0 chi4 = chi4 + new4 integ5 = model5.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp5 = integ5.getVal()*norm5 new5 = pow(exp5-obs,2)/exp5 chi5 = chi5 + new5 print "chi1 %d "%(chi1) print "chi2 %d "%(chi2) print "chi3 %d "%(chi3) print "chi4 %d "%(chi4) print "chi5 %d "%(chi5) if not args.decoBkg: print " " res.Print() # res2.Print() # res3.Print() # res4.Print() # res5.Print() # res6.Print() # res7.Print() # decorrelated background parameters for Bayesian limits if args.decoBkg: signal_norm.setConstant() res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) res.Print() ## temp workspace for the PDF diagonalizer w_tmp = RooWorkspace("w_tmp") deco = PdfDiagonalizer("deco",w_tmp,res) # here diagonalizing only the shape parameters since the overall normalization is already decorrelated background_deco = deco.diagonalize(background) print "##################### workspace for decorrelation" w_tmp.Print("v") print "##################### original parameters" background.getParameters(rooDataHist).Print("v") print "##################### decorrelated parameters" # needed if want to evaluate limits without background systematics if args.fixBkg: w_tmp.var("deco_eig1").setConstant() w_tmp.var("deco_eig2").setConstant() if not args.fixP3: w_tmp.var("deco_eig3").setConstant() background_deco.getParameters(rooDataHist).Print("v") print "##################### original pdf" background.Print() print "##################### decorrelated pdf" background_deco.Print() # release signal normalization signal_norm.setConstant(kFALSE) # set the background normalization range to +/- 5 sigma bkg_val = background_norm.getVal() bkg_error = background_norm.getError() background_norm.setMin(bkg_val-5*bkg_error) background_norm.setMax(bkg_val+5*bkg_error) background_norm.Print() # change background PDF names background.SetName("background_old") background_deco.SetName("background") # needed if want to evaluate limits without background systematics if args.fixBkg: background_norm.setConstant() p1.setConstant() p2.setConstant() p3.setConstant() # ----------------------------------------- # dictionaries holding systematic variations of the signal shape hSig_Syst = {} hSig_Syst_DataHist = {} sigCDF = TGraph(hSig.GetNbinsX()+1) # JES and JER uncertainties if args.jesUnc != None or args.jerUnc != None: sigCDF.SetPoint(0,0.,0.) integral = 0. for i in range(1, hSig.GetNbinsX()+1): x = hSig.GetXaxis().GetBinLowEdge(i+1) integral = integral + hSig.GetBinContent(i) sigCDF.SetPoint(i,x,integral) if args.jesUnc != None: hSig_Syst['JESUp'] = copy.deepcopy(hSig) hSig_Syst['JESDown'] = copy.deepcopy(hSig) if args.jerUnc != None: hSig_Syst['JERUp'] = copy.deepcopy(hSig) hSig_Syst['JERDown'] = copy.deepcopy(hSig) # reset signal histograms for key in hSig_Syst.keys(): hSig_Syst[key].Reset() hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key) # produce JES signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX()+1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i+1) jes = 1. - args.jesUnc xLowPrime = jes*xLow xUpPrime = jes*xUp hSig_Syst['JESUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jes = 1. + args.jesUnc xLowPrime = jes*xLow xUpPrime = jes*xUp hSig_Syst['JESDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JESUp'] = RooDataHist('hSig_JESUp','hSig_JESUp',RooArgList(mjj),hSig_Syst['JESUp']) hSig_Syst_DataHist['JESDown'] = RooDataHist('hSig_JESDown','hSig_JESDown',RooArgList(mjj),hSig_Syst['JESDown']) if args.jyes: c2 = TCanvas("c2","c2",800,800) mframe2 = mjj.frame(ROOT.RooFit.Title("JES One Sigma Shifts")) mframe2.SetAxisRange(525.,1200.) hSig_Syst_DataHist['JESUp'].plotOn(mframe2, ROOT.RooFit.Name("JESUP"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JESDown'].plotOn(mframe2,ROOT.RooFit.Name("JESDOWN"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe2, ROOT.RooFit.DataError(2),ROOT.RooFit.Name("SIG"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe2.Draw() mframe2.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7,0.8,0.9,0.9) leg.AddEntry(mframe2.findObject("SIG"),"Signal Model","l") leg.AddEntry(mframe2.findObject("JESUP"),"+1 Sigma","l") leg.AddEntry(mframe2.findObject("JESDOWN"),"-1 Sigma","l") leg.Draw() jesname = args.pdir+'/jes_m'+str(mass)+fstr+'.pdf' c2.SaveAs(jesname) # produce JER signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX()+1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i+1) jer = 1. - args.jerUnc xLowPrime = jer*(xLow-float(mass))+float(mass) xUpPrime = jer*(xUp-float(mass))+float(mass) hSig_Syst['JERUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jer = 1. + args.jerUnc xLowPrime = jer*(xLow-float(mass))+float(mass) xUpPrime = jer*(xUp-float(mass))+float(mass) hSig_Syst['JERDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JERUp'] = RooDataHist('hSig_JERUp','hSig_JERUp',RooArgList(mjj),hSig_Syst['JERUp']) hSig_Syst_DataHist['JERDown'] = RooDataHist('hSig_JERDown','hSig_JERDown',RooArgList(mjj),hSig_Syst['JERDown']) if args.jyes: c3 = TCanvas("c3","c3",800,800) mframe3 = mjj.frame(ROOT.RooFit.Title("JER One Sigma Shifts")) mframe3.SetAxisRange(525.,1200.) hSig_Syst_DataHist['JERUp'].plotOn(mframe3,ROOT.RooFit.Name("JERUP"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JERDown'].plotOn(mframe3,ROOT.RooFit.Name("JERDOWN"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe3,ROOT.RooFit.DrawOption("L"),ROOT.RooFit.Name("SIG"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe3.Draw() mframe3.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7,0.8,0.9,0.9) leg.AddEntry(mframe3.findObject("SIG"),"Signal Model","l") leg.AddEntry(mframe3.findObject("JERUP"),"+1 Sigma","l") leg.AddEntry(mframe3.findObject("JERDOWN"),"-1 Sigma","l") leg.Draw() jername = args.pdir+'/jer_m'+str(mass)+fstr+'.pdf' c3.SaveAs(jername) # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') dcName = 'datacard_' + args.final_state + '_m' + str(mass) + postfix + '.txt' wsName = 'workspace_' + args.final_state + '_m' + str(mass) + postfix + '.root' w = RooWorkspace('w','workspace') getattr(w,'import')(rooSigHist,RooFit.Rename("signal")) if args.jesUnc != None: getattr(w,'import')(hSig_Syst_DataHist['JESUp'],RooFit.Rename("signal__JESUp")) getattr(w,'import')(hSig_Syst_DataHist['JESDown'],RooFit.Rename("signal__JESDown")) if args.jerUnc != None: getattr(w,'import')(hSig_Syst_DataHist['JERUp'],RooFit.Rename("signal__JERUp")) getattr(w,'import')(hSig_Syst_DataHist['JERDown'],RooFit.Rename("signal__JERDown")) if args.decoBkg: getattr(w,'import')(background_deco,ROOT.RooCmdArg()) else: getattr(w,'import')(background,ROOT.RooCmdArg(),RooFit.Rename("background")) #if use different fits for shape uncertainties #getattr(w,'import')(,ROOT.RooCmdArg(),RooFit.Rename("background__bkgUp")) #getattr(w,'import')(,ROOT.RooCmdArg(),RooFit.Rename("background__bkgDown")) getattr(w,'import')(background_norm,ROOT.RooCmdArg()) getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs")) w.Print() w.writeToFile(os.path.join(args.output_path,wsName)) beffUnc = 0.3 boffUnc = 0.06 datacard = open(os.path.join(args.output_path,dcName),'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if args.jesUnc != None or args.jerUnc != None: datacard.write('shapes * * '+wsName+' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: datacard.write('shapes * * '+wsName+' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background\n') datacard.write('process 0 1\n') datacard.write('rate -1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n'%(1.+args.lumiUnc)) datacard.write('beff lnN %f -\n'%(1.+beffUnc)) datacard.write('boff lnN %f -\n'%(1.+boffUnc)) datacard.write('bkg lnN - 1.03\n') if args.jesUnc != None: datacard.write('JES shape 1 -\n') if args.jerUnc != None: datacard.write('JER shape 1 -\n') # flat parameters --- flat prior datacard.write('background_norm flatParam\n') if args.decoBkg: datacard.write('deco_eig1 flatParam\n') datacard.write('deco_eig2 flatParam\n') if not args.fixP3: datacard.write('deco_eig3 flatParam\n') else: datacard.write('p1 flatParam\n') datacard.write('p2 flatParam\n') if not args.fixP3: datacard.write('p3 flatParam\n') datacard.close() print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) )
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2" # input parameters parser = ArgumentParser( description= 'Script that creates combine datacards and corresponding RooFit workspaces', epilog=usage) parser.add_argument("--inputData", dest="inputData", required=True, help="Input data spectrum", metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", required=True, help="Data histogram name", metavar="DATA_HISTNAME") parser.add_argument("--inputSig", dest="inputSig", required=True, help="Input signal shapes", metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", required=True, help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)") parser.add_argument( "-o", "--output_path", dest="output_path", required=True, help="Output path where datacards and workspaces will be stored", metavar="OUTPUT_PATH") parser.add_argument( "-l", "--lumi", dest="lumi", required=True, default=1000., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument( "--massMin", dest="massMin", default=500, type=int, help= "Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument( "--massMax", dest="massMax", default=1200, type=int, help= "Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument( "--p1", dest="p1", default=5.0000e-03, type=float, help="Fit function p1 parameter (default: %(default)e)", metavar="P1") parser.add_argument( "--p2", dest="p2", default=9.1000e+00, type=float, help="Fit function p2 parameter (default: %(default)e)", metavar="P2") parser.add_argument( "--p3", dest="p3", default=5.0000e-01, type=float, help="Fit function p3 parameter (default: %(default)e)", metavar="P3") parser.add_argument( "--lumiUnc", dest="lumiUnc", required=True, type=float, help="Relative uncertainty in the integrated luminosity", metavar="LUMI_UNC") parser.add_argument("--jesUnc", dest="jesUnc", type=float, help="Relative uncertainty in the jet energy scale", metavar="JES_UNC") parser.add_argument( "--jerUnc", dest="jerUnc", type=float, help="Relative uncertainty in the jet energy resolution", metavar="JER_UNC") parser.add_argument( "--sqrtS", dest="sqrtS", default=13000., type=float, help="Collision center-of-mass energy (default: %(default).1f)", metavar="SQRTS") parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters") parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") parser.add_argument( "--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)") parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots") parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots") parser.add_argument( "--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)") parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared") parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument( "--mass", type=int, nargs='*', default=1000, help= "Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument( "--massrange", type=int, nargs=3, help="Define a range of masses to be produced. Format: min max step", metavar=('MIN', 'MAX', 'STEP')) mass_group.add_argument("--masslist", help="List containing mass information") args = parser.parse_args() if args.atype == 'hG': fstr = "bbhGGBB" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'hR': fstr = "bbhRS" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'lG': fstr = "bblGGBB" in2 = 'bcorrbin/binmodl.root' else: fstr = "bblRS" in2 = 'bcorrbin/binmodl.root' # check if the output directory exists if not os.path.isdir(os.path.join(os.getcwd(), args.output_path)): os.mkdir(os.path.join(os.getcwd(), args.output_path)) # mass points for which resonance shapes will be produced masses = [] if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX + STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py", "")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0, kFALSE) RooMsgService.instance().setStreamStatus(1, kFALSE) # input data file inputData = TFile(args.inputData) # input data histogram hData = inputData.Get(args.dataHistname) inData2 = TFile(in2) hData2 = inData2.Get('h_data') # input sig file inputSig = TFile(args.inputSig) sqrtS = args.sqrtS # mass variable mjj = RooRealVar('mjj', 'mjj', float(args.massMin), float(args.massMax)) # integrated luminosity and signal cross section lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..." % ( args.final_state, int(mass)) # get signal shape hSig = inputSig.Get("h_" + args.final_state + "_" + str(int(mass))) # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity) hSig.Scale( signalCrossSection * lumi / hSig.Integral() ) # divide by a number that provides roughly an r value of 1-10 rooSigHist = RooDataHist('rooSigHist', 'rooSigHist', RooArgList(mjj), hSig) print 'Signal acceptance:', (rooSigHist.sumEntries() / hSig.Integral()) signal = RooHistPdf('signal', 'signal', RooArgSet(mjj), rooSigHist) signal_norm = RooRealVar('signal_norm', 'signal_norm', 0, -1e+05, 1e+05) signal_norm2 = RooRealVar('signal_norm2', 'signal_norm2', 0, -1e+05, 1e+05) signal_norm3 = RooRealVar('signal_norm3', 'signal_norm3', 0, -1e+05, 1e+05) signal_norm4 = RooRealVar('signal_norm4', 'signal_norm4', 0, -1e+05, 1e+05) signal_norm5 = RooRealVar('signal_norm5', 'signal_norm5', 0, -1e+05, 1e+05) if args.fitBonly: signal_norm.setConstant() signal_norm2.setConstant() signal_norm3.setConstant() signal_norm4.setConstant() signal_norm5.setConstant() p1 = RooRealVar('p1', 'p1', args.p1, 0., 100.) p2 = RooRealVar('p2', 'p2', args.p2, 0., 60.) p3 = RooRealVar('p3', 'p3', args.p3, -10., 10.) p4 = RooRealVar('p4', 'p4', 5.6, -50., 50.) p5 = RooRealVar('p5', 'p5', 10., -50., 50.) p6 = RooRealVar('p6', 'p6', .016, -50., 50.) p7 = RooRealVar('p7', 'p7', 8., -50., 50.) p8 = RooRealVar('p8', 'p8', .22, -50., 50.) p9 = RooRealVar('p9', 'p9', 14.1, -50., 50.) p10 = RooRealVar('p10', 'p10', 8., -50., 50.) p11 = RooRealVar('p11', 'p11', 4.8, -50., 50.) p12 = RooRealVar('p12', 'p12', 7., -50., 50.) p13 = RooRealVar('p13', 'p13', 7., -50., 50.) p14 = RooRealVar('p14', 'p14', 7., -50., 50.) p15 = RooRealVar('p15', 'p15', 1., -50., 50.) p16 = RooRealVar('p16', 'p16', 9., -50., 50.) p17 = RooRealVar('p17', 'p17', 0.6, -50., 50.) if args.fixP3: p3.setConstant() background = RooGenericPdf( 'background', '(pow(1-@0/%.1f,@1)/pow(@0/%.1f,@2+@3*log(@0/%.1f)))' % (sqrtS, sqrtS, sqrtS), RooArgList(mjj, p1, p2, p3)) dataInt = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norm = RooRealVar('background_norm', 'background_norm', dataInt, 0., 1e+08) background2 = RooGenericPdf( 'background2', '(pow(@0/%.1f,-@1)*pow(1-@0/%.1f,@2))' % (sqrtS, sqrtS), RooArgList(mjj, p4, p5)) dataInt2 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background2_norm = RooRealVar('background2_norm', 'background2_norm', dataInt2, 0., 1e+08) background3 = RooGenericPdf('background3', '(1/pow(@1+@0/%.1f,@2))' % (sqrtS), RooArgList(mjj, p6, p7)) dataInt3 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background3_norm = RooRealVar('background3_norm', 'background3_norm', dataInt3, 0., 1e+08) background4 = RooGenericPdf( 'background4', '(1/pow(@1+@2*@0/%.1f+pow(@0/%.1f,2),@3))' % (sqrtS, sqrtS), RooArgList(mjj, p8, p9, p10)) dataInt4 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background4_norm = RooRealVar('background4_norm', 'background4_norm', dataInt4, 0., 1e+08) background5 = RooGenericPdf( 'background5', '(pow(@0/%.1f,-@1)*pow(1-pow(@0/%.1f,1/3),@2))' % (sqrtS, sqrtS), RooArgList(mjj, p11, p12)) dataInt5 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background5_norm = RooRealVar('background5_norm', 'background5_norm', dataInt5, 0., 1e+08) background6 = RooGenericPdf( 'background6', '(pow(@0/%.1f,2)+@1*@0/%.1f+@2)' % (sqrtS, sqrtS), RooArgList(mjj, p13, p14)) dataInt6 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norm6 = RooRealVar('background_norm6', 'background_norm6', dataInt6, 0., 1e+08) background7 = RooGenericPdf( 'background7', '((-1+@1*@0/%.1f)*pow(@0/%.1f,@2+@3*log(@0/%.1f)))' % (sqrtS, sqrtS, sqrtS), RooArgList(mjj, p15, p16, p17)) dataInt7 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norm7 = RooRealVar('background_norm7', 'background_norm7', dataInt7, 0., 1e+08) #Extend PDFs exts = RooExtendPdf('extsignal', 'Extended Signal Pdf', signal, signal_norm) extb = RooExtendPdf('extbackground', 'Extended Background Pdf', background, background_norm) exts2 = RooExtendPdf('extsignal2', 'Extended Signal Pdf2', signal, signal_norm2) extb2 = RooExtendPdf('extbackground2', 'Extended Background Pdf2', background2, background2_norm) exts3 = RooExtendPdf('extsignal3', 'Extended Signal Pdf3', signal, signal_norm3) extb3 = RooExtendPdf('extbackground3', 'Extended Background Pdf3', background3, background3_norm) exts4 = RooExtendPdf('extsignal4', 'Extended Signal Pdf4', signal, signal_norm4) extb4 = RooExtendPdf('extbackground4', 'Extended Background Pdf4', background4, background4_norm) exts5 = RooExtendPdf('extsignal5', 'Extended Signal Pdf5', signal, signal_norm5) extb5 = RooExtendPdf('extbackground5', 'Extended Background Pdf5', background5, background5_norm) # S+B model model = RooAddPdf("model", "s+b", RooArgList(extb, exts)) model2 = RooAddPdf("model2", "s+b2", RooArgList(extb2, exts2)) model3 = RooAddPdf("model3", "s+b3", RooArgList(extb3, exts3)) model4 = RooAddPdf("model4", "s+b4", RooArgList(extb4, exts4)) model5 = RooAddPdf("model5", "s+b5", RooArgList(extb5, exts5)) #model6 = RooAddPdf("model6","s+b6",RooArgList(background6,signal),RooArgList(background_norm6,signal_norm)) #model7 = RooAddPdf("model7","s+b7",RooArgList(background7,signal),RooArgList(background_norm7,signal_norm)) rooDataHist = RooDataHist('rooDatahist', 'rooDathist', RooArgList(mjj), hData) if args.runFit: mframe = mjj.frame() rooDataHist.plotOn(mframe, ROOT.RooFit.Name("setonedata")) res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframe, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res2 = model2.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model2.plotOn(mframe, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res3 = model3.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model3.plotOn(mframe, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res4 = model4.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model4.plotOn(mframe, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res5 = model5.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model5.plotOn(mframe, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) # res6 = model6.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model6.plotOn(mframe, ROOT.RooFit.Name("model6"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kPink)) # res7 = model7.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model7.plotOn(mframe, ROOT.RooFit.Name("model7"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kAzure)) rooDataHist2 = RooDataHist('rooDatahist2', 'rooDathist2', RooArgList(mjj), hData2) # rooDataHist2.plotOn(mframe, ROOT.RooFit.Name("data")) if args.pyes: c = TCanvas("c", "c", 800, 800) mframe.SetAxisRange(300., 1300.) c.SetLogy() # mframe.SetMaximum(10) # mframe.SetMinimum(1) mframe.Draw() fitname = args.pdir + '/5funcfit_m' + str(mass) + fstr + '.pdf' c.SaveAs(fitname) # cpull = TCanvas("cpull","cpull",800,800) # pulls = mframe.pullHist("data","model1") # pulls.Draw("ABX") # pullname = args.pdir+'/pull_m'+str(mass)+fstr+'.pdf' # cpull.SaveAs(pullname) # cpull2 = TCanvas("cpull2","cpull2",800,800) # pulls2 = mframe.pullHist("setonedata","model1") # pulls2.Draw("ABX") # pull2name = args.pdir+'/pull2_m'+str(mass)+fstr+'.pdf' # cpull2.SaveAs(pull2name) if args.widefit: mframew = mjj.frame() rooDataHist2.plotOn(mframew, ROOT.RooFit.Name("data")) res6 = model.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframew, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res7 = model2.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model2.plotOn(mframew, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res8 = model3.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model3.plotOn(mframew, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res9 = model4.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model4.plotOn(mframew, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res10 = model5.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model5.plotOn(mframew, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) if args.pyes: c = TCanvas("c", "c", 800, 800) mframew.SetAxisRange(300., 1300.) c.SetLogy() # mframew.SetMaximum(10) # mframew.SetMinimum(1) mframew.Draw() fitname = args.pdir + '/5funcfittowide_m' + str( mass) + fstr + '.pdf' c.SaveAs(fitname) cpull = TCanvas("cpull", "cpull", 800, 800) pulls = mframew.pullHist("data", "model1") pulls.Draw("ABX") pullname = args.pdir + '/pullwidefit_m' + str( mass) + fstr + '.pdf' cpull.SaveAs(pullname) if args.chi2: fullInt = model.createIntegral(RooArgSet(mjj)) norm = dataInt / fullInt.getVal() chi1 = 0. fullInt2 = model2.createIntegral(RooArgSet(mjj)) norm2 = dataInt2 / fullInt2.getVal() chi2 = 0. fullInt3 = model3.createIntegral(RooArgSet(mjj)) norm3 = dataInt3 / fullInt3.getVal() chi3 = 0. fullInt4 = model4.createIntegral(RooArgSet(mjj)) norm4 = dataInt4 / fullInt4.getVal() chi4 = 0. fullInt5 = model5.createIntegral(RooArgSet(mjj)) norm5 = dataInt5 / fullInt5.getVal() chi5 = 0. for i in range(args.massMin, args.massMax): new = 0 new2 = 0 new3 = 0 new4 = 0 new5 = 0 height = hData.GetBinContent(i) xLow = hData.GetXaxis().GetBinLowEdge(i) xUp = hData.GetXaxis().GetBinLowEdge(i + 1) obs = height * (xUp - xLow) mjj.setRange("intrange", xLow, xUp) integ = model.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp = integ.getVal() * norm new = pow(exp - obs, 2) / exp chi1 = chi1 + new integ2 = model2.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp2 = integ2.getVal() * norm2 new2 = pow(exp2 - obs, 2) / exp2 chi2 = chi2 + new2 integ3 = model3.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp3 = integ3.getVal() * norm3 new3 = pow(exp3 - obs, 2) / exp3 chi3 = chi3 + new3 integ4 = model4.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp4 = integ4.getVal() * norm4 if exp4 != 0: new4 = pow(exp4 - obs, 2) / exp4 else: new4 = 0 chi4 = chi4 + new4 integ5 = model5.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp5 = integ5.getVal() * norm5 new5 = pow(exp5 - obs, 2) / exp5 chi5 = chi5 + new5 print "chi1 %d " % (chi1) print "chi2 %d " % (chi2) print "chi3 %d " % (chi3) print "chi4 %d " % (chi4) print "chi5 %d " % (chi5) if not args.decoBkg: print " " res.Print() res2.Print() res3.Print() res4.Print() res5.Print() # res6.Print() # res7.Print() # decorrelated background parameters for Bayesian limits if args.decoBkg: signal_norm.setConstant() res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) res.Print() ## temp workspace for the PDF diagonalizer w_tmp = RooWorkspace("w_tmp") deco = PdfDiagonalizer("deco", w_tmp, res) # here diagonalizing only the shape parameters since the overall normalization is already decorrelated background_deco = deco.diagonalize(background) print "##################### workspace for decorrelation" w_tmp.Print("v") print "##################### original parameters" background.getParameters(rooDataHist).Print("v") print "##################### decorrelated parameters" # needed if want to evaluate limits without background systematics if args.fixBkg: w_tmp.var("deco_eig1").setConstant() w_tmp.var("deco_eig2").setConstant() if not args.fixP3: w_tmp.var("deco_eig3").setConstant() background_deco.getParameters(rooDataHist).Print("v") print "##################### original pdf" background.Print() print "##################### decorrelated pdf" background_deco.Print() # release signal normalization signal_norm.setConstant(kFALSE) # set the background normalization range to +/- 5 sigma bkg_val = background_norm.getVal() bkg_error = background_norm.getError() background_norm.setMin(bkg_val - 5 * bkg_error) background_norm.setMax(bkg_val + 5 * bkg_error) background_norm.Print() # change background PDF names background.SetName("background_old") background_deco.SetName("background") # needed if want to evaluate limits without background systematics if args.fixBkg: background_norm.setConstant() p1.setConstant() p2.setConstant() p3.setConstant() # ----------------------------------------- # dictionaries holding systematic variations of the signal shape hSig_Syst = {} hSig_Syst_DataHist = {} sigCDF = TGraph(hSig.GetNbinsX() + 1) # JES and JER uncertainties if args.jesUnc != None or args.jerUnc != None: sigCDF.SetPoint(0, 0., 0.) integral = 0. for i in range(1, hSig.GetNbinsX() + 1): x = hSig.GetXaxis().GetBinLowEdge(i + 1) integral = integral + hSig.GetBinContent(i) sigCDF.SetPoint(i, x, integral) if args.jesUnc != None: hSig_Syst['JESUp'] = copy.deepcopy(hSig) hSig_Syst['JESDown'] = copy.deepcopy(hSig) if args.jerUnc != None: hSig_Syst['JERUp'] = copy.deepcopy(hSig) hSig_Syst['JERDown'] = copy.deepcopy(hSig) # reset signal histograms for key in hSig_Syst.keys(): hSig_Syst[key].Reset() hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key) # produce JES signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX() + 1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i + 1) jes = 1. - args.jesUnc xLowPrime = jes * xLow xUpPrime = jes * xUp hSig_Syst['JESUp'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jes = 1. + args.jesUnc xLowPrime = jes * xLow xUpPrime = jes * xUp hSig_Syst['JESDown'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JESUp'] = RooDataHist('hSig_JESUp', 'hSig_JESUp', RooArgList(mjj), hSig_Syst['JESUp']) hSig_Syst_DataHist['JESDown'] = RooDataHist( 'hSig_JESDown', 'hSig_JESDown', RooArgList(mjj), hSig_Syst['JESDown']) if args.jyes: c2 = TCanvas("c2", "c2", 800, 800) mframe2 = mjj.frame(ROOT.RooFit.Title("JES One Sigma Shifts")) mframe2.SetAxisRange(args.massMin, args.massMax) hSig_Syst_DataHist['JESUp'].plotOn( mframe2, ROOT.RooFit.Name("JESUP"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JESDown'].plotOn( mframe2, ROOT.RooFit.Name("JESDOWN"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe2, ROOT.RooFit.DataError(2), ROOT.RooFit.Name("SIG"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe2.Draw() mframe2.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7, 0.8, 0.9, 0.9) leg.SetFillColor(0) leg.AddEntry(mframe2.findObject("SIG"), "Signal Model", "l") leg.AddEntry(mframe2.findObject("JESUP"), "+1 Sigma", "l") leg.AddEntry(mframe2.findObject("JESDOWN"), "-1 Sigma", "l") leg.Draw() jesname = args.pdir + '/jes_m' + str(mass) + fstr + '.pdf' c2.SaveAs(jesname) # produce JER signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX() + 1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i + 1) jer = 1. - args.jerUnc xLowPrime = jer * (xLow - float(mass)) + float(mass) xUpPrime = jer * (xUp - float(mass)) + float(mass) hSig_Syst['JERUp'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jer = 1. + args.jerUnc xLowPrime = jer * (xLow - float(mass)) + float(mass) xUpPrime = jer * (xUp - float(mass)) + float(mass) hSig_Syst['JERDown'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JERUp'] = RooDataHist('hSig_JERUp', 'hSig_JERUp', RooArgList(mjj), hSig_Syst['JERUp']) hSig_Syst_DataHist['JERDown'] = RooDataHist( 'hSig_JERDown', 'hSig_JERDown', RooArgList(mjj), hSig_Syst['JERDown']) if args.jyes: c3 = TCanvas("c3", "c3", 800, 800) mframe3 = mjj.frame(ROOT.RooFit.Title("JER One Sigma Shifts")) mframe3.SetAxisRange(args.massMin, args.massMax) hSig_Syst_DataHist['JERUp'].plotOn( mframe3, ROOT.RooFit.Name("JERUP"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JERDown'].plotOn( mframe3, ROOT.RooFit.Name("JERDOWN"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe3, ROOT.RooFit.DrawOption("L"), ROOT.RooFit.Name("SIG"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe3.Draw() mframe3.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7, 0.8, 0.9, 0.9) leg.SetFillColor(0) leg.AddEntry(mframe3.findObject("SIG"), "Signal Model", "l") leg.AddEntry(mframe3.findObject("JERUP"), "+1 Sigma", "l") leg.AddEntry(mframe3.findObject("JERDOWN"), "-1 Sigma", "l") leg.Draw() jername = args.pdir + '/jer_m' + str(mass) + fstr + '.pdf' c3.SaveAs(jername) # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') dcName = 'datacard_' + args.final_state + '_m' + str( mass) + postfix + '.txt' wsName = 'workspace_' + args.final_state + '_m' + str( mass) + postfix + '.root' w = RooWorkspace('w', 'workspace') getattr(w, 'import')(rooSigHist, RooFit.Rename("signal")) if args.jesUnc != None: getattr(w, 'import')(hSig_Syst_DataHist['JESUp'], RooFit.Rename("signal__JESUp")) getattr(w, 'import')(hSig_Syst_DataHist['JESDown'], RooFit.Rename("signal__JESDown")) if args.jerUnc != None: getattr(w, 'import')(hSig_Syst_DataHist['JERUp'], RooFit.Rename("signal__JERUp")) getattr(w, 'import')(hSig_Syst_DataHist['JERDown'], RooFit.Rename("signal__JERDown")) if args.decoBkg: getattr(w, 'import')(background_deco, ROOT.RooCmdArg()) else: getattr(w, 'import')(background, ROOT.RooCmdArg(), RooFit.Rename("background")) getattr(w, 'import')(background2, ROOT.RooCmdArg(), RooFit.Rename("background2")) getattr(w, 'import')(background3, ROOT.RooCmdArg(), RooFit.Rename("background3")) getattr(w, 'import')(background4, ROOT.RooCmdArg(), RooFit.Rename("background4")) getattr(w, 'import')(background5, ROOT.RooCmdArg(), RooFit.Rename("background5")) getattr(w, 'import')(background_norm, ROOT.RooCmdArg(), RooFit.Rename("background_norm")) getattr(w, 'import')(background2_norm, ROOT.RooCmdArg(), RooFit.Rename("background2_norm")) getattr(w, 'import')(background3_norm, ROOT.RooCmdArg(), RooFit.Rename("background3_norm")) getattr(w, 'import')(background4_norm, ROOT.RooCmdArg(), RooFit.Rename("background4_norm")) getattr(w, 'import')(background5_norm, ROOT.RooCmdArg(), RooFit.Rename("background5_norm")) getattr(w, 'import')(res) getattr(w, 'import')(res2) getattr(w, 'import')(res3) getattr(w, 'import')(res4) getattr(w, 'import')(res5) getattr(w, 'import')(background_norm, ROOT.RooCmdArg()) getattr(w, 'import')(signal_norm, ROOT.RooCmdArg()) getattr(w, 'import')(rooDataHist, RooFit.Rename("data_obs")) w.Print() w.writeToFile(os.path.join(args.output_path, wsName)) beffUnc = 0.3 boffUnc = 0.06 datacard = open(os.path.join(args.output_path, dcName), 'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if args.jesUnc != None or args.jerUnc != None: datacard.write('shapes * * ' + wsName + ' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: datacard.write('shapes * * ' + wsName + ' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background\n') datacard.write('process 0 1\n') datacard.write('rate -1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n' % (1. + args.lumiUnc)) datacard.write('beff lnN %f -\n' % (1. + beffUnc)) datacard.write('boff lnN %f -\n' % (1. + boffUnc)) datacard.write('bkg lnN - 1.03\n') if args.jesUnc != None: datacard.write('JES shape 1 -\n') if args.jerUnc != None: datacard.write('JER shape 1 -\n') # flat parameters --- flat prior datacard.write('background_norm flatParam\n') if args.decoBkg: datacard.write('deco_eig1 flatParam\n') datacard.write('deco_eig2 flatParam\n') if not args.fixP3: datacard.write('deco_eig3 flatParam\n') else: datacard.write('p1 flatParam\n') datacard.write('p2 flatParam\n') if not args.fixP3: datacard.write('p3 flatParam\n') datacard.close() print '>> Datacards and workspaces created and stored in %s/' % ( os.path.join(os.getcwd(), args.output_path))
def alpha(channel): nElec = channel.count("e") nMuon = channel.count("m") nLept = nElec + nMuon nBtag = channel.count("b") # Channel-dependent settings # Background function. Semi-working options are: EXP, EXP2, EXPN, EXPTAIL if nLept == 0: treeName = "SR" signName = "XZh" colorVjet = sample["DYJetsToNuNu"]["linecolor"] triName = "HLT_PFMET" leptCut = "0==0" topVeto = selection["TopVetocut"] massVar = "X_cmass" binFact = 1 fitFunc = "EXPN" if nBtag < 2 else "EXPN" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitAltFuncVjet = "POL" if nBtag < 2 else "POL" fitFuncVV = "EXPGAUS" if nBtag < 2 else "EXPGAUS" fitFuncTop = "GAUS2" elif nLept == 1: treeName = "WCR" signName = "XWh" colorVjet = sample["WJetsToLNu"]["linecolor"] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isWtoEN" if nElec > 0 else "isWtoMN" topVeto = selection["TopVetocut"] massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXPTAIL" if nBtag < 2 else "EXPN" fitAltFunc = "EXPN" if nBtag < 2 else "POW" else: fitFunc = "EXPN" if nBtag < 2 else "EXPN" fitAltFunc = "EXPTAIL" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitAltFuncVjet = "POL" if nBtag < 2 else "POL" fitFuncVV = "EXPGAUS" if nBtag < 2 else "EXPGAUS" fitFuncTop = "GAUS3" if nBtag < 2 else "GAUS2" else: treeName = "XZh" signName = "XZh" colorVjet = sample["DYJetsToLL"]["linecolor"] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isZtoEE" if nElec > 0 else "isZtoMM" topVeto = "X_dPhi>2.5" massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitAltFunc = "POW" if nBtag < 2 else "POW" else: fitFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitAltFunc = "POW" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 and nElec < 1 else "EXP" fitAltFuncVjet = "POL" if nBtag < 2 else "POL" fitFuncVV = "EXPGAUS2" if nBtag < 2 else "EXPGAUS2" fitFuncTop = "GAUS" btagCut = selection["2Btag"] if nBtag == 2 else selection["1Btag"] print "--- Channel", channel, "---" print " number of electrons:", nElec, " muons:", nMuon, " b-tags:", nBtag print " read tree:", treeName, "and trigger:", triName if ALTERNATIVE: print " using ALTERNATIVE fit functions" print "-" * 11 * 2 # Silent RooFit RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) # *******************************************************# # # # Variables and selections # # # # *******************************************************# # Define all the variables from the trees that will be used in the cuts and fits # this steps actually perform a "projection" of the entire tree on the variables in thei ranges, so be careful once setting the limits X_mass = RooRealVar(massVar, "m_{X}" if nLept > 0 else "m_{T}^{X}", XBINMIN, XBINMAX, "GeV") J_mass = RooRealVar("fatjet1_prunedMassCorr", "jet corrected pruned mass", HBINMIN, HBINMAX, "GeV") CSV1 = RooRealVar("fatjet1_CSVR1", "", -1.0e99, 1.0e4) CSV2 = RooRealVar("fatjet1_CSVR2", "", -1.0e99, 1.0e4) nB = RooRealVar("fatjet1_nBtag", "", 0.0, 4) CSVTop = RooRealVar("bjet1_CSVR", "", -1.0e99, 1.0e4) X_dPhi = RooRealVar("X_dPhi", "", 0.0, 3.15) isZtoEE = RooRealVar("isZtoEE", "", 0.0, 2) isZtoMM = RooRealVar("isZtoMM", "", 0.0, 2) isWtoEN = RooRealVar("isWtoEN", "", 0.0, 2) isWtoMN = RooRealVar("isWtoMN", "", 0.0, 2) weight = RooRealVar("eventWeightLumi", "", -1.0e9, 1.0) # Define the RooArgSet which will include all the variables defined before # there is a maximum of 9 variables in the declaration, so the others need to be added with 'add' variables = RooArgSet(X_mass, J_mass, CSV1, CSV2, nB, CSVTop, X_dPhi) variables.add(RooArgSet(isZtoEE, isZtoMM, isWtoEN, isWtoMN, weight)) # set reasonable ranges for J_mass and X_mass # these are used in the fit in order to avoid ROOFIT to look in regions very far away from where we are fitting # (honestly, it is not clear to me why it is necessary, but without them the fit often explodes) J_mass.setRange("h_reasonable_range", LOWMIN, HIGMAX) X_mass.setRange("X_reasonable_range", XBINMIN, XBINMAX) # Set RooArgSets once for all, see https://root.cern.ch/phpBB3/viewtopic.php?t=11758 jetMassArg = RooArgSet(J_mass) # Define the ranges in fatJetMass - these will be used to define SB and SR J_mass.setRange("LSBrange", LOWMIN, LOWMAX) J_mass.setRange("HSBrange", HIGMIN, HIGMAX) J_mass.setRange("VRrange", LOWMAX, SIGMIN) J_mass.setRange("SRrange", SIGMIN, SIGMAX) # Set binning for plots J_mass.setBins(HBINS) X_mass.setBins(binFact * XBINS) # Define the selection for the various categories (base + SR / LSBcut / HSBcut ) baseCut = leptCut + " && " + btagCut + "&&" + topVeto massCut = massVar + ">%d" % XBINMIN baseCut += " && " + massCut # Cuts SRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), SIGMIN, J_mass.GetName(), SIGMAX) LSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX) HSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) SBcut = baseCut + " && ((%s>%d && %s<%d) || (%s>%d && %s<%d))" % ( J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX, J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX, ) VRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMAX, J_mass.GetName(), SIGMIN) # Binning binsJmass = RooBinning(HBINS, HBINMIN, HBINMAX) # binsJmass.addUniform(HBINS, HBINMIN, HBINMAX) binsXmass = RooBinning(binFact * XBINS, XBINMIN, XBINMAX) # binsXmass.addUniform(binFact*XBINS, XBINMIN, XBINMAX) # *******************************************************# # # # Input files # # # # *******************************************************# # Import the files using TChains (separately for the bkg "classes" that we want to describe: here DY and VV+ST+TT) treeData = TChain(treeName) treeMC = TChain(treeName) treeVjet = TChain(treeName) treeVV = TChain(treeName) treeTop = TChain(treeName) treeSign = {} nevtSign = {} for i, m in enumerate(massPoints): treeSign[m] = TChain(treeName) # Read data pd = getPrimaryDataset(triName) if len(pd) == 0: raw_input("Warning: Primary Dataset not recognized, continue?") for i, s in enumerate(pd): treeData.Add(NTUPLEDIR + s + ".root") # Read V+jets backgrounds for i, s in enumerate(["WJetsToLNu_HT", "DYJetsToNuNu_HT", "DYJetsToLL_HT"]): for j, ss in enumerate(sample[s]["files"]): treeVjet.Add(NTUPLEDIR + ss + ".root") # Read VV backgrounds for i, s in enumerate(["VV"]): for j, ss in enumerate(sample[s]["files"]): treeVV.Add(NTUPLEDIR + ss + ".root") # Read Top backgrounds for i, s in enumerate(["ST", "TTbar"]): for j, ss in enumerate(sample[s]["files"]): treeTop.Add(NTUPLEDIR + ss + ".root") # Read signals for i, m in enumerate(massPoints): for j, ss in enumerate(sample["%s_M%d" % (signName, m)]["files"]): treeSign[m].Add(NTUPLEDIR + ss + ".root") sfile = TFile(NTUPLEDIR + ss + ".root", "READ") shist = sfile.Get("Counters/Counter") nevtSign[m] = shist.GetBinContent(1) sfile.Close() # Sum all background MC treeMC.Add(treeVjet) treeMC.Add(treeVV) treeMC.Add(treeTop) # create a dataset to host data in sideband (using this dataset we are automatically blind in the SR!) setDataSB = RooDataSet( "setDataSB", "setDataSB", variables, RooFit.Cut(SBcut), RooFit.WeightVar(weight), RooFit.Import(treeData) ) setDataLSB = RooDataSet( "setDataLSB", "setDataLSB", variables, RooFit.Import(setDataSB), RooFit.Cut(LSBcut), RooFit.WeightVar(weight) ) setDataHSB = RooDataSet( "setDataHSB", "setDataHSB", variables, RooFit.Import(setDataSB), RooFit.Cut(HSBcut), RooFit.WeightVar(weight) ) # Observed data (WARNING, BLIND!) setDataSR = RooDataSet( "setDataSR", "setDataSR", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeData) ) setDataVR = RooDataSet( "setDataVR", "setDataVR", variables, RooFit.Cut(VRcut), RooFit.WeightVar(weight), RooFit.Import(treeData) ) # Observed in the VV mass, just for plotting purposes setDataSRSB = RooDataSet( "setDataSRSB", "setDataSRSB", variables, RooFit.Cut("(" + SRcut + ") || (" + SBcut + ")"), RooFit.WeightVar(weight), RooFit.Import(treeData), ) # same for the bkg datasets from MC, where we just apply the base selections (not blind) setVjet = RooDataSet( "setVjet", "setVjet", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVjet) ) setVjetSB = RooDataSet( "setVjetSB", "setVjetSB", variables, RooFit.Import(setVjet), RooFit.Cut(SBcut), RooFit.WeightVar(weight) ) setVjetSR = RooDataSet( "setVjetSR", "setVjetSR", variables, RooFit.Import(setVjet), RooFit.Cut(SRcut), RooFit.WeightVar(weight) ) setVV = RooDataSet( "setVV", "setVV", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVV) ) setVVSB = RooDataSet( "setVVSB", "setVVSB", variables, RooFit.Import(setVV), RooFit.Cut(SBcut), RooFit.WeightVar(weight) ) setVVSR = RooDataSet( "setVVSR", "setVVSR", variables, RooFit.Import(setVV), RooFit.Cut(SRcut), RooFit.WeightVar(weight) ) setTop = RooDataSet( "setTop", "setTop", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeTop) ) setTopSB = RooDataSet( "setTopSB", "setTopSB", variables, RooFit.Import(setTop), RooFit.Cut(SBcut), RooFit.WeightVar(weight) ) setTopSR = RooDataSet( "setTopSR", "setTopSR", variables, RooFit.Import(setTop), RooFit.Cut(SRcut), RooFit.WeightVar(weight) ) print " Data events SB: %.2f" % setDataSB.sumEntries() print " V+jets entries: %.2f" % setVjet.sumEntries() print " VV, VH entries: %.2f" % setVV.sumEntries() print " Top,ST entries: %.2f" % setTop.sumEntries() nVV = RooRealVar("nVV", "VV normalization", setVV.sumEntries(SBcut), 0.0, 2 * setVV.sumEntries(SBcut)) nTop = RooRealVar("nTop", "Top normalization", setTop.sumEntries(SBcut), 0.0, 2 * setTop.sumEntries(SBcut)) nVjet = RooRealVar("nVjet", "Vjet normalization", setDataSB.sumEntries(), 0.0, 2 * setDataSB.sumEntries(SBcut)) nVjet2 = RooRealVar("nVjet2", "Vjet2 normalization", setDataSB.sumEntries(), 0.0, 2 * setDataSB.sumEntries(SBcut)) # Apply Top SF nTop.setVal(nTop.getVal() * topSF[nLept][nBtag]) nTop.setError(nTop.getVal() * topSFErr[nLept][nBtag]) # Define entries entryVjet = RooRealVar("entryVjets", "V+jets normalization", setVjet.sumEntries(), 0.0, 1.0e6) entryVV = RooRealVar("entryVV", "VV normalization", setVV.sumEntries(), 0.0, 1.0e6) entryTop = RooRealVar("entryTop", "Top normalization", setTop.sumEntries(), 0.0, 1.0e6) entrySB = RooRealVar("entrySB", "Data SB normalization", setDataSB.sumEntries(SBcut), 0.0, 1.0e6) entrySB.setError(math.sqrt(entrySB.getVal())) entryLSB = RooRealVar("entryLSB", "Data LSB normalization", setDataSB.sumEntries(LSBcut), 0.0, 1.0e6) entryLSB.setError(math.sqrt(entryLSB.getVal())) entryHSB = RooRealVar("entryHSB", "Data HSB normalization", setDataSB.sumEntries(HSBcut), 0.0, 1.0e6) entryHSB.setError(math.sqrt(entryHSB.getVal())) ################################################################################### # _ _ # # | \ | | | (_) | | (_) # # | \| | ___ _ __ _ __ ___ __ _| |_ ___ __ _| |_ _ ___ _ __ # # | . ` |/ _ \| '__| '_ ` _ \ / _` | | / __|/ _` | __| |/ _ \| '_ \ # # | |\ | (_) | | | | | | | | (_| | | \__ \ (_| | |_| | (_) | | | | # # |_| \_|\___/|_| |_| |_| |_|\__,_|_|_|___/\__,_|\__|_|\___/|_| |_| # # # ################################################################################### # fancy ASCII art thanks to, I guess, Jose # start by creating the fit models to get the normalization: # * MAIN and SECONDARY bkg are taken from MC by fitting the whole J_mass range # * The two PDFs are added together using the relative normalizations of the two bkg from MC # * DATA is then fit in the sidebands only using the combined bkg PDF # * The results of the fit are then estrapolated in the SR and the integral is evaluated. # * This defines the bkg normalization in the SR # *******************************************************# # # # V+jets normalization # # # # *******************************************************# # Variables for V+jets constVjet = RooRealVar("constVjet", "slope of the exp", -0.020, -1.0, 0.0) offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 30.0, -50.0, 400.0) widthVjet = RooRealVar("widthVjet", "width of the erf", 100.0, 1.0, 200.0) # 0, 400 a0Vjet = RooRealVar("a0Vjet", "width of the erf", -0.1, -5, 0) a1Vjet = RooRealVar("a1Vjet", "width of the erf", 0.6, 0, 5) a2Vjet = RooRealVar("a2Vjet", "width of the erf", -0.1, -1, 1) if channel == "XZhnnb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 500.0, 200.0, 1000.0) if channel == "XZhnnbb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 350.0, 200.0, 500.0) # if channel == "XWhenb" or channel == "XZheeb": # offsetVjet.setVal(120.) # offsetVjet.setConstant(True) if channel == "XWhenb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 120.0, 80.0, 155.0) if channel == "XWhenbb" or channel == "XZhmmb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 67.0, 50.0, 100.0) if channel == "XWhmnb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 30.0, -50.0, 600.0) if channel == "XZheeb": offsetVjet.setMin(-400) offsetVjet.setVal(0.0) offsetVjet.setMax(1000) widthVjet.setVal(1.0) # Define V+jets model if fitFuncVjet == "ERFEXP": VjetMass = RooErfExpPdf("VjetMass", fitFuncVjet, J_mass, constVjet, offsetVjet, widthVjet) elif fitFuncVjet == "EXP": VjetMass = RooExponential("VjetMass", fitFuncVjet, J_mass, constVjet) elif fitFuncVjet == "GAUS": VjetMass = RooGaussian("VjetMass", fitFuncVjet, J_mass, offsetVjet, widthVjet) elif fitFuncVjet == "POL": VjetMass = RooChebychev("VjetMass", fitFuncVjet, J_mass, RooArgList(a0Vjet, a1Vjet, a2Vjet)) elif fitFuncVjet == "POW": VjetMass = RooGenericPdf("VjetMass", fitFuncVjet, "@0^@1", RooArgList(J_mass, a0Vjet)) else: print " ERROR! Pdf", fitFuncVjet, "is not implemented for Vjets" exit() if fitAltFuncVjet == "POL": VjetMass2 = RooChebychev("VjetMass2", "polynomial for V+jets mass", J_mass, RooArgList(a0Vjet, a1Vjet, a2Vjet)) else: print " ERROR! Pdf", fitAltFuncVjet, "is not implemented for Vjets" exit() # fit to main bkg in MC (whole range) frVjet = VjetMass.fitTo( setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) frVjet2 = VjetMass2.fitTo( setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS Vjets] *" + "*" * 40, "\n", frVjet.Print(), "\n", "*" * 80 # likelihoodScan(VjetMass, setVjet, [constVjet, offsetVjet, widthVjet]) # *******************************************************# # # # VV, VH normalization # # # # *******************************************************# # Variables for VV # Error function and exponential to model the bulk constVV = RooRealVar("constVV", "slope of the exp", -0.030, -0.1, 0.0) offsetVV = RooRealVar("offsetVV", "offset of the erf", 90.0, 1.0, 300.0) widthVV = RooRealVar("widthVV", "width of the erf", 50.0, 1.0, 100.0) erfrVV = RooErfExpPdf("baseVV", "error function for VV jet mass", J_mass, constVV, offsetVV, widthVV) expoVV = RooExponential("baseVV", "error function for VV jet mass", J_mass, constVV) # gaussian for the V mass peak meanVV = RooRealVar("meanVV", "mean of the gaussian", 90.0, 60.0, 100.0) sigmaVV = RooRealVar("sigmaVV", "sigma of the gaussian", 10.0, 6.0, 30.0) fracVV = RooRealVar("fracVV", "fraction of gaussian wrt erfexp", 3.2e-1, 0.0, 1.0) gausVV = RooGaussian("gausVV", "gaus for VV jet mass", J_mass, meanVV, sigmaVV) # gaussian for the H mass peak meanVH = RooRealVar("meanVH", "mean of the gaussian", 125.0, 100.0, 150.0) sigmaVH = RooRealVar("sigmaVH", "sigma of the gaussian", 10.0, 5.0, 50.0) fracVH = RooRealVar("fracVH", "fraction of gaussian wrt erfexp", 1.5e-2, 0.0, 1.0) gausVH = RooGaussian("gausVH", "gaus for VH jet mass", J_mass, meanVH, sigmaVH) # Define VV model if fitFuncVV == "ERFEXPGAUS": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVV, erfrVV), RooArgList(fracVV)) elif fitFuncVV == "ERFEXPGAUS2": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVH, gausVV, erfrVV), RooArgList(fracVH, fracVV)) elif fitFuncVV == "EXPGAUS": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVV, expoVV), RooArgList(fracVV)) elif fitFuncVV == "EXPGAUS2": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVH, gausVV, expoVV), RooArgList(fracVH, fracVV)) else: print " ERROR! Pdf", fitFuncVV, "is not implemented for VV" exit() # fit to secondary bkg in MC (whole range) frVV = VVMass.fitTo( setVV, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS VV] ****" + "*" * 40, "\n", frVV.Print(), "\n", "*" * 80 # *******************************************************# # # # Top, ST normalization # # # # *******************************************************# # Variables for Top # Error Function * Exponential to model the bulk constTop = RooRealVar("constTop", "slope of the exp", -0.030, -1.0, 0.0) offsetTop = RooRealVar("offsetTop", "offset of the erf", 175.0, 50.0, 250.0) widthTop = RooRealVar("widthTop", "width of the erf", 100.0, 1.0, 300.0) gausTop = RooGaussian("baseTop", "gaus for Top jet mass", J_mass, offsetTop, widthTop) erfrTop = RooErfExpPdf("baseTop", "error function for Top jet mass", J_mass, constTop, offsetTop, widthTop) # gaussian for the W mass peak meanW = RooRealVar("meanW", "mean of the gaussian", 80.0, 70.0, 90.0) sigmaW = RooRealVar("sigmaW", "sigma of the gaussian", 10.0, 2.0, 20.0) fracW = RooRealVar("fracW", "fraction of gaussian wrt erfexp", 0.1, 0.0, 1.0) gausW = RooGaussian("gausW", "gaus for W jet mass", J_mass, meanW, sigmaW) # gaussian for the Top mass peak meanT = RooRealVar("meanT", "mean of the gaussian", 175.0, 150.0, 200.0) sigmaT = RooRealVar("sigmaT", "sigma of the gaussian", 12.0, 5.0, 30.0) fracT = RooRealVar("fracT", "fraction of gaussian wrt erfexp", 0.1, 0.0, 1.0) gausT = RooGaussian("gausT", "gaus for T jet mass", J_mass, meanT, sigmaT) if channel == "XZheeb" or channel == "XZheebb" or channel == "XZhmmb" or channel == "XZhmmbb": offsetTop = RooRealVar("offsetTop", "offset of the erf", 200.0, -50.0, 450.0) widthTop = RooRealVar("widthTop", "width of the erf", 100.0, 1.0, 1000.0) # Define Top model if fitFuncTop == "ERFEXPGAUS2": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausW, gausT, erfrTop), RooArgList(fracW, fracT)) elif fitFuncTop == "ERFEXPGAUS": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausT, erfrTop), RooArgList(fracT)) elif fitFuncTop == "GAUS3": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausW, gausT, gausTop), RooArgList(fracW, fracT)) elif fitFuncTop == "GAUS2": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausT, gausTop), RooArgList(fracT)) elif fitFuncTop == "GAUS": TopMass = RooGaussian("TopMass", fitFuncTop, J_mass, offsetTop, widthTop) else: print " ERROR! Pdf", fitFuncTop, "is not implemented for Top" exit() # fit to secondary bkg in MC (whole range) frTop = TopMass.fitTo( setTop, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS TOP] ***" + "*" * 40, "\n", frTop.Print(), "\n", "*" * 80 # likelihoodScan(TopMass, setTop, [offsetTop, widthTop]) # *******************************************************# # # # All bkg normalization # # # # *******************************************************# # nVjet.setConstant(False) # nVjet2.setConstant(False) # # constVjet.setConstant(False) # offsetVjet.setConstant(False) # widthVjet.setConstant(False) # a0Vjet.setConstant(False) # a1Vjet.setConstant(False) # a2Vjet.setConstant(False) constVV.setConstant(True) offsetVV.setConstant(True) widthVV.setConstant(True) meanVV.setConstant(True) sigmaVV.setConstant(True) fracVV.setConstant(True) meanVH.setConstant(True) sigmaVH.setConstant(True) fracVH.setConstant(True) constTop.setConstant(True) offsetTop.setConstant(True) widthTop.setConstant(True) meanW.setConstant(True) sigmaW.setConstant(True) fracW.setConstant(True) meanT.setConstant(True) sigmaT.setConstant(True) fracT.setConstant(True) nVV.setConstant(True) nTop.setConstant(True) nVjet.setConstant(False) nVjet2.setConstant(False) # Final background model by adding the main+secondary pdfs (using 'coef': ratio of the secondary/main, from MC) TopMass_ext = RooExtendPdf("TopMass_ext", "extended p.d.f", TopMass, nTop) VVMass_ext = RooExtendPdf("VVMass_ext", "extended p.d.f", VVMass, nVV) VjetMass_ext = RooExtendPdf("VjetMass_ext", "extended p.d.f", VjetMass, nVjet) VjetMass2_ext = RooExtendPdf("VjetMass_ext", "extended p.d.f", VjetMass, nVjet2) BkgMass = RooAddPdf( "BkgMass", "BkgMass", RooArgList(TopMass_ext, VVMass_ext, VjetMass_ext), RooArgList(nTop, nVV, nVjet) ) BkgMass2 = RooAddPdf( "BkgMass2", "BkgMass2", RooArgList(TopMass_ext, VVMass_ext, VjetMass2_ext), RooArgList(nTop, nVV, nVjet2) ) BkgMass.fixAddCoefRange("h_reasonable_range") BkgMass2.fixAddCoefRange("h_reasonable_range") # Extended fit model to data in SB frMass = BkgMass.fitTo( setDataSB, RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) # , RooFit.NumCPU(10) if VERBOSE: print "********** Fit result [JET MASS DATA] **" + "*" * 40, "\n", frMass.Print(), "\n", "*" * 80 frMass2 = BkgMass2.fitTo( setDataSB, RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS DATA] **" + "*" * 40, "\n", frMass2.Print(), "\n", "*" * 80 # if SCAN: # likelihoodScan(VjetMass, setVjet, [constVjet, offsetVjet, widthVjet]) # Fix normalization and parameters of V+jets after the fit to data nVjet.setConstant(True) nVjet2.setConstant(True) constVjet.setConstant(True) offsetVjet.setConstant(True) widthVjet.setConstant(True) a0Vjet.setConstant(True) a1Vjet.setConstant(True) a2Vjet.setConstant(True) # integrals for global normalization # do not integrate the composte model: results have no sense # integral for normalization in the SB iSBVjet = VjetMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iSBVV = VVMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iSBTop = TopMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) # integral for normalization in the SR iSRVjet = VjetMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iSRVV = VVMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iSRTop = TopMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) # integral for normalization in the VR iVRVjet = VjetMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) iVRVV = VVMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) iVRTop = TopMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # formual vars SByield = RooFormulaVar( "SByield", "extrapolation to SR", "@0*@1 + @2*@3 + @4*@5", RooArgList(iSBVjet, nVjet, iSBVV, nVV, iSBTop, nTop) ) VRyield = RooFormulaVar( "VRyield", "extrapolation to VR", "@0*@1 + @2*@3 + @4*@5", RooArgList(iVRVjet, nVjet, iVRVV, nVV, iVRTop, nTop) ) SRyield = RooFormulaVar( "SRyield", "extrapolation to SR", "@0*@1 + @2*@3 + @4*@5", RooArgList(iSRVjet, nVjet, iSRVV, nVV, iSRTop, nTop) ) # fractions fSBVjet = RooRealVar( "fVjet", "Fraction of Vjet events in SB", iSBVjet.getVal() * nVjet.getVal() / SByield.getVal(), 0.0, 1.0 ) fSBVV = RooRealVar( "fSBVV", "Fraction of VV events in SB", iSBVV.getVal() * nVV.getVal() / SByield.getVal(), 0.0, 1.0 ) fSBTop = RooRealVar( "fSBTop", "Fraction of Top events in SB", iSBTop.getVal() * nTop.getVal() / SByield.getVal(), 0.0, 1.0 ) fSRVjet = RooRealVar( "fSRVjet", "Fraction of Vjet events in SR", iSRVjet.getVal() * nVjet.getVal() / SRyield.getVal(), 0.0, 1.0 ) fSRVV = RooRealVar( "fSRVV", "Fraction of VV events in SR", iSRVV.getVal() * nVV.getVal() / SRyield.getVal(), 0.0, 1.0 ) fSRTop = RooRealVar( "fSRTop", "Fraction of Top events in SR", iSRTop.getVal() * nTop.getVal() / SRyield.getVal(), 0.0, 1.0 ) # final normalization values bkgYield = SRyield.getVal() bkgYield2 = ( (VjetMass2.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange"))).getVal() * nVjet2.getVal() + iSRVV.getVal() * nVV.getVal() + iSRTop.getVal() * nTop.getVal() ) bkgYield_syst = math.sqrt(SRyield.getPropagatedError(frVV) ** 2 + SRyield.getPropagatedError(frTop) ** 2) bkgYield_stat = math.sqrt(SRyield.getPropagatedError(frMass) ** 2) bkgYield_alte = abs(bkgYield - bkgYield2) # /bkgYield bkgYield_eig_norm = RooRealVar("predSR_eig_norm", "expected yield in SR", bkgYield, 0.0, 1.0e6) print "Events in channel", channel, ": V+jets %.3f (%.1f%%), VV %.3f (%.1f%%), Top %.3f (%.1f%%)" % ( iSRVjet.getVal() * nVjet.getVal(), fSRVjet.getVal() * 100, iSRVV.getVal() * nVV.getVal(), fSRVV.getVal() * 100, iSRTop.getVal() * nTop.getVal(), fSRTop.getVal() * 100, ) print "Events in channel", channel, ": Integral = $%.3f$ & $\pm %.3f$ & $\pm %.3f$ & $\pm %.3f$, observed = %.0f" % ( bkgYield, bkgYield_stat, bkgYield_syst, bkgYield_alte, setDataSR.sumEntries() if not False else -1, )
bkg.plotOn(phiFrame,LineColor(kRed),Normalization(bFrac),LineStyle(kDashed)) signal.plotOn(phiFrame,LineColor(kGreen),Normalization(1.0-bFrac)) tot.paramOn(phiFrame,RooFit.Layout(0.72,0.99,0.4))#,Parameters(RooArgSet(nSig))) #signal.paramOn(phiFrame,RooFit.Layout(0.57,0.99,0.65),Parameters(RooArgSet(mean,sigma))) lowranges = [] uppranges = [] sides = [3.0,5.0,8.0] for i in sides: mass_ref_c_kkk.setRange("sigma_"+ str(i),mean.getVal()-float(i)*sigma.getVal(),mean.getVal()+float(i)*sigma.getVal()) lowranges.append(mean.getVal()-float(i)*sigma.getVal()) uppranges.append(mean.getVal()+float(i)*sigma.getVal()) totIntegralSig = signal.createIntegral(RooArgSet(mass_ref_c_kkk)).getVal() totIntegralBkg = bkg.analyticalIntegral(bkg.getAnalyticalIntegral(RooArgSet(mass_ref_c_kkk),RooArgSet(mass_ref_c_kkk))) totIntegralTot = tot.createIntegral(RooArgSet(mass_ref_c_kkk)).getVal() print "Tot sig: " + str(totIntegralSig) print "Tot bkg: " + str(totIntegralBkg) print "Tot tot: " + str(totIntegralTot) sigIntegrals = [] totIntegrals = [] bkgIntegrals = [] phiFrame.Draw()