def __init__ (self, pars): self.pars = pars self.ws = RooWorkspace('wjj2dfitter') self.utils = Wjj2DFitterUtils(self.pars) self.useImportPars = False self.rangeString = None obs = [] for v in self.pars.var: try: vName = self.pars.varNames[v] except AttributeError: vName = v obs.append(vName) var1 = self.ws.factory('%s[%f,%f]' % (vName, self.pars.varRanges[v][1], self.pars.varRanges[v][2]) ) var1.setUnit('GeV') try: var1.SetTitle(self.pars.varTitles[v]) except AttributeError: var1.SetTitle('m_{jj}') var1.setPlotLabel(var1.GetTitle()) if len(self.pars.varRanges[v][3]) > 1: vbinning = RooBinning(len(self.pars.varRanges[v][3]) - 1, array('d', self.pars.varRanges[v][3]), '%sBinning' % vName) var1.setBinning(vbinning) else: var1.setBins(self.pars.varRanges[v][0]) var1.Print() if v in self.pars.exclude: var1.setRange('signalRegion', self.pars.exclude[v][0], self.pars.exclude[v][1]) var1.setRange('lowSideband', var1.getMin(), self.pars.exclude[v][0]) var1.setRange('highSideband', self.pars.exclude[v][1], var1.getMax()) self.rangeString = 'lowSideband,highSideband' self.ws.defineSet('obsSet', ','.join(obs))
def signal(channel, stype): if 'VBF' in channel: stype = 'XZHVBF' else: stype = 'XZH' # HVT model if stype.startswith('X'): signalType = 'HVT' genPoints = [800, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000, 3500, 4000, 4500, 5000] massPoints = [x for x in range(800, 5000+1, 100)] interPar = True else: print "Signal type", stype, "not recognized" return n = len(genPoints) category = channel cColor = color[category] if category in color else 1 nElec = channel.count('e') nMuon = channel.count('m') nLept = nElec + nMuon nBtag = channel.count('b') if '0b' in channel: nBtag = 0 X_name = "VH_mass" if not os.path.exists(PLOTDIR+stype+category): os.makedirs(PLOTDIR+stype+category) #*******************************************************# # # # Variables and selections # # # #*******************************************************# X_mass = RooRealVar( "X_mass", "m_{ZH}", XBINMIN, XBINMAX, "GeV") J_mass = RooRealVar( "H_mass", "jet mass", LOWMIN, HIGMAX, "GeV") V_mass = RooRealVar( "V_mass", "V jet mass", -9., 1.e6, "GeV") CSV1 = RooRealVar( "H_csv1", "", -999., 2. ) CSV2 = RooRealVar( "H_csv2", "", -999., 2. ) DeepCSV1= RooRealVar( "H_deepcsv1", "", -999., 2. ) DeepCSV2= RooRealVar( "H_deepcsv2", "", -999., 2. ) H_ntag = RooRealVar( "H_ntag", "", -9., 9. ) H_dbt = RooRealVar( "H_dbt", "", -2., 2. ) H_tau21 = RooRealVar( "H_tau21", "", -9., 2. ) H_eta = RooRealVar( "H_eta", "", -9., 9. ) H_tau21_ddt = RooRealVar( "H_ddt", "", -9., 2. ) MaxBTag = RooRealVar( "MaxBTag", "", -10., 2. ) H_chf = RooRealVar( "H_chf", "", -1., 2. ) MinDPhi = RooRealVar( "MinDPhi", "", -1., 99. ) DPhi = RooRealVar( "DPhi", "", -1., 99. ) DEta = RooRealVar( "DEta", "", -1., 99. ) Mu1_relIso = RooRealVar( "Mu1_relIso", "", -1., 99. ) Mu2_relIso = RooRealVar( "Mu2_relIso", "", -1., 99. ) nTaus = RooRealVar( "nTaus", "", -1., 99. ) Vpt = RooRealVar( "V.Pt()", "", -1., 1.e6 ) V_pt = RooRealVar( "V_pt", "", -1., 1.e6 ) H_pt = RooRealVar( "H_pt", "", -1., 1.e6 ) VH_deltaR=RooRealVar( "VH_deltaR", "", -1., 99. ) isZtoNN = RooRealVar( "isZtoNN", "", 0., 2. ) isZtoEE = RooRealVar( "isZtoEE", "", 0., 2. ) isZtoMM = RooRealVar( "isZtoMM", "", 0., 2. ) isHtobb = RooRealVar( "isHtobb", "", 0., 2. ) isVBF = RooRealVar( "isVBF", "", 0., 2. ) isMaxBTag_loose = RooRealVar( "isMaxBTag_loose", "", 0., 2. ) weight = RooRealVar( "eventWeightLumi", "", -1.e9, 1.e9 ) Xmin = XBINMIN Xmax = XBINMAX # 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, V_mass, CSV1, CSV2, H_ntag, H_dbt, H_tau21) variables.add(RooArgSet(DEta, DPhi, MaxBTag, MinDPhi, nTaus, Vpt)) variables.add(RooArgSet(DeepCSV1, DeepCSV2,VH_deltaR, H_tau21_ddt)) variables.add(RooArgSet(isZtoNN, isZtoEE, isZtoMM, isHtobb, isMaxBTag_loose, weight)) variables.add(RooArgSet(isVBF, Mu1_relIso, Mu2_relIso, H_chf, H_pt, V_pt,H_eta)) #X_mass.setRange("X_extended_range", X_mass.getMin(), X_mass.getMax()) X_mass.setRange("X_reasonable_range", X_mass.getMin(), X_mass.getMax()) X_mass.setRange("X_integration_range", Xmin, Xmax) X_mass.setBins(int((X_mass.getMax() - X_mass.getMin())/100)) binsXmass = RooBinning(int((X_mass.getMax() - X_mass.getMin())/100), X_mass.getMin(), X_mass.getMax()) X_mass.setBinning(binsXmass, "PLOT") massArg = RooArgSet(X_mass) # Cuts SRcut = selection[category]+selection['SR'] print " Cut:\t", SRcut #*******************************************************# # # # Signal fits # # # #*******************************************************# treeSign = {} setSignal = {} vmean = {} vsigma = {} valpha1 = {} vslope1 = {} smean = {} ssigma = {} salpha1 = {} sslope1 = {} salpha2 = {} sslope2 = {} a1 = {} a2 = {} sbrwig = {} signal = {} signalExt = {} signalYield = {} signalIntegral = {} signalNorm = {} signalXS = {} frSignal = {} frSignal1 = {} frSignal2 = {} frSignal3 = {} # Signal shape uncertainties (common amongst all mass points) xmean_fit = RooRealVar("sig_p1_fit", "Variation of the resonance position with the fit uncertainty", 0.005, -1., 1.) smean_fit = RooRealVar("CMSRunII_sig_p1_fit", "Change of the resonance position with the fit uncertainty", 0., -10, 10) xmean_jes = RooRealVar("sig_p1_scale_jes", "Variation of the resonance position with the jet energy scale", 0.010, -1., 1.) #0.001 smean_jes = RooRealVar("CMSRunII_sig_p1_jes", "Change of the resonance position with the jet energy scale", 0., -10, 10) xmean_e = RooRealVar("sig_p1_scale_e", "Variation of the resonance position with the electron energy scale", 0.001, -1., 1.) smean_e = RooRealVar("CMSRunII_sig_p1_scale_e", "Change of the resonance position with the electron energy scale", 0., -10, 10) xmean_m = RooRealVar("sig_p1_scale_m", "Variation of the resonance position with the muon energy scale", 0.001, -1., 1.) smean_m = RooRealVar("CMSRunII_sig_p1_scale_m", "Change of the resonance position with the muon energy scale", 0., -10, 10) xsigma_fit = RooRealVar("sig_p2_fit", "Variation of the resonance width with the fit uncertainty", 0.02, -1., 1.) ssigma_fit = RooRealVar("CMSRunII_sig_p2_fit", "Change of the resonance width with the fit uncertainty", 0., -10, 10) xsigma_jes = RooRealVar("sig_p2_scale_jes", "Variation of the resonance width with the jet energy scale", 0.010, -1., 1.) #0.001 ssigma_jes = RooRealVar("CMSRunII_sig_p2_jes", "Change of the resonance width with the jet energy scale", 0., -10, 10) xsigma_jer = RooRealVar("sig_p2_scale_jer", "Variation of the resonance width with the jet energy resolution", 0.020, -1., 1.) ssigma_jer = RooRealVar("CMSRunII_sig_p2_jer", "Change of the resonance width with the jet energy resolution", 0., -10, 10) xsigma_e = RooRealVar("sig_p2_scale_e", "Variation of the resonance width with the electron energy scale", 0.001, -1., 1.) ssigma_e = RooRealVar("CMSRunII_sig_p2_scale_e", "Change of the resonance width with the electron energy scale", 0., -10, 10) xsigma_m = RooRealVar("sig_p2_scale_m", "Variation of the resonance width with the muon energy scale", 0.040, -1., 1.) ssigma_m = RooRealVar("CMSRunII_sig_p2_scale_m", "Change of the resonance width with the muon energy scale", 0., -10, 10) xalpha1_fit = RooRealVar("sig_p3_fit", "Variation of the resonance alpha with the fit uncertainty", 0.03, -1., 1.) salpha1_fit = RooRealVar("CMSRunII_sig_p3_fit", "Change of the resonance alpha with the fit uncertainty", 0., -10, 10) xslope1_fit = RooRealVar("sig_p4_fit", "Variation of the resonance slope with the fit uncertainty", 0.10, -1., 1.) sslope1_fit = RooRealVar("CMSRunII_sig_p4_fit", "Change of the resonance slope with the fit uncertainty", 0., -10, 10) xmean_fit.setConstant(True) smean_fit.setConstant(True) xmean_jes.setConstant(True) smean_jes.setConstant(True) xmean_e.setConstant(True) smean_e.setConstant(True) xmean_m.setConstant(True) smean_m.setConstant(True) xsigma_fit.setConstant(True) ssigma_fit.setConstant(True) xsigma_jes.setConstant(True) ssigma_jes.setConstant(True) xsigma_jer.setConstant(True) ssigma_jer.setConstant(True) xsigma_e.setConstant(True) ssigma_e.setConstant(True) xsigma_m.setConstant(True) ssigma_m.setConstant(True) xalpha1_fit.setConstant(True) salpha1_fit.setConstant(True) xslope1_fit.setConstant(True) sslope1_fit.setConstant(True) # the alpha method is now done. for m in massPoints: signalString = "M%d" % m signalMass = "%s_M%d" % (stype, m) signalName = "%s%s_M%d" % (stype, category, m) signalColor = sample[signalMass]['linecolor'] if signalName in sample else 1 # define the signal PDF vmean[m] = RooRealVar(signalName + "_vmean", "Crystal Ball mean", m, m*0.5, m*1.25) smean[m] = RooFormulaVar(signalName + "_mean", "@0*(1+@1*@2)*(1+@3*@4)*(1+@5*@6)*(1+@7*@8)", RooArgList(vmean[m], xmean_e, smean_e, xmean_m, smean_m, xmean_jes, smean_jes, xmean_fit, smean_fit)) vsigma[m] = RooRealVar(signalName + "_vsigma", "Crystal Ball sigma", m*0.035, m*0.01, m*0.4) sigmaList = RooArgList(vsigma[m], xsigma_e, ssigma_e, xsigma_m, ssigma_m, xsigma_jes, ssigma_jes, xsigma_jer, ssigma_jer) sigmaList.add(RooArgList(xsigma_fit, ssigma_fit)) ssigma[m] = RooFormulaVar(signalName + "_sigma", "@0*(1+@1*@2)*(1+@3*@4)*(1+@5*@6)*(1+@7*@8)*(1+@9*@10)", sigmaList) valpha1[m] = RooRealVar(signalName + "_valpha1", "Crystal Ball alpha", 1., 0., 5.) # number of sigmas where the exp is attached to the gaussian core. >0 left, <0 right salpha1[m] = RooFormulaVar(signalName + "_alpha1", "@0*(1+@1*@2)", RooArgList(valpha1[m], xalpha1_fit, salpha1_fit)) vslope1[m] = RooRealVar(signalName + "_vslope1", "Crystal Ball slope", 10., 1., 60.) # slope of the power tail #10 1 60 sslope1[m] = RooFormulaVar(signalName + "_slope1", "@0*(1+@1*@2)", RooArgList(vslope1[m], xslope1_fit, sslope1_fit)) salpha2[m] = RooRealVar(signalName + "_alpha2", "Crystal Ball alpha", 2, 1., 5.) # number of sigmas where the exp is attached to the gaussian core. >0 left, <0 right sslope2[m] = RooRealVar(signalName + "_slope2", "Crystal Ball slope", 10, 1.e-1, 115.) # slope of the power tail #define polynomial #a1[m] = RooRealVar(signalName + "_a1", "par 1 for polynomial", m, 0.5*m, 2*m) a1[m] = RooRealVar(signalName + "_a1", "par 1 for polynomial", 0.001*m, 0.0005*m, 0.01*m) a2[m] = RooRealVar(signalName + "_a2", "par 2 for polynomial", 0.05, -1.,1.) #if channel=='nnbbVBF' or channel=='nn0bVBF': # signal[m] = RooPolynomial(signalName,"m_{%s'} = %d GeV" % (stype[1], m) , X_mass, RooArgList(a1[m],a2[m])) #else: # signal[m] = RooCBShape(signalName, "m_{%s'} = %d GeV" % (stype[1], m), X_mass, smean[m], ssigma[m], salpha1[m], sslope1[m]) # Signal name does not have the channel signal[m] = RooCBShape(signalName, "m_{%s'} = %d GeV" % (stype[1], m), X_mass, smean[m], ssigma[m], salpha1[m], sslope1[m]) # Signal name does not have the channel # extend the PDF with the yield to perform an extended likelihood fit signalYield[m] = RooRealVar(signalName+"_yield", "signalYield", 100, 0., 1.e6) signalNorm[m] = RooRealVar(signalName+"_norm", "signalNorm", 1., 0., 1.e6) signalXS[m] = RooRealVar(signalName+"_xs", "signalXS", 1., 0., 1.e6) signalExt[m] = RooExtendPdf(signalName+"_ext", "extended p.d.f", signal[m], signalYield[m]) vslope1[m].setMax(50.) vslope1[m].setVal(20.) #valpha1[m].setVal(1.0) #valpha1[m].setConstant(True) if 'bb' in channel and 'VBF' not in channel: if 'nn' in channel: valpha1[m].setVal(0.5) elif '0b' in channel and 'VBF' not in channel: if 'nn' in channel: if m==800: valpha1[m].setVal(2.) vsigma[m].setVal(m*0.04) elif 'ee' in channel: valpha1[m].setVal(0.8) if m==800: #valpha1[m].setVal(1.2) valpha1[m].setVal(2.5) vslope1[m].setVal(50.) elif 'mm' in channel: if m==800: valpha1[m].setVal(2.) vsigma[m].setVal(m*0.03) else: vmean[m].setVal(m*0.9) vsigma[m].setVal(m*0.08) elif 'bb' in channel and 'VBF' in channel: if 'nn' in channel: if m!=1800: vmean[m].setVal(m*0.8) vsigma[m].setVal(m*0.08) valpha1[m].setMin(1.) elif 'ee' in channel: valpha1[m].setVal(0.7) elif 'mm' in channel: if m==800: vslope1[m].setVal(50.) valpha1[m].setVal(0.7) elif '0b' in channel and 'VBF' in channel: if 'nn' in channel: valpha1[m].setVal(3.) vmean[m].setVal(m*0.8) vsigma[m].setVal(m*0.08) valpha1[m].setMin(1.) elif 'ee' in channel: if m<2500: valpha1[m].setVal(2.) if m==800: vsigma[m].setVal(m*0.05) elif m==1000: vsigma[m].setVal(m*0.03) elif m>1000 and m<1800: vsigma[m].setVal(m*0.04) elif 'mm' in channel: if m<2000: valpha1[m].setVal(2.) if m==1000 or m==1800: vsigma[m].setVal(m*0.03) elif m==1200 or m==1600: vsigma[m].setVal(m*0.04) #if m < 1000: vsigma[m].setVal(m*0.06) # If it's not the proper channel, make it a gaussian #if nLept==0 and 'VBF' in channel: # valpha1[m].setVal(5) # valpha1[m].setConstant(True) # vslope1[m].setConstant(True) # salpha2[m].setConstant(True) # sslope2[m].setConstant(True) # ---------- if there is no simulated signal, skip this mass point ---------- if m in genPoints: if VERBOSE: print " - Mass point", m # define the dataset for the signal applying the SR cuts treeSign[m] = TChain("tree") for j, ss in enumerate(sample[signalMass]['files']): treeSign[m].Add(NTUPLEDIR + ss + ".root") if treeSign[m].GetEntries() <= 0.: if VERBOSE: print " - 0 events available for mass", m, "skipping mass point..." signalNorm[m].setVal(-1) vmean[m].setConstant(True) vsigma[m].setConstant(True) salpha1[m].setConstant(True) sslope1[m].setConstant(True) salpha2[m].setConstant(True) sslope2[m].setConstant(True) signalNorm[m].setConstant(True) signalXS[m].setConstant(True) continue setSignal[m] = RooDataSet("setSignal_"+signalName, "setSignal", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeSign[m])) if VERBOSE: print " - Dataset with", setSignal[m].sumEntries(), "events loaded" # FIT signalYield[m].setVal(setSignal[m].sumEntries()) if treeSign[m].GetEntries(SRcut) > 5: if VERBOSE: print " - Running fit" frSignal[m] = signalExt[m].fitTo(setSignal[m], RooFit.Save(1), RooFit.Extended(True), RooFit.SumW2Error(True), RooFit.PrintLevel(-1)) if VERBOSE: print "********** Fit result [", m, "] **", category, "*"*40, "\n", frSignal[m].Print(), "\n", "*"*80 if VERBOSE: frSignal[m].correlationMatrix().Print() drawPlot(signalMass, stype+channel, X_mass, signal[m], setSignal[m], frSignal[m]) else: print " WARNING: signal", stype, "and mass point", m, "in channel", channel, "has 0 entries or does not exist" # Remove HVT cross section (which is the same for Zlep and Zinv) if stype == "XZHVBF": sample_name = 'Zprime_VBF_Zh_Zlephinc_narrow_M-%d' % m else: sample_name = 'ZprimeToZHToZlepHinc_narrow_M%d' % m xs = xsection[sample_name]['xsec'] signalXS[m].setVal(xs * 1000.) signalIntegral[m] = signalExt[m].createIntegral(massArg, RooFit.NormSet(massArg), RooFit.Range("X_integration_range")) boundaryFactor = signalIntegral[m].getVal() if VERBOSE: print " - Fit normalization vs integral:", signalYield[m].getVal(), "/", boundaryFactor, "events" if channel=='nnbb' and m==5000: signalNorm[m].setVal(2.5) elif channel=='nn0b' and m==5000: signalNorm[m].setVal(6.7) else: signalNorm[m].setVal( boundaryFactor * signalYield[m].getVal() / signalXS[m].getVal()) # here normalize to sigma(X) x Br(X->VH) = 1 [fb] a1[m].setConstant(True) a2[m].setConstant(True) vmean[m].setConstant(True) vsigma[m].setConstant(True) valpha1[m].setConstant(True) vslope1[m].setConstant(True) salpha2[m].setConstant(True) sslope2[m].setConstant(True) signalNorm[m].setConstant(True) signalXS[m].setConstant(True) #*******************************************************# # # # Signal interpolation # # # #*******************************************************# # ====== CONTROL PLOT ====== c_signal = TCanvas("c_signal", "c_signal", 800, 600) c_signal.cd() frame_signal = X_mass.frame() for m in genPoints[:-2]: if m in signalExt.keys(): signal[m].plotOn(frame_signal, RooFit.LineColor(sample["%s_M%d" % (stype, m)]['linecolor']), RooFit.Normalization(signalNorm[m].getVal(), RooAbsReal.NumEvent), RooFit.Range("X_reasonable_range")) frame_signal.GetXaxis().SetRangeUser(0, 6500) frame_signal.Draw() drawCMS(-1, YEAR, "Simulation") drawAnalysis(channel) drawRegion(channel) c_signal.SaveAs(PLOTDIR+"/"+stype+category+"/"+stype+"_Signal.pdf") c_signal.SaveAs(PLOTDIR+"/"+stype+category+"/"+stype+"_Signal.png") #if VERBOSE: raw_input("Press Enter to continue...") # ====== CONTROL PLOT ====== # Normalization gnorm = TGraphErrors() gnorm.SetTitle(";m_{X} (GeV);integral (GeV)") gnorm.SetMarkerStyle(20) gnorm.SetMarkerColor(1) gnorm.SetMaximum(0) inorm = TGraphErrors() inorm.SetMarkerStyle(24) fnorm = TF1("fnorm", "pol9", 800, 5000) #"pol5" if not channel=="XZHnnbb" else "pol6" #pol5*TMath::Floor(x-1800) + ([5]*x + [6]*x*x)*(1-TMath::Floor(x-1800)) fnorm.SetLineColor(920) fnorm.SetLineStyle(7) fnorm.SetFillColor(2) fnorm.SetLineColor(cColor) # Mean gmean = TGraphErrors() gmean.SetTitle(";m_{X} (GeV);gaussian mean (GeV)") gmean.SetMarkerStyle(20) gmean.SetMarkerColor(cColor) gmean.SetLineColor(cColor) imean = TGraphErrors() imean.SetMarkerStyle(24) fmean = TF1("fmean", "pol1", 0, 5000) fmean.SetLineColor(2) fmean.SetFillColor(2) # Width gsigma = TGraphErrors() gsigma.SetTitle(";m_{X} (GeV);gaussian width (GeV)") gsigma.SetMarkerStyle(20) gsigma.SetMarkerColor(cColor) gsigma.SetLineColor(cColor) isigma = TGraphErrors() isigma.SetMarkerStyle(24) fsigma = TF1("fsigma", "pol1", 0, 5000) fsigma.SetLineColor(2) fsigma.SetFillColor(2) # Alpha1 galpha1 = TGraphErrors() galpha1.SetTitle(";m_{X} (GeV);crystal ball lower alpha") galpha1.SetMarkerStyle(20) galpha1.SetMarkerColor(cColor) galpha1.SetLineColor(cColor) ialpha1 = TGraphErrors() ialpha1.SetMarkerStyle(24) falpha1 = TF1("falpha", "pol0", 0, 5000) falpha1.SetLineColor(2) falpha1.SetFillColor(2) # Slope1 gslope1 = TGraphErrors() gslope1.SetTitle(";m_{X} (GeV);exponential lower slope (1/Gev)") gslope1.SetMarkerStyle(20) gslope1.SetMarkerColor(cColor) gslope1.SetLineColor(cColor) islope1 = TGraphErrors() islope1.SetMarkerStyle(24) fslope1 = TF1("fslope", "pol0", 0, 5000) fslope1.SetLineColor(2) fslope1.SetFillColor(2) # Alpha2 galpha2 = TGraphErrors() galpha2.SetTitle(";m_{X} (GeV);crystal ball upper alpha") galpha2.SetMarkerStyle(20) galpha2.SetMarkerColor(cColor) galpha2.SetLineColor(cColor) ialpha2 = TGraphErrors() ialpha2.SetMarkerStyle(24) falpha2 = TF1("falpha", "pol0", 0, 5000) falpha2.SetLineColor(2) falpha2.SetFillColor(2) # Slope2 gslope2 = TGraphErrors() gslope2.SetTitle(";m_{X} (GeV);exponential upper slope (1/Gev)") gslope2.SetMarkerStyle(20) gslope2.SetMarkerColor(cColor) gslope2.SetLineColor(cColor) islope2 = TGraphErrors() islope2.SetMarkerStyle(24) fslope2 = TF1("fslope", "pol0", 0, 5000) fslope2.SetLineColor(2) fslope2.SetFillColor(2) n = 0 for i, m in enumerate(genPoints): if not m in signalNorm.keys(): continue if signalNorm[m].getVal() < 1.e-6: continue signalString = "M%d" % m signalName = "%s_M%d" % (stype, m) if gnorm.GetMaximum() < signalNorm[m].getVal(): gnorm.SetMaximum(signalNorm[m].getVal()) gnorm.SetPoint(n, m, signalNorm[m].getVal()) gmean.SetPoint(n, m, vmean[m].getVal()) gmean.SetPointError(n, 0, min(vmean[m].getError(), vmean[m].getVal()*0.02)) gsigma.SetPoint(n, m, vsigma[m].getVal()) gsigma.SetPointError(n, 0, min(vsigma[m].getError(), vsigma[m].getVal()*0.05)) galpha1.SetPoint(n, m, valpha1[m].getVal()) galpha1.SetPointError(n, 0, min(valpha1[m].getError(), valpha1[m].getVal()*0.10)) gslope1.SetPoint(n, m, vslope1[m].getVal()) gslope1.SetPointError(n, 0, min(vslope1[m].getError(), vslope1[m].getVal()*0.10)) galpha2.SetPoint(n, m, salpha2[m].getVal()) galpha2.SetPointError(n, 0, min(salpha2[m].getError(), salpha2[m].getVal()*0.10)) gslope2.SetPoint(n, m, sslope2[m].getVal()) gslope2.SetPointError(n, 0, min(sslope2[m].getError(), sslope2[m].getVal()*0.10)) n = n + 1 print "fit on gmean:" gmean.Fit(fmean, "Q0", "SAME") print "fit on gsigma:" gsigma.Fit(fsigma, "Q0", "SAME") print "fit on galpha:" galpha1.Fit(falpha1, "Q0", "SAME") print "fit on gslope:" gslope1.Fit(fslope1, "Q0", "SAME") galpha2.Fit(falpha2, "Q0", "SAME") gslope2.Fit(fslope2, "Q0", "SAME") #for m in [5000, 5500]: gnorm.SetPoint(gnorm.GetN(), m, gnorm.Eval(m, 0, "S")) gnorm.Fit(fnorm, "Q", "SAME", 700, 5000) for m in massPoints: signalName = "%s_M%d" % (stype, m) if vsigma[m].getVal() < 10.: vsigma[m].setVal(10.) # Interpolation method syield = gnorm.Eval(m) spline = gnorm.Eval(m, 0, "S") sfunct = fnorm.Eval(m) #delta = min(abs(1.-spline/sfunct), abs(1.-spline/syield)) delta = abs(1.-spline/sfunct) if sfunct > 0 else 0 syield = spline if interPar: jmean = gmean.Eval(m) jsigma = gsigma.Eval(m) jalpha1 = galpha1.Eval(m) jslope1 = gslope1.Eval(m) else: jmean = fmean.GetParameter(0) + fmean.GetParameter(1)*m + fmean.GetParameter(2)*m*m jsigma = fsigma.GetParameter(0) + fsigma.GetParameter(1)*m + fsigma.GetParameter(2)*m*m jalpha1 = falpha1.GetParameter(0) + falpha1.GetParameter(1)*m + falpha1.GetParameter(2)*m*m jslope1 = fslope1.GetParameter(0) + fslope1.GetParameter(1)*m + fslope1.GetParameter(2)*m*m inorm.SetPoint(inorm.GetN(), m, syield) signalNorm[m].setVal(syield) imean.SetPoint(imean.GetN(), m, jmean) if jmean > 0: vmean[m].setVal(jmean) isigma.SetPoint(isigma.GetN(), m, jsigma) if jsigma > 0: vsigma[m].setVal(jsigma) ialpha1.SetPoint(ialpha1.GetN(), m, jalpha1) if not jalpha1==0: valpha1[m].setVal(jalpha1) islope1.SetPoint(islope1.GetN(), m, jslope1) if jslope1 > 0: vslope1[m].setVal(jslope1) c1 = TCanvas("c1", "Crystal Ball", 1200, 800) c1.Divide(2, 2) c1.cd(1) gmean.SetMinimum(0.) gmean.Draw("APL") imean.Draw("P, SAME") drawRegion(channel) c1.cd(2) gsigma.SetMinimum(0.) gsigma.Draw("APL") isigma.Draw("P, SAME") drawRegion(channel) c1.cd(3) galpha1.Draw("APL") ialpha1.Draw("P, SAME") drawRegion(channel) galpha1.GetYaxis().SetRangeUser(0., 5.) c1.cd(4) gslope1.Draw("APL") islope1.Draw("P, SAME") drawRegion(channel) gslope1.GetYaxis().SetRangeUser(0., 125.) if False: c1.cd(5) galpha2.Draw("APL") ialpha2.Draw("P, SAME") drawRegion(channel) c1.cd(6) gslope2.Draw("APL") islope2.Draw("P, SAME") drawRegion(channel) gslope2.GetYaxis().SetRangeUser(0., 10.) c1.Print(PLOTDIR+stype+category+"/"+stype+"_SignalShape.pdf") c1.Print(PLOTDIR+stype+category+"/"+stype+"_SignalShape.png") c2 = TCanvas("c2", "Signal Efficiency", 800, 600) c2.cd(1) gnorm.SetMarkerColor(cColor) gnorm.SetMarkerStyle(20) gnorm.SetLineColor(cColor) gnorm.SetLineWidth(2) gnorm.Draw("APL") inorm.Draw("P, SAME") gnorm.GetXaxis().SetRangeUser(genPoints[0]-100, genPoints[-1]+100) gnorm.GetYaxis().SetRangeUser(0., gnorm.GetMaximum()*1.25) drawCMS(-1,YEAR , "Simulation") drawAnalysis(channel) drawRegion(channel) c2.Print(PLOTDIR+stype+category+"/"+stype+"_SignalNorm.pdf") c2.Print(PLOTDIR+stype+category+"/"+stype+"_SignalNorm.png") #*******************************************************# # # # Generate workspace # # # #*******************************************************# # create workspace w = RooWorkspace("ZH_RunII", "workspace") for m in massPoints: getattr(w, "import")(signal[m], RooFit.Rename(signal[m].GetName())) getattr(w, "import")(signalNorm[m], RooFit.Rename(signalNorm[m].GetName())) getattr(w, "import")(signalXS[m], RooFit.Rename(signalXS[m].GetName())) w.writeToFile("%s%s.root" % (WORKDIR, stype+channel), True) print "Workspace", "%s%s.root" % (WORKDIR, stype+channel), "saved successfully" sys.exit()
def signal(category): interPar = True n = len(genPoints) cColor = color[category] if category in color else 4 nBtag = category.count('b') isAH = False #relict from using Alberto's more complex script if not os.path.exists(PLOTDIR + "MC_signal_" + YEAR): os.makedirs(PLOTDIR + "MC_signal_" + YEAR) #*******************************************************# # # # Variables and selections # # # #*******************************************************# X_mass = RooRealVar("jj_mass_widejet", "m_{jj}", X_min, X_max, "GeV") j1_pt = RooRealVar("jpt_1", "jet1 pt", 0., 13000., "GeV") jj_deltaEta = RooRealVar("jj_deltaEta_widejet", "", 0., 5.) jbtag_WP_1 = RooRealVar("jbtag_WP_1", "", -1., 4.) jbtag_WP_2 = RooRealVar("jbtag_WP_2", "", -1., 4.) fatjetmass_1 = RooRealVar("fatjetmass_1", "", -1., 2500.) fatjetmass_2 = RooRealVar("fatjetmass_2", "", -1., 2500.) jid_1 = RooRealVar("jid_1", "j1 ID", -1., 8.) jid_2 = RooRealVar("jid_2", "j2 ID", -1., 8.) jnmuons_1 = RooRealVar("jnmuons_1", "j1 n_{#mu}", -1., 8.) jnmuons_2 = RooRealVar("jnmuons_2", "j2 n_{#mu}", -1., 8.) jnmuons_loose_1 = RooRealVar("jnmuons_loose_1", "jnmuons_loose_1", -1., 8.) jnmuons_loose_2 = RooRealVar("jnmuons_loose_2", "jnmuons_loose_2", -1., 8.) nmuons = RooRealVar("nmuons", "n_{#mu}", -1., 10.) nelectrons = RooRealVar("nelectrons", "n_{e}", -1., 10.) HLT_AK8PFJet500 = RooRealVar("HLT_AK8PFJet500", "", -1., 1.) HLT_PFJet500 = RooRealVar("HLT_PFJet500", "", -1., 1.) HLT_CaloJet500_NoJetID = RooRealVar("HLT_CaloJet500_NoJetID", "", -1., 1.) HLT_PFHT900 = RooRealVar("HLT_PFHT900", "", -1., 1.) HLT_AK8PFJet550 = RooRealVar("HLT_AK8PFJet550", "", -1., 1.) HLT_PFJet550 = RooRealVar("HLT_PFJet550", "", -1., 1.) HLT_CaloJet550_NoJetID = RooRealVar("HLT_CaloJet550_NoJetID", "", -1., 1.) HLT_PFHT1050 = RooRealVar("HLT_PFHT1050", "", -1., 1.) #HLT_DoublePFJets100_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets100_CaloBTagDeepCSV_p71" , "", -1., 1. ) #HLT_DoublePFJets116MaxDeta1p6_DoubleCaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets116MaxDeta1p6_DoubleCaloBTagDeepCSV_p71", "", -1., 1. ) #HLT_DoublePFJets128MaxDeta1p6_DoubleCaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets128MaxDeta1p6_DoubleCaloBTagDeepCSV_p71", "", -1., 1. ) #HLT_DoublePFJets200_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets200_CaloBTagDeepCSV_p71" , "", -1., 1. ) #HLT_DoublePFJets350_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets350_CaloBTagDeepCSV_p71" , "", -1., 1. ) #HLT_DoublePFJets40_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets40_CaloBTagDeepCSV_p71" , "", -1., 1. ) weight = RooRealVar("eventWeightLumi", "", -1.e9, 1.e9) # 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) variables.add( RooArgSet(j1_pt, jj_deltaEta, jbtag_WP_1, jbtag_WP_2, fatjetmass_1, fatjetmass_2, jnmuons_1, jnmuons_2, weight)) variables.add( RooArgSet(nmuons, nelectrons, jid_1, jid_2, jnmuons_loose_1, jnmuons_loose_2)) variables.add( RooArgSet(HLT_AK8PFJet500, HLT_PFJet500, HLT_CaloJet500_NoJetID, HLT_PFHT900, HLT_AK8PFJet550, HLT_PFJet550, HLT_CaloJet550_NoJetID, HLT_PFHT1050)) #variables.add(RooArgSet(HLT_DoublePFJets100_CaloBTagDeepCSV_p71, HLT_DoublePFJets116MaxDeta1p6_DoubleCaloBTagDeepCSV_p71, HLT_DoublePFJets128MaxDeta1p6_DoubleCaloBTagDeepCSV_p71, HLT_DoublePFJets200_CaloBTagDeepCSV_p71, HLT_DoublePFJets350_CaloBTagDeepCSV_p71, HLT_DoublePFJets40_CaloBTagDeepCSV_p71)) X_mass.setRange("X_reasonable_range", X_mass.getMin(), X_mass.getMax()) X_mass.setRange("X_integration_range", X_mass.getMin(), X_mass.getMax()) if VARBINS: binsXmass = RooBinning(len(abins) - 1, abins) X_mass.setBinning(binsXmass) plot_binning = RooBinning( int((X_mass.getMax() - X_mass.getMin()) / 100.), X_mass.getMin(), X_mass.getMax()) else: X_mass.setBins(int((X_mass.getMax() - X_mass.getMin()) / 10)) binsXmass = RooBinning(int((X_mass.getMax() - X_mass.getMin()) / 100.), X_mass.getMin(), X_mass.getMax()) plot_binning = binsXmass X_mass.setBinning(plot_binning, "PLOT") #X_mass.setBins(int((X_mass.getMax() - X_mass.getMin())/10)) #binsXmass = RooBinning(int((X_mass.getMax() - X_mass.getMin())/100), X_mass.getMin(), X_mass.getMax()) #X_mass.setBinning(binsXmass, "PLOT") massArg = RooArgSet(X_mass) # Cuts if BTAGGING == 'semimedium': SRcut = aliasSM[category] #SRcut = aliasSM[category+"_vetoAK8"] else: SRcut = alias[category].format(WP=working_points[BTAGGING]) #SRcut = alias[category+"_vetoAK8"].format(WP=working_points[BTAGGING]) if ADDSELECTION: SRcut += SELECTIONS[options.selection] print " Cut:\t", SRcut #*******************************************************# # # # Signal fits # # # #*******************************************************# treeSign = {} setSignal = {} vmean = {} vsigma = {} valpha1 = {} vslope1 = {} valpha2 = {} vslope2 = {} smean = {} ssigma = {} salpha1 = {} sslope1 = {} salpha2 = {} sslope2 = {} sbrwig = {} signal = {} signalExt = {} signalYield = {} signalIntegral = {} signalNorm = {} signalXS = {} frSignal = {} frSignal1 = {} frSignal2 = {} frSignal3 = {} # Signal shape uncertainties (common amongst all mass points) xmean_jes = RooRealVar( "CMS" + YEAR + "_sig_" + category + "_p1_scale_jes", "Variation of the resonance position with the jet energy scale", 0.02, -1., 1.) #0.001 smean_jes = RooRealVar( "CMS" + YEAR + "_sig_" + category + "_p1_jes", "Change of the resonance position with the jet energy scale", 0., -10, 10) xsigma_jer = RooRealVar( "CMS" + YEAR + "_sig_" + category + "_p2_scale_jer", "Variation of the resonance width with the jet energy resolution", 0.10, -1., 1.) ssigma_jer = RooRealVar( "CMS" + YEAR + "_sig_" + category + "_p2_jer", "Change of the resonance width with the jet energy resolution", 0., -10, 10) xmean_jes.setConstant(True) smean_jes.setConstant(True) xsigma_jer.setConstant(True) ssigma_jer.setConstant(True) for m in massPoints: signalMass = "%s_M%d" % (stype, m) signalName = "ZpBB_{}_{}_M{}".format(YEAR, category, m) sampleName = "ZpBB_M{}".format(m) signalColor = sample[sampleName][ 'linecolor'] if signalName in sample else 1 # define the signal PDF vmean[m] = RooRealVar(signalName + "_vmean", "Crystal Ball mean", m, m * 0.96, m * 1.05) smean[m] = RooFormulaVar(signalName + "_mean", "@0*(1+@1*@2)", RooArgList(vmean[m], xmean_jes, smean_jes)) vsigma[m] = RooRealVar(signalName + "_vsigma", "Crystal Ball sigma", m * 0.0233, m * 0.019, m * 0.025) ssigma[m] = RooFormulaVar( signalName + "_sigma", "@0*(1+@1*@2)", RooArgList(vsigma[m], xsigma_jer, ssigma_jer)) valpha1[m] = RooRealVar( signalName + "_valpha1", "Crystal Ball alpha 1", 0.2, 0.05, 0.28 ) # number of sigmas where the exp is attached to the gaussian core. >0 left, <0 right salpha1[m] = RooFormulaVar(signalName + "_alpha1", "@0", RooArgList(valpha1[m])) #vslope1[m] = RooRealVar(signalName + "_vslope1", "Crystal Ball slope 1", 10., 0.1, 20.) # slope of the power tail vslope1[m] = RooRealVar(signalName + "_vslope1", "Crystal Ball slope 1", 13., 10., 20.) # slope of the power tail sslope1[m] = RooFormulaVar(signalName + "_slope1", "@0", RooArgList(vslope1[m])) valpha2[m] = RooRealVar(signalName + "_valpha2", "Crystal Ball alpha 2", 1.) valpha2[m].setConstant(True) salpha2[m] = RooFormulaVar(signalName + "_alpha2", "@0", RooArgList(valpha2[m])) #vslope2[m] = RooRealVar(signalName + "_vslope2", "Crystal Ball slope 2", 6., 2.5, 15.) # slope of the higher power tail ## FIXME test FIXME vslope2_estimation = -5.88111436852 + m * 0.00728809389442 + m * m * ( -1.65059568762e-06) + m * m * m * (1.25128996309e-10) vslope2[m] = RooRealVar(signalName + "_vslope2", "Crystal Ball slope 2", vslope2_estimation, vslope2_estimation * 0.9, vslope2_estimation * 1.1) # slope of the higher power tail ## FIXME end FIXME sslope2[m] = RooFormulaVar( signalName + "_slope2", "@0", RooArgList(vslope2[m])) # slope of the higher power tail signal[m] = RooDoubleCrystalBall(signalName, "m_{%s'} = %d GeV" % ('X', m), X_mass, smean[m], ssigma[m], salpha1[m], sslope1[m], salpha2[m], sslope2[m]) # extend the PDF with the yield to perform an extended likelihood fit signalYield[m] = RooRealVar(signalName + "_yield", "signalYield", 50, 0., 1.e15) signalNorm[m] = RooRealVar(signalName + "_norm", "signalNorm", 1., 0., 1.e15) signalXS[m] = RooRealVar(signalName + "_xs", "signalXS", 1., 0., 1.e15) signalExt[m] = RooExtendPdf(signalName + "_ext", "extended p.d.f", signal[m], signalYield[m]) # ---------- if there is no simulated signal, skip this mass point ---------- if m in genPoints: if VERBOSE: print " - Mass point", m # define the dataset for the signal applying the SR cuts treeSign[m] = TChain("tree") if YEAR == 'run2': pd = sample[sampleName]['files'] if len(pd) > 3: print "multiple files given than years for a single masspoint:", pd sys.exit() for ss in pd: if not '2016' in ss and not '2017' in ss and not '2018' in ss: print "unknown year given in:", ss sys.exit() else: pd = [x for x in sample[sampleName]['files'] if YEAR in x] if len(pd) > 1: print "multiple files given for a single masspoint/year:", pd sys.exit() for ss in pd: if options.unskimmed: j = 0 while True: if os.path.exists(NTUPLEDIR + ss + "/" + ss + "_flatTuple_{}.root".format(j)): treeSign[m].Add(NTUPLEDIR + ss + "/" + ss + "_flatTuple_{}.root".format(j)) j += 1 else: print "found {} files for sample:".format(j), ss break else: if os.path.exists(NTUPLEDIR + ss + ".root"): treeSign[m].Add(NTUPLEDIR + ss + ".root") else: print "found no file for sample:", ss if treeSign[m].GetEntries() <= 0.: if VERBOSE: print " - 0 events available for mass", m, "skipping mass point..." signalNorm[m].setVal(-1) vmean[m].setConstant(True) vsigma[m].setConstant(True) salpha1[m].setConstant(True) sslope1[m].setConstant(True) salpha2[m].setConstant(True) sslope2[m].setConstant(True) signalNorm[m].setConstant(True) signalXS[m].setConstant(True) continue #setSignal[m] = RooDataSet("setSignal_"+signalName, "setSignal", variables, RooFit.Cut(SRcut), RooFit.WeightVar("eventWeightLumi*BTagAK4Weight_deepJet"), RooFit.Import(treeSign[m])) setSignal[m] = RooDataSet("setSignal_" + signalName, "setSignal", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeSign[m])) if VERBOSE: print " - Dataset with", setSignal[m].sumEntries( ), "events loaded" # FIT entries = setSignal[m].sumEntries() if entries < 0. or entries != entries: entries = 0 signalYield[m].setVal(entries) # Instead of eventWeightLumi #signalYield[m].setVal(entries * LUMI / (300000 if YEAR=='run2' else 100000) ) if treeSign[m].GetEntries(SRcut) > 5: if VERBOSE: print " - Running fit" frSignal[m] = signalExt[m].fitTo(setSignal[m], RooFit.Save(1), RooFit.Extended(True), RooFit.SumW2Error(True), RooFit.PrintLevel(-1)) if VERBOSE: print "********** Fit result [", m, "] **", category, "*" * 40, "\n", frSignal[ m].Print(), "\n", "*" * 80 if VERBOSE: frSignal[m].correlationMatrix().Print() drawPlot(signalMass + "_" + category, stype + category, X_mass, signal[m], setSignal[m], frSignal[m]) else: print " WARNING: signal", stype, "and mass point", m, "in category", category, "has 0 entries or does not exist" # Remove HVT cross sections #xs = getCrossSection(stype, channel, m) xs = 1. signalXS[m].setVal(xs * 1000.) signalIntegral[m] = signalExt[m].createIntegral( massArg, RooFit.NormSet(massArg), RooFit.Range("X_integration_range")) boundaryFactor = signalIntegral[m].getVal() if boundaryFactor < 0. or boundaryFactor != boundaryFactor: boundaryFactor = 0 if VERBOSE: print " - Fit normalization vs integral:", signalYield[ m].getVal(), "/", boundaryFactor, "events" signalNorm[m].setVal(boundaryFactor * signalYield[m].getVal() / signalXS[m].getVal() ) # here normalize to sigma(X) x Br = 1 [fb] vmean[m].setConstant(True) vsigma[m].setConstant(True) valpha1[m].setConstant(True) vslope1[m].setConstant(True) valpha2[m].setConstant(True) vslope2[m].setConstant(True) signalNorm[m].setConstant(True) signalXS[m].setConstant(True) #*******************************************************# # # # Signal interpolation # # # #*******************************************************# ### FIXME FIXME just for a test FIXME FIXME #print #print #print "slope2 fit results:" #print #y_vals = [] #for m in genPoints: # y_vals.append(vslope2[m].getVal()) #print "m =", genPoints #print "y =", y_vals #sys.exit() ### FIXME FIXME test end FIXME FIXME # ====== CONTROL PLOT ====== color_scheme = [ 636, 635, 634, 633, 632, 633, 636, 635, 634, 633, 632, 633, 636, 635, 634, 633, 632, 633, 636, 635, 634, 633, 632, 633, 636, 635, 634, 633, 632, 633, 636, 635, 634, 633, 632, 633, 636, 635, 634, 633, 632, 633 ] c_signal = TCanvas("c_signal", "c_signal", 800, 600) c_signal.cd() frame_signal = X_mass.frame() for j, m in enumerate(genPoints): if m in signalExt.keys(): #print "color:",(j%9)+1 #print "signalNorm[m].getVal() =", signalNorm[m].getVal() #print "RooAbsReal.NumEvent =", RooAbsReal.NumEvent signal[m].plotOn( frame_signal, RooFit.LineColor(color_scheme[j]), RooFit.Normalization(signalNorm[m].getVal(), RooAbsReal.NumEvent), RooFit.Range("X_reasonable_range")) frame_signal.GetXaxis().SetRangeUser(0, 10000) frame_signal.Draw() drawCMS(-1, "Simulation Preliminary", year=YEAR) #drawCMS(-1, "Work in Progress", year=YEAR, suppressCMS=True) #drawCMS(-1, "", year=YEAR, suppressCMS=True) drawAnalysis(category) drawRegion(category) c_signal.SaveAs(PLOTDIR + "MC_signal_" + YEAR + "/" + stype + "_" + category + "_Signal.pdf") c_signal.SaveAs(PLOTDIR + "MC_signal_" + YEAR + "/" + stype + "_" + category + "_Signal.png") #if VERBOSE: raw_input("Press Enter to continue...") # ====== CONTROL PLOT ====== # Normalization gnorm = TGraphErrors() gnorm.SetTitle(";m_{X} (GeV);integral (GeV)") gnorm.SetMarkerStyle(20) gnorm.SetMarkerColor(1) gnorm.SetMaximum(0) inorm = TGraphErrors() inorm.SetMarkerStyle(24) fnorm = TF1("fnorm", "pol9", 700, 3000) fnorm.SetLineColor(920) fnorm.SetLineStyle(7) fnorm.SetFillColor(2) fnorm.SetLineColor(cColor) # Mean gmean = TGraphErrors() gmean.SetTitle(";m_{X} (GeV);gaussian mean (GeV)") gmean.SetMarkerStyle(20) gmean.SetMarkerColor(cColor) gmean.SetLineColor(cColor) imean = TGraphErrors() imean.SetMarkerStyle(24) fmean = TF1("fmean", "pol1", 0, 10000) fmean.SetLineColor(2) fmean.SetFillColor(2) # Width gsigma = TGraphErrors() gsigma.SetTitle(";m_{X} (GeV);gaussian width (GeV)") gsigma.SetMarkerStyle(20) gsigma.SetMarkerColor(cColor) gsigma.SetLineColor(cColor) isigma = TGraphErrors() isigma.SetMarkerStyle(24) fsigma = TF1("fsigma", "pol1", 0, 10000) fsigma.SetLineColor(2) fsigma.SetFillColor(2) # Alpha1 galpha1 = TGraphErrors() galpha1.SetTitle(";m_{X} (GeV);crystal ball lower alpha") galpha1.SetMarkerStyle(20) galpha1.SetMarkerColor(cColor) galpha1.SetLineColor(cColor) ialpha1 = TGraphErrors() ialpha1.SetMarkerStyle(24) falpha1 = TF1("falpha", "pol1", 0, 10000) #pol0 falpha1.SetLineColor(2) falpha1.SetFillColor(2) # Slope1 gslope1 = TGraphErrors() gslope1.SetTitle(";m_{X} (GeV);exponential lower slope (1/Gev)") gslope1.SetMarkerStyle(20) gslope1.SetMarkerColor(cColor) gslope1.SetLineColor(cColor) islope1 = TGraphErrors() islope1.SetMarkerStyle(24) fslope1 = TF1("fslope", "pol1", 0, 10000) #pol0 fslope1.SetLineColor(2) fslope1.SetFillColor(2) # Alpha2 galpha2 = TGraphErrors() galpha2.SetTitle(";m_{X} (GeV);crystal ball upper alpha") galpha2.SetMarkerStyle(20) galpha2.SetMarkerColor(cColor) galpha2.SetLineColor(cColor) ialpha2 = TGraphErrors() ialpha2.SetMarkerStyle(24) falpha2 = TF1("falpha", "pol1", 0, 10000) #pol0 falpha2.SetLineColor(2) falpha2.SetFillColor(2) # Slope2 gslope2 = TGraphErrors() gslope2.SetTitle(";m_{X} (GeV);exponential upper slope (1/Gev)") gslope2.SetMarkerStyle(20) gslope2.SetMarkerColor(cColor) gslope2.SetLineColor(cColor) islope2 = TGraphErrors() islope2.SetMarkerStyle(24) fslope2 = TF1("fslope", "pol1", 0, 10000) #pol0 fslope2.SetLineColor(2) fslope2.SetFillColor(2) n = 0 for i, m in enumerate(genPoints): if not m in signalNorm.keys(): continue if signalNorm[m].getVal() < 1.e-6: continue if gnorm.GetMaximum() < signalNorm[m].getVal(): gnorm.SetMaximum(signalNorm[m].getVal()) gnorm.SetPoint(n, m, signalNorm[m].getVal()) #gnorm.SetPointError(i, 0, signalNorm[m].getVal()/math.sqrt(treeSign[m].GetEntriesFast())) gmean.SetPoint(n, m, vmean[m].getVal()) gmean.SetPointError(n, 0, min(vmean[m].getError(), vmean[m].getVal() * 0.02)) gsigma.SetPoint(n, m, vsigma[m].getVal()) gsigma.SetPointError( n, 0, min(vsigma[m].getError(), vsigma[m].getVal() * 0.05)) galpha1.SetPoint(n, m, valpha1[m].getVal()) galpha1.SetPointError( n, 0, min(valpha1[m].getError(), valpha1[m].getVal() * 0.10)) gslope1.SetPoint(n, m, vslope1[m].getVal()) gslope1.SetPointError( n, 0, min(vslope1[m].getError(), vslope1[m].getVal() * 0.10)) galpha2.SetPoint(n, m, salpha2[m].getVal()) galpha2.SetPointError( n, 0, min(valpha2[m].getError(), valpha2[m].getVal() * 0.10)) gslope2.SetPoint(n, m, sslope2[m].getVal()) gslope2.SetPointError( n, 0, min(vslope2[m].getError(), vslope2[m].getVal() * 0.10)) #tmpVar = w.var(var+"_"+signalString) #print m, tmpVar.getVal(), tmpVar.getError() n = n + 1 gmean.Fit(fmean, "Q0", "SAME") gsigma.Fit(fsigma, "Q0", "SAME") galpha1.Fit(falpha1, "Q0", "SAME") gslope1.Fit(fslope1, "Q0", "SAME") galpha2.Fit(falpha2, "Q0", "SAME") gslope2.Fit(fslope2, "Q0", "SAME") # gnorm.Fit(fnorm, "Q0", "", 700, 5000) #for m in [5000, 5500]: gnorm.SetPoint(gnorm.GetN(), m, gnorm.Eval(m, 0, "S")) #gnorm.Fit(fnorm, "Q", "SAME", 700, 6000) gnorm.Fit(fnorm, "Q", "SAME", 1800, 8000) ## adjusted recently for m in massPoints: if vsigma[m].getVal() < 10.: vsigma[m].setVal(10.) # Interpolation method syield = gnorm.Eval(m) spline = gnorm.Eval(m, 0, "S") sfunct = fnorm.Eval(m) #delta = min(abs(1.-spline/sfunct), abs(1.-spline/syield)) delta = abs(1. - spline / sfunct) if sfunct > 0 else 0 syield = spline if interPar: #jmean = gmean.Eval(m) #jsigma = gsigma.Eval(m) #jalpha1 = galpha1.Eval(m) #jslope1 = gslope1.Eval(m) #jalpha2 = galpha2.Eval(m) #jslope2 = gslope2.Eval(m) jmean = gmean.Eval(m, 0, "S") jsigma = gsigma.Eval(m, 0, "S") jalpha1 = galpha1.Eval(m, 0, "S") jslope1 = gslope1.Eval(m, 0, "S") jalpha2 = galpha2.Eval(m, 0, "S") jslope2 = gslope2.Eval(m, 0, "S") else: jmean = fmean.GetParameter( 0) + fmean.GetParameter(1) * m + fmean.GetParameter(2) * m * m jsigma = fsigma.GetParameter(0) + fsigma.GetParameter( 1) * m + fsigma.GetParameter(2) * m * m jalpha1 = falpha1.GetParameter(0) + falpha1.GetParameter( 1) * m + falpha1.GetParameter(2) * m * m jslope1 = fslope1.GetParameter(0) + fslope1.GetParameter( 1) * m + fslope1.GetParameter(2) * m * m jalpha2 = falpha2.GetParameter(0) + falpha2.GetParameter( 1) * m + falpha2.GetParameter(2) * m * m jslope2 = fslope2.GetParameter(0) + fslope2.GetParameter( 1) * m + fslope2.GetParameter(2) * m * m inorm.SetPoint(inorm.GetN(), m, syield) signalNorm[m].setVal(max(0., syield)) imean.SetPoint(imean.GetN(), m, jmean) if jmean > 0: vmean[m].setVal(jmean) isigma.SetPoint(isigma.GetN(), m, jsigma) if jsigma > 0: vsigma[m].setVal(jsigma) ialpha1.SetPoint(ialpha1.GetN(), m, jalpha1) if not jalpha1 == 0: valpha1[m].setVal(jalpha1) islope1.SetPoint(islope1.GetN(), m, jslope1) if jslope1 > 0: vslope1[m].setVal(jslope1) ialpha2.SetPoint(ialpha2.GetN(), m, jalpha2) if not jalpha2 == 0: valpha2[m].setVal(jalpha2) islope2.SetPoint(islope2.GetN(), m, jslope2) if jslope2 > 0: vslope2[m].setVal(jslope2) #### newly introduced, not yet sure if helpful: vmean[m].removeError() vsigma[m].removeError() valpha1[m].removeError() valpha2[m].removeError() vslope1[m].removeError() vslope2[m].removeError() #signalNorm[m].setConstant(False) ## newly put here to ensure it's freely floating in the combine fit #c1 = TCanvas("c1", "Crystal Ball", 1200, 1200) #if not isAH else 1200 #c1.Divide(2, 3) c1 = TCanvas("c1", "Crystal Ball", 1800, 800) c1.Divide(3, 2) c1.cd(1) gmean.SetMinimum(0.) gmean.Draw("APL") imean.Draw("P, SAME") drawRegion(category) drawCMS(-1, "Simulation Preliminary", year=YEAR) ## new FIXME c1.cd(2) gsigma.SetMinimum(0.) gsigma.Draw("APL") isigma.Draw("P, SAME") drawRegion(category) drawCMS(-1, "Simulation Preliminary", year=YEAR) ## new FIXME c1.cd(3) galpha1.Draw("APL") ialpha1.Draw("P, SAME") drawRegion(category) drawCMS(-1, "Simulation Preliminary", year=YEAR) ## new FIXME galpha1.GetYaxis().SetRangeUser(0., 1.1) #adjusted upper limit from 5 to 2 c1.cd(4) gslope1.Draw("APL") islope1.Draw("P, SAME") drawRegion(category) drawCMS(-1, "Simulation Preliminary", year=YEAR) ## new FIXME gslope1.GetYaxis().SetRangeUser(0., 150.) #adjusted upper limit from 125 to 60 if True: #isAH: c1.cd(5) galpha2.Draw("APL") ialpha2.Draw("P, SAME") drawRegion(category) drawCMS(-1, "Simulation Preliminary", year=YEAR) ## new FIXME galpha2.GetYaxis().SetRangeUser(0., 2.) c1.cd(6) gslope2.Draw("APL") islope2.Draw("P, SAME") drawRegion(category) drawCMS(-1, "Simulation Preliminary", year=YEAR) ## new FIXME gslope2.GetYaxis().SetRangeUser(0., 20.) c1.Print(PLOTDIR + "MC_signal_" + YEAR + "/" + stype + "_" + category + "_SignalShape.pdf") c1.Print(PLOTDIR + "MC_signal_" + YEAR + "/" + stype + "_" + category + "_SignalShape.png") c2 = TCanvas("c2", "Signal Efficiency", 800, 600) c2.cd(1) gnorm.SetMarkerColor(cColor) gnorm.SetMarkerStyle(20) gnorm.SetLineColor(cColor) gnorm.SetLineWidth(2) gnorm.Draw("APL") inorm.Draw("P, SAME") gnorm.GetXaxis().SetRangeUser(genPoints[0] - 100, genPoints[-1] + 100) gnorm.GetYaxis().SetRangeUser(0., gnorm.GetMaximum() * 1.25) drawCMS(-1, "Simulation Preliminary", year=YEAR) #drawCMS(-1, "Work in Progress", year=YEAR, suppressCMS=True) #drawCMS(-1, "", year=YEAR, suppressCMS=True) drawAnalysis(category) drawRegion(category) c2.Print(PLOTDIR + "MC_signal_" + YEAR + "/" + stype + "_" + category + "_SignalNorm.pdf") c2.Print(PLOTDIR + "MC_signal_" + YEAR + "/" + stype + "_" + category + "_SignalNorm.png") #*******************************************************# # # # Generate workspace # # # #*******************************************************# # create workspace w = RooWorkspace("Zprime_" + YEAR, "workspace") for m in massPoints: getattr(w, "import")(signal[m], RooFit.Rename(signal[m].GetName())) getattr(w, "import")(signalNorm[m], RooFit.Rename(signalNorm[m].GetName())) getattr(w, "import")(signalXS[m], RooFit.Rename(signalXS[m].GetName())) w.writeToFile(WORKDIR + "MC_signal_%s_%s.root" % (YEAR, category), True) print "Workspace", WORKDIR + "MC_signal_%s_%s.root" % ( YEAR, category), "saved successfully"
def signal(category): interPar = True n = len(genPoints) cColor = color[category] if category in color else 4 nBtag = category.count('b') isAH = False #relict from using Alberto's more complex script if not os.path.exists(PLOTDIR+"MC_signal_"+YEAR): os.makedirs(PLOTDIR+"MC_signal_"+YEAR) #*******************************************************# # # # Variables and selections # # # #*******************************************************# X_mass = RooRealVar ( "jj_mass_widejet", "m_{jj}", X_min, X_max, "GeV") j1_pt = RooRealVar( "jpt_1", "jet1 pt", 0., 13000., "GeV") jj_deltaEta = RooRealVar( "jj_deltaEta_widejet", "", 0., 5.) jbtag_WP_1 = RooRealVar("jbtag_WP_1", "", -1., 4. ) jbtag_WP_2 = RooRealVar("jbtag_WP_2", "", -1., 4. ) fatjetmass_1 = RooRealVar("fatjetmass_1", "", -1., 2500. ) fatjetmass_2 = RooRealVar("fatjetmass_2", "", -1., 2500. ) jid_1 = RooRealVar( "jid_1", "j1 ID", -1., 8.) jid_2 = RooRealVar( "jid_2", "j2 ID", -1., 8.) jnmuons_1 = RooRealVar( "jnmuons_1", "j1 n_{#mu}", -1., 8.) jnmuons_2 = RooRealVar( "jnmuons_2", "j2 n_{#mu}", -1., 8.) jmuonpt_1 = RooRealVar( "jmuonpt_1", "j1 muon pt", 0., 13000.) jmuonpt_2 = RooRealVar( "jmuonpt_2", "j2 muon pt", 0., 13000.) nmuons = RooRealVar( "nmuons", "n_{#mu}", -1., 10. ) nelectrons = RooRealVar("nelectrons", "n_{e}", -1., 10. ) HLT_AK8PFJet500 = RooRealVar("HLT_AK8PFJet500" , "", -1., 1. ) HLT_PFJet500 = RooRealVar("HLT_PFJet500" , "" , -1., 1. ) HLT_CaloJet500_NoJetID = RooRealVar("HLT_CaloJet500_NoJetID" , "" , -1., 1. ) HLT_PFHT900 = RooRealVar("HLT_PFHT900" , "" , -1., 1. ) HLT_AK8PFJet550 = RooRealVar("HLT_AK8PFJet550" , "", -1., 1. ) HLT_PFJet550 = RooRealVar("HLT_PFJet550" , "" , -1., 1. ) HLT_CaloJet550_NoJetID = RooRealVar("HLT_CaloJet550_NoJetID" , "" , -1., 1. ) HLT_PFHT1050 = RooRealVar("HLT_PFHT1050" , "" , -1., 1. ) HLT_DoublePFJets100_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets100_CaloBTagDeepCSV_p71" , "", -1., 1. ) HLT_DoublePFJets116MaxDeta1p6_DoubleCaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets116MaxDeta1p6_DoubleCaloBTagDeepCSV_p71", "", -1., 1. ) HLT_DoublePFJets128MaxDeta1p6_DoubleCaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets128MaxDeta1p6_DoubleCaloBTagDeepCSV_p71", "", -1., 1. ) HLT_DoublePFJets200_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets200_CaloBTagDeepCSV_p71" , "", -1., 1. ) HLT_DoublePFJets350_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets350_CaloBTagDeepCSV_p71" , "", -1., 1. ) HLT_DoublePFJets40_CaloBTagDeepCSV_p71 =RooRealVar("HLT_DoublePFJets40_CaloBTagDeepCSV_p71" , "", -1., 1. ) weight = RooRealVar( "eventWeightLumi", "", -1.e9, 1.e9 ) # 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) variables.add(RooArgSet(j1_pt, jj_deltaEta, jbtag_WP_1, jbtag_WP_2, fatjetmass_1, fatjetmass_2, jnmuons_1, jnmuons_2, weight)) variables.add(RooArgSet(nmuons, nelectrons, jid_1, jid_2, jmuonpt_1, jmuonpt_2)) variables.add(RooArgSet(HLT_AK8PFJet500, HLT_PFJet500, HLT_CaloJet500_NoJetID, HLT_PFHT900, HLT_AK8PFJet550, HLT_PFJet550, HLT_CaloJet550_NoJetID, HLT_PFHT1050)) variables.add(RooArgSet(HLT_DoublePFJets100_CaloBTagDeepCSV_p71, HLT_DoublePFJets116MaxDeta1p6_DoubleCaloBTagDeepCSV_p71, HLT_DoublePFJets128MaxDeta1p6_DoubleCaloBTagDeepCSV_p71, HLT_DoublePFJets200_CaloBTagDeepCSV_p71, HLT_DoublePFJets350_CaloBTagDeepCSV_p71, HLT_DoublePFJets40_CaloBTagDeepCSV_p71)) X_mass.setRange("X_reasonable_range", X_mass.getMin(), X_mass.getMax()) X_mass.setRange("X_integration_range", X_mass.getMin(), X_mass.getMax()) if VARBINS: binsXmass = RooBinning(len(abins)-1, abins) X_mass.setBinning(binsXmass) plot_binning = RooBinning(int((X_mass.getMax()-X_mass.getMin())/100), X_mass.getMin(), X_mass.getMax()) else: X_mass.setBins(int((X_mass.getMax()-X_mass.getMin())/10)) binsXmass = RooBinning(int((X_mass.getMax()-X_mass.getMin())/100), X_mass.getMin(), X_mass.getMax()) plot_binning = binsXmass X_mass.setBinning(plot_binning, "PLOT") #X_mass.setBins(int((X_mass.getMax() - X_mass.getMin())/10)) #binsXmass = RooBinning(int((X_mass.getMax() - X_mass.getMin())/100), X_mass.getMin(), X_mass.getMax()) #X_mass.setBinning(binsXmass, "PLOT") massArg = RooArgSet(X_mass) # Cuts if BTAGGING=='semimedium': SRcut = aliasSM[category] #SRcut = aliasSM[category+"_vetoAK8"] else: SRcut = alias[category].format(WP=working_points[BTAGGING]) #SRcut = alias[category+"_vetoAK8"].format(WP=working_points[BTAGGING]) if ADDSELECTION: SRcut += SELECTIONS[options.selection] print " Cut:\t", SRcut #*******************************************************# # # # Signal fits # # # #*******************************************************# treeSign = {} setSignal = {} vmean = {} vsigma = {} valpha1 = {} vslope1 = {} valpha2 = {} vslope2 = {} smean = {} ssigma = {} salpha1 = {} sslope1 = {} salpha2 = {} sslope2 = {} sbrwig = {} signal = {} signalExt = {} signalYield = {} signalIntegral = {} signalNorm = {} signalXS = {} frSignal = {} frSignal1 = {} frSignal2 = {} frSignal3 = {} # Signal shape uncertainties (common amongst all mass points) xmean_jes = RooRealVar("CMS"+YEAR+"_sig_"+category+"_p1_scale_jes", "Variation of the resonance position with the jet energy scale", 0.02, -1., 1.) #0.001 smean_jes = RooRealVar("CMS"+YEAR+"_sig_"+category+"_p1_jes", "Change of the resonance position with the jet energy scale", 0., -10, 10) xsigma_jer = RooRealVar("CMS"+YEAR+"_sig_"+category+"_p2_scale_jer", "Variation of the resonance width with the jet energy resolution", 0.10, -1., 1.) ssigma_jer = RooRealVar("CMS"+YEAR+"_sig_"+category+"_p2_jer", "Change of the resonance width with the jet energy resolution", 0., -10, 10) xmean_jes.setConstant(True) smean_jes.setConstant(True) xsigma_jer.setConstant(True) ssigma_jer.setConstant(True) for m in massPoints: signalMass = "%s_M%d" % (stype, m) signalName = "ZpBB_{}_{}_M{}".format(YEAR, category, m) sampleName = "bstar_M{}".format(m) signalColor = sample[sampleName]['linecolor'] if signalName in sample else 1 # define the signal PDF vmean[m] = RooRealVar(signalName + "_vmean", "Crystal Ball mean", m, m*0.96, m*1.05) smean[m] = RooFormulaVar(signalName + "_mean", "@0*(1+@1*@2)", RooArgList(vmean[m], xmean_jes, smean_jes)) vsigma[m] = RooRealVar(signalName + "_vsigma", "Crystal Ball sigma", m*0.0233, m*0.019, m*0.025) ssigma[m] = RooFormulaVar(signalName + "_sigma", "@0*(1+@1*@2)", RooArgList(vsigma[m], xsigma_jer, ssigma_jer)) valpha1[m] = RooRealVar(signalName + "_valpha1", "Crystal Ball alpha 1", 0.2, 0.05, 0.28) # number of sigmas where the exp is attached to the gaussian core. >0 left, <0 right salpha1[m] = RooFormulaVar(signalName + "_alpha1", "@0", RooArgList(valpha1[m])) #vslope1[m] = RooRealVar(signalName + "_vslope1", "Crystal Ball slope 1", 10., 0.1, 20.) # slope of the power tail vslope1[m] = RooRealVar(signalName + "_vslope1", "Crystal Ball slope 1", 13., 10., 20.) # slope of the power tail sslope1[m] = RooFormulaVar(signalName + "_slope1", "@0", RooArgList(vslope1[m])) valpha2[m] = RooRealVar(signalName + "_valpha2", "Crystal Ball alpha 2", 1.) valpha2[m].setConstant(True) salpha2[m] = RooFormulaVar(signalName + "_alpha2", "@0", RooArgList(valpha2[m])) #vslope2[m] = RooRealVar(signalName + "_vslope2", "Crystal Ball slope 2", 6., 2.5, 15.) # slope of the higher power tail ## FIXME test FIXME vslope2_estimation = -5.88111436852 + m*0.00728809389442 + m*m*(-1.65059568762e-06) + m*m*m*(1.25128996309e-10) vslope2[m] = RooRealVar(signalName + "_vslope2", "Crystal Ball slope 2", vslope2_estimation, vslope2_estimation*0.9, vslope2_estimation*1.1) # slope of the higher power tail ## FIXME end FIXME sslope2[m] = RooFormulaVar(signalName + "_slope2", "@0", RooArgList(vslope2[m])) # slope of the higher power tail signal[m] = RooDoubleCrystalBall(signalName, "m_{%s'} = %d GeV" % ('X', m), X_mass, smean[m], ssigma[m], salpha1[m], sslope1[m], salpha2[m], sslope2[m]) # extend the PDF with the yield to perform an extended likelihood fit signalYield[m] = RooRealVar(signalName+"_yield", "signalYield", 50, 0., 1.e15) signalNorm[m] = RooRealVar(signalName+"_norm", "signalNorm", 1., 0., 1.e15) signalXS[m] = RooRealVar(signalName+"_xs", "signalXS", 1., 0., 1.e15) signalExt[m] = RooExtendPdf(signalName+"_ext", "extended p.d.f", signal[m], signalYield[m]) # ---------- if there is no simulated signal, skip this mass point ---------- if m in genPoints: if VERBOSE: print " - Mass point", m # define the dataset for the signal applying the SR cuts treeSign[m] = TChain("tree") if YEAR=='run2': pd = sample[sampleName]['files'] if len(pd)>3: print "multiple files given than years for a single masspoint:",pd sys.exit() for ss in pd: if not '2016' in ss and not '2017' in ss and not '2018' in ss: print "unknown year given in:", ss sys.exit() else: pd = [x for x in sample[sampleName]['files'] if YEAR in x] if len(pd)>1: print "multiple files given for a single masspoint/year:",pd sys.exit() for ss in pd: if options.unskimmed: j=0 while True: if os.path.exists(NTUPLEDIR + ss + "/" + ss + "_flatTuple_{}.root".format(j)): treeSign[m].Add(NTUPLEDIR + ss + "/" + ss + "_flatTuple_{}.root".format(j)) j += 1 else: print "found {} files for sample:".format(j), ss break else: if os.path.exists(NTUPLEDIR + ss + ".root"): treeSign[m].Add(NTUPLEDIR + ss + ".root") else: print "found no file for sample:", ss if treeSign[m].GetEntries() <= 0.: if VERBOSE: print " - 0 events available for mass", m, "skipping mass point..." signalNorm[m].setVal(-1) vmean[m].setConstant(True) vsigma[m].setConstant(True) salpha1[m].setConstant(True) sslope1[m].setConstant(True) salpha2[m].setConstant(True) sslope2[m].setConstant(True) signalNorm[m].setConstant(True) signalXS[m].setConstant(True) continue #setSignal[m] = RooDataSet("setSignal_"+signalName, "setSignal", variables, RooFit.Cut(SRcut), RooFit.WeightVar("eventWeightLumi*BTagAK4Weight_deepJet"), RooFit.Import(treeSign[m])) setSignal[m] = RooDataSet("setSignal_"+signalName, "setSignal", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeSign[m])) if VERBOSE: print " - Dataset with", setSignal[m].sumEntries(), "events loaded" # FIT entries = setSignal[m].sumEntries() if entries < 0. or entries != entries: entries = 0 signalYield[m].setVal(entries) # Instead of eventWeightLumi #signalYield[m].setVal(entries * LUMI / (300000 if YEAR=='run2' else 100000) ) if treeSign[m].GetEntries(SRcut) > 5: if VERBOSE: print " - Running fit" frSignal[m] = signalExt[m].fitTo(setSignal[m], RooFit.Save(1), RooFit.Extended(True), RooFit.SumW2Error(True), RooFit.PrintLevel(-1)) if VERBOSE: print "********** Fit result [", m, "] **", category, "*"*40, "\n", frSignal[m].Print(), "\n", "*"*80 if VERBOSE: frSignal[m].correlationMatrix().Print() drawPlot(signalMass+"_"+category, stype+category, X_mass, signal[m], setSignal[m], frSignal[m]) else: print " WARNING: signal", stype, "and mass point", m, "in category", category, "has 0 entries or does not exist" # Remove HVT cross sections #xs = getCrossSection(stype, channel, m) xs = 1. signalXS[m].setVal(xs * 1000.) signalIntegral[m] = signalExt[m].createIntegral(massArg, RooFit.NormSet(massArg), RooFit.Range("X_integration_range")) boundaryFactor = signalIntegral[m].getVal() if boundaryFactor < 0. or boundaryFactor != boundaryFactor: boundaryFactor = 0 if VERBOSE: print " - Fit normalization vs integral:", signalYield[m].getVal(), "/", boundaryFactor, "events" signalNorm[m].setVal( boundaryFactor * signalYield[m].getVal() / signalXS[m].getVal()) # here normalize to sigma(X) x Br = 1 [fb]
def dijet(category): channel = 'bb' stype = channel isSB = True # relict from using Alberto's more complex script isData = not ISMC nTupleDir = NTUPLEDIR samples = data if isData else back pd = [] for sample_name in samples: if YEAR == 'run2': pd += sample[sample_name]['files'] else: pd += [x for x in sample[sample_name]['files'] if YEAR in x] print "datasets:", pd if not os.path.exists(PLOTDIR): os.makedirs(PLOTDIR) if BIAS: print "Running in BIAS mode" order = 0 RSS = {} X_mass = RooRealVar("jj_mass_widejet", "m_{jj}", X_min, X_max, "GeV") weight = RooRealVar("MANtag_weight", "", -1.e9, 1.e9) variables = RooArgSet(X_mass) variables.add(RooArgSet(weight)) if VARBINS: binsXmass = RooBinning(len(abins) - 1, abins) X_mass.setBinning(RooBinning(len(abins_narrow) - 1, abins_narrow)) plot_binning = RooBinning( int((X_mass.getMax() - X_mass.getMin()) / 100), X_mass.getMin(), X_mass.getMax()) else: X_mass.setBins(int((X_mass.getMax() - X_mass.getMin()) / 10)) binsXmass = RooBinning(int((X_mass.getMax() - X_mass.getMin()) / 100), X_mass.getMin(), X_mass.getMax()) plot_binning = binsXmass baseCut = "" print stype, "|", baseCut print " - Reading from Tree" treeBkg = TChain("tree") for ss in pd: if os.path.exists(nTupleDir + ss + "_" + BTAGGING + ".root"): treeBkg.Add(nTupleDir + ss + "_" + BTAGGING + ".root") else: print "found no file for sample:", ss setData = RooDataSet("setData", "Data (QCD+TTbar MC)", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeBkg)) nevents = setData.sumEntries() dataMin, dataMax = array('d', [0.]), array('d', [0.]) setData.getRange(X_mass, dataMin, dataMax) xmin, xmax = dataMin[0], dataMax[0] lastBin = X_mass.getMax() if VARBINS: for b in narrow_bins: if b > xmax: lastBin = b break print "Imported", ( "data" if isData else "MC" ), "RooDataSet with", nevents, "events between [%.1f, %.1f]" % (xmin, xmax) #xmax = xmax+binsXmass.averageBinWidth() # start form next bin # 1 parameter print "fitting 1 parameter model" p1_1 = RooRealVar("CMS" + YEAR + "_" + category + "_p1_1", "p1", 7.0, 0., 2000.) modelBkg1 = RooGenericPdf("Bkg1", "Bkg. fit (2 par.)", "1./pow(@0/13000, @1)", RooArgList(X_mass, p1_1)) normzBkg1 = RooRealVar( modelBkg1.GetName() + "_norm", "Number of background events", nevents, 0., 5. * nevents) #range dependent of actual number of events! modelExt1 = RooExtendPdf(modelBkg1.GetName() + "_ext", modelBkg1.GetTitle(), modelBkg1, normzBkg1) fitRes1 = modelExt1.fitTo(setData, RooFit.Extended(True), RooFit.Save(1), RooFit.SumW2Error(not isData), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.PrintLevel(1 if VERBOSE else -1)) fitRes1.Print() RSS[1] = drawFit("Bkg1", category, X_mass, modelBkg1, setData, binsXmass, [fitRes1], normzBkg1.getVal()) # 2 parameters print "fitting 2 parameter model" p2_1 = RooRealVar("CMS" + YEAR + "_" + category + "_p2_1", "p1", 0., -100., 1000.) p2_2 = RooRealVar("CMS" + YEAR + "_" + category + "_p2_2", "p2", p1_1.getVal(), -100., 600.) modelBkg2 = RooGenericPdf("Bkg2", "Bkg. fit (3 par.)", "pow(1-@0/13000, @1) / pow(@0/13000, @2)", RooArgList(X_mass, p2_1, p2_2)) normzBkg2 = RooRealVar(modelBkg2.GetName() + "_norm", "Number of background events", nevents, 0., 5. * nevents) modelExt2 = RooExtendPdf(modelBkg2.GetName() + "_ext", modelBkg2.GetTitle(), modelBkg2, normzBkg2) fitRes2 = modelExt2.fitTo(setData, RooFit.Extended(True), RooFit.Save(1), RooFit.SumW2Error(not isData), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.PrintLevel(1 if VERBOSE else -1)) fitRes2.Print() RSS[2] = drawFit("Bkg2", category, X_mass, modelBkg2, setData, binsXmass, [fitRes2], normzBkg2.getVal()) # 3 parameters print "fitting 3 parameter model" p3_1 = RooRealVar("CMS" + YEAR + "_" + category + "_p3_1", "p1", p2_1.getVal(), -2000., 2000.) p3_2 = RooRealVar("CMS" + YEAR + "_" + category + "_p3_2", "p2", p2_2.getVal(), -400., 2000.) p3_3 = RooRealVar("CMS" + YEAR + "_" + category + "_p3_3", "p3", -2.5, -500., 500.) modelBkg3 = RooGenericPdf( "Bkg3", "Bkg. fit (4 par.)", "pow(1-@0/13000, @1) / pow(@0/13000, @2+@3*log(@0/13000))", RooArgList(X_mass, p3_1, p3_2, p3_3)) normzBkg3 = RooRealVar(modelBkg3.GetName() + "_norm", "Number of background events", nevents, 0., 5. * nevents) modelExt3 = RooExtendPdf(modelBkg3.GetName() + "_ext", modelBkg3.GetTitle(), modelBkg3, normzBkg3) fitRes3 = modelExt3.fitTo(setData, RooFit.Extended(True), RooFit.Save(1), RooFit.SumW2Error(not isData), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.PrintLevel(1 if VERBOSE else -1)) fitRes3.Print() RSS[3] = drawFit("Bkg3", category, X_mass, modelBkg3, setData, binsXmass, [fitRes3], normzBkg3.getVal()) # 4 parameters print "fitting 4 parameter model" p4_1 = RooRealVar("CMS" + YEAR + "_" + category + "_p4_1", "p1", p3_1.getVal(), -2000., 2000.) p4_2 = RooRealVar("CMS" + YEAR + "_" + category + "_p4_2", "p2", p3_2.getVal(), -2000., 2000.) p4_3 = RooRealVar("CMS" + YEAR + "_" + category + "_p4_3", "p3", p3_3.getVal(), -50., 50.) p4_4 = RooRealVar("CMS" + YEAR + "_" + category + "_p4_4", "p4", 0.1, -50., 50.) modelBkg4 = RooGenericPdf( "Bkg4", "Bkg. fit (5 par.)", "pow(1 - @0/13000, @1) / pow(@0/13000, @2+@3*log(@0/13000)+@4*pow(log(@0/13000), 2))", RooArgList(X_mass, p4_1, p4_2, p4_3, p4_4)) normzBkg4 = RooRealVar(modelBkg4.GetName() + "_norm", "Number of background events", nevents, 0., 5. * nevents) modelExt4 = RooExtendPdf(modelBkg4.GetName() + "_ext", modelBkg4.GetTitle(), modelBkg4, normzBkg4) fitRes4 = modelExt4.fitTo(setData, RooFit.Extended(True), RooFit.Save(1), RooFit.SumW2Error(not isData), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.PrintLevel(1 if VERBOSE else -1)) fitRes4.Print() RSS[4] = drawFit("Bkg4", category, X_mass, modelBkg4, setData, binsXmass, [fitRes4], normzBkg4.getVal()) # Normalization parameters are should be set constant, but shape ones should not # if BIAS: # p1_1.setConstant(True) # p2_1.setConstant(True) # p2_2.setConstant(True) # p3_1.setConstant(True) # p3_2.setConstant(True) # p3_3.setConstant(True) # p4_1.setConstant(True) # p4_2.setConstant(True) # p4_3.setConstant(True) # p4_4.setConstant(True) normzBkg1.setConstant(True) normzBkg2.setConstant(True) normzBkg3.setConstant(True) normzBkg4.setConstant(True) #*******************************************************# # # # Fisher # # # #*******************************************************# # Fisher test with open(PLOTDIR + "/Fisher_" + category + ".tex", 'w') as fout: fout.write(r"\begin{tabular}{c|c|c|c|c}") fout.write("\n") fout.write(r"function & $\chi^2$ & RSS & ndof & F-test \\") fout.write("\n") fout.write("\hline") fout.write("\n") CL_high = False for o1 in range(1, 5): o2 = min(o1 + 1, 5) fout.write("%d par & %.2f & %.2f & %d & " % (o1 + 1, RSS[o1]["chi2"], RSS[o1]["rss"], RSS[o1]["nbins"] - RSS[o1]["npar"])) if o2 > len(RSS): fout.write(r"\\") fout.write("\n") continue #order==0 and CL = fisherTest(RSS[o1]['rss'], RSS[o2]['rss'], o1 + 1., o2 + 1., RSS[o1]["nbins"]) fout.write("CL=%.3f " % (CL)) if CL > 0.10: # The function with less parameters is enough if not CL_high: order = o1 #fout.write( "%d par are sufficient " % (o1+1)) CL_high = True else: #fout.write( "%d par are needed " % (o2+1)) if not CL_high: order = o2 fout.write(r"\\") fout.write("\n") fout.write("\hline") fout.write("\n") fout.write(r"\end{tabular}") print "saved F-test table as", PLOTDIR + "/Fisher_" + category + ".tex" #print "-"*25 #print "function & $\\chi^2$ & RSS & ndof & F-test & result \\\\" #print "\\multicolumn{6}{c}{", "Zprime_to_bb", "} \\\\" #print "\\hline" #CL_high = False #for o1 in range(1, 5): # o2 = min(o1 + 1, 5) # print "%d par & %.2f & %.2f & %d & " % (o1+1, RSS[o1]["chi2"], RSS[o1]["rss"], RSS[o1]["nbins"]-RSS[o1]["npar"]), # if o2 > len(RSS): # print "\\\\" # continue #order==0 and # CL = fisherTest(RSS[o1]['rss'], RSS[o2]['rss'], o1+1., o2+1., RSS[o1]["nbins"]) # print "%d par vs %d par CL=%f & " % (o1+1, o2+1, CL), # if CL > 0.10: # The function with less parameters is enough # if not CL_high: # order = o1 # print "%d par are sufficient" % (o1+1), # CL_high=True # else: # print "%d par are needed" % (o2+1), # if not CL_high: # order = o2 # print "\\\\" #print "\\hline" #print "-"*25 #print "@ Order is", order, "("+category+")" #order = min(3, order) #order = 2 if order == 1: modelBkg = modelBkg1 #.Clone("Bkg") modelAlt = modelBkg2 #.Clone("BkgAlt") normzBkg = normzBkg1 #.Clone("Bkg_norm") fitRes = fitRes1 elif order == 2: modelBkg = modelBkg2 #.Clone("Bkg") modelAlt = modelBkg3 #.Clone("BkgAlt") normzBkg = normzBkg2 #.Clone("Bkg_norm") fitRes = fitRes2 elif order == 3: modelBkg = modelBkg3 #.Clone("Bkg") modelAlt = modelBkg4 #.Clone("BkgAlt") normzBkg = normzBkg3 #.Clone("Bkg_norm") fitRes = fitRes3 elif order == 4: modelBkg = modelBkg4 #.Clone("Bkg") modelAlt = modelBkg3 #.Clone("BkgAlt") normzBkg = normzBkg4 #.Clone("Bkg_norm") fitRes = fitRes4 else: print "Functions with", order + 1, "or more parameters are needed to fit the background" exit() modelBkg.SetName("Bkg_" + YEAR + "_" + category) modelAlt.SetName("Alt_" + YEAR + "_" + category) normzBkg.SetName("Bkg_" + YEAR + "_" + category + "_norm") print "-" * 25 # Generate pseudo data setToys = RooDataSet() setToys.SetName("data_toys") setToys.SetTitle("Data (toys)") if not isData: print " - Generating", nevents, "events for toy data" setToys = modelBkg.generate(RooArgSet(X_mass), nevents) #setToys = modelAlt.generate(RooArgSet(X_mass), nevents) print "toy data generated" if VERBOSE: raw_input("Press Enter to continue...") #*******************************************************# # # # Plot # # # #*******************************************************# print "starting to plot" c = TCanvas("c_" + category, category, 800, 800) c.Divide(1, 2) setTopPad(c.GetPad(1), RATIO) setBotPad(c.GetPad(2), RATIO) c.cd(1) frame = X_mass.frame() setPadStyle(frame, 1.25, True) if VARBINS: frame.GetXaxis().SetRangeUser(X_mass.getMin(), lastBin) signal = getSignal( category, stype, 2000) #replacing Alberto's getSignal by own dummy function graphData = setData.plotOn(frame, RooFit.Binning(plot_binning), RooFit.Scaling(False), RooFit.Invisible()) modelBkg.plotOn(frame, RooFit.VisualizeError(fitRes, 1, False), RooFit.LineColor(602), RooFit.FillColor(590), RooFit.FillStyle(1001), RooFit.DrawOption("FL"), RooFit.Name("1sigma")) modelBkg.plotOn(frame, RooFit.LineColor(602), RooFit.FillColor(590), RooFit.FillStyle(1001), RooFit.DrawOption("L"), RooFit.Name(modelBkg.GetName())) modelAlt.plotOn(frame, RooFit.LineStyle(7), RooFit.LineColor(613), RooFit.FillColor(609), RooFit.FillStyle(1001), RooFit.DrawOption("L"), RooFit.Name(modelAlt.GetName())) if not isSB and signal[0] is not None: # FIXME remove /(2./3.) signal[0].plotOn( frame, RooFit.Normalization(signal[1] * signal[2], RooAbsReal.NumEvent), RooFit.LineStyle(3), RooFit.LineWidth(6), RooFit.LineColor(629), RooFit.DrawOption("L"), RooFit.Name("Signal")) graphData = setData.plotOn( frame, RooFit.Binning(plot_binning), RooFit.Scaling(False), RooFit.XErrorSize(0 if not VARBINS else 1), RooFit.DataError(RooAbsData.Poisson if isData else RooAbsData.SumW2), RooFit.DrawOption("PE0"), RooFit.Name(setData.GetName())) fixData(graphData.getHist(), True, True, not isData) pulls = frame.pullHist(setData.GetName(), modelBkg.GetName(), True) chi = frame.chiSquare(setData.GetName(), modelBkg.GetName(), True) #setToys.plotOn(frame, RooFit.DataError(RooAbsData.Poisson), RooFit.DrawOption("PE0"), RooFit.MarkerColor(2)) frame.GetYaxis().SetTitle("Events / ( 100 GeV )") frame.GetYaxis().SetTitleOffset(1.05) frame.Draw() #print "frame drawn" # Get Chi2 # chi2[1] = frame.chiSquare(modelBkg1.GetName(), setData.GetName()) # chi2[2] = frame.chiSquare(modelBkg2.GetName(), setData.GetName()) # chi2[3] = frame.chiSquare(modelBkg3.GetName(), setData.GetName()) # chi2[4] = frame.chiSquare(modelBkg4.GetName(), setData.GetName()) frame.SetMaximum(frame.GetMaximum() * 10) frame.SetMinimum(max(frame.GetMinimum(), 1.e-1)) c.GetPad(1).SetLogy() drawAnalysis(category) drawRegion(category, True) #drawCMS(LUMI, "Simulation Preliminary") drawCMS(LUMI, "Work in Progress", suppressCMS=True) leg = TLegend(0.575, 0.6, 0.95, 0.9) leg.SetBorderSize(0) leg.SetFillStyle(0) #1001 leg.SetFillColor(0) leg.AddEntry(setData.GetName(), setData.GetTitle() + " (%d events)" % nevents, "PEL") leg.AddEntry(modelBkg.GetName(), modelBkg.GetTitle(), "FL") #.SetTextColor(629) leg.AddEntry(modelAlt.GetName(), modelAlt.GetTitle(), "L") if not isSB and signal[0] is not None: leg.AddEntry("Signal", signal[0].GetTitle(), "L") leg.SetY1(0.9 - leg.GetNRows() * 0.05) leg.Draw() latex = TLatex() latex.SetNDC() latex.SetTextSize(0.04) latex.SetTextFont(42) if not isSB: latex.DrawLatex(leg.GetX1() * 1.16, leg.GetY1() - 0.04, "HVT model B (g_{V}=3)") # latex.DrawLatex(0.67, leg.GetY1()-0.045, "#sigma_{X} = 1.0 pb") c.cd(2) frame_res = X_mass.frame() setPadStyle(frame_res, 1.25) frame_res.addPlotable(pulls, "P") setBotStyle(frame_res, RATIO, False) if VARBINS: frame_res.GetXaxis().SetRangeUser(X_mass.getMin(), lastBin) frame_res.GetYaxis().SetRangeUser(-5, 5) frame_res.GetYaxis().SetTitle("pulls(#sigma)") frame_res.GetYaxis().SetTitleOffset(0.3) frame_res.Draw() fixData(pulls, False, True, False) drawChi2(RSS[order]["chi2"], RSS[order]["nbins"] - (order + 1), True) line = drawLine(X_mass.getMin(), 0, lastBin, 0) if VARBINS: c.SaveAs(PLOTDIR + "/BkgSR_" + category + ".pdf") c.SaveAs(PLOTDIR + "/BkgSR_" + category + ".png") else: c.SaveAs(PLOTDIR + "/BkgSR_" + category + ".pdf") c.SaveAs(PLOTDIR + "/BkgSR_" + category + ".png") #*******************************************************# # # # Generate workspace # # # #*******************************************************# if BIAS: gSystem.Load("libHiggsAnalysisCombinedLimit.so") from ROOT import RooMultiPdf cat = RooCategory("pdf_index", "Index of Pdf which is active") pdfs = RooArgList(modelBkg, modelAlt) roomultipdf = RooMultiPdf("roomultipdf", "All Pdfs", cat, pdfs) normulti = RooRealVar("roomultipdf_norm", "Number of background events", nevents, 0., 1.e6) normzBkg.setConstant( False ) ## newly put here to ensure it's freely floating in the combine fit # create workspace w = RooWorkspace("Zprime_" + YEAR, "workspace") # Dataset if isData: getattr(w, "import")(setData, RooFit.Rename("data_obs")) else: getattr(w, "import")(setToys, RooFit.Rename("data_obs")) #getattr(w, "import")(setData, RooFit.Rename("data_obs")) if BIAS: getattr(w, "import")(cat, RooFit.Rename(cat.GetName())) getattr(w, "import")(normulti, RooFit.Rename(normulti.GetName())) getattr(w, "import")(roomultipdf, RooFit.Rename(roomultipdf.GetName())) getattr(w, "import")(modelBkg, RooFit.Rename(modelBkg.GetName())) getattr(w, "import")(modelAlt, RooFit.Rename(modelAlt.GetName())) getattr(w, "import")(normzBkg, RooFit.Rename(normzBkg.GetName())) w.writeToFile(WORKDIR + "%s_%s.root" % (DATA_TYPE + "_" + YEAR, category), True) print "Workspace", WORKDIR + "%s_%s.root" % ( DATA_TYPE + "_" + YEAR, category), "saved successfully" if VERBOSE: raw_input("Press Enter to continue...")
one = const(1.) zero = const(0.) tau = Inverse('tau', 'tau', gamma) # tauk = Inverse('tauk', 'tauk', kgamma) ## acceptance spline_knots = [0.5, 1.0, 1.5, 2.0, 3.0, 12.0] spline_coeffs = [ 0.03902e-01, 7.32741e-01, 9.98736e-01, 1.16514e+00, 1.25167e+00, 1.28624e+00 ] assert (len(spline_knots) == len(spline_coeffs)) # knot binning mode = "Bs2DsPi" knotbinning = RooBinning(time.getMin(), time.getMax(), '{}_knotbinning'.format(mode)) for v in spline_knots: knotbinning.addBoundary(v) knotbinning.removeBoundary(time.getMin()) knotbinning.removeBoundary(time.getMax()) oldbinning, lo, hi = time.getBinning(), time.getMin(), time.getMax() time.setBinning(knotbinning, '{}_knotbinning'.format(mode)) time.setBinning(oldbinning) time.setRange(lo, hi) del knotbinning, oldbinning, lo, hi # knot coefficients coefflist = RooArgList() for i, v in enumerate(spline_coeffs): coefflist.add(const(v)) i = len(spline_coeffs)
def rooFit108(): print ">>> setup model - a B decay with mixing..." dt = RooRealVar("dt","dt",-20,20) dm = RooRealVar("dm","dm",0.472) tau = RooRealVar("tau","tau",1.547) w = RooRealVar("w","mistag rate",0.1) dw = RooRealVar("dw","delta mistag rate",0.) # Build categories - possible values states # https://root.cern/doc/v610/classRooCategory.html mixState = RooCategory("mixState","B0/B0bar mixing state") mixState.defineType("mixed",-1) mixState.defineType("unmixed",1) tagFlav = RooCategory("tagFlav","Flavour of the tagged B0") tagFlav.defineType("B0",1) tagFlav.defineType("B0bar",-1) # Build a gaussian resolution model dterr = RooRealVar("dterr","dterr",0.1,1.0) bias1 = RooRealVar("bias1","bias1",0) sigma1 = RooRealVar("sigma1","sigma1",0.1) gm1 = RooGaussModel("gm1","gauss model 1",dt,bias1,sigma1) # Construct Bdecay (x) gauss # https://root.cern/doc/v610/classRooBMixDecay.html bmix = RooBMixDecay("bmix","decay",dt,mixState,tagFlav,tau,dm,w,dw,gm1,RooBMixDecay.DoubleSided) print ">>> sample data from data..." data = bmix.generate(RooArgSet(dt,mixState,tagFlav),2000) # RooDataSet print ">>> show dt distribution with custom binning..." # Make plot of dt distribution of data in range (-15,15) with fine binning for dt>0 # and coarse binning for dt<0 tbins = RooBinning(-15,15) # Create binning object with range (-15,15) tbins.addUniform(60,-15,0) # Add 60 bins with uniform spacing in range (-15,0) tbins.addUniform(15,0,15) # Add 15 bins with uniform spacing in range (0,15) dtframe = dt.frame(Range(-15,15),Title("dt distribution with custom binning")) # RooPlot data.plotOn(dtframe,Binning(tbins)) bmix.plotOn(dtframe) # NB: Note that bin density for each bin is adjusted to that of default frame # binning as shown in Y axis label (100 bins --> Events/0.4*Xaxis-dim) so that # all bins represent a consistent density distribution print ">>> plot mixstate asymmetry with custom binning..." # Make plot of dt distribution of data asymmetry in 'mixState' with variable binning abins = RooBinning(-10,10) # Create binning object with range (-10,10) abins.addBoundary(0) # Add boundaries at 0 abins.addBoundaryPair(1) # Add boundaries at (-1,1) abins.addBoundaryPair(2) # Add boundaries at (-2,2) abins.addBoundaryPair(3) # Add boundaries at (-3,3) abins.addBoundaryPair(4) # Add boundaries at (-4,4) abins.addBoundaryPair(6) # Add boundaries at (-6,6) aframe = dt.frame(Range(-10,10),Title("MixState asymmetry distribution with custom binning")) # RooPlot # Plot mixState asymmetry of data with specified customg binning data.plotOn(aframe,Asymmetry(mixState),Binning(abins)) # Plot corresponding property of pdf bmix.plotOn(aframe,Asymmetry(mixState)) # Adjust vertical range of plot to sensible values for an asymmetry aframe.SetMinimum(-1.1) aframe.SetMaximum( 1.1) # NB: For asymmetry distributions no density corrects are needed (and are thus not applied) print "\n>>> draw on canvas..." canvas = TCanvas("canvas","canvas",100,100,1400,600) canvas.Divide(2) canvas.cd(1) gPad.SetLeftMargin(0.15); gPad.SetRightMargin(0.02) dtframe.GetYaxis().SetLabelOffset(0.008) dtframe.GetYaxis().SetTitleOffset(1.6) dtframe.GetYaxis().SetTitleSize(0.045) dtframe.GetXaxis().SetTitleSize(0.045) dtframe.Draw() canvas.cd(2) gPad.SetLeftMargin(0.15); gPad.SetRightMargin(0.02) aframe.GetYaxis().SetLabelOffset(0.008) aframe.GetYaxis().SetTitleOffset(1.6) aframe.GetYaxis().SetTitleSize(0.045) aframe.GetXaxis().SetTitleSize(0.045) aframe.Draw() canvas.SaveAs("rooFit108.png")