def createWorkspace(options): """ Reads out the histograms from the pickle file and converts them to a RooDataHist Prepare PDFs Save all to a RooWorkspace """ # Read file cachefile = open(options.input, 'r') masshistos = pickle.load(cachefile) cachefile.close() print '>>> Read mass histos from (%s)' % options.input ## Scale all the mass histograms in one go: cachefile = open(".xsecweights.pck", 'r') xsecweights = pickle.load(cachefile) cachefile.close() print '>>> Read xsec weights from cache (.xsecweights.pck)' from extractNtrkWeights import extractNTrkWeights ntkWeights = extractNTrkWeights() for key, hist in masshistos.iteritems(): ## Xsection scaling hist.Scale(LUMI * xsecweights[CHANMASSTOPROCNAME[(key[1], key[2])]]) ## Ntrack bin reweighting to data try: hist.Scale(ntkWeights['inclusive'][key[4]]) except IndexError: pass bkgmasshistos = None try: cachefile = open(options.inputBkg, 'r') bkgmasshistos = pickle.load(cachefile) ## Note that these are already scaled to xs*lumi ## and weighted to data ntrack multiplicities cachefile.close() print '>>> Read background shapes from (%s)' % options.inputBkg except IOError: print '>>> No valid background shapes file found' # Extract the configurations from the diffhistos dictionary config = readConfig(masshistos) chselList, massList, trkMultList, combList, procList = config print 'Selected channels available :', chselList print 'Mass points available: ', massList print 'Track multiplicities available: ', trkMultList print 'Combinations available: ', combList print 'Processes available: ', procList # Initiate a workspace where the observable is the SVLMass # and the variable to fit is mtop ws = ROOT.RooWorkspace('w') SVLmass = ws.factory('SVLMass[100,0,300]') mtop = ws.factory('mtop[172.5,100,200]') sigStrength = ws.factory('mu[1.0,0.0,5.0]') # Import binned PDFs from histograms read from file for chsel in chselList: for trk in trkMultList: #backgrounds try: # These are already properly scaled by xsec hbkg = bkgmasshistos[(chsel, trk)] name = 'SVLMass_unm_%s_bg_%d' % (chsel, trk) getattr(ws, 'import')(ROOT.RooDataHist(name, name, ROOT.RooArgList(SVLmass), hbkg)) ws.factory('%s_bgexp_%d[%f]' % (chsel, trk, hbkg.Integral())) except Exception, e: raise e #signal for mass in massList: # ttbar for comb in ['cor', 'wro']: htt = masshistos[(chsel, 'tt', mass, comb, trk)] getattr(ws, 'import')(ROOT.RooDataHist( htt.GetName(), htt.GetTitle(), ROOT.RooArgList(SVLmass), htt)) # Only correct combinations for single top ht = None for stProc in ['t', 'tbar', 'tW', 'tbarW']: try: # get all available single top templates h = masshistos[(chsel, stProc, mass, 'cor', trk)] if ht is None: ht = h.Clone("SVLMass_%s_%s_%d_t_%d" % ('cor', chsel, 10 * mass, trk)) else: ht.Add(h) except KeyError: pass if ht: getattr(ws, 'import')(ROOT.RooDataHist( ht.GetName(), ht.GetTitle(), ROOT.RooArgList(SVLmass), ht)) # Unmatched for tt and wrong+unmatched for single top are merged htt_unm, ht_wrounm = None, None for mass in massList: htt = masshistos[(chsel, 'tt', mass, 'unm', trk)] if htt_unm is None: htt_unm = htt.Clone("SVLMass_unm_%s_tt_%d" % (chsel, trk)) else: htt_unm.Add(htt) for comb in ['unm', 'wro']: for stProc in ['t', 'tbar', 'tW', 'tbarW']: try: # get all available single top templates ht = masshistos[(chsel, stProc, mass, comb, trk)] if ht_wrounm is None: ht_wrounm = ht.Clone("SVLMass_wrounm_%s_t_%d" % (chsel, trk)) else: ht_wrounm.Add(ht) except KeyError: pass if htt_unm: getattr(ws, 'import')(ROOT.RooDataHist(htt_unm.GetName(), htt_unm.GetTitle(), ROOT.RooArgList(SVLmass), htt_unm)) if ht_wrounm: getattr(ws, 'import')(ROOT.RooDataHist(ht_wrounm.GetName(), ht_wrounm.GetTitle(), ROOT.RooArgList(SVLmass), ht_wrounm))
def createWorkspace(options): """ Reads out the histograms from the pickle file and converts them to a RooDataHist Prepare PDFs Save all to a RooWorkspace """ # Read file cachefile = open(options.input,'r') masshistos = pickle.load(cachefile) cachefile.close() print '>>> Read mass histos from (%s)' % options.input ## Scale all the mass histograms in one go: cachefile = open(".xsecweights.pck", 'r') xsecweights = pickle.load(cachefile) cachefile.close() print '>>> Read xsec weights from cache (.xsecweights.pck)' from extractNtrkWeights import extractNTrkWeights ntkWeights = extractNTrkWeights() for key, hist in masshistos.iteritems(): ## Xsection scaling hist.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[(key[1], key[2])]]) ## Ntrack bin reweighting to data try: hist.Scale(ntkWeights['inclusive'][key[4]]) except IndexError: pass bkgmasshistos=None try: cachefile = open(options.inputBkg,'r') bkgmasshistos = pickle.load(cachefile) ## Note that these are already scaled to xs*lumi ## and weighted to data ntrack multiplicities cachefile.close() print '>>> Read background shapes from (%s)' % options.inputBkg except IOError: print '>>> No valid background shapes file found' # Extract the configurations from the diffhistos dictionary config = readConfig(masshistos) chselList, massList, trkMultList, combList, procList = config print 'Selected channels available :', chselList print 'Mass points available: ', massList print 'Track multiplicities available: ', trkMultList print 'Combinations available: ', combList print 'Processes available: ' , procList # Initiate a workspace where the observable is the SVLMass # and the variable to fit is mtop ws = ROOT.RooWorkspace('w') SVLmass = ws.factory('SVLMass[100,0,300]') mtop = ws.factory('mtop[172.5,100,200]') sigStrength = ws.factory('mu[1.0,0.0,5.0]') # Import binned PDFs from histograms read from file for chsel in chselList: for trk in trkMultList: #backgrounds try: # These are already properly scaled by xsec hbkg = bkgmasshistos[(chsel,trk)] name = 'SVLMass_unm_%s_bg_%d'%(chsel,trk) getattr(ws,'import')(ROOT.RooDataHist(name,name, ROOT.RooArgList(SVLmass), hbkg)) ws.factory('%s_bgexp_%d[%f]'%(chsel,trk,hbkg.Integral())) except Exception, e: raise e #signal for mass in massList: # ttbar for comb in ['cor','wro']: htt = masshistos[(chsel,'tt',mass,comb,trk)] getattr(ws,'import')(ROOT.RooDataHist(htt.GetName(), htt.GetTitle(), ROOT.RooArgList(SVLmass), htt)) # Only correct combinations for single top ht = None for stProc in ['t','tbar','tW','tbarW']: try: # get all available single top templates h = masshistos[(chsel,stProc,mass,'cor',trk)] if ht is None: ht = h.Clone("SVLMass_%s_%s_%d_t_%d"%('cor',chsel,10*mass,trk)) else: ht.Add(h) except KeyError: pass if ht: getattr(ws,'import')(ROOT.RooDataHist(ht.GetName(), ht.GetTitle(), ROOT.RooArgList(SVLmass), ht)) # Unmatched for tt and wrong+unmatched for single top are merged htt_unm, ht_wrounm = None, None for mass in massList: htt = masshistos[(chsel,'tt',mass,'unm',trk)] if htt_unm is None : htt_unm=htt.Clone("SVLMass_unm_%s_tt_%d"%(chsel,trk)) else : htt_unm.Add(htt) for comb in ['unm','wro']: for stProc in ['t','tbar','tW','tbarW']: try: # get all available single top templates ht = masshistos[(chsel,stProc,mass,comb,trk)] if ht_wrounm is None : ht_wrounm=ht.Clone("SVLMass_wrounm_%s_t_%d"%(chsel,trk)) else : ht_wrounm.Add(ht) except KeyError: pass if htt_unm: getattr(ws,'import')(ROOT.RooDataHist(htt_unm.GetName(), htt_unm.GetTitle(), ROOT.RooArgList(SVLmass), htt_unm)) if ht_wrounm: getattr(ws,'import')(ROOT.RooDataHist(ht_wrounm.GetName(), ht_wrounm.GetTitle(), ROOT.RooArgList(SVLmass), ht_wrounm))
def main(args, opt): os.system('mkdir -p %s'%opt.outDir) mcfiles = {} # procname -> filename datafiles = {} # procname -> filename try: for fname in os.listdir(args[0]): if not osp.splitext(fname)[1] == '.root': continue isdata,procname,splitno = resolveFilename(fname) if isdata: if not procname in datafiles: datafiles[procname] = [] datafiles[procname].append(osp.join(args[0],fname)) else: if 'QCD' in procname: continue ## exclude QCD if procname == 'TTJets_MSDecays_172v5': continue ## have those already if 'SingleT' in procname: continue ## have those already if not procname in mcfiles: mcfiles[procname] = [] mcfiles[procname].append(osp.join(args[0],fname)) except IndexError: print "Please provide a valid input directory" exit(-1) ## Produce (or read) the histogram data bghistos = makeBackgroundHistos(mcfiles, opt) cachefile = open(".xsecweights.pck", 'r') xsecweights = pickle.load(cachefile) cachefile.close() print '>>> Read xsec weights from cache (.xsecweights.pck)' cachefile = open(".svldyscalefactors.pck", 'r') dySFs = pickle.load(cachefile) cachefile.close() print '>>> Read DY scale factors from cache (.svldyscalefactors.pck)' cachefile = open(".svlqcdtemplates.pck", 'r') qcdTemplates = pickle.load(cachefile) cachefile.close() print '>>> Read QCD templates from cache (.svlqcdtemplates.pck)' ## Read SV Track multiplicity weights: from extractNtrkWeights import extractNTrkWeights ntkWeights = extractNTrkWeights() ## Now add them up with proper scales mcprocesses = [k for k in mcfiles.keys() if not 'Data8TeV' in k] bghistos_added = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt) bghistos_added_dyup = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, dyScale=1.3) bghistos_added_dydn = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, dyScale=0.7) bghistos_added_qcdup = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, qcdScale=1.1) bghistos_added_qcddn = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, qcdScale=0.9) ## Produce data histograms datahistos = makeDataHistos(datafiles, opt) datahistos_added = sumDataHistos(datafiles.keys(), datahistos) # Rebin also data, if required: if opt.rebin>0: for hist in datahistos_added.values(): hist.Rebin(opt.rebin) ## Save the background only shapes separately as templates for the fit cachefile = open(".svlbgtemplates.pck", 'w') pickle.dump(bghistos_added, cachefile, pickle.HIGHEST_PROTOCOL) print '>>> Dumped bg templates to cache (.svlbgtemplates.pck)' cachefile.close() ## Read syst histos: cachefile = open(".svlsysthistos.pck", 'r') systhistos = pickle.load(cachefile) print '>>> Read systematics histograms from cache (.svlsysthistos.pck)' cachefile.close() ## Read mass scan histos: cachefile = open(".svlmasshistos.pck", 'r') masshistos = pickle.load(cachefile) print '>>> Read mass scan histograms from cache (.svlmasshistos.pck)' # (tag, chan, mass, comb) -> histo # (tag, chan, mass, comb, ntk) -> histo cachefile.close() ofi = ROOT.TFile.Open(osp.join(opt.outDir,'pe_inputs.root'),'RECREATE') ofi.cd() ##################################################### ## Central mass point and syst samples for syst in ([s for s,_,_,_ in ALLSYSTS] + ['dyup','dydown','qcdup','qcddown','ntkmult']): odir = ofi.mkdir(syst + '_172v5') odir.cd() for tag,_,_ in SELECTIONS: for ntk,_ in NTRKBINS: hname = "SVLMass_%s_%s_%s" % (tag,syst+'_172v5',ntk) if not syst in ['dyup','dydown','qcdup','qcddown','ntkmult', 'tchscaleup','tchscaledown', 'twchscaleup','twchscaledown']: hfinal = systhistos[(tag,syst,'tot',ntk)].Clone(hname) else: hfinal = systhistos[(tag,'nominal','tot',ntk)].Clone(hname) try: ## Systs from separate samples if syst in ['tchscaleup','tchscaledown', 'twchscaleup','twchscaledown']: scale = LUMI*xsecweights[CHANMASSTOPROCNAME[('tt', 172.5)]] else: scale = LUMI*xsecweights[SYSTTOPROCNAME[syst][0]] except KeyError: ## Systs from event weights scale = LUMI*xsecweights[CHANMASSTOPROCNAME[('tt', 172.5)]] hfinal.Scale(scale) ## Renormalize some variations with event weights if syst in SYSTSTOBERENORMALIZED: normintegral = systhistos[(tag,'nominal','tot',ntk)].Integral() normintegral *= LUMI*xsecweights[CHANMASSTOPROCNAME[('tt', 172.5)]] normintegral /= hfinal.Integral() hfinal.Scale(normintegral) ## Add single top stProcs=['t', 'tbar', 'tW', 'tbarW'] stSystProcs=[] if 'tchscale' in syst: stProcs=['tW', 'tbarW'] stSystProcs=['t', 'tbar'] if 'twchscale' in syst: stProcs=['t', 'tbar'] stSystProcs=['tW', 'tbarW'] for st in stProcs: hsinglet = masshistos[(tag, st, 172.5,'tot',ntk)].Clone('%s_%s'%(hname,st)) hsinglet.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[(st, 172.5)]]) hfinal.Add(hsinglet) for st in stSystProcs: hsinglet = systhistos[(tag, syst, 'tot', ntk)].Clone('%s_%s'%(hname,st)) hsinglet.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[(st, 172.5)]]) hfinal.Add(hsinglet) ## Add the backgrounds if not syst in ['dyup','dydown','qcdup','qcddown']: hfinal.Add(bghistos_added[(tag,ntk)]) else: ## From the scaled bghistos if necessary bghistos_added_scaled = { 'dyup' : bghistos_added_dyup, 'dydown' : bghistos_added_dydn, 'qcdup' : bghistos_added_qcdup, 'qcddown' : bghistos_added_qcddn, }[syst] hfinal.Add(bghistos_added_scaled[(tag,ntk)]) ## Rebin if requested if opt.rebin>0: hfinal.Rebin(opt.rebin) ## Scale by SV track multiplicity weights: if not syst == 'ntkmult': hfinal.Scale(ntkWeights['inclusive'][ntk]) ## Write out to file hfinal.Write(hname, ROOT.TObject.kOverwrite) ##################################################### ## Non-central mass points ROOT.gSystem.Load('libUserCodeTopMassSecVtx.so') from ROOT import th1fmorph # extract mass points from dictionary mass_points = sorted(list(set([key[2] for key in masshistos.keys()]))) mass_points = mass_points[1:-1] # remove outermost points debughistos = [] for mass in mass_points: if mass == 172.5: continue mname = 'nominal_%s' % str(mass).replace('.','v') odir = ofi.mkdir(mname) odir.cd() for tag,_,_ in SELECTIONS: for ntk,_ in NTRKBINS: hname = "SVLMass_%s_%s_%s" % (tag,mname,ntk) hfinal = masshistos[(tag,'tt',mass,'tot',ntk)].Clone(hname) hfinal.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[('tt', mass)]]) ## Add single top (t-channel, for which we have the samples) for st in ['t', 'tbar']: hsinglet = masshistos[(tag, st, mass,'tot',ntk)].Clone('%s_%s'%(hname,st)) hsinglet.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[(st, mass)]]) hfinal.Add(hsinglet) ## Add single top (tW-channel, for which we don't have samples) ## Morph between the two extreme mass points to get ## the non existing ones for st in ['tW', 'tbarW']: if mass not in [166.5, 178.5]: hsingletW = th1fmorph('%s_%s_morph'%(hname,st), '%s_%s_morphed'%(hname,st), masshistos[(tag, 'tW', 166.5,'tot',ntk)], masshistos[(tag, 'tW', 178.5,'tot',ntk)], 166.5, 178.5, mass, masshistos[(tag, 'tW', 166.5,'tot',ntk)].Integral()) hsingletW.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[(st, 166.5)]] * TWXSECS[mass]/TWXSECS[166.5]) hsingletW.SetDirectory(0) else: hsingletW = masshistos[(tag, st, mass,'tot',ntk)].Clone('%s_%s'%(hname,st)) hsingletW.Scale(LUMI*xsecweights[CHANMASSTOPROCNAME[(st, mass)]]) hfinal.Add(hsingletW) ## Add the combined backgrounds hfinal.Add(bghistos_added[(tag,ntk)]) ## Rebin if requested if opt.rebin>0: hfinal.Rebin(opt.rebin) ## Scale by SV track multiplicity weights: hfinal.Scale(ntkWeights['inclusive'][ntk]) ## Write out to file hfinal.Write(hname, ROOT.TObject.kOverwrite) ## Write also data histos ofi.cd() odir = ofi.mkdir('data') odir.cd() for tag,_,_ in SELECTIONS: for ntk,_ in NTRKBINS: hname = "SVLMass_%s_data_%s" % (tag,ntk) datahistos_added[(tag,ntk)].Write(hname, ROOT.TObject.kOverwrite) print ('>>> Wrote pseudo experiment inputs to file (%s)' % osp.join(opt.outDir,'pe_inputs.root')) ofi.Write() ofi.Close() return 0
def main(args, opt): os.system('mkdir -p %s' % opt.outDir) mcfiles = {} # procname -> filename datafiles = {} # procname -> filename try: for fname in os.listdir(args[0]): if not osp.splitext(fname)[1] == '.root': continue isdata, procname, splitno = resolveFilename(fname) if isdata: if not procname in datafiles: datafiles[procname] = [] datafiles[procname].append(osp.join(args[0], fname)) else: if 'QCD' in procname: continue ## exclude QCD if procname == 'TTJets_MSDecays_172v5': continue ## have those already if 'SingleT' in procname: continue ## have those already if not procname in mcfiles: mcfiles[procname] = [] mcfiles[procname].append(osp.join(args[0], fname)) except IndexError: print "Please provide a valid input directory" exit(-1) ## Produce (or read) the histogram data bghistos = makeBackgroundHistos(mcfiles, opt) cachefile = open(".xsecweights.pck", 'r') xsecweights = pickle.load(cachefile) cachefile.close() print '>>> Read xsec weights from cache (.xsecweights.pck)' cachefile = open(".svldyscalefactors.pck", 'r') dySFs = pickle.load(cachefile) cachefile.close() print '>>> Read DY scale factors from cache (.svldyscalefactors.pck)' cachefile = open(".svlqcdtemplates.pck", 'r') qcdTemplates = pickle.load(cachefile) cachefile.close() print '>>> Read QCD templates from cache (.svlqcdtemplates.pck)' ## Read SV Track multiplicity weights: from extractNtrkWeights import extractNTrkWeights ntkWeights = extractNTrkWeights() ## Now add them up with proper scales mcprocesses = [k for k in mcfiles.keys() if not 'Data8TeV' in k] bghistos_added = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt) bghistos_added_dyup = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, dyScale=1.3) bghistos_added_dydn = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, dyScale=0.7) bghistos_added_qcdup = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, qcdScale=1.1) bghistos_added_qcddn = sumBGHistos(processes=mcprocesses, bghistos=bghistos, xsecweights=xsecweights, ntkWeights=ntkWeights, dySFs=dySFs, qcdTemplates=qcdTemplates, opt=opt, qcdScale=0.9) ## Produce data histograms datahistos = makeDataHistos(datafiles, opt) datahistos_added = sumDataHistos(datafiles.keys(), datahistos) # Rebin also data, if required: if opt.rebin > 0: for hist in datahistos_added.values(): hist.Rebin(opt.rebin) ## Save the background only shapes separately as templates for the fit cachefile = open(".svlbgtemplates.pck", 'w') pickle.dump(bghistos_added, cachefile, pickle.HIGHEST_PROTOCOL) print '>>> Dumped bg templates to cache (.svlbgtemplates.pck)' cachefile.close() ## Read syst histos: cachefile = open(".svlsysthistos.pck", 'r') systhistos = pickle.load(cachefile) print '>>> Read systematics histograms from cache (.svlsysthistos.pck)' cachefile.close() ## Read mass scan histos: cachefile = open(".svlmasshistos.pck", 'r') masshistos = pickle.load(cachefile) print '>>> Read mass scan histograms from cache (.svlmasshistos.pck)' # (tag, chan, mass, comb) -> histo # (tag, chan, mass, comb, ntk) -> histo cachefile.close() ## Signal only (tt+t+tW) shapes signalonly = {} ofi = ROOT.TFile.Open(osp.join(opt.outDir, 'pe_inputs.root'), 'RECREATE') ofi.cd() ##################################################### ## Central mass point and syst samples to_be_processed = ([s for s, _, _, _ in ALLSYSTS] + ['dyup', 'dydown', 'qcdup', 'qcddown', 'ntkmult']) if opt.skip_systs: to_be_processed = ['nominal'] for syst in to_be_processed: odir = ofi.mkdir(syst + '_172v5') odir.cd() for tag, _, _ in SELECTIONS: for ntk, _ in NTRKBINS: hname = "SVLMass_%s_%s_%s" % (tag, syst + '_172v5', ntk) if not syst in [ 'dyup', 'dydown', 'qcdup', 'qcddown', 'ntkmult', 'tchscaleup', 'tchscaledown', 'twchscaleup', 'twchscaledown' ]: hfinal = systhistos[(tag, syst, 'tot', ntk)].Clone(hname) else: hfinal = systhistos[(tag, 'nominal', 'tot', ntk)].Clone(hname) try: ## Systs from separate samples if syst in [ 'tchscaleup', 'tchscaledown', 'twchscaleup', 'twchscaledown' ]: scale = LUMI * xsecweights[CHANMASSTOPROCNAME[('tt', 172.5)]] else: scale = LUMI * xsecweights[SYSTTOPROCNAME[syst][0]] except KeyError: ## Systs from event weights scale = LUMI * xsecweights[CHANMASSTOPROCNAME[('tt', 172.5)]] hfinal.Scale(scale) ## Renormalize some variations with event weights if syst in SYSTSTOBERENORMALIZED: normintegral = systhistos[(tag, 'nominal', 'tot', ntk)].Integral() normintegral *= LUMI * xsecweights[CHANMASSTOPROCNAME[ ('tt', 172.5)]] normintegral /= hfinal.Integral() hfinal.Scale(normintegral) ## Add single top stProcs = ['t', 'tbar', 'tW', 'tbarW'] stSystProcs = [] if 'tchscale' in syst: stProcs = ['tW', 'tbarW'] stSystProcs = ['t', 'tbar'] if 'twchscale' in syst: stProcs = ['t', 'tbar'] stSystProcs = ['tW', 'tbarW'] for st in stProcs: hsinglet = masshistos[(tag, st, 172.5, 'tot', ntk)].Clone('%s_%s' % (hname, st)) hsinglet.Scale( LUMI * xsecweights[CHANMASSTOPROCNAME[(st, 172.5)]]) hfinal.Add(hsinglet) for st in stSystProcs: hsinglet = systhistos[(tag, syst, 'tot', ntk)].Clone('%s_%s' % (hname, st)) hsinglet.Scale( LUMI * xsecweights[CHANMASSTOPROCNAME[(st, 172.5)]]) hfinal.Add(hsinglet) ## Save signal only shapes if syst == 'nominal': signalonly[(tag, 172.5, ntk)] = hfinal.Clone('%s_sigonly' % hname) signalonly[(tag, 172.5, ntk)].Scale(ntkWeights['inclusive'][ntk]) if opt.rebin > 0: signalonly[(tag, 172.5, ntk)].Rebin(opt.rebin) ## Add the backgrounds if not syst in ['dyup', 'dydown', 'qcdup', 'qcddown']: hfinal.Add(bghistos_added[(tag, ntk)]) else: ## From the scaled bghistos if necessary bghistos_added_scaled = { 'dyup': bghistos_added_dyup, 'dydown': bghistos_added_dydn, 'qcdup': bghistos_added_qcdup, 'qcddown': bghistos_added_qcddn, }[syst] hfinal.Add(bghistos_added_scaled[(tag, ntk)]) ## Rebin if requested if opt.rebin > 0: hfinal.Rebin(opt.rebin) ## Scale by SV track multiplicity weights: if not syst == 'ntkmult': hfinal.Scale(ntkWeights['inclusive'][ntk]) ## Write out to file hfinal.Write(hname, ROOT.TObject.kOverwrite) ##################################################### ## Non-central mass points ROOT.gSystem.Load('libUserCodeTopMassSecVtx.so') from ROOT import th1fmorph # extract mass points from dictionary mass_points = sorted(list(set([key[2] for key in masshistos.keys()]))) mass_points = mass_points[1:-1] # remove outermost points debughistos = [] for mass in mass_points: if mass == 172.5: continue mname = 'nominal_%s' % str(mass).replace('.', 'v') odir = ofi.mkdir(mname) odir.cd() for tag, _, _ in SELECTIONS: for ntk, _ in NTRKBINS: hname = "SVLMass_%s_%s_%s" % (tag, mname, ntk) hfinal = masshistos[(tag, 'tt', mass, 'tot', ntk)].Clone(hname) hfinal.Scale(LUMI * xsecweights[CHANMASSTOPROCNAME[('tt', mass)]]) ## Add single top (t-channel, for which we have the samples) for st in ['t', 'tbar']: hsinglet = masshistos[(tag, st, mass, 'tot', ntk)].Clone('%s_%s' % (hname, st)) hsinglet.Scale(LUMI * xsecweights[CHANMASSTOPROCNAME[(st, mass)]]) hfinal.Add(hsinglet) ## Add single top (tW-channel, for which we don't have samples) ## Morph between the two extreme mass points to get ## the non existing ones for st in ['tW', 'tbarW']: if mass not in [166.5, 178.5]: hsingletW = th1fmorph( '%s_%s_morph' % (hname, st), '%s_%s_morphed' % (hname, st), masshistos[(tag, 'tW', 166.5, 'tot', ntk)], masshistos[(tag, 'tW', 178.5, 'tot', ntk)], 166.5, 178.5, mass, masshistos[(tag, 'tW', 166.5, 'tot', ntk)].Integral()) hsingletW.Scale( LUMI * xsecweights[CHANMASSTOPROCNAME[(st, 166.5)]] * TWXSECS[mass] / TWXSECS[166.5]) hsingletW.SetDirectory(0) else: hsingletW = masshistos[(tag, st, mass, 'tot', ntk)].Clone('%s_%s' % (hname, st)) hsingletW.Scale( LUMI * xsecweights[CHANMASSTOPROCNAME[(st, mass)]]) hfinal.Add(hsingletW) ## Save signal only shapes signalonly[(tag, mass, ntk)] = hfinal.Clone('%s_sigonly' % hname) signalonly[(tag, mass, ntk)].Scale(ntkWeights['inclusive'][ntk]) if opt.rebin > 0: signalonly[(tag, mass, ntk)].Rebin(opt.rebin) ## Add the combined backgrounds hfinal.Add(bghistos_added[(tag, ntk)]) ## Rebin if requested if opt.rebin > 0: hfinal.Rebin(opt.rebin) ## Scale by SV track multiplicity weights: hfinal.Scale(ntkWeights['inclusive'][ntk]) ## Write out to file hfinal.Write(hname, ROOT.TObject.kOverwrite) ## Save the signal only shapes (tt+t+tW) as input for the combined plot cachefile = open(".svlsignalshapes.pck", 'w') pickle.dump(signalonly, cachefile, pickle.HIGHEST_PROTOCOL) print '>>> Dumped signal only shapes to cache (.svlsignalshapes.pck)' cachefile.close() ## Write also data histos ofi.cd() odir = ofi.mkdir('data') odir.cd() for tag, _, _ in SELECTIONS: for ntk, _ in NTRKBINS: hname = "SVLMass_%s_data_%s" % (tag, ntk) datahistos_added[(tag, ntk)].Write(hname, ROOT.TObject.kOverwrite) print('>>> Wrote pseudo experiment inputs to file (%s)' % osp.join(opt.outDir, 'pe_inputs.root')) ofi.Write() ofi.Close() return 0