def writefiles(self, listname, **kwargs): """Write filenames to text file for fast look up in future.""" writeevts = kwargs.pop('nevts', False) # also write nevents to file listname = repkey(listname, ERA=self.era, GROUP=self.group, SAMPLE=self.name) print ">>> Write list to %r..." % (listname) ensuredir(os.path.dirname(listname)) filenevts = self.getfilenevts(checkfiles=True, ** kwargs) if writeevts else None treename = kwargs.pop('tree', 'Events') files = self.getfiles(**kwargs) with open(listname, 'w+') as lfile: for infile in files: if writeevts: nevts = filenevts.get(infile, -1) if nevts < 0: LOG.warning( "Did not find nevents of %s. Trying again..." % (infile)) nevts = getnevents(infile, treename) infile = "%s:%d" % (infile, nevts ) # write $FILENAM(:NEVTS) lfile.write(infile + '\n')
def writefiles(self,listname,**kwargs): """Write filenames to text file for fast look up in future. If there is more than one DAS dataset path, write lists separately for each path.""" kwargs = kwargs.copy() # do not edit given dictionary writeevts = kwargs.pop('nevts',False) # also write nevents to file listname = repkey(listname,ERA=self.era,GROUP=self.group,SAMPLE=self.name) ensuredir(os.path.dirname(listname)) filenevts = self.getfilenevts(checkfiles=True,**kwargs) if writeevts else None treename = kwargs.pop('tree','Events') # do not pass to Sample.getfiles kwargs.pop('ncores') # do not pass to Sample.getfiles kwargs['refresh'] = False # already got file list in Sample.filenevts files = self.getfiles(**kwargs) # get right URL if not files: LOG.warning("writefiles: Did not find any files!") def _writefile(ofile,fname,prefix=""): """Help function to write individual files.""" if writeevts: # add nevents at end of infile string nevts = filenevts.get(fname,-1) # retrieve from cache if nevts<0: LOG.warning("Did not find nevents of %s. Trying again..."%(fname)) nevts = getnevents(fname,treename) # get nevents from file fname = "%s:%d"%(fname,nevts) # write $FILENAM(:NEVTS) ofile.write(prefix+fname+'\n') paths = self.paths if '$PATH' in listname else [self.paths[0]] for path in paths: listname_ = repkey(listname,PATH=path.strip('/').replace('/','__')) with open(listname_,'w+') as lfile: if '$PATH' in listname: # write only the file list of this path to this text file print ">>> Write %s files to list %r..."%(len(self.pathfiles[path]),listname_) for infile in self.pathfiles[path]: _writefile(lfile,infile) elif len(self.paths)<=1: # write file list for the only path if self.nevents>0: print ">>> Write %s files to list %r..."%(len(files),listname_) else: print ">>> Write %s files (%d events) to list %r..."%(len(files),self.nevents,listname_) for infile in files: _writefile(lfile,infile) else: # divide up list per DAS dataset path if self.nevents>0: print ">>> Write %s files to list %r..."%(len(files),listname_) else: print ">>> Write %s files (%d events) to list %r..."%(len(files),self.nevents,listname_) for i, path in enumerate(self.paths): print ">>> %3s files for %s..."%(len(self.pathfiles[path]),path) lfile.write("DASPATH=%s\n"%(path)) # write special line to text file, which loadfiles() can parse for infile in self.pathfiles[path]: # loop over this list (general list is sorted) LOG.insist(infile in files,"Did not find file %s in general list! %s"%(infile,files)) _writefile(lfile,infile,prefix=" ") if i+1<len(self.paths): # add extra white line between blocks lfile.write("\n")
def hadd(self, sources, target, **kwargs): """Hadd files. Create intermediate target file if needed.""" target = self.expandpath(target, here=True) verb = kwargs.get('verb', self.verbosity) tmpdir = kwargs.get( 'tmpdir', target.startswith(self.parent) and self.cpurl != '') htarget = target if tmpdir: if not isinstance(tmpdir, str): tmpdir = self.tmpdir tmpdir = ensuredir(tmpdir, verb=verb) htarget = os.path.join(tmpdir, os.path.basename(target)) if isinstance(sources, basestring): sources = [sources] source = "" for i, file in enumerate(sources, 1): source += self.expandpath(file, url=self.fileurl) + ' ' source = source.strip() if verb >= 2: print ">>> %-10s = %r" % ('sources', sources) print ">>> %-10s = %r" % ('source', source) print ">>> %-10s = %r" % ('target', target) print ">>> %-10s = %r" % ('htarget', htarget) out = self.execute("%s %s %s" % (self.haddcmd, htarget, source), verb=verb) if tmpdir: cpout = self.cp(htarget, target, verb=verb) rmfile(htarget) return out
def getconfig(verb=0, refresh=False): """Get configuration from JSON file.""" global _cfgdefaults, basedir, CONFIG if CONFIG and not refresh: return CONFIG # SETTING cfgdir = ensuredir(basedir, "config") cfgname = os.path.join(cfgdir, "config.json") cfgdict = _cfgdefaults.copy() rqdstrs = [ k for k, v in _cfgdefaults.iteritems() if isinstance(v, basestring) ] rqddicts = [k for k, v in _cfgdefaults.iteritems() if isinstance(v, dict)] # GET CONFIG if os.path.isfile(cfgname): with open(cfgname, 'r') as file: cfgdict = json.load(file, object_pairs_hook=OrderedDict) update = False for key in _cfgdefaults.keys(): # check for missing keys if key not in cfgdict: LOG.warning( "Key '%s' not set in config file %s. Setting to default %r" % (key, os.path.relpath(cfgname), _cfgdefaults[key])) cfgdict[key] = _cfgdefaults[key] update = True if update: print ">>> Saving defaults..." with open(cfgname, 'w') as file: json.dump(cfgdict, file, indent=2) else: LOG.warning( "Config file '%s' does not exist in %s. Creating with defaults..." % (cfgname, cfgdir)) with open(cfgname, 'w') as file: json.dump(cfgdict, file, indent=2) # SANITY CHECKS - format of values for required keys for key in rqdstrs: assert key in cfgdict, "Required key '%s' not found in the configuration file..." % ( key) assert isinstance(cfgdict[key],basestring),\ "Required value for '%s' must be a string or unicode! Instead is of type %s: %r"%(key,type(cfgdict[key]),key) for key in rqddicts: assert key in cfgdict, "Required key '%s' not found in the configuration file..." % ( key) assert isinstance(cfgdict[key],dict),\ "Required value for '%s' must be a dictionary! Instead is of type %s: %r"%(key,type(cfgdict[key]),cfgdict[key]) # RETURN if verb >= 1: print '-' * 80 print ">>> Reading config JSON file '%s'" % cfgname for key, value in cfgdict.iteritems(): print ">>> %-13s = %s" % (key, value) print '-' * 80 CONFIG = Config(cfgdict, cfgname) return CONFIG
def compareMCProfiles(samples, channel, era, tag=""): """Compare MC profiles.""" print ">>> compareMCProfiles()" hname = 'pileup' htitle = 'MC average' outdir = ensuredir("plots") avehist = None hists = [] if tag and tag[0] != '_': tag = '_' + tag if 'pmx' in tag: htitle += " %s pre-mixing" % ("old" if "old" in tag else "new") # GET histograms for sample, fname in samples: print ">>> %s" % (fname) file, hist = gethist(fname, hname, retfile=True) hist.SetName(sample) hist.SetTitle(sample) hist.SetDirectory(0) if avehist == None: avehist = hist.Clone('average%s' % tag) avehist.SetTitle(htitle) avehist.SetDirectory(0) else: avehist.Add(hist) hist.Scale(1. / hist.Integral()) hists.append(hist) file.Close() # PLOT hists = [avehist] + hists colors = [kBlack] + linecolors avehist.Scale(1. / avehist.Integral()) pname = "%s/pileup_MC_%s%s" % (outdir, era, tag) xtitle = "Number of true interactions" plot = Plot(hists, ratio=True) plot.draw(xtitle=xtitle, ytitle="A.U.", rtitle="MC / Ave.", textsize=0.032, rmin=0.45, rmax=1.55, denom=2, colors=colors) plot.drawlegend('TTR', tsize=0.04, latex=False) plot.saveas(pname + ".png") plot.saveas(pname + ".pdf") plot.close(keep=True) for hist in hists: # clean memory if hist == avehist: continue if hist.GetDirectory(): gDirectory.Delete(hist.GetName()) else: hist.Delete() return avehist
def main(): nevts = 1000000 predefine = True #and False # initialize histogram before calling filling sample = 'ZTT' #'Data' outdir = ensuredir('plots') filedict = makesamples(nevts, sample=sample, outdir=outdir) file, tree = filedict[sample] nevts = tree.GetEntries() print ">>> Using pseudo data %s..." % (file.GetName()) variables = [ ('m_vis', 20, 0, 140), ('m_vis', [ 0, 20, 40, 50, 60, 65, 70, 75, 80, 85, 90, 95, 100, 110, 130, 160, 200 ]), ('pt_1', 40, 0, 120), ('pt_2', 40, 0, 120), ('pt_1+pt_2', 40, 0, 200), ('eta_1', 30, -3, 3), ('eta_2', 30, -3, 3), ('min(eta_1,eta_2)', 30, -3, 3), ('njets', 10, 0, 10), ] variables2D = [ ('pt_1', 50, 0, 100, 'pt_2', 50, 0, 100), ('pt_1', 50, 0, 100, 'eta_1', 50, -3, 3), ('pt_2', 50, 0, 100, 'eta_2', 50, -3, 3), ('eta_1', 50, -3, 3, 'eta_1', 50, -3, 3), ('pt_1', 50, 0, 100, 'm_vis', 50, 0, 150), ('pt_2', 50, 0, 100, 'm_vis', 50, 0, 150), ] selections = [ ('pt_1>30 && pt_2>30 && abs(eta_1)<2.4 && abs(eta_2)<2.4', "weight"), ] dtime1 = singledraw(tree, variables, selections, outdir=outdir, predefine=predefine) dtime2 = multidraw(tree, variables, selections, outdir=outdir, predefine=predefine) dtime3 = multidraw2D(tree, variables2D, selections, outdir=outdir, predefine=predefine) file.Close() print ">>> Result: MultiDraw is %.2f times faster than TTree::Draw for %s events and %s variables!" % ( dtime1 / dtime2, nevts, len(variables))
def compareDataMCProfiles(datahists,mchist,era="",minbiases=0.0,tag="",rmin=0.6,rmax=1.4,delete=False): """Compare data/MC profiles.""" print ">>> compareDataMCProfiles()" mctitle = "MC average" outdir = ensuredir("plots") if islist(datahists): # multiple datahists if all(islist(x) for x in datahists): # datahists = [(minbias1,datahist1),...] minbiases = [m for m,h in datahists] datahists = [h for m,h in datahists] else: # is single datahist histogram minbiases = [minbiases] datahists = [datahists] hists = datahists+[mchist] styles = [kSolid]*len(datahists)+[kDashed] colors = [kBlack]+linecolors if len(datahists)==1 else linecolors[:len(datahists)]+[kBlack] if 'pmx' in tag: width = 0.36 position = 'TCR' else: width = 0.39 position = 'TR' if era and isinstance(era,str) and any(s in era for s in ["Run","VFP"]): width = max(width,0.26+(len(era)-5)*0.018) position = 'TCR' if tag and tag[0]!='_': tag = '_'+tag if 'pmx' in tag: mctitle += " (%s pre-mixing)"%("old" if "old" in tag else "new") if len(minbiases)==1 and minbiases[0]>0: tag = "_"+str(minbiases[0]).replace('.','p') for datahist, minbias in zip(datahists,minbiases): title = "Data" if era: title += " %s"%(era) if minbias>0: title += ", %.1f pb"%(minbias) if 'VFP' in era: title = title.replace("_"," ").replace("VFP","-VFP") datahist.SetTitle(title) datahist.Scale(1./datahist.Integral()) mchist.SetTitle(mctitle) mchist.Scale(1./mchist.Integral()) xtitle = "Number of interactions" pname = "%s/pileup_Data-MC_%s%s"%(outdir,era,tag) plot = Plot(hists,ratio=True) plot.draw(xtitle=xtitle,ytitle="A.U.",rtitle="Data / MC", textsize=0.045,rmin=rmin,rmax=rmax,denom=-1,colors=colors,styles=styles) plot.drawlegend(position,width=width) plot.saveas(pname+".png") plot.saveas(pname+".pdf") plot.close(keep=True) if delete: deletehist(datahists) # clean memory
def setdefaultconfig(verb=0): """Set configuration to default values.""" global _cfgdefaults, basedir, CONFIG # SETTING cfgdir = ensuredir(basedir,"config") cfgname = os.path.join(cfgdir,"config.json") cfgdict = _cfgdefaults.copy() if os.path.isfile(cfgname): LOG.warning("Config file '%s' already exists. Overwriting with defaults..."%(cfgname)) CONFIG = Config(cfgdict,cfgname) CONFIG.write() return CONFIG
def hadd(self, sources, target, **kwargs): """Hadd files. Create intermediate target file if needed.""" target = self.expandpath(target, here=True) dryrun = kwargs.get('dry', False) verb = kwargs.get('verb', self.verbosity) fileurl = kwargs.get('url', self.fileurl) maxopen = kwargs.get('maxopenfiles', 0) # maximum number of files opened via -n option tmpdir = kwargs.get( 'tmpdir', target.startswith(self.parent) and self.cpurl != '') htarget = target if tmpdir: # create temporary dir for hadd target, and copy after if not isinstance(tmpdir, str): tmpdir = self.tmpdir tmpdir = ensuredir(tmpdir, verb=verb) htarget = os.path.join(tmpdir, os.path.basename(target)) if isinstance(sources, basestring): sources = [sources] source = "" for i, file in enumerate(sources, 1): fname = os.path.basename(file) if '$PATH' in file and fileurl and isglob( fname): # expand glob pattern parent = os.path.dirname(file) files = self.getfiles(parent, filter=fname, url=fileurl) source += ' '.join(files) + ' ' else: source += self.expandpath(file, url=fileurl) + ' ' source = source.strip() if verb >= 2: print ">>> %-10s = %r" % ('sources', sources) print ">>> %-10s = %r" % ('source', source) print ">>> %-10s = %r" % ('target', target) print ">>> %-10s = %r" % ('htarget', htarget) print ">>> %-10s = %r" % ('maxopen', maxopen) haddcmd = self.haddcmd if maxopen >= 1: haddcmd += " -n %s" % (maxopen) out = self.execute("%s %s %s" % (haddcmd, htarget, source), dry=dryrun, verb=verb) if tmpdir: # copy hadd target and remove temporary file cpout = self.cp(htarget, target, dry=dryrun, verb=verb) if not dryrun: rmfile(htarget) return out
def compareDataMCProfiles(datahist, mchist, era, minbias, tag="", rmin=0.75, rmax=1.25): """Compare data/MC profiles.""" print ">>> compareDataMCProfiles()" mctitle = "MC average" outdir = ensuredir("plots") hists = [datahist, mchist] colors = [kBlack] + linecolors width = 0.36 if 'pmx' in tag else 0.26 if isinstance(era, str) and "Run" in era: width = max(width, 0.26 + (len(era) - 5) * 0.02) if tag and tag[0] != '_': tag = '_' + tag if 'pmx' in tag: mctitle += " (%s pre-mixing)" % ("old" if "old" in tag else "new") datahist.SetTitle("Data %s, %.1f pb" % (era, minbias)) mchist.SetTitle(mctitle) datahist.Scale(1. / datahist.Integral()) mchist.Scale(1. / mchist.Integral()) xtitle = "Number of interactions" pname = "%s/pileup_Data-MC_%s_%s%s" % (outdir, era, str(minbias).replace( '.', 'p'), tag) plot = Plot(hists, ratio=True) plot.draw(xtitle=xtitle, ytitle="A.U.", rtitle="Data / MC", textsize=0.045, rmin=rmin, rmax=rmax, denom=2, colors=colors) plot.drawlegend('TCR', width=width) plot.saveas(pname + ".png") plot.saveas(pname + ".pdf") plot.close(keep=True) deletehist(datahist) # clean memory
def main(args): eras = args.eras injson = args.injson periods = args.periods rrange = args.rrange diffs = args.diffs outdir = args.outdir verbosity = args.verbosity for era in eras: if diffs: compareJSONs(diffs, verb=verbosity) elif periods: periods = cleanPeriods(periods) jname = injson or getJSON(era) outdir = ensuredir("json") for period in periods: jsonout = filterJSONByRunNumberRange(jname, era, period=period, outdir=outdir, verb=verbosity) elif rrange: jname = injson or getJSON(era) jsonout = filterJSONByRunNumberRange(jname, era, rrange=rrange, outdir=outdir, verb=verbosity) else: print ">>> Please specifiy a period (-p BCD) or a range of run numbers (-r 272007-278770)" print ">>> JSON for %r: %s" % (era, jname) print ">>> datasets: " datasets = getRuns(era) for period in sorted(datasets.keys()): start, end = datasets[period] print ">>> %s: %s-%s" % (period, start, end)
def testBatch(path,verb=0): # SETTINGS verbosity = args.verbosity dryrun = args.dryrun # prepare job and submit command, but do not submit ntasks = args.ntasks # only run a few test tasks per job nchecks = args.nchecks # number of times to check job status queue = args.queue # queue option for the batch system (job flavor for HTCondor) time = args.time # maximum time for the batch system batchopts = args.batchopts # extra options for the batch system #prompt = args.prompt # ask user confirmation before submitting outdir = ensuredir("testBatch") logdir = ensuredir("testBatch/log") jobname = "testBatch" tasklist = os.path.join(outdir,"testBatch.txt") # INITIALIZE LOG.header("__init__") #batch = ensuremodule(system,"PicoProducer.batch."+batch) batch = getbatch(args.batch,verb=verbosity+1) print ">>> %r"%(batch) print ">>> %-10s = %s"%('jobname',jobname) print ">>> %-10s = %s"%('ntasks',ntasks) print ">>> %-10s = %s"%('nchecks',nchecks) print ">>> %-10s = %s"%('outdir',outdir) print ">>> %-10s = %s"%('logdir',logdir) print ">>> %-10s = %s"%('dryrun',dryrun) print ">>> %-10s = %s"%('queue',queue) print ">>> %-10s = %s"%('time',time) print ">>> %-10s = %s"%('batchopts',batchopts) print ">>> %-10s = %s"%('verbosity',verbosity) print ">>> " # PREPARE JOBS createtasks(tasklist,ntasks) # SUBMIT LOG.header("Submit") jkwargs = { # key-word arguments for batch.submit 'name': jobname, 'opt': batchopts, 'dry': dryrun, 'short': True, 'queue':queue, 'time':time } if batch.system=='HTCondor': # use specific settings for KIT condor if 'etp' in platform.node(): script = "python/batch/submit_HTCondor_KIT.sub" else: script = "python/batch/submit_HTCondor.sub" appcmds = ["initialdir=%s"%(outdir), "mylogfile='log/%s.$(ClusterId).$(ProcId).log'"%(jobname)] jkwargs.update({ 'app': appcmds }) elif batch.system=='SLURM': script = "python/batch/submit_SLURM.sh" logfile = os.path.join(logdir,"%x.%A.%a.log") # $JOBNAME.o$JOBID.$TASKID.log jkwargs.update({ 'log': logfile, 'array': ntasks }) #elif batch.system=='SGE': #elif batch.system=='CRAB': else: LOG.throw(NotImplementedError,"Submission for batch system '%s' has not been implemented (yet)..."%(batch.system)) jobid = batch.submit(script,tasklist,**jkwargs) print ">>> jobid: %s"%(jobid) # CHECK JOBS LOG.header("Check jobs") for i in xrange(nchecks): jobs = batch.jobs(jobid,verb=verbosity-1) # get refreshed job list #jobs = batch.jobs(verb=verbosity-1) # get refreshed job list print ">>> job objects: %r"%(jobs) print ">>> " #for job in jobs: # print ">>> Found job %r, status=%r, args=%r"%(job,job.getstatus(),job.args.rstrip()) if i<nchecks-1: sleep(2)
def main(args): print "" analysis = 'ztt_tid' obsset = args.observables channels = args.channels eras = args.eras tag = "" bin = 'Tight' title = "m_{T} < 60 GeV, D_{#zeta} > -25 GeV, |#Delta#eta| < 1.5" #"mutau, DeepTau2017v2p1VSjet" fname = "$DIR/$ANALYSIS_$OBS_$CHANNEL-$BIN-$ERA$TAG.shapes.root" pname = "$DIR/$OBS_$CHANNEL-$BIN-$ERA$TAG_$FIT.png" #outfile = "$TAG/$ANALYSIS_%s_$CHANNEL-$ERA%s.inputs.root"%(obs,tag+outtag) # PLOT SETTINGS ZTT = "Z -> #tau#tau" # "Z -> #tau_{#mu}#tau_{h}" #STYLE.sample_colors['ZTT'] = STYLE.kOrange-4 STYLE.sample_titles.update({ 'ZTT': ZTT, 'ZTT_DM0': ZTT + ", h^{#pm}", 'ZTT_DM1': ZTT + ", h^{#pm}#pi^{0}", 'ZTT_DM10': ZTT + ", h^{#pm}h^{#mp}h^{#pm}", 'ZTT_DM11': ZTT + ", h^{#pm}h^{#mp}h^{#pm}#pi^{0}", 'ZJ': "Z -> ll", }) procs = [ 'ZTT', 'ZL', 'ZJ', 'TTT', 'TTJ', 'W', 'ST', 'VV', 'QCD', 'data_obs' #'STT', 'STJ' ] groups = [ (['^TT*'], 'Top', 'ttbar'), #,STYLE.sample_colors['TT']), #(['^TT*','ST*'],'Top','ttbar and single top'), (['W*', 'ZJ', 'VV', 'ST*', 'QCD'], 'EWK', 'Electroweak'), #,STYLE.sample_colors['EWK']), ] title_dict = { 'mvis': "m_{vis} (GeV)", 'mtau': "m(#tau_{h}) (GeV)", } tsize = 0.054 PLOT._lsize = 0.040 # label size ratio = False pos = 'x=0.56,y=0.88' ncol = 1 square = not ratio and False exts = ['png', 'pdf', 'root', 'C'] if "mtau" in obsset: procs = ['ZTT_DM0', 'ZTT_DM1', 'ZTT_DM10', 'ZTT_DM11'] + procs[1:] pos = 'x=0.22,y=0.85' ncol = 2 # PLOT for era in eras: setera(era, extra="") for channel in channels: for obs in obsset: indir = "output/%s" % era outdir = ensuredir("plots/%s" % era) xtitle = title_dict.get(obs) fname_ = repkey(fname, DIR=indir, ANALYSIS=analysis, OBS=obs, CHANNEL=channel, BIN=bin, ERA=era, TAG=tag) pname_ = repkey(pname, DIR=outdir, ANALYSIS=analysis, OBS=obs, CHANNEL=channel, BIN=bin, ERA=era, TAG=tag) drawpostfit(fname_, bin, procs, pname=pname_, tag=tag, group=groups, title=title, xtitle=xtitle, tsize=tsize, pos=pos, ncol=ncol, ratio=ratio, square=square, exts=exts)
def main(): eras = args.eras periods = cleanEras(args.periods) channel = args.channel types = args.types verbosity = args.verbosity minbiases = [69.2] if periods else [69.2, 80.0, 69.2 * 1.046, 69.2 * 0.954] for era in args.eras: year = getyear(era) mcfilename = "MC_PileUp_%s.root" % (era) jsondir = os.path.join(datadir, 'json', str(year)) pileup = os.path.join(jsondir, "pileup_latest.txt") CMSStyle.setCMSEra(year) if era == '2016': # https://twiki.cern.ch/twiki/bin/viewauth/CMS/PdmV2017Analysis # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions16/13TeV/ReReco/Final/Cert_271036-284044_13TeV_23Sep2016ReReco_Collisions16_JSON.txt" # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions16/13TeV/Final/Cert_271036-284044_13TeV_PromptReco_Collisions16_JSON.txt # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions16/13TeV/PileUp/pileup_latest.txt JSON = os.path.join( jsondir, "Cert_271036-284044_13TeV_ReReco_07Aug2017_Collisions16_JSON.txt" ) datasets = { 'B': (272007, 275376), 'C': (275657, 276283), 'D': (276315, 276811), 'E': (276831, 277420), 'F': (277772, 278808), 'G': (278820, 280385), 'H': (280919, 284044), } campaign = "Moriond17" samples = [ ( 'TT', "TT", ), ( 'DY', "DYJetsToLL_M-10to50", ), ( 'DY', "DYJetsToLL_M-50", ), ( 'DY', "DY1JetsToLL_M-50", ), ( 'DY', "DY2JetsToLL_M-50", ), ( 'DY', "DY3JetsToLL_M-50", ), ( 'WJ', "WJetsToLNu", ), ( 'WJ', "W1JetsToLNu", ), ( 'WJ', "W2JetsToLNu", ), ( 'WJ', "W3JetsToLNu", ), ( 'WJ', "W4JetsToLNu", ), ( 'ST', "ST_tW_top", ), ( 'ST', "ST_tW_antitop", ), ( 'ST', "ST_t-channel_top", ), ( 'ST', "ST_t-channel_antitop", ), #( 'ST', "ST_s-channel", ), ( 'VV', "WW", ), ( 'VV', "WZ", ), ( 'VV', "ZZ", ), ] elif '2017' in era: # https://twiki.cern.ch/twiki/bin/viewauth/CMS/PdmV2017Analysis # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions16/13TeV/Final/Cert_271036-284044_13TeV_PromptReco_Collisions16_JSON.txt # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions17/13TeV/PileUp/pileup_latest.txt JSON = os.path.join( jsondir, "Cert_294927-306462_13TeV_PromptReco_Collisions17_JSON.txt") datasets = { 'B': (297020, 299329), 'C': (299337, 302029), 'D': (302030, 303434), 'E': (303435, 304826), 'F': (304911, 306462), } samples_bug = [] samples_fix = [] if 'UL' in era: campaign = "Summer19" samples_fix = [ #( 'DY', "DYJetsToLL_M-10to50", ), ( 'DY', "DYJetsToLL_M-50", ), ( 'DY', "DY1JetsToLL_M-50", ), ( 'DY', "DY2JetsToLL_M-50", ), ( 'DY', "DY3JetsToLL_M-50", ), ( 'DY', "DY4JetsToLL_M-50", ), #( 'TT', "TTTo2L2Nu", ), ( 'TT', "TTToHadronic", ), #( 'TT', "TTToSemiLeptonic", ), ( 'WJ', "WJetsToLNu", ), ( 'WJ', "W1JetsToLNu", ), ( 'WJ', "W2JetsToLNu", ), ( 'WJ', "W3JetsToLNu", ), ( 'WJ', "W4JetsToLNu", ), ( 'ST', "ST_tW_top", ), ( 'ST', "ST_tW_antitop", ), ( 'ST', "ST_t-channel_top", ), ( 'ST', "ST_t-channel_antitop", ), #( 'ST', "ST_s-channel", ), #( 'VV', "WW", ), #( 'VV', "WZ", ), #( 'VV', "ZZ", ), ] else: campaign = "Winter17_V2" samples_bug = [ ( 'DY', "DYJetsToLL_M-50", ), ( 'WJ', "W3JetsToLNu", ), ( 'VV', "WZ", ), ] samples_fix = [ ( 'DY', "DYJetsToLL_M-10to50", ), ( 'DY', "DY1JetsToLL_M-50", ), ( 'DY', "DY2JetsToLL_M-50", ), ( 'DY', "DY3JetsToLL_M-50", ), ( 'DY', "DY4JetsToLL_M-50", ), ( 'TT', "TTTo2L2Nu", ), ( 'TT', "TTToHadronic", ), ( 'TT', "TTToSemiLeptonic", ), ( 'WJ', "WJetsToLNu", ), ( 'WJ', "W1JetsToLNu", ), ( 'WJ', "W2JetsToLNu", ), ( 'WJ', "W4JetsToLNu", ), ( 'ST', "ST_tW_top", ), ( 'ST', "ST_tW_antitop", ), ( 'ST', "ST_t-channel_top", ), ( 'ST', "ST_t-channel_antitop", ), #( 'ST', "ST_s-channel", ), ( 'VV', "WW", ), ( 'VV', "ZZ", ), ] samples = samples_bug + samples_fix else: # https://twiki.cern.ch/twiki/bin/viewauth/CMS/PdmV2018Analysis # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions18/13TeV/PromptReco # /afs/cern.ch/cms/CAF/CMSCOMM/COMM_DQM/certification/Collisions18/13TeV/PileUp/pileup_latest.txt JSON = os.path.join( jsondir, "Cert_314472-325175_13TeV_PromptReco_Collisions18_JSON.txt") datasets = { 'A': (315252, 316995), 'B': (317080, 319310), 'C': (319337, 320065), 'D': (320673, 325175), } campaign = "Autumn18" samples = [ ( 'TT', "TTTo2L2Nu", ), ( 'TT', "TTToHadronic", ), ( 'TT', "TTToSemiLeptonic", ), ( 'DY', "DYJetsToLL_M-10to50", ), ( 'DY', "DYJetsToLL_M-50", ), ( 'DY', "DY1JetsToLL_M-50", ), ( 'DY', "DY2JetsToLL_M-50", ), ( 'DY', "DY3JetsToLL_M-50", ), ( 'DY', "DY4JetsToLL_M-50", ), #( 'WJ', "WJetsToLNu", ), ( 'WJ', "W1JetsToLNu", ), ( 'WJ', "W2JetsToLNu", ), ( 'WJ', "W3JetsToLNu", ), ( 'WJ', "W4JetsToLNu", ), ( 'ST', "ST_tW_top", ), ( 'ST', "ST_tW_antitop", ), ( 'ST', "ST_t-channel_top", ), ( 'ST', "ST_t-channel_antitop", ), #( 'ST', "ST_s-channel", ), ( 'VV', "WW", ), ( 'VV', "WZ", ), ( 'VV', "ZZ", ), ] # SAMPLES FILENAMES fname = "$PICODIR/$SAMPLE_$CHANNEL.root" if '$PICODIR' in fname: import TauFW.PicoProducer.tools.config as GLOB CONFIG = GLOB.getconfig(verb=verbosity) fname = repkey(fname, PICODIR=CONFIG['picodir']) for i, (group, sample) in enumerate(samples): fname = repkey(fname, ERA=era, GROUP=group, SAMPLE=sample, CHANNEL=channel) samples[i] = (sample, fname) if verbosity >= 1: print ">>> samples = %r" % (samples) # JSON jsons = {} if periods: outdir = ensuredir("json") for period in periods: start, end = getPeriodRunNumbers(period, datasets) erarun = "Run%d%s" % (era, period) jsonout = "json/" + re.sub(r"\d{6}-\d{6}", erarun, JSON.split('/')[-1]) filterJSONByRunNumberRange(JSON, jsonout, start, end, verb=verbosity) jsons[erarun] = jsonout else: jsons[era] = JSON # DATA datahists = {period: [] for period in jsons} if 'data' in types: for period, json in jsons.iteritems(): for minbias in minbiases: filename = "Data_PileUp_%s_%s.root" % ( period, str(minbias).replace('.', 'p')) datahist = getDataProfile(filename, json, pileup, 100, era, minbias) datahists[period].append((minbias, datahist)) elif args.plot: for era in jsons: for minbias in minbiases: filename = "Data_PileUp_%s_%s.root" % ( era, str(minbias).replace('.', 'p')) file, hist = gethist(filename, 'pileup', retfile=True) if not file or not hist: continue hist.SetDirectory(0) file.Close() datahists[era].append((minbias, hist)) # MC if 'mc' in types: mcfilename = "MC_PileUp_%s.root" % (era) #mcfilename = "MC_PileUp_%s_%s.root"%(era,campaign) getMCProfile(mcfilename, samples, channel, era) if args.plot: mchist = compareMCProfiles(samples, channel, era) for era in jsons: for minbias, datahist in datahists[era]: compareDataMCProfiles(datahist, mchist, era, minbias) deletehist(mchist) # clean memory if era == '2017': # also check new/old pmx separately mcfilename_bug = mcfilename.replace(".root", "_old_pmx.root") mcfilename_fix = mcfilename.replace(".root", "_new_pmx.root") getMCProfile(mcfilename_bug, samples_bug, channel, era) getMCProfile(mcfilename_fix, samples_fix, channel, era) if args.plot: mchist_bug = compareMCProfiles(samples_bug, channel, era, tag="old_pmx") mchist_fix = compareMCProfiles(samples_fix, channel, era, tag="new_pmx") for era in jsons: for minbias, datahist in datahists[era]: compareDataMCProfiles(datahist, mchist_bug, era, minbias, tag="old_pmx") compareDataMCProfiles(datahist, mchist_fix, era, minbias, tag="new_pmx") # FLAT if 'flat' in types: filename = "MC_PileUp_%d_FlatPU0to75.root" % era hist_flat = getFlatProfile(filename, 75) for era in jsons: for minbias, datahist in datahists[era]: compareDataMCProfiles(datahist, hist_flat, era, minbias, tag="FlatPU0to75", rmin=0.0, rmax=3.1)
def createinputs(fname, sampleset, observables, bins, **kwargs): """Create histogram inputs in ROOT file for datacards. fname: filename pattern of ROOT file sampleset: SampleSet object observables: list of Variables objects bins: list of Selection objects """ #LOG.header("createinputs") outdir = kwargs.get('outdir', "") tag = kwargs.get('tag', "") # file tag htag = kwargs.get('htag', "") # hist tag for systematic filters = kwargs.get('filter', None) # only create histograms for these processes vetoes = kwargs.get('veto', None) # veto these processes parallel = kwargs.get('parallel', True) # MultiDraw histograms in parallel recreate = kwargs.get('recreate', False) # recreate ROOT file replaceweight = kwargs.get('replaceweight', None) # replace weight extraweight = kwargs.get('weight', "") # extraweight shiftQCD = kwargs.get('shiftQCD', 0) # e.g 0.30 for 30% verbosity = kwargs.get('verb', 0) option = 'RECREATE' if recreate else 'UPDATE' method = 'QCD_OSSS' if filters == None or 'QCD' in filters else None method = kwargs.get('method', method) # FILE LOGISTICS: prepare file and directories files = {} ensuredir(outdir) fname = os.path.join(outdir, fname) for obs in observables: obsname = obs.filename ftag = tag + obs.tag fname_ = repkey(fname, OBS=obsname, TAG=tag) file = TFile.Open(fname_, option) if recreate: print ">>> created file %s" % (fname_) for selection in bins: if not obs.plotfor(selection): continue obs.changecontext(selection) ensureTDirectory(file, selection.filename, cd=True, verb=verbosity) if recreate: string = joincuts(selection.selection, obs.cut) TNamed("selection", string).Write( ) # write exact selection string to ROOT file for the record / debugging #TNamed("weight",sampleset.weight).Write() LOG.verb( "%s selection %r: %r" % (obsname, selection.name, string), verbosity, 1) files[obs] = file # GET HISTS for selection in bins: bin = selection.filename # bin name print ">>>\n>>> " + color( " %s " % (bin), 'magenta', bold=True, ul=True) if htag: print ">>> systematic uncertainty: %s" % (color( htag.lstrip('_'), 'grey')) if recreate or verbosity >= 1: print ">>> %r" % (selection.selection) hists = sampleset.gethists(observables, selection, method=method, split=True, parallel=parallel, filter=filters, veto=vetoes) # SAVE HIST ljust = 4 + max(11, len(htag)) # extra space TAB = LOG.table("%10.1f %10d %-18s %s") TAB.printheader('events', 'entries', 'variable', 'process'.ljust(ljust)) for obs, hist in hists.iterhists(): name = lreplace(hist.GetName(), obs.filename).strip( '_') # histname = $VAR_$NAME (see Sample.gethist) if not name.endswith(htag): name += htag # HIST = $PROCESS_$SYSTEMATIC name = repkey(name, BIN=bin) drawopt = 'E1' if 'data' in name else 'EHIST' lcolor = kBlack if any( s in name for s in ['data', 'ST', 'VV']) else hist.GetFillColor() hist.SetOption(drawopt) hist.SetLineColor(lcolor) hist.SetFillStyle(0) # no fill in ROOT file hist.SetName(name) hist.GetXaxis().SetTitle(obs.title) for i, yval in enumerate(hist): if yval < 0: print ">>> replace bin %d (%.3f<0) of %r" % ( i, yval, hist.GetName()) hist.SetBinContent(i, 0) files[obs].cd(bin) # $FILE:$BIN/$PROCESS_$SYSTEMATC hist.Write(name, TH1.kOverwrite) TAB.printrow(hist.GetSumOfWeights(), hist.GetEntries(), obs.printbins(), name) deletehist(hist) # clean memory # CLOSE for obs, file in files.iteritems(): file.Close()
def plotpanels(ratio, **kwargs): # SETTING width = kwargs.get('width', 800) height = kwargs.get('height', 750) lmargin = kwargs.get('lmargin', 1.) outdir = ensuredir("plots/") fname = 'multipad_%sx%s_%s' % (width, height, str(ratio)) fname = outdir + fname.replace('.', 'p') + '.png' # CANVAS canvas = TCanvas('canvas', 'canvas', 100, 100, width, height) canvas.SetFillColor(0) canvas.SetBorderMode(0) canvas.SetFrameBorderMode(0) canvas.SetMargin(0.0, 0.0, 0.0, 0.0) # LRBT canvas.Divide(2) pad1 = canvas.GetPad(1) pad2 = canvas.GetPad(2) pad1.SetPad('pad1', 'pad1', 0.0, ratio, 1.0, 1.0) pad1.SetMargin(0.14 * lmargin, 0.04, 0.11, 0.08) pad1.SetFillColor(0) #pad1.SetFillStyle(4000) # transparant (for pdf) #pad1.SetFillStyle(0) #pad1.SetBorderMode(0) pad1.Draw() pad2.SetPad('pad2', 'pad2', 0.0, 0.0, 1.0, ratio) pad2.SetMargin(0.14 * lmargin, 0.04, 0.30, 0.10) pad2.SetFillColor(0) #pad2.SetFillColorAlpha(0,0.0) #pad2.SetFillStyle(4000) # transparant (for pdf) #pad2.SetBorderMode(0) pad2.Draw() # SIZES # https://root.cern.ch/doc/master/classTPad.html TH, TW = pad1.GetWh() * pad1.GetHNDC(), pad1.GetWw() * pad1.GetWNDC() BH, BW = pad2.GetWh() * pad2.GetHNDC(), pad2.GetWw() * pad2.GetWNDC() TR = TH / TW BR = BH / BW TM = max(TH, TW) BM = max(BH, BW) Tm = min(TH, TW) Bm = min(BH, BW) print ">>> %6s: %8s %8s %8s %8s %8s %8s %8s" % ( 'pad', 'Wh', 'HNDC', 'Wh*HNDC', 'Ww', 'WNDC', 'Ww*WNDC', 'Wh*HNDC/Ww*WNDC') print ">>> %6s: %8.1f %8.3f %8.1f %8.1f %8.3f %8.1f" % ( 'canvas', canvas.GetWh(), canvas.GetHNDC(), canvas.GetWh() * canvas.GetHNDC(), canvas.GetWw(), canvas.GetWNDC(), canvas.GetWw() * canvas.GetWNDC()) print ">>> %6s: %8.1f %8.3f %8.1f %8.1f %8.3f %8.1f %10.3f" % ( 'pad1', pad1.GetWh(), pad1.GetHNDC(), pad1.GetWh() * pad1.GetHNDC(), pad1.GetWw(), pad1.GetWNDC(), pad1.GetWw() * pad1.GetWNDC(), TR) print ">>> %6s: %8.1f %8.3f %8.1f %8.1f %8.3f %8.1f %10.3f" % ( 'pad2', pad2.GetWh(), pad2.GetHNDC(), pad2.GetWh() * pad2.GetHNDC(), pad2.GetWw(), pad2.GetWNDC(), pad2.GetWw() * pad2.GetWNDC(), BR) #scale = 1.0 #scale = 1./ratio #scale = (1.-ratio)/ratio #scale = (1.-ratio)/ratio if canvas.GetWh()<canvas.GetWw() else ratio/(1.-ratio) #scale = TR/BR scale = Tm / Bm #scale = float(H)/W if W>H else 1 # float(W)/H oscale = 1. / scale tsize = 0.05 bsize = tsize * scale toffset = 1.2 boffset = toffset * oscale #boffset = 1.0+(toffset-1)*oscale print ">>> 1/r=%.4f, (1-r)/r=%.4f, HNDC1/HNDC2=%.4f, WNDC1/WNDC2=%.4f, TR/BR=%.4f, TM/BM=%.4f, Tm/Bm=%.4f" % ( 1. / ratio, (1. - ratio) / ratio, pad1.GetHNDC() / pad2.GetHNDC(), pad1.GetWNDC() / pad2.GetWNDC(), TR / BR, TM / BM, Tm / Bm) print ">>> tsize=%.4f, bsize=%.4f, scale=%.4f" % (tsize, bsize, scale) print ">>> toffset=%.4f, boffset=%.4f, scale=%.4f" % (toffset, boffset, oscale) # TOP HIST canvas.cd(1) thist = TH1D('top', 'top', 10, 0, 100) thist.GetXaxis().SetTitle("X title") thist.GetYaxis().SetTitle("Y title") print ">>> thist.GetXaxis().GetTitleOffset()=%.4f" % ( thist.GetXaxis().GetTitleOffset()) print ">>> thist.GetYaxis().GetTitleOffset()=%.4f" % ( thist.GetYaxis().GetTitleOffset()) thist.GetXaxis().SetTitleSize(tsize) thist.GetYaxis().SetTitleSize(tsize) #thist.GetXaxis().SetTitleOffset(toffset) thist.GetYaxis().SetTitleOffset(toffset) thist.GetXaxis().SetLabelSize(tsize) thist.GetYaxis().SetLabelSize(tsize) thist.Draw() # BOTTOM HIST canvas.cd(2) bhist = thist.Clone('bottom') bhist.SetTitle('bottom') bhist.GetXaxis().SetTitleSize(bsize) bhist.GetYaxis().SetTitleSize(bsize) #thist.GetXaxis().SetTitleOffset(boffset) bhist.GetYaxis().SetTitleOffset(boffset) bhist.GetXaxis().SetLabelSize(bsize) bhist.GetYaxis().SetLabelSize(bsize) bhist.Draw() # FINISH canvas.SaveAs(fname) canvas.Close() print ">>> "
def compare(fnames, variables, **kwargs): # SETTING tnames = kwargs.get('tree', []) entries = kwargs.get('entries', []) # entries of files outdir = kwargs.get('outdir', "compare") tag = kwargs.get('tag', "") cut = kwargs.get('cut', "") norm = kwargs.get('norm', False) ensuredir(outdir) if isinstance(tnames, str): tnames = [tnames] * len(fnames) else: while len(tnames) < len(fnames): tnames.append(tnames[-1]) if norm: tag += "_norm" # normalize each histogram # GET FILES & TREES files = [] trees = [] for fname, tname in zip(fnames, tnames): file = TFile.Open(fname, 'READ') tree = file.Get(tname) files.append(file) trees.append(tree) for variable in variables[:]: if not hasattr(tree, variable.name): LOG.warning( "compare: tree %s:%s does not contain branch %r! Skipping..." % (fname, tname, variable.name)) variables.remove(variable) while len(entries) < len(trees): i = len(entries) entry = "%s %d" % (tnames[i], i + 1) entries.append(entry) # PLOT for variable in variables: fname = "%s/%s%s.png" % (outdir, variable, tag) rrange = 0.5 header = "Compare" # legend header text = "" # corner text ratio = True #and False logy = True and False grid = True #and False staterr = True #and False # add uncertainty band to first histogram lstyle = 1 # solid lines LOG.header(fname) # GET HISOGRAMS hists = [] for i, (tree, htitle) in enumerate(zip(trees, entries)): hname = "%s_%d" % (variable.filename, i) #hist = variable.gethist(hname,htitle) #dcmd = variable.drawcmd(hname) hist = variable.draw( tree, cut, name=hname, title=htitle) # create and fill hist from tree evts = hist.GetEntries() hist.SetTitle("%s (%d)" % (htitle, evts)) hists.append(hist) print ">>> %r: entries=%d, integral=%s, mean=%#.6g, s.d.=%#.6g" % ( htitle, evts, hist.Integral(), hist.GetMean(), hist.GetStdDev()) # DRAW PLOT plot = Plot(variable, hists, norm=norm) plot.draw(ratio=True, logy=logy, ratiorange=rrange, lstyle=lstyle, grid=grid, staterr=staterr) plot.drawlegend(header=header) plot.drawtext(text) plot.saveas(fname) plot.close() print
def filterJSONByRunNumberRange(jsoninname, era="", period=None, rrange=None, start=None, end=None, outdir='json', verb=0): """Split a given JSON file by start and end run number.""" outdir = ensuredir(outdir) if period: datasets = getRuns(era) start, end = getPeriodRunNumbers(period, datasets) eraname = "Run%s%s" % (era, period) elif rrange: match = range_rexp.match(rrange) if not match: raise IOERROR( "Could not find range pattern in %r. Format should be e.g. 123456-1234567" % (rrange)) start, end = int(match.group(1)), int(match.group(2)) eraname = "%s-%s" % (start, end) elif start > 0 and end > 0: eraname = "%s-%s" % (start, end) else: raise IOError( "filterJSONByRunNumberRange: Please set either period (e.g. period='BCD'), " "or the range (e.g. rrange='272007-278770'), or start and end (start=272007, end=278770)" ) jsonoutname = os.path.join( outdir, range_rexp.sub(eraname, os.path.basename(jsoninname))) print ">>> filterJSONByRunNumberRange: %r for period=%r, range=%s-%s" % ( eraname, period, start, end) # READ JSON IN with open(jsoninname, 'r') as jsonin: data = json.load(jsonin) # FILTER run number range nkeep = 0 ndrop = 0 for element in sorted(data.keys()): if element.isdigit(): runnumber = int(element) if runnumber < start or runnumber > end: ndrop += 1 if verb >= 2: print ">>> dropping %s" % runnumber del data[element] else: nkeep += 1 if verb >= 2: print ">>> keeping %s" % runnumber else: print "Warning! filterJSONByRunNumberRange: element is not an integer (run number): '%s'" % element # WRITE JSON OUT with open(jsonoutname, 'w') as jsonout: data = json.dump(data, jsonout, sort_keys=True) # SUMMARY print ">>> output: %r" % (jsonoutname) print ">>> saved %s / %s run numbers" % (nkeep, nkeep + ndrop) return jsonoutname
def drawpostfit(fname, bin, procs, **kwargs): """Plot pre- and post-fit plots PostFitShapesFromWorkspace.""" print '>>>\n>>> drawpostfit("%s","%s")' % (fname, bin) outdir = kwargs.get('outdir', "") pname = kwargs.get('pname', "$FIT.png") # replace $FIT = 'prefit', 'postfit' ratio = kwargs.get('ratio', True) tag = kwargs.get('tag', "") xtitle = kwargs.get('xtitle', None) title = kwargs.get('title', None) text = kwargs.get('text', "") tsize = kwargs.get('tsize', 0.050) xmin = kwargs.get('xmin', None) xmax = kwargs.get('xmax', None) ymargin = kwargs.get('ymargin', 1.22) groups = kwargs.get('group', []) position = kwargs.get('pos', None) # legend position ncol = kwargs.get('ncol', None) # legend columns square = kwargs.get('square', False) era = kwargs.get('era', "") exts = kwargs.get('exts', ['pdf', 'png']) # figure extension ymax = None fits = ['prefit', 'postfit'] file = ensureTFile(fname, 'READ') if outdir: ensuredir(outdir) if era: setera(era) # DRAW PRE-/POST-FIT for fit in fits: fitdirname = "%s_%s" % (bin, fit) dir = file.Get(fitdirname) if not dir: LOG.warning('drawpostfit: Did not find dir "%s"' % (fitdirname), pre=" ") return obshist = None exphists = [] # GET HIST for proc in procs: #reversed(samples): hname = "%s/%s" % (fitdirname, proc) hist = file.Get(hname) if not hist: LOG.warning( 'drawpostfit: Could not find "%s" template in directory "%s_%s"' % (proc, bin, fit), pre=" ") continue if 'data_obs' in proc: obshist = hist hist.SetLineColor(1) ymax = hist.GetMaximum() * ymargin else: exphists.append(hist) if proc in STYLE.sample_titles: hist.SetTitle(STYLE.sample_titles[proc]) if proc in STYLE.sample_colors: hist.SetFillStyle(1001) hist.SetFillColor(STYLE.sample_colors[proc]) if len(exphists) == 0: LOG.warning( 'drawpostfit: Could not find any templates in directory "%s"' % (bin), pre=" ") continue if not obshist: LOG.warning( 'drawpostfit: Could not find a data template in directory "%s"' % (bin), pre=" ") continue for groupargs in groups: grouphists(exphists, *groupargs, replace=True) # PLOT xtitle = (xtitle or exphists[0].GetXaxis().GetTitle() ) #.replace('[GeV]','(GeV)') xmax = xmax or exphists[0].GetXaxis().GetXmax() xmin = xmin or exphists[0].GetXaxis().GetXmin() errtitle = "Pre-fit stat. + syst. unc." if fit == 'prefit' else "Post-fit unc." pname_ = repkey(pname, FIT=fit, ERA=era) rmin, rmax = (0.28, 1.52) plot = Stack(xtitle, obshist, exphists) plot.draw(xmin=xmin, xmax=xmax, ymax=ymax, square=square, ratio=ratio, rmin=rmin, rmax=rmax, staterror=True, errtitle=errtitle) plot.drawlegend(position, tsize=tsize, text=text, ncol=ncol) if title: plot.drawtext(title, bold=False) plot.saveas(pname_, outdir=outdir, ext=exts) plot.close() file.Close()
def plotinputs(fname, varprocs, observables, bins, **kwargs): """Plot histogram inputs from ROOT file for datacards, and write to ROOT file. fname: filename pattern of ROOT file varprocs: dictionary for systematic variation to list of processes, e.g. { 'Nom': ['ZTT','TTT','W','QCD','data_obs'], 'TESUp': ['ZTT','TTT'], 'TESDown': ['ZTT','TTT'] } observables: list of Variables objects bins: list of Selection objects """ #LOG.header("plotinputs") tag = kwargs.get('tag', "") pname = kwargs.get('pname', "$OBS_$BIN$TAG.png") outdir = kwargs.get('outdir', 'plots') text = kwargs.get('text', "$BIN") groups = kwargs.get('group', []) # add processes together into one histogram verbosity = kwargs.get('verb', 0) ensuredir(outdir) print ">>>\n>>> " + color(" plotting... ", 'magenta', bold=True, ul=True) for obs in observables: obsname = obs.filename ftag = tag + obs.tag fname_ = repkey(fname, OBS=obsname, TAG=ftag) file = ensureTFile(fname_, 'UPDATE') for set, procs in varprocs.iteritems( ): # loop over processes with variation if set == 'Nom': systag = "" # no systematics tag for nominal procs_ = procs[:] else: systag = '_' + set # systematics tag for variation, e.g. '_TESUp' procs_ = [ (p + systag if p in procs else p) for p in varprocs['Nom'] ] # add tag to varied processes for selection in bins: if not obs.plotfor(selection): continue obs.changecontext(selection) bin = selection.filename text_ = repkey( text, BIN=selection.title) # extra text in plot corner tdir = ensureTDirectory(file, bin, cd=True) # directory with histograms if set == 'Nom': gStyle.Write( 'style', TH1.kOverwrite ) # write current TStyle object to reproduce plots # STACKS pname_ = repkey(pname, OBS=obsname, BIN=bin, TAG=ftag + systag) # image file name wname = "stack" + systag # name in ROOT file stackinputs(tdir, obs, procs_, group=groups, save=pname_, write=wname, text=text_) # VARIATIONS if 'Down' in set: systag_ = systag.replace( 'Down', '') # e.g.'_TES' without 'Up' or 'Down' suffix pname_ = repkey(pname, OBS=obsname, BIN=bin, TAG=ftag + "_$PROC" + systag) # image file name wname = "plot_$PROC" + systag # name in ROOT file comparevars(tdir, obs, procs, systag_, save=pname_, write=wname, text=text_) file.Close()
def compare(fnames, varsets, **kwargs): # SETTING tname = kwargs.get('tree', 'Events') entries = kwargs.get('entries', []) # entries of files outdir = kwargs.get('outdir', "compare") tag = kwargs.get('tag', "") cut = kwargs.get('cut', "") norm = kwargs.get('norm', False) ensuredir(outdir) if norm: tag += "_norm" # normalize each histogram tree = TChain(tname) # GET FILES & TREES for fname in fnames: tree.Add(fname) # PLOT for varset in varsets: fname = "%s/%s%s.png" % (outdir, '-'.join(v.filename for v in varset), tag) rrange = 0.5 header = "Compare" # legend header text = "" # corner text ratio = True #and False logy = True and False grid = True #and False staterr = True #and False # add uncertainty band to first histogram lstyle = 1 # solid lines xvar = varset[0] LOG.header(fname) # GET HISOGRAMS hists = [] for i, variable in enumerate(varset): hname = "%s_%d" % (variable.filename, i) htitle = variable.name #hist = variable.gethist(hname,htitle) #dcmd = variable.drawcmd(hname) hist = variable.draw( tree, cut, name=hname, title=htitle) # create and fill hist from tree evts = hist.GetEntries() hist.SetTitle(htitle) #"%s (%d)"%(htitle,evts) hists.append(hist) print ">>> %r: entries=%d, integral=%s, mean=%#.6g, s.d.=%#.6g" % ( htitle, evts, hist.Integral(), hist.GetMean(), hist.GetStdDev()) # DRAW PLOT plot = Plot(xvar, hists, norm=norm) plot.draw(ratio=True, logy=logy, ratiorange=rrange, lstyle=lstyle, grid=grid, staterr=staterr) plot.drawlegend(header=header, latex=False) plot.drawtext(text) plot.saveas(fname) plot.close() print