8 ROOT.gROOT.SetBatch(
True)
9 ROOT.PyConfig.IgnoreCommandLineOptions =
True
15 "CMSSW_6_2_0_SLHC15": {
"UPG2019withGEM":
"DES19_62_V8",
"UPG2023SHNoTaper":
"DES23_62_V1"},
16 "CMSSW_6_2_0_SLHC17": {
"UPG2019withGEM":
"DES19_62_V8",
"UPG2023SHNoTaper":
"DES23_62_V1"},
17 "CMSSW_6_2_0_SLHC20": {
"UPG2019withGEM":
"DES19_62_V8",
"UPG2023SHNoTaper":
"DES23_62_V1"},
18 "CMSSW_7_0_0_AlcaCSA14": {
"default":
"POSTLS170_V5_AlcaCSA14",
"fullsim_50ns":
"POSTLS170_V6_AlcaCSA14"},
19 "CMSSW_7_0_7_pmx": {
"default":
"PLS170_V7AN1",
"fullsim_50ns":
"PLS170_V6AN1"},
20 "CMSSW_7_0_9_patch3": {
"default":
"PLS170_V7AN2",
"fullsim_50ns":
"PLS170_V6AN2"},
21 "CMSSW_7_0_9_patch3_Premix": {
"default":
"PLS170_V7AN2",
"fullsim_50ns":
"PLS170_V6AN2"},
22 "CMSSW_7_1_0": {
"default":
"POSTLS171_V15",
"fullsim_50ns":
"POSTLS171_V16"},
23 "CMSSW_7_1_9": {
"default":
"POSTLS171_V17",
"fullsim_50ns":
"POSTLS171_V18"},
24 "CMSSW_7_1_9_patch2": {
"default":
"POSTLS171_V17",
"fullsim_50ns":
"POSTLS171_V18"},
25 "CMSSW_7_1_10_patch2": {
"default":
"MCRUN2_71_V1",
"fullsim_50ns":
"MCRUN2_71_V0"},
26 "CMSSW_7_2_0_pre5": {
"default":
"POSTLS172_V3",
"fullsim_50ns":
"POSTLS172_V4"},
27 "CMSSW_7_2_0_pre7": {
"default":
"PRE_LS172_V11",
"fullsim_50ns":
"PRE_LS172_V12"},
28 "CMSSW_7_2_0_pre8": {
"default":
"PRE_LS172_V15",
"fullsim_50ns":
"PRE_LS172_V16"},
29 "CMSSW_7_2_0": {
"default":
"PRE_LS172_V15",
"fullsim_50ns":
"PRE_LS172_V16"},
30 "CMSSW_7_2_0_PHYS14": {
"default":
"PHYS14_25_V1_Phys14"},
31 "CMSSW_7_2_2_patch1": {
"default":
"MCRUN2_72_V1",
"fullsim_50ns":
"MCRUN2_72_V0"},
32 "CMSSW_7_2_2_patch1_Fall14DR": {
"default":
"MCRUN2_72_V3_71XGENSIM"},
34 "CMSSW_7_3_0_pre1": {
"default":
"PRE_LS172_V15",
"fullsim_50ns":
"PRE_LS172_V16"},
36 "CMSSW_7_3_0_pre2": {
"default":
"MCRUN2_73_V1",
"fullsim_50ns":
"MCRUN2_73_V0"},
37 "CMSSW_7_3_0_pre3": {
"default":
"MCRUN2_73_V5",
"fullsim_50ns":
"MCRUN2_73_V4"},
38 "CMSSW_7_3_0": {
"default":
"MCRUN2_73_V7",
"fullsim_50ns":
"MCRUN2_73_V6"},
39 "CMSSW_7_3_0_71XGENSIM": {
"default":
"MCRUN2_73_V7_71XGENSIM"},
40 "CMSSW_7_3_0_71XGENSIM_FIXGT": {
"default":
"MCRUN2_73_V9_71XGENSIM_FIXGT"},
41 "CMSSW_7_3_1_patch1": {
"default":
"MCRUN2_73_V9",
"fastsim":
"MCRUN2_73_V7"},
42 "CMSSW_7_3_1_patch1_GenSim_7113": {
"default":
"MCRUN2_73_V9_GenSim_7113"},
43 "CMSSW_7_3_3": {
"default":
"MCRUN2_73_V11",
"fullsim_50ns":
"MCRUN2_73_V10",
"fastsim":
"MCRUN2_73_V13"},
44 "CMSSW_7_4_0_pre1": {
"default":
"MCRUN2_73_V5",
"fullsim_50ns":
"MCRUN2_73_V4"},
45 "CMSSW_7_4_0_pre2": {
"default":
"MCRUN2_73_V7",
"fullsim_50ns":
"MCRUN2_73_V6"},
46 "CMSSW_7_4_0_pre2_73XGENSIM": {
"default":
"MCRUN2_73_V7_73XGENSIM_Pythia6",
"fullsim_50ns":
"MCRUN2_73_V6_73XGENSIM_Pythia6"},
47 "CMSSW_7_4_0_pre5": {
"default":
"MCRUN2_73_V7",
"fullsim_50ns":
"MCRUN2_73_V6"},
48 "CMSSW_7_4_0_pre5_BS": {
"default":
"MCRUN2_73_V9_postLS1beamspot",
"fullsim_50ns":
"MCRUN2_73_V8_postLS1beamspot"},
49 "CMSSW_7_4_0_pre6": {
"default":
"MCRUN2_74_V1",
"fullsim_50ns":
"MCRUN2_74_V0"},
50 "CMSSW_7_4_0_pre6_pmx": {
"default":
"MCRUN2_74_V1",
"fullsim_50ns":
"MCRUN2_74_V0"},
51 "CMSSW_7_4_0_pre8": {
"default":
"MCRUN2_74_V7",
"fullsim_25ns":
"MCRUN2_74_V5_AsympMinGT",
"fullsim_50ns":
"MCRUN2_74_V4_StartupMinGT"},
52 "CMSSW_7_4_0_pre8_25ns_asymptotic": {
"default":
"MCRUN2_74_V7"},
53 "CMSSW_7_4_0_pre8_50ns_startup": {
"default":
"MCRUN2_74_V6"},
54 "CMSSW_7_4_0_pre8_50ns_asympref": {
"default":
"MCRUN2_74_V5A_AsympMinGT"},
55 "CMSSW_7_4_0_pre8_50ns_asymptotic": {
"default":
"MCRUN2_74_V7A_AsympGT"},
56 "CMSSW_7_4_0_pre8_ROOT6": {
"default":
"MCRUN2_74_V7"},
57 "CMSSW_7_4_0_pre8_pmx": {
"default":
"MCRUN2_74_V7",
"fullsim_50ns":
"MCRUN2_74_V6"},
58 "CMSSW_7_4_0_pre8_pmx_v2": {
"default":
"MCRUN2_74_V7_gs_pre7",
"fullsim_50ns":
"MCRUN2_74_V6_gs_pre7"},
61 _releasePostfixes = [
"_AlcaCSA14",
"_PHYS14",
"_TEST",
"_pmx_v2",
"_pmx",
"_Fall14DR",
"_71XGENSIM_FIXGT",
"_71XGENSIM",
"_73XGENSIM",
"_BS",
"_GenSim_7113",
62 "_25ns_asymptotic",
"_50ns_startup",
"_50ns_asympref",
"_50ns_asymptotic"]
64 for pf
in _releasePostfixes:
66 return release.replace(pf,
"")
74 sample -- Sample object
75 release -- CMSSW release string
77 if not release
in _globalTags:
78 print "Release %s not found from globaltag map in validation.py" % release
80 gtmap = _globalTags[release]
81 if sample.hasOverrideGlobalTag():
82 ogt = sample.overrideGlobalTag()
84 gtmap = _globalTags[ogt[release]]
86 if sample.hasScenario():
87 return gtmap[sample.scenario()]
88 if sample.pileupType() ==
"50ns":
89 return gtmap.get(
"fullsim_50ns", gtmap[
"default"])
90 if sample.pileupType() ==
"25ns":
91 return gtmap.get(
"fullsim_25ns", gtmap[
"default"])
93 return gtmap.get(
"fastsim", gtmap[
"default"])
94 return gtmap[
"default"]
98 "6_2_X":
"https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_6_2_x/",
99 "7_0_X":
"https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_0_x/",
100 "7_1_X":
"https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_1_x/",
101 "7_2_X":
"https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_2_x/",
102 "7_3_X":
"https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_3_x/",
103 "7_4_X":
"https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_4_x/",
107 """Get RelVal download URL for a given release."""
108 version_re = re.compile(
"CMSSW_(?P<X>\d+)_(?P<Y>\d+)")
109 m = version_re.search(release)
111 raise Exception(
"Regex %s does not match to release version %s" % (version_re.pattern, release))
112 version =
"%s_%s_X" % (m.group(
"X"), m.group(
"Y"))
113 if not version
in _relvalUrls:
114 print "No RelVal URL for version %s, please update _relvalUrls" % version
116 return _relvalUrls[version]
119 """Represents a RelVal sample."""
120 def __init__(self, sample, append=None, midfix=None, putype=None,
121 fastsim=
False, fastsimCorrespondingFullsimPileup=
None,
122 version=
"v1", scenario=
None, overrideGlobalTag=
None):
126 sample -- String for name of the sample
129 append -- String for a variable name within the DWM file names, to be directly appended to sample name (e.g. "HS"; default None)
130 midfix -- String for a variable name within the DQM file names, to be appended after underscore to "sample name+append" (e.g. "13", "UP15"; default None)
131 putype -- String for pileup type (e.g. "25ns"/"50ns" for FullSim, "AVE20" for FastSim; default None)
132 fastsim -- Bool indicating the FastSim status (default False)
133 fastsimCorrespondingFullSimPileup -- String indicating what is the FullSim pileup sample corresponding this FastSim sample. Must be set if fastsim=True and putype!=None (default None)
134 version -- String for dataset/DQM file version (default "v1")
135 scenario -- Geometry scenario for upgrade samples (default None)
136 overrideGlobalTag -- GlobalTag obtained from release information (in the form of {"release": "actualRelease"}; default None)
149 raise Exception(
"If fastsim=True and putype!=None, also fastsimCorrespondingFullsimPileup must be != None")
152 """Get the sample name"""
156 """Get the sample name"""
160 """Return True if sample has pileup"""
161 return self.
_putype is not None
164 """Return "PU"/"noPU" corresponding the pileup status"""
171 """Return the pileup type"""
172 if isinstance(self.
_putype, dict):
173 return self._putype.get(release, self.
_putype[
"default"])
179 return self._version.get(release, self.
_version[
"default"])
196 """Return True for FastSim sample"""
200 """Return True for FullSim sample"""
206 def dirname(self, newRepository, newRelease, newSelection):
207 """Return the output directory name
210 newRepository -- String for base directory for output files
211 newRelease -- String for CMSSW release
212 newSelection -- String for histogram selection
217 return "{newRepository}/{newRelease}/{newSelection}{pileup}/{sample}".
format(
218 newRepository=newRepository, newRelease=newRelease, newSelection=newSelection,
219 pileup=pileup, sample=sample)
222 """Return the DQM file name
225 newRelease -- String for CMSSW release
248 fname =
'DQM_V0001_R000000001__{sample}{midfix}__{newrelease}-{pileup}{globaltag}{scenario}{fastsim}-{version}__DQMIO.root'.
format(
250 pileup=pileup, globaltag=globalTag, scenario=scenario, fastsim=fastsim,
251 version=self.
version(newRelease)
257 """Return the dataset pattern
260 newRelease -- String for CMSSW release
268 fastsim =
"_FastSim-"
273 return "{sample}/{newrelease}-{pileup}{globaltag}{fastsim}{version}/GEN-SIM-{digi}RECO".
format(
274 sample=self.
_sample, newrelease=newRelease,
275 pileup=pileup, globaltag=globalTag, fastsim=fastsim, digi=digi,
276 version=self.
version(newRelease)
280 """Base class for Tracking/Vertex validation."""
281 def __init__(self, fullsimSamples, fastsimSamples, newRelease, newFileModifier=None, selectionName=""):
285 fullsimSamples -- List of Sample objects for FullSim samples (may be empty)
286 fastsimSamples -- List of Sample objects for FastSim samples (may be empty)
287 newRelease -- CMSSW release to be validated
288 newFileModifier -- If given, a function to modify the names of the new files (function takes a string and returns a string)
289 selectionName -- If given, use this string as the selection name (appended to GlobalTag for directory names)
294 print >>sys.stderr,
'Error: CMSSW environment variables are not available.'
295 print >>sys.stderr,
' Please run cmsenv'
312 """Download DQM files. Requires grid certificate and asks your password for it."""
316 filenames =
filter(
lambda f:
not os.path.exists(f), filenames)
317 if len(filenames) == 0:
318 print "All files already downloaded"
322 urls = [relvalUrl+f
for f
in filenames]
323 certfile = os.path.join(os.environ[
"HOME"],
".globus",
"usercert.pem")
324 if not os.path.exists(certfile):
325 print "Certificate file {certfile} does not exist, unable to download RelVal files from {url}".
format(certfile=certfile, url=relvalUrl)
327 keyfile = os.path.join(os.environ[
"HOME"],
".globus",
"userkey.pem")
328 if not os.path.exists(certfile):
329 print "Private key file {keyfile} does not exist, unable to download RelVal files from {url}".
format(keyfile=keyfile, url=relvalUrl)
332 cmd = [
"curl",
"--cert-type",
"PEM",
"--cert", certfile,
"--key", keyfile,
"-k"]
334 cmd.extend([
"-O", u])
335 print "Downloading %d files from RelVal URL %s:" % (len(filenames), relvalUrl)
336 print " "+
"\n ".
join(filenames)
337 print "Please provide your private key pass phrase when curl asks it"
338 ret = subprocess.call(cmd)
340 print "Downloading failed with exit code %d" % ret
346 p = subprocess.Popen([
"file", f], stdout=subprocess.PIPE)
347 stdout = p.communicate()[0]
348 if p.returncode != 0:
349 print "file command failed with exit code %d" % p.returncode
351 if not "ROOT" in stdout:
352 print "File {f} is not ROOT, please check the correct version, GobalTag etc. from {url}".
format(f=f, url=relvalUrl)
354 if os.path.exists(f):
359 def doPlots(self, algos, qualities, refRelease, refRepository, newRepository, plotter, plotterDrawArgs={}):
360 """Create validation plots.
363 algos -- List of strings for algoritms
364 qualities -- List of strings for quality flags (can be None)
365 refRelease -- String for reference CMSSW release
366 refRepository -- String for directory where reference root files are
367 newRepository -- String for directory whete to put new files
368 plotter -- plotting.Plotter object that does the plotting
371 plotterDrawArgs -- Dictionary for additional arguments to Plotter.draw() (default: {})
379 if qualities
is None:
394 correspondingFull =
None
396 if fast.name() != full.name():
399 if not full.hasPileup():
401 if fast.fastsimCorrespondingFullsimPileup() != full.pileupType():
407 if correspondingFull
is None:
408 correspondingFull = full
410 raise Exception(
"Got multiple compatible FullSim samples for FastSim sample %s %s" % (fast.name(), fast.pileup()))
411 if correspondingFull
is None:
412 raise Exception(
"Did not find compatible FullSim sample for FastSim sample %s %s" % (fast.name(), fast.pileup()))
418 """Do the real plotting work for a given algorithm, quality flag, and sample."""
425 if sample.hasScenario():
426 tmp +=
"_"+sample.scenario()
427 tmp +=
"_"+sample.pileup()
429 refSelection = refGlobalTag+tmp
430 newSelection = newGlobalTag+tmp
431 if sample.hasPileup()
and not sample.fastsim():
432 refSelection +=
"_"+sample.pileupType(self.
_refRelease)
433 newSelection +=
"_"+sample.pileupType(self.
_newRelease)
437 if not os.path.exists(harvestedfile):
438 print "Harvested file %s does not exist!" % harvestedfile
441 valname =
"val.{sample}.root".
format(sample=sample.name())
447 tmp.extend([refSelection, sample.name()])
448 refdir = os.path.join(*tmp)
454 tmp.extend([newSelection, sample.name()])
455 newdir = os.path.join(*tmp)
458 refValFilePath = os.path.join(refdir, valname)
459 if not os.path.exists(refValFilePath):
460 print "Reference file %s not found" % refValFilePath
461 if not plotting.missingOk:
462 print "If this is acceptable, please set 'plotting.missingOk=True'"
467 refValFile = ROOT.TFile.Open(refValFilePath)
474 print "Comparing ref and new {sim} {sample} {algo} {quality}".
format(
475 sim=
"FullSim" if not sample.fastsim()
else "FastSim",
476 sample=sample.name(), algo=algo, quality=quality)
477 self._plotter.create([refValFile, newValFile], [
485 if refValFile
is not None:
489 print "Moving plots and %s to %s" % (valname, newdir)
490 if not os.path.exists(newdir):
493 shutil.move(f, os.path.join(newdir, f))
496 """Do the real plotting work for FastSim vs. FullSim for a given algorithm, quality flag, and sample."""
503 fastSelection = fastGlobalTag+
"_"+fastSample.pileup()+tmp
504 fullSelection = fullGlobalTag+
"_"+fullSample.pileup()+tmp
505 if fullSample.hasPileup():
506 fullSelection +=
"_"+fullSample.pileupType(self.
_newRelease)
514 valname =
"val.{sample}.root".
format(sample=fastSample.name())
515 fastValFilePath = os.path.join(fastdir, valname)
516 if not os.path.exists(fastValFilePath):
517 print "FastSim file %s not found" % fastValFilePath
518 fullValFilePath = os.path.join(fulldir, valname)
519 if not os.path.exists(fullValFilePath):
520 print "FullSim file %s not found" % fullValFilePath
522 fastValFile = ROOT.TFile.Open(fastValFilePath)
523 fullValFile = ROOT.TFile.Open(fullValFilePath)
526 print "Comparing FullSim and FastSim {sample} {algo} {quality}".
format(
527 sample=fastSample.name(), algo=algo, quality=quality)
528 self._plotter.create([fullValFile, fastValFile], [
539 print "Moving plots to %s" % (newdir)
540 if not os.path.exists(newdir):
543 shutil.move(f, os.path.join(newdir, f))
546 """Do the real plotting work for Old vs. New pileup scenarios for a given algorithm, quality flag, and sample."""
549 refGlobalTag = newGlobalTag +
"_OldPU"
553 refSelection = refGlobalTag+
"_"+sample.pileup()+tmp+
"_"+sample.pileupType(self.
_newRelease)
554 newSelection = newGlobalTag+
"_"+sample.pileup()+tmp+
"_"+sample.pileupType(self.
_newRelease)
562 valname =
"val.{sample}.root".
format(sample=sample.name())
563 refValFilePath = os.path.join(refdir, valname)
564 if not os.path.exists(refValFilePath):
565 print "Ref pileup file %s not found" % refValFilePath
566 newValFilePath = os.path.join(newdir, valname)
567 if not os.path.exists(newValFilePath):
568 print "New pileup file %s not found" % newValFilePath
570 refValFile = ROOT.TFile.Open(refValFilePath)
571 newValFile = ROOT.TFile.Open(newValFilePath)
574 print "Comparing Old and New pileup {sample} {algo} {quality}".
format(
575 sample=sample.name(), algo=algo, quality=quality)
576 self._plotter.create([refValFile, newValFile], [
587 print "Moving plots to %s" % (resdir)
588 if not os.path.exists(resdir):
591 shutil.move(f, os.path.join(resdir, f))
594 """Copy a subdirectory from oldfile to newfile.
597 oldfile -- String for source TFile
598 newfile -- String for destination TFile
599 basenames -- List of strings for base directories, first existing one is picked
600 dirname -- String for directory name under the base directory
602 oldf = ROOT.TFile.Open(oldfile)
605 for basename
in basenames:
606 dirold = oldf.GetDirectory(basename)
610 raise Exception(
"Did not find any of %s directories from file %s" % (
",".
join(basenames, oldfile)))
612 d = dirold.Get(dirname)
614 raise Exception(
"Did not find directory %s under %s" % (dirname, dirold.GetPath()))
617 newf = ROOT.TFile.Open(newfile,
"RECREATE")
619 for d
in basenames[0].
split(
"/"):
620 dirnew = dirnew.mkdir(d)
622 dirnew = dirnew.mkdir(dirname)
629 """Copy recursively objects from src TDirectory to dst TDirectory."""
630 keys = src.GetListOfKeys()
632 classname = key.GetClassName()
633 cl = ROOT.TClass.GetClass(classname)
636 if cl.InheritsFrom(
"TDirectory"):
637 src2 = src.GetDirectory(key.GetName())
638 dst2 = dst.mkdir(key.GetName())
640 elif cl.InheritsFrom(
"TTree"):
643 newt = t.CloneTree(-1,
"fast")
658 def doPlots(self, algos, qualities, plotter, algoDirMap=None, newdirFunc=None, plotterDrawArgs={}):
664 if qualities
is None:
676 if not os.path.exists(f):
677 print "File %s not found" % f
679 openFiles.append(ROOT.TFile.Open(f))
702 self._plotter.create(openFiles, self.
_labels, subdir=subdir)
710 newdir = os.path.join(newdir, self.
_newdirFunc(algo, quality))
712 print "Moving plots to %s" % newdir
713 if not os.path.exists(newdir):
716 shutil.move(f, os.path.join(newdir, f))
_fastsimCorrespondingFullsimPileup
def fastsimCorrespondingFullsimPileup
static std::string join(char **cmd)