test
CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
validation.py
Go to the documentation of this file.
1 import os
2 import re
3 import sys
4 import shutil
5 import subprocess
6 
7 import ROOT
8 ROOT.gROOT.SetBatch(True)
9 ROOT.PyConfig.IgnoreCommandLineOptions = True
10 
11 import plotting
12 import html
13 
14 # Mapping from releases to GlobalTags
15 _globalTags = {
16  "CMSSW_6_2_0": {"default": "PRE_ST62_V8"},
17  "CMSSW_6_2_0_SLHC15": {"UPG2019withGEM": "DES19_62_V8", "UPG2023SHNoTaper": "DES23_62_V1"},
18  "CMSSW_6_2_0_SLHC17": {"UPG2019withGEM": "DES19_62_V8", "UPG2023SHNoTaper": "DES23_62_V1"},
19  "CMSSW_6_2_0_SLHC20": {"UPG2019withGEM": "DES19_62_V8", "UPG2023SHNoTaper": "DES23_62_V1"},
20  "CMSSW_6_2_0_SLHC27_phase1": {"default": "DES17_62_V8_UPG17"},
21  "CMSSW_7_0_0": {"default": "POSTLS170_V3", "fullsim_50ns": "POSTLS170_V4"},
22  "CMSSW_7_0_0_AlcaCSA14": {"default": "POSTLS170_V5_AlcaCSA14", "fullsim_50ns": "POSTLS170_V6_AlcaCSA14"},
23  "CMSSW_7_0_7_pmx": {"default": "PLS170_V7AN1", "fullsim_50ns": "PLS170_V6AN1"},
24  "CMSSW_7_0_9_patch3": {"default": "PLS170_V7AN2", "fullsim_50ns": "PLS170_V6AN2"},
25  "CMSSW_7_0_9_patch3_Premix": {"default": "PLS170_V7AN2", "fullsim_50ns": "PLS170_V6AN2"},
26  "CMSSW_7_1_0": {"default": "POSTLS171_V15", "fullsim_50ns": "POSTLS171_V16"},
27  "CMSSW_7_1_9": {"default": "POSTLS171_V17", "fullsim_50ns": "POSTLS171_V18"},
28  "CMSSW_7_1_9_patch2": {"default": "POSTLS171_V17", "fullsim_50ns": "POSTLS171_V18"},
29  "CMSSW_7_1_10_patch2": {"default": "MCRUN2_71_V1", "fullsim_50ns": "MCRUN2_71_V0"},
30  "CMSSW_7_2_0_pre5": {"default": "POSTLS172_V3", "fullsim_50ns": "POSTLS172_V4"},
31  "CMSSW_7_2_0_pre7": {"default": "PRE_LS172_V11", "fullsim_50ns": "PRE_LS172_V12"},
32  "CMSSW_7_2_0_pre8": {"default": "PRE_LS172_V15", "fullsim_50ns": "PRE_LS172_V16"},
33  "CMSSW_7_2_0": {"default": "PRE_LS172_V15", "fullsim_50ns": "PRE_LS172_V16"},
34  "CMSSW_7_2_0_PHYS14": {"default": "PHYS14_25_V1_Phys14"},
35  "CMSSW_7_2_2_patch1": {"default": "MCRUN2_72_V1", "fullsim_50ns": "MCRUN2_72_V0"},
36  "CMSSW_7_2_2_patch1_Fall14DR": {"default": "MCRUN2_72_V3_71XGENSIM"},
37 # "CMSSW_7_3_0_pre1": {"default": "PRE_LS172_V15", "fullsim_25ns": "PRE_LS172_V15_OldPU", "fullsim_50ns": "PRE_LS172_V16_OldPU"},
38  "CMSSW_7_3_0_pre1": {"default": "PRE_LS172_V15", "fullsim_50ns": "PRE_LS172_V16"},
39 # "CMSSW_7_3_0_pre2": {"default": "MCRUN2_73_V1_OldPU", "fullsim_50ns": "MCRUN2_73_V0_OldPU"},
40  "CMSSW_7_3_0_pre2": {"default": "MCRUN2_73_V1", "fullsim_50ns": "MCRUN2_73_V0"},
41  "CMSSW_7_3_0_pre3": {"default": "MCRUN2_73_V5", "fullsim_50ns": "MCRUN2_73_V4"},
42  "CMSSW_7_3_0": {"default": "MCRUN2_73_V7", "fullsim_50ns": "MCRUN2_73_V6"},
43  "CMSSW_7_3_0_71XGENSIM": {"default": "MCRUN2_73_V7_71XGENSIM"},
44  "CMSSW_7_3_0_71XGENSIM_FIXGT": {"default": "MCRUN2_73_V9_71XGENSIM_FIXGT"},
45  "CMSSW_7_3_1_patch1": {"default": "MCRUN2_73_V9", "fastsim": "MCRUN2_73_V7"},
46  "CMSSW_7_3_1_patch1_GenSim_7113": {"default": "MCRUN2_73_V9_GenSim_7113"},
47  "CMSSW_7_3_3": {"default": "MCRUN2_73_V11", "fullsim_50ns": "MCRUN2_73_V10", "fastsim": "MCRUN2_73_V13"},
48  "CMSSW_7_4_0_pre1": {"default": "MCRUN2_73_V5", "fullsim_50ns": "MCRUN2_73_V4"},
49  "CMSSW_7_4_0_pre2": {"default": "MCRUN2_73_V7", "fullsim_50ns": "MCRUN2_73_V6"},
50  "CMSSW_7_4_0_pre2_73XGENSIM": {"default": "MCRUN2_73_V7_73XGENSIM_Pythia6", "fullsim_50ns": "MCRUN2_73_V6_73XGENSIM_Pythia6"},
51  "CMSSW_7_4_0_pre5": {"default": "MCRUN2_73_V7", "fullsim_50ns": "MCRUN2_73_V6"},
52  "CMSSW_7_4_0_pre5_BS": {"default": "MCRUN2_73_V9_postLS1beamspot", "fullsim_50ns": "MCRUN2_73_V8_postLS1beamspot"},
53  "CMSSW_7_4_0_pre6": {"default": "MCRUN2_74_V1", "fullsim_50ns": "MCRUN2_74_V0"},
54  "CMSSW_7_4_0_pre8": {"default": "MCRUN2_74_V7", "fullsim_25ns": "MCRUN2_74_V5_AsympMinGT", "fullsim_50ns": "MCRUN2_74_V4_StartupMinGT"},
55  "CMSSW_7_4_0_pre8_minimal": {"default": "MCRUN2_74_V5_MinGT", "fullsim_25ns": "MCRUN2_74_V5_AsympMinGT", "fullsim_50ns": "MCRUN2_74_V4_StartupMinGT"},
56  "CMSSW_7_4_0_pre8_25ns_asymptotic": {"default": "MCRUN2_74_V7"},
57  "CMSSW_7_4_0_pre8_50ns_startup": {"default": "MCRUN2_74_V6"},
58  "CMSSW_7_4_0_pre8_50ns_asympref": {"default": "MCRUN2_74_V5A_AsympMinGT"}, # for reference of 50ns asymptotic
59  "CMSSW_7_4_0_pre8_50ns_asymptotic": {"default": "MCRUN2_74_V7A_AsympGT"},
60  "CMSSW_7_4_0_pre8_ROOT6": {"default": "MCRUN2_74_V7"},
61  "CMSSW_7_4_0_pre8_pmx": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
62  "CMSSW_7_4_0_pre8_pmx_v2": {"default": "MCRUN2_74_V7_gs_pre7", "fullsim_50ns": "MCRUN2_74_V6_gs_pre7"},
63  "CMSSW_7_4_0_pre8_pmx_v3": {"default": "MCRUN2_74_V7_bis", "fullsim_50ns": "MCRUN2_74_V6_bis"},
64  "CMSSW_7_4_0_pre9": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
65  "CMSSW_7_4_0_pre9_ROOT6": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
66  "CMSSW_7_4_0_pre9_extended": {"default": "MCRUN2_74_V7_extended"},
67  "CMSSW_7_4_0": {"default": "MCRUN2_74_V7_gensim_740pre7", "fullsim_50ns": "MCRUN2_74_V6_gensim_740pre7", "fastsim": "MCRUN2_74_V7"},
68  "CMSSW_7_4_0_71XGENSIM": {"default": "MCRUN2_74_V7_GENSIM_7_1_15", "fullsim_50ns": "MCRUN2_74_V6_GENSIM_7_1_15"},
69  "CMSSW_7_4_0_71XGENSIM_PU": {"default": "MCRUN2_74_V7_gs7115_puProd", "fullsim_50ns": "MCRUN2_74_V6_gs7115_puProd"},
70  "CMSSW_7_4_0_71XGENSIM_PXworst": {"default": "MCRUN2_74_V7C_pxWorst_gs7115", "fullsim_50ns": "MCRUN2_74_V6A_pxWorst_gs7115"},
71  "CMSSW_7_4_0_71XGENSIM_PXbest": {"default": "MCRUN2_74_V7D_pxBest_gs7115", "fullsim_50ns": "MCRUN2_74_V6B_pxBest_gs7115"},
72  "CMSSW_7_4_0_pmx": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
73  "CMSSW_7_4_1": {"default": "MCRUN2_74_V9_gensim_740pre7", "fullsim_50ns": "MCRUN2_74_V8_gensim_740pre7", "fastsim": "MCRUN2_74_V9"},
74  "CMSSW_7_4_1_71XGENSIM": {"default": "MCRUN2_74_V9_gensim71X", "fullsim_50ns": "MCRUN2_74_V8_gensim71X"},
75  "CMSSW_7_4_1_extended": {"default": "MCRUN2_74_V9_extended"},
76  "CMSSW_7_4_3": {"default": "MCRUN2_74_V9", "fullsim_50ns": "MCRUN2_74_V8", "fastsim": "MCRUN2_74_V9", "fastsim_25ns": "MCRUN2_74_V9_fixMem"},
77  "CMSSW_7_4_3_extended": {"default": "MCRUN2_74_V9_ext","fastsim": "MCRUN2_74_V9_fixMem"},
78  "CMSSW_7_4_3_pmx": {"default": "MCRUN2_74_V9_ext", "fullsim_50ns": "MCRUN2_74_V8", "fastsim": "MCRUN2_74_V9_fixMem"},
79  "CMSSW_7_4_3_patch1_unsch": {"default": "MCRUN2_74_V9_unsch", "fullsim_50ns": "MCRUN2_74_V8_unsch"},
80  "CMSSW_7_4_4": {"default": "MCRUN2_74_V9_38Tbis", "fullsim_50ns": "MCRUN2_74_V8_38Tbis"},
81  "CMSSW_7_4_4_0T": {"default": "MCRUN2_740TV1_0Tv2", "fullsim_50ns": "MCRUN2_740TV0_0TV2", "fullsim_25ns": "MCRUN2_740TV1_0TV2"},
82  "CMSSW_7_4_6_patch6": {"default": "MCRUN2_74_V9_scheduled", "fullsim_50ns": "MCRUN2_74_V8_scheduled"},
83  "CMSSW_7_4_6_patch6_unsch": {"default": "MCRUN2_74_V9", "fullsim_50ns": "MCRUN2_74_V8"},
84  "CMSSW_7_4_6_patch6_noCCC": {"default": "MCRUN2_74_V9_unsch_noCCC", "fullsim_50ns": "MCRUN2_74_V8_unsch_noCCC"},
85  "CMSSW_7_4_6_patch6_noCCC_v3": {"default": "MCRUN2_74_V9_unsch_noCCC_v3", "fullsim_50ns": "MCRUN2_74_V8_unsch_noCCC_v3"},
86  "CMSSW_7_4_6_patch6_BS": {"default": "74X_mcRun2_asymptotic_realisticBS_v0_2015Jul24", "fullsim_50ns": "74X_mcRun2_startup_realisticBS_v0_2015Jul24PU", "fullsim_25ns": "74X_mcRun2_asymptotic_realisticBS_v0_2015Jul24PU"},
87  "CMSSW_7_4_8_patch1_MT": {"default": "MCRUN2_74_V11_mulTrh", "fullsim_50ns": "MCRUN2_74_V10_mulTrh",},
88  "CMSSW_7_4_12": {"default": "74X_mcRun2_asymptotic_v2", "fullsim_25ns": "74X_mcRun2_asymptotic_v2_v2", "fullsim_50ns": "74X_mcRun2_startup_v2_v2"},
89  "CMSSW_7_5_0_pre1": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
90  "CMSSW_7_5_0_pre2": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
91  "CMSSW_7_5_0_pre3": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
92  "CMSSW_7_5_0_pre4": {"default": "MCRUN2_75_V1", "fullsim_50ns": "MCRUN2_75_V0"},
93  "CMSSW_7_5_0_pre5": {"default": "MCRUN2_75_V5", "fullsim_50ns": "MCRUN2_75_V4"},
94  "CMSSW_7_5_0_pre6": {"default": "75X_mcRun2_asymptotic_v1", "fullsim_50ns": "75X_mcRun2_startup_v1"},
95  "CMSSW_7_5_0": {"default": "75X_mcRun2_asymptotic_v1", "fullsim_50ns": "75X_mcRun2_startup_v1"},
96  "CMSSW_7_5_0_71XGENSIM": {"default": "75X_mcRun2_asymptotic_v1_gs7115", "fullsim_50ns": "75X_mcRun2_startup_v1_gs7115"},
97  "CMSSW_7_5_1": {"default": "75X_mcRun2_asymptotic_v3", "fullsim_50ns": "75X_mcRun2_startup_v3"},
98  "CMSSW_7_5_1_71XGENSIM": {"default": "75X_mcRun2_asymptotic_v3_gs7118", "fullsim_50ns": "75X_mcRun2_startup_v3_gs7118"},
99  "CMSSW_7_5_2": {"default": "75X_mcRun2_asymptotic_v5", "fullsim_50ns": "75X_mcRun2_startup_v4"},
100  "CMSSW_7_6_0_pre1": {"default": "75X_mcRun2_asymptotic_v1", "fullsim_50ns": "75X_mcRun2_startup_v1"},
101  "CMSSW_7_6_0_pre2": {"default": "75X_mcRun2_asymptotic_v2", "fullsim_50ns": "75X_mcRun2_startup_v2"},
102  "CMSSW_7_6_0_pre3": {"default": "75X_mcRun2_asymptotic_v2", "fullsim_50ns": "75X_mcRun2_startup_v2"},
103  "CMSSW_7_6_0_pre4": {"default": "76X_mcRun2_asymptotic_v1", "fullsim_50ns": "76X_mcRun2_startup_v1"},
104  "CMSSW_7_6_0_pre5": {"default": "76X_mcRun2_asymptotic_v1", "fullsim_50ns": "76X_mcRun2_startup_v1"},
105  "CMSSW_7_6_0_pre6": {"default": "76X_mcRun2_asymptotic_v4", "fullsim_50ns": "76X_mcRun2_startup_v4"},
106  "CMSSW_7_6_0_pre7": {"default": "76X_mcRun2_asymptotic_v5", "fullsim_50ns": "76X_mcRun2_startup_v5", "fastsim": "76X_mcRun2_asymptotic_v5_resub"},
107  "CMSSW_7_6_0": {"default": "76X_mcRun2_asymptotic_v11", "fullsim_50ns": "76X_mcRun2_startup_v11"},
108  "CMSSW_7_6_0_71XGENSIM": {"default": "76X_mcRun2_asymptotic_v11_gs7120p2rlBS", "fullsim_50ns": "76X_mcRun2_startup_v11_gs7120p2rlBS"},
109  "CMSSW_7_6_2": {"default": "76X_mcRun2_asymptotic_v12", "fullsim_50ns": "76X_mcRun2_startup_v11"},
110  "CMSSW_7_6_3_patch2_0T": {"default": "76X_mcRun2_0T_v1_0Tv1GT"},
111  "CMSSW_8_0_0_pre1": {"default": "76X_mcRun2_asymptotic_v11", "fullsim_50ns": "76X_mcRun2_startup_v11"},
112  "CMSSW_8_0_0_pre2": {"default": "76X_mcRun2_asymptotic_v12", "fullsim_50ns": "76X_mcRun2_startup_v11"},
113  "CMSSW_8_0_0_pre2_phase1": {"default": "76X_upgrade2017_design_v7"},
114  "CMSSW_8_0_0_pre2_phase1_rereco": {"default": "76X_upgrade2017_design_v7_rereco"},
115  "CMSSW_8_0_0_pre3_phase1": {"default": "76X_upgrade2017_design_v8"},
116  "CMSSW_8_0_0_pre3_phase1_pythia8": {"default": "76X_upgrade2017_design_v8_pythia8"},
117  "CMSSW_8_0_0_pre4": {"default": "76X_mcRun2_asymptotic_v13", "fullsim_50ns": "76X_mcRun2_startup_v12"},
118  "CMSSW_8_0_0_pre4_phase1": {"default": "76X_upgrade2017_design_v8_UPG17"},
119  "CMSSW_8_0_0_pre4_phase1_13TeV": {"default": "76X_upgrade2017_design_v8_UPG17"},
120  "CMSSW_8_0_0_pre4_ecal15fb": {"default": "80X_mcRun2_asymptotic_2016EcalTune_15fb_v0_ecal15fbm1"},
121  "CMSSW_8_0_0_pre4_ecal30fb": {"default": "80X_mcRun2_asymptotic_2016EcalTune_30fb_v0_ecal30fbm1"},
122 }
123 
124 _releasePostfixes = ["_AlcaCSA14", "_PHYS14", "_TEST", "_71XGENSIM_pmx", "_pmx_v2", "_pmx_v3", "_pmx", "_Fall14DR", "_71XGENSIM_FIXGT", "_71XGENSIM_PU", "_71XGENSIM_PXbest", "_71XGENSIM_PXworst", "_71XGENSIM", "_73XGENSIM", "_BS", "_GenSim_7113", "_extended",
125  "_25ns_asymptotic", "_50ns_startup", "_50ns_asympref", "_50ns_asymptotic", "_minimal", "_0T", "_unsch", "_noCCC_v3", "_noCCC", "_MT", "_phase1_rereco", "_phase1_pythia8", "_phase1_13TeV", "_phase1", "_ecal15fb", "_ecal30fb"]
126 def _stripRelease(release):
127  for pf in _releasePostfixes:
128  if pf in release:
129  return release.replace(pf, "")
130  return release
131 
132 
133 def _getGlobalTag(sample, release):
134  """Get a GlobalTag.
135 
136  Arguments:
137  sample -- Sample object
138  release -- CMSSW release string
139  """
140  if not release in _globalTags:
141  print "Release %s not found from globaltag map in validation.py" % release
142  sys.exit(1)
143  gtmap = _globalTags[release]
144  if sample.hasOverrideGlobalTag():
145  ogt = sample.overrideGlobalTag()
146  if release in ogt:
147  gtmap = _globalTags[ogt[release]]
148  if sample.fullsim():
149  if sample.hasScenario():
150  return gtmap[sample.scenario()]
151  if sample.hasPileup():
152  puType = sample.pileupType()
153  if "50ns" in puType:
154  return gtmap.get("fullsim_50ns", gtmap["default"])
155  if "25ns" in puType:
156  return gtmap.get("fullsim_25ns", gtmap["default"])
157  if sample.fastsim():
158  if sample.hasPileup():
159  puType = sample.pileupType()
160  if "25ns" in puType:
161  return gtmap.get("fastsim_25ns", gtmap["default"])
162  return gtmap.get("fastsim", gtmap["default"])
163  return gtmap["default"]
164 
165 # Mapping from release series to RelVal download URLs
166 _relvalUrls = {
167  "6_2_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_6_2_x/",
168  "7_0_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_0_x/",
169  "7_1_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_1_x/",
170  "7_2_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_2_x/",
171  "7_3_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_3_x/",
172  "7_4_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_4_x/",
173  "7_5_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_5_x/",
174  "7_6_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_6_x/",
175  "8_0_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_8_0_x/",
176 }
177 
178 def _getRelValUrl(release):
179  """Get RelVal download URL for a given release."""
180  version_re = re.compile("CMSSW_(?P<X>\d+)_(?P<Y>\d+)")
181  m = version_re.search(release)
182  if not m:
183  raise Exception("Regex %s does not match to release version %s" % (version_re.pattern, release))
184  version = "%s_%s_X" % (m.group("X"), m.group("Y"))
185  if not version in _relvalUrls:
186  print "No RelVal URL for version %s, please update _relvalUrls" % version
187  sys.exit(1)
188  return _relvalUrls[version]
189 
190 class Sample:
191  """Represents a RelVal sample."""
192  def __init__(self, sample, append=None, midfix=None, putype=None,
193  fastsim=False, fastsimCorrespondingFullsimPileup=None,
194  version="v1", dqmVersion="0001", scenario=None, overrideGlobalTag=None):
195  """Constructor.
196 
197  Arguments:
198  sample -- String for name of the sample
199 
200  Keyword arguments
201  append -- String for a variable name within the DWM file names, to be directly appended to sample name (e.g. "HS"; default None)
202  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)
203  putype -- String for pileup type (e.g. "25ns"/"50ns" for FullSim, "AVE20" for FastSim; default None)
204  fastsim -- Bool indicating the FastSim status (default False)
205  fastsimCorrespondingFullSimPileup -- String indicating what is the FullSim pileup sample corresponding this FastSim sample. Must be set if fastsim=True and putype!=None (default None)
206  version -- String for dataset/DQM file version (default "v1")
207  scenario -- Geometry scenario for upgrade samples (default None)
208  overrideGlobalTag -- GlobalTag obtained from release information (in the form of {"release": "actualRelease"}; default None)
209  """
210  self._sample = sample
211  self._append = append
212  self._midfix = midfix
213  self._putype = putype
214  self._fastsim = fastsim
215  self._fastsimCorrespondingFullsimPileup = fastsimCorrespondingFullsimPileup
216  self._version = version
217  self._dqmVersion = dqmVersion
218  self._scenario = scenario
219  self._overrideGlobalTag = overrideGlobalTag
220 
221  if self._fastsim and self.hasPileup() and self._fastsimCorrespondingFullsimPileup is None:
223 
224  def digest(self):
225  """Return a tuple uniquely identifying the sample, to be used e.g. as a key to dict"""
226  return (self.name(), self.pileupType(), self.scenario(), self.fastsim())
227 
228  def sample(self):
229  """Get the sample name"""
230  return self._sample
231 
232  def name(self):
233  """Get the sample name"""
234  return self._sample
235 
236  def label(self):
237  return self._sample
238 
239  def hasPileup(self):
240  """Return True if sample has pileup"""
241  return self._putype is not None
242 
243  def pileup(self):
244  """Return "PU"/"noPU" corresponding the pileup status"""
245  if self.hasPileup():
246  return "PU"
247  else:
248  return "noPU"
249 
250  def pileupType(self, release=None):
251  """Return the pileup type"""
252  if isinstance(self._putype, dict):
253  return self._putype.get(release, self._putype["default"])
254  else:
255  return self._putype
256 
257  def version(self, release=None):
258  if isinstance(self._version, dict):
259  return self._version.get(release, self._version["default"])
260  else:
261  return self._version
262 
263  def hasScenario(self):
264  return self._scenario is not None
265 
266  def scenario(self):
267  return self._scenario
268 
270  return self._overrideGlobalTag is not None
271 
272  def overrideGlobalTag(self):
273  return self._overrideGlobalTag
274 
275  def fastsim(self):
276  """Return True for FastSim sample"""
277  return self._fastsim
278 
279  def fullsim(self):
280  """Return True for FullSim sample"""
281  return not self._fastsim
282 
285 
286  def dirname(self, newRepository, newRelease, newSelection):
287  """Return the output directory name
288 
289  Arguments:
290  newRepository -- String for base directory for output files
291  newRelease -- String for CMSSW release
292  newSelection -- String for histogram selection
293  """
294  pileup = ""
295  if self.hasPileup() and not self._fastsim:
296  pileup = "_"+self._putype
297  return "{newRepository}/{newRelease}/{newSelection}{pileup}/{sample}".format(
298  newRepository=newRepository, newRelease=newRelease, newSelection=newSelection,
299  pileup=pileup, sample=sample)
300 
301  def filename(self, newRelease):
302  """Return the DQM file name
303 
304  Arguments:
305  newRelease -- String for CMSSW release
306  """
307  pileup = ""
308  fastsim = ""
309  midfix = ""
310  scenario = ""
311  sample = self._sample
312  if self._append is not None:
313  midfix += self._append
314  if self._midfix is not None:
315  midfix += "_"+self._midfix
316  if self.hasPileup():
317  if self._fastsim:
318  #sample = sample.replace("RelVal", "RelValFS_")
319  # old style
320  #pileup = "PU_"
321  #midfix += "_"+self.pileupType(newRelease)
322  # new style
323  pileup = "PU"+self.pileupType(newRelease)+"_"
324  else:
325  pileup = "PU"+self.pileupType(newRelease)+"_"
326  if self._fastsim:
327  fastsim = "_FastSim"
328  if self._scenario is not None:
329  scenario = "_"+self._scenario
330 
331  globalTag = _getGlobalTag(self, newRelease)
332 
333  fname = 'DQM_V{dqmVersion}_R000000001__{sample}{midfix}__{newrelease}-{pileup}{globaltag}{scenario}{fastsim}-{version}__DQMIO.root'.format(
334  sample=sample, midfix=midfix, newrelease=_stripRelease(newRelease),
335  pileup=pileup, globaltag=globalTag, scenario=scenario, fastsim=fastsim,
336  version=self.version(newRelease), dqmVersion=self._dqmVersion
337  )
338 
339  return fname
340 
341  def datasetpattern(self, newRelease):
342  """Return the dataset pattern
343 
344  Arguments:
345  newRelease -- String for CMSSW release
346  """
347  pileup = ""
348  fastsim = ""
349  digi = ""
350  if self.hasPileup():
351  pileup = "-PU_"
352  if self._fastsim:
353  fastsim = "_FastSim-"
354  digi = "DIGI-"
355  else:
356  fastsim = "*"
357  globalTag = _getGlobalTag(self, newRelease)
358  return "{sample}/{newrelease}-{pileup}{globaltag}{fastsim}{version}/GEN-SIM-{digi}RECO".format(
359  sample=self._sample, newrelease=newRelease,
360  pileup=pileup, globaltag=globalTag, fastsim=fastsim, digi=digi,
361  version=self.version(newRelease)
362  )
363 
365  """Base class for Tracking/Vertex validation."""
366  def __init__(self, fullsimSamples, fastsimSamples, refRelease, refRepository, newRelease, newRepository, newFileModifier=None, selectionName=""):
367  """Constructor.
368 
369  Arguments:
370  fullsimSamples -- List of Sample objects for FullSim samples (may be empty)
371  fastsimSamples -- List of Sample objects for FastSim samples (may be empty)
372  refRelease -- String for reference CMSSW release (can be None for no reference release)
373  newRepository -- String for directory whete to put new files
374  newRelease -- CMSSW release to be validated
375  refRepository -- String for directory where reference root files are
376  newFileModifier -- If given, a function to modify the names of the new files (function takes a string and returns a string)
377  selectionName -- If given, use this string as the selection name (appended to GlobalTag for directory names)
378  """
379  try:
380  self._newRelease = os.environ["CMSSW_VERSION"]
381  except KeyError:
382  print >>sys.stderr, 'Error: CMSSW environment variables are not available.'
383  print >>sys.stderr, ' Please run cmsenv'
384  sys.exit()
385 
386  self._fullsimSamples = fullsimSamples
387  self._fastsimSamples = fastsimSamples
388  self._refRelease = refRelease
389  self._refRepository = refRepository
390  self._newRelease = newRelease
391  self._newBaseDir = os.path.join(newRepository, self._newRelease)
392  self._newFileModifier = newFileModifier
393  self._selectionName = selectionName
394 
395  def _getDirectoryName(self, *args, **kwargs):
396  return None
397 
398  def _getSelectionName(self, *args, **kwargs):
399  return self._selectionName
400 
401  def download(self):
402  """Download DQM files. Requires grid certificate and asks your password for it."""
403  filenames = [s.filename(self._newRelease) for s in self._fullsimSamples+self._fastsimSamples]
404  if self._newFileModifier is not None:
405  filenames = map(self._newFileModifier, filenames)
406  filenames = filter(lambda f: not os.path.exists(f), filenames)
407  if len(filenames) == 0:
408  print "All files already downloaded"
409  return
410 
411  relvalUrl = _getRelValUrl(self._newRelease)
412  urls = [relvalUrl+f for f in filenames]
413  certfile = os.path.join(os.environ["HOME"], ".globus", "usercert.pem")
414  if not os.path.exists(certfile):
415  print "Certificate file {certfile} does not exist, unable to download RelVal files from {url}".format(certfile=certfile, url=relvalUrl)
416  sys.exit(1)
417  keyfile = os.path.join(os.environ["HOME"], ".globus", "userkey.pem")
418  if not os.path.exists(certfile):
419  print "Private key file {keyfile} does not exist, unable to download RelVal files from {url}".format(keyfile=keyfile, url=relvalUrl)
420  sys.exit(1)
421 
422  cmd = ["curl", "--cert-type", "PEM", "--cert", certfile, "--key", keyfile, "-k"]
423  for u in urls:
424  cmd.extend(["-O", u])
425  print "Downloading %d files from RelVal URL %s:" % (len(filenames), relvalUrl)
426  print " "+"\n ".join(filenames)
427  print "Please provide your private key pass phrase when curl asks it"
428  ret = subprocess.call(cmd)
429  if ret != 0:
430  print "Downloading failed with exit code %d" % ret
431  sys.exit(1)
432 
433  # verify
434  allFine = True
435  for f in filenames:
436  p = subprocess.Popen(["file", f], stdout=subprocess.PIPE)
437  stdout = p.communicate()[0]
438  if p.returncode != 0:
439  print "file command failed with exit code %d" % p.returncode
440  sys.exit(1)
441  if not "ROOT" in stdout:
442  print "File {f} is not ROOT, please check the correct version, GlobalTag etc. from {url}".format(f=f, url=relvalUrl)
443  allFine = False
444  if os.path.exists(f):
445  os.remove(f)
446  if not allFine:
447  sys.exit(1)
448 
449  def createHtmlReport(self):
450  return html.HtmlReport(self._newRelease, self._newBaseDir)
451 
452  def doPlots(self, plotter, plotterDrawArgs={}, limitSubFoldersOnlyTo=None, htmlReport=html.HtmlReportDummy(), doFastVsFull=True):
453  """Create validation plots.
454 
455  Arguments:
456  plotter -- plotting.Plotter object that does the plotting
457 
458  Keyword arguments:
459  plotterDrawArgs -- Dictionary for additional arguments to Plotter.draw() (default: {})
460  limitSubFoldersOnlyTo -- If not None, should be a dictionary from string to an object. The string is the name of a PlotFolder, and the object is PlotFolder-type specific to limit the subfolders to be processed. In general case the object is a list of strings, but e.g. for track iteration plots it is a function taking the algo and quality as parameters.
461  htmlReport -- Object returned by createHtmlReport(), in case HTML report generation is desired
462  doFastVsFull -- Do FastSim vs. FullSim comparison? (default: True)
463  """
464  self._plotter = plotter
465  self._plotterDrawArgs = plotterDrawArgs
466 
467  # New vs. Ref
468  for sample in self._fullsimSamples+self._fastsimSamples:
469  # Check that the new DQM file exists
470  harvestedFile = sample.filename(self._newRelease)
471  if not os.path.exists(harvestedFile):
472  print "Harvested file %s does not exist!" % harvestedFile
473  sys.exit(1)
474 
475  plotterInstance = plotter.readDirs(harvestedFile)
476  htmlReport.beginSample(sample)
477  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
478  if plotterFolder.onlyForPileup() and not sample.hasPileup():
479  continue
480  plotFiles = self._doPlots(sample, harvestedFile, plotterFolder, dqmSubFolder, htmlReport)
481  htmlReport.addPlots(plotterFolder, dqmSubFolder, plotFiles)
482  # TODO: the pileup case is still to be migrated
483 # if s.fullsim() and s.hasPileup():
484 # self._doPlotsPileup(a, q, s)
485 
486 
487  # Fast vs. Full
488  if not doFastVsFull:
489  return
490  for fast in self._fastsimSamples:
491  correspondingFull = None
492  for full in self._fullsimSamples:
493  if fast.name() != full.name():
494  continue
495  if fast.hasPileup():
496  if not full.hasPileup():
497  continue
498  if fast.fastsimCorrespondingFullsimPileup() != full.pileupType():
499  continue
500  else:
501  if full.hasPileup():
502  continue
503 
504  if correspondingFull is None:
505  correspondingFull = full
506  else:
507  raise Exception("Got multiple compatible FullSim samples for FastSim sample %s %s" % (fast.name(), fast.pileup()))
508  if correspondingFull is None:
509  raise Exception("Did not find compatible FullSim sample for FastSim sample %s %s" % (fast.name(), fast.pileup()))
510 
511  # If we reach here, the harvestedFile must exist
512  harvestedFile = fast.filename(self._newRelease)
513  plotterInstance = plotter.readDirs(harvestedFile)
514  htmlReport.beginSample(fast, fastVsFull=True)
515  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
516  if plotterFolder.onlyForPileup() and not fast.hasPileup():
517  continue
518  plotFiles = self._doPlotsFastFull(fast, correspondingFull, plotterFolder, dqmSubFolder, htmlReport)
519  htmlReport.addPlots(plotterFolder, dqmSubFolder, plotFiles)
520 
521  def _getRefFileAndSelection(self, sample, plotterFolder, dqmSubFolder, selectionNameBase, valname):
522  if self._refRelease is None:
523  return (None, "")
524 
525  refGlobalTag = _getGlobalTag(sample, self._refRelease)
526  def _createRefSelection(selectionName):
527  sel = refGlobalTag+selectionNameBase+selectionName
528  if sample.hasPileup():
529  refPu = sample.pileupType(self._refRelease)
530  if refPu != "":
531  sel += "_"+refPu
532  return sel
533  refSelection = _createRefSelection(plotterFolder.getSelectionName(dqmSubFolder))
534 
535  # Construct reference directory name, and open reference file it it exists
536  refValFile = None
537  triedRefValFiles = []
538  tmp = [self._refRepository, self._refRelease]
539  if sample.fastsim():
540  tmp.extend(["fastsim", self._refRelease])
541  for selName in plotterFolder.getSelectionNameIterator(dqmSubFolder):
542  refSel = _createRefSelection(selName)
543  refdir = os.path.join(*(tmp+[refSel, sample.name()]))
544 
545  # Open reference file if it exists
546  refValFilePath = os.path.join(refdir, valname)
547  if os.path.exists(refValFilePath):
548  refSelection = refSel
549  refValFile = ROOT.TFile.Open(refValFilePath)
550  break
551  else:
552  triedRefValFiles.append(refValFilePath)
553  if refValFile is None:
554  if len(triedRefValFiles) == 1:
555  if plotting.verbose:
556  print "Reference file %s not found" % triedRefValFiles[0]
557  else:
558  if plotting.verbose:
559  print "None of the possible reference files %s not found" % ",".join(triedRefValFiles)
560 
561  return (refValFile, refSelection)
562 
563  def _doPlots(self, sample, harvestedFile, plotterFolder, dqmSubFolder, htmlReport):
564  """Do the real plotting work for a given sample and DQM subfolder"""
565  # Get GlobalTags
566  newGlobalTag = _getGlobalTag(sample, self._newRelease)
567 
568  # Construct selection string
569  selectionNameBase = ""
570  if sample.hasScenario():
571  selectionNameBase += "_"+sample.scenario()
572  selectionNameBase += "_"+sample.pileup()
573  newSelection = newGlobalTag+selectionNameBase+plotterFolder.getSelectionName(dqmSubFolder)
574  if sample.hasPileup():
575  newPu = sample.pileupType(self._newRelease)
576  if newPu != "":
577  newSelection += "_"+newPu
578 
579  valname = "val.{sample}.root".format(sample=sample.name())
580 
581  # Construct reference file and selection string
582  (refValFile, refSelection) = self._getRefFileAndSelection(sample, plotterFolder, dqmSubFolder, selectionNameBase, valname)
583 
584  # Construct new directory name
585  tmp = []
586  if sample.fastsim():
587  tmp.extend(["fastsim", self._newRelease])
588  tmp.extend([newSelection, sample.name()])
589  newsubdir = os.path.join(*tmp)
590  newdir = os.path.join(self._newBaseDir, newsubdir)
591 
592  # Copy the relevant histograms to a new validation root file
593  # TODO: treat the case where dqmSubFolder is empty
594  newValFile = _copySubDir(harvestedFile, valname, plotterFolder.getPossibleDQMFolders(), dqmSubFolder.subfolder if dqmSubFolder is not None else None)
595  fileList = []
596 
597  # Do the plots
598  if plotting.verbose:
599  print "Comparing ref and new {sim} {sample} {translatedFolder}".format(
600  sim="FullSim" if not sample.fastsim() else "FastSim",
601  sample=sample.name(), translatedFolder=str(dqmSubFolder.translated) if dqmSubFolder is not None else "")
602  rootFiles = [refValFile, newValFile]
603  legendLabels = [
604  "%s, %s %s" % (sample.name(), _stripRelease(self._refRelease), refSelection) if self._refRelease is not None else "dummy",
605  "%s, %s %s" % (sample.name(), _stripRelease(self._newRelease), newSelection)
606  ]
607  plotterFolder.create(rootFiles, legendLabels, dqmSubFolder, isPileupSample=sample.hasPileup())
608  fileList.extend(plotterFolder.draw(**self._plotterDrawArgs))
609  # Copy val file only if there were plots
610  if len(fileList) > 0:
611  fileList.append(valname)
612 
613  # For tables we just try them all, and see which ones succeed
614  for tableCreator in plotterFolder.getTableCreators():
615  htmlReport.addTable(tableCreator.create(rootFiles, legendLabels, dqmSubFolder))
616 
617  newValFile.Close()
618  if refValFile is not None:
619  refValFile.Close()
620 
621  if len(fileList) == 0:
622  return []
623 
624  # Move plots to new directory
625  print "Moving plots and %s to %s" % (valname, newdir)
626  if not os.path.exists(newdir):
627  os.makedirs(newdir)
628  for f in fileList:
629  shutil.move(f, os.path.join(newdir, f))
630  return map(lambda n: os.path.join(newsubdir, n), fileList)
631 
632  def _doPlotsFastFull(self, fastSample, fullSample, plotterFolder, dqmSubFolder, htmlReport):
633  """Do the real plotting work for FastSim vs. FullSim for a given algorithm, quality flag, and sample."""
634  # Get GlobalTags
635  fastGlobalTag = _getGlobalTag(fastSample, self._newRelease)
636  fullGlobalTag = _getGlobalTag(fullSample, self._newRelease)
637 
638  # Construct selection string
639  tmp = plotterFolder.getSelectionName(dqmSubFolder)
640  fastSelection = fastGlobalTag+"_"+fastSample.pileup()+tmp
641  fullSelection = fullGlobalTag+"_"+fullSample.pileup()+tmp
642  if fullSample.hasPileup():
643  fullSelection += "_"+fullSample.pileupType(self._newRelease)
644  fastSelection += "_"+fastSample.pileupType(self._newRelease)
645 
646  # Construct directories for FastSim, FullSim, and for the results
647  fastdir = os.path.join(self._newBaseDir, "fastsim", self._newRelease, fastSelection, fastSample.name())
648  fulldir = os.path.join(self._newBaseDir, fullSelection, fullSample.name())
649  newsubdir = os.path.join("fastfull", self._newRelease, fastSelection, fastSample.name())
650  newdir = os.path.join(self._newBaseDir, newsubdir)
651 
652  # Open input root files
653  valname = "val.{sample}.root".format(sample=fastSample.name())
654  fastValFilePath = os.path.join(fastdir, valname)
655  if not os.path.exists(fastValFilePath) and plotting.verbose:
656  print "FastSim file %s not found" % fastValFilePath
657  fullValFilePath = os.path.join(fulldir, valname)
658  if not os.path.exists(fullValFilePath) and plotting.verbose:
659  print "FullSim file %s not found" % fullValFilePath
660 
661  fastValFile = ROOT.TFile.Open(fastValFilePath)
662  fullValFile = ROOT.TFile.Open(fullValFilePath)
663 
664  # Do plots
665  if plotting.verbose:
666  print "Comparing FullSim and FastSim {sample} {translatedFolder}".format(
667  sample=fastSample.name(), translatedFolder=str(dqmSubFolder.translated) if dqmSubFolder is not None else "")
668  rootFiles = [fullValFile, fastValFile]
669  legendLabels = [
670  "FullSim %s, %s %s" % (fullSample.name(), _stripRelease(self._newRelease), fullSelection),
671  "FastSim %s, %s %s" % (fastSample.name(), _stripRelease(self._newRelease), fastSelection),
672  ]
673  plotterFolder.create(rootFiles, legendLabels, dqmSubFolder, isPileupSample=fastSample.hasPileup(), requireAllHistograms=True)
674  fileList = plotterFolder.draw(**self._plotterDrawArgs)
675 
676  # For tables we just try them all, and see which ones succeed
677  for tableCreator in plotterFolder.getTableCreators():
678  htmlReport.addTable(tableCreator.create(rootFiles, legendLabels, dqmSubFolder))
679 
680  fullValFile.Close()
681  fastValFile.Close()
682 
683  # Move plots to new directory
684  print "Moving plots to %s" % (newdir)
685  if not os.path.exists(newdir):
686  os.makedirs(newdir)
687  for f in fileList:
688  shutil.move(f, os.path.join(newdir, f))
689  return map(lambda n: os.path.join(newsubdir, n), fileList)
690 
691  # TODO: this method is still to be migrated
692  def _doPlotsPileup(self, algo, quality, sample):
693  """Do the real plotting work for Old vs. New pileup scenarios for a given algorithm, quality flag, and sample."""
694  # Get GlobalTags
695  newGlobalTag = _getGlobalTag(sample, self._newRelease)
696  refGlobalTag = newGlobalTag + "_OldPU"
697 
698  # Construct selection string
699  tmp = self._getSelectionName(quality, algo)
700  refSelection = refGlobalTag+"_"+sample.pileup()+tmp+"_"+sample.pileupType(self._newRelease)
701  newSelection = newGlobalTag+"_"+sample.pileup()+tmp+"_"+sample.pileupType(self._newRelease)
702 
703  # Construct directories for FastSim, FullSim, and for the results
704  refdir = os.path.join(self._newBaseDir, refSelection, sample.name())
705  newdir = os.path.join(self._newBaseDir, newSelection, sample.name())
706  resdir = os.path.join(self._newBaseDir, "pileup", self._newRelease, newSelection, sample.name())
707 
708  # Open input root files
709  valname = "val.{sample}.root".format(sample=sample.name())
710  refValFilePath = os.path.join(refdir, valname)
711  if not os.path.exists(refValFilePath) and plotting.verbose:
712  print "Ref pileup file %s not found" % refValFilePath
713  newValFilePath = os.path.join(newdir, valname)
714  if not os.path.exists(newValFilePath) and plotting.verbose:
715  print "New pileup file %s not found" % newValFilePath
716 
717  refValFile = ROOT.TFile.Open(refValFilePath)
718  newValFile = ROOT.TFile.Open(newValFilePath)
719 
720  # Do plots
721  if plotting.verbose:
722  print "Comparing Old and New pileup {sample} {algo} {quality}".format(
723  sample=sample.name(), algo=algo, quality=quality)
724  self._plotter.create([refValFile, newValFile], [
725  "%d BX %s, %s %s" % ({"25ns": 10, "50ns": 20}[sample.pileupType(self._newRelease)], sample.name(), _stripRelease(self._newRelease), refSelection),
726  "35 BX %s, %s %s" % (sample.name(), _stripRelease(self._newRelease), newSelection),
727  ],
728  subdir = self._getDirectoryName(quality, algo))
729  fileList = self._plotter.draw(**self._plotterDrawArgs)
730 
731  newValFile.Close()
732  refValFile.Close()
733 
734  # Move plots to new directory
735  print "Moving plots to %s" % (resdir)
736  if not os.path.exists(resdir):
737  os.makedirs(resdir)
738  for f in fileList:
739  shutil.move(f, os.path.join(resdir, f))
740  subdir = newdir.replace(self._newBaseDir+"/", "")
741  return map(lambda n: os.path.join(subdir, n), fileList)
742 
743 def _copySubDir(oldfile, newfile, basenames, dirname):
744  """Copy a subdirectory from oldfile to newfile.
745 
746  Arguments:
747  oldfile -- String for source TFile
748  newfile -- String for destination TFile
749  basenames -- List of strings for base directories, first existing one is picked
750  dirname -- String for directory name under the base directory
751  """
752  oldf = ROOT.TFile.Open(oldfile)
753 
754  dirold = None
755  for basename in basenames:
756  dirold = oldf.GetDirectory(basename)
757  if dirold:
758  break
759  if not dirold:
760  raise Exception("Did not find any of %s directories from file %s" % (",".join(basenames), oldfile))
761  if dirname:
762  d = dirold.Get(dirname)
763  if not d:
764  raise Exception("Did not find directory %s under %s" % (dirname, dirold.GetPath()))
765  dirold = d
766 
767  newf = ROOT.TFile.Open(newfile, "RECREATE")
768  dirnew = newf
769  for d in basenames[0].split("/"):
770  dirnew = dirnew.mkdir(d)
771  if dirname:
772  dirnew = dirnew.mkdir(dirname)
773  _copyDir(dirold, dirnew)
774 
775  oldf.Close()
776  return newf
777 
778 def _copyDir(src, dst):
779  """Copy non-TTree objects from src TDirectory to dst TDirectory."""
780  keys = src.GetListOfKeys()
781  for key in keys:
782  classname = key.GetClassName()
783  cl = ROOT.TClass.GetClass(classname)
784  if not cl:
785  continue
786  if not (cl.InheritsFrom("TTree") and cl.InheritsFrom("TDirectory")):
787  dst.cd()
788  obj = key.ReadObj()
789  obj.Write()
790  obj.Delete()
791 
793  def __init__(self, label, name, pileup=True):
794  self._label = label
795  self._name = name
796  self._pileup = pileup
797 
798  def digest(self):
799  # Label should be unique among the plotting run, so it serves also as the digest
800  return self._label
801 
802  def label(self):
803  return self._label
804 
805  def name(self):
806  return self._name
807 
808  def fastsim(self):
809  # No need to emulate the release validation fastsim behaviour here
810  return False
811 
812  def hasPileup(self):
813  return self._pileup
814 
815  def pileupType(self):
816  return ""
817 
819  def __init__(self, files, labels, newdir):
820  self._files = files
821  self._labels = labels
822  self._newdir = newdir
823 
824  def createHtmlReport(self, validationName=""):
825  return html.HtmlReport(validationName, self._newdir)
826 
827  def doPlots(self, plotter, subdirprefix=None, sample=None, plotterDrawArgs={}, limitSubFoldersOnlyTo=None, htmlReport=html.HtmlReportDummy()):
828  if subdirprefix is None and sample is None:
829  raise Exception("Need either 'subdirprefix' or 'sample'")
830  if subdirprefix is not None and sample is not None:
831  raise Exception("May give only one of 'subdirprefix' or 'sample', got both")
832 
833  self._subdirprefix = sample.label() if sample is not None else subdirprefix
834  self._plotterDrawArgs = plotterDrawArgs
835 
836  self._openFiles = []
837  for f in self._files:
838  if not os.path.exists(f):
839  print "File %s not found" % f
840  sys.exit(1)
841  self._openFiles.append(ROOT.TFile.Open(f))
842 
843  plotterInstance = plotter.readDirs(*self._openFiles)
844  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
845  if sample is not None and plotterFolder.onlyForPileup() and not sample.hasPileup():
846  continue
847  plotFiles = self._doPlots(plotterFolder, dqmSubFolder, htmlReport)
848  if len(plotFiles) > 0:
849  htmlReport.addPlots(plotterFolder, dqmSubFolder, plotFiles)
850 
851  for tf in self._openFiles:
852  tf.Close()
853  self._openFiles = []
854 
855  def _doPlots(self, plotterFolder, dqmSubFolder, htmlReport):
856  plotterFolder.create(self._openFiles, self._labels, dqmSubFolder)
857  fileList = plotterFolder.draw(**self._plotterDrawArgs)
858 
859  for tableCreator in plotterFolder.getTableCreators():
860  htmlReport.addTable(tableCreator.create(self._openFiles, self._labels, dqmSubFolder))
861 
862  newsubdir = self._subdirprefix+plotterFolder.getSelectionName(dqmSubFolder)
863  newdir = os.path.join(self._newdir, newsubdir)
864 
865  if len(fileList) == 0:
866  return fileList
867 
868  print "Moving plots to %s" % newdir
869  if not os.path.exists(newdir):
870  os.makedirs(newdir)
871  for f in fileList:
872  shutil.move(f, os.path.join(newdir, f))
873  return map(lambda n: os.path.join(newsubdir, n), fileList)
_fastsimCorrespondingFullsimPileup
Definition: validation.py:215
def _copySubDir
Definition: validation.py:743
def _getGlobalTag
Definition: validation.py:133
def _stripRelease
Definition: validation.py:126
def fastsimCorrespondingFullsimPileup
Definition: validation.py:283
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
double split
Definition: MVATrainer.cc:139
def _getRelValUrl
Definition: validation.py:178
def _copyDir
Definition: validation.py:778