def initialize(cfg, version, mass): RooMsgService.instance().setGlobalKillBelow(RF.ERROR) gROOT.SetBatch(True) #gSystem.Load("libWSMaker.so") gSystem.Load("libPlotUtils.so") ws, g = getWorkspace(version, mass) logging.info("Preparing NP to the requested values") # Make postfit plots if not cfg._main_is_prefit: rfr, suffix = getFitResult(cfg) transferResults(cfg, ws, rfr) plotdir = "output/{0}/plots/postfit".format(version) # Make prefit plots else: plotdir = "output/{0}/plots/prefit".format(version) rfr = getInitialFitRes(cfg, ws) ws.loadSnapshot("vars_initial") suffix = "Prefit" # GetBinning binHist = getBinningDir(g) os.system("mkdir -vp " + plotdir) cfg._yieldsfile = os.path.join(plotdir, "Yields_{0}.yik".format(suffix)) cfg._plot_objs_file = os.path.join(plotdir, "plotobjs_{0}.yik".format(suffix)) return ws, rfr, suffix, plotdir, g, binHist
def model(self, ws, debug = 0): if self.sModel not in self.items: if debug>0: print self.legend, 'no Model section defined in the config file' print self.legend, 'no model will be created' return legend = '['+self.sModel+']:' # FIXME: find a better way to load custom PDFs #gROOT.ProcessLine(".L dijetQstarPdf.cxx+"); #gROOT.ProcessLine(".L Qstar_qg.cxx+"); #gROOT.ProcessLine(".L Qstar_qg_2.cxx+"); #gROOT.ProcessLine(".L Jacobian_mt.cxx+"); model_items = self.items[self.sModel] if (debug>0): print 'Loading model to the workspace', ws.GetName() # using RooStats::HLFactory to parse the model # make a temp file with a card file card_file_name = 'hlfCardFile.rs' with open(card_file_name, 'w') as cardfile: for item in model_items: print >> cardfile, item[0], '=', item[1] hlfVerbosity = debug > 0 #hlf = ROOT.RooStats.HLFactory('HLFactoryExost', card_file_name, True) hlf = RooStats.HLFactory('HLFactoryExost', ws, hlfVerbosity) self.modelAutoImportWarningExplanation(legend, debug) current_messaging_level = RooMsgService.instance().globalKillBelow() ; if debug <= 0: RooMsgService.instance().setGlobalKillBelow(RooFit.ERROR) ; hlf.ProcessCard(card_file_name) print legend, 'importing nonstandard class code into the workspace...' ws.importClassCode(); #ws.importClassCode('Qstar_qg', true); print legend, '...code import done' # return messaging to the original level RooMsgService.instance().setGlobalKillBelow(current_messaging_level) ;
def __init__(self, fit_data_collection, method="TMinuit"): RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) self.method = method self.logger = logging.getLogger("RooFit") self.constraints = fit_data_collection.constraints() self.constraint_type = "" self.saved_result = None self.fit_data_collection = fit_data_collection self.samples = fit_data_collection.mc_samples() self.normalisation = fit_data_collection.mc_normalisation() self.fit_data_1 = self.fit_data_collection.fit_data.items()[0][1] self.fit_boundaries = self.fit_data_1.fit_boundaries self.data_label = FitData.data_label self.histograms = self.fit_data_1.histograms_
def __init__(self, fit_data_collection, method='TMinuit'): RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) self.method = method self.logger = logging.getLogger('RooFit') self.constraints = fit_data_collection.constraints() self.constraint_type = '' self.saved_result = None self.fit_data_collection = fit_data_collection self.samples = fit_data_collection.mc_samples() self.normalisation = fit_data_collection.mc_normalisation() self.fit_data_1 = self.fit_data_collection.fit_data.items()[0][1] self.fit_boundaries = self.fit_data_1.fit_boundaries self.data_label = FitData.data_label self.histograms = self.fit_data_1.histograms_
def rf_verbosity(lvl): """Set RooFit verbosity level""" from ROOT import RooMsgService msgsvc = RooMsgService.instance() oldlvl = msgsvc.globalKillBelow() msgsvc.setGlobalKillBelow(lvl) return oldlvl
def model(self, ws, debug=0): if self.sModel not in self.items: if debug > 0: print self.legend, 'no Model section defined in the config file' print self.legend, 'no model will be created' return legend = '[' + self.sModel + ']:' # FIXME: find a better way to load custom PDFs #gROOT.ProcessLine(".L dijetQstarPdf.cxx+"); #gROOT.ProcessLine(".L Qstar_qg.cxx+"); #gROOT.ProcessLine(".L Qstar_qg_2.cxx+"); #gROOT.ProcessLine(".L Jacobian_mt.cxx+"); model_items = self.items[self.sModel] if (debug > 0): print 'Loading model to the workspace', ws.GetName() # using RooStats::HLFactory to parse the model # make a temp file with a card file card_file_name = 'hlfCardFile.rs' with open(card_file_name, 'w') as cardfile: for item in model_items: print >> cardfile, item[0], '=', item[1] hlfVerbosity = debug > 0 #hlf = ROOT.RooStats.HLFactory('HLFactoryExost', card_file_name, True) hlf = RooStats.HLFactory('HLFactoryExost', ws, hlfVerbosity) self.modelAutoImportWarningExplanation(legend, debug) current_messaging_level = RooMsgService.instance().globalKillBelow() if debug <= 0: RooMsgService.instance().setGlobalKillBelow(RooFit.ERROR) hlf.ProcessCard(card_file_name) print legend, 'importing nonstandard class code into the workspace...' ws.importClassCode() #ws.importClassCode('Qstar_qg', true); print legend, '...code import done' # return messaging to the original level RooMsgService.instance().setGlobalKillBelow(current_messaging_level)
def action(ws, action_name, settings = None): legend = '[Action]:' print legend, 'beginning the ', action_name, 'action' if action_name == 'bayes': if settings['status'] == 'fail': print legend, 'Bayesian calculator failed to configure' print legend, 'action stopped.' return legend = '[Bayesian calculator]:' #mconf = ws.obj('exostModelConfig') mconf = ws.obj(settings['model_config_name']) bCalc = ws.obj('exostBayes') # to suppress messages when pdf goes to zero RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) if mconf.GetParametersOfInterest().getSize() == 1: bInt = bCalc.GetInterval() cl = bCalc.ConfidenceLevel() print legend, str(cl)+'% CL central interval: [', bInt.LowerLimit(), ' - ', bInt.UpperLimit(), ']' print legend, 'or', str(cl+(1.0-cl)/2), '% CL limits' # make a posterior plot if settings['do_posterior_plot']: plot = bCalc.GetPosteriorPlot() c1 = TCanvas('c1','Bayesian Calculator Result'); c1.cd(1) plot.Draw() c1.SaveAs('bayesian_example_plot.'+settings['plot_format']) else: print legend, 'Error: Bayesian Calc. only supports one parameter of interest' print legend, 'the', action_name, 'action is done'
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/dijetFitResults_FuncType0_nParFit4_MC_1invfb.root --dataHistname hist_mass_1GeV --inputSig inputs/ResonanceShapes_qg_13TeV_PU30_Spring15.root -f qg -o datacards -l 1000 --massrange 1200 7000 100" # input parameters parser = ArgumentParser(description='Script that creates combine datacards and corresponding RooFit workspaces',epilog=usage) parser.add_argument("--inputData", dest="inputData", required=True, help="Input data spectrum", metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", required=True, help="Data histogram name", metavar="DATA_HISTNAME") parser.add_argument("--inputSig", dest="inputSig", required=True, help="Input signal shapes", metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", required=True, help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("-o", "--output_path", dest="output_path", required=True, help="Output path where datacards and workspaces will be stored", metavar="OUTPUT_PATH") parser.add_argument("-l", "--lumi", dest="lumi", required=True, default=1000., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument("--massMin", dest="massMin", default=1118, help="Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument("--massMax", dest="massMax", default=9067, help="Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument("--p1", dest="p1", default=7.7666e+00, type=float, help="Fit function p1 parameter (default: %(default)e)", metavar="P1") parser.add_argument("--p2", dest="p2", default=5.3748e+00, type=float, help="Fit function p2 parameter (default: %(default)e)", metavar="P2") parser.add_argument("--p3", dest="p3", default=5.6385e-03, type=float, help="Fit function p3 parameter (default: %(default)e)", metavar="P3") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=0, help="Fit strategy (default: %(default).1f)") parser.add_argument("--sqrtS", dest="sqrtS", type=float, default=13000., help="Collision center-of-mass energy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument("--mass", type=int, nargs = '*', default = 1000, help="Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument("--massrange", type=int, nargs = 3, help="Define a range of masses to be produced. Format: min max step", metavar = ('MIN', 'MAX', 'STEP') ) mass_group.add_argument("--masslist", help = "List containing mass information" ) args = parser.parse_args() # check if the output directory exists if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ): os.mkdir( os.path.join(os.getcwd(),args.output_path) ) # mass points for which resonance shapes will be produced masses = [] if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX+STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py","")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import TFile, TH1F, TH1D, kTRUE, kFALSE from ROOT import RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0,kFALSE) RooMsgService.instance().setStreamStatus(1,kFALSE) # input data file inputData = TFile(args.inputData) # input data histogram hData = inputData.Get(args.dataHistname) # input sig file inputSig = TFile(args.inputSig) sqrtS = args.sqrtS for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..."%(args.final_state, int(mass)) hSig = inputSig.Get( "h_" + args.final_state + "_" + str(int(mass)) ) # calculate acceptance of the dijet mass cut sigAcc = hSig.Integral(hSig.GetXaxis().FindBin(args.massMin),hSig.GetXaxis().FindBin(args.massMax))/hSig.Integral(1,hSig.GetXaxis().FindBin(args.massMax)) mjj = RooRealVar('mjj','mjj',args.massMin,args.massMax) rooSigHist = RooDataHist('rooSigHist','rooSigHist',RooArgList(mjj),hSig) rooSigHist.Print() signal = RooHistPdf('signal','signal',RooArgSet(mjj),rooSigHist) signal.Print() signal_norm = RooRealVar('signal_norm','signal_norm',0,-1e+04,1e+04) if args.fitBonly: signal_norm.setConstant() signal_norm.Print() p1 = RooRealVar('p1','p1',args.p1,0.,100.) p2 = RooRealVar('p2','p2',args.p2,0.,60.) p3 = RooRealVar('p3','p3',args.p3,-10.,10.) background = RooGenericPdf('background','(pow(1-@0/%.1f,@1)/pow(@0/%.1f,@2+@3*log(@0/%.1f)))'%(sqrtS,sqrtS,sqrtS),RooArgList(mjj,p1,p2,p3)) background.Print() dataInt = hData.Integral(hData.GetXaxis().FindBin(args.massMin),hData.GetXaxis().FindBin(args.massMax)) background_norm = RooRealVar('background_norm','background_norm',dataInt,0.,1e+07) background_norm.Print() # S+B model model = RooAddPdf("model","s+b",RooArgList(background,signal),RooArgList(background_norm,signal_norm)) rooDataHist = RooDataHist('rooDatahist','rooDathist',RooArgList(mjj),hData) rooDataHist.Print() if args.runFit: res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) res.Print() dcName = 'datacard_' + args.final_state + '_m' + str(mass) + '.txt' wsName = 'workspace_' + args.final_state + '_m' + str(mass) + '.root' w = RooWorkspace('w','workspace') getattr(w,'import')(signal) getattr(w,'import')(background) getattr(w,'import')(background_norm) getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs")) w.Print() w.writeToFile(os.path.join(args.output_path,wsName)) # ----------------------------------------- # write a datacard lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section expectedSignalRate = signalCrossSection*lumi*sigAcc datacard = open(os.path.join(args.output_path,dcName),'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') datacard.write('shapes * * '+wsName+' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background\n') datacard.write('process 0 1\n') datacard.write('rate '+str(expectedSignalRate)+' 1\n') datacard.write('------------------------------\n') #flat parameters --- flat prior datacard.write('background_norm flatParam\n') datacard.write('p1 flatParam\n') datacard.write('p2 flatParam\n') datacard.write('p3 flatParam\n') datacard.close() print '>> Datacards and workspaces created and stored in %s/.'%( os.path.join(os.getcwd(),args.output_path) )
#import HWW2DConfig config = __import__(opts.modeConfig) import RooWjj2DFitter from ROOT import TCanvas, RooFit, RooLinkedListIter, TMath, RooRandom, TFile, \ RooDataHist, RooMsgService, TStopwatch, RooAbsPdf, RooAbsData, \ RooWorkspace, RooArgList, RooAddPdf import pulls timer = TStopwatch() timer.Start() #RooAbsPdf.defaultIntegratorConfig().setEpsRel(1e-9) #RooAbsPdf.defaultIntegratorConfig().setEpsAbs(1e-9) if not opts.debug: RooMsgService.instance().setGlobalKillBelow(RooFit.WARNING) RooMsgService.instance().addStream(RooFit.ERROR, RooFit.Prefix(True), RooFit.ClassName('RooExpPoly'), RooFit.OutputFile('/dev/null')) RooMsgService.instance().Print('v') if hasattr(opts, "seed") and (opts.seed >= 0): print "random seed:", opts.seed RooRandom.randomGenerator().SetSeed(opts.seed) mvaCutOverride = None if hasattr(opts, "mvaCut"): mvaCutOverride = opts.mvaCut mjjArgs = []
ntuple_file = None if args[0] in input_data.keys(): ntuple_file = input_data[args[0]] from P2VV.Load import P2VVLibrary from P2VV.Load import RooFitOutput from P2VV.RooFitWrappers import * from itertools import product from ROOT import RooCBShape as CrystalBall from P2VV.Parameterizations.GeneralUtils import valid_combinations #from P2VV.Load import RooFitOutput from ROOT import RooMsgService RooMsgService.instance().addStream(RooFit.DEBUG,RooFit.Topic(RooFit.Generation)) ## RooMsgService.instance().addStream(RooFit.DEBUG,RooFit.Topic(RooFit.Integration)) obj = RooObject( workspace = 'w') w = obj.ws() from math import pi t = RealVar('time', Title = 'decay time', Unit='ps', Observable = True, MinMax=(0.3, 14)) m = RealVar('mass', Title = 'B mass', Unit = 'MeV', Observable = True, MinMax = (5250, 5550)) nPV = RealVar('nPV', Title = 'nPV', Observable = True, MinMax = (0, 15)) mpsi = RealVar('mdau1', Title = 'J/psi mass', Unit = 'MeV', Observable = True, MinMax = (3030, 3150)) st = RealVar('sigmat',Title = '#sigma(t)', Unit = 'ps', Observable = True, MinMax = (0.0001, 0.12)) # Categories hlt1_biased = Category('hlt1_biased', States = {'biased' : 1, 'not_biased' : 0}, Observable = True) hlt1_unbiased = Category('hlt1_unbiased_dec', States = {'unbiased' : 1, 'not_unbiased' : 0}, Observable = True)
# set up fitting options fitopts = [ RooFit.Timer(), RooFit.Save(), RooFit.Strategy(config['FitConfig']['Strategy']), RooFit.Optimize(config['FitConfig']['Optimize']), RooFit.Offset(config['FitConfig']['Offset']), RooFit.NumCPU(config['FitConfig']['NumCPU']) ] # set up blinding for data fitopts.append( RooFit.Verbose(not (config['IsData'] and config['Blinding']))) if config['IsData'] and config['Blinding']: from ROOT import RooMsgService RooMsgService.instance().setGlobalKillBelow(RooFit.WARNING) fitopts.append(RooFit.PrintLevel(-1)) fitOpts = RooLinkedList() for o in fitopts: fitOpts.Add(o) # fit rawfitresult = fitpdf['pdf'].fitTo(tupleDataSet, fitOpts) # pretty-print the result from B2DXFitters.FitResult import getDsHBlindFitResult result = getDsHBlindFitResult(config['IsData'], config['Blinding'], rawfitresult) print result ''' doubleCanvas = TCanvas();
# set constant what is supposed to be constant setConstantIfSoConfigured(config, fitpdf) # set up fitting options fitopts = [ RooFit.Timer(), RooFit.Save(), RooFit.Strategy(config['FitConfig']['Strategy']), RooFit.Optimize(config['FitConfig']['Optimize']), RooFit.Offset(config['FitConfig']['Offset']), RooFit.NumCPU(config['FitConfig']['NumCPU']) ] # set up blinding for data fitopts.append(RooFit.Verbose(not (config['IsData'] and config['Blinding']))) if config['IsData'] and config['Blinding']: from ROOT import RooMsgService RooMsgService.instance().setGlobalKillBelow(RooFit.WARNING) fitopts.append(RooFit.PrintLevel(-1)) fitOpts = RooLinkedList() for o in fitopts: fitOpts.Add(o) # fit rawfitresult = fitpdf.fitTo(ds, fitOpts) # pretty-print the result from B2DXFitters.FitResult import getDsHBlindFitResult result = getDsHBlindFitResult(config['IsData'], config['Blinding'], rawfitresult) print result # write raw fit result and workspace to separate ROOT files from ROOT import TFile
def alpha(channel): nElec = channel.count("e") nMuon = channel.count("m") nLept = nElec + nMuon nBtag = channel.count("b") # Channel-dependent settings # Background function. Semi-working options are: EXP, EXP2, EXPN, EXPTAIL if nLept == 0: treeName = "SR" signName = "XZh" colorVjet = sample["DYJetsToNuNu"]["linecolor"] triName = "HLT_PFMET" leptCut = "0==0" topVeto = selection["TopVetocut"] massVar = "X_cmass" binFact = 1 fitFunc = "EXPN" if nBtag < 2 else "EXPN" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitAltFuncVjet = "POL" if nBtag < 2 else "POL" fitFuncVV = "EXPGAUS" if nBtag < 2 else "EXPGAUS" fitFuncTop = "GAUS2" elif nLept == 1: treeName = "WCR" signName = "XWh" colorVjet = sample["WJetsToLNu"]["linecolor"] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isWtoEN" if nElec > 0 else "isWtoMN" topVeto = selection["TopVetocut"] massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXPTAIL" if nBtag < 2 else "EXPN" fitAltFunc = "EXPN" if nBtag < 2 else "POW" else: fitFunc = "EXPN" if nBtag < 2 else "EXPN" fitAltFunc = "EXPTAIL" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitAltFuncVjet = "POL" if nBtag < 2 else "POL" fitFuncVV = "EXPGAUS" if nBtag < 2 else "EXPGAUS" fitFuncTop = "GAUS3" if nBtag < 2 else "GAUS2" else: treeName = "XZh" signName = "XZh" colorVjet = sample["DYJetsToLL"]["linecolor"] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isZtoEE" if nElec > 0 else "isZtoMM" topVeto = "X_dPhi>2.5" massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitAltFunc = "POW" if nBtag < 2 else "POW" else: fitFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitAltFunc = "POW" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 and nElec < 1 else "EXP" fitAltFuncVjet = "POL" if nBtag < 2 else "POL" fitFuncVV = "EXPGAUS2" if nBtag < 2 else "EXPGAUS2" fitFuncTop = "GAUS" btagCut = selection["2Btag"] if nBtag == 2 else selection["1Btag"] print "--- Channel", channel, "---" print " number of electrons:", nElec, " muons:", nMuon, " b-tags:", nBtag print " read tree:", treeName, "and trigger:", triName if ALTERNATIVE: print " using ALTERNATIVE fit functions" print "-" * 11 * 2 # Silent RooFit RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) # *******************************************************# # # # Variables and selections # # # # *******************************************************# # Define all the variables from the trees that will be used in the cuts and fits # this steps actually perform a "projection" of the entire tree on the variables in thei ranges, so be careful once setting the limits X_mass = RooRealVar(massVar, "m_{X}" if nLept > 0 else "m_{T}^{X}", XBINMIN, XBINMAX, "GeV") J_mass = RooRealVar("fatjet1_prunedMassCorr", "jet corrected pruned mass", HBINMIN, HBINMAX, "GeV") CSV1 = RooRealVar("fatjet1_CSVR1", "", -1.0e99, 1.0e4) CSV2 = RooRealVar("fatjet1_CSVR2", "", -1.0e99, 1.0e4) nB = RooRealVar("fatjet1_nBtag", "", 0.0, 4) CSVTop = RooRealVar("bjet1_CSVR", "", -1.0e99, 1.0e4) X_dPhi = RooRealVar("X_dPhi", "", 0.0, 3.15) isZtoEE = RooRealVar("isZtoEE", "", 0.0, 2) isZtoMM = RooRealVar("isZtoMM", "", 0.0, 2) isWtoEN = RooRealVar("isWtoEN", "", 0.0, 2) isWtoMN = RooRealVar("isWtoMN", "", 0.0, 2) weight = RooRealVar("eventWeightLumi", "", -1.0e9, 1.0) # Define the RooArgSet which will include all the variables defined before # there is a maximum of 9 variables in the declaration, so the others need to be added with 'add' variables = RooArgSet(X_mass, J_mass, CSV1, CSV2, nB, CSVTop, X_dPhi) variables.add(RooArgSet(isZtoEE, isZtoMM, isWtoEN, isWtoMN, weight)) # set reasonable ranges for J_mass and X_mass # these are used in the fit in order to avoid ROOFIT to look in regions very far away from where we are fitting # (honestly, it is not clear to me why it is necessary, but without them the fit often explodes) J_mass.setRange("h_reasonable_range", LOWMIN, HIGMAX) X_mass.setRange("X_reasonable_range", XBINMIN, XBINMAX) # Set RooArgSets once for all, see https://root.cern.ch/phpBB3/viewtopic.php?t=11758 jetMassArg = RooArgSet(J_mass) # Define the ranges in fatJetMass - these will be used to define SB and SR J_mass.setRange("LSBrange", LOWMIN, LOWMAX) J_mass.setRange("HSBrange", HIGMIN, HIGMAX) J_mass.setRange("VRrange", LOWMAX, SIGMIN) J_mass.setRange("SRrange", SIGMIN, SIGMAX) # Set binning for plots J_mass.setBins(HBINS) X_mass.setBins(binFact * XBINS) # Define the selection for the various categories (base + SR / LSBcut / HSBcut ) baseCut = leptCut + " && " + btagCut + "&&" + topVeto massCut = massVar + ">%d" % XBINMIN baseCut += " && " + massCut # Cuts SRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), SIGMIN, J_mass.GetName(), SIGMAX) LSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX) HSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) SBcut = baseCut + " && ((%s>%d && %s<%d) || (%s>%d && %s<%d))" % ( J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX, J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX, ) VRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMAX, J_mass.GetName(), SIGMIN) # Binning binsJmass = RooBinning(HBINS, HBINMIN, HBINMAX) # binsJmass.addUniform(HBINS, HBINMIN, HBINMAX) binsXmass = RooBinning(binFact * XBINS, XBINMIN, XBINMAX) # binsXmass.addUniform(binFact*XBINS, XBINMIN, XBINMAX) # *******************************************************# # # # Input files # # # # *******************************************************# # Import the files using TChains (separately for the bkg "classes" that we want to describe: here DY and VV+ST+TT) treeData = TChain(treeName) treeMC = TChain(treeName) treeVjet = TChain(treeName) treeVV = TChain(treeName) treeTop = TChain(treeName) treeSign = {} nevtSign = {} for i, m in enumerate(massPoints): treeSign[m] = TChain(treeName) # Read data pd = getPrimaryDataset(triName) if len(pd) == 0: raw_input("Warning: Primary Dataset not recognized, continue?") for i, s in enumerate(pd): treeData.Add(NTUPLEDIR + s + ".root") # Read V+jets backgrounds for i, s in enumerate(["WJetsToLNu_HT", "DYJetsToNuNu_HT", "DYJetsToLL_HT"]): for j, ss in enumerate(sample[s]["files"]): treeVjet.Add(NTUPLEDIR + ss + ".root") # Read VV backgrounds for i, s in enumerate(["VV"]): for j, ss in enumerate(sample[s]["files"]): treeVV.Add(NTUPLEDIR + ss + ".root") # Read Top backgrounds for i, s in enumerate(["ST", "TTbar"]): for j, ss in enumerate(sample[s]["files"]): treeTop.Add(NTUPLEDIR + ss + ".root") # Read signals for i, m in enumerate(massPoints): for j, ss in enumerate(sample["%s_M%d" % (signName, m)]["files"]): treeSign[m].Add(NTUPLEDIR + ss + ".root") sfile = TFile(NTUPLEDIR + ss + ".root", "READ") shist = sfile.Get("Counters/Counter") nevtSign[m] = shist.GetBinContent(1) sfile.Close() # Sum all background MC treeMC.Add(treeVjet) treeMC.Add(treeVV) treeMC.Add(treeTop) # create a dataset to host data in sideband (using this dataset we are automatically blind in the SR!) setDataSB = RooDataSet( "setDataSB", "setDataSB", variables, RooFit.Cut(SBcut), RooFit.WeightVar(weight), RooFit.Import(treeData) ) setDataLSB = RooDataSet( "setDataLSB", "setDataLSB", variables, RooFit.Import(setDataSB), RooFit.Cut(LSBcut), RooFit.WeightVar(weight) ) setDataHSB = RooDataSet( "setDataHSB", "setDataHSB", variables, RooFit.Import(setDataSB), RooFit.Cut(HSBcut), RooFit.WeightVar(weight) ) # Observed data (WARNING, BLIND!) setDataSR = RooDataSet( "setDataSR", "setDataSR", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeData) ) setDataVR = RooDataSet( "setDataVR", "setDataVR", variables, RooFit.Cut(VRcut), RooFit.WeightVar(weight), RooFit.Import(treeData) ) # Observed in the VV mass, just for plotting purposes setDataSRSB = RooDataSet( "setDataSRSB", "setDataSRSB", variables, RooFit.Cut("(" + SRcut + ") || (" + SBcut + ")"), RooFit.WeightVar(weight), RooFit.Import(treeData), ) # same for the bkg datasets from MC, where we just apply the base selections (not blind) setVjet = RooDataSet( "setVjet", "setVjet", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVjet) ) setVjetSB = RooDataSet( "setVjetSB", "setVjetSB", variables, RooFit.Import(setVjet), RooFit.Cut(SBcut), RooFit.WeightVar(weight) ) setVjetSR = RooDataSet( "setVjetSR", "setVjetSR", variables, RooFit.Import(setVjet), RooFit.Cut(SRcut), RooFit.WeightVar(weight) ) setVV = RooDataSet( "setVV", "setVV", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVV) ) setVVSB = RooDataSet( "setVVSB", "setVVSB", variables, RooFit.Import(setVV), RooFit.Cut(SBcut), RooFit.WeightVar(weight) ) setVVSR = RooDataSet( "setVVSR", "setVVSR", variables, RooFit.Import(setVV), RooFit.Cut(SRcut), RooFit.WeightVar(weight) ) setTop = RooDataSet( "setTop", "setTop", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeTop) ) setTopSB = RooDataSet( "setTopSB", "setTopSB", variables, RooFit.Import(setTop), RooFit.Cut(SBcut), RooFit.WeightVar(weight) ) setTopSR = RooDataSet( "setTopSR", "setTopSR", variables, RooFit.Import(setTop), RooFit.Cut(SRcut), RooFit.WeightVar(weight) ) print " Data events SB: %.2f" % setDataSB.sumEntries() print " V+jets entries: %.2f" % setVjet.sumEntries() print " VV, VH entries: %.2f" % setVV.sumEntries() print " Top,ST entries: %.2f" % setTop.sumEntries() nVV = RooRealVar("nVV", "VV normalization", setVV.sumEntries(SBcut), 0.0, 2 * setVV.sumEntries(SBcut)) nTop = RooRealVar("nTop", "Top normalization", setTop.sumEntries(SBcut), 0.0, 2 * setTop.sumEntries(SBcut)) nVjet = RooRealVar("nVjet", "Vjet normalization", setDataSB.sumEntries(), 0.0, 2 * setDataSB.sumEntries(SBcut)) nVjet2 = RooRealVar("nVjet2", "Vjet2 normalization", setDataSB.sumEntries(), 0.0, 2 * setDataSB.sumEntries(SBcut)) # Apply Top SF nTop.setVal(nTop.getVal() * topSF[nLept][nBtag]) nTop.setError(nTop.getVal() * topSFErr[nLept][nBtag]) # Define entries entryVjet = RooRealVar("entryVjets", "V+jets normalization", setVjet.sumEntries(), 0.0, 1.0e6) entryVV = RooRealVar("entryVV", "VV normalization", setVV.sumEntries(), 0.0, 1.0e6) entryTop = RooRealVar("entryTop", "Top normalization", setTop.sumEntries(), 0.0, 1.0e6) entrySB = RooRealVar("entrySB", "Data SB normalization", setDataSB.sumEntries(SBcut), 0.0, 1.0e6) entrySB.setError(math.sqrt(entrySB.getVal())) entryLSB = RooRealVar("entryLSB", "Data LSB normalization", setDataSB.sumEntries(LSBcut), 0.0, 1.0e6) entryLSB.setError(math.sqrt(entryLSB.getVal())) entryHSB = RooRealVar("entryHSB", "Data HSB normalization", setDataSB.sumEntries(HSBcut), 0.0, 1.0e6) entryHSB.setError(math.sqrt(entryHSB.getVal())) ################################################################################### # _ _ # # | \ | | | (_) | | (_) # # | \| | ___ _ __ _ __ ___ __ _| |_ ___ __ _| |_ _ ___ _ __ # # | . ` |/ _ \| '__| '_ ` _ \ / _` | | / __|/ _` | __| |/ _ \| '_ \ # # | |\ | (_) | | | | | | | | (_| | | \__ \ (_| | |_| | (_) | | | | # # |_| \_|\___/|_| |_| |_| |_|\__,_|_|_|___/\__,_|\__|_|\___/|_| |_| # # # ################################################################################### # fancy ASCII art thanks to, I guess, Jose # start by creating the fit models to get the normalization: # * MAIN and SECONDARY bkg are taken from MC by fitting the whole J_mass range # * The two PDFs are added together using the relative normalizations of the two bkg from MC # * DATA is then fit in the sidebands only using the combined bkg PDF # * The results of the fit are then estrapolated in the SR and the integral is evaluated. # * This defines the bkg normalization in the SR # *******************************************************# # # # V+jets normalization # # # # *******************************************************# # Variables for V+jets constVjet = RooRealVar("constVjet", "slope of the exp", -0.020, -1.0, 0.0) offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 30.0, -50.0, 400.0) widthVjet = RooRealVar("widthVjet", "width of the erf", 100.0, 1.0, 200.0) # 0, 400 a0Vjet = RooRealVar("a0Vjet", "width of the erf", -0.1, -5, 0) a1Vjet = RooRealVar("a1Vjet", "width of the erf", 0.6, 0, 5) a2Vjet = RooRealVar("a2Vjet", "width of the erf", -0.1, -1, 1) if channel == "XZhnnb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 500.0, 200.0, 1000.0) if channel == "XZhnnbb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 350.0, 200.0, 500.0) # if channel == "XWhenb" or channel == "XZheeb": # offsetVjet.setVal(120.) # offsetVjet.setConstant(True) if channel == "XWhenb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 120.0, 80.0, 155.0) if channel == "XWhenbb" or channel == "XZhmmb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 67.0, 50.0, 100.0) if channel == "XWhmnb": offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 30.0, -50.0, 600.0) if channel == "XZheeb": offsetVjet.setMin(-400) offsetVjet.setVal(0.0) offsetVjet.setMax(1000) widthVjet.setVal(1.0) # Define V+jets model if fitFuncVjet == "ERFEXP": VjetMass = RooErfExpPdf("VjetMass", fitFuncVjet, J_mass, constVjet, offsetVjet, widthVjet) elif fitFuncVjet == "EXP": VjetMass = RooExponential("VjetMass", fitFuncVjet, J_mass, constVjet) elif fitFuncVjet == "GAUS": VjetMass = RooGaussian("VjetMass", fitFuncVjet, J_mass, offsetVjet, widthVjet) elif fitFuncVjet == "POL": VjetMass = RooChebychev("VjetMass", fitFuncVjet, J_mass, RooArgList(a0Vjet, a1Vjet, a2Vjet)) elif fitFuncVjet == "POW": VjetMass = RooGenericPdf("VjetMass", fitFuncVjet, "@0^@1", RooArgList(J_mass, a0Vjet)) else: print " ERROR! Pdf", fitFuncVjet, "is not implemented for Vjets" exit() if fitAltFuncVjet == "POL": VjetMass2 = RooChebychev("VjetMass2", "polynomial for V+jets mass", J_mass, RooArgList(a0Vjet, a1Vjet, a2Vjet)) else: print " ERROR! Pdf", fitAltFuncVjet, "is not implemented for Vjets" exit() # fit to main bkg in MC (whole range) frVjet = VjetMass.fitTo( setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) frVjet2 = VjetMass2.fitTo( setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS Vjets] *" + "*" * 40, "\n", frVjet.Print(), "\n", "*" * 80 # likelihoodScan(VjetMass, setVjet, [constVjet, offsetVjet, widthVjet]) # *******************************************************# # # # VV, VH normalization # # # # *******************************************************# # Variables for VV # Error function and exponential to model the bulk constVV = RooRealVar("constVV", "slope of the exp", -0.030, -0.1, 0.0) offsetVV = RooRealVar("offsetVV", "offset of the erf", 90.0, 1.0, 300.0) widthVV = RooRealVar("widthVV", "width of the erf", 50.0, 1.0, 100.0) erfrVV = RooErfExpPdf("baseVV", "error function for VV jet mass", J_mass, constVV, offsetVV, widthVV) expoVV = RooExponential("baseVV", "error function for VV jet mass", J_mass, constVV) # gaussian for the V mass peak meanVV = RooRealVar("meanVV", "mean of the gaussian", 90.0, 60.0, 100.0) sigmaVV = RooRealVar("sigmaVV", "sigma of the gaussian", 10.0, 6.0, 30.0) fracVV = RooRealVar("fracVV", "fraction of gaussian wrt erfexp", 3.2e-1, 0.0, 1.0) gausVV = RooGaussian("gausVV", "gaus for VV jet mass", J_mass, meanVV, sigmaVV) # gaussian for the H mass peak meanVH = RooRealVar("meanVH", "mean of the gaussian", 125.0, 100.0, 150.0) sigmaVH = RooRealVar("sigmaVH", "sigma of the gaussian", 10.0, 5.0, 50.0) fracVH = RooRealVar("fracVH", "fraction of gaussian wrt erfexp", 1.5e-2, 0.0, 1.0) gausVH = RooGaussian("gausVH", "gaus for VH jet mass", J_mass, meanVH, sigmaVH) # Define VV model if fitFuncVV == "ERFEXPGAUS": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVV, erfrVV), RooArgList(fracVV)) elif fitFuncVV == "ERFEXPGAUS2": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVH, gausVV, erfrVV), RooArgList(fracVH, fracVV)) elif fitFuncVV == "EXPGAUS": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVV, expoVV), RooArgList(fracVV)) elif fitFuncVV == "EXPGAUS2": VVMass = RooAddPdf("VVMass", fitFuncVV, RooArgList(gausVH, gausVV, expoVV), RooArgList(fracVH, fracVV)) else: print " ERROR! Pdf", fitFuncVV, "is not implemented for VV" exit() # fit to secondary bkg in MC (whole range) frVV = VVMass.fitTo( setVV, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS VV] ****" + "*" * 40, "\n", frVV.Print(), "\n", "*" * 80 # *******************************************************# # # # Top, ST normalization # # # # *******************************************************# # Variables for Top # Error Function * Exponential to model the bulk constTop = RooRealVar("constTop", "slope of the exp", -0.030, -1.0, 0.0) offsetTop = RooRealVar("offsetTop", "offset of the erf", 175.0, 50.0, 250.0) widthTop = RooRealVar("widthTop", "width of the erf", 100.0, 1.0, 300.0) gausTop = RooGaussian("baseTop", "gaus for Top jet mass", J_mass, offsetTop, widthTop) erfrTop = RooErfExpPdf("baseTop", "error function for Top jet mass", J_mass, constTop, offsetTop, widthTop) # gaussian for the W mass peak meanW = RooRealVar("meanW", "mean of the gaussian", 80.0, 70.0, 90.0) sigmaW = RooRealVar("sigmaW", "sigma of the gaussian", 10.0, 2.0, 20.0) fracW = RooRealVar("fracW", "fraction of gaussian wrt erfexp", 0.1, 0.0, 1.0) gausW = RooGaussian("gausW", "gaus for W jet mass", J_mass, meanW, sigmaW) # gaussian for the Top mass peak meanT = RooRealVar("meanT", "mean of the gaussian", 175.0, 150.0, 200.0) sigmaT = RooRealVar("sigmaT", "sigma of the gaussian", 12.0, 5.0, 30.0) fracT = RooRealVar("fracT", "fraction of gaussian wrt erfexp", 0.1, 0.0, 1.0) gausT = RooGaussian("gausT", "gaus for T jet mass", J_mass, meanT, sigmaT) if channel == "XZheeb" or channel == "XZheebb" or channel == "XZhmmb" or channel == "XZhmmbb": offsetTop = RooRealVar("offsetTop", "offset of the erf", 200.0, -50.0, 450.0) widthTop = RooRealVar("widthTop", "width of the erf", 100.0, 1.0, 1000.0) # Define Top model if fitFuncTop == "ERFEXPGAUS2": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausW, gausT, erfrTop), RooArgList(fracW, fracT)) elif fitFuncTop == "ERFEXPGAUS": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausT, erfrTop), RooArgList(fracT)) elif fitFuncTop == "GAUS3": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausW, gausT, gausTop), RooArgList(fracW, fracT)) elif fitFuncTop == "GAUS2": TopMass = RooAddPdf("TopMass", fitFuncTop, RooArgList(gausT, gausTop), RooArgList(fracT)) elif fitFuncTop == "GAUS": TopMass = RooGaussian("TopMass", fitFuncTop, J_mass, offsetTop, widthTop) else: print " ERROR! Pdf", fitFuncTop, "is not implemented for Top" exit() # fit to secondary bkg in MC (whole range) frTop = TopMass.fitTo( setTop, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS TOP] ***" + "*" * 40, "\n", frTop.Print(), "\n", "*" * 80 # likelihoodScan(TopMass, setTop, [offsetTop, widthTop]) # *******************************************************# # # # All bkg normalization # # # # *******************************************************# # nVjet.setConstant(False) # nVjet2.setConstant(False) # # constVjet.setConstant(False) # offsetVjet.setConstant(False) # widthVjet.setConstant(False) # a0Vjet.setConstant(False) # a1Vjet.setConstant(False) # a2Vjet.setConstant(False) constVV.setConstant(True) offsetVV.setConstant(True) widthVV.setConstant(True) meanVV.setConstant(True) sigmaVV.setConstant(True) fracVV.setConstant(True) meanVH.setConstant(True) sigmaVH.setConstant(True) fracVH.setConstant(True) constTop.setConstant(True) offsetTop.setConstant(True) widthTop.setConstant(True) meanW.setConstant(True) sigmaW.setConstant(True) fracW.setConstant(True) meanT.setConstant(True) sigmaT.setConstant(True) fracT.setConstant(True) nVV.setConstant(True) nTop.setConstant(True) nVjet.setConstant(False) nVjet2.setConstant(False) # Final background model by adding the main+secondary pdfs (using 'coef': ratio of the secondary/main, from MC) TopMass_ext = RooExtendPdf("TopMass_ext", "extended p.d.f", TopMass, nTop) VVMass_ext = RooExtendPdf("VVMass_ext", "extended p.d.f", VVMass, nVV) VjetMass_ext = RooExtendPdf("VjetMass_ext", "extended p.d.f", VjetMass, nVjet) VjetMass2_ext = RooExtendPdf("VjetMass_ext", "extended p.d.f", VjetMass, nVjet2) BkgMass = RooAddPdf( "BkgMass", "BkgMass", RooArgList(TopMass_ext, VVMass_ext, VjetMass_ext), RooArgList(nTop, nVV, nVjet) ) BkgMass2 = RooAddPdf( "BkgMass2", "BkgMass2", RooArgList(TopMass_ext, VVMass_ext, VjetMass2_ext), RooArgList(nTop, nVV, nVjet2) ) BkgMass.fixAddCoefRange("h_reasonable_range") BkgMass2.fixAddCoefRange("h_reasonable_range") # Extended fit model to data in SB frMass = BkgMass.fitTo( setDataSB, RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) # , RooFit.NumCPU(10) if VERBOSE: print "********** Fit result [JET MASS DATA] **" + "*" * 40, "\n", frMass.Print(), "\n", "*" * 80 frMass2 = BkgMass2.fitTo( setDataSB, RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1), ) if VERBOSE: print "********** Fit result [JET MASS DATA] **" + "*" * 40, "\n", frMass2.Print(), "\n", "*" * 80 # if SCAN: # likelihoodScan(VjetMass, setVjet, [constVjet, offsetVjet, widthVjet]) # Fix normalization and parameters of V+jets after the fit to data nVjet.setConstant(True) nVjet2.setConstant(True) constVjet.setConstant(True) offsetVjet.setConstant(True) widthVjet.setConstant(True) a0Vjet.setConstant(True) a1Vjet.setConstant(True) a2Vjet.setConstant(True) # integrals for global normalization # do not integrate the composte model: results have no sense # integral for normalization in the SB iSBVjet = VjetMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iSBVV = VVMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iSBTop = TopMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) # integral for normalization in the SR iSRVjet = VjetMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iSRVV = VVMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iSRTop = TopMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) # integral for normalization in the VR iVRVjet = VjetMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) iVRVV = VVMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) iVRTop = TopMass.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # formual vars SByield = RooFormulaVar( "SByield", "extrapolation to SR", "@0*@1 + @2*@3 + @4*@5", RooArgList(iSBVjet, nVjet, iSBVV, nVV, iSBTop, nTop) ) VRyield = RooFormulaVar( "VRyield", "extrapolation to VR", "@0*@1 + @2*@3 + @4*@5", RooArgList(iVRVjet, nVjet, iVRVV, nVV, iVRTop, nTop) ) SRyield = RooFormulaVar( "SRyield", "extrapolation to SR", "@0*@1 + @2*@3 + @4*@5", RooArgList(iSRVjet, nVjet, iSRVV, nVV, iSRTop, nTop) ) # fractions fSBVjet = RooRealVar( "fVjet", "Fraction of Vjet events in SB", iSBVjet.getVal() * nVjet.getVal() / SByield.getVal(), 0.0, 1.0 ) fSBVV = RooRealVar( "fSBVV", "Fraction of VV events in SB", iSBVV.getVal() * nVV.getVal() / SByield.getVal(), 0.0, 1.0 ) fSBTop = RooRealVar( "fSBTop", "Fraction of Top events in SB", iSBTop.getVal() * nTop.getVal() / SByield.getVal(), 0.0, 1.0 ) fSRVjet = RooRealVar( "fSRVjet", "Fraction of Vjet events in SR", iSRVjet.getVal() * nVjet.getVal() / SRyield.getVal(), 0.0, 1.0 ) fSRVV = RooRealVar( "fSRVV", "Fraction of VV events in SR", iSRVV.getVal() * nVV.getVal() / SRyield.getVal(), 0.0, 1.0 ) fSRTop = RooRealVar( "fSRTop", "Fraction of Top events in SR", iSRTop.getVal() * nTop.getVal() / SRyield.getVal(), 0.0, 1.0 ) # final normalization values bkgYield = SRyield.getVal() bkgYield2 = ( (VjetMass2.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange"))).getVal() * nVjet2.getVal() + iSRVV.getVal() * nVV.getVal() + iSRTop.getVal() * nTop.getVal() ) bkgYield_syst = math.sqrt(SRyield.getPropagatedError(frVV) ** 2 + SRyield.getPropagatedError(frTop) ** 2) bkgYield_stat = math.sqrt(SRyield.getPropagatedError(frMass) ** 2) bkgYield_alte = abs(bkgYield - bkgYield2) # /bkgYield bkgYield_eig_norm = RooRealVar("predSR_eig_norm", "expected yield in SR", bkgYield, 0.0, 1.0e6) print "Events in channel", channel, ": V+jets %.3f (%.1f%%), VV %.3f (%.1f%%), Top %.3f (%.1f%%)" % ( iSRVjet.getVal() * nVjet.getVal(), fSRVjet.getVal() * 100, iSRVV.getVal() * nVV.getVal(), fSRVV.getVal() * 100, iSRTop.getVal() * nTop.getVal(), fSRTop.getVal() * 100, ) print "Events in channel", channel, ": Integral = $%.3f$ & $\pm %.3f$ & $\pm %.3f$ & $\pm %.3f$, observed = %.0f" % ( bkgYield, bkgYield_stat, bkgYield_syst, bkgYield_alte, setDataSR.sumEntries() if not False else -1, )
"""controls RooFit output messages Defines RooFit output streams and topics for P2VV """ import P2VV.RooFitDecorators print "P2VV - INFO: RooFitOutput: setting RooFit output streams" from ROOT import RooFit, RooMsgService # get message service instance msgServ = RooMsgService.instance() # remove plotting streams with "INFO" as a minimum level for stream in msgServ : # if stream.minLevel == RooFit.INFO : stream -= RooFit.Minimization if stream.minLevel <= RooFit.PROGRESS : stream -= RooFit.Plotting stream -= RooFit.Caching stream -= RooFit.Eval
help='use keys pdf for background') parser.add_option('-b', action='store_true', default=False, dest='b', help='no x windows') (opts, args) = parser.parse_args() import pyroot_logon from ROOT import gROOT gROOT.ProcessLine('.L buildSimPdf.cc+') from ROOT import readData,computeRatio,computeRatioError,buildPdf,\ computeSumError,\ RooWorkspace,RooFit,TCanvas,kRed,kGreen,kDashed,buildSimPdf,RooArgSet,\ RooRealVar,RooMsgService, TMath, TFile, RooAbsReal from math import sqrt RooMsgService.instance().setGlobalKillBelow(RooFit.ERROR) hidatafile = 'data/dimuonTree_150mub.root' ppdatafile = 'data/dimuonTree_2011_pp.root' mmin = 7. mmax = 14. cuts = '(muPlusPt > %0.1f) && (muMinusPt > %0.1f) && (abs(upsRapidity)<2.4) && (vProb > 0.05)' \ % (opts.pt, opts.pt) simparamfile = opts.paramfile useKeys = opts.keys ## cuts = '(muPlusPt > 3.5) && (muMinusPt > 3.5) && (abs(upsRapidity)<2.4)' ## simparamfile = 'nom3.5SimFit.txt'
def bayesian(self, ws, debug=0): if self.sBayes not in self.items: if debug > 0: print self.legend, 'no Bayesian Calculator section in the config file' print self.legend, 'cannot configure Bayesian calculator' return {'status': 'fail'} legend = '[' + self.sBayes + ']:' _name = 'exostBayes' # getting items as a dictionary bayes_items = {} bayes_items.update(self.items[self.sBayes]) print legend, 'Configuring Bayesian calculator... ' # check if a CL is specified m_conf_name = self.check_value(self.sBayes, 'model_config') if m_conf_name == -1: print legend, 'Error: model config is not specified' print legend, 'Error:', self.sBayes, 'cannot be configured' return {'status': 'fail'} # check if data is specified data_name = self.check_value(self.sBayes, 'data') data_valid = False if data_name != -1: data_valid = True if ws.data(data_name) != None: data = ws.data(data_name) else: data_valid = False print legend, 'Error: dataset', data_name, 'is not defined' if data_valid == False: print legend, 'Error:', self.sBayes, 'cannot be configured' return {'status': 'fail'} # check if a CL is specified conf_level = self.check_value(self.sBayes, 'confidence_level') if conf_level == -1: print legend, 'Warning: desired confidence level is not specified, setting to 0.90' conf_level = 0.90 # check if a posterior plot is requested post_plot = self.check_value(self.sBayes, 'posterior_plot') b_post_plot = False if post_plot == -1: print legend, 'will generate a posterior plot' b_post_plot = True elif post_plot == 'True': b_post_plot = True else: b_post_plot = False # plot format if post_plot: plot_format = self.check_value(self.sBayes, 'plot_format') if plot_format == -1: plot_format = 'png' # to suppress messgaes when pdf goes to zero RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) #mconf = ws.obj('exostModelConfig') mconf = ws.obj(m_conf_name) if mconf == None: if debug > 0: print self.legend, 'fail to get Model Config' print self.legend, 'unable to configure Bayesian calculator' print self.legend, 'calculator will not be imported into the workspace' return {'status': 'fail'} bCalc = RooStats.BayesianCalculator(data, mconf) bCalc.SetConfidenceLevel(float(conf_level)) ############# FIXME: debug test #bInt = bCalc.GetInterval() #print legend, 'DEBUG3*******************************' # #cl = bCalc.ConfidenceLevel() #print legend, str(cl)+'% CL central interval: [', bInt.LowerLimit(), ' - ', bInt.UpperLimit(), ']' #print legend, 'or', str(cl+(1.0-cl)/2), '% CL limits' ############################## #size = 1.0 - float(conf_level) #bCalc.SetTestSize(size) # import the calculator into the Workspace getattr(ws, 'import')(bCalc, _name) print legend, 'Bayesian calculator', _name, 'is configured and added to workspace', ws.GetName( ) print legend, 'done' return { 'do_posterior_plot': b_post_plot, 'status': 'success', 'model_config_name': m_conf_name, 'plot_format': plot_format }
def bayesian(self, ws, debug = 0): if self.sBayes not in self.items: if debug>0: print self.legend, 'no Bayesian Calculator section in the config file' print self.legend, 'cannot configure Bayesian calculator' return {'status':'fail'} legend = '['+self.sBayes+']:' _name = 'exostBayes' # getting items as a dictionary bayes_items = {} bayes_items.update(self.items[self.sBayes]) print legend, 'Configuring Bayesian calculator... ' # check if a CL is specified m_conf_name = self.check_value(self.sBayes, 'model_config') if m_conf_name == -1: print legend, 'Error: model config is not specified' print legend, 'Error:', self.sBayes, 'cannot be configured' return {'status':'fail'} # check if data is specified data_name = self.check_value(self.sBayes, 'data') data_valid = False if data_name != -1: data_valid = True if ws.data(data_name) != None: data = ws.data(data_name) else: data_valid = False print legend, 'Error: dataset', data_name, 'is not defined' if data_valid == False: print legend, 'Error:', self.sBayes, 'cannot be configured' return {'status':'fail'} # check if a CL is specified conf_level = self.check_value(self.sBayes, 'confidence_level') if conf_level == -1: print legend, 'Warning: desired confidence level is not specified, setting to 0.90' conf_level = 0.90 # check if a posterior plot is requested post_plot = self.check_value(self.sBayes, 'posterior_plot') b_post_plot = False if post_plot == -1: print legend, 'will generate a posterior plot' b_post_plot = True elif post_plot == 'True': b_post_plot = True else: b_post_plot = False # plot format if post_plot: plot_format = self.check_value(self.sBayes, 'plot_format') if plot_format == -1: plot_format = 'png' # to suppress messgaes when pdf goes to zero RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) #mconf = ws.obj('exostModelConfig') mconf = ws.obj(m_conf_name) if mconf == None: if debug > 0: print self.legend, 'fail to get Model Config' print self.legend, 'unable to configure Bayesian calculator' print self.legend, 'calculator will not be imported into the workspace' return {'status':'fail'} bCalc = RooStats.BayesianCalculator(data, mconf) bCalc.SetConfidenceLevel(float(conf_level)) ############# FIXME: debug test #bInt = bCalc.GetInterval() #print legend, 'DEBUG3*******************************' # #cl = bCalc.ConfidenceLevel() #print legend, str(cl)+'% CL central interval: [', bInt.LowerLimit(), ' - ', bInt.UpperLimit(), ']' #print legend, 'or', str(cl+(1.0-cl)/2), '% CL limits' ############################## #size = 1.0 - float(conf_level) #bCalc.SetTestSize(size) # import the calculator into the Workspace getattr(ws, 'import')(bCalc, _name) print legend, 'Bayesian calculator', _name, 'is configured and added to workspace', ws.GetName() print legend, 'done' return {'do_posterior_plot':b_post_plot, 'status':'success', 'model_config_name':m_conf_name, 'plot_format':plot_format}
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2" # input parameters parser = ArgumentParser( description= 'Script that creates combine datacards and corresponding RooFit workspaces', epilog=usage) parser.add_argument("analysis", type=str, help="Analysis name") parser.add_argument("model", type=str, help="Model (Hbb, RSG)") #parser.add_argument("--inputData", dest="inputData", required=True, # help="Input data spectrum", # metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", type=str, default="h_data", help="Data histogram name", metavar="DATA_HISTNAME") #parser.add_argument("--inputSig", dest="inputSig", required=True, # help="Input signal shapes", # metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", default="qq", help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("--fit_functions", dest="fit_functions", default="f1,f2,f3,f4,f5", help="List of fit functions") #parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)") parser.add_argument( "-o", "--output_path", dest="output_path", help= "Output path where datacards and workspaces will be stored. If not specified, this is derived from limit_configuration.", metavar="OUTPUT_PATH") parser.add_argument("--correctTrigger", dest="correctTrigger", action='store_true', help="Include trigger correction in PDF") parser.add_argument( "-l", "--lumi", dest="lumi", default=19700., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument( "--massMin", dest="massMin", default=500, type=int, help= "Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument( "--massMax", dest="massMax", default=1200, type=int, help= "Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument( "--fitSignal", action="store_true", help= "Use signal fitted shapes (CB+Voigtian) instead of histogram templates" ) #parser.add_argument("--lumiUnc", dest="lumiUnc", # required=True, type=float, # help="Relative uncertainty in the integrated luminosity", # metavar="LUMI_UNC") #parser.add_argument("--jesUnc", dest="jesUnc", # type=float, # help="Relative uncertainty in the jet energy scale", # metavar="JES_UNC") #parser.add_argument("--jerUnc", dest="jerUnc", # type=float, # help="Relative uncertainty in the jet energy resolution", # metavar="JER_UNC") parser.add_argument( "--sqrtS", dest="sqrtS", default=8000., type=float, help="Collision center-of-mass energy (default: %(default).1f)", metavar="SQRTS") parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters") parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") parser.add_argument( "--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)") parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots") parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots") parser.add_argument( "--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)") parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared") parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument( "--mass", type=int, nargs='*', default=1000, help= "Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument( "--massrange", type=int, nargs=3, help="Define a range of masses to be produced. Format: min max step", metavar=('MIN', 'MAX', 'STEP')) mass_group.add_argument("--masslist", help="List containing mass information") args = parser.parse_args() fit_functions = args.fit_functions.split(",") # mass points for which resonance shapes will be produced masses = [] if args.fitBonly: masses.append(750) else: if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX + STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py", "")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooProdPdf, RooEffProd, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0, kFALSE) RooMsgService.instance().setStreamStatus(1, kFALSE) # input data file #inputData = TFile(limit_config.get_data_input(args.analysis)) # input data histogram #hData = inputData.Get(args.dataHistname) #hData.SetDirectory(0) data_file = TFile( analysis_config.get_b_histogram_filename(args.analysis, "BJetPlusX_2012")) hData = data_file.Get("BHistograms/h_pfjet_mjj") hData.SetDirectory(0) # input sig file if not args.fitSignal: print "[create_datacards] INFO : Opening resonance shapes file at " + limit_config.get_resonance_shapes( args.analysis, args.model) inputSig = TFile( limit_config.get_resonance_shapes(args.analysis, args.model), "READ") sqrtS = args.sqrtS # mass variable mjj = RooRealVar('mjj', 'mjj', float(args.massMin), float(args.massMax)) # integrated luminosity and signal cross section lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section if args.correctTrigger: trigger_efficiency_pdf = trigger_efficiency.get_pdf(args.analysis, mjj) trigger_efficiency_formula = trigger_efficiency.get_formula( args.analysis, mjj) else: trigger_efficiency_pdf = trigger_efficiency.get_trivial_pdf(mjj) trigger_efficiency_formula = trigger_efficiency.get_trivial_formula( mjj) for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..." % ( args.final_state, int(mass)) rooDataHist = RooDataHist('rooDatahist', 'rooDathist', RooArgList(mjj), hData) if not args.fitSignal: hSig = inputSig.Get("h_" + args.final_state + "_" + str(int(mass))) if not hSig: raise Exception("Couldn't find histogram " + "h_" + args.final_state + "_" + str(int(mass)) + " in file " + limit_config.get_resonance_shapes( args.analysis, args.model)) # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity) hSig.Scale( signalCrossSection * lumi / hSig.Integral() ) # divide by a number that provides roughly an r value of 1-10 rooSigHist = RooDataHist('rooSigHist', 'rooSigHist', RooArgList(mjj), hSig) print 'Signal acceptance:', (rooSigHist.sumEntries() / hSig.Integral()) # If using fitted signal shapes, load the signal PDF if args.fitSignal: print "[create_datacards] Loading fitted signal PDFs from " + analysis_config.get_signal_fit_file( args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)) f_signal_pdfs = TFile( analysis_config.get_signal_fit_file( args.analysis, args.model, mass, "bukin", interpolated=( not mass in analysis_config.simulation.simulated_masses)), "READ") w_signal = f_signal_pdfs.Get("w_signal") input_parameters = signal_fits.get_parameters( w_signal.pdf("signal")) # Make a new PDF with nuisance parameters signal_pdf_notrig, signal_vars = signal_fits.make_signal_pdf_systematic( "bukin", mjj, mass=mass) signal_pdf_name = signal_pdf_notrig.GetName() signal_pdf_notrig.SetName(signal_pdf_name + "_notrig") #signal_pdf = RooProdPdf(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_pdf) signal_pdf = RooEffProd(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_formula) # Copy input parameter values signal_vars["xp_0"].setVal(input_parameters["xp"][0]) signal_vars["xp_0"].setError(input_parameters["xp"][1]) signal_vars["xp_0"].setConstant() signal_vars["sigp_0"].setVal(input_parameters["sigp"][0]) signal_vars["sigp_0"].setError(input_parameters["sigp"][1]) signal_vars["sigp_0"].setConstant() signal_vars["xi_0"].setVal(input_parameters["xi"][0]) signal_vars["xi_0"].setError(input_parameters["xi"][1]) signal_vars["xi_0"].setConstant() signal_vars["rho1_0"].setVal(input_parameters["rho1"][0]) signal_vars["rho1_0"].setError(input_parameters["rho1"][1]) signal_vars["rho1_0"].setConstant() signal_vars["rho2_0"].setVal(input_parameters["rho2"][0]) signal_vars["rho2_0"].setError(input_parameters["rho2"][1]) signal_vars["rho2_0"].setConstant() f_signal_pdfs.Close() signal_parameters = {} signal_pdfs_notrig = {} signal_pdfs = {} signal_norms = {} background_pdfs = {} background_pdfs_notrig = {} background_parameters = {} background_norms = {} signal_epdfs = {} background_epdfs = {} models = {} fit_results = {} for fit_function in fit_functions: print "[create_datacards] INFO : On fit function {}".format( fit_function) if args.fitSignal: # Make a copy of the signal PDF, so that each fitTo call uses its own copy. # The copy should have all variables set constant. #signal_pdfs[fit_function], signal_parameters[fit_function] = signal_fits.copy_signal_pdf("bukin", signal_pdf, mjj, tag=fit_function, include_systematics=True) signal_pdfs_notrig[fit_function] = ROOT.RooBukinPdf( signal_pdf_notrig, signal_pdf_notrig.GetName() + "_" + fit_function) signal_pdfs[fit_function] = RooEffProd( signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_formula) #signal_pdfs[fit_function] = RooProdPdf(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_pdf) iterator = signal_pdfs_notrig[fit_function].getVariables( ).createIterator() this_parameter = iterator.Next() while this_parameter: this_parameter.setConstant() this_parameter = iterator.Next() else: signal_pdfs[fit_function] = RooHistPdf( 'signal_' + fit_function, 'signal_' + fit_function, RooArgSet(mjj), rooSigHist) signal_norms[fit_function] = RooRealVar( 'signal_norm_' + fit_function, 'signal_norm_' + fit_function, 0., 0., 1e+05) if args.fitBonly: signal_norms[fit_function].setConstant() background_pdfs_notrig[fit_function], background_parameters[ fit_function] = make_background_pdf(fit_function, mjj, collision_energy=8000.) background_pdf_name = background_pdfs_notrig[fit_function].GetName( ) background_pdfs_notrig[fit_function].SetName(background_pdf_name + "_notrig") background_pdfs[fit_function] = RooEffProd( background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_formula) #background_pdfs[fit_function] = RooProdPdf(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_pdf) #background_pdfs[fit_function] = background_pdfs_notrig[fit_function] #background_pdfs[fit_function].SetName(background_pdf_name) # Initial values if "trigbbh" in args.analysis: if fit_function == "f3": background_parameters[fit_function]["p1"].setVal(55.) background_parameters[fit_function]["p1"].setMin(20.) background_parameters[fit_function]["p2"].setVal(8.) elif fit_function == "f4": background_parameters[fit_function]["p1"].setVal(28.) background_parameters[fit_function]["p2"].setVal(-22.) background_parameters[fit_function]["p3"].setVal(10.) elif "trigbbl" in args.analysis: if fit_function == "f3": background_parameters[fit_function]["p1"].setVal(82.) background_parameters[fit_function]["p1"].setMin(60.) background_parameters[fit_function]["p2"].setVal(8.) elif fit_function == "f4": background_parameters[fit_function]["p1"].setVal(41.) background_parameters[fit_function]["p2"].setVal(-45.) background_parameters[fit_function]["p3"].setVal(10.) data_integral = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norms[fit_function] = RooRealVar( 'background_' + fit_function + '_norm', 'background_' + fit_function + '_norm', data_integral, 0., 1.e8) signal_epdfs[fit_function] = RooExtendPdf( 'esignal_' + fit_function, 'esignal_' + fit_function, signal_pdfs[fit_function], signal_norms[fit_function]) background_epdfs[fit_function] = RooExtendPdf( 'ebackground_' + fit_function, 'ebackground_' + fit_function, background_pdfs[fit_function], background_norms[fit_function]) models[fit_function] = RooAddPdf( 'model_' + fit_function, 's+b', RooArgList(background_epdfs[fit_function], signal_epdfs[fit_function])) if args.runFit: print "[create_datacards] INFO : Starting fit with function {}".format( fit_function) fit_results[fit_function] = models[fit_function].fitTo( rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy), RooFit.Verbose(0)) print "[create_datacards] INFO : Done with fit {}. Printing results.".format( fit_function) fit_results[fit_function].Print() print "[create_datacards] DEBUG : End args.runFit if block." # needed if want to evaluate limits without background systematics if args.fixBkg: background_norms[fit_function].setConstant() for par_name, par in background_parameters[ fit_function].iteritems(): par.setConstant() # ----------------------------------------- #signal_pdfs_syst = {} # JES and JER uncertainties if args.fitSignal: print "[create_datacards] INFO : Getting signal PDFs from " + analysis_config.get_signal_fit_file( args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)) f_signal_pdfs = TFile( analysis_config.get_signal_fit_file( args.analysis, args.model, mass, "bukin", interpolated=( not mass in analysis_config.simulation.simulated_masses))) w_signal = f_signal_pdfs.Get("w_signal") if "jes" in systematics: xp_central = signal_vars["xp_0"].getVal() #print w_signal.pdf("signal__JESUp") #print signal_fits.get_parameters(w_signal.pdf("signal__JESUp")) xp_up = signal_fits.get_parameters( w_signal.pdf("signal__JESUp"))["xpJESUp"][0] xp_down = signal_fits.get_parameters( w_signal.pdf("signal__JESDown"))["xpJESDown"][0] signal_vars["dxp"].setVal( max(abs(xp_up - xp_central), abs(xp_down - xp_central))) if signal_vars["dxp"].getVal() > 2 * mass * 0.1: print "[create_datacards] WARNING : Large dxp value. dxp = {}, xp_down = {}, xp_central = {}, xp_up = {}".format( signal_vars["dxp"].getVal(), xp_down, xp_central, xp_up) signal_vars["alpha_jes"].setVal(0.) signal_vars["alpha_jes"].setConstant(False) else: signal_vars["dxp"].setVal(0.) signal_vars["alpha_jes"].setVal(0.) signal_vars["alpha_jes"].setConstant() signal_vars["dxp"].setError(0.) signal_vars["dxp"].setConstant() if "jer" in systematics: sigp_central = signal_vars["sigp_0"].getVal() sigp_up = signal_fits.get_parameters( w_signal.pdf("signal__JERUp"))["sigpJERUp"][0] sigp_down = signal_fits.get_parameters( w_signal.pdf("signal__JERDown"))["sigpJERDown"][0] signal_vars["dsigp"].setVal( max(abs(sigp_up - sigp_central), abs(sigp_down - sigp_central))) signal_vars["alpha_jer"].setVal(0.) signal_vars["alpha_jer"].setConstant(False) else: signal_vars["dsigp"].setVal(0.) signal_vars["alpha_jer"].setVal(0.) signal_vars["alpha_jer"].setConstant() signal_vars["dsigp"].setError(0.) signal_vars["dsigp"].setConstant() #for variation in ["JERUp", "JERDown"]: # signal_pdfs_syst[variation] = w_signal.pdf("signal__" + variation) #for variation, pdf in signal_pdfs_syst.iteritems(): # signal_parameters = pdf.getVariables() # iter = signal_parameters.createIterator() # var = iter.Next() # while var: # var.setConstant() # var = iter.Next() f_signal_pdfs.Close() else: # dictionaries holding systematic variations of the signal shape hSig_Syst = {} hSig_Syst_DataHist = {} sigCDF = TGraph(hSig.GetNbinsX() + 1) if "jes" in systematics or "jer" in systematics: sigCDF.SetPoint(0, 0., 0.) integral = 0. for i in range(1, hSig.GetNbinsX() + 1): x = hSig.GetXaxis().GetBinLowEdge(i + 1) integral = integral + hSig.GetBinContent(i) sigCDF.SetPoint(i, x, integral) if "jes" in systematics: hSig_Syst['JESUp'] = copy.deepcopy(hSig) hSig_Syst['JESDown'] = copy.deepcopy(hSig) if "jer" in systematics: hSig_Syst['JERUp'] = copy.deepcopy(hSig) hSig_Syst['JERDown'] = copy.deepcopy(hSig) # reset signal histograms for key in hSig_Syst.keys(): hSig_Syst[key].Reset() hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key) # produce JES signal shapes if "jes" in systematics: for i in range(1, hSig.GetNbinsX() + 1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i + 1) jes = 1. - systematics["jes"] xLowPrime = jes * xLow xUpPrime = jes * xUp hSig_Syst['JESUp'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jes = 1. + systematics["jes"] xLowPrime = jes * xLow xUpPrime = jes * xUp hSig_Syst['JESDown'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JESUp'] = RooDataHist( 'hSig_JESUp', 'hSig_JESUp', RooArgList(mjj), hSig_Syst['JESUp']) hSig_Syst_DataHist['JESDown'] = RooDataHist( 'hSig_JESDown', 'hSig_JESDown', RooArgList(mjj), hSig_Syst['JESDown']) # produce JER signal shapes if "jer" in systematics: for i in range(1, hSig.GetNbinsX() + 1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i + 1) jer = 1. - systematics["jer"] xLowPrime = jer * (xLow - float(mass)) + float(mass) xUpPrime = jer * (xUp - float(mass)) + float(mass) hSig_Syst['JERUp'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jer = 1. + systematics["jer"] xLowPrime = jer * (xLow - float(mass)) + float(mass) xUpPrime = jer * (xUp - float(mass)) + float(mass) hSig_Syst['JERDown'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JERUp'] = RooDataHist( 'hSig_JERUp', 'hSig_JERUp', RooArgList(mjj), hSig_Syst['JERUp']) hSig_Syst_DataHist['JERDown'] = RooDataHist( 'hSig_JERDown', 'hSig_JERDown', RooArgList(mjj), hSig_Syst['JERDown']) # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') wsName = 'workspace_' + args.final_state + '_m' + str( mass) + postfix + '.root' w = RooWorkspace('w', 'workspace') if args.fitSignal: signal_pdf.SetName("signal") getattr(w, 'import')(signal_pdf, RooFit.Rename("signal")) # Create a norm variable "signal_norm" which normalizes the PDF to unity. norm = args.lumi #signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", 1. / norm, 0.1 / norm, 10. / norm) #if args.analysis == "trigbbh_CSVTM" and mass >= 1100: signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm / 100., norm / 100. / 10., norm * 10.) #else: # signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm, norm / 10., norm * 10.) print "[create_datacards] INFO : Set signal norm to {}".format( signal_norm.getVal()) signal_norm.setConstant() getattr(w, 'import')(signal_norm, ROOT.RooCmdArg()) #if "jes" in systematics: # getattr(w,'import')(signal_pdfs_syst['JESUp'],RooFit.Rename("signal__JESUp")) # getattr(w,'import')(signal_pdfs_syst['JESDown'],RooFit.Rename("signal__JESDown")) #if "jer" in systematics: # getattr(w,'import')(signal_pdfs_syst['JERUp'],RooFit.Rename("signal__JERUp")) # getattr(w,'import')(signal_pdfs_syst['JERDown'],RooFit.Rename("signal__JERDown")) else: getattr(w, 'import')(rooSigHist, RooFit.Rename("signal")) if "jes" in systematics: getattr(w, 'import')(hSig_Syst_DataHist['JESUp'], RooFit.Rename("signal__JESUp")) getattr(w, 'import')(hSig_Syst_DataHist['JESDown'], RooFit.Rename("signal__JESDown")) if "jer" in systematics: getattr(w, 'import')(hSig_Syst_DataHist['JERUp'], RooFit.Rename("signal__JERUp")) getattr(w, 'import')(hSig_Syst_DataHist['JERDown'], RooFit.Rename("signal__JERDown")) if args.decoBkg: getattr(w, 'import')(background_deco, ROOT.RooCmdArg()) else: for fit_function in fit_functions: print "Importing background PDF" print background_pdfs[fit_function] background_pdfs[fit_function].Print() getattr(w, 'import')(background_pdfs[fit_function], ROOT.RooCmdArg(), RooFit.Rename("background_" + fit_function), RooFit.RecycleConflictNodes()) w.pdf("background_" + fit_function).Print() getattr(w, 'import')(background_norms[fit_function], ROOT.RooCmdArg(), RooFit.Rename("background_" + fit_function + "_norm")) getattr(w, 'import')(fit_results[fit_function]) getattr(w, 'import')(signal_norms[fit_function], ROOT.RooCmdArg()) if args.fitBonly: getattr(w, 'import')(models[fit_function], ROOT.RooCmdArg(), RooFit.RecycleConflictNodes()) getattr(w, 'import')(rooDataHist, RooFit.Rename("data_obs")) w.Print() print "Starting save" if args.output_path: if not os.path.isdir(os.path.join(os.getcwd(), args.output_path)): os.mkdir(os.path.join(os.getcwd(), args.output_path)) print "[create_datacards] INFO : Writing workspace to file {}".format( os.path.join(args.output_path, wsName)) w.writeToFile(os.path.join(args.output_path, wsName)) else: print "[create_datacards] INFO : Writing workspace to file {}".format( limit_config.get_workspace_filename( args.analysis, args.model, mass, fitBonly=args.fitBonly, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) w.writeToFile( limit_config.get_workspace_filename( args.analysis, args.model, mass, fitBonly=args.fitBonly, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) # Clean up for name, obj in signal_norms.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_pdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_pdfs_notrig.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_norms.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_pdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_pdfs_notrig.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_epdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_epdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in fit_results.iteritems(): if obj: obj.IsA().Destructor(obj) for name, dict_l2 in background_parameters.iteritems(): for name2, obj in dict_l2.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in models.iteritems(): if obj: obj.IsA().Destructor(obj) rooDataHist.IsA().Destructor(rooDataHist) w.IsA().Destructor(w) # Make datacards only if S+B fitted if not args.fitBonly: beffUnc = 0.3 boffUnc = 0.06 for fit_function in fit_functions: if args.output_path: dcName = 'datacard_' + args.final_state + '_m' + str( mass) + postfix + '_' + fit_function + '.txt' print "[create_datacards] INFO : Writing datacard to file {}".format( os.path.join(args.output_path, dcName)) datacard = open(os.path.join(args.output_path, dcName), 'w') else: print "[create_datacards] INFO : Writing datacard to file {}".format( limit_config.get_datacard_filename( args.analysis, args.model, mass, fit_function, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) datacard = open( limit_config.get_datacard_filename( args.analysis, args.model, mass, fit_function, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger), 'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if ("jes" in systematics or "jer" in systematics) and not args.fitSignal: if args.output_path: datacard.write('shapes * * ' + wsName + ' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: datacard.write('shapes * * ' + os.path.basename( limit_config.get_workspace_filename( args.analysis, args.model, mass, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) + ' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: if args.output_path: datacard.write('shapes * * ' + wsName + ' w:$PROCESS\n') else: datacard.write('shapes * * ' + os.path.basename( limit_config.get_workspace_filename( args.analysis, args.model, mass, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) + ' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background_' + fit_function + '\n') datacard.write('process 0 1\n') if args.fitSignal: datacard.write('rate 1 1\n') else: datacard.write('rate -1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n' % (1. + systematics["luminosity"])) datacard.write('beff lnN %f -\n' % (1. + beffUnc)) datacard.write('boff lnN %f -\n' % (1. + boffUnc)) #datacard.write('bkg lnN - 1.03\n') if args.fitSignal: if "jes" in systematics: datacard.write("alpha_jes param 0.0 1.0\n") if "jer" in systematics: datacard.write("alpha_jer param 0.0 1.0\n") else: if "jes" in systematics: datacard.write('JES shape 1 -\n') if "jer" in systematics: datacard.write('JER shape 1 -\n') # flat parameters --- flat prior datacard.write('background_' + fit_function + '_norm flatParam\n') if args.decoBkg: datacard.write('deco_eig1 flatParam\n') datacard.write('deco_eig2 flatParam\n') else: for par_name, par in background_parameters[ fit_function].iteritems(): datacard.write(fit_function + "_" + par_name + ' flatParam\n') datacard.close() print "[create_datacards] INFO : Done with this datacard" #print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) ) print "All done."
parser.add_option('-b', action='store_true', default=False, dest='b', help='no x windows') (opts, args) = parser.parse_args() import pyroot_logon from ROOT import gROOT gROOT.ProcessLine('.L buildSimPdf.cc+') from ROOT import readData,computeRatio,computeRatioError,buildPdf,\ computeSumError,\ RooWorkspace,RooFit,TCanvas,kRed,kGreen,kDashed,buildSimPdf,RooArgSet,\ RooRealVar,RooMsgService, TMath, TFile, RooAbsReal, TGraph, \ RooStats from math import sqrt RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) hidatafile = 'data/dimuonTree_150mub.root' ppdatafile = 'data/dimuonTree_2011_pp.root' mmin = 7. mmax = 14. cuts = '(muPlusPt > %0.1f) && (muMinusPt > %0.1f) && (abs(upsRapidity)<2.4) && (vProb > 0.05)' \ % (opts.pt, opts.pt) simparamfile = opts.paramfile useKeys = opts.keys ## cuts = '(muPlusPt > 3.5) && (muMinusPt > 3.5) && (abs(upsRapidity)<2.4)' ## simparamfile = 'nom3.5SimFit.txt' ws = RooWorkspace("ws","ws")
'Lb': { 'color': 8, 'style': 2 }, 'lB': { 'color': 30, 'style': 2 }, 'comb': { 'color': 13, 'style': 5 }, } # set output message level RooMsgService.instance().setGlobalKillBelow(4) useMinos = True def NewCanvas(name='c1'): canv = TCanvas(name, '', 1000, 1000) canv.SetFillColor(4000) canv.SetFillStyle(4000) return canv canv = NewCanvas() canv.SaveAs(tMPfIG + '[') TGaxis.SetMaxDigits(3)
def alpha(channel): nElec = channel.count('e') nMuon = channel.count('m') nLept = nElec + nMuon nBtag = channel.count('b') # Channel-dependent settings # Background function. Semi-working options are: EXP, EXP2, EXPN, EXPTAIL if nLept == 0: treeName = 'SR' signName = 'XZh' colorVjet = sample['DYJetsToNuNu']['linecolor'] triName = "HLT_PFMET" leptCut = "0==0" topVeto = selection["TopVetocut"] massVar = "X_cmass" binFact = 1 #fitFunc = "EXP" #fitFunc = "EXP2" #fitFunc = "EXPN" #fitFunc = "EXPTAIL" fitFunc = "EXPN" if nBtag < 2 else "EXP" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "ERFEXP" fitFuncVV = "EXPGAUS" fitFuncTop = "GAUS2" elif nLept == 1: treeName = 'WCR' signName = 'XWh' colorVjet = sample['WJetsToLNu']['linecolor'] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isWtoEN" if nElec > 0 else "isWtoMN" topVeto = selection["TopVetocut"] massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" else: fitFunc = "EXPTAIL" if nBtag < 2 else "EXP" fitAltFunc = "EXPN" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "ERFEXP" fitFuncVV = "EXPGAUS" fitFuncTop = "GAUS3" if nBtag < 2 else "GAUS2" else: treeName = 'XZh' signName = 'XZh' colorVjet = sample['DYJetsToLL']['linecolor'] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isZtoEE" if nElec > 0 else "isZtoMM" topVeto = "0==0" massVar = "X_mass" binFact = 5 if nElec > 0: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "POW" if nBtag < 2 else "POW" else: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "POW" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitFuncVV = "EXPGAUS2" fitFuncTop = "GAUS" btagCut = selection["2Btag"] if nBtag == 2 else selection["1Btag"] print "--- Channel", channel, "---" print " number of electrons:", nElec, " muons:", nMuon, " b-tags:", nBtag print " read tree:", treeName, "and trigger:", triName if ALTERNATIVE: print " using ALTERNATIVE fit functions" print "-"*11*2 # Silent RooFit RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) #*******************************************************# # # # Variables and selections # # # #*******************************************************# # Define all the variables from the trees that will be used in the cuts and fits # this steps actually perform a "projection" of the entire tree on the variables in thei ranges, so be careful once setting the limits X_mass = RooRealVar( massVar, "m_{X}" if nLept > 0 else "m_{T}^{X}", XBINMIN, XBINMAX, "GeV") J_mass = RooRealVar( "fatjet1_prunedMassCorr", "corrected pruned mass", HBINMIN, HBINMAX, "GeV") CSV1 = RooRealVar( "fatjet1_CSVR1", "", -1.e99, 1.e4 ) CSV2 = RooRealVar( "fatjet1_CSVR2", "", -1.e99, 1.e4 ) nBtag = RooRealVar( "fatjet1_nBtag", "", 0., 4 ) CSVTop = RooRealVar( "bjet1_CSVR", "", -1.e99, 1.e4 ) isZtoEE = RooRealVar("isZtoEE", "", 0., 2 ) isZtoMM = RooRealVar("isZtoMM", "", 0., 2 ) isWtoEN = RooRealVar("isWtoEN", "", 0., 2 ) isWtoMN = RooRealVar("isWtoMN", "", 0., 2 ) weight = RooRealVar( "eventWeightLumi", "", -1.e9, 1. ) # Define the RooArgSet which will include all the variables defined before # there is a maximum of 9 variables in the declaration, so the others need to be added with 'add' variables = RooArgSet(X_mass, J_mass, CSV1, CSV2, nBtag, CSVTop) variables.add(RooArgSet(isZtoEE, isZtoMM, isWtoEN, isWtoMN, weight)) # Define the ranges in fatJetMass - these will be used to define SB and SR J_mass.setRange("LSBrange", LOWMIN, LOWMAX) J_mass.setRange("HSBrange", HIGMIN, HIGMAX) J_mass.setRange("VRrange", LOWMAX, SIGMIN) J_mass.setRange("SRrange", SIGMIN, SIGMAX) J_mass.setBins(54) # Define the selection for the various categories (base + SR / LSBcut / HSBcut ) baseCut = leptCut + " && " + btagCut + "&&" + topVeto massCut = massVar + ">%d" % XBINMIN baseCut += " && " + massCut # Cuts SRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), SIGMIN, J_mass.GetName(), SIGMAX) LSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX) HSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) SBcut = baseCut + " && ((%s>%d && %s<%d) || (%s>%d && %s<%d))" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX, J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) VRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMAX, J_mass.GetName(), SIGMIN) # Binning binsJmass = RooBinning(HBINMIN, HBINMAX) binsJmass.addUniform(HBINS, HBINMIN, HBINMAX) binsXmass = RooBinning(XBINMIN, XBINMAX) binsXmass.addUniform(binFact*XBINS, XBINMIN, XBINMAX) #*******************************************************# # # # Input files # # # #*******************************************************# # Import the files using TChains (separately for the bkg "classes" that we want to describe: here DY and VV+ST+TT) treeData = TChain(treeName) treeMC = TChain(treeName) treeVjet = TChain(treeName) treeVV = TChain(treeName) treeTop = TChain(treeName) # treeSign = {} # nevtSign = {} # Read data print "read data start" pd = getPrimaryDataset(triName) if len(pd)==0: raw_input("Warning: Primary Dataset not recognized, continue?") for i, s in enumerate(pd): treeData.Add(NTUPLEDIR + s + ".root") # Read V+jets backgrounds print "read V+jet start" for i, s in enumerate(["WJetsToLNu_HT", "DYJetsToNuNu_HT", "DYJetsToLL_HT"]): for j, ss in enumerate(sample[s]['files']): treeVjet.Add(NTUPLEDIR + ss + ".root") # Read VV backgrounds print "read VV start" for i, s in enumerate(["VV"]): for j, ss in enumerate(sample[s]['files']): treeVV.Add(NTUPLEDIR + ss + ".root") # Read Top backgrounds print "read Top start" for i, s in enumerate(["ST", "TTbar"]): for j, ss in enumerate(sample[s]['files']): treeTop.Add(NTUPLEDIR + ss + ".root") # Sum all background MC treeMC.Add(treeVjet) treeMC.Add(treeVV) treeMC.Add(treeTop) # print "prepare SB dataset" # create a dataset to host data in sideband (using this dataset we are automatically blind in the SR!) # setDataSB = RooDataSet("setDataSB", "setDataSB", variables, RooFit.Cut(SBcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) # setDataLSB = RooDataSet("setDataLSB", "setDataLSB", variables, RooFit.Import(setDataSB), RooFit.Cut(LSBcut), RooFit.WeightVar(weight)) # setDataHSB = RooDataSet("setDataHSB", "setDataHSB", variables, RooFit.Import(setDataSB), RooFit.Cut(HSBcut), RooFit.WeightVar(weight)) # print "prepare SR dataset" # Observed data (WARNING, BLIND!) # setDataSR = RooDataSet("setDataSR", "setDataSR", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) # setDataVR = RooDataSet("setDataVR", "setDataVR", variables, RooFit.Cut(VRcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) # Observed in the VV mass, just for plotting purposes print "prepare MC dataset" # same for the bkg datasets from MC, where we just apply the base selections (not blind) setVjet = RooDataSet("setVjet", "setVjet", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVjet)) setVjetSB = RooDataSet("setVjetSB", "setVjetSB", variables, RooFit.Import(setVjet), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setVjetSR = RooDataSet("setVjetSR", "setVjetSR", variables, RooFit.Import(setVjet), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) print "finish Vjet dataset" # setVV = RooDataSet("setVV", "setVV", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVV)) # setVVSB = RooDataSet("setVVSB", "setVVSB", variables, RooFit.Import(setVV), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) # setVVSR = RooDataSet("setVVSR", "setVVSR", variables, RooFit.Import(setVV), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) # print "finish VV dataset" # setTop = RooDataSet("setTop", "setTop", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeTop)) # setTopSB = RooDataSet("setTopSB", "setTopSB", variables, RooFit.Import(setTop), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) # setTopSR = RooDataSet("setTopSR", "setTopSR", variables, RooFit.Import(setTop), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) # print "finish Top dataset" # print " Data events SB: %.2f" % setDataSB.sumEntries() print " V+jets entries: %.2f" % setVjet.sumEntries() # print " VV, VH entries: %.2f" % setVV.sumEntries() # print " Top,ST entries: %.2f" % setTop.sumEntries() # the relative normalization of the varius bkg is taken from MC by counting all the events in the full fatJetMass range #coef = RooRealVar("coef", "coef", setVV.sumEntries()/setVjet.sumEntries(),0.,1.) # coef_VV_Vjet = RooRealVar("coef2_1", "coef2_1", setVV.sumEntries()/setVjet.sumEntries(), 0., 1.) # coef_Top_VVVjet = RooRealVar("coef3_21", "coef3_21", setTop.sumEntries()/(setVjet.sumEntries()+setVV.sumEntries()),0.,1.); # coef_VV_Vjet.setConstant(True) # coef_Top_VVVjet.setConstant(True) # Define entries entryVjet = RooRealVar("entryVjets", "V+jets normalization", setVjet.sumEntries(), 0., 1.e6) # entryVV = RooRealVar("entryVV", "VV normalization", setVV.sumEntries(), 0., 1.e6) # entryTop = RooRealVar("entryTop", "Top normalization", setTop.sumEntries(), 0., 1.e6) # entrySB = RooRealVar("entrySB", "Data SB normalization", setDataSB.sumEntries(SBcut), 0., 1.e6) # entrySB.setError(math.sqrt(entrySB.getVal())) # entryLSB = RooRealVar("entryLSB", "Data LSB normalization", setDataSB.sumEntries(LSBcut), 0., 1.e6) # entryLSB.setError(math.sqrt(entryLSB.getVal())) # entryHSB = RooRealVar("entryHSB", "Data HSB normalization", setDataSB.sumEntries(HSBcut), 0., 1.e6) # entryHSB.setError(math.sqrt(entryHSB.getVal())) #*******************************************************# # # # NORMALIZATION # # # #*******************************************************# # set reasonable ranges for J_mass and X_mass # these are used in the fit in order to avoid ROOFIT to look in regions very far away from where we are fitting J_mass.setRange("h_reasonable_range", LOWMIN, HIGMAX) X_mass.setRange("X_reasonable_range", XBINMIN, XBINMAX) # Set RooArgSets once for all, see https://root.cern.ch/phpBB3/viewtopic.php?t=11758 jetMassArg = RooArgSet(J_mass) ############################## # # # Yu-hsiang test region # # # ############################## # test it in the channel "XZhnnb" print "the channel is", channel if channel == "XZhnnb": # ------------------------------------------------------------------- # draw the setVjet Jmass_frame = J_mass.frame(RooFit.Title("test frame")) setVjet.plotOn(Jmass_frame) # ------------------------------------------------------------------- # use a PDF to fit the dataset print "fitFuncVjet is", fitFuncVjet constVjet_value_initial = -0.020 offsetVjet_value_initial = 30. widthVjet_value_initial = 100. constVjet_test = RooRealVar("constVjet_test", "slope of the exp", constVjet_value_initial , -1., 0.) offsetVjet_test = RooRealVar("offsetVjet_test", "offset of the erf", offsetVjet_value_initial, -50., 200.) widthVjet_test = RooRealVar("widthVjet_test", "width of the erf", widthVjet_value_initial, 1., 200.) modelVjet_test = RooErfExpPdf("modelVjet_test", "error function for V+jets mass", J_mass, constVjet_test, offsetVjet_test, widthVjet_test) # constVjet_test.Print() # offsetVjet_test.Print() # widthVjet_test.Print() # constVjet_test.setConstant(True) # offsetVjet_test.setConstant(True) # widthVjet_test.setConstant(True) frVjet_test = modelVjet_test.fitTo(setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # constVjet_test.Print() # offsetVjet_test.Print() # widthVjet_test.Print() constVjet_value_fit_MC = constVjet_test.getVal() offsetVjet_value_fit_MC = offsetVjet_test.getVal() widthVjet_value_fit_MC = widthVjet_test.getVal() print "constVjet_value_fit_MC:", constVjet_value_fit_MC, "offsetVjet_value_fit_MC:",offsetVjet_value_fit_MC,"widthVjet_value_fit_MC:",widthVjet_value_fit_MC modelVjet_test.plotOn(Jmass_frame,RooFit.LineColor(4)) # ------------------------------------------------------------------- # use the shape of fit to generate the psudo-data Entries_pseudo_data = setVjet.sumEntries() # Entries_pseudo_data = 502 # Entries_pseudo_data = 5021 pseudo_data = modelVjet_test.generate(RooArgSet(J_mass),Entries_pseudo_data ) # pseudo_data = modelVjet_test.generate(RooArgSet(J_mass),setVjet.sumEntries()) # pseudo_data = modelVjet_test.generate(RooArgSet(J_mass),502 ) # pseudo_data = modelVjet_test.generate(RooArgSet(J_mass),5021 ) # pseudo_data.Print("v") Jmass_frame2 = J_mass.frame(RooFit.Title("test frame2")) pseudo_data.plotOn(Jmass_frame2) modelVjet_test.plotOn(Jmass_frame2,RooFit.LineColor(4)) # ------------------------------------------------------------------- # make another dataset that remove the signal region pseudo_data_SB = RooDataSet("pseudo_data_SB", "pseudo_data_SB", RooArgSet(J_mass), RooFit.Import(pseudo_data), RooFit.Cut("fatjet1_prunedMassCorr<65 || fatjet1_prunedMassCorr>135") ) pseudo_data_SB.plotOn(Jmass_frame2,RooFit.LineColor(2)) # ------------------------------------------------------------------- # use another PDF to fit the pseudo-data in SB only constVjet_test2 = RooRealVar("constVjet_test2", "slope of the exp", constVjet_value_fit_MC , -1., 0.) offsetVjet_test2 = RooRealVar("offsetVjet_test2", "offset of the erf", offsetVjet_value_fit_MC , -50., 200.) widthVjet_test2 = RooRealVar("widthVjet_test2", "width of the erf", widthVjet_value_fit_MC , 1., 200.) modelVjet_test2 = RooErfExpPdf("modelVjet_test2", "error function for V+jets mass", J_mass, constVjet_test2, offsetVjet_test2, widthVjet_test2) frVjet_test2 = modelVjet_test2.fitTo(pseudo_data_SB, RooFit.SumW2Error(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # frVjet_test2 = modelVjet_test2.fitTo(pseudo_data_SB, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) constVjet_value_fit_pseudo_data_SB = constVjet_test2.getVal() offsetVjet_value_fit_pseudo_data_SB = offsetVjet_test2.getVal() widthVjet_value_fit_pseudo_data_SB = widthVjet_test2.getVal() print "constVjet_value_fit_pseudo_data_SB:", constVjet_value_fit_pseudo_data_SB, "offsetVjet_value_fit_pseudo_data_SB:",offsetVjet_value_fit_pseudo_data_SB,"widthVjet_value_fit_pseudo_data_SB:",widthVjet_value_fit_pseudo_data_SB Jmass_frame3 = J_mass.frame(RooFit.Title("test frame3, fit the pseudo-data in SB only")) pseudo_data_SB.plotOn(Jmass_frame3) modelVjet_test2.plotOn(Jmass_frame3,RooFit.LineColor(4),RooFit.Range("h_reasonable_range")) # ------------------------------------------------------------------- # calculate the Gen_value, the Fit_value and the Bias= ( Fit_value - Gen_value)/Gen_value iGen_value = modelVjet_test.createIntegral(RooArgSet(J_mass), RooFit.Range("VRrange,SRrange")) print "iGen_value:", iGen_value.getVal() iFit_value = modelVjet_test2.createIntegral(RooArgSet(J_mass), RooFit.Range("VRrange,SRrange")) print "iFit_value:", iFit_value.getVal() Bias_value = ( iFit_value.getVal() - iGen_value.getVal() ) / iGen_value.getVal() print "Bias_value of VR+SR:", Bias_value # -------------- iGen_value = modelVjet_test.createIntegral(RooArgSet(J_mass), RooFit.Range("SRrange")) print "iGen_value:", iGen_value.getVal() iFit_value = modelVjet_test2.createIntegral(RooArgSet(J_mass), RooFit.Range("SRrange")) print "iFit_value:", iFit_value.getVal() Bias_value = ( iFit_value.getVal() - iGen_value.getVal() ) / iGen_value.getVal() print "Bias_value of SR:", Bias_value # iGen_value = modelVjet_test.createIntegral(RooArgSet(J_mass),RooFit.NormSet(RooArgSet(J_mass)), RooFit.Range("VRrange,SRrange")) # print "iGen_value:", iGen_value.getVal() # iGen_value = modelVjet_test.createIntegral(RooArgSet(J_mass),RooFit.NormSet(RooArgSet(J_mass)), RooFit.Range("VRrange,SRrange")) # print "iGen_value:", iGen_value.getVal() # iGen_value = modelVjet_test.createIntegral(RooArgSet(J_mass), RooFit.Range("h_reasonable_range")) # print "iGen_value:", iGen_value.getVal() # iGen_value = modelVjet_test.createIntegral(RooArgSet(J_mass)) # print "iGen_value:", iGen_value.getVal() # ------------------------------------------------------------------- # repeat thousand times to see bias distribution h_Bias = TH1D("h_Bias","h_Bias",80,-1,1); Jmass_frame4 = J_mass.frame(RooFit.Title("test frame4")) times_max = 50000 constVjet_test.setConstant(True) offsetVjet_test.setConstant(True) widthVjet_test.setConstant(True) constVjet_test3 = RooRealVar("constVjet_test3", "slope of the exp", constVjet_value_fit_MC , -1., 0.) offsetVjet_test3 = RooRealVar("offsetVjet_test3", "offset of the erf", offsetVjet_value_fit_MC , -50., 200.) widthVjet_test3 = RooRealVar("widthVjet_test3", "width of the erf", widthVjet_value_fit_MC , 1., 200.) for times in range(0,times_max): # inside loop # print "times:", times if times % 10 == 0 : print "Processing times:", times+1 ,"of", times_max # generate pseudo-data # n_1_prime = gRandom->Poisson(n_1); Entries_pseudo_data_fluc = gRandom.Poisson( Entries_pseudo_data ) # print "Entries_pseudo_data:", Entries_pseudo_data # print "Entries_pseudo_data_fluc:", Entries_pseudo_data_fluc # pseudo_data2 = modelVjet_test.generate(RooArgSet(J_mass),Entries_pseudo_data ) pseudo_data2 = modelVjet_test.generate(RooArgSet(J_mass),Entries_pseudo_data_fluc ) # pseudo_data2.plotOn(Jmass_frame3,RooFit.LineColor(4),RooFit.Range("h_reasonable_range")) # take out VR+SR pseudo_data_SB2 = RooDataSet("pseudo_data_SB2", "pseudo_data_SB2", RooArgSet(J_mass), RooFit.Import(pseudo_data2), RooFit.Cut("fatjet1_prunedMassCorr<65 || fatjet1_prunedMassCorr>135") ) # use other PDF to fit # print "constVjet_value_fit_MC:",constVjet_value_fit_MC constVjet_test3.setVal(constVjet_value_fit_MC) offsetVjet_test3.setVal(offsetVjet_value_fit_MC) widthVjet_test3.setVal(widthVjet_value_fit_MC) modelVjet_test3 = RooErfExpPdf("modelVjet_test3", "error function for V+jets mass", J_mass, constVjet_test3, offsetVjet_test3, widthVjet_test3) frVjet_test3 = modelVjet_test3.fitTo(pseudo_data_SB2, RooFit.SumW2Error(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # calculate the bias iGen_value2 = modelVjet_test.createIntegral(jetMassArg,RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) # print "iGen_value2:", iGen_value2.getVal() iFit_value2 = modelVjet_test3.createIntegral(jetMassArg,RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) # print "iFit_value2:", iFit_value2.getVal() Bias_value2 = ( iFit_value2.getVal() - iGen_value2.getVal() ) / iGen_value2.getVal() # print "Bias_value2 of VR+SR:", Bias_value2 h_Bias.Fill(Bias_value2) # ------------------------------------------------------------------- # plot and save Save_Dir = "/afs/cern.ch/user/y/yuchang/www/jacopo_plotsAlpha/yu_hsiang_bias_study" c_test = TCanvas("test","test draw",800,600) c_test.cd() Jmass_frame.Draw() c_test.SaveAs(Save_Dir+"/"+"VJet_MC_fit_get_shape.pdf") c_test2 = TCanvas("test2","test draw 2",800,600) c_test2.cd() Jmass_frame2.Draw() c_test2.SaveAs(Save_Dir+"/"+"use_shape_to_generate_pseudo_data.pdf") # c_test2.SaveAs(Save_Dir+"/"+"use_shape_to_generate_pseudo_data_test.pdf") c_test3 = TCanvas("test3","test draw 3",800,600) c_test3.cd() Jmass_frame3.Draw() c_test3.SaveAs(Save_Dir+"/"+"fit_pseudo_data_in_SB_only.pdf") c_test4 = TCanvas("test4","test draw 4",800,600) c_test4.cd() h_Bias.Draw() c_test4.SaveAs(Save_Dir+"/"+"h_Bias.pdf")
def setup_workspace(): import ROOT from ROOT import RooWorkspace, gROOT, gStyle, RooAbsReal, RooMsgService, RooFit #from ROOT import RooFit, gROOT, gDirectory, gStyle, gPad, TTree, RooCmdArg,RooBinning #from ROOT import RooRealVar, RooMappedCategory, RooCategory, RooFormulaVar, RooAbsData #from ROOT import RooBMixDecay, RooMCStudy, RooAddModel, RooEffProd, RooMsgService #from ROOT import RooWorkspace, TCanvas, TFile, kFALSE, kTRUE, RooDataSet, TStopwatch #from ROOT import RooArgSet, RooArgList, RooRandom, RooMinuit, RooAbsReal, RooDataHist #from ROOT import TBrowser, TH2F, TF1, TH1F, RooGenericPdf, RooLinkedList gROOT.SetStyle("Plain") gStyle.SetPalette(1) gStyle.SetOptStat(0) gStyle.SetOptFit(0) gStyle.SetOptStat(1111) gStyle.SetOptFit(10111) gStyle.SetOptTitle(1) #RooAbsReal.defaultIntegratorConfig().Print() #RooAbsReal.defaultIntegratorConfig().setEpsAbs(1e-10) #RooAbsReal.defaultIntegratorConfig().setEpsRel(1e-10) RooAbsReal.defaultIntegratorConfig().Print() print "Numeric integration set up" #TODO: is the integration acceptable? ##This controls the logging output from RooFit #RooMsgService.instance().addStream(RooFit.DEBUG,RooFit.Topic(RooFit.Fitting)) RooMsgService.instance().deleteStream(1) #RooMsgService.instance().addStream(RooFit.INFO,RooFit.Topic(RooFit.Generation + RooFit.Minization + RooFit.Plotting + RooFit.Fitting + RooFit.Integration + RooFit.LinkStateMgmt + RooFit.Eval + RooFit.Caching + RooFit.Optimization + RooFit.ObjectHandling + RooFit.InputArguments + RooFit.Tracing + RooFit.Contents + RooFit.DataHandling + RooFit.NumericIntegration)) RooMsgService.instance().addStream(RooFit.INFO,RooFit.Topic(RooFit.LinkStateMgmt + RooFit.Caching + RooFit.ObjectHandling + RooFit.InputArguments + RooFit.Tracing)) RooMsgService.instance().Print() print "Message service set up" w = RooWorkspace("w",False) w.factory("RAND[0,1]") D0_M = w.factory("D0_M[1800,1930]") #TODO: define mass ranges slightly better Del_M = w.factory("Del_M[139,155]") D0_M.setUnit("MeV") Del_M.setUnit("MeV") for dst_side in ["", "dstsig", "dsthigh", "dstlow"]: for d_side in ["", "dsig", "dhigh", "dlow"]: name = dst_side+d_side if dst_side == "dsthigh": Del_M.setRange(name,148.,155.) elif dst_side == "dstsig": Del_M.setRange(name,143.,148.) elif dst_side == "dstlow": Del_M.setRange(name,139.,143.) if d_side == "dhigh": Del_M.setRange(name,1885.,1930.) elif d_side == "dsig": Del_M.setRange(name,1835.,1885.) elif d_side == "dlow": Del_M.setRange(name,1800.,1835.) w.defineSet("args","D0_M,Del_M") w.defineSet("argsPreCut","D0_M,Del_M,RAND") w.factory("RooGaussian::D0M_Sig_Gaus1(D0_M,D0M_Sig_Gaus_Mean[1865,1850,1880],D0M_Sig_Gaus_Sigma1[10,1,30])") w.factory("RooGaussian::D0M_Sig_Gaus2(D0_M,D0M_Sig_Gaus_Mean,D0M_Sig_Gaus_Sigma2[3,1,30])") w.factory("SUM::D0M_Sig_Gaus(D0M_Sig_Gaus1_Frac[0.8,0,1]*D0M_Sig_Gaus1,D0M_Sig_Gaus2)") w.factory("RooGaussian::D0M_MisId_Gaus1(D0_M,D0M_MisId_Gaus_Mean[1800,1740,1820],D0M_Sig_Gaus_Sigma1)") w.factory("RooGaussian::D0M_MisId_Gaus2(D0_M,D0M_MisId_Gaus_Mean,D0M_Sig_Gaus_Sigma2)") w.factory("SUM::D0M_MisId_Gaus(D0M_Sig_Gaus1_Frac*D0M_MisId_Gaus1,D0M_MisId_Gaus2)") w.factory("RooChebychev::D0M_Bkg_Poly(D0_M,{D0M_Bkg_Poly_a1[0,-1,1]})") w.factory("RooGaussian::DelM_Sig_Gaus1(Del_M,DelM_Sig_Gaus_Mean[145.5,143,148],DelM_Sig_Gaus_Sigma1[1,0,5] )") w.factory("RooGaussian::DelM_Sig_Gaus2(Del_M,DelM_Sig_Gaus_Mean,DelM_Sig_Gaus_Sigma2[.1,0,2] )") w.factory("SUM::DelM_Sig_Gaus(DelM_Sig_Gaus1_Frac[0.8,0,1]*DelM_Sig_Gaus1,DelM_Sig_Gaus2)") w.factory("RooDstD0BG::DelM_Bkg(Del_M,DelM_Bkg_m0[139.5,134,144],DelM_Bkg_c[80,0,1000],DelM_Bkg_a[-1,-100,10],DelM_Bkg_b[0.2,-0.2,10])") w.factory("PROD::Sig(DelM_Sig_Gaus,D0M_Sig_Gaus)") w.factory("PROD::Comb(DelM_Bkg,D0M_Bkg_Poly)") w.factory("PROD::MisId(DelM_Sig_Gaus,D0M_MisId_Gaus)") w.factory("PROD::Prompt(DelM_Bkg,D0M_Sig_Gaus)") w.factory("SUM::Final_PDF(N_Sig[10000,0,50000]*Sig,N_Prompt[5000,0,20000]*Prompt,N_Comb[10000,0,50000]*Comb,N_MisId[500,0,5000]*MisId)") return w
def setup_workspace(config): import ROOT from ROOT import RooWorkspace, gROOT, gStyle, RooAbsReal, RooMsgService, RooFit #from ROOT import RooFit, gROOT, gDirectory, gStyle, gPad, TTree, RooCmdArg,RooBinning #from ROOT import RooRealVar, RooMappedCategory, RooCategory, RooFormulaVar, RooAbsData #from ROOT import RooBMixDecay, RooMCStudy, RooAddModel, RooEffProd, RooMsgService #from ROOT import RooWorkspace, TCanvas, TFile, kFALSE, kTRUE, RooDataSet, TStopwatch #from ROOT import RooArgSet, RooArgList, RooRandom, RooMinuit, RooAbsReal, RooDataHist #from ROOT import TBrowser, TH2F, TF1, TH1F, RooGenericPdf, RooLinkedList from math import sqrt gROOT.SetStyle("Plain") gStyle.SetPalette(1) gStyle.SetOptStat(0) gStyle.SetOptFit(0) gStyle.SetOptStat(1111) gStyle.SetOptFit(10111) gStyle.SetOptTitle(1) #gROOT.ProcessLine(".L RooGaussianTrunk.cxx+") #gROOT.ProcessLine(".L RooCBShapeTrunk.cxx+") #gROOT.ProcessLine(".L RooChebychevTrunk.cxx+") #from ROOT import RooGaussianTrunk, RooChebychevTrunk, RooCBShapeTrunk #RooAbsReal.defaultIntegratorConfig().Print() RooAbsReal.defaultIntegratorConfig().setEpsAbs(1e-8) RooAbsReal.defaultIntegratorConfig().setEpsRel(1e-8) #RooAbsReal.defaultIntegratorConfig().setEpsAbs(1e-6) #RooAbsReal.defaultIntegratorConfig().setEpsRel(1e-6) RooAbsReal.defaultIntegratorConfig().Print() print "Numeric integration set up" #TODO: is the integration acceptable? ##This controls the logging output from RooFit #RooMsgService.instance().addStream(RooFit.DEBUG,RooFit.Topic(RooFit.Fitting)) RooMsgService.instance().deleteStream(1) #RooMsgService.instance().addStream(RooFit.INFO,RooFit.Topic(RooFit.Generation + RooFit.Minization + RooFit.Plotting + RooFit.Fitting + RooFit.Integration + RooFit.LinkStateMgmt + RooFit.Eval + RooFit.Caching + RooFit.Optimization + RooFit.ObjectHandling + RooFit.InputArguments + RooFit.Tracing + RooFit.Contents + RooFit.DataHandling + RooFit.NumericIntegration)) RooMsgService.instance().addStream(RooFit.INFO,RooFit.Topic(RooFit.LinkStateMgmt + RooFit.Caching + RooFit.ObjectHandling + RooFit.InputArguments + RooFit.Tracing)) RooMsgService.instance().Print() print "Message service set up" w = RooWorkspace("w",False) w.factory("RAND[0,1]") if "norm" not in config["mode"]: D0_Mass = w.factory("D0_Mass[1815,1915]") else: D0_Mass = w.factory("D0_Mass[1800,1930]") D0_Mass.setUnit("MeV") D0_Mass.setBins(60) Del_Mass = w.factory("Del_Mass[139,155]") Del_Mass.setUnit("MeV") Del_Mass.setBins(60) if "norm" not in config["mode"]: Dataset = w.factory("DataSet[BDT1,BDT2,BDT3]") else: Dataset = w.factory("DataSet[Norm]") w.factory("classID[Sig=0,Bkg=1]") w.factory("BDT_ada[-1,1]") w.factory("x1_PIDe[-2,20]") w.factory("x2_ProbNNmu[0,1]") #D0_Mass.setRange("blinded",1700.,1900.) if "norm" not in config["mode"]: dataCats = ["", "BDT1", "BDT2", "BDT3"] else: dataCats = ["", "Norm"] for data in dataCats: for dst_side in ["", "delsig", "delhigh", "dellow"]: for d_side in ["", "dsig", "dhigh", "dlow", "dhigh1", "dlow1", "dhigh2", "dlow2"]: name = data+dst_side+d_side if data == "BDT1": Dataset.setRange(name,"BDT1") elif data == "BDT2": Dataset.setRange(name,"BDT2") elif data == "BDT3": Dataset.setRange(name,"BDT3") elif data == "Norm": Dataset.setRange(name,"Norm") if dst_side == "delhigh": Del_Mass.setRange(name,148.,155.) elif dst_side == "delsig": Del_Mass.setRange(name,143.,148.) elif dst_side == "dellow": Del_Mass.setRange(name,139.,143.) if d_side == "dhigh2": D0_Mass.setRange(name,1910.,1930.) elif d_side == "dhigh1": D0_Mass.setRange(name,1890.,1910.) elif d_side == "dhigh": D0_Mass.setRange(name,1890.,1930.) elif d_side == "dsig": D0_Mass.setRange(name,1840.,1890.) elif d_side == "dlow": D0_Mass.setRange(name,1800.,1840.) elif d_side == "dlow1": D0_Mass.setRange(name,1820.,1840.) elif d_side == "dlow2": D0_Mass.setRange(name,1800.,1820.) w.defineSet("args","D0_Mass,Del_Mass,DataSet") w.defineSet("argsBasic","D0_Mass,Del_Mass") #w.defineSet("argsPreCut","D0_Mass,Del_Mass,RAND,classID,BDT_ada") w.defineSet("argsPreCut","D0_Mass,Del_Mass,RAND,classID,BDT_ada,x1_PIDe,x2_ProbNNmu") w.defineSet("argsPreCutPiPi","D0_Mass,Del_Mass,RAND") w.defineSet("argsPreCutKPi","D0_Mass,Del_Mass,RAND") # --- Norm --- if config['norm'] is "kpi": w.factory("{D0_Mass,Norm_D0M_Min[1815],Norm_D0M_Max[1915]}") else: w.factory("{D0_Mass,Norm_D0M_Min[1826],Norm_D0M_Max[1920]}") w.factory("RooGenericPdf::Norm_D0M_Range('(D0_Mass>Norm_D0M_Min&&D0_Mass<Norm_D0M_Max)',{D0_Mass,Norm_D0M_Min,Norm_D0M_Max})") w.factory("RooFormulaVar::Norm_D0M_Sig_Gaus2_Sigma('Norm_D0M_Sig_Gaus1_Sigma+Norm_D0M_Sig_Gaus2_Sigma_Diff',{Norm_D0M_Sig_Gaus1_Sigma[5,0,10],Norm_D0M_Sig_Gaus2_Sigma_Diff[5,0.,10.]})") w.factory("RooFormulaVar::Norm_D0M_Sig_Gaus3_Sigma('Norm_D0M_Sig_Gaus1_Sigma+Norm_D0M_Sig_Gaus2_Sigma_Diff+Norm_D0M_Sig_Gaus3_Sigma_Diff',{Norm_D0M_Sig_Gaus1_Sigma,Norm_D0M_Sig_Gaus2_Sigma_Diff,Norm_D0M_Sig_Gaus3_Sigma_Diff[2,0.,20.]})") w.factory("RooFormulaVar::Norm_D0M_Sig_Gaus1_Sigma_Scaled('Norm_D0M_Sig_Gaus1_Sigma*Norm_D0M_Sig_Gaus_Sigma_Scale',{Norm_D0M_Sig_Gaus1_Sigma,Norm_D0M_Sig_Gaus_Sigma_Scale[1]})") w.factory("RooFormulaVar::Norm_D0M_Sig_Gaus2_Sigma_Scaled('(Norm_D0M_Sig_Gaus1_Sigma+Norm_D0M_Sig_Gaus2_Sigma_Diff)*Norm_D0M_Sig_Gaus_Sigma_Scale',{Norm_D0M_Sig_Gaus1_Sigma,Norm_D0M_Sig_Gaus2_Sigma_Diff,Norm_D0M_Sig_Gaus_Sigma_Scale})") w.factory("RooFormulaVar::Norm_D0M_Sig_Gaus3_Sigma_Scaled('(Norm_D0M_Sig_Gaus1_Sigma+Norm_D0M_Sig_Gaus2_Sigma_Diff+Norm_D0M_Sig_Gaus3_Sigma_Diff)*Norm_D0M_Sig_Gaus_Sigma_Scale',{Norm_D0M_Sig_Gaus1_Sigma,Norm_D0M_Sig_Gaus2_Sigma_Diff,Norm_D0M_Sig_Gaus3_Sigma_Diff,Norm_D0M_Sig_Gaus_Sigma_Scale})") # D0_Mass Signal w.factory("RooCBShape::Norm_D0M_Sig_Gaus1(D0_Mass,Norm_D0M_Sig_Gaus_Mean[1867,1850,1880],Norm_D0M_Sig_Gaus1_Sigma_Scaled,Norm_D0M_Sig_Gaus1_alpha[1.5,0,6],Norm_D0M_Sig_Gaus1_n[2,0,20])") #w.factory("RooGaussian::Norm_D0M_Sig_Gaus1(D0_Mass,Norm_D0M_Sig_Gaus_Mean[1867,1850,1880],Norm_D0M_Sig_Gaus1_Sigma_Scaled)") w.factory("RooCBShape::Norm_D0M_Sig_Gaus2(D0_Mass,Norm_D0M_Sig_Gaus_Mean,Norm_D0M_Sig_Gaus2_Sigma_Scaled,Norm_D0M_Sig_Gaus2_alpha[1.5,0,6],Norm_D0M_Sig_Gaus2_n[2,0,20])") #w.factory("RooGaussian::Norm_D0M_Sig_Gaus2(D0_Mass,Norm_D0M_Sig_Gaus_Mean,Norm_D0M_Sig_Gaus2_Sigma_Scaled)") #w.factory("RooGaussian::Norm_D0M_Sig_Gaus3(D0_Mass,Norm_D0M_Sig_Gaus3_Mean[1867,1850,1880],Norm_D0M_Sig_Gaus3_Sigma_Scaled)") w.factory("RooGaussian::Norm_D0M_Sig_Gaus3(D0_Mass,Norm_D0M_Sig_Gaus_Mean,Norm_D0M_Sig_Gaus3_Sigma_Scaled)") #w.factory("RooCBShape::Norm_D0M_Sig_Gaus3(D0_Mass,Norm_D0M_Sig_Gaus_Mean,Norm_D0M_Sig_Gaus3_Sigma_Scaled,Norm_D0M_Sig_Gaus3_alpha[1.5,0,6],Norm_D0M_Sig_Gaus3_n[0.5,0,20])") #w.factory("SUM::Norm_D0M_Sig(Norm_D0M_Sig_Gaus1_Frac[0.4,0,1]*Norm_D0M_Sig_Gaus1,Norm_D0M_Sig_Gaus3_Frac[0.1,0,1]*Norm_D0M_Sig_Gaus3,Norm_D0M_Sig_Gaus2)") w.factory("SUM::Norm_D0M_Sig(Norm_D0M_Sig_Gaus1_Frac[0.4,0,1]*Norm_D0M_Sig_Gaus1,Norm_D0M_Sig_Gaus2)") #w.factory("PROD::Norm_D0M_Sig(Norm_D0M_Sig_Sum,Norm_D0M_Range)") # D0_Mass MisId #w.factory("RooGaussian::Norm_D0M_MisId_Gaus1(D0_Mass,Norm_D0M_MisId_Gaus_Mean[1790,1720,1820],Norm_D0M_Sig_Gaus1_Sigma)") #w.factory("RooGaussian::Norm_D0M_MisId_Gaus2(D0_Mass,Norm_D0M_MisId_Gaus_Mean,Norm_D0M_Sig_Gaus2_Sigma)") #w.factory("SUM::Norm_D0M_MisId(Norm_D0M_Sig_Gaus1_Frac*Norm_D0M_MisId_Gaus1,Norm_D0M_MisId_Gaus2)") ##w.factory("PROD::Norm_D0M_MisId(Norm_D0M_MisId_Sum,Norm_D0M_Range)") ##w.factory("RooExponential::Norm_D0M_MisId_Exp(D0_Mass,Norm_D0M_MisId_Exp_Const[-0.15,-.3,-.1])") ##w.factory("PROD::Norm_D0M_MisId(Norm_D0M_MisId_Exp,Norm_D0M_Range)") # D0_Mass Combinatorical w.factory('{Norm_D0M_Bkg_Cheby_1[-0.5,-1,1]}') #w.factory("RooChebychev::Norm_D0M_Bkg_Poly(D0_Mass,{Norm_D0M_Bkg_Cheby_1[-0.25,-1.5,1]})") #w.factory("PROD::Norm_D0M_Bkg(Norm_D0M_Bkg_Poly,Norm_D0M_Range)") w.factory("RooExponential::Norm_D0M_Bkg(D0_Mass,Norm_D0M_Bkg_Exp_c[-0.0088,-0.05,-0.001])") #w.factory("RooChebychev::Norm_D0M_Bkg(D0_Mass,{Norm_D0M_Bkg_Cheby_1})") #w.factory("RooChebychev::Norm_D0M_Bkg(D0_Mass,{Norm_D0M_Bkg_Cheby_1,Norm_D0M_Bkg_Cheby_2[-0.1,-0.7,1]})") w.factory("RooFormulaVar::Norm_DelM_Sig_Gaus_Mean_Shifted('Norm_DelM_Sig_Gaus_Mean+Norm_DelM_Sig_Gaus_Mean_Shift',{Norm_DelM_Sig_Gaus_Mean[145.5,145,146],Norm_DelM_Sig_Gaus_Mean_Shift[0]})") w.factory("RooFormulaVar::Norm_DelM_Sig_Gaus3_Mean_Shifted('Norm_DelM_Sig_Gaus3_Mean+Norm_DelM_Sig_Gaus_Mean_Shift',{Norm_DelM_Sig_Gaus3_Mean[145.7,144,155],Norm_DelM_Sig_Gaus_Mean_Shift})") w.factory("RooFormulaVar::Norm_DelM_Sig_Gaus2_Sigma('Norm_DelM_Sig_Gaus1_Sigma+Norm_DelM_Sig_Gaus2_Sigma_Diff',{Norm_DelM_Sig_Gaus1_Sigma[.4,0,1],Norm_DelM_Sig_Gaus2_Sigma_Diff[0.4,0.,1.]})") w.factory("RooFormulaVar::Norm_DelM_Sig_Gaus3_Sigma('Norm_DelM_Sig_Gaus1_Sigma+Norm_DelM_Sig_Gaus2_Sigma_Diff+Norm_DelM_Sig_Gaus3_Sigma_Diff',{Norm_DelM_Sig_Gaus1_Sigma,Norm_DelM_Sig_Gaus2_Sigma_Diff,Norm_DelM_Sig_Gaus3_Sigma_Diff[0.4,0.,3.]})") # Del_Mass signal w.factory("{Norm_DelM_Sig_Gaus3_Frac[0.01,0,.7]}") #w.factory("RooCBShape::Norm_DelM_Sig_Gaus1(Del_Mass,Norm_DelM_Sig_Gaus_Mean_Shifted,Norm_DelM_Sig_Gaus1_Sigma[.4,0,1],Norm_DelM_Sig_CB1_alpha[1.5,0,6], BDT%(n)i_D0M_Sig_CB1_n[2,0,10] )") w.factory("RooGaussian::Norm_DelM_Sig_Gaus1(Del_Mass,Norm_DelM_Sig_Gaus_Mean_Shifted,Norm_DelM_Sig_Gaus1_Sigma)") w.factory("RooGaussian::Norm_DelM_Sig_Gaus2(Del_Mass,Norm_DelM_Sig_Gaus_Mean_Shifted,Norm_DelM_Sig_Gaus2_Sigma)") w.factory("RooGaussian::Norm_DelM_Sig_Gaus3(Del_Mass,Norm_DelM_Sig_Gaus3_Mean_Shifted,Norm_DelM_Sig_Gaus3_Sigma)") w.factory("SUM::Norm_DelM_Sig(Norm_DelM_Sig_Gaus1_Frac[0.1,0,.7]*Norm_DelM_Sig_Gaus1,Norm_DelM_Sig_Gaus3_Frac*Norm_DelM_Sig_Gaus3,Norm_DelM_Sig_Gaus2)") #w.factory("SUM::Norm_DelM_Sig(Norm_DelM_Sig_Gaus1_Frac[0.1,0,.7]*Norm_DelM_Sig_Gaus1,Norm_DelM_Sig_Gaus2)") # mis recod w.factory("RooGaussian::Norm_DelM_MisRecod_Gaus1(Del_Mass,Norm_DelM_MisRecod_Gaus_Mean[145.5,145,146],Norm_DelM_MisRecod_Gaus_Sigma1[1.2,0,5] )") w.factory("RooChebychev::Norm_D0M_MisRecod(D0_Mass,{Norm_D0M_MisRecod_Cheby_1[0,-1,1]})") # Del_Mass Combinatorical #w.factory("RooDstD0BG::Norm_DelM_Bkg(Del_Mass,Norm_DelM_Bkg_m0[139.5,137.5,140.5],Norm_DelM_Bkg_c[40,7,350],Norm_DelM_Bkg_a[-20,-100,-1],Norm_DelM_Bkg_b[0.4,-1,2])") w.factory("RooDstD0BG::Norm_DelM_Bkg(Del_Mass,Norm_DelM_Bkg_m0[139.5,137.5,140.5],Norm_DelM_Bkg_m0,Norm_DelM_Bkg_a[-20,-100,-1],Norm_DelM_Bkg_b[0.4,-1,2])") w.factory("{Norm_DelM_Bkg_c[40,7,350]}") # Del_Mass signal w.factory("RooGaussian::Norm_DelM_MisId(Del_Mass,Norm_DelM_Sig_Gaus_Mean,Norm_DelM_MisId_Gaus_Sigma1[1,0,3])") w.factory("PROD::Norm_Sig(Norm_DelM_Sig,Norm_D0M_Sig)") w.factory("PROD::Norm_Comb(Norm_DelM_Bkg,Norm_D0M_Bkg)") w.factory("PROD::Norm_MisRecod(Norm_DelM_MisRecod_Gaus1,Norm_D0M_MisRecod)") #w.factory("PROD::Norm_MisId(Norm_DelM_MisId,Norm_D0M_MisId)") #w.factory("PROD::Norm_MisId(Norm_DelM_Sig,Norm_D0M_MisId)") #w.factory("PROD::Norm_MisId_Prompt(Norm_DelM_Bkg,Norm_D0M_MisId)") w.factory("PROD::Norm_Prompt(Norm_DelM_Bkg,Norm_D0M_Sig)") w.factory("{Norm_N_Sig[65000,20000,500000],Norm_N_MisId[1300,100,3000],Norm_N_MisRecod[5000,100,30000],Norm_N_MisId_Prompt[500,10,1000]}") # --- eMu --- #w.factory("EMu_N_Sig[1000,0,100000]") for n in (1,2,3): w.factory("BDT%(n)i_Sig_Eff[0.3,0,1]"%({"n":n})) w.factory("EMu_Eff[%f]"%(config['emuEff'])) w.factory("EMu_BR[1e-8,-1e-7,1e-7]") if config['norm'] is 'pipi': w.factory("Norm_Eff[%f]"%(config['pipiEff'])) w.factory("Norm_BR[%f]"%(config['pipiBR'][0])) w.obj("Norm_BR").setError(config['pipiBR'][1]) elif config['norm'] is 'kpi': w.factory("Norm_Eff[%f]"%(config['kpiEff'])) w.factory("Norm_BR[%f]"%(config['kpiBR'][0])) w.obj("Norm_BR").setError(config['kpiBR'][1]) w.factory("RooFormulaVar::N_PiPi('Norm_N_Sig*(%f)',{Norm_N_Sig})"%(config['pipiAsEmuEff']*config['pipiBR'][0]/config['kpiBR'][0]/config['kpiEff'],)) w.factory("RooFormulaVar::EMu_N_Sig('abs(Norm_N_Sig*((EMu_BR*EMu_Eff)/(Norm_BR*Norm_Eff)))',{Norm_BR,EMu_BR,EMu_Eff,Norm_Eff,Norm_N_Sig})") w.factory("{EMu_D0M_Min[1815],EMu_D0M_Max[1915]}") w.factory("RooGaussian::Norm_Constraint(Norm_N_Sig,%f,%f)"%(config["normEvents"][0],config["normEvents"][1])) # D0_Mass Combinatorical w.factory("RooGenericPdf::BDT_D0M_Blind('(D0_Mass<1700||D0_Mass>1900)',{D0_Mass})") w.factory("RooGenericPdf::BDT_D0M_Range('(D0_Mass>EMu_D0M_Min&&D0_Mass<EMu_D0M_Max)',{D0_Mass,EMu_D0M_Min,EMu_D0M_Max})") w.factory("RooChebychev::BDT_D0M_Bkg(D0_Mass,{BDT_D0M_Bkg_Cheby_1[-0.7,-3.0,0.0],BDT_D0M_Bkg_Cheby_2[-0.2,-3.0,0.0]})") w.factory("PROD::BDT_D0M_Bkg_Blind(BDT_D0M_Bkg,BDT_D0M_Blind)") # Del_Mass Combinatorical w.factory("RooDstD0BG::BDT_DelM_Bkg(Del_Mass,BDT_DelM_Bkg_m0[139.5,137.5,140.5],BDT_DelM_Bkg_c[40,7,350],BDT_DelM_Bkg_a[-20,-100,-1],BDT_DelM_Bkg_b[-0.1,-2,1])"%({"n":n})) w.factory("{BDT_D0M_Sig_CB1_alphaleft[0.3,0,1]}") w.factory("{BDT_D0M_Sig_CB2_alpharight[-0.5,-5,0]}") for n in (1,2,3): if n is not 3: w.factory("RooFormulaVar::BDT%(n)i_N_Sig('EMu_N_Sig*BDT%(n)i_Sig_Eff',{EMu_N_Sig,BDT%(n)i_Sig_Eff})"%({"n":n})) else: w.factory("RooFormulaVar::BDT%(n)i_N_Sig('EMu_N_Sig*(1-(BDT1_Sig_Eff+BDT2_Sig_Eff))',{EMu_N_Sig,BDT1_Sig_Eff,BDT2_Sig_Eff})"%({"n":n})) # D0_Mass Signal w.factory("{BDT%(n)i_D0M_Sig_CB2_alpharight[-0.5,-5,0],BDT%(n)i_D0M_Sig_CB1_alphaleft[0.3,0,1]}"%({"n":n})) w.factory("RooCBShape:BDT%(n)i_D0M_Sig_CB1(D0_Mass, BDT%(n)i_D0M_Sig_CB_Mean[1850,1750,1900], BDT%(n)i_D0M_Sig_CB1_Sigma[10,1,30], BDT_D0M_Sig_CB1_alphaleft, BDT%(n)i_D0M_Sig_CB1_n[2,0,10])"%({"n":n})) w.factory("RooCBShape:BDT%(n)i_D0M_Sig_CB2(D0_Mass, BDT%(n)i_D0M_Sig_CB_Mean, BDT%(n)i_D0M_Sig_CB2_Sigma[3,1,30], BDT_D0M_Sig_CB2_alpharight, BDT%(n)i_D0M_Sig_CB2_n[5,0,50])"%({"n":n})) w.factory("SUM::BDT%(n)i_D0M_Sig(BDT%(n)i_D0M_Sig_CB1_Frac[0.8,0,1]*BDT%(n)i_D0M_Sig_CB1,BDT%(n)i_D0M_Sig_CB2)"%({"n":n})) # Del_Mass signal w.factory("{BDT%(n)i_DelM_Sig_Gaus1_Frac[0.75,0,1]}"%({"n":n})) w.factory("RooGaussian::BDT%(n)i_DelM_Sig_Gaus1(Del_Mass,BDT%(n)i_DelM_Sig_Gaus_Mean[145.5,143,148],BDT%(n)i_DelM_Sig_Gaus_Sigma1[1,0,5] )"%({"n":n})) w.factory("RooGaussian::BDT%(n)i_DelM_Sig_Gaus2(Del_Mass,BDT%(n)i_DelM_Sig_Gaus_Mean,BDT%(n)i_DelM_Sig_Gaus_Sigma2[.1,0,2] )"%({"n":n})) #w.factory("{BDT%(n)i_DelM_Sig_Gaus3_Frac[0.05,0,0.1],BDT%(n)i_DelM_Sig_Gaus_Mean_2[148,143,152],BDT%(n)i_DelM_Sig_Gaus_Sigma3[10,0,20]}"%({"n":n})) w.factory("RooGaussian::BDT%(n)i_DelM_Sig_Gaus3(Del_Mass,BDT%(n)i_DelM_Sig_Gaus_Mean_3[148,143,152],BDT%(n)i_DelM_Sig_Gaus_Sigma3[10,0,20] )"%({"n":n})) w.factory("SUM::BDT%(n)i_DelM_Sig(BDT%(n)i_DelM_Sig_Gaus3_Frac[0.05,0,0.1]*BDT%(n)i_DelM_Sig_Gaus3,BDT%(n)i_DelM_Sig_Gaus2_Frac[0.2,0,1]*BDT%(n)i_DelM_Sig_Gaus2,BDT%(n)i_DelM_Sig_Gaus1)"%({"n":n})) #w.factory("SUM::BDT%(n)i_DelM_Sig(BDT%(n)i_DelM_Sig_Gaus2_Frac[0.2,0,1]*BDT%(n)i_DelM_Sig_Gaus2,BDT%(n)i_DelM_Sig_Gaus1)"%({"n":n})) w.factory("PROD::BDT%(n)i_Sig(BDT%(n)i_DelM_Sig,BDT%(n)i_D0M_Sig)"%({"n":n})) w.factory("PROD::BDT%(n)i_Comb_Blind(BDT_DelM_Bkg,BDT_D0M_Bkg_Blind)"%({"n":n})) w.factory("PROD::BDT%(n)i_Comb(BDT_DelM_Bkg,BDT_D0M_Bkg)"%({"n":n})) w.factory("{BDT1_PiPi_Eff[0.5,0,1],BDT2_PiPi_Eff[0.3,0,1]}") w.factory("{BDT_D0M_PiPi_CB2_alpharight[-0.5,-5,0],BDT_D0M_PiPi_CB1_alphaleft[0.8,0,3]}") for n in (1,2,3): if n is not 3: w.factory("RooFormulaVar::BDT%(n)i_N_PiPi('N_PiPi*BDT%(n)i_PiPi_Eff',{N_PiPi,BDT%(n)i_PiPi_Eff})"%({"n":n})) else: w.factory("RooFormulaVar::BDT%(n)i_N_PiPi('N_PiPi*(1-(BDT1_PiPi_Eff+BDT2_PiPi_Eff))',{N_PiPi,BDT1_PiPi_Eff,BDT2_PiPi_Eff})"%({"n":n})) # D0_Mass PiPi w.factory("{BDT%(n)i_D0M_PiPi_CB2_alpharight[-0.5,-5,0],BDT%(n)i_D0M_PiPi_CB1_alphaleft[0.8,0,3]}"%({"n":n})) w.factory("RooCBShape:BDT%(n)i_D0M_PiPi_CB1(D0_Mass, BDT%(n)i_D0M_PiPi_CB_Mean[1850,1750,1900], BDT%(n)i_D0M_PiPi_CB1_Sigma[10,1,30], BDT_D0M_PiPi_CB1_alphaleft, BDT%(n)i_D0M_PiPi_CB1_n[2,0,10])"%({"n":n})) w.factory("RooCBShape:BDT%(n)i_D0M_PiPi_CB2(D0_Mass, BDT%(n)i_D0M_PiPi_CB_Mean, BDT%(n)i_D0M_PiPi_CB2_Sigma[3,1,30], BDT_D0M_PiPi_CB2_alpharight, BDT%(n)i_D0M_PiPi_CB2_n[5,0,50])"%({"n":n})) w.factory("SUM::BDT%(n)i_D0M_PiPi(BDT%(n)i_D0M_PiPi_CB1_Frac[0.8,0,1]*BDT%(n)i_D0M_PiPi_CB1,BDT%(n)i_D0M_PiPi_CB2)"%({"n":n})) # Del_Mass signal w.factory("{BDT%(n)i_DelM_PiPi_Gaus1_Frac[0.75,0,1]}"%({"n":n})) w.factory("RooGaussian::BDT%(n)i_DelM_PiPi_Gaus1(Del_Mass,BDT%(n)i_DelM_PiPi_Gaus_Mean[145.5,143,148],BDT%(n)i_DelM_PiPi_Gaus_Sigma1[1,0,5] )"%({"n":n})) w.factory("RooGaussian::BDT%(n)i_DelM_PiPi_Gaus2(Del_Mass,BDT%(n)i_DelM_PiPi_Gaus_Mean_2[145.5,143,148],BDT%(n)i_DelM_PiPi_Gaus_Sigma2[.1,0,2] )"%({"n":n})) #w.factory("{BDT%(n)i_DelM_PiPi_Gaus3_Frac[0.05,0,0.1],BDT%(n)i_DelM_PiPi_Gaus_Mean_2[148,143,152],BDT%(n)i_DelM_PiPi_Gaus_Sigma3[10,0,20]}"%({"n":n})) w.factory("RooGaussian::BDT%(n)i_DelM_PiPi_Gaus3(Del_Mass,BDT%(n)i_DelM_PiPi_Gaus_Mean_3[148,143,152],BDT%(n)i_DelM_PiPi_Gaus_Sigma3[10,0,20] )"%({"n":n})) w.factory("SUM::BDT%(n)i_DelM_PiPi(BDT%(n)i_DelM_PiPi_Gaus3_Frac[0.05,0,0.1]*BDT%(n)i_DelM_PiPi_Gaus3,BDT%(n)i_DelM_PiPi_Gaus2_Frac[0.2,0,1]*BDT%(n)i_DelM_PiPi_Gaus2,BDT%(n)i_DelM_PiPi_Gaus1)"%({"n":n})) #w.factory("SUM::BDT%(n)i_DelM_Sig(BDT%(n)i_DelM_PiPi_Gaus2_Frac[0.2,0,1]*BDT%(n)i_DelM_PiPi_Gaus2,BDT%(n)i_DelM_PiPi_Gaus1)"%({"n":n})) w.factory("PROD::BDT%(n)i_PiPi(BDT%(n)i_DelM_PiPi,BDT%(n)i_D0M_PiPi)"%({"n":n})) #w.factory("SUM::BDT%(n)i_Final_PDF_Blind(BDT%(n)i_N_Sig*BDT%(n)i_Sig,BDT%(n)i_N_Comb[1000,0,10000]*BDT%(n)i_Comb_Blind)"%({"n":n})) #w.factory("SUM::BDT%(n)i_Final_PDF(BDT%(n)i_N_Sig*BDT%(n)i_Sig,BDT%(n)i_N_Comb*BDT%(n)i_Comb)"%({"n":n})) w.factory("SUM::BDT%(n)i_Final_PDF_Blind(BDT%(n)i_N_Sig*BDT%(n)i_Sig,BDT%(n)i_N_Comb[1000,0,10000]*BDT%(n)i_Comb_Blind,BDT%(n)i_N_PiPi*BDT%(n)i_PiPi)"%({"n":n})) w.factory("SUM::BDT%(n)i_Final_PDF(BDT%(n)i_N_Sig*BDT%(n)i_Sig,BDT%(n)i_N_Comb*BDT%(n)i_Comb,BDT%(n)i_N_PiPi*BDT%(n)i_PiPi)"%({"n":n})) w.factory("PROD::BDT%(n)i_Final_PDF_Constrained(BDT%(n)i_Final_PDF,Norm_Constraint)"%({"n":n})) #w.obj('Norm_D0M_Sig_Gaus1_Frac').setMin(0.0) ; w.obj('Norm_D0M_Sig_Gaus1_Frac').setMax(1.0) #w.obj('Norm_D0M_Sig_Gaus1_Frac').setVal(0.429624062534) ; w.obj('Norm_D0M_Sig_Gaus1_Frac').setError(0.0289511133792) #w.obj('Norm_D0M_Sig_Gaus1_Frac').setConstant(False) #w.obj('Norm_D0M_Sig_Gaus_Mean').setMin(1850.0) ; w.obj('Norm_D0M_Sig_Gaus_Mean').setMax(1880.0) #w.obj('Norm_D0M_Sig_Gaus_Mean').setVal(1867.01515277) ; w.obj('Norm_D0M_Sig_Gaus_Mean').setError(0.0296569841856) #w.obj('Norm_D0M_Sig_Gaus_Mean').setConstant(False) #w.obj('Norm_D0M_Sig_Gaus1_Sigma').setMin(0.0) ; w.obj('Norm_D0M_Sig_Gaus1_Sigma').setMax(10.0) #w.obj('Norm_D0M_Sig_Gaus1_Sigma').setVal(6.92118344347) ; w.obj('Norm_D0M_Sig_Gaus1_Sigma').setError(0.117795059995) #w.obj('Norm_D0M_Sig_Gaus1_Sigma').setConstant(False) #w.obj('Norm_D0M_Sig_Gaus2_Sigma').setMin(5.0) ; w.obj('Norm_D0M_Sig_Gaus2_Sigma').setMax(20.0) #w.obj('Norm_D0M_Sig_Gaus2_Sigma').setVal(10.3140938882) ; w.obj('Norm_D0M_Sig_Gaus2_Sigma').setError(0.117955520203) #w.obj('Norm_D0M_Sig_Gaus2_Sigma').setConstant(False) #w.obj('Norm_DelM_Bkg_a').setMin(-100.0) ; w.obj('Norm_DelM_Bkg_a').setMax(-1.0) #w.obj('Norm_DelM_Bkg_a').setVal(-16.1932460031) ; w.obj('Norm_DelM_Bkg_a').setError(0.43302849663) #w.obj('Norm_DelM_Bkg_a').setConstant(False) #w.obj('Norm_DelM_Bkg_b').setMin(-0.5) ; w.obj('Norm_DelM_Bkg_b').setMax(2.0) #w.obj('Norm_DelM_Bkg_b').setVal(0.178920942238) ; w.obj('Norm_DelM_Bkg_b').setError(0.0376477247211) #w.obj('Norm_DelM_Bkg_b').setConstant(False) #w.obj('Norm_DelM_Bkg_c').setMin(7.0) ; w.obj('Norm_DelM_Bkg_c').setMax(350.0) #w.obj('Norm_DelM_Bkg_c').setVal(36.1602832374) ; w.obj('Norm_DelM_Bkg_c').setError(5.19925002062) #w.obj('Norm_DelM_Bkg_c').setConstant(False) #w.obj('Norm_DelM_Bkg_m0').setMin(137.5) ; w.obj('Norm_DelM_Bkg_m0').setMax(140.5) #w.obj('Norm_DelM_Bkg_m0').setVal(139.316358242) ; w.obj('Norm_DelM_Bkg_m0').setError(5.10021351516e-05) #w.obj('Norm_DelM_Bkg_m0').setConstant(False) #w.obj('Norm_DelM_Sig_Gaus1_Frac').setMin(0.0) ; w.obj('Norm_DelM_Sig_Gaus1_Frac').setMax(1.) #w.obj('Norm_DelM_Sig_Gaus1_Frac').setVal(0.279248861884) ; w.obj('Norm_DelM_Sig_Gaus1_Frac').setError(0.0191547718614) #w.obj('Norm_DelM_Sig_Gaus1_Frac').setConstant(False) #w.obj('Norm_DelM_Sig_Gaus_Mean').setMin(145.0) ; w.obj('Norm_DelM_Sig_Gaus_Mean').setMax(146.0) #w.obj('Norm_DelM_Sig_Gaus_Mean').setVal(145.448069656) ; w.obj('Norm_DelM_Sig_Gaus_Mean').setError(0.00294967951486) #w.obj('Norm_DelM_Sig_Gaus_Mean').setConstant(False) #w.obj('Norm_DelM_Sig_Gaus1_Sigma').setMin(0.0) ; w.obj('Norm_DelM_Sig_Gaus1_Sigma').setMax(1.0) #w.obj('Norm_DelM_Sig_Gaus1_Sigma').setVal(0.429900766218) ; w.obj('Norm_DelM_Sig_Gaus1_Sigma').setError(0.0119155696871) #w.obj('Norm_DelM_Sig_Gaus1_Sigma').setConstant(False) #w.obj('Norm_DelM_Sig_Gaus2_Sigma').setMin(0.1) ; w.obj('Norm_DelM_Sig_Gaus2_Sigma').setMax(2.0) #w.obj('Norm_DelM_Sig_Gaus2_Sigma').setVal(0.827483577936) ; w.obj('Norm_DelM_Sig_Gaus2_Sigma').setError(0.00898522299303) #w.obj('Norm_DelM_Sig_Gaus2_Sigma').setConstant(False) if config['mode'] == 'mc': w.factory("SIMUL::Final_PDF(DataSet,BDT1=BDT1_Sig,BDT2=BDT2_Sig,BDT3=BDT3_Sig)") #w.obj("Final_PDF").Print("v") #w.obj("BDT1_Sig").Print("v") elif config['mode'] == 'mcpipi': w.factory("SIMUL::Final_PDF(DataSet,BDT1=BDT1_PiPi,BDT2=BDT2_PiPi,BDT3=BDT3_PiPi)") elif config['mode'] == 'datapretoy': w.factory("SIMUL::Final_PDF(DataSet,BDT1=BDT1_Comb_Blind,BDT2=BDT2_Comb_Blind,BDT3=BDT3_Comb_Blind)") elif config['mode'] == 'toy': w.factory("SIMUL::Final_PDF(DataSet,Norm=Norm_Final_PDF,BDT1=BDT1_Final_PDF,BDT2=BDT2_Final_PDF,BDT3=BDT3_Final_PDF)") w.factory("SIMUL::Final_PDF_Background(DataSet,Norm=Norm_Final_PDF,BDT1=BDT1_Comb,BDT2=BDT2_Comb,BDT3=BDT3_Comb)") w.factory("SIMUL::Final_PDF_Constrained(DataSet,BDT1=BDT1_Final_PDF_Constrained,BDT2=BDT2_Final_PDF_Constrained,BDT3=BDT3_Final_PDF_Constrained)") elif config['mode'] == 'mcnorm': w.factory("SIMUL::Final_PDF(DataSet,Norm=Norm_Sig)") elif config['mode'] == 'norm': #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig[65000,20000,110000]*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisId[1300,100,3000]*Norm_MisId,Norm_N_MisId_Prompt[500,10,1000]*Norm_MisId_Prompt)") #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig[65000,20000,110000]*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisId[1300,100,3000]*Norm_MisId)") #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig[65000,20000,110000]*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisId_Prompt[500,10,1000]*Norm_MisId_Prompt)") #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisRecod*Norm_MisRecod)") w.factory("SUM::Norm_Final_PDF(Norm_N_Sig*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb)") w.factory("SIMUL::Final_PDF(DataSet,Norm=Norm_Final_PDF)") elif config['mode'] == 'data': #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig[65000,20000,110000]*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisId[1300,100,3000]*Norm_MisId,Norm_N_MisId_Prompt[500,10,1000]*Norm_MisId_Prompt)") #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig[65000,20000,110000]*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisId[1300,100,3000]*Norm_MisId)") #w.factory("SUM::Norm_Final_PDF(Norm_N_Sig[65000,20000,110000]*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb,Norm_N_MisId_Prompt[500,10,1000]*Norm_MisId_Prompt)") w.factory("SUM::Norm_Final_PDF(Norm_N_Sig*Norm_Sig,Norm_N_Prompt[35000,20000,60000]*Norm_Prompt,Norm_N_Comb[67000,1000,90000]*Norm_Comb)") w.factory("SIMUL::Final_PDF(DataSet,Norm=Norm_Final_PDF,BDT1=BDT1_Final_PDF,BDT2=BDT2_Final_PDF,BDT3=BDT3_Final_PDF)") w.factory("SIMUL::Final_PDF_Background(DataSet,Norm=Norm_Final_PDF,BDT1=BDT1_Comb,BDT2=BDT2_Comb,BDT3=BDT3_Comb)") w.factory("SIMUL::Final_PDF_Constrained(DataSet,BDT1=BDT1_Final_PDF_Constrained,BDT2=BDT2_Final_PDF_Constrained,BDT3=BDT3_Final_PDF_Constrained)") w.obj('Norm_N_Comb').setMin(2000.0*config["normScale"]) ; w.obj('Norm_N_Comb').setMax(15000.0*config["normScale"]) w.obj('Norm_N_Comb').setVal(7850.56516616*config["normScale"]) ; w.obj('Norm_N_Comb').setError(177.821454726/sqrt(config["normScale"])) w.obj('Norm_N_MisRecod').setMin(100.0*config["normScale"]) ; w.obj('Norm_N_MisRecod').setMax(40000.0*config["normScale"]) w.obj('Norm_N_MisRecod').setVal(20316.944222*config["normScale"]) ; w.obj('Norm_N_MisRecod').setError(248.324102117/sqrt(config["normScale"])) w.obj('Norm_N_Prompt').setMin(6000.0*config["normScale"]) ; w.obj('Norm_N_Prompt').setMax(60000.0*config["normScale"]) w.obj('Norm_N_Prompt').setVal(29326.825063*config["normScale"]) ; w.obj('Norm_N_Prompt').setError(247.656992623/sqrt(config["normScale"])) w.obj('Norm_N_Sig').setMin(2000.0*config["normScale"]) ; w.obj('Norm_N_Sig').setMax(270000.0*config["normScale"]) w.obj('Norm_N_Sig').setVal(135370.*config["normScale"]) ; w.obj('Norm_N_Sig').setError(430./sqrt(config["normScale"])) if mode_later_than('mcnorm',config['mode']): # nll analyse, nlls up to 1610.0 on Thu Jul 31 15:14:35 2014 run on fitResult.norm_kpi_2011_6.0.0.4.root # # WARNING derivitive_ratio bottom is zero 169 689.330300 696.763943 696.763943 # INFO extrapolate lower edge [False, -0.2368609160806532, 1610.0] # INFO extrapolate upper edge [False, 0.300022797868122, 1610.0] w.obj('Norm_D0M_Bkg_Exp_c').setMin(-0.236860916081) ; w.obj('Norm_D0M_Bkg_Exp_c').setMax(0.300022797868) ; w.obj('Norm_D0M_Bkg_Exp_c').setVal(-0.0221074305011) ; w.obj('Norm_D0M_Bkg_Exp_c').setError(0.00127007751403) # WARNING derivitive_ratio bottom is zero 169 5199.217924 5509.102918 5509.102918 w.obj('Norm_D0M_Sig_Gaus1_Sigma').setMin(5.8) ; w.obj('Norm_D0M_Sig_Gaus1_Sigma').setMax(8.6) ; w.obj('Norm_D0M_Sig_Gaus1_Sigma').setVal(7.2) ; w.obj('Norm_D0M_Sig_Gaus1_Sigma').setError(0.0305815254416) # WARNING derivitive_ratio bottom is zero 119 62.077791 62.077791 62.077791 # WARNING Dont want to expand max range 99.112383 too far # INFO extrapolate upper edge [False, 10.5, 1610.0] # WARNING upper edge 10.500000 hits limit 5.000000 w.obj('Norm_D0M_Sig_Gaus1_alpha').setMin(1.14) ; w.obj('Norm_D0M_Sig_Gaus1_alpha').setMax(5.0) ; w.obj('Norm_D0M_Sig_Gaus1_alpha').setVal(2.298) ; w.obj('Norm_D0M_Sig_Gaus1_alpha').setError(0.0393012987558) # WARNING Dont want to expand max range 899.409174 too far # INFO extrapolate upper edge [False, 35.0, 1610.0] # WARNING upper edge 35.000000 hits limit 20.000000 w.obj('Norm_D0M_Sig_Gaus1_n').setMin(0.3375) ; w.obj('Norm_D0M_Sig_Gaus1_n').setMax(20.0) ; w.obj('Norm_D0M_Sig_Gaus1_n').setVal(2.30375) ; w.obj('Norm_D0M_Sig_Gaus1_n').setError(0.537418026352) # WARNING derivitive_ratio bottom is zero 127 1374.893616 1418.388895 1418.388895 # INFO extrapolate upper edge [False, 10.856461576572277, 1610.0] w.obj('Norm_D0M_Sig_Gaus2_Sigma_Diff').setMin(1.25) ; w.obj('Norm_D0M_Sig_Gaus2_Sigma_Diff').setMax(10.8564615766) ; w.obj('Norm_D0M_Sig_Gaus2_Sigma_Diff').setVal(5.09258463063) ; w.obj('Norm_D0M_Sig_Gaus2_Sigma_Diff').setError(0.115261989641) # WARNING derivitive_ratio bottom is zero 100 768.841852 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 101 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 102 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 103 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 104 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 105 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 106 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 107 768.841850 768.841850 768.841850 # WARNING derivitive_ratio bottom is zero 108 768.841850 768.841850 768.841850 # INFO extrapolate upper edge [False, 10.11481217459233, 1610.0] # WARNING upper edge 10.114812 hits limit 5.000000 w.obj('Norm_D0M_Sig_Gaus2_alpha').setMin(1.44) ; w.obj('Norm_D0M_Sig_Gaus2_alpha').setMax(5.0) ; w.obj('Norm_D0M_Sig_Gaus2_alpha').setVal(2.152) ; w.obj('Norm_D0M_Sig_Gaus2_alpha').setError(0.0415387821092) # WARNING derivitive_ratio bottom is zero 230 629.750229 630.182190 630.182190 # INFO extrapolate lower edge [False, -0.9760496583225814, 1610.0] # WARNING Dont want to expand max range 50.491612 too far # INFO extrapolate upper edge [False, 35.0, 1610.0] # WARNING lower edge -0.976050 hits limit 0.000000 # WARNING upper edge 35.000000 hits limit 20.000000 w.obj('Norm_D0M_Sig_Gaus2_n').setMin(0.0) ; w.obj('Norm_D0M_Sig_Gaus2_n').setMax(20.0) ; w.obj('Norm_D0M_Sig_Gaus2_n').setVal(1.0) ; w.obj('Norm_D0M_Sig_Gaus2_n').setError(0.0563707589481) # WARNING derivitive_ratio bottom is zero 102 100475.575388 104489.200281 104489.200281 w.obj('Norm_D0M_Sig_Gaus_Mean').setMin(1864.1) ; w.obj('Norm_D0M_Sig_Gaus_Mean').setMax(1868.6) ; w.obj('Norm_D0M_Sig_Gaus_Mean').setVal(1866.35) ; w.obj('Norm_D0M_Sig_Gaus_Mean').setError(0.0282504176865) # WARNING derivitive_ratio bottom is zero 102 950.574510 1090.331482 1090.331482 # INFO extrapolate upper edge [False, 8.675242367234118, 1610.0] w.obj('Norm_DelM_Bkg_a').setMin(-30.7) ; w.obj('Norm_DelM_Bkg_a').setMax(8.67524236723) ; w.obj('Norm_DelM_Bkg_a').setVal(-14.9499030531) ; w.obj('Norm_DelM_Bkg_a').setError(0.352110679985) # WARNING derivitive_ratio bottom is zero 286 2509.484557 2524.607389 2524.607389 # INFO extrapolate lower edge [False, 135.51700895240305, 1610.0] w.obj('Norm_DelM_Bkg_m0').setMin(135.517008952) ; w.obj('Norm_DelM_Bkg_m0').setMax(140.245) ; w.obj('Norm_DelM_Bkg_m0').setVal(139.29940179) ; w.obj('Norm_DelM_Bkg_m0').setError(0.00278162353152) # WARNING derivitive_ratio bottom is zero 168 12637.921551 12941.900194 12941.900194 w.obj('Norm_DelM_Sig_Gaus1_Sigma').setMin(0.275) ; w.obj('Norm_DelM_Sig_Gaus1_Sigma').setMax(0.58) ; w.obj('Norm_DelM_Sig_Gaus1_Sigma').setVal(0.4275) ; w.obj('Norm_DelM_Sig_Gaus1_Sigma').setError(0.00623690681335) # WARNING derivitive_ratio bottom is zero 140 7646.478871 7794.222379 7794.222379 w.obj('Norm_DelM_Sig_Gaus2_Sigma_Diff').setMin(0.145) ; w.obj('Norm_DelM_Sig_Gaus2_Sigma_Diff').setMax(0.56) ; w.obj('Norm_DelM_Sig_Gaus2_Sigma_Diff').setVal(0.311) ; w.obj('Norm_DelM_Sig_Gaus2_Sigma_Diff').setError(0.00961908230633) # WARNING derivitive_ratio bottom is zero 135 7889.258317 7968.149060 7968.149060 w.obj('Norm_DelM_Sig_Gaus3_Mean').setMin(144.385) ; w.obj('Norm_DelM_Sig_Gaus3_Mean').setMax(147.52) ; w.obj('Norm_DelM_Sig_Gaus3_Mean').setVal(145.9525) ; w.obj('Norm_DelM_Sig_Gaus3_Mean').setError(0.0297743321414) # WARNING derivitive_ratio bottom is zero 127 1441.937761 1456.115731 1456.115731 # INFO extrapolate lower edge [False, -1.562458158266192, 1610.0] # INFO extrapolate upper edge [False, 3.2886360831918586, 1610.0] # WARNING lower edge -1.562458 hits limit 0.000000 w.obj('Norm_DelM_Sig_Gaus3_Sigma_Diff').setMin(0.0) ; w.obj('Norm_DelM_Sig_Gaus3_Sigma_Diff').setMax(3.28863608319) ; w.obj('Norm_DelM_Sig_Gaus3_Sigma_Diff').setVal(0.657727216638) ; w.obj('Norm_DelM_Sig_Gaus3_Sigma_Diff').setError(0.037812360311) # WARNING derivitive_ratio bottom is zero 102 17487.965272 18067.587218 18067.587218 w.obj('Norm_DelM_Sig_Gaus_Mean').setMin(145.25) ; w.obj('Norm_DelM_Sig_Gaus_Mean').setMax(145.6) ; w.obj('Norm_DelM_Sig_Gaus_Mean').setVal(145.425) ; w.obj('Norm_DelM_Sig_Gaus_Mean').setError(0.00389207378424) # WARNING derivitive_ratio bottom is zero 171 1440.310455 1466.512994 1466.512994 # INFO extrapolate lower edge [False, -1161.7298062300902, 1610.0] # INFO extrapolate upper edge [False, 6502.909990291508, 1610.0] # WARNING lower edge -1161.729806 hits limit 0.000000 w.obj('Norm_N_Comb').setMin(0.0*config["normScale"]) ; w.obj('Norm_N_Comb').setMax(6502.90999029*config["normScale"]) ; w.obj('Norm_N_Comb').setVal(1300.58199806*config["normScale"]) ; w.obj('Norm_N_Comb').setError(69.7188799676/sqrt(config["normScale"])) # WARNING derivitive_ratio bottom is zero 142 1629.344232 1679.974917 1679.974917 # INFO extrapolate lower edge [False, 10931.649121116747, 1610.0] w.obj('Norm_N_Prompt').setMin(10931.6491211*config["normScale"]) ; w.obj('Norm_N_Prompt').setMax(30995.7616494*config["normScale"]) ; w.obj('Norm_N_Prompt').setVal(18957.2941324*config["normScale"]) ; w.obj('Norm_N_Prompt').setError(247.513270145/sqrt(config["normScale"])) # WARNING derivitive_ratio bottom is zero 148 1585.358526 1642.672043 1642.672043 # INFO extrapolate lower edge [False, 64907.007351854576, 1610.0] w.obj('Norm_N_Sig').setMin(64907.0073519*config["normScale"]) ; w.obj('Norm_N_Sig').setMax(99148.5248*config["normScale"]) ; w.obj('Norm_N_Sig').setVal(82027.7660759*config["normScale"]) ; w.obj('Norm_N_Sig').setError(349.170253164/sqrt(config["normScale"])) #w.obj('Norm_DelM_Bkg_b').setVal(0) #w.obj('Norm_DelM_Bkg_b').setConstant(True) w.obj('Norm_D0M_Sig_Gaus1_Frac').setVal(0.7) #w.obj('Norm_D0M_Sig_Gaus3_Frac').setVal(0.35) w.obj('Norm_DelM_Sig_Gaus1_Frac').setVal(0.25) w.obj('Norm_DelM_Sig_Gaus3_Frac').setVal(0.15) w.obj('Norm_D0M_Sig_Gaus1_Frac').setConstant(True) #w.obj('Norm_D0M_Sig_Gaus3_Frac').setConstant(True) w.obj('Norm_DelM_Sig_Gaus1_Frac').setConstant(True) w.obj('Norm_DelM_Sig_Gaus3_Frac').setConstant(True) config['postHook'](w) return w
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2" # input parameters parser = ArgumentParser(description='Script that creates combine datacards and corresponding RooFit workspaces',epilog=usage) parser.add_argument("analysis", type=str, help="Analysis name") parser.add_argument("model", type=str, help="Model (Hbb, RSG)") #parser.add_argument("--inputData", dest="inputData", required=True, # help="Input data spectrum", # metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", type=str, default="h_data", help="Data histogram name", metavar="DATA_HISTNAME") #parser.add_argument("--inputSig", dest="inputSig", required=True, # help="Input signal shapes", # metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", default="qq", help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("--fit_functions", dest="fit_functions", default="f1,f2,f3,f4,f5", help="List of fit functions") #parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)") parser.add_argument("-o", "--output_path", dest="output_path", help="Output path where datacards and workspaces will be stored. If not specified, this is derived from limit_configuration.", metavar="OUTPUT_PATH") parser.add_argument("--correctTrigger", dest="correctTrigger", action='store_true', help="Include trigger correction in PDF") parser.add_argument("-l", "--lumi", dest="lumi", default=19700., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument("--massMin", dest="massMin", default=500, type=int, help="Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument("--massMax", dest="massMax", default=1200, type=int, help="Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument("--fitSignal", action="store_true", help="Use signal fitted shapes (CB+Voigtian) instead of histogram templates") #parser.add_argument("--lumiUnc", dest="lumiUnc", # required=True, type=float, # help="Relative uncertainty in the integrated luminosity", # metavar="LUMI_UNC") #parser.add_argument("--jesUnc", dest="jesUnc", # type=float, # help="Relative uncertainty in the jet energy scale", # metavar="JES_UNC") #parser.add_argument("--jerUnc", dest="jerUnc", # type=float, # help="Relative uncertainty in the jet energy resolution", # metavar="JER_UNC") parser.add_argument("--sqrtS", dest="sqrtS", default=8000., type=float, help="Collision center-of-mass energy (default: %(default).1f)", metavar="SQRTS") parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters") parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") parser.add_argument("--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)") parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots") parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots") parser.add_argument("--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)") parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared") parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument("--mass", type=int, nargs = '*', default = 1000, help="Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument("--massrange", type=int, nargs = 3, help="Define a range of masses to be produced. Format: min max step", metavar = ('MIN', 'MAX', 'STEP') ) mass_group.add_argument("--masslist", help = "List containing mass information" ) args = parser.parse_args() fit_functions = args.fit_functions.split(",") # mass points for which resonance shapes will be produced masses = [] if args.fitBonly: masses.append(750) else: if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX+STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py","")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooProdPdf, RooEffProd, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0,kFALSE) RooMsgService.instance().setStreamStatus(1,kFALSE) # input data file #inputData = TFile(limit_config.get_data_input(args.analysis)) # input data histogram #hData = inputData.Get(args.dataHistname) #hData.SetDirectory(0) data_file = TFile(analysis_config.get_b_histogram_filename(args.analysis, "BJetPlusX_2012")) hData = data_file.Get("BHistograms/h_pfjet_mjj") hData.SetDirectory(0) # input sig file if not args.fitSignal: print "[create_datacards] INFO : Opening resonance shapes file at " + limit_config.get_resonance_shapes(args.analysis, args.model) inputSig = TFile(limit_config.get_resonance_shapes(args.analysis, args.model), "READ") sqrtS = args.sqrtS # mass variable mjj = RooRealVar('mjj','mjj',float(args.massMin),float(args.massMax)) # integrated luminosity and signal cross section lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section if args.correctTrigger: trigger_efficiency_pdf = trigger_efficiency.get_pdf(args.analysis, mjj) trigger_efficiency_formula = trigger_efficiency.get_formula(args.analysis, mjj) else: trigger_efficiency_pdf = trigger_efficiency.get_trivial_pdf(mjj) trigger_efficiency_formula = trigger_efficiency.get_trivial_formula(mjj) for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..."%(args.final_state, int(mass)) rooDataHist = RooDataHist('rooDatahist','rooDathist',RooArgList(mjj),hData) if not args.fitSignal: hSig = inputSig.Get( "h_" + args.final_state + "_" + str(int(mass)) ) if not hSig: raise Exception("Couldn't find histogram " + "h_" + args.final_state + "_" + str(int(mass)) + " in file " + limit_config.get_resonance_shapes(args.analysis, args.model)) # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity) hSig.Scale(signalCrossSection*lumi/hSig.Integral()) # divide by a number that provides roughly an r value of 1-10 rooSigHist = RooDataHist('rooSigHist','rooSigHist',RooArgList(mjj),hSig) print 'Signal acceptance:', (rooSigHist.sumEntries()/hSig.Integral()) # If using fitted signal shapes, load the signal PDF if args.fitSignal: print "[create_datacards] Loading fitted signal PDFs from " + analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)) f_signal_pdfs = TFile(analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)), "READ") w_signal = f_signal_pdfs.Get("w_signal") input_parameters = signal_fits.get_parameters(w_signal.pdf("signal")) # Make a new PDF with nuisance parameters signal_pdf_notrig, signal_vars = signal_fits.make_signal_pdf_systematic("bukin", mjj, mass=mass) signal_pdf_name = signal_pdf_notrig.GetName() signal_pdf_notrig.SetName(signal_pdf_name + "_notrig") #signal_pdf = RooProdPdf(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_pdf) signal_pdf = RooEffProd(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_formula) # Copy input parameter values signal_vars["xp_0"].setVal(input_parameters["xp"][0]) signal_vars["xp_0"].setError(input_parameters["xp"][1]) signal_vars["xp_0"].setConstant() signal_vars["sigp_0"].setVal(input_parameters["sigp"][0]) signal_vars["sigp_0"].setError(input_parameters["sigp"][1]) signal_vars["sigp_0"].setConstant() signal_vars["xi_0"].setVal(input_parameters["xi"][0]) signal_vars["xi_0"].setError(input_parameters["xi"][1]) signal_vars["xi_0"].setConstant() signal_vars["rho1_0"].setVal(input_parameters["rho1"][0]) signal_vars["rho1_0"].setError(input_parameters["rho1"][1]) signal_vars["rho1_0"].setConstant() signal_vars["rho2_0"].setVal(input_parameters["rho2"][0]) signal_vars["rho2_0"].setError(input_parameters["rho2"][1]) signal_vars["rho2_0"].setConstant() f_signal_pdfs.Close() signal_parameters = {} signal_pdfs_notrig = {} signal_pdfs = {} signal_norms = {} background_pdfs = {} background_pdfs_notrig = {} background_parameters = {} background_norms = {} signal_epdfs = {} background_epdfs = {} models = {} fit_results = {} for fit_function in fit_functions: print "[create_datacards] INFO : On fit function {}".format(fit_function) if args.fitSignal: # Make a copy of the signal PDF, so that each fitTo call uses its own copy. # The copy should have all variables set constant. #signal_pdfs[fit_function], signal_parameters[fit_function] = signal_fits.copy_signal_pdf("bukin", signal_pdf, mjj, tag=fit_function, include_systematics=True) signal_pdfs_notrig[fit_function] = ROOT.RooBukinPdf(signal_pdf_notrig, signal_pdf_notrig.GetName() + "_" + fit_function) signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_formula) #signal_pdfs[fit_function] = RooProdPdf(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_pdf) iterator = signal_pdfs_notrig[fit_function].getVariables().createIterator() this_parameter = iterator.Next() while this_parameter: this_parameter.setConstant() this_parameter = iterator.Next() else: signal_pdfs[fit_function] = RooHistPdf('signal_' + fit_function,'signal_' + fit_function, RooArgSet(mjj), rooSigHist) signal_norms[fit_function] = RooRealVar('signal_norm_' + fit_function, 'signal_norm_' + fit_function, 0., 0., 1e+05) if args.fitBonly: signal_norms[fit_function].setConstant() background_pdfs_notrig[fit_function], background_parameters[fit_function] = make_background_pdf(fit_function, mjj, collision_energy=8000.) background_pdf_name = background_pdfs_notrig[fit_function].GetName() background_pdfs_notrig[fit_function].SetName(background_pdf_name + "_notrig") background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_formula) #background_pdfs[fit_function] = RooProdPdf(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_pdf) #background_pdfs[fit_function] = background_pdfs_notrig[fit_function] #background_pdfs[fit_function].SetName(background_pdf_name) # Initial values if "trigbbh" in args.analysis: if fit_function == "f3": background_parameters[fit_function]["p1"].setVal(55.) background_parameters[fit_function]["p1"].setMin(20.) background_parameters[fit_function]["p2"].setVal(8.) elif fit_function == "f4": background_parameters[fit_function]["p1"].setVal(28.) background_parameters[fit_function]["p2"].setVal(-22.) background_parameters[fit_function]["p3"].setVal(10.) elif "trigbbl" in args.analysis: if fit_function == "f3": background_parameters[fit_function]["p1"].setVal(82.) background_parameters[fit_function]["p1"].setMin(60.) background_parameters[fit_function]["p2"].setVal(8.) elif fit_function == "f4": background_parameters[fit_function]["p1"].setVal(41.) background_parameters[fit_function]["p2"].setVal(-45.) background_parameters[fit_function]["p3"].setVal(10.) data_integral = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norms[fit_function] = RooRealVar('background_' + fit_function + '_norm', 'background_' + fit_function + '_norm', data_integral, 0., 1.e8) signal_epdfs[fit_function] = RooExtendPdf('esignal_' + fit_function, 'esignal_' + fit_function, signal_pdfs[fit_function], signal_norms[fit_function]) background_epdfs[fit_function] = RooExtendPdf('ebackground_' + fit_function, 'ebackground_' + fit_function, background_pdfs[fit_function], background_norms[fit_function]) models[fit_function] = RooAddPdf('model_' + fit_function, 's+b', RooArgList(background_epdfs[fit_function], signal_epdfs[fit_function])) if args.runFit: print "[create_datacards] INFO : Starting fit with function {}".format(fit_function) fit_results[fit_function] = models[fit_function].fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy), RooFit.Verbose(0)) print "[create_datacards] INFO : Done with fit {}. Printing results.".format(fit_function) fit_results[fit_function].Print() print "[create_datacards] DEBUG : End args.runFit if block." # needed if want to evaluate limits without background systematics if args.fixBkg: background_norms[fit_function].setConstant() for par_name, par in background_parameters[fit_function].iteritems(): par.setConstant() # ----------------------------------------- #signal_pdfs_syst = {} # JES and JER uncertainties if args.fitSignal: print "[create_datacards] INFO : Getting signal PDFs from " + analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)) f_signal_pdfs = TFile(analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))) w_signal = f_signal_pdfs.Get("w_signal") if "jes" in systematics: xp_central = signal_vars["xp_0"].getVal() #print w_signal.pdf("signal__JESUp") #print signal_fits.get_parameters(w_signal.pdf("signal__JESUp")) xp_up = signal_fits.get_parameters(w_signal.pdf("signal__JESUp"))["xpJESUp"][0] xp_down = signal_fits.get_parameters(w_signal.pdf("signal__JESDown"))["xpJESDown"][0] signal_vars["dxp"].setVal(max(abs(xp_up - xp_central), abs(xp_down - xp_central))) if signal_vars["dxp"].getVal() > 2 * mass * 0.1: print "[create_datacards] WARNING : Large dxp value. dxp = {}, xp_down = {}, xp_central = {}, xp_up = {}".format(signal_vars["dxp"].getVal(), xp_down, xp_central, xp_up) signal_vars["alpha_jes"].setVal(0.) signal_vars["alpha_jes"].setConstant(False) else: signal_vars["dxp"].setVal(0.) signal_vars["alpha_jes"].setVal(0.) signal_vars["alpha_jes"].setConstant() signal_vars["dxp"].setError(0.) signal_vars["dxp"].setConstant() if "jer" in systematics: sigp_central = signal_vars["sigp_0"].getVal() sigp_up = signal_fits.get_parameters(w_signal.pdf("signal__JERUp"))["sigpJERUp"][0] sigp_down = signal_fits.get_parameters(w_signal.pdf("signal__JERDown"))["sigpJERDown"][0] signal_vars["dsigp"].setVal(max(abs(sigp_up - sigp_central), abs(sigp_down - sigp_central))) signal_vars["alpha_jer"].setVal(0.) signal_vars["alpha_jer"].setConstant(False) else: signal_vars["dsigp"].setVal(0.) signal_vars["alpha_jer"].setVal(0.) signal_vars["alpha_jer"].setConstant() signal_vars["dsigp"].setError(0.) signal_vars["dsigp"].setConstant() #for variation in ["JERUp", "JERDown"]: # signal_pdfs_syst[variation] = w_signal.pdf("signal__" + variation) #for variation, pdf in signal_pdfs_syst.iteritems(): # signal_parameters = pdf.getVariables() # iter = signal_parameters.createIterator() # var = iter.Next() # while var: # var.setConstant() # var = iter.Next() f_signal_pdfs.Close() else: # dictionaries holding systematic variations of the signal shape hSig_Syst = {} hSig_Syst_DataHist = {} sigCDF = TGraph(hSig.GetNbinsX()+1) if "jes" in systematics or "jer" in systematics: sigCDF.SetPoint(0,0.,0.) integral = 0. for i in range(1, hSig.GetNbinsX()+1): x = hSig.GetXaxis().GetBinLowEdge(i+1) integral = integral + hSig.GetBinContent(i) sigCDF.SetPoint(i,x,integral) if "jes" in systematics: hSig_Syst['JESUp'] = copy.deepcopy(hSig) hSig_Syst['JESDown'] = copy.deepcopy(hSig) if "jer" in systematics: hSig_Syst['JERUp'] = copy.deepcopy(hSig) hSig_Syst['JERDown'] = copy.deepcopy(hSig) # reset signal histograms for key in hSig_Syst.keys(): hSig_Syst[key].Reset() hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key) # produce JES signal shapes if "jes" in systematics: for i in range(1, hSig.GetNbinsX()+1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i+1) jes = 1. - systematics["jes"] xLowPrime = jes*xLow xUpPrime = jes*xUp hSig_Syst['JESUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jes = 1. + systematics["jes"] xLowPrime = jes*xLow xUpPrime = jes*xUp hSig_Syst['JESDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JESUp'] = RooDataHist('hSig_JESUp','hSig_JESUp',RooArgList(mjj),hSig_Syst['JESUp']) hSig_Syst_DataHist['JESDown'] = RooDataHist('hSig_JESDown','hSig_JESDown',RooArgList(mjj),hSig_Syst['JESDown']) # produce JER signal shapes if "jer" in systematics: for i in range(1, hSig.GetNbinsX()+1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i+1) jer = 1. - systematics["jer"] xLowPrime = jer*(xLow-float(mass))+float(mass) xUpPrime = jer*(xUp-float(mass))+float(mass) hSig_Syst['JERUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jer = 1. + systematics["jer"] xLowPrime = jer*(xLow-float(mass))+float(mass) xUpPrime = jer*(xUp-float(mass))+float(mass) hSig_Syst['JERDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JERUp'] = RooDataHist('hSig_JERUp','hSig_JERUp',RooArgList(mjj),hSig_Syst['JERUp']) hSig_Syst_DataHist['JERDown'] = RooDataHist('hSig_JERDown','hSig_JERDown',RooArgList(mjj),hSig_Syst['JERDown']) # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') wsName = 'workspace_' + args.final_state + '_m' + str(mass) + postfix + '.root' w = RooWorkspace('w','workspace') if args.fitSignal: signal_pdf.SetName("signal") getattr(w,'import')(signal_pdf,RooFit.Rename("signal")) # Create a norm variable "signal_norm" which normalizes the PDF to unity. norm = args.lumi #signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", 1. / norm, 0.1 / norm, 10. / norm) #if args.analysis == "trigbbh_CSVTM" and mass >= 1100: signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm/100., norm/100. / 10., norm * 10.) #else: # signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm, norm / 10., norm * 10.) print "[create_datacards] INFO : Set signal norm to {}".format(signal_norm.getVal()) signal_norm.setConstant() getattr(w,'import')(signal_norm,ROOT.RooCmdArg()) #if "jes" in systematics: # getattr(w,'import')(signal_pdfs_syst['JESUp'],RooFit.Rename("signal__JESUp")) # getattr(w,'import')(signal_pdfs_syst['JESDown'],RooFit.Rename("signal__JESDown")) #if "jer" in systematics: # getattr(w,'import')(signal_pdfs_syst['JERUp'],RooFit.Rename("signal__JERUp")) # getattr(w,'import')(signal_pdfs_syst['JERDown'],RooFit.Rename("signal__JERDown")) else: getattr(w,'import')(rooSigHist,RooFit.Rename("signal")) if "jes" in systematics: getattr(w,'import')(hSig_Syst_DataHist['JESUp'],RooFit.Rename("signal__JESUp")) getattr(w,'import')(hSig_Syst_DataHist['JESDown'],RooFit.Rename("signal__JESDown")) if "jer" in systematics: getattr(w,'import')(hSig_Syst_DataHist['JERUp'],RooFit.Rename("signal__JERUp")) getattr(w,'import')(hSig_Syst_DataHist['JERDown'],RooFit.Rename("signal__JERDown")) if args.decoBkg: getattr(w,'import')(background_deco,ROOT.RooCmdArg()) else: for fit_function in fit_functions: print "Importing background PDF" print background_pdfs[fit_function] background_pdfs[fit_function].Print() getattr(w,'import')(background_pdfs[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function), RooFit.RecycleConflictNodes()) w.pdf("background_" + fit_function).Print() getattr(w,'import')(background_norms[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function + "_norm")) getattr(w,'import')(fit_results[fit_function]) getattr(w,'import')(signal_norms[fit_function],ROOT.RooCmdArg()) if args.fitBonly: getattr(w,'import')(models[fit_function],ROOT.RooCmdArg(),RooFit.RecycleConflictNodes()) getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs")) w.Print() print "Starting save" if args.output_path: if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ): os.mkdir( os.path.join(os.getcwd(),args.output_path) ) print "[create_datacards] INFO : Writing workspace to file {}".format(os.path.join(args.output_path,wsName)) w.writeToFile(os.path.join(args.output_path,wsName)) else: print "[create_datacards] INFO : Writing workspace to file {}".format(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitBonly=args.fitBonly, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) w.writeToFile(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitBonly=args.fitBonly, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) # Clean up for name, obj in signal_norms.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_pdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_pdfs_notrig.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_norms.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_pdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_pdfs_notrig.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_epdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_epdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in fit_results.iteritems(): if obj: obj.IsA().Destructor(obj) for name, dict_l2 in background_parameters.iteritems(): for name2, obj in dict_l2.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in models.iteritems(): if obj: obj.IsA().Destructor(obj) rooDataHist.IsA().Destructor(rooDataHist) w.IsA().Destructor(w) # Make datacards only if S+B fitted if not args.fitBonly: beffUnc = 0.3 boffUnc = 0.06 for fit_function in fit_functions: if args.output_path: dcName = 'datacard_' + args.final_state + '_m' + str(mass) + postfix + '_' + fit_function + '.txt' print "[create_datacards] INFO : Writing datacard to file {}".format(os.path.join(args.output_path,dcName)) datacard = open(os.path.join(args.output_path,dcName),'w') else: print "[create_datacards] INFO : Writing datacard to file {}".format(limit_config.get_datacard_filename(args.analysis, args.model, mass, fit_function, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) datacard = open(limit_config.get_datacard_filename(args.analysis, args.model, mass, fit_function, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger), 'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if ("jes" in systematics or "jer" in systematics) and not args.fitSignal: if args.output_path: datacard.write('shapes * * '+wsName+' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: datacard.write('shapes * * '+os.path.basename(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger))+' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: if args.output_path: datacard.write('shapes * * '+wsName+' w:$PROCESS\n') else: datacard.write('shapes * * '+os.path.basename(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger))+' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background_' + fit_function + '\n') datacard.write('process 0 1\n') if args.fitSignal: datacard.write('rate 1 1\n') else: datacard.write('rate -1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n'%(1.+systematics["luminosity"])) datacard.write('beff lnN %f -\n'%(1.+beffUnc)) datacard.write('boff lnN %f -\n'%(1.+boffUnc)) #datacard.write('bkg lnN - 1.03\n') if args.fitSignal: if "jes" in systematics: datacard.write("alpha_jes param 0.0 1.0\n") if "jer" in systematics: datacard.write("alpha_jer param 0.0 1.0\n") else: if "jes" in systematics: datacard.write('JES shape 1 -\n') if "jer" in systematics: datacard.write('JER shape 1 -\n') # flat parameters --- flat prior datacard.write('background_' + fit_function + '_norm flatParam\n') if args.decoBkg: datacard.write('deco_eig1 flatParam\n') datacard.write('deco_eig2 flatParam\n') else: for par_name, par in background_parameters[fit_function].iteritems(): datacard.write(fit_function + "_" + par_name + ' flatParam\n') datacard.close() print "[create_datacards] INFO : Done with this datacard" #print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) ) print "All done."
#signalEfficiency = options.sigEff ######## some options are incompatible, to avoid errors ### if bkgConst: bkgNuisance = False if bkgNuisance: bkgConst = False if histpdfSig: fitSig = False if histpdfBkg: fitDat = False ############# gROOT.SetBatch(ROOT.kTRUE) gROOT.Reset() setTDRStyle() gROOT.ForceStyle() gROOT.SetStyle('tdrStyle') RooMsgService.instance().setSilentMode(ROOT.kTRUE) RooMsgService.instance().setStreamStatus(0, ROOT.kFALSE) RooMsgService.instance().setStreamStatus(1, ROOT.kFALSE) # ----------------------------------------- # get histograms ## ---- CERN ------- #PATH = '/cmshome/gdimperi/Dijet/CMSDIJETrepo/CMSSW_7_2_1_DiJet/src/CMSDIJET/DijetRootTreeAnalyzer/output/' # #filenameSig = '/cmshome/gdimperi/Dijet/CMSDIJETrepo/CMSSW_7_2_1_DiJet/src/CMSDIJET/DijetRootTreeMaker/test/Resonance_Shapes_qg_PU20_13TeV_newJEC.root' ##filenameSig = PATH+'rootfile_QstarToJJ_M_'+str(mass)+'_Tune4C_13TeV_pythia8__Phys14DR-PU20bx25_PHYS14_25_V1-v1__MINIAODSIM_reduced_skim.root' ##pseudodatatset ##filenameDat = PATH+'../test_fit/dijetFitResults_FuncType0_nParFit4_MC_1fb-1_Dinko.root' #filenameDat = "/cmshome/gdimperi/Dijet/CMSDIJETrepo/CMSSW_7_2_1_DiJet/src/CMSDIJET/DijetRootTreeAnalyzer/test_fit/toys_Bonly.root" # ##QCD MC
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2" # input parameters parser = ArgumentParser( description= 'Script that creates combine datacards and corresponding RooFit workspaces', epilog=usage) parser.add_argument("--inputData", dest="inputData", required=True, help="Input data spectrum", metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", required=True, help="Data histogram name", metavar="DATA_HISTNAME") parser.add_argument("--inputSig", dest="inputSig", required=True, help="Input signal shapes", metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", required=True, help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)") parser.add_argument( "-o", "--output_path", dest="output_path", required=True, help="Output path where datacards and workspaces will be stored", metavar="OUTPUT_PATH") parser.add_argument( "-l", "--lumi", dest="lumi", required=True, default=1000., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument( "--massMin", dest="massMin", default=500, type=int, help= "Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument( "--massMax", dest="massMax", default=1200, type=int, help= "Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument( "--p1", dest="p1", default=5.0000e-03, type=float, help="Fit function p1 parameter (default: %(default)e)", metavar="P1") parser.add_argument( "--p2", dest="p2", default=9.1000e+00, type=float, help="Fit function p2 parameter (default: %(default)e)", metavar="P2") parser.add_argument( "--p3", dest="p3", default=5.0000e-01, type=float, help="Fit function p3 parameter (default: %(default)e)", metavar="P3") parser.add_argument( "--lumiUnc", dest="lumiUnc", required=True, type=float, help="Relative uncertainty in the integrated luminosity", metavar="LUMI_UNC") parser.add_argument("--jesUnc", dest="jesUnc", type=float, help="Relative uncertainty in the jet energy scale", metavar="JES_UNC") parser.add_argument( "--jerUnc", dest="jerUnc", type=float, help="Relative uncertainty in the jet energy resolution", metavar="JER_UNC") parser.add_argument( "--sqrtS", dest="sqrtS", default=13000., type=float, help="Collision center-of-mass energy (default: %(default).1f)", metavar="SQRTS") parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters") parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") parser.add_argument( "--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)") parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots") parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots") parser.add_argument( "--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)") parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared") parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument( "--mass", type=int, nargs='*', default=1000, help= "Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument( "--massrange", type=int, nargs=3, help="Define a range of masses to be produced. Format: min max step", metavar=('MIN', 'MAX', 'STEP')) mass_group.add_argument("--masslist", help="List containing mass information") args = parser.parse_args() if args.atype == 'hG': fstr = "bbhGGBB" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'hR': fstr = "bbhRS" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'lG': fstr = "bblGGBB" in2 = 'bcorrbin/binmodl.root' else: fstr = "bblRS" in2 = 'bcorrbin/binmodl.root' # check if the output directory exists if not os.path.isdir(os.path.join(os.getcwd(), args.output_path)): os.mkdir(os.path.join(os.getcwd(), args.output_path)) # mass points for which resonance shapes will be produced masses = [] if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX + STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py", "")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0, kFALSE) RooMsgService.instance().setStreamStatus(1, kFALSE) # input data file inputData = TFile(args.inputData) # input data histogram hData = inputData.Get(args.dataHistname) inData2 = TFile(in2) hData2 = inData2.Get('h_data') # input sig file inputSig = TFile(args.inputSig) sqrtS = args.sqrtS # mass variable mjj = RooRealVar('mjj', 'mjj', float(args.massMin), float(args.massMax)) # integrated luminosity and signal cross section lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..." % ( args.final_state, int(mass)) # get signal shape hSig = inputSig.Get("h_" + args.final_state + "_" + str(int(mass))) # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity) hSig.Scale( signalCrossSection * lumi / hSig.Integral() ) # divide by a number that provides roughly an r value of 1-10 rooSigHist = RooDataHist('rooSigHist', 'rooSigHist', RooArgList(mjj), hSig) print 'Signal acceptance:', (rooSigHist.sumEntries() / hSig.Integral()) signal = RooHistPdf('signal', 'signal', RooArgSet(mjj), rooSigHist) signal_norm = RooRealVar('signal_norm', 'signal_norm', 0, -1e+05, 1e+05) signal_norm2 = RooRealVar('signal_norm2', 'signal_norm2', 0, -1e+05, 1e+05) signal_norm3 = RooRealVar('signal_norm3', 'signal_norm3', 0, -1e+05, 1e+05) signal_norm4 = RooRealVar('signal_norm4', 'signal_norm4', 0, -1e+05, 1e+05) signal_norm5 = RooRealVar('signal_norm5', 'signal_norm5', 0, -1e+05, 1e+05) if args.fitBonly: signal_norm.setConstant() signal_norm2.setConstant() signal_norm3.setConstant() signal_norm4.setConstant() signal_norm5.setConstant() p1 = RooRealVar('p1', 'p1', args.p1, 0., 100.) p2 = RooRealVar('p2', 'p2', args.p2, 0., 60.) p3 = RooRealVar('p3', 'p3', args.p3, -10., 10.) p4 = RooRealVar('p4', 'p4', 5.6, -50., 50.) p5 = RooRealVar('p5', 'p5', 10., -50., 50.) p6 = RooRealVar('p6', 'p6', .016, -50., 50.) p7 = RooRealVar('p7', 'p7', 8., -50., 50.) p8 = RooRealVar('p8', 'p8', .22, -50., 50.) p9 = RooRealVar('p9', 'p9', 14.1, -50., 50.) p10 = RooRealVar('p10', 'p10', 8., -50., 50.) p11 = RooRealVar('p11', 'p11', 4.8, -50., 50.) p12 = RooRealVar('p12', 'p12', 7., -50., 50.) p13 = RooRealVar('p13', 'p13', 7., -50., 50.) p14 = RooRealVar('p14', 'p14', 7., -50., 50.) p15 = RooRealVar('p15', 'p15', 1., -50., 50.) p16 = RooRealVar('p16', 'p16', 9., -50., 50.) p17 = RooRealVar('p17', 'p17', 0.6, -50., 50.) if args.fixP3: p3.setConstant() background = RooGenericPdf( 'background', '(pow(1-@0/%.1f,@1)/pow(@0/%.1f,@2+@3*log(@0/%.1f)))' % (sqrtS, sqrtS, sqrtS), RooArgList(mjj, p1, p2, p3)) dataInt = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norm = RooRealVar('background_norm', 'background_norm', dataInt, 0., 1e+08) background2 = RooGenericPdf( 'background2', '(pow(@0/%.1f,-@1)*pow(1-@0/%.1f,@2))' % (sqrtS, sqrtS), RooArgList(mjj, p4, p5)) dataInt2 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background2_norm = RooRealVar('background2_norm', 'background2_norm', dataInt2, 0., 1e+08) background3 = RooGenericPdf('background3', '(1/pow(@1+@0/%.1f,@2))' % (sqrtS), RooArgList(mjj, p6, p7)) dataInt3 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background3_norm = RooRealVar('background3_norm', 'background3_norm', dataInt3, 0., 1e+08) background4 = RooGenericPdf( 'background4', '(1/pow(@1+@2*@0/%.1f+pow(@0/%.1f,2),@3))' % (sqrtS, sqrtS), RooArgList(mjj, p8, p9, p10)) dataInt4 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background4_norm = RooRealVar('background4_norm', 'background4_norm', dataInt4, 0., 1e+08) background5 = RooGenericPdf( 'background5', '(pow(@0/%.1f,-@1)*pow(1-pow(@0/%.1f,1/3),@2))' % (sqrtS, sqrtS), RooArgList(mjj, p11, p12)) dataInt5 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background5_norm = RooRealVar('background5_norm', 'background5_norm', dataInt5, 0., 1e+08) background6 = RooGenericPdf( 'background6', '(pow(@0/%.1f,2)+@1*@0/%.1f+@2)' % (sqrtS, sqrtS), RooArgList(mjj, p13, p14)) dataInt6 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norm6 = RooRealVar('background_norm6', 'background_norm6', dataInt6, 0., 1e+08) background7 = RooGenericPdf( 'background7', '((-1+@1*@0/%.1f)*pow(@0/%.1f,@2+@3*log(@0/%.1f)))' % (sqrtS, sqrtS, sqrtS), RooArgList(mjj, p15, p16, p17)) dataInt7 = hData.Integral( hData.GetXaxis().FindBin(float(args.massMin)), hData.GetXaxis().FindBin(float(args.massMax))) background_norm7 = RooRealVar('background_norm7', 'background_norm7', dataInt7, 0., 1e+08) #Extend PDFs exts = RooExtendPdf('extsignal', 'Extended Signal Pdf', signal, signal_norm) extb = RooExtendPdf('extbackground', 'Extended Background Pdf', background, background_norm) exts2 = RooExtendPdf('extsignal2', 'Extended Signal Pdf2', signal, signal_norm2) extb2 = RooExtendPdf('extbackground2', 'Extended Background Pdf2', background2, background2_norm) exts3 = RooExtendPdf('extsignal3', 'Extended Signal Pdf3', signal, signal_norm3) extb3 = RooExtendPdf('extbackground3', 'Extended Background Pdf3', background3, background3_norm) exts4 = RooExtendPdf('extsignal4', 'Extended Signal Pdf4', signal, signal_norm4) extb4 = RooExtendPdf('extbackground4', 'Extended Background Pdf4', background4, background4_norm) exts5 = RooExtendPdf('extsignal5', 'Extended Signal Pdf5', signal, signal_norm5) extb5 = RooExtendPdf('extbackground5', 'Extended Background Pdf5', background5, background5_norm) # S+B model model = RooAddPdf("model", "s+b", RooArgList(extb, exts)) model2 = RooAddPdf("model2", "s+b2", RooArgList(extb2, exts2)) model3 = RooAddPdf("model3", "s+b3", RooArgList(extb3, exts3)) model4 = RooAddPdf("model4", "s+b4", RooArgList(extb4, exts4)) model5 = RooAddPdf("model5", "s+b5", RooArgList(extb5, exts5)) #model6 = RooAddPdf("model6","s+b6",RooArgList(background6,signal),RooArgList(background_norm6,signal_norm)) #model7 = RooAddPdf("model7","s+b7",RooArgList(background7,signal),RooArgList(background_norm7,signal_norm)) rooDataHist = RooDataHist('rooDatahist', 'rooDathist', RooArgList(mjj), hData) if args.runFit: mframe = mjj.frame() rooDataHist.plotOn(mframe, ROOT.RooFit.Name("setonedata")) res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframe, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res2 = model2.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model2.plotOn(mframe, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res3 = model3.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model3.plotOn(mframe, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res4 = model4.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model4.plotOn(mframe, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res5 = model5.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy)) # model5.plotOn(mframe, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) # res6 = model6.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model6.plotOn(mframe, ROOT.RooFit.Name("model6"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kPink)) # res7 = model7.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model7.plotOn(mframe, ROOT.RooFit.Name("model7"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kAzure)) rooDataHist2 = RooDataHist('rooDatahist2', 'rooDathist2', RooArgList(mjj), hData2) # rooDataHist2.plotOn(mframe, ROOT.RooFit.Name("data")) if args.pyes: c = TCanvas("c", "c", 800, 800) mframe.SetAxisRange(300., 1300.) c.SetLogy() # mframe.SetMaximum(10) # mframe.SetMinimum(1) mframe.Draw() fitname = args.pdir + '/5funcfit_m' + str(mass) + fstr + '.pdf' c.SaveAs(fitname) # cpull = TCanvas("cpull","cpull",800,800) # pulls = mframe.pullHist("data","model1") # pulls.Draw("ABX") # pullname = args.pdir+'/pull_m'+str(mass)+fstr+'.pdf' # cpull.SaveAs(pullname) # cpull2 = TCanvas("cpull2","cpull2",800,800) # pulls2 = mframe.pullHist("setonedata","model1") # pulls2.Draw("ABX") # pull2name = args.pdir+'/pull2_m'+str(mass)+fstr+'.pdf' # cpull2.SaveAs(pull2name) if args.widefit: mframew = mjj.frame() rooDataHist2.plotOn(mframew, ROOT.RooFit.Name("data")) res6 = model.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframew, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res7 = model2.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model2.plotOn(mframew, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res8 = model3.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model3.plotOn(mframew, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res9 = model4.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model4.plotOn(mframew, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res10 = model5.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model5.plotOn(mframew, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) if args.pyes: c = TCanvas("c", "c", 800, 800) mframew.SetAxisRange(300., 1300.) c.SetLogy() # mframew.SetMaximum(10) # mframew.SetMinimum(1) mframew.Draw() fitname = args.pdir + '/5funcfittowide_m' + str( mass) + fstr + '.pdf' c.SaveAs(fitname) cpull = TCanvas("cpull", "cpull", 800, 800) pulls = mframew.pullHist("data", "model1") pulls.Draw("ABX") pullname = args.pdir + '/pullwidefit_m' + str( mass) + fstr + '.pdf' cpull.SaveAs(pullname) if args.chi2: fullInt = model.createIntegral(RooArgSet(mjj)) norm = dataInt / fullInt.getVal() chi1 = 0. fullInt2 = model2.createIntegral(RooArgSet(mjj)) norm2 = dataInt2 / fullInt2.getVal() chi2 = 0. fullInt3 = model3.createIntegral(RooArgSet(mjj)) norm3 = dataInt3 / fullInt3.getVal() chi3 = 0. fullInt4 = model4.createIntegral(RooArgSet(mjj)) norm4 = dataInt4 / fullInt4.getVal() chi4 = 0. fullInt5 = model5.createIntegral(RooArgSet(mjj)) norm5 = dataInt5 / fullInt5.getVal() chi5 = 0. for i in range(args.massMin, args.massMax): new = 0 new2 = 0 new3 = 0 new4 = 0 new5 = 0 height = hData.GetBinContent(i) xLow = hData.GetXaxis().GetBinLowEdge(i) xUp = hData.GetXaxis().GetBinLowEdge(i + 1) obs = height * (xUp - xLow) mjj.setRange("intrange", xLow, xUp) integ = model.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp = integ.getVal() * norm new = pow(exp - obs, 2) / exp chi1 = chi1 + new integ2 = model2.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp2 = integ2.getVal() * norm2 new2 = pow(exp2 - obs, 2) / exp2 chi2 = chi2 + new2 integ3 = model3.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp3 = integ3.getVal() * norm3 new3 = pow(exp3 - obs, 2) / exp3 chi3 = chi3 + new3 integ4 = model4.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp4 = integ4.getVal() * norm4 if exp4 != 0: new4 = pow(exp4 - obs, 2) / exp4 else: new4 = 0 chi4 = chi4 + new4 integ5 = model5.createIntegral( RooArgSet(mjj), ROOT.RooFit.NormSet(RooArgSet(mjj)), ROOT.RooFit.Range("intrange")) exp5 = integ5.getVal() * norm5 new5 = pow(exp5 - obs, 2) / exp5 chi5 = chi5 + new5 print "chi1 %d " % (chi1) print "chi2 %d " % (chi2) print "chi3 %d " % (chi3) print "chi4 %d " % (chi4) print "chi5 %d " % (chi5) if not args.decoBkg: print " " res.Print() res2.Print() res3.Print() res4.Print() res5.Print() # res6.Print() # res7.Print() # decorrelated background parameters for Bayesian limits if args.decoBkg: signal_norm.setConstant() res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) res.Print() ## temp workspace for the PDF diagonalizer w_tmp = RooWorkspace("w_tmp") deco = PdfDiagonalizer("deco", w_tmp, res) # here diagonalizing only the shape parameters since the overall normalization is already decorrelated background_deco = deco.diagonalize(background) print "##################### workspace for decorrelation" w_tmp.Print("v") print "##################### original parameters" background.getParameters(rooDataHist).Print("v") print "##################### decorrelated parameters" # needed if want to evaluate limits without background systematics if args.fixBkg: w_tmp.var("deco_eig1").setConstant() w_tmp.var("deco_eig2").setConstant() if not args.fixP3: w_tmp.var("deco_eig3").setConstant() background_deco.getParameters(rooDataHist).Print("v") print "##################### original pdf" background.Print() print "##################### decorrelated pdf" background_deco.Print() # release signal normalization signal_norm.setConstant(kFALSE) # set the background normalization range to +/- 5 sigma bkg_val = background_norm.getVal() bkg_error = background_norm.getError() background_norm.setMin(bkg_val - 5 * bkg_error) background_norm.setMax(bkg_val + 5 * bkg_error) background_norm.Print() # change background PDF names background.SetName("background_old") background_deco.SetName("background") # needed if want to evaluate limits without background systematics if args.fixBkg: background_norm.setConstant() p1.setConstant() p2.setConstant() p3.setConstant() # ----------------------------------------- # dictionaries holding systematic variations of the signal shape hSig_Syst = {} hSig_Syst_DataHist = {} sigCDF = TGraph(hSig.GetNbinsX() + 1) # JES and JER uncertainties if args.jesUnc != None or args.jerUnc != None: sigCDF.SetPoint(0, 0., 0.) integral = 0. for i in range(1, hSig.GetNbinsX() + 1): x = hSig.GetXaxis().GetBinLowEdge(i + 1) integral = integral + hSig.GetBinContent(i) sigCDF.SetPoint(i, x, integral) if args.jesUnc != None: hSig_Syst['JESUp'] = copy.deepcopy(hSig) hSig_Syst['JESDown'] = copy.deepcopy(hSig) if args.jerUnc != None: hSig_Syst['JERUp'] = copy.deepcopy(hSig) hSig_Syst['JERDown'] = copy.deepcopy(hSig) # reset signal histograms for key in hSig_Syst.keys(): hSig_Syst[key].Reset() hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key) # produce JES signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX() + 1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i + 1) jes = 1. - args.jesUnc xLowPrime = jes * xLow xUpPrime = jes * xUp hSig_Syst['JESUp'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jes = 1. + args.jesUnc xLowPrime = jes * xLow xUpPrime = jes * xUp hSig_Syst['JESDown'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JESUp'] = RooDataHist('hSig_JESUp', 'hSig_JESUp', RooArgList(mjj), hSig_Syst['JESUp']) hSig_Syst_DataHist['JESDown'] = RooDataHist( 'hSig_JESDown', 'hSig_JESDown', RooArgList(mjj), hSig_Syst['JESDown']) if args.jyes: c2 = TCanvas("c2", "c2", 800, 800) mframe2 = mjj.frame(ROOT.RooFit.Title("JES One Sigma Shifts")) mframe2.SetAxisRange(args.massMin, args.massMax) hSig_Syst_DataHist['JESUp'].plotOn( mframe2, ROOT.RooFit.Name("JESUP"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JESDown'].plotOn( mframe2, ROOT.RooFit.Name("JESDOWN"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe2, ROOT.RooFit.DataError(2), ROOT.RooFit.Name("SIG"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe2.Draw() mframe2.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7, 0.8, 0.9, 0.9) leg.SetFillColor(0) leg.AddEntry(mframe2.findObject("SIG"), "Signal Model", "l") leg.AddEntry(mframe2.findObject("JESUP"), "+1 Sigma", "l") leg.AddEntry(mframe2.findObject("JESDOWN"), "-1 Sigma", "l") leg.Draw() jesname = args.pdir + '/jes_m' + str(mass) + fstr + '.pdf' c2.SaveAs(jesname) # produce JER signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX() + 1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i + 1) jer = 1. - args.jerUnc xLowPrime = jer * (xLow - float(mass)) + float(mass) xUpPrime = jer * (xUp - float(mass)) + float(mass) hSig_Syst['JERUp'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jer = 1. + args.jerUnc xLowPrime = jer * (xLow - float(mass)) + float(mass) xUpPrime = jer * (xUp - float(mass)) + float(mass) hSig_Syst['JERDown'].SetBinContent( i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JERUp'] = RooDataHist('hSig_JERUp', 'hSig_JERUp', RooArgList(mjj), hSig_Syst['JERUp']) hSig_Syst_DataHist['JERDown'] = RooDataHist( 'hSig_JERDown', 'hSig_JERDown', RooArgList(mjj), hSig_Syst['JERDown']) if args.jyes: c3 = TCanvas("c3", "c3", 800, 800) mframe3 = mjj.frame(ROOT.RooFit.Title("JER One Sigma Shifts")) mframe3.SetAxisRange(args.massMin, args.massMax) hSig_Syst_DataHist['JERUp'].plotOn( mframe3, ROOT.RooFit.Name("JERUP"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JERDown'].plotOn( mframe3, ROOT.RooFit.Name("JERDOWN"), ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe3, ROOT.RooFit.DrawOption("L"), ROOT.RooFit.Name("SIG"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe3.Draw() mframe3.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7, 0.8, 0.9, 0.9) leg.SetFillColor(0) leg.AddEntry(mframe3.findObject("SIG"), "Signal Model", "l") leg.AddEntry(mframe3.findObject("JERUP"), "+1 Sigma", "l") leg.AddEntry(mframe3.findObject("JERDOWN"), "-1 Sigma", "l") leg.Draw() jername = args.pdir + '/jer_m' + str(mass) + fstr + '.pdf' c3.SaveAs(jername) # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') dcName = 'datacard_' + args.final_state + '_m' + str( mass) + postfix + '.txt' wsName = 'workspace_' + args.final_state + '_m' + str( mass) + postfix + '.root' w = RooWorkspace('w', 'workspace') getattr(w, 'import')(rooSigHist, RooFit.Rename("signal")) if args.jesUnc != None: getattr(w, 'import')(hSig_Syst_DataHist['JESUp'], RooFit.Rename("signal__JESUp")) getattr(w, 'import')(hSig_Syst_DataHist['JESDown'], RooFit.Rename("signal__JESDown")) if args.jerUnc != None: getattr(w, 'import')(hSig_Syst_DataHist['JERUp'], RooFit.Rename("signal__JERUp")) getattr(w, 'import')(hSig_Syst_DataHist['JERDown'], RooFit.Rename("signal__JERDown")) if args.decoBkg: getattr(w, 'import')(background_deco, ROOT.RooCmdArg()) else: getattr(w, 'import')(background, ROOT.RooCmdArg(), RooFit.Rename("background")) getattr(w, 'import')(background2, ROOT.RooCmdArg(), RooFit.Rename("background2")) getattr(w, 'import')(background3, ROOT.RooCmdArg(), RooFit.Rename("background3")) getattr(w, 'import')(background4, ROOT.RooCmdArg(), RooFit.Rename("background4")) getattr(w, 'import')(background5, ROOT.RooCmdArg(), RooFit.Rename("background5")) getattr(w, 'import')(background_norm, ROOT.RooCmdArg(), RooFit.Rename("background_norm")) getattr(w, 'import')(background2_norm, ROOT.RooCmdArg(), RooFit.Rename("background2_norm")) getattr(w, 'import')(background3_norm, ROOT.RooCmdArg(), RooFit.Rename("background3_norm")) getattr(w, 'import')(background4_norm, ROOT.RooCmdArg(), RooFit.Rename("background4_norm")) getattr(w, 'import')(background5_norm, ROOT.RooCmdArg(), RooFit.Rename("background5_norm")) getattr(w, 'import')(res) getattr(w, 'import')(res2) getattr(w, 'import')(res3) getattr(w, 'import')(res4) getattr(w, 'import')(res5) getattr(w, 'import')(background_norm, ROOT.RooCmdArg()) getattr(w, 'import')(signal_norm, ROOT.RooCmdArg()) getattr(w, 'import')(rooDataHist, RooFit.Rename("data_obs")) w.Print() w.writeToFile(os.path.join(args.output_path, wsName)) beffUnc = 0.3 boffUnc = 0.06 datacard = open(os.path.join(args.output_path, dcName), 'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if args.jesUnc != None or args.jerUnc != None: datacard.write('shapes * * ' + wsName + ' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: datacard.write('shapes * * ' + wsName + ' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background\n') datacard.write('process 0 1\n') datacard.write('rate -1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n' % (1. + args.lumiUnc)) datacard.write('beff lnN %f -\n' % (1. + beffUnc)) datacard.write('boff lnN %f -\n' % (1. + boffUnc)) datacard.write('bkg lnN - 1.03\n') if args.jesUnc != None: datacard.write('JES shape 1 -\n') if args.jerUnc != None: datacard.write('JER shape 1 -\n') # flat parameters --- flat prior datacard.write('background_norm flatParam\n') if args.decoBkg: datacard.write('deco_eig1 flatParam\n') datacard.write('deco_eig2 flatParam\n') if not args.fixP3: datacard.write('deco_eig3 flatParam\n') else: datacard.write('p1 flatParam\n') datacard.write('p2 flatParam\n') if not args.fixP3: datacard.write('p3 flatParam\n') datacard.close() print '>> Datacards and workspaces created and stored in %s/' % ( os.path.join(os.getcwd(), args.output_path))
from cpyroot.tools.DataMC import DataMCPlot, Histogram from ROOT import RooRealVar, RooPolynomial, RooConstVar, RooDataSet, RooDataHist, RooHistPdf, RooGaussian, RooArgSet, RooAddPdf, RooArgList, RooFit, SetOwnership, RooAbsArg from ROOT import RooMsgService from ROOT import TCanvas RooMsgService.instance().setSilentMode(True) RooMsgService.instance().setGlobalKillBelow(RooFit.ERROR) class BaseFitter(object): def __init__(self, plot): assert (isinstance(plot, DataMCPlot)) self.plot = plot self._make_underlying_model() self._make_dataset() self._make_fit_model() self._fit() def _make_underlying_model(self): self.pdfs = {} self.yields = {} # yields are plain floats self.ryields = {} # keep track of roofit objects for memory management nbins, xmin, xmax = self.plot.histos[0].GetBinning() self.xvar = RooRealVar("x", "x", xmin, xmax) self.xvar.setBins(nbins) self.pdfs = {} self.hists = [] pdfs = RooArgList() yields = RooArgList() for compname, comp in self.plot.histosDict.iteritems(): if comp.weighted.Integral() == 0:
def main(): # usage description usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2" # input parameters parser = ArgumentParser(description='Script that creates combine datacards and corresponding RooFit workspaces',epilog=usage) parser.add_argument("--inputData", dest="inputData", required=True, help="Input data spectrum", metavar="INPUT_DATA") parser.add_argument("--dataHistname", dest="dataHistname", required=True, help="Data histogram name", metavar="DATA_HISTNAME") parser.add_argument("--inputSig", dest="inputSig", required=True, help="Input signal shapes", metavar="INPUT_SIGNAL") parser.add_argument("-f", "--final_state", dest="final_state", required=True, help="Final state (e.g. qq, qg, gg)", metavar="FINAL_STATE") parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)") parser.add_argument("-o", "--output_path", dest="output_path", required=True, help="Output path where datacards and workspaces will be stored", metavar="OUTPUT_PATH") parser.add_argument("-l", "--lumi", dest="lumi", required=True, default=1000., type=float, help="Integrated luminosity in pb-1 (default: %(default).1f)", metavar="LUMI") parser.add_argument("--massMin", dest="massMin", default=500, type=int, help="Lower bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MIN") parser.add_argument("--massMax", dest="massMax", default=1200, type=int, help="Upper bound of the mass range used for fitting (default: %(default)s)", metavar="MASS_MAX") parser.add_argument("--p1", dest="p1", default=5.0000e-03, type=float, help="Fit function p1 parameter (default: %(default)e)", metavar="P1") parser.add_argument("--p2", dest="p2", default=9.1000e+00, type=float, help="Fit function p2 parameter (default: %(default)e)", metavar="P2") parser.add_argument("--p3", dest="p3", default=5.0000e-01, type=float, help="Fit function p3 parameter (default: %(default)e)", metavar="P3") parser.add_argument("--lumiUnc", dest="lumiUnc", required=True, type=float, help="Relative uncertainty in the integrated luminosity", metavar="LUMI_UNC") parser.add_argument("--jesUnc", dest="jesUnc", type=float, help="Relative uncertainty in the jet energy scale", metavar="JES_UNC") parser.add_argument("--jerUnc", dest="jerUnc", type=float, help="Relative uncertainty in the jet energy resolution", metavar="JER_UNC") parser.add_argument("--sqrtS", dest="sqrtS", default=13000., type=float, help="Collision center-of-mass energy (default: %(default).1f)", metavar="SQRTS") parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter") parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit") parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit") parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters") parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters") parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)") parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout") parser.add_argument("--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)") parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots") parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots") parser.add_argument("--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)") parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared") parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist") mass_group = parser.add_mutually_exclusive_group(required=True) mass_group.add_argument("--mass", type=int, nargs = '*', default = 1000, help="Mass can be specified as a single value or a whitespace separated list (default: %(default)i)" ) mass_group.add_argument("--massrange", type=int, nargs = 3, help="Define a range of masses to be produced. Format: min max step", metavar = ('MIN', 'MAX', 'STEP') ) mass_group.add_argument("--masslist", help = "List containing mass information" ) args = parser.parse_args() if args.atype == 'hG': fstr = "bbhGGBB" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'hR': fstr = "bbhRS" in2 = 'bcorrbin/binmodh.root' elif args.atype == 'lG': fstr = "bblGGBB" in2 = 'bcorrbin/binmodl.root' else: fstr = "bblRS" in2 = 'bcorrbin/binmodl.root' # check if the output directory exists if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ): os.mkdir( os.path.join(os.getcwd(),args.output_path) ) # mass points for which resonance shapes will be produced masses = [] if args.massrange != None: MIN, MAX, STEP = args.massrange masses = range(MIN, MAX+STEP, STEP) elif args.masslist != None: # A mass list was provided print "Will create mass list according to", args.masslist masslist = __import__(args.masslist.replace(".py","")) masses = masslist.masses else: masses = args.mass # sort masses masses.sort() # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0,kFALSE) RooMsgService.instance().setStreamStatus(1,kFALSE) # input data file inputData = TFile(args.inputData) # input data histogram hData = inputData.Get(args.dataHistname) inData2 = TFile(in2) hData2 = inData2.Get('h_data') # input sig file inputSig = TFile(args.inputSig) sqrtS = args.sqrtS # mass variable mjj = RooRealVar('mjj','mjj',float(args.massMin),float(args.massMax)) # integrated luminosity and signal cross section lumi = args.lumi signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section for mass in masses: print ">> Creating datacard and workspace for %s resonance with m = %i GeV..."%(args.final_state, int(mass)) # get signal shape hSig = inputSig.Get( "h_" + args.final_state + "_" + str(int(mass)) ) # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity) hSig.Scale(signalCrossSection*lumi/hSig.Integral()) # divide by a number that provides roughly an r value of 1-10 rooSigHist = RooDataHist('rooSigHist','rooSigHist',RooArgList(mjj),hSig) print 'Signal acceptance:', (rooSigHist.sumEntries()/hSig.Integral()) signal = RooHistPdf('signal','signal',RooArgSet(mjj),rooSigHist) signal_norm = RooRealVar('signal_norm','signal_norm',0,-1e+05,1e+05) if args.fitBonly: signal_norm.setConstant() p1 = RooRealVar('p1','p1',args.p1,0.,100.) p2 = RooRealVar('p2','p2',args.p2,0.,60.) p3 = RooRealVar('p3','p3',args.p3,-10.,10.) p4 = RooRealVar('p4','p4',5.6,-50.,50.) p5 = RooRealVar('p5','p5',10.,-50.,50.) p6 = RooRealVar('p6','p6',.016,-50.,50.) p7 = RooRealVar('p7','p7',8.,-50.,50.) p8 = RooRealVar('p8','p8',.22,-50.,50.) p9 = RooRealVar('p9','p9',14.1,-50.,50.) p10 = RooRealVar('p10','p10',8.,-50.,50.) p11 = RooRealVar('p11','p11',4.8,-50.,50.) p12 = RooRealVar('p12','p12',7.,-50.,50.) p13 = RooRealVar('p13','p13',7.,-50.,50.) p14 = RooRealVar('p14','p14',7.,-50.,50.) p15 = RooRealVar('p15','p15',1.,-50.,50.) p16 = RooRealVar('p16','p16',9.,-50.,50.) p17 = RooRealVar('p17','p17',0.6,-50.,50.) if args.fixP3: p3.setConstant() background = RooGenericPdf('background','(pow(1-@0/%.1f,@1)/pow(@0/%.1f,@2+@3*log(@0/%.1f)))'%(sqrtS,sqrtS,sqrtS),RooArgList(mjj,p1,p2,p3)) dataInt = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm = RooRealVar('background_norm','background_norm',dataInt,0.,1e+08) background2 = RooGenericPdf('background2','(pow(@0/%.1f,-@1)*pow(1-@0/%.1f,@2))'%(sqrtS,sqrtS),RooArgList(mjj,p4,p5)) dataInt2 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm2 = RooRealVar('background_norm2','background_norm2',dataInt2,0.,1e+08) background3 = RooGenericPdf('background3','(1/pow(@1+@0/%.1f,@2))'%(sqrtS),RooArgList(mjj,p6,p7)) dataInt3 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm3 = RooRealVar('background_norm3','background_norm3',dataInt3,0.,1e+08) background4 = RooGenericPdf('background4','(1/pow(@1+@2*@0/%.1f+pow(@0/%.1f,2),@3))'%(sqrtS,sqrtS),RooArgList(mjj,p8,p9,p10)) dataInt4 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm4 = RooRealVar('background_norm4','background_norm4',dataInt4,0.,1e+08) background5 = RooGenericPdf('background5','(pow(@0/%.1f,-@1)*pow(1-pow(@0/%.1f,1/3),@2))'%(sqrtS,sqrtS),RooArgList(mjj,p11,p12)) dataInt5 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm5 = RooRealVar('background_norm5','background_norm5',dataInt5,0.,1e+08) background6 = RooGenericPdf('background6','(pow(@0/%.1f,2)+@1*@0/%.1f+@2)'%(sqrtS,sqrtS),RooArgList(mjj,p13,p14)) dataInt6 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm6 = RooRealVar('background_norm6','background_norm6',dataInt6,0.,1e+08) background7 = RooGenericPdf('background7','((-1+@1*@0/%.1f)*pow(@0/%.1f,@2+@3*log(@0/%.1f)))'%(sqrtS,sqrtS,sqrtS),RooArgList(mjj,p15,p16,p17)) dataInt7 = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norm7 = RooRealVar('background_norm7','background_norm7',dataInt7,0.,1e+08) # S+B model model = RooAddPdf("model","s+b",RooArgList(background,signal),RooArgList(background_norm,signal_norm)) model2 = RooAddPdf("model2","s+b2",RooArgList(background2,signal),RooArgList(background_norm2,signal_norm)) model3 = RooAddPdf("model3","s+b3",RooArgList(background3,signal),RooArgList(background_norm3,signal_norm)) model4 = RooAddPdf("model4","s+b4",RooArgList(background4,signal),RooArgList(background_norm4,signal_norm)) model5 = RooAddPdf("model5","s+b5",RooArgList(background5,signal),RooArgList(background_norm5,signal_norm)) model6 = RooAddPdf("model6","s+b6",RooArgList(background6,signal),RooArgList(background_norm6,signal_norm)) model7 = RooAddPdf("model7","s+b7",RooArgList(background7,signal),RooArgList(background_norm7,signal_norm)) rooDataHist = RooDataHist('rooDatahist','rooDathist',RooArgList(mjj),hData) if args.runFit: mframe = mjj.frame() rooDataHist.plotOn(mframe, ROOT.RooFit.Name("setonedata"), ROOT.RooFit.Invisible()) res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframe, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res2 = model2.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model2.plotOn(mframe, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res3 = model3.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model3.plotOn(mframe, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res4 = model4.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model4.plotOn(mframe, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res5 = model5.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model5.plotOn(mframe, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) res6 = model6.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model6.plotOn(mframe, ROOT.RooFit.Name("model6"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kPink)) res7 = model7.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) # model7.plotOn(mframe, ROOT.RooFit.Name("model7"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kAzure)) rooDataHist2 = RooDataHist('rooDatahist2','rooDathist2',RooArgList(mjj),hData2) rooDataHist2.plotOn(mframe, ROOT.RooFit.Name("data")) canvas = TCanvas("cdouble", "cdouble", 800, 1000) gStyle.SetOptStat(0); gStyle.SetOptTitle(0); top = TPad("top", "top", 0., 0.5, 1., 1.) top.SetBottomMargin(0.03) top.Draw() top.SetLogy() bottom = TPad("bottom", "bottom", 0., 0., 1., 0.5) bottom.SetTopMargin(0.02) bottom.SetBottomMargin(0.2) bottom.Draw() top.cd() frame_top = TH1D("frame_top", "frame_top", 100, 526, 1500) frame_top.GetXaxis().SetTitleSize(0) frame_top.GetXaxis().SetLabelSize(0) frame_top.GetYaxis().SetLabelSize(0.04) frame_top.GetYaxis().SetTitleSize(0.04) frame_top.GetYaxis().SetTitle("Events") frame_top.SetMaximum(1000.) frame_top.SetMinimum(0.1) frame_top.Draw("axis") mframe.Draw("p e1 same") bottom.cd() frame_bottom = TH1D("frame_bottom", "frame_bottom", 100, 526, 1500) frame_bottom.GetXaxis().SetTitle("m_{jj} [GeV]") frame_bottom.GetYaxis().SetTitle("Pull") frame_bottom.GetXaxis().SetLabelSize(0.04) frame_bottom.GetXaxis().SetTitleSize(0.06) frame_bottom.GetXaxis().SetLabelOffset(0.01) frame_bottom.GetXaxis().SetTitleOffset(1.1) frame_bottom.GetYaxis().SetLabelSize(0.04) frame_bottom.GetYaxis().SetTitleSize(0.04) frame_bottom.GetYaxis().SetTitleOffset(0.85) frame_bottom.SetMaximum(4.) frame_bottom.SetMinimum(-3.) frame_bottom.Draw("axis") zero = TLine(526., 0., 1500., 0.) zero.SetLineColor(ROOT.EColor.kBlack) zero.SetLineStyle(1) zero.SetLineWidth(2) zero.Draw("same") # Ratio histogram with no errors (not so well defined, since this isn't a well-defined efficiency) newHist = mframe.getHist("data") curve = mframe.getObject(1) hresid = newHist.makePullHist(curve,kTRUE) resframe = mjj.frame() mframe.SetAxisRange(526.,1500.) resframe.addPlotable(hresid,"B X") resframe.Draw("same") canvas.cd() canvas.SaveAs("testdouble.pdf") if args.pyes: c = TCanvas("c","c",800,800) mframe.SetAxisRange(300.,1300.) c.SetLogy() # mframe.SetMaximum(10) # mframe.SetMinimum(1) mframe.Draw() fitname = args.pdir+'/5funcfit_m'+str(mass)+fstr+'.pdf' c.SaveAs(fitname) cpull = TCanvas("cpull","cpull",800,800) pulls = mframe.pullHist("data","model3") pulls.Draw("ABX") pullname = args.pdir+'/pull_m'+str(mass)+fstr+'.pdf' cpull.SaveAs(pullname) cpull2 = TCanvas("cpull2","cpull2",800,800) pulls2 = mframe.pullHist("setonedata","model1") pulls2.Draw("ABX") pull2name = args.pdir+'/pull2_m'+str(mass)+fstr+'.pdf' cpull2.SaveAs(pull2name) if args.widefit: mframew = mjj.frame() rooDataHist2.plotOn(mframew, ROOT.RooFit.Name("data")) res6 = model.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model.plotOn(mframew, ROOT.RooFit.Name("model1"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) res7 = model2.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model2.plotOn(mframew, ROOT.RooFit.Name("model2"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kOrange)) res8 = model3.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model3.plotOn(mframew, ROOT.RooFit.Name("model3"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) res9 = model4.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model4.plotOn(mframew, ROOT.RooFit.Name("model4"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) res10 = model5.fitTo(rooDataHist2, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) model5.plotOn(mframew, ROOT.RooFit.Name("model5"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.LineWidth(1), ROOT.RooFit.LineColor(ROOT.EColor.kViolet)) if args.pyes: c = TCanvas("c","c",800,800) mframew.SetAxisRange(300.,1300.) c.SetLogy() # mframew.SetMaximum(10) # mframew.SetMinimum(1) mframew.Draw() fitname = args.pdir+'/5funcfittowide_m'+str(mass)+fstr+'.pdf' c.SaveAs(fitname) cpull = TCanvas("cpull","cpull",800,800) pulls = mframew.pullHist("data","model1") pulls.Draw("ABX") pullname = args.pdir+'/pullwidefit_m'+str(mass)+fstr+'.pdf' cpull.SaveAs(pullname) if args.chi2: fullInt = model.createIntegral(RooArgSet(mjj)) norm = dataInt/fullInt.getVal() chi1 = 0. fullInt2 = model2.createIntegral(RooArgSet(mjj)) norm2 = dataInt2/fullInt2.getVal() chi2 = 0. fullInt3 = model3.createIntegral(RooArgSet(mjj)) norm3 = dataInt3/fullInt3.getVal() chi3 = 0. fullInt4 = model4.createIntegral(RooArgSet(mjj)) norm4 = dataInt4/fullInt4.getVal() chi4 = 0. fullInt5 = model5.createIntegral(RooArgSet(mjj)) norm5 = dataInt5/fullInt5.getVal() chi5 = 0. for i in range(args.massMin, args.massMax): new = 0 new2 = 0 new3 = 0 new4 = 0 new5 = 0 height = hData.GetBinContent(i) xLow = hData.GetXaxis().GetBinLowEdge(i) xUp = hData.GetXaxis().GetBinLowEdge(i+1) obs = height*(xUp-xLow) mjj.setRange("intrange",xLow,xUp) integ = model.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp = integ.getVal()*norm new = pow(exp-obs,2)/exp chi1 = chi1 + new integ2 = model2.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp2 = integ2.getVal()*norm2 new2 = pow(exp2-obs,2)/exp2 chi2 = chi2 + new2 integ3 = model3.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp3 = integ3.getVal()*norm3 new3 = pow(exp3-obs,2)/exp3 chi3 = chi3 + new3 integ4 = model4.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp4 = integ4.getVal()*norm4 if exp4 != 0: new4 = pow(exp4-obs,2)/exp4 else: new4 = 0 chi4 = chi4 + new4 integ5 = model5.createIntegral(RooArgSet(mjj),ROOT.RooFit.NormSet(RooArgSet(mjj)),ROOT.RooFit.Range("intrange")) exp5 = integ5.getVal()*norm5 new5 = pow(exp5-obs,2)/exp5 chi5 = chi5 + new5 print "chi1 %d "%(chi1) print "chi2 %d "%(chi2) print "chi3 %d "%(chi3) print "chi4 %d "%(chi4) print "chi5 %d "%(chi5) if not args.decoBkg: print " " res.Print() # res2.Print() # res3.Print() # res4.Print() # res5.Print() # res6.Print() # res7.Print() # decorrelated background parameters for Bayesian limits if args.decoBkg: signal_norm.setConstant() res = model.fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Strategy(args.fitStrategy)) res.Print() ## temp workspace for the PDF diagonalizer w_tmp = RooWorkspace("w_tmp") deco = PdfDiagonalizer("deco",w_tmp,res) # here diagonalizing only the shape parameters since the overall normalization is already decorrelated background_deco = deco.diagonalize(background) print "##################### workspace for decorrelation" w_tmp.Print("v") print "##################### original parameters" background.getParameters(rooDataHist).Print("v") print "##################### decorrelated parameters" # needed if want to evaluate limits without background systematics if args.fixBkg: w_tmp.var("deco_eig1").setConstant() w_tmp.var("deco_eig2").setConstant() if not args.fixP3: w_tmp.var("deco_eig3").setConstant() background_deco.getParameters(rooDataHist).Print("v") print "##################### original pdf" background.Print() print "##################### decorrelated pdf" background_deco.Print() # release signal normalization signal_norm.setConstant(kFALSE) # set the background normalization range to +/- 5 sigma bkg_val = background_norm.getVal() bkg_error = background_norm.getError() background_norm.setMin(bkg_val-5*bkg_error) background_norm.setMax(bkg_val+5*bkg_error) background_norm.Print() # change background PDF names background.SetName("background_old") background_deco.SetName("background") # needed if want to evaluate limits without background systematics if args.fixBkg: background_norm.setConstant() p1.setConstant() p2.setConstant() p3.setConstant() # ----------------------------------------- # dictionaries holding systematic variations of the signal shape hSig_Syst = {} hSig_Syst_DataHist = {} sigCDF = TGraph(hSig.GetNbinsX()+1) # JES and JER uncertainties if args.jesUnc != None or args.jerUnc != None: sigCDF.SetPoint(0,0.,0.) integral = 0. for i in range(1, hSig.GetNbinsX()+1): x = hSig.GetXaxis().GetBinLowEdge(i+1) integral = integral + hSig.GetBinContent(i) sigCDF.SetPoint(i,x,integral) if args.jesUnc != None: hSig_Syst['JESUp'] = copy.deepcopy(hSig) hSig_Syst['JESDown'] = copy.deepcopy(hSig) if args.jerUnc != None: hSig_Syst['JERUp'] = copy.deepcopy(hSig) hSig_Syst['JERDown'] = copy.deepcopy(hSig) # reset signal histograms for key in hSig_Syst.keys(): hSig_Syst[key].Reset() hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key) # produce JES signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX()+1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i+1) jes = 1. - args.jesUnc xLowPrime = jes*xLow xUpPrime = jes*xUp hSig_Syst['JESUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jes = 1. + args.jesUnc xLowPrime = jes*xLow xUpPrime = jes*xUp hSig_Syst['JESDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JESUp'] = RooDataHist('hSig_JESUp','hSig_JESUp',RooArgList(mjj),hSig_Syst['JESUp']) hSig_Syst_DataHist['JESDown'] = RooDataHist('hSig_JESDown','hSig_JESDown',RooArgList(mjj),hSig_Syst['JESDown']) if args.jyes: c2 = TCanvas("c2","c2",800,800) mframe2 = mjj.frame(ROOT.RooFit.Title("JES One Sigma Shifts")) mframe2.SetAxisRange(525.,1200.) hSig_Syst_DataHist['JESUp'].plotOn(mframe2, ROOT.RooFit.Name("JESUP"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JESDown'].plotOn(mframe2,ROOT.RooFit.Name("JESDOWN"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe2, ROOT.RooFit.DataError(2),ROOT.RooFit.Name("SIG"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe2.Draw() mframe2.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7,0.8,0.9,0.9) leg.AddEntry(mframe2.findObject("SIG"),"Signal Model","l") leg.AddEntry(mframe2.findObject("JESUP"),"+1 Sigma","l") leg.AddEntry(mframe2.findObject("JESDOWN"),"-1 Sigma","l") leg.Draw() jesname = args.pdir+'/jes_m'+str(mass)+fstr+'.pdf' c2.SaveAs(jesname) # produce JER signal shapes if args.jesUnc != None: for i in range(1, hSig.GetNbinsX()+1): xLow = hSig.GetXaxis().GetBinLowEdge(i) xUp = hSig.GetXaxis().GetBinLowEdge(i+1) jer = 1. - args.jerUnc xLowPrime = jer*(xLow-float(mass))+float(mass) xUpPrime = jer*(xUp-float(mass))+float(mass) hSig_Syst['JERUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) jer = 1. + args.jerUnc xLowPrime = jer*(xLow-float(mass))+float(mass) xUpPrime = jer*(xUp-float(mass))+float(mass) hSig_Syst['JERDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime)) hSig_Syst_DataHist['JERUp'] = RooDataHist('hSig_JERUp','hSig_JERUp',RooArgList(mjj),hSig_Syst['JERUp']) hSig_Syst_DataHist['JERDown'] = RooDataHist('hSig_JERDown','hSig_JERDown',RooArgList(mjj),hSig_Syst['JERDown']) if args.jyes: c3 = TCanvas("c3","c3",800,800) mframe3 = mjj.frame(ROOT.RooFit.Title("JER One Sigma Shifts")) mframe3.SetAxisRange(525.,1200.) hSig_Syst_DataHist['JERUp'].plotOn(mframe3,ROOT.RooFit.Name("JERUP"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kRed), ROOT.RooFit.LineColor(ROOT.EColor.kRed)) hSig_Syst_DataHist['JERDown'].plotOn(mframe3,ROOT.RooFit.Name("JERDOWN"),ROOT.RooFit.DrawOption("L"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kBlue), ROOT.RooFit.LineColor(ROOT.EColor.kBlue)) rooSigHist.plotOn(mframe3,ROOT.RooFit.DrawOption("L"),ROOT.RooFit.Name("SIG"), ROOT.RooFit.DataError(2), ROOT.RooFit.LineStyle(1), ROOT.RooFit.MarkerColor(ROOT.EColor.kGreen), ROOT.RooFit.LineColor(ROOT.EColor.kGreen)) mframe3.Draw() mframe3.GetXaxis().SetTitle("Dijet Mass (GeV)") leg = TLegend(0.7,0.8,0.9,0.9) leg.AddEntry(mframe3.findObject("SIG"),"Signal Model","l") leg.AddEntry(mframe3.findObject("JERUP"),"+1 Sigma","l") leg.AddEntry(mframe3.findObject("JERDOWN"),"-1 Sigma","l") leg.Draw() jername = args.pdir+'/jer_m'+str(mass)+fstr+'.pdf' c3.SaveAs(jername) # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') dcName = 'datacard_' + args.final_state + '_m' + str(mass) + postfix + '.txt' wsName = 'workspace_' + args.final_state + '_m' + str(mass) + postfix + '.root' w = RooWorkspace('w','workspace') getattr(w,'import')(rooSigHist,RooFit.Rename("signal")) if args.jesUnc != None: getattr(w,'import')(hSig_Syst_DataHist['JESUp'],RooFit.Rename("signal__JESUp")) getattr(w,'import')(hSig_Syst_DataHist['JESDown'],RooFit.Rename("signal__JESDown")) if args.jerUnc != None: getattr(w,'import')(hSig_Syst_DataHist['JERUp'],RooFit.Rename("signal__JERUp")) getattr(w,'import')(hSig_Syst_DataHist['JERDown'],RooFit.Rename("signal__JERDown")) if args.decoBkg: getattr(w,'import')(background_deco,ROOT.RooCmdArg()) else: getattr(w,'import')(background,ROOT.RooCmdArg(),RooFit.Rename("background")) #if use different fits for shape uncertainties #getattr(w,'import')(,ROOT.RooCmdArg(),RooFit.Rename("background__bkgUp")) #getattr(w,'import')(,ROOT.RooCmdArg(),RooFit.Rename("background__bkgDown")) getattr(w,'import')(background_norm,ROOT.RooCmdArg()) getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs")) w.Print() w.writeToFile(os.path.join(args.output_path,wsName)) beffUnc = 0.3 boffUnc = 0.06 datacard = open(os.path.join(args.output_path,dcName),'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if args.jesUnc != None or args.jerUnc != None: datacard.write('shapes * * '+wsName+' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n') else: datacard.write('shapes * * '+wsName+' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background\n') datacard.write('process 0 1\n') datacard.write('rate -1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n'%(1.+args.lumiUnc)) datacard.write('beff lnN %f -\n'%(1.+beffUnc)) datacard.write('boff lnN %f -\n'%(1.+boffUnc)) datacard.write('bkg lnN - 1.03\n') if args.jesUnc != None: datacard.write('JES shape 1 -\n') if args.jerUnc != None: datacard.write('JER shape 1 -\n') # flat parameters --- flat prior datacard.write('background_norm flatParam\n') if args.decoBkg: datacard.write('deco_eig1 flatParam\n') datacard.write('deco_eig2 flatParam\n') if not args.fixP3: datacard.write('deco_eig3 flatParam\n') else: datacard.write('p1 flatParam\n') datacard.write('p2 flatParam\n') if not args.fixP3: datacard.write('p3 flatParam\n') datacard.close() print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) )
if options.bash: gROOT.SetBatch(True) colour = [ TColor(1001, 0., 0., 0., "black", 1.), TColor(1002, 230./255, 159./255, 0., "orange", 1.), TColor(1003, 86./255, 180./255, 233./255, "skyblue", 1.), TColor(1004, 0., 158./255, 115./255, "bluishgreen", 1.), TColor(1005, 0., 114./255, 178./255, "blue", 1.), TColor(1006, 213./255, 94./255, 0., "vermillion", 1.), TColor(1007, 204./255, 121./255, 167./255, "reddishpurple", 1.), ] ########## SETTINGS ########## # Silent RooFit RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) #gStyle.SetOptStat(0) gStyle.SetOptTitle(0) gStyle.SetPadTopMargin(0.06) gStyle.SetPadRightMargin(0.05) gStyle.SetErrorX(0.) NTUPLEDIR = "/work/pbaertsc/heavy_resonance/" PLOTDIR = "/work/pbaertsc/heavy_resonance/ZprimeToZHAnalysis/plotsSignal/" CARDDIR = "datacards/" WORKDIR = "workspace/" RATIO = 4 LUMI = 137190. YEAR = 'combined' VERBOSE = options.verbose
def alpha(channel): nElec = channel.count('e') nMuon = channel.count('m') nLept = nElec + nMuon nBtag = channel.count('b') # Channel-dependent settings # Background function. Semi-working options are: EXP, EXP2, EXPN, EXPTAIL if nLept == 0: treeName = 'SR' signName = 'XZh' colorVjet = sample['DYJetsToNuNu']['linecolor'] triName = "HLT_PFMET" leptCut = "0==0" topVeto = selection["TopVetocut"] massVar = "X_cmass" binFact = 1 #fitFunc = "EXP" #fitFunc = "EXP2" #fitFunc = "EXPN" #fitFunc = "EXPTAIL" fitFunc = "EXPN" if nBtag < 2 else "EXP" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "ERFEXP" fitFuncVV = "EXPGAUS" fitFuncTop = "GAUS2" elif nLept == 1: treeName = 'WCR' signName = 'XWh' colorVjet = sample['WJetsToLNu']['linecolor'] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isWtoEN" if nElec > 0 else "isWtoMN" topVeto = selection["TopVetocut"] massVar = "X_mass" binFact = 2 if nElec > 0: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "EXPTAIL" if nBtag < 2 else "EXPTAIL" else: fitFunc = "EXPTAIL" if nBtag < 2 else "EXP" fitAltFunc = "EXPN" if nBtag < 2 else "EXPTAIL" fitFuncVjet = "ERFEXP" if nBtag < 2 else "ERFEXP" fitFuncVV = "EXPGAUS" fitFuncTop = "GAUS3" if nBtag < 2 else "GAUS2" else: treeName = 'XZh' signName = 'XZh' colorVjet = sample['DYJetsToLL']['linecolor'] triName = "HLT_Ele" if nElec > 0 else "HLT_Mu" leptCut = "isZtoEE" if nElec > 0 else "isZtoMM" topVeto = "0==0" massVar = "X_mass" binFact = 5 if nElec > 0: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "POW" if nBtag < 2 else "POW" else: fitFunc = "EXP" if nBtag < 2 else "EXP" fitAltFunc = "POW" if nBtag < 2 else "POW" fitFuncVjet = "ERFEXP" if nBtag < 2 else "EXP" fitFuncVV = "EXPGAUS2" fitFuncTop = "GAUS" btagCut = selection["2Btag"] if nBtag == 2 else selection["1Btag"] print "--- Channel", channel, "---" print " number of electrons:", nElec, " muons:", nMuon, " b-tags:", nBtag print " read tree:", treeName, "and trigger:", triName if ALTERNATIVE: print " using ALTERNATIVE fit functions" print "-"*11*2 # Silent RooFit RooMsgService.instance().setGlobalKillBelow(RooFit.FATAL) #*******************************************************# # # # Variables and selections # # # #*******************************************************# # Define all the variables from the trees that will be used in the cuts and fits # this steps actually perform a "projection" of the entire tree on the variables in thei ranges, so be careful once setting the limits X_mass = RooRealVar( massVar, "m_{X}" if nLept > 0 else "m_{T}^{X}", XBINMIN, XBINMAX, "GeV") J_mass = RooRealVar( "fatjet1_prunedMassCorr", "corrected pruned mass", HBINMIN, HBINMAX, "GeV") CSV1 = RooRealVar( "fatjet1_CSVR1", "", -1.e99, 1.e4 ) CSV2 = RooRealVar( "fatjet1_CSVR2", "", -1.e99, 1.e4 ) nBtag = RooRealVar( "fatjet1_nBtag", "", 0., 4 ) CSVTop = RooRealVar( "bjet1_CSVR", "", -1.e99, 1.e4 ) isZtoEE = RooRealVar("isZtoEE", "", 0., 2 ) isZtoMM = RooRealVar("isZtoMM", "", 0., 2 ) isWtoEN = RooRealVar("isWtoEN", "", 0., 2 ) isWtoMN = RooRealVar("isWtoMN", "", 0., 2 ) weight = RooRealVar( "eventWeightLumi", "", -1.e9, 1. ) # Define the RooArgSet which will include all the variables defined before # there is a maximum of 9 variables in the declaration, so the others need to be added with 'add' variables = RooArgSet(X_mass, J_mass, CSV1, CSV2, nBtag, CSVTop) variables.add(RooArgSet(isZtoEE, isZtoMM, isWtoEN, isWtoMN, weight)) # Define the ranges in fatJetMass - these will be used to define SB and SR J_mass.setRange("LSBrange", LOWMIN, LOWMAX) J_mass.setRange("HSBrange", HIGMIN, HIGMAX) J_mass.setRange("VRrange", LOWMAX, SIGMIN) J_mass.setRange("SRrange", SIGMIN, SIGMAX) J_mass.setBins(54) # Define the selection for the various categories (base + SR / LSBcut / HSBcut ) baseCut = leptCut + " && " + btagCut + "&&" + topVeto massCut = massVar + ">%d" % XBINMIN baseCut += " && " + massCut # Cuts SRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), SIGMIN, J_mass.GetName(), SIGMAX) LSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX) HSBcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) SBcut = baseCut + " && ((%s>%d && %s<%d) || (%s>%d && %s<%d))" % (J_mass.GetName(), LOWMIN, J_mass.GetName(), LOWMAX, J_mass.GetName(), HIGMIN, J_mass.GetName(), HIGMAX) VRcut = baseCut + " && %s>%d && %s<%d" % (J_mass.GetName(), LOWMAX, J_mass.GetName(), SIGMIN) # Binning binsJmass = RooBinning(HBINMIN, HBINMAX) binsJmass.addUniform(HBINS, HBINMIN, HBINMAX) binsXmass = RooBinning(XBINMIN, XBINMAX) binsXmass.addUniform(binFact*XBINS, XBINMIN, XBINMAX) #*******************************************************# # # # Input files # # # #*******************************************************# # Import the files using TChains (separately for the bkg "classes" that we want to describe: here DY and VV+ST+TT) treeData = TChain(treeName) treeMC = TChain(treeName) treeVjet = TChain(treeName) treeVV = TChain(treeName) treeTop = TChain(treeName) # treeSign = {} # nevtSign = {} # Read data pd = getPrimaryDataset(triName) if len(pd)==0: raw_input("Warning: Primary Dataset not recognized, continue?") for i, s in enumerate(pd): treeData.Add(NTUPLEDIR + s + ".root") # Read V+jets backgrounds for i, s in enumerate(["WJetsToLNu_HT", "DYJetsToNuNu_HT", "DYJetsToLL_HT"]): for j, ss in enumerate(sample[s]['files']): treeVjet.Add(NTUPLEDIR + ss + ".root") # Read VV backgrounds for i, s in enumerate(["VV"]): for j, ss in enumerate(sample[s]['files']): treeVV.Add(NTUPLEDIR + ss + ".root") # Read Top backgrounds for i, s in enumerate(["ST", "TTbar"]): for j, ss in enumerate(sample[s]['files']): treeTop.Add(NTUPLEDIR + ss + ".root") # Sum all background MC treeMC.Add(treeVjet) treeMC.Add(treeVV) treeMC.Add(treeTop) # create a dataset to host data in sideband (using this dataset we are automatically blind in the SR!) setDataSB = RooDataSet("setDataSB", "setDataSB", variables, RooFit.Cut(SBcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) setDataLSB = RooDataSet("setDataLSB", "setDataLSB", variables, RooFit.Import(setDataSB), RooFit.Cut(LSBcut), RooFit.WeightVar(weight)) setDataHSB = RooDataSet("setDataHSB", "setDataHSB", variables, RooFit.Import(setDataSB), RooFit.Cut(HSBcut), RooFit.WeightVar(weight)) # Observed data (WARNING, BLIND!) setDataSR = RooDataSet("setDataSR", "setDataSR", variables, RooFit.Cut(SRcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) setDataVR = RooDataSet("setDataVR", "setDataVR", variables, RooFit.Cut(VRcut), RooFit.WeightVar(weight), RooFit.Import(treeData)) # Observed in the VV mass, just for plotting purposes # same for the bkg datasets from MC, where we just apply the base selections (not blind) setVjet = RooDataSet("setVjet", "setVjet", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVjet)) setVjetSB = RooDataSet("setVjetSB", "setVjetSB", variables, RooFit.Import(setVjet), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setVjetSR = RooDataSet("setVjetSR", "setVjetSR", variables, RooFit.Import(setVjet), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) setVV = RooDataSet("setVV", "setVV", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeVV)) setVVSB = RooDataSet("setVVSB", "setVVSB", variables, RooFit.Import(setVV), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setVVSR = RooDataSet("setVVSR", "setVVSR", variables, RooFit.Import(setVV), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) setTop = RooDataSet("setTop", "setTop", variables, RooFit.Cut(baseCut), RooFit.WeightVar(weight), RooFit.Import(treeTop)) setTopSB = RooDataSet("setTopSB", "setTopSB", variables, RooFit.Import(setTop), RooFit.Cut(SBcut), RooFit.WeightVar(weight)) setTopSR = RooDataSet("setTopSR", "setTopSR", variables, RooFit.Import(setTop), RooFit.Cut(SRcut), RooFit.WeightVar(weight)) print " Data events SB: %.2f" % setDataSB.sumEntries() print " V+jets entries: %.2f" % setVjet.sumEntries() print " VV, VH entries: %.2f" % setVV.sumEntries() print " Top,ST entries: %.2f" % setTop.sumEntries() # the relative normalization of the varius bkg is taken from MC by counting all the events in the full fatJetMass range #coef = RooRealVar("coef", "coef", setVV.sumEntries()/setVjet.sumEntries(),0.,1.) coef_VV_Vjet = RooRealVar("coef2_1", "coef2_1", setVV.sumEntries()/setVjet.sumEntries(), 0., 1.) coef_Top_VVVjet = RooRealVar("coef3_21", "coef3_21", setTop.sumEntries()/(setVjet.sumEntries()+setVV.sumEntries()),0.,1.); coef_VV_Vjet.setConstant(True) coef_Top_VVVjet.setConstant(True) # Define entries entryVjet = RooRealVar("entryVjets", "V+jets normalization", setVjet.sumEntries(), 0., 1.e6) entryVV = RooRealVar("entryVV", "VV normalization", setVV.sumEntries(), 0., 1.e6) entryTop = RooRealVar("entryTop", "Top normalization", setTop.sumEntries(), 0., 1.e6) entrySB = RooRealVar("entrySB", "Data SB normalization", setDataSB.sumEntries(SBcut), 0., 1.e6) entrySB.setError(math.sqrt(entrySB.getVal())) entryLSB = RooRealVar("entryLSB", "Data LSB normalization", setDataSB.sumEntries(LSBcut), 0., 1.e6) entryLSB.setError(math.sqrt(entryLSB.getVal())) entryHSB = RooRealVar("entryHSB", "Data HSB normalization", setDataSB.sumEntries(HSBcut), 0., 1.e6) entryHSB.setError(math.sqrt(entryHSB.getVal())) #*******************************************************# # # # NORMALIZATION # # # #*******************************************************# # set reasonable ranges for J_mass and X_mass # these are used in the fit in order to avoid ROOFIT to look in regions very far away from where we are fitting J_mass.setRange("h_reasonable_range", LOWMIN, HIGMAX) X_mass.setRange("X_reasonable_range", XBINMIN, XBINMAX) # Set RooArgSets once for all, see https://root.cern.ch/phpBB3/viewtopic.php?t=11758 jetMassArg = RooArgSet(J_mass) #*******************************************************# # # # V+jets normalization # # # #*******************************************************# # Variables for V+jets constVjet = RooRealVar("constVjet", "slope of the exp", -0.020, -1., 0.) offsetVjet = RooRealVar("offsetVjet", "offset of the erf", 30., -50., 200.) widthVjet = RooRealVar("widthVjet", "width of the erf", 100., 1., 200.) offsetVjet.setConstant(True) a0Vjet = RooRealVar("a0Vjet", "width of the erf", -0.1, -5, 0) a1Vjet = RooRealVar("a1Vjet", "width of the erf", 0.6, 0, 5) a2Vjet = RooRealVar("a2Vjet", "width of the erf", -0.1, -1, 1) # Define V+jets model if fitFuncVjet == "ERFEXP": modelVjet = RooErfExpPdf("modelVjet", "error function for V+jets mass", J_mass, constVjet, offsetVjet, widthVjet) elif fitFuncVjet == "EXP": modelVjet = RooExponential("modelVjet", "exp for V+jets mass", J_mass, constVjet) elif fitFuncVjet == "POL": modelVjet = RooChebychev("modelVjet", "polynomial for V+jets mass", J_mass, RooArgList(a0Vjet, a1Vjet, a2Vjet)) elif fitFuncVjet == "POW": modelVjet = RooGenericPdf("modelVjet", "powerlaw for X mass", "@0^@1", RooArgList(J_mass, a0Vjet)) else: print " ERROR! Pdf", fitFuncVjet, "is not implemented for Vjets" exit() # fit to main bkg in MC (whole range) frVjet = modelVjet.fitTo(setVjet, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # integrals and number of events iSBVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iLSBVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) iHSBVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) iSRVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iVRVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # Do not remove the following lines, integrals are computed here iALVjet = modelVjet.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg)) nSBVjet = iSBVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(SBcut) nLSBVjet = iLSBVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(LSBcut) nHSBVjet = iHSBVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(HSBcut) nSRVjet = iSRVjet.getVal()/iALVjet.getVal()*setVjet.sumEntries(SRcut) drawPlot("JetMass_Vjet", channel, J_mass, modelVjet, setVjet, binsJmass, frVjet) if VERBOSE: print "********** Fit result [JET MASS Vjets] *"+"*"*40, "\n", frVjet.Print(), "\n", "*"*80 #*******************************************************# # # # VV, VH normalization # # # #*******************************************************# # Variables for VV # Error function and exponential to model the bulk constVV = RooRealVar("constVV", "slope of the exp", -0.030, -0.1, 0.) offsetVV = RooRealVar("offsetVV", "offset of the erf", 90., 1., 300.) widthVV = RooRealVar("widthVV", "width of the erf", 50., 1., 100.) erfrVV = RooErfExpPdf("baseVV", "error function for VV jet mass", J_mass, constVV, offsetVV, widthVV) expoVV = RooExponential("baseVV", "error function for VV jet mass", J_mass, constVV) # gaussian for the V mass peak meanVV = RooRealVar("meanVV", "mean of the gaussian", 90., 60., 100.) sigmaVV = RooRealVar("sigmaVV", "sigma of the gaussian", 10., 6., 30.) fracVV = RooRealVar("fracVV", "fraction of gaussian wrt erfexp", 3.2e-1, 0., 1.) gausVV = RooGaussian("gausVV", "gaus for VV jet mass", J_mass, meanVV, sigmaVV) # gaussian for the H mass peak meanVH = RooRealVar("meanVH", "mean of the gaussian", 125., 100., 150.) sigmaVH = RooRealVar("sigmaVH", "sigma of the gaussian", 30., 5., 40.) fracVH = RooRealVar("fracVH", "fraction of gaussian wrt erfexp", 1.5e-2, 0., 1.) gausVH = RooGaussian("gausVH", "gaus for VH jet mass", J_mass, meanVH, sigmaVH) # Define VV model if fitFuncVV == "ERFEXPGAUS": modelVV = RooAddPdf("modelVV", "error function + gaus for VV jet mass", RooArgList(gausVV, erfrVV), RooArgList(fracVV)) elif fitFuncVV == "ERFEXPGAUS2": modelVV = RooAddPdf("modelVV", "error function + gaus + gaus for VV jet mass", RooArgList(gausVH, gausVV, erfrVV), RooArgList(fracVH, fracVV)) elif fitFuncVV == "EXPGAUS": modelVV = RooAddPdf("modelVV", "error function + gaus for VV jet mass", RooArgList(gausVV, expoVV), RooArgList(fracVV)) elif fitFuncVV == "EXPGAUS2": modelVV = RooAddPdf("modelVV", "error function + gaus + gaus for VV jet mass", RooArgList(gausVH, gausVV, expoVV), RooArgList(fracVH, fracVV)) else: print " ERROR! Pdf", fitFuncVV, "is not implemented for VV" exit() # fit to secondary bkg in MC (whole range) frVV = modelVV.fitTo(setVV, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # integrals and number of events iSBVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iLSBVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) iHSBVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) iSRVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iVRVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # Do not remove the following lines, integrals are computed here iALVV = modelVV.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg)) nSBVV = iSBVV.getVal()/iALVV.getVal()*setVV.sumEntries(SBcut) nLSBVV = iLSBVV.getVal()/iALVV.getVal()*setVV.sumEntries(LSBcut) nHSBVV = iHSBVV.getVal()/iALVV.getVal()*setVV.sumEntries(HSBcut) nSRVV = iSRVV.getVal()/iALVV.getVal()*setVV.sumEntries(SRcut) rSBSRVV = nSRVV/nSBVV drawPlot("JetMass_VV", channel, J_mass, modelVV, setVV, binsJmass, frVV) if VERBOSE: print "********** Fit result [JET MASS VV] ****"+"*"*40, "\n", frVV.Print(), "\n", "*"*80 #*******************************************************# # # # Top, ST normalization # # # #*******************************************************# # Variables for Top # Error Function * Exponential to model the bulk constTop = RooRealVar("constTop", "slope of the exp", -0.030, -1., 0.) offsetTop = RooRealVar("offsetTop", "offset of the erf", 175.0, 50., 250.) widthTop = RooRealVar("widthTop", "width of the erf", 100.0, 1., 300.) gausTop = RooGaussian("baseTop", "gaus for Top jet mass", J_mass, offsetTop, widthTop) erfrTop = RooErfExpPdf("baseTop", "error function for Top jet mass", J_mass, constTop, offsetTop, widthTop) # gaussian for the W mass peak meanW = RooRealVar("meanW", "mean of the gaussian", 80., 70., 90.) sigmaW = RooRealVar("sigmaW", "sigma of the gaussian", 10., 2., 20.) fracW = RooRealVar("fracW", "fraction of gaussian wrt erfexp", 0.1, 0., 1.) gausW = RooGaussian("gausW", "gaus for W jet mass", J_mass, meanW, sigmaW) # gaussian for the Top mass peak meanT = RooRealVar("meanT", "mean of the gaussian", 175., 150., 200.) sigmaT = RooRealVar("sigmaT", "sigma of the gaussian", 12., 5., 50.) fracT = RooRealVar("fracT", "fraction of gaussian wrt erfexp", 0.1, 0., 1.) gausT = RooGaussian("gausT", "gaus for T jet mass", J_mass, meanT, sigmaT) # Define Top model if fitFuncTop == "ERFEXPGAUS2": modelTop = RooAddPdf("modelTop", "error function + gaus + gaus for Top jet mass", RooArgList(gausW, gausT, erfrTop), RooArgList(fracW, fracT)) elif fitFuncTop == "ERFEXPGAUS": modelTop = RooAddPdf("modelTop", "error function + gaus for Top jet mass", RooArgList(gausT, erfrTop), RooArgList(fracT)) elif fitFuncTop == "GAUS3": modelTop = RooAddPdf("modelTop", "gaus + gaus + gaus for Top jet mass", RooArgList(gausW, gausT, gausTop), RooArgList(fracW, fracT)) elif fitFuncTop == "GAUS2": modelTop = RooAddPdf("modelTop", "gaus + gaus for Top jet mass", RooArgList(gausT, gausTop), RooArgList(fracT)) elif fitFuncTop == "GAUS": modelTop = RooGaussian("modelTop", "gaus for Top jet mass", J_mass, offsetTop, widthTop) else: print " ERROR! Pdf", fitFuncTop, "is not implemented for Top" exit() # fit to secondary bkg in MC (whole range) frTop = modelTop.fitTo(setTop, RooFit.SumW2Error(True), RooFit.Range("h_reasonable_range"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.Save(1), RooFit.PrintLevel(1 if VERBOSE else -1)) # integrals and number of events iSBTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) iLSBTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) iHSBTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) iSRTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) iVRTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # Do not remove the following lines, integrals are computed here iALTop = modelTop.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg)) nSBTop = iSBTop.getVal()/iALTop.getVal()*setTop.sumEntries(SBcut) nLSBTop = iLSBTop.getVal()/iALTop.getVal()*setTop.sumEntries(LSBcut) nHSBTop = iHSBTop.getVal()/iALTop.getVal()*setTop.sumEntries(HSBcut) nSRTop = iSRTop.getVal()/iALTop.getVal()*setTop.sumEntries(SRcut) drawPlot("JetMass_Top", channel, J_mass, modelTop, setTop, binsJmass, frTop) if VERBOSE: print "********** Fit result [JET MASS TOP] ***"+"*"*40, "\n", frTop.Print(), "\n", "*"*80 #*******************************************************# # # # All bkg normalization # # # #*******************************************************# constVjet.setConstant(True) offsetVjet.setConstant(True) widthVjet.setConstant(True) a0Vjet.setConstant(True) a1Vjet.setConstant(True) a2Vjet.setConstant(True) constVV.setConstant(True) offsetVV.setConstant(True) widthVV.setConstant(True) meanVV.setConstant(True) sigmaVV.setConstant(True) fracVV.setConstant(True) meanVH.setConstant(True) sigmaVH.setConstant(True) fracVH.setConstant(True) constTop.setConstant(True) offsetTop.setConstant(True) widthTop.setConstant(True) meanW.setConstant(True) sigmaW.setConstant(True) fracW.setConstant(True) meanT.setConstant(True) sigmaT.setConstant(True) fracT.setConstant(True) # Final background model by adding the main+secondary pdfs (using 'coef': ratio of the secondary/main, from MC) model = RooAddPdf("model", "model", RooArgList(modelTop, modelVV, modelVjet), RooArgList(coef_Top_VVVjet, coef_VV_Vjet))#FIXME model.fixAddCoefRange("h_reasonable_range") # Extended fit model to data in SB # all the 3 sidebands (Low / High / the 2 combined) could be used # currently using the LOW+HIGH (the others are commented out) yieldLSB = RooRealVar("yieldLSB", "Lower SB normalization", 10, 0., 1.e6) yieldHSB = RooRealVar("yieldHSB", "Higher SB normalization", 10, 0., 1.e6) yieldSB = RooRealVar("yieldSB", "All SB normalization", 10, 0., 1.e6) #model_ext = RooExtendPdf("model_ext", "extended p.d.f", model, yieldLSB) #model_ext = RooExtendPdf("model_ext", "extended p.d.f", model, yieldHSB) model_ext = RooExtendPdf("model_ext", "extended p.d.f", model, yieldSB) #frMass = model_ext.fitTo(setDataSB, RooFit.ConditionalObservables(RooArgSet(J_mass)),RooFit.SumW2Error(True),RooFit.Extended(True),RooFit.Range("LSBrange"),RooFit.PrintLevel(-1)) #frMass = model_ext.fitTo(setDataSB, RooFit.ConditionalObservables(RooArgSet(J_mass)),RooFit.SumW2Error(True),RooFit.Extended(True),RooFit.Range("HSBrange"),RooFit.PrintLevel(-1)) #frMass = model_ext.fitTo(setDataSB, RooFit.ConditionalObservables(RooArgSet(J_mass)), RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Range("LSBrange,HSBrange"), RooFit.Strategy(2), RooFit.Minimizer("Minuit2"), RooFit.PrintLevel(1 if VERBOSE else -1)) #print "********** Fit result [JET MASS DATA] **"+"*"*40 #print frMass.Print() #print "*"*80 # Calculate integral of the model obtained from the fit to data (fraction of PDF that is within a given region) #nSB = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange,HSBrange")) #nSB = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("LSBrange")) #nSB = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("HSBrange")) #nSR = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("SRrange")) #nVR = model_ext.createIntegral(jetMassArg, RooFit.NormSet(jetMassArg), RooFit.Range("VRrange")) # scale the yieldSB from SB to SR using the ratio of the PDFs defined by the two integrals SRyield = RooFormulaVar("SRyield", "extrapolation to SR","(@0-@1*@3-@2*@4) * @5/@6 +@1*@7+@2*@8", RooArgList(entrySB, entryVV, entryTop, iSBVV, iSBTop, iSRVjet, iSBVjet, iSRVV, iSRTop)) VRyield = RooFormulaVar("VRyield", "extrapolation to VR","(@0-@1*@3-@2*@4) * @5/@6 +@1*@7+@2*@8", RooArgList(entrySB, entryVV, entryTop, iSBVV, iSBTop, iVRVjet, iSBVjet, iVRVV, iVRTop)) HSByield = RooFormulaVar("SRyield", "extrapolation to SR","(@0-@1*@3-@2*@4) * @5/@6 +@1*@7+@2*@8", RooArgList(entryLSB, entryVV, entryTop, iLSBVV, iLSBTop, iHSBVjet, iLSBVjet, iHSBVV, iHSBTop)) # RooFormulaVar SRyield("SRyield","extrapolation to SR","(@0/@1)*@2",RooArgList(*nSR,*nSB,yieldLowerSB)) # RooFormulaVar SRyield("SRyield","extrapolation to SR","(@0/@1)*@2",RooArgList(*nSR,*nSB,yieldHigherSB)) #SRyield = RooFormulaVar("SRyield", "extrapolation to SR","(@0/@1)*@2", RooArgList(nSR, nSB, entrySB)) bkgYield = SRyield.getVal() bkgYield_error = math.sqrt(SRyield.getPropagatedError(frVjet)**2 + SRyield.getPropagatedError(frVV)**2 + SRyield.getPropagatedError(frTop)**2 + (entrySB.getError()*rSBSRVV)**2) bkgNorm = entrySB.getVal() + SRyield.getVal() + VRyield.getVal() bkgYield_eig_norm = RooRealVar("predSR_eig_norm", "expected yield in SR", bkgYield, 0., 1.e6) bkgYieldExt = HSByield.getVal() drawPlot("JetMass", channel, J_mass, model, setDataSB, binsJmass, None, None, "", bkgNorm, True) print channel, "normalization = %.3f +/- %.3f, observed = %.0f" % (bkgYield, bkgYield_error, setDataSR.sumEntries() if not BLIND else -1) if VERBOSE: raw_input("Press Enter to continue...")
parser.add_option("--rebin" ,action="store",type="int" ,dest="rebin" ,default=5) parser.add_option("--lumi" ,action="store",type="float" ,dest="lumi" ,default=1000) (options, args) = parser.parse_args() xmin = options.xmin xmax = options.xmax rebin = options.rebin lumi = options.lumi gROOT.Reset() setTDRStyle() gROOT.ForceStyle() gROOT.SetStyle('tdrStyle') RooMsgService.instance().setSilentMode(ROOT.kTRUE) RooMsgService.instance().setStreamStatus(0,ROOT.kFALSE) RooMsgService.instance().setStreamStatus(1,ROOT.kFALSE) filename = [ 'Histo_TT.root', 'Histo_JetHT.root' ] norm = [] nevents = [] histo = [] roohisto = [] histoCtl = [] roohistoCtl = [] # define observable x = RooRealVar('mTop','mTop',xmin,xmax)
def run_single_mass(args, mass): print "[run_single_mass] INFO : Creating datacard and workspace for m = %i GeV..."%(int(mass)) if args.fit_functions == "all": #fit_functions = ["dijet4", "dijet5", "modexp4", "polyx6", "atlas4", "atlas5", "polypower4", "rational3", "rational4"] fit_functions = ["dijet4", "modexp4", "polyx6", "polypower4"] else: fit_functions = args.fit_functions.split(",") # import ROOT stuff from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooProdPdf, RooEffProd, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf, RooFormulaVar if not args.debug: RooMsgService.instance().setSilentMode(kTRUE) RooMsgService.instance().setStreamStatus(0,kFALSE) RooMsgService.instance().setStreamStatus(1,kFALSE) # Stuff mjj = RooRealVar('mjj','mjj',float(args.massMin),float(args.massMax)) lumi = args.lumi signalCrossSection = 1. # Set to 1 so that the limit on r can be interpreted as a limit on the signal cross section # Input data file if args.qcd: data_sample = "QCD_TuneZ2star_8TeV_pythia6" elif "trigbb" in args.analysis: data_sample = "BJetPlusX_2012" elif "trigmu" in args.analysis: data_sample = "SingleMu_2012" data_file_path = analysis_config.get_b_histogram_filename(args.analysis, data_sample) if args.condor: data_file_path = os.path.basename(data_file_path) data_file = TFile(data_file_path) hData_notrigcorr = data_file.Get("BHistograms/h_pfjet_mjj") hData_notrigcorr.SetDirectory(0) hData_name = hData_notrigcorr.GetName() hData_notrigcorr.SetName(hData_name + "_notrigcorr") # Trigger correction on data if args.fitTrigger: # Make trigger correction objects trigeff_pt_formula, trigeff_vars = trigger_efficiency.get_var_formula(args.analysis, mjj) trigeff_btag_var = RooRealVar("trigeff_btag", "trigeff_btag", 0., 1.) trigeff_btag_var.setVal(trigger_efficiency.online_btag_eff[args.analysis][0]) trigeff_btag_var.setConstant() trigeff_btag_formula = RooFormulaVar("trigeff_btag_formula", "@0", RooArgList(trigeff_btag_var)) #trigeff_btag_var.setConstant() trigeff_total_formula = RooFormulaVar("trigeff_total_formula", "@0*@1", RooArgList(trigeff_btag_var, trigeff_pt_formula)) #for trigeff_var_name, trigeff_var in trigeff_vars.iteritems(): # trigeff_var.setConstant() if args.correctTrigger: # Apply trigger correction to data histogram hData = CorrectTriggerEfficiency(hData_notrigcorr, args.analysis) # Still need b-tagging efficiency to scale the MC if not args.useMCTrigger: trigeff_btag_var = RooRealVar("trigeff_btag", "trigeff_btag", 0., 1.) trigeff_btag_var.setVal(trigger_efficiency.online_btag_eff[args.analysis][0]) trigeff_btag_var.setConstant() trigeff_btag_formula = RooFormulaVar("trigeff_btag_formula", "@0", RooArgList(trigeff_btag_var)) # Use a RooRealVar instead! You want to be able to apply a systematic in combine. # trigeff_btag_formula = RooFormulaVar("trigeff_btag_formula", str(trigger_efficiency.online_btag_eff[args.analysis][0]), RooArgList()) else: hData = hData_notrigcorr if args.qcd: # For QCD, scale the histogram by the online b-tag trigger efficiency. if args.analysis == "NoTrigger_eta1p7_CSVTM": trigeff_btag_formula = RooFormulaVar("trigeff_btag_formula", str(trigger_efficiency.online_btag_eff["trigbbl_CSVTM"][0]), RooArgList()) elif args.analysis == "NoTrigger_eta2p2_CSVTM": trigeff_btag_formula = RooFormulaVar("trigeff_btag_formula", str(trigger_efficiency.online_btag_eff["trigbbh_CSVTM"][0]), RooArgList()) if args.analysis == "NoTrigger_eta1p7_CSVTM": hData.Scale(trigger_efficiency.online_btag_eff["trigbbl_CSVTM"][0]) elif args.analysis == "NoTrigger_eta2p2_CSVTM": hData.Scale(trigger_efficiency.online_btag_eff["trigbbh_CSVTM"][0]) else: print "[create_datacards_parallel] ERROR : QCD fit requested, but analysis != NoTrigger_etaXpY_CSVTM. I don't know what to do!" sys.exit(1) hData.SetName(hData_name) rooDataHist = RooDataHist('rooDatahist','rooDatahist',RooArgList(mjj),hData) if args.correctTrigger: rooDataHist_notrigcorr = RooDataHist("rooDatahist_notrigcorr", "rooDatahist_notrigcorr", RooArgList(mjj), hData_notrigcorr) # Get signal pdf * btag efficiency if args.useMCTrigger: signal_pdf_file = analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)) if args.condor: signal_pdf_file = os.path.basename(signal_pdf_file) print "[create_datacards] Loading fitted signal PDFs from " + signal_pdf_file f_signal_pdfs = TFile(signal_pdf_file, "READ") f_signal_pdfs.Print() w_signal = f_signal_pdfs.Get("w_signal") w_signal.Print() bukin_pdf = w_signal.pdf("signal_bukin") bukin_pdf.Print() else: if args.analysis == "trigbbl_CSVTM" or args.analysis == "NoTrigger_eta1p7_CSVTM": notrig_analysis = "NoTrigger_eta1p7_CSVTM" elif args.analysis == "trigbbh_CSVTM" or args.analysis == "NoTrigger_eta2p2_CSVTM": notrig_analysis = "NoTrigger_eta2p2_CSVTM" elif args.analysis == "trigbbl_CSVM" or args.analysis == "NoTrigger_eta1p7_CSVM": notrig_analysis = "NoTrigger_eta1p7_CSVM" elif args.analysis == "trigbbh_CSVM" or args.analysis == "NoTrigger_eta2p2_CSVM": notrig_analysis = "NoTrigger_eta2p2_CSVM" else: print "[run_single_mass] ERROR : I don't know a no-trigger variant of analysis {}. Please make one, or specify --useMCTrigger.".format(args.analysis) sys.exit(1) print analysis_config.simulation.simulated_masses signal_pdf_file = analysis_config.get_signal_fit_file(notrig_analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)) print "[create_datacards] Loading fitted signal PDFs from " + signal_pdf_file if args.condor: signal_pdf_file = os.path.basename(signal_pdf_file) f_signal_pdfs = TFile(signal_pdf_file, "READ") w_signal = f_signal_pdfs.Get("w_signal") bukin_pdf = w_signal.pdf("signal") bukin_pdf.SetName("signal_bukin") input_signal_parameters = signal_fits.get_parameters(bukin_pdf) # Make a new PDF with nuisance parameters signal_pdf_notrig, signal_vars = signal_fits.make_signal_pdf_systematic("bukin", mjj, mass=mass) signal_pdf_name = signal_pdf_notrig.GetName() signal_pdf_notrig.SetName(signal_pdf_name + "_notrig") # Add trigger efficiency if args.useMCTrigger: if args.fitTrigger: # Online b-tagging eff incorporated in Bukin/acceptance, so signal pdf = Bukin * pT efficiency signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_pt_formula) elif args.correctTrigger: # Signal PDF = bukin; b-tag efficiency already included in normalization signal_pdf = signal_pdf_notrig signal_pdf.SetName(signal_pdf_name) else: if args.fitTrigger: # Signal PDF = bukin * total trigger efficiency signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_total_formula) elif args.correctTrigger: if args.useMCTrigger: signal_pdf = signal_pdf_notrig signal_pdf.SetName("signal") else: # Signal PDF = bukin * btag efficiency signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_btag_formula) elif args.qcd: # Signal PDF = bukin * btag efficiency # Same as correctTrigger signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_btag_formula) # Copy input parameter values signal_vars["xp_0"].setVal(input_signal_parameters["xp"][0]) signal_vars["xp_0"].setError(input_signal_parameters["xp"][1]) signal_vars["xp_0"].setConstant() signal_vars["sigp_0"].setVal(input_signal_parameters["sigp"][0]) signal_vars["sigp_0"].setError(input_signal_parameters["sigp"][1]) signal_vars["sigp_0"].setConstant() signal_vars["xi_0"].setVal(input_signal_parameters["xi"][0]) signal_vars["xi_0"].setError(input_signal_parameters["xi"][1]) signal_vars["xi_0"].setConstant() signal_vars["rho1_0"].setVal(input_signal_parameters["rho1"][0]) signal_vars["rho1_0"].setError(input_signal_parameters["rho1"][1]) signal_vars["rho1_0"].setConstant() signal_vars["rho2_0"].setVal(input_signal_parameters["rho2"][0]) signal_vars["rho2_0"].setError(input_signal_parameters["rho2"][1]) signal_vars["rho2_0"].setConstant() f_signal_pdfs.Close() signal_parameters = {} signal_pdfs_notrig = {} signal_pdfs = {} signal_norms = {} background_pdfs = {} background_pdfs_notrig = {} background_parameters = {} background_norms = {} signal_epdfs = {} background_epdfs = {} models = {} fit_results = {} if args.fitOffB: # Load RooHistPdf if "bbl" in args.analysis or "eta1p7" in args.analysis: eta_region = "eta1p7" offline_btag_eff_vars = { "p0":RooRealVar("offline_btag_eff_p0", "offline_btag_eff_p0", 6.78251e-03, 6.78251e-03 - 10.*7.66906e-05, 6.78251e-03 + 10.*7.66906e-05), "p1":RooRealVar("offline_btag_eff_p1", "offline_btag_eff_p1", -9.55614e-06, -9.55614e-06 - 10.*1.04286e-07, -9.55614e-06 + 10.*1.04286e-07), "p2":RooRealVar("offline_btag_eff_p2", "offline_btag_eff_p2", 4.39468e-09, 4.39468e-09 - 1.e-07, 4.39468e-09 + 1.e-07), } offline_btag_eff_formula = RooFormulaVar("offline_btag_eff", "max(@0+(@1*@3)+(@2*@3*@3), 0.)", RooArgList(offline_btag_eff_vars["p0"], offline_btag_eff_vars["p1"], offline_btag_eff_vars["p2"], mjj)) elif "bbh" in args.analysis or "eta2p2" in args.analysis: eta_region = "eta2p2" offline_btag_eff_vars = { "p0":RooRealVar("offline_btag_eff_p0", "offline_btag_eff_p0", -1.72721e-03, -1.72721e-03 - 10.*3.04992e-05, -1.72721e-03 + 10.*3.04992e-05), "p1":RooRealVar("offline_btag_eff_p1", "offline_btag_eff_p1", 1.72562e-06, 1.72562e-06 - 10.*3.23472e-08, 1.72562e-06 + 10.*3.23472e-08), "p2":RooRealVar("offline_btag_eff_p2", "offline_btag_eff_p2", 8.74866e-03, 8.74866e-03 - 10.*7.81413e-05, 8.74866e-03 + 10.*7.81413e-05), "p3":RooRealVar("offline_btag_eff_p3", "offline_btag_eff_p3", -1.67123e-03, -1.67123e-03 - 10.*4.30607e-05, -1.67123e-03 + 10.*4.30607e-05), } offline_btag_eff_formula = RooFormulaVar("offline_btag_eff", "max(@0+@1*@4+ @2*exp(@3*@4), 0.)", RooArgList(offline_btag_eff_vars["p0"],offline_btag_eff_vars["p1"],offline_btag_eff_vars["p2"],offline_btag_eff_vars["p3"], mjj)) #f_offline_btag_eff = TFile(analysis_config.get_offline_btag_file("CSVTM", eta_region)) #h_offline_btag_eff = f_offline_btag_eff.Get("h_offline_btag_eff") #print h_offline_btag_eff #offline_btag_eff_rdh = RooDataHist("rdh_offline_btag_eff", "rdh_offline_btag_eff", RooArgList(mjj), h_offline_btag_eff) #offline_btag_eff_pdf = RooHistPdf("pdf_offline_btag_eff", "pdf_offline_btag_eff", RooArgSet(mjj), offline_btag_eff_rdh) for fit_function in fit_functions: print "[create_datacards] INFO : On fit function {}".format(fit_function) # Make a copy of the signal PDF, so that each fitTo call uses its own copy. # The copy should have all variables set constant. #signal_pdfs[fit_function], signal_parameters[fit_function] = signal_fits.copy_signal_pdf("bukin", signal_pdf, mjj, tag=fit_function, include_systematics=True) signal_pdfs_notrig[fit_function] = ROOT.RooBukinPdf(signal_pdf_notrig, signal_pdf_notrig.GetName() + "_" + fit_function) iterator = signal_pdfs_notrig[fit_function].getVariables().createIterator() this_parameter = iterator.Next() while this_parameter: this_parameter.setConstant() this_parameter = iterator.Next() # Add trigger efficiency if args.useMCTrigger: if args.fitTrigger: signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_pt_formula) else: signal_pdfs[fit_function] = signal_pdfs_notrig[fit_function] signal_pdfs[fit_functions].SetName(signal_pdf.GetName() + "_" + fit_function) elif args.fitTrigger: # Signal PDF = bukin * total trigger efficiency signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_total_formula) elif args.correctTrigger: # Signal PDF = bukin * btag efficiency signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_btag_formula) elif args.qcd: # Signal PDF = bukin * btag efficiency signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_btag_formula) signal_norms[fit_function] = RooRealVar('signal_norm_' + fit_function, 'signal_norm_' + fit_function, 0., 0., 1e+05) if args.fitBonly: signal_norms[fit_function].setConstant() # Make background PDF background_pdfs_notrig[fit_function], background_parameters[fit_function] = make_background_pdf(fit_function, mjj, collision_energy=8000.) background_pdf_name = background_pdfs_notrig[fit_function].GetName() background_pdfs_notrig[fit_function].SetName(background_pdf_name + "_notrig") if args.fitTrigger and args.fitOffB: background_pdf_intermediate = RooEffProd(background_pdf_name + "_intermediate", background_pdf_name + "_intermediate", background_pdfs_notrig[fit_function], offline_btag_eff_formula) background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdf_intermediate, trigeff_pt_formula) elif args.fitTrigger and not args.fitOffB: background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigeff_pt_formula) elif args.fitOffB and not args.fitTrigger: background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], offline_btag_eff_formula) else: background_pdfs[fit_function] = background_pdfs_notrig[fit_function] background_pdfs[fit_function].SetName(background_pdf_name) # Initial values if "trigbbh" in args.analysis: if fit_function == "dijet4": if mass == 650: background_parameters[fit_function]["p1"].setVal(-2.2473e+01) background_parameters[fit_function]["p2"].setVal(1.4923e+01) background_parameters[fit_function]["p3"].setVal(1.3077e+00) else: background_parameters[fit_function]["p1"].setVal(-13.5877235358) background_parameters[fit_function]["p2"].setVal(14.0659901462) background_parameters[fit_function]["p3"].setVal(1.24550474025) background_parameters[fit_function]["p1"].setMin(-50.) background_parameters[fit_function]["p1"].setMax(50.) elif fit_function == "f2": background_parameters[fit_function]["p1"].setVal(6.06731321562) background_parameters[fit_function]["p2"].setVal(6.06264502704) elif fit_function == "polypower3": background_parameters[fit_function]["p1"].setVal(50.0270215343) background_parameters[fit_function]["p2"].setVal(8.17180937688) background_parameters[fit_function]["p1"].setMin(20.) elif fit_function == "polypower4": background_parameters[fit_function]["p1"].setVal(31.3765210572) background_parameters[fit_function]["p2"].setVal(-22.5800092219) background_parameters[fit_function]["p3"].setVal(9.94548656557) elif fit_function == "f5": background_parameters[fit_function]["p1"].setVal(5.51929170927) background_parameters[fit_function]["p2"].setVal(4.25521547671) elif fit_function == "f6": background_parameters[fit_function]["p1"].setVal(35.) background_parameters[fit_function]["p2"].setVal(-28.) background_parameters[fit_function]["p3"].setVal(0.) background_parameters[fit_function]["p4"].setVal(10.) elif "trigbbl" in args.analysis: if fit_function == "dijet4": background_parameters[fit_function]["p1"].setVal(-32.4727133488) background_parameters[fit_function]["p2"].setVal(18.7641649883) background_parameters[fit_function]["p3"].setVal(1.84028034937) elif fit_function == "f2": background_parameters[fit_function]["p1"].setVal(4.96261586452) background_parameters[fit_function]["p2"].setVal(19.0848105961) if fit_function == "polypower3": background_parameters[fit_function]["p1"].setVal(60.0000032579) background_parameters[fit_function]["p2"].setVal(8.00317534363) background_parameters[fit_function]["p1"].setMin(60.) elif fit_function == "polypower4": background_parameters[fit_function]["p1"].setVal(25.4109169544) background_parameters[fit_function]["p2"].setVal(-42.56719661) background_parameters[fit_function]["p3"].setVal(12.3295648189) elif fit_function == "f5": background_parameters[fit_function]["p1"].setVal(3.74859358646) background_parameters[fit_function]["p2"].setVal(11.4366903839) elif fit_function == "f6": background_parameters[fit_function]["p1"].setVal(35.) background_parameters[fit_function]["p2"].setVal(-43.) background_parameters[fit_function]["p3"].setVal(0.) background_parameters[fit_function]["p4"].setVal(10.) data_integral = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax))) background_norms[fit_function] = RooRealVar('background_' + fit_function + '_norm', 'background_' + fit_function + '_norm', data_integral, 0., 1.e8) signal_epdfs[fit_function] = RooExtendPdf('esignal_' + fit_function, 'esignal_' + fit_function, signal_pdfs[fit_function], signal_norms[fit_function]) background_epdfs[fit_function] = RooExtendPdf('ebackground_' + fit_function, 'ebackground_' + fit_function, background_pdfs[fit_function], background_norms[fit_function]) models[fit_function] = RooAddPdf('model_' + fit_function, 's+b', RooArgList(background_epdfs[fit_function], signal_epdfs[fit_function])) if args.runFit and not args.dconly: print "[create_datacards] INFO : Starting fit with function {}".format(fit_function) models[fit_function].Print() # Fix the trigger efficiency for this fit if args.fitTrigger: trigeff_vars["alpha_trigeff_p0"].setConstant(True) trigeff_vars["alpha_trigeff_p1"].setConstant(True) trigeff_btag_var.setConstant(True) if args.fitOffB: for var in offline_btag_eff_vars.values(): var.setConstant(True) fit_results[fit_function] = models[fit_function].fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy), RooFit.Verbose(0)) print "[create_datacards] INFO : Done with fit {}. Printing results.".format(fit_function) fit_results[fit_function].Print() if args.fitTrigger: # Current strategy: freeze the trigger nuisance parameters. trigeff_vars["alpha_trigeff_p0"].setConstant(True) trigeff_vars["alpha_trigeff_p1"].setConstant(True) trigeff_btag_var.setConstant(True) if args.fitOffB: for var in offline_btag_eff_vars.values(): var.setConstant(False) print "[create_datacards] DEBUG : End args.runFit if block." # needed if want to evaluate limits without background systematics if args.fixBkg: background_norms[fit_function].setConstant() for par_name, par in background_parameters[fit_function].iteritems(): par.setConstant() # ----------------------------------------- # Set values of signal systematic variables # JES and JER uncertainties if "jes" in systematics: xp_central = signal_vars["xp_0"].getVal() xp_up = signal_fits.get_parameters(w_signal.pdf("signal__JESUp"))["xpJESUp"][0] xp_down = signal_fits.get_parameters(w_signal.pdf("signal__JESDown"))["xpJESDown"][0] signal_vars["dxp"].setVal(max(abs(xp_up - xp_central), abs(xp_down - xp_central))) if signal_vars["dxp"].getVal() > 2 * mass * 0.1: print "[create_datacards] WARNING : Large dxp value. dxp = {}, xp_down = {}, xp_central = {}, xp_up = {}".format(signal_vars["dxp"].getVal(), xp_down, xp_central, xp_up) signal_vars["alpha_jes"].setVal(0.) signal_vars["alpha_jes"].setConstant(False) else: signal_vars["dxp"].setVal(0.) signal_vars["alpha_jes"].setVal(0.) signal_vars["alpha_jes"].setConstant() signal_vars["dxp"].setError(0.) signal_vars["dxp"].setConstant() if "jer" in systematics: sigp_central = signal_vars["sigp_0"].getVal() sigp_up = signal_fits.get_parameters(w_signal.pdf("signal__JERUp"))["sigpJERUp"][0] sigp_down = signal_fits.get_parameters(w_signal.pdf("signal__JERDown"))["sigpJERDown"][0] signal_vars["dsigp"].setVal(max(abs(sigp_up - sigp_central), abs(sigp_down - sigp_central))) signal_vars["alpha_jer"].setVal(0.) signal_vars["alpha_jer"].setConstant(False) else: signal_vars["dsigp"].setVal(0.) signal_vars["alpha_jer"].setVal(0.) signal_vars["alpha_jer"].setConstant() signal_vars["dsigp"].setError(0.) signal_vars["dsigp"].setConstant() # ----------------------------------------- # create a datacard and corresponding workspace postfix = (('_' + args.postfix) if args.postfix != '' else '') wsName = 'workspace_' + args.final_state + '_m' + str(mass) + postfix + '.root' if not args.dconly: w = RooWorkspace('w','workspace') signal_pdf.SetName("signal") getattr(w,'import')(signal_pdf,RooFit.Rename("signal")) norm = args.lumi signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm/100., norm/100. / 10., norm * 10.) print "[create_datacards] INFO : Set signal norm to {}".format(signal_norm.getVal()) signal_norm.setConstant() getattr(w,'import')(signal_norm,ROOT.RooCmdArg()) for fit_function in fit_functions: print "Importing background PDF" print background_pdfs[fit_function] background_pdfs[fit_function].Print() getattr(w,'import')(background_pdfs[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function), RooFit.RecycleConflictNodes()) w.pdf("background_" + fit_function).Print() getattr(w,'import')(background_norms[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function + "_norm")) getattr(w,'import')(fit_results[fit_function]) getattr(w,'import')(signal_norms[fit_function],ROOT.RooCmdArg()) if args.fitBonly: getattr(w,'import')(models[fit_function],ROOT.RooCmdArg(),RooFit.RecycleConflictNodes()) getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs")) if args.correctTrigger: getattr(w,'import')(rooDataHist_notrigcorr, RooFit.Rename("data_obs_notrigcorr")) w.Print() print "Starting save" if args.output_path: if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ): os.mkdir( os.path.join(os.getcwd(),args.output_path) ) workspace_output_path = os.path.join(args.output_path,wsName) else: workspace_output_path = limit_config.get_workspace_filename(args.analysis, args.model, mass, fitBonly=args.fitBonly, fitTrigger=args.fitTrigger, correctTrigger=args.correctTrigger, useMCTrigger=args.useMCTrigger, qcd=args.qcd, fitOffB=args.fitOffB) if args.condor: workspace_output_path = os.path.basename(workspace_output_path) print "[create_datacards] INFO : Writing workspace to file {}".format(workspace_output_path) w.writeToFile(workspace_output_path) if args.correctTrigger: f_workspace = TFile(workspace_output_path, "UPDATE") hData.Write() hData_notrigcorr.Write() # Clean up for name, obj in signal_norms.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_pdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_pdfs_notrig.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_norms.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_pdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_pdfs_notrig.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in signal_epdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in background_epdfs.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in fit_results.iteritems(): if obj: obj.IsA().Destructor(obj) for name, dict_l2 in background_parameters.iteritems(): for name2, obj in dict_l2.iteritems(): if obj: obj.IsA().Destructor(obj) for name, obj in models.iteritems(): if obj: obj.IsA().Destructor(obj) rooDataHist.IsA().Destructor(rooDataHist) if not args.dconly: w.IsA().Destructor(w) # Make datacards only if S+B fitted #beffUnc = 0.3 boffUnc = systematics["boff"][args.analysis][args.model].Eval(mass) pdfUnc = systematics["pdfunc"][args.analysis][args.model].Eval(mass) for fit_function in fit_functions: if args.output_path: dcName = 'datacard_' + args.final_state + '_m' + str(mass) + postfix + '_' + fit_function + '.txt' datacard_output_path = os.path.join(args.output_path,dcName) else: datacard_output_path = limit_config.get_datacard_filename(args.analysis, args.model, mass, fit_function, fitTrigger=args.fitTrigger, correctTrigger=args.correctTrigger, useMCTrigger=args.useMCTrigger, qcd=args.qcd, fitOffB=args.fitOffB, fitBonly=args.fitBonly) if args.condor: datacard_output_path = os.path.basename(datacard_output_path) print "[create_datacards] INFO : Writing datacard to file {}".format(datacard_output_path) datacard = open(datacard_output_path, 'w') datacard.write('imax 1\n') datacard.write('jmax 1\n') datacard.write('kmax *\n') datacard.write('---------------\n') if args.output_path: datacard.write('shapes * * '+wsName+' w:$PROCESS\n') else: datacard.write('shapes * * '+os.path.basename(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitTrigger=args.fitTrigger, correctTrigger=args.correctTrigger, useMCTrigger=args.useMCTrigger, qcd=args.qcd, fitOffB=args.fitOffB, fitBonly=args.fitBonly))+' w:$PROCESS\n') datacard.write('---------------\n') datacard.write('bin 1\n') datacard.write('observation -1\n') datacard.write('------------------------------\n') datacard.write('bin 1 1\n') datacard.write('process signal background_' + fit_function + '\n') datacard.write('process 0 1\n') datacard.write('rate 1 1\n') datacard.write('------------------------------\n') datacard.write('lumi lnN %f -\n'%(1.+systematics["luminosity"])) if not args.useMCTrigger: datacard.write('bon lnN %f -\n'%(1.+ (trigger_efficiency.online_btag_eff[args.analysis][2] / trigger_efficiency.online_btag_eff[args.analysis][0]))) else: datacard.write('bon lnN %f -\n'%(1.+ systematics["bon"])) #datacard.write('beff lnN %f -\n'%(1.+beffUnc)) datacard.write('boff lnN %f -\n'%(1.+boffUnc)) datacard.write('pdf lnN %f -\n'%(1.+pdfUnc)) #datacard.write('bkg lnN - 1.03\n') if "jes" in systematics: datacard.write("alpha_jes param 0.0 1.0\n") if "jer" in systematics: datacard.write("alpha_jer param 0.0 1.0\n") if args.fitOffB: if eta_region == "eta1p7": datacard.write("offline_btag_eff_p0 param 6.78251e-03 3.82505e-04\n") datacard.write("offline_btag_eff_p1 param -9.55614e-06 1.13679e-06\n") datacard.write("offline_btag_eff_p2 param 4.39468e-09 7.90724e-10\n") elif eta_region == "eta2p2": datacard.write("offline_btag_eff_p0 param -1.72721e-03 3.04992e-05\n") datacard.write("offline_btag_eff_p1 param 1.72562e-06 3.23472e-08\n") datacard.write("offline_btag_eff_p2 param 8.74866e-03 7.81413e-05\n") datacard.write("offline_btag_eff_p3 param -1.67123e-03 4.30607e-05\n") # Current decision: don't put in nuisance parameters for trigger efficiency sigmoid. Impact is likely small. #if args.fitTrigger: # if "bbl" in args.analysis or "eta1p7" in args.analysis: # datacard.write("alpha_trigeff_p0 param {} {}\n".format(0.0, 1.0)) # datacard.write("alpha_trigeff_p1 param {} {}\n".format(0.0, 1.0)) # Background fit parameters --- flat prior datacard.write('background_' + fit_function + '_norm flatParam\n') for par_name, par in background_parameters[fit_function].iteritems(): datacard.write(fit_function + "_" + par_name + ' flatParam\n') datacard.close() print "[create_datacards] INFO : Done with this datacard" #print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) ) print "Done with mass {}.".format(mass)