CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
validation.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from __future__ import absolute_import
3 import os
4 import re
5 import sys
6 import shutil
7 import subprocess
8 import urllib.request
9 import multiprocessing
10 
11 import ROOT
12 ROOT.gROOT.SetBatch(True)
13 ROOT.PyConfig.IgnoreCommandLineOptions = True
14 
15 from . import plotting
16 from . import html
17 
18 # Mapping from releases to GlobalTags
19 _globalTags = {
20  "CMSSW_6_2_0": {"default": "PRE_ST62_V8"},
21  "CMSSW_6_2_0_SLHC15": {"UPG2019withGEM": "DES19_62_V8", "UPG2023SHNoTaper": "DES23_62_V1"},
22  "CMSSW_6_2_0_SLHC17": {"UPG2019withGEM": "DES19_62_V8", "UPG2023SHNoTaper": "DES23_62_V1"},
23  "CMSSW_6_2_0_SLHC20": {"UPG2019withGEM": "DES19_62_V8", "UPG2023SHNoTaper": "DES23_62_V1_UPG2023SHNoTaper"},
24  "CMSSW_6_2_0_SLHC22": {"UPG2023SHNoTaper": "PH2_1K_FB_V6_UPG23SHNoTaper",
25  # map 81X GReco and tilted to SHNoTaper
26  "2023GReco": "PH2_1K_FB_V6_UPG23SHNoTaper", "2023GRecoPU35": "", "2023GRecoPU140": "", "2023GRecoPU200": "",
27  "2023tilted": "PH2_1K_FB_V6_UPG23SHNoTaper", "2023tiltedPU35": "", "2023tiltedPU140": "", "2023tiltedPU200": ""},
28  "CMSSW_6_2_0_SLHC26": {"LHCCRefPU140": "DES23_62_V1_LHCCRefPU140", "LHCCRefPU200": "DES23_62_V1_LHCCRefPU200",
29  # map 81X GReco and tilted to LHCCRef
30  "2023GReco": "", "2023GRecoPU35": "", "2023GRecoPU140": "DES23_62_V1_LHCCRefPU140", "2023GRecoPU200": "DES23_62_V1_LHCCRefPU200",
31  "2023tilted": "", "2023tiltedPU35": "", "2023tiltedPU140": "DES23_62_V1_LHCCRefPU140", "2023tiltedPU200": "DES23_62_V1_LHCCRefPU200"},
32  "CMSSW_6_2_0_SLHC27_phase1": {"default": "DES17_62_V8_UPG17"},
33  "CMSSW_7_0_0": {"default": "POSTLS170_V3", "fullsim_50ns": "POSTLS170_V4"},
34  "CMSSW_7_0_0_AlcaCSA14": {"default": "POSTLS170_V5_AlcaCSA14", "fullsim_50ns": "POSTLS170_V6_AlcaCSA14"},
35  "CMSSW_7_0_7_pmx": {"default": "PLS170_V7AN1", "fullsim_50ns": "PLS170_V6AN1"},
36  "CMSSW_7_0_9_patch3": {"default": "PLS170_V7AN2", "fullsim_50ns": "PLS170_V6AN2"},
37  "CMSSW_7_0_9_patch3_Premix": {"default": "PLS170_V7AN2", "fullsim_50ns": "PLS170_V6AN2"},
38  "CMSSW_7_1_0": {"default": "POSTLS171_V15", "fullsim_50ns": "POSTLS171_V16"},
39  "CMSSW_7_1_9": {"default": "POSTLS171_V17", "fullsim_50ns": "POSTLS171_V18"},
40  "CMSSW_7_1_9_patch2": {"default": "POSTLS171_V17", "fullsim_50ns": "POSTLS171_V18"},
41  "CMSSW_7_1_10_patch2": {"default": "MCRUN2_71_V1", "fullsim_50ns": "MCRUN2_71_V0"},
42  "CMSSW_7_2_0_pre5": {"default": "POSTLS172_V3", "fullsim_50ns": "POSTLS172_V4"},
43  "CMSSW_7_2_0_pre7": {"default": "PRE_LS172_V11", "fullsim_50ns": "PRE_LS172_V12"},
44  "CMSSW_7_2_0_pre8": {"default": "PRE_LS172_V15", "fullsim_50ns": "PRE_LS172_V16"},
45  "CMSSW_7_2_0": {"default": "PRE_LS172_V15", "fullsim_50ns": "PRE_LS172_V16"},
46  "CMSSW_7_2_0_PHYS14": {"default": "PHYS14_25_V1_Phys14"},
47  "CMSSW_7_2_2_patch1": {"default": "MCRUN2_72_V1", "fullsim_50ns": "MCRUN2_72_V0"},
48  "CMSSW_7_2_2_patch1_Fall14DR": {"default": "MCRUN2_72_V3_71XGENSIM"},
49 # "CMSSW_7_3_0_pre1": {"default": "PRE_LS172_V15", "fullsim_25ns": "PRE_LS172_V15_OldPU", "fullsim_50ns": "PRE_LS172_V16_OldPU"},
50  "CMSSW_7_3_0_pre1": {"default": "PRE_LS172_V15", "fullsim_50ns": "PRE_LS172_V16"},
51 # "CMSSW_7_3_0_pre2": {"default": "MCRUN2_73_V1_OldPU", "fullsim_50ns": "MCRUN2_73_V0_OldPU"},
52  "CMSSW_7_3_0_pre2": {"default": "MCRUN2_73_V1", "fullsim_50ns": "MCRUN2_73_V0"},
53  "CMSSW_7_3_0_pre3": {"default": "MCRUN2_73_V5", "fullsim_50ns": "MCRUN2_73_V4"},
54  "CMSSW_7_3_0": {"default": "MCRUN2_73_V7", "fullsim_50ns": "MCRUN2_73_V6"},
55  "CMSSW_7_3_0_71XGENSIM": {"default": "MCRUN2_73_V7_71XGENSIM"},
56  "CMSSW_7_3_0_71XGENSIM_FIXGT": {"default": "MCRUN2_73_V9_71XGENSIM_FIXGT"},
57  "CMSSW_7_3_1_patch1": {"default": "MCRUN2_73_V9", "fastsim": "MCRUN2_73_V7"},
58  "CMSSW_7_3_1_patch1_GenSim_7113": {"default": "MCRUN2_73_V9_GenSim_7113"},
59  "CMSSW_7_3_3": {"default": "MCRUN2_73_V11", "fullsim_50ns": "MCRUN2_73_V10", "fastsim": "MCRUN2_73_V13"},
60  "CMSSW_7_4_0_pre1": {"default": "MCRUN2_73_V5", "fullsim_50ns": "MCRUN2_73_V4"},
61  "CMSSW_7_4_0_pre2": {"default": "MCRUN2_73_V7", "fullsim_50ns": "MCRUN2_73_V6"},
62  "CMSSW_7_4_0_pre2_73XGENSIM": {"default": "MCRUN2_73_V7_73XGENSIM_Pythia6", "fullsim_50ns": "MCRUN2_73_V6_73XGENSIM_Pythia6"},
63  "CMSSW_7_4_0_pre5": {"default": "MCRUN2_73_V7", "fullsim_50ns": "MCRUN2_73_V6"},
64  "CMSSW_7_4_0_pre5_BS": {"default": "MCRUN2_73_V9_postLS1beamspot", "fullsim_50ns": "MCRUN2_73_V8_postLS1beamspot"},
65  "CMSSW_7_4_0_pre6": {"default": "MCRUN2_74_V1", "fullsim_50ns": "MCRUN2_74_V0"},
66  "CMSSW_7_4_0_pre8": {"default": "MCRUN2_74_V7", "fullsim_25ns": "MCRUN2_74_V5_AsympMinGT", "fullsim_50ns": "MCRUN2_74_V4_StartupMinGT"},
67  "CMSSW_7_4_0_pre8_minimal": {"default": "MCRUN2_74_V5_MinGT", "fullsim_25ns": "MCRUN2_74_V5_AsympMinGT", "fullsim_50ns": "MCRUN2_74_V4_StartupMinGT"},
68  "CMSSW_7_4_0_pre8_25ns_asymptotic": {"default": "MCRUN2_74_V7"},
69  "CMSSW_7_4_0_pre8_50ns_startup": {"default": "MCRUN2_74_V6"},
70  "CMSSW_7_4_0_pre8_50ns_asympref": {"default": "MCRUN2_74_V5A_AsympMinGT"}, # for reference of 50ns asymptotic
71  "CMSSW_7_4_0_pre8_50ns_asymptotic": {"default": "MCRUN2_74_V7A_AsympGT"},
72  "CMSSW_7_4_0_pre8_ROOT6": {"default": "MCRUN2_74_V7"},
73  "CMSSW_7_4_0_pre8_pmx": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
74  "CMSSW_7_4_0_pre8_pmx_v2": {"default": "MCRUN2_74_V7_gs_pre7", "fullsim_50ns": "MCRUN2_74_V6_gs_pre7"},
75  "CMSSW_7_4_0_pre8_pmx_v3": {"default": "MCRUN2_74_V7_bis", "fullsim_50ns": "MCRUN2_74_V6_bis"},
76  "CMSSW_7_4_0_pre9": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
77  "CMSSW_7_4_0_pre9_ROOT6": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
78  "CMSSW_7_4_0_pre9_extended": {"default": "MCRUN2_74_V7_extended"},
79  "CMSSW_7_4_0": {"default": "MCRUN2_74_V7_gensim_740pre7", "fullsim_50ns": "MCRUN2_74_V6_gensim_740pre7", "fastsim": "MCRUN2_74_V7"},
80  "CMSSW_7_4_0_71XGENSIM": {"default": "MCRUN2_74_V7_GENSIM_7_1_15", "fullsim_50ns": "MCRUN2_74_V6_GENSIM_7_1_15"},
81  "CMSSW_7_4_0_71XGENSIM_PU": {"default": "MCRUN2_74_V7_gs7115_puProd", "fullsim_50ns": "MCRUN2_74_V6_gs7115_puProd"},
82  "CMSSW_7_4_0_71XGENSIM_PXworst": {"default": "MCRUN2_74_V7C_pxWorst_gs7115", "fullsim_50ns": "MCRUN2_74_V6A_pxWorst_gs7115"},
83  "CMSSW_7_4_0_71XGENSIM_PXbest": {"default": "MCRUN2_74_V7D_pxBest_gs7115", "fullsim_50ns": "MCRUN2_74_V6B_pxBest_gs7115"},
84  "CMSSW_7_4_0_pmx": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
85  "CMSSW_7_4_1": {"default": "MCRUN2_74_V9_gensim_740pre7", "fullsim_50ns": "MCRUN2_74_V8_gensim_740pre7", "fastsim": "MCRUN2_74_V9"},
86  "CMSSW_7_4_1_71XGENSIM": {"default": "MCRUN2_74_V9_gensim71X", "fullsim_50ns": "MCRUN2_74_V8_gensim71X"},
87  "CMSSW_7_4_1_extended": {"default": "MCRUN2_74_V9_extended"},
88  "CMSSW_7_4_3": {"default": "MCRUN2_74_V9", "fullsim_50ns": "MCRUN2_74_V8", "fastsim": "MCRUN2_74_V9", "fastsim_25ns": "MCRUN2_74_V9_fixMem"},
89  "CMSSW_7_4_3_extended": {"default": "MCRUN2_74_V9_ext","fastsim": "MCRUN2_74_V9_fixMem"},
90  "CMSSW_7_4_3_pmx": {"default": "MCRUN2_74_V9_ext", "fullsim_50ns": "MCRUN2_74_V8", "fastsim": "MCRUN2_74_V9_fixMem"},
91  "CMSSW_7_4_3_patch1_unsch": {"default": "MCRUN2_74_V9_unsch", "fullsim_50ns": "MCRUN2_74_V8_unsch"},
92  "CMSSW_7_4_4": {"default": "MCRUN2_74_V9_38Tbis", "fullsim_50ns": "MCRUN2_74_V8_38Tbis"},
93  "CMSSW_7_4_4_0T": {"default": "MCRUN2_740TV1_0Tv2", "fullsim_50ns": "MCRUN2_740TV0_0TV2", "fullsim_25ns": "MCRUN2_740TV1_0TV2"},
94  "CMSSW_7_4_6_patch6": {"default": "MCRUN2_74_V9_scheduled", "fullsim_50ns": "MCRUN2_74_V8_scheduled"},
95  "CMSSW_7_4_6_patch6_unsch": {"default": "MCRUN2_74_V9", "fullsim_50ns": "MCRUN2_74_V8"},
96  "CMSSW_7_4_6_patch6_noCCC": {"default": "MCRUN2_74_V9_unsch_noCCC", "fullsim_50ns": "MCRUN2_74_V8_unsch_noCCC"},
97  "CMSSW_7_4_6_patch6_noCCC_v3": {"default": "MCRUN2_74_V9_unsch_noCCC_v3", "fullsim_50ns": "MCRUN2_74_V8_unsch_noCCC_v3"},
98  "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"},
99  "CMSSW_7_4_8_patch1_MT": {"default": "MCRUN2_74_V11_mulTrh", "fullsim_50ns": "MCRUN2_74_V10_mulTrh",},
100  "CMSSW_7_4_12": {"default": "74X_mcRun2_asymptotic_v2", "fullsim_25ns": "74X_mcRun2_asymptotic_v2_v2", "fullsim_50ns": "74X_mcRun2_startup_v2_v2"},
101  "CMSSW_7_5_0_pre1": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
102  "CMSSW_7_5_0_pre2": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
103  "CMSSW_7_5_0_pre3": {"default": "MCRUN2_74_V7", "fullsim_50ns": "MCRUN2_74_V6"},
104  "CMSSW_7_5_0_pre4": {"default": "MCRUN2_75_V1", "fullsim_50ns": "MCRUN2_75_V0"},
105  "CMSSW_7_5_0_pre5": {"default": "MCRUN2_75_V5", "fullsim_50ns": "MCRUN2_75_V4"},
106  "CMSSW_7_5_0_pre6": {"default": "75X_mcRun2_asymptotic_v1", "fullsim_50ns": "75X_mcRun2_startup_v1"},
107  "CMSSW_7_5_0": {"default": "75X_mcRun2_asymptotic_v1", "fullsim_50ns": "75X_mcRun2_startup_v1"},
108  "CMSSW_7_5_0_71XGENSIM": {"default": "75X_mcRun2_asymptotic_v1_gs7115", "fullsim_50ns": "75X_mcRun2_startup_v1_gs7115"},
109  "CMSSW_7_5_1": {"default": "75X_mcRun2_asymptotic_v3", "fullsim_50ns": "75X_mcRun2_startup_v3"},
110  "CMSSW_7_5_1_71XGENSIM": {"default": "75X_mcRun2_asymptotic_v3_gs7118", "fullsim_50ns": "75X_mcRun2_startup_v3_gs7118"},
111  "CMSSW_7_5_2": {"default": "75X_mcRun2_asymptotic_v5", "fullsim_50ns": "75X_mcRun2_startup_v4"},
112  "CMSSW_7_6_0_pre1": {"default": "75X_mcRun2_asymptotic_v1", "fullsim_50ns": "75X_mcRun2_startup_v1"},
113  "CMSSW_7_6_0_pre2": {"default": "75X_mcRun2_asymptotic_v2", "fullsim_50ns": "75X_mcRun2_startup_v2"},
114  "CMSSW_7_6_0_pre3": {"default": "75X_mcRun2_asymptotic_v2", "fullsim_50ns": "75X_mcRun2_startup_v2"},
115  "CMSSW_7_6_0_pre4": {"default": "76X_mcRun2_asymptotic_v1", "fullsim_50ns": "76X_mcRun2_startup_v1"},
116  "CMSSW_7_6_0_pre5": {"default": "76X_mcRun2_asymptotic_v1", "fullsim_50ns": "76X_mcRun2_startup_v1"},
117  "CMSSW_7_6_0_pre6": {"default": "76X_mcRun2_asymptotic_v4", "fullsim_50ns": "76X_mcRun2_startup_v4"},
118  "CMSSW_7_6_0_pre7": {"default": "76X_mcRun2_asymptotic_v5", "fullsim_50ns": "76X_mcRun2_startup_v5", "fastsim": "76X_mcRun2_asymptotic_v5_resub"},
119  "CMSSW_7_6_0": {"default": "76X_mcRun2_asymptotic_v11", "fullsim_50ns": "76X_mcRun2_startup_v11"},
120  "CMSSW_7_6_0_71XGENSIM": {"default": "76X_mcRun2_asymptotic_v11_gs7120p2rlBS", "fullsim_50ns": "76X_mcRun2_startup_v11_gs7120p2rlBS"},
121  "CMSSW_7_6_2": {"default": "76X_mcRun2_asymptotic_v12", "fullsim_50ns": "76X_mcRun2_startup_v11"},
122  "CMSSW_7_6_3_patch2_0T": {"default": "76X_mcRun2_0T_v1_0Tv1GT"},
123  "CMSSW_8_0_0_pre1": {"default": "76X_mcRun2_asymptotic_v11", "fullsim_50ns": "76X_mcRun2_startup_v11"},
124  "CMSSW_8_0_0_pre2": {"default": "76X_mcRun2_asymptotic_v12", "fullsim_50ns": "76X_mcRun2_startup_v11"},
125  "CMSSW_8_0_0_pre2_phase1": {"default": "76X_upgrade2017_design_v7"},
126  "CMSSW_8_0_0_pre2_phase1_rereco": {"default": "76X_upgrade2017_design_v7_rereco"},
127  "CMSSW_8_0_0_pre3_phase1": {"default": "76X_upgrade2017_design_v8"},
128  "CMSSW_8_0_0_pre3_phase1_pythia8": {"default": "76X_upgrade2017_design_v8_pythia8"},
129  "CMSSW_8_0_0_pre4": {"default": "76X_mcRun2_asymptotic_v13", "fullsim_50ns": "76X_mcRun2_startup_v12"},
130  "CMSSW_8_0_0_pre4_phase1": {"default": "76X_upgrade2017_design_v8_UPG17"},
131  "CMSSW_8_0_0_pre4_phase1_13TeV": {"default": "76X_upgrade2017_design_v8_UPG17"},
132  "CMSSW_8_0_0_pre4_ecal15fb": {"default": "80X_mcRun2_asymptotic_2016EcalTune_15fb_v0_ecal15fbm1"},
133  "CMSSW_8_0_0_pre4_ecal30fb": {"default": "80X_mcRun2_asymptotic_2016EcalTune_30fb_v0_ecal30fbm1"},
134  "CMSSW_8_0_0_pre5": {"default": "80X_mcRun2_asymptotic_v1", "fullsim_50ns": "80X_mcRun2_startup_v1"},
135  "CMSSW_8_0_0_pre5_phase1": {"default": "80X_upgrade2017_design_v1_UPG17"},
136  "CMSSW_8_0_0_pre6": {"default": "80X_mcRun2_asymptotic_v4"},
137  "CMSSW_8_0_0_pre6_phase1": {"default": "80X_upgrade2017_design_v3_UPG17"},
138  "CMSSW_8_0_0_pre6_MT": {"default": "80X_mcRun2_asymptotic_v4_multiCoreResub"},
139  "CMSSW_8_0_0": {"default": "80X_mcRun2_asymptotic_v4"},
140  "CMSSW_8_0_0_patch1_phase1": {"default": "80X_upgrade2017_design_v4_UPG17"},
141  "CMSSW_8_0_0_patch1_phase1_rereco": {"default": "80X_upgrade2017_design_v4_UPG17_rereco"},
142  "CMSSW_8_0_0_patch2": {"default": "80X_mcRun2_asymptotic_v5_refGT"},
143  "CMSSW_8_0_0_patch2_pixDynIneff": {"default": "80X_mcRun2_asymptotic_v5_2016PixDynIneff_targetGT"},
144 # "CMSSW_8_0_0_patch2": {"default": "80X_mcRun2_asymptotic_v5_refGT"},
145 # "CMSSW_8_0_0_patch2_pixDynIneff": {"default": "80X_mcRun2_asymptotic_v5_2016PixDynIneff_targetGT"},
146  "CMSSW_8_0_0_patch2": {"default": "80X_mcRun2_asymptotic_v5_refGT_resub"},
147  "CMSSW_8_0_0_patch2_pixDynIneff": {"default": "80X_mcRun2_asymptotic_v5_2016PixDynIneff_targetGT_resub"},
148  "CMSSW_8_0_1": {"default": "80X_mcRun2_asymptotic_v6"},
149  "CMSSW_8_0_1_71XGENSIM": {"default": "80X_mcRun2_asymptotic_v6_gs7120p2"},
150  "CMSSW_8_0_1_gcc530": {"default": "80X_mcRun2_asymptotic_v6_gcc530"},
151  "CMSSW_8_0_3_71XGENSIM": {"default": "80X_mcRun2_asymptotic_2016_v3_gs7120p2NewGTv3"},
152  "CMSSW_8_0_3_71XGENSIM_hcal": {"default": "80X_mcRun2_asymptotic_2016_v3_gs71xNewGtHcalCust"},
153  "CMSSW_8_0_3_71XGENSIM_tec": {"default": "80X_mcRun2_asymptotic_SiStripBad_TEC_CL62_for2016_v1_mc_gs7120p2TrkCoolLoop"},
154  "CMSSW_8_0_5": {"default": "80X_mcRun2_asymptotic_v12_gs7120p2", "fastsim": "80X_mcRun2_asymptotic_v12"},
155  "CMSSW_8_0_5_pmx": {"default": "80X_mcRun2_asymptotic_v12_gs7120p2_resub", "fastsim": "80X_mcRun2_asymptotic_v12"},
156  "CMSSW_8_0_10": {"default": "80X_mcRun2_asymptotic_v14"},
157  "CMSSW_8_0_10_patch1_BS": {"default": "80X_mcRun2_asymptotic_RealisticBS_25ns_13TeV2016_v1_mc_realisticBS2016"},
158  "CMSSW_8_0_11": {"default": "80X_mcRun2_asymptotic_v14"},
159  "CMSSW_8_0_15": {"default": "80X_mcRun2_asymptotic_v16_gs7120p2", "fastsim": "80X_mcRun2_asymptotic_v16"},
160  "CMSSW_8_0_16": {"default": "80X_mcRun2_asymptotic_v16_gs7120p2", "fastsim": "80X_mcRun2_asymptotic_v16"},
161  "CMSSW_8_0_16_Tranche4GT": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v0_gs7120p2_Tranch4GT",
162  "fastsim": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v0_Tranch4GT", "RelValTTbar": "80X_mcRun2_asymptotic_2016_TrancheIV_v0_Tr4GT_resub"}, "fastsim_25ns": "80X_mcRun2_asymptotic_2016_TrancheIV_v0_Tranch4GT"},
163  "CMSSW_8_0_16_Tranche4GT_v2": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v2_Tr4GT_v2"},
164  "CMSSW_8_0_16_Tranche4GT_pmx": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v0_gs7120p2_Tranch4GT", "fastsim": "80X_mcRun2_asymptotic_2016_TrancheIV_v0_resub"},
165  "CMSSW_8_0_19_Tranche4GT_v2": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v2_Tr4GT_v2"},
166  "CMSSW_8_0_20_Tranche4GT": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v4_Tr4GT_v4"},
167  "CMSSW_8_0_21_Tranche4GT": {"default": "80X_mcRun2_asymptotic_2016_TrancheIV_v6_Tr4GT_v6"},
168  "CMSSW_8_1_0_pre1": {"default": "80X_mcRun2_asymptotic_v6"},
169  "CMSSW_8_1_0_pre1_phase1": {"default": "80X_upgrade2017_design_v4_UPG17", "fullsim_25ns": "80X_upgrade2017_design_v4_UPG17PU35"},
170  "CMSSW_8_1_0_pre2": {"default": "80X_mcRun2_asymptotic_v10_gs810pre2", "fastsim": "80X_mcRun2_asymptotic_v10"},
171  "CMSSW_8_1_0_pre2_phase1": {"default": "80X_upgrade2017_design_v9_UPG17designGT", "fullsim_25ns": "80X_upgrade2017_design_v9_UPG17PU35designGT"},
172  "CMSSW_8_1_0_pre2_phase1_realGT": {"default": "80X_upgrade2017_realistic_v1_UPG17realGT", "fullsim_25ns": "80X_upgrade2017_realistic_v1_UPG17PU35realGT"},
173  "CMSSW_8_1_0_pre3": {"default": "80X_mcRun2_asymptotic_v12"},
174  "CMSSW_8_1_0_pre3_phase1": {"default": "80X_upgrade2017_realistic_v3_UPG17", "fullsim_25ns": "80X_upgrade2017_realistic_v3_UPG17PU35"},
175  "CMSSW_8_1_0_pre4": {"default": "80X_mcRun2_asymptotic_v13"},
176  "CMSSW_8_1_0_pre4_phase1": {"default": "80X_upgrade2017_realistic_v4_UPG17", "fullsim_25ns": "80X_upgrade2017_realistic_v4_UPG17PU35"},
177  "CMSSW_8_1_0_pre5": {"default": "80X_mcRun2_asymptotic_v13"},
178  "CMSSW_8_1_0_pre5_phase1": {"default": "80X_upgrade2017_realistic_v4_resubUPG17", "fullsim_25ns": "80X_upgrade2017_realistic_v4_resubUPG17PU35"},
179  "CMSSW_8_1_0_pre6": {"default": "80X_mcRun2_asymptotic_v14"},
180  "CMSSW_8_1_0_pre6_phase1": {"default": "81X_upgrade2017_realistic_v0_UPG17", "fullsim_25ns": "81X_upgrade2017_realistic_v0_UPG17PU35"},
181  "CMSSW_8_1_0_pre7": {"default": "81X_mcRun2_asymptotic_v0"},
182  "CMSSW_8_1_0_pre7_phase1": {"default": "81X_upgrade2017_realistic_v2_UPG17", "fullsim_25ns": "81X_upgrade2017_realistic_v2_UPG17PU35"},
183  "CMSSW_8_1_0_pre7_phase1_newGT": {"default": "81X_upgrade2017_realistic_v3_UPG17newGT", "fullsim_25ns": "81X_upgrade2017_realistic_v3_UPG17PU35newGTresub"},
184  "CMSSW_8_1_0_pre7_phase2": {"2023GReco": "81X_mcRun2_asymptotic_v0_2023GReco", "2023GRecoPU35": "", "2023GRecoPU140": "81X_mcRun2_asymptotic_v0_2023GRecoPU140resubmit2", "2023GRecoPU200": "81X_mcRun2_asymptotic_v0_2023GRecoPU200resubmit2",
185  "2023tilted": "81X_mcRun2_asymptotic_v0_2023tilted", "2023tiltedPU35": "", "2023tiltedPU140": "81X_mcRun2_asymptotic_v0_2023tiltedPU140resubmit2", "2023tiltedPU200": "81X_mcRun2_asymptotic_v0_2023tiltedPU200resubmit2"},
186  "CMSSW_8_1_0_pre8": {"default": "81X_mcRun2_asymptotic_v1"},
187  "CMSSW_8_1_0_pre8_phase1": {"default": "81X_upgrade2017_realistic_v3_UPG17", "fullsim_25ns": "81X_upgrade2017_realistic_v3_UPG17PU35"},
188  "CMSSW_8_1_0_pre8_phase1_newGT": {"default": "81X_upgrade2017_realistic_v4_UPG17newGT", "fullsim_25ns": "81X_upgrade2017_realistic_v4_UPG17PU35newGT"},
189  "CMSSW_8_1_0_pre8_phase1_newGT2": {"default": "81X_upgrade2017_realistic_v5_UPG17newGTset2", "fullsim_25ns": "81X_upgrade2017_realistic_v5_UPG17PU35newGTset2"},
190  "CMSSW_8_1_0_pre8_phase2": {"2023GReco": "81X_mcRun2_asymptotic_v1_resub2023GReco", "2023GRecoPU35": "81X_mcRun2_asymptotic_v1_resub2023GRecoPU35", "2023GRecoPU140": "81X_mcRun2_asymptotic_v1_resub2023GRecoPU140", "2023GRecoPU200": "81X_mcRun2_asymptotic_v1_resub2023GRecoPU200",
191  "2023tilted": "81X_mcRun2_asymptotic_v1_2023tilted", "2023tiltedPU35": "81X_mcRun2_asymptotic_v1_2023tiltedPU", "2023tiltedPU140": "81X_mcRun2_asymptotic_v1_2023tiltedPU140", "2023tiltedPU200": "81X_mcRun2_asymptotic_v1_2023tiltedPU200"},
192  "CMSSW_8_1_0_pre9": {"default": "81X_mcRun2_asymptotic_v2"},
193  "CMSSW_8_1_0_pre9_Geant4102": {"default": "81X_mcRun2_asymptotic_v2"},
194  "CMSSW_8_1_0_pre9_phase1": {"default": "81X_upgrade2017_realistic_v5_UPG17", "fullsim_25ns": "81X_upgrade2017_realistic_v5_UPG17PU35"},
195  "CMSSW_8_1_0_pre9_phase1_newGT": {"default": "81X_upgrade2017_realistic_v6_UPG17newGT", "fullsim_25ns": "81X_upgrade2017_realistic_v6_UPG17PU35newGT"},
196  "CMSSW_8_1_0_pre10": {"default": "81X_mcRun2_asymptotic_v5_recycle", "fullsim_25ns": "81X_mcRun2_asymptotic_v5_resub", "fastsim": "81X_mcRun2_asymptotic_v5"},
197  "CMSSW_8_1_0_pre10_pmx": {"default": "81X_mcRun2_asymptotic_v5"},
198  "CMSSW_8_1_0_pre10_phase1": {"default": "81X_upgrade2017_realistic_v9_UPG17resub", "fullsim_25ns": "81X_upgrade2017_realistic_v9_UPG17PU35resub"},
199  "CMSSW_8_1_0_pre11": {"default": "81X_mcRun2_asymptotic_Candidate_2016_08_30_11_31_55", "fullsim_25ns": "81X_mcRun2_asymptotic_Candidate_2016_08_30_11_31_55_resub", "fastsim_25ns": "81X_mcRun2_asymptotic_Candidate_2016_08_30_11_31_55_resub2"},
200  "CMSSW_8_1_0_pre11_pmx": {"default": "81X_mcRun2_asymptotic_Candidate_2016_08_30_11_31_55"},
201  "CMSSW_8_1_0_pre11_phase1": {"default": "81X_upgrade2017_realistic_v9_UPG17", "fullsim_25ns": "81X_upgrade2017_realistic_v9_UPG17PU35"},
202  "CMSSW_8_1_0_pre12": {"default": "81X_mcRun2_asymptotic_v8", "fullsim_25ns": "81X_mcRun2_asymptotic_v8_resub", "fastsim": "81X_mcRun2_asymptotic_v8_resub", "fastsim_25ns": "81X_mcRun2_asymptotic_v8"},
203  "CMSSW_8_1_0_pre12_pmx": {"default": "81X_mcRun2_asymptotic_v8_resub", "fastsim_25ns": "81X_mcRun2_asymptotic_v8_rsub"},
204  "CMSSW_8_1_0_pre12_phase1": {"default": "81X_upgrade2017_realistic_v13"},
205  "CMSSW_8_1_0_pre12_phase1_newBPix": {"default": "81X_upgrade2017_realistic_newBPix_wAlign_v1_BpixGeom"},
206  "CMSSW_8_1_0_pre12_phase1_newBPixFPix": {"default": "81X_upgrade2017_realistic_v13_BpixFpixGeom"},
207  "CMSSW_8_1_0_pre12_phase1_newBPixFPixHCAL": {"default": "81X_upgrade2017_HCALdev_v2_BpixFpixHcalGeom"},
208  "CMSSW_8_1_0_pre12_phase1_newHCAL": {"default": "81X_upgrade2017_HCALdev_v2_HcalGeom"},
209  "CMSSW_8_1_0_pre12_phase1_newBPixHCAL": {"default": "81X_upgrade2017_HCALdev_v2_NewBPix_BpixHcalGeom"},
210  "CMSSW_8_1_0_pre15": {"default": "81X_mcRun2_asymptotic_v11"},
211  "CMSSW_8_1_0_pre15_HIP": {"default": "81X_mcRun2_asymptotic_v11_hip"},
212  "CMSSW_8_1_0_pre15_PU": {"default": "81X_mcRun2_asymptotic_v11_M17"},
213  "CMSSW_8_1_0_pre15_PU_HIP": {"default": "81X_mcRun2_asymptotic_v11_hipM17"},
214  "CMSSW_8_1_0_pre15_phase1": {"default": "81X_upgrade2017_realistic_v17_BpixFpixHcalGeom",
215  "Design": "81X_upgrade2017_design_IdealBS_v1_2017design", "Design_fullsim_25ns": "81X_upgrade2017_design_IdealBS_v1_design"},
216  "CMSSW_8_1_0_pre16": {"default": "81X_mcRun2_asymptotic_v11"},
217  "CMSSW_8_1_0_pre16_phase1": {"default": "81X_upgrade2017_realistic_v22", "Design": "81X_upgrade2017_design_IdealBS_v6"},
218  "CMSSW_8_1_0": {"default": "81X_mcRun2_asymptotic_v12"},
219  "CMSSW_8_1_0_phase1": {"default": "81X_upgrade2017_realistic_v26_HLT2017"},
220  "CMSSW_9_0_0_pre1": {"default": "90X_mcRun2_asymptotic_v0"},
221  "CMSSW_9_0_0_pre1_phase1": {"default": "90X_upgrade2017_realistic_v0",
222  "Design": "90X_upgrade2017_design_IdealBS_v0", "Design_fullsim_25ns": "90X_upgrade2017_design_IdealBS_v0_resub"},
223  "CMSSW_9_0_0_pre2": {"default": "90X_mcRun2_asymptotic_v0"},
224  "CMSSW_9_0_0_pre2_ROOT6": {"default": "90X_mcRun2_asymptotic_v0"},
225  "CMSSW_9_0_0_pre2_phase1": {"default": "90X_upgrade2017_realistic_v0",
226  "Design": "90X_upgrade2017_design_IdealBS_v0", "Design_fullsim_25ns": "90X_upgrade2017_design_IdealBS_v0_resub"},
227  "CMSSW_9_0_0_pre4": {"default": "90X_mcRun2_asymptotic_v1", "fullsim_25ns": "90X_mcRun2_asymptotic_v1_resub"},
228  "CMSSW_9_0_0_pre4_phase1": {"default": "90X_upgrade2017_realistic_v6", "fullsim_25ns_PU50": "Nonexistent",
229  "Design": "90X_upgrade2017_design_IdealBS_v6"},
230  "CMSSW_9_0_0_pre4_GS": {"default": "90X_mcRun2_asymptotic_v1_GSval", "fullsim_25ns": "90X_mcRun2_asymptotic_v1_GSval"},
231  "CMSSW_9_0_0_pre4_phase1_ecalsrb5": {"default": "90X_upgrade2017_realistic_v6_B5"},
232  "CMSSW_9_0_0_pre4_phase1_ecalsrc1": {"default": "90X_upgrade2017_realistic_v6_C1"},
233  "CMSSW_9_0_0_pre4_phase1_ecalsrd7": {"default": "90X_upgrade2017_realistic_v6_D7"},
234  "CMSSW_9_0_0_pre5": {"default": "90X_mcRun2_asymptotic_v4"},
235  "CMSSW_9_0_0_pre5_pmx": {"default": "90X_mcRun2_asymptotic_v4", "fastsim_25ns": "90X_mcRun2_asymptotic_v4_resub"},
236  "CMSSW_9_0_0_pre5_phase1": {"default": "90X_upgrade2017_realistic_v15",
237  "fullsim_25ns_PU35": "90X_upgrade2017_realistic_v15_resub", "fullsim_25ns_PU50": "90X_upgrade2017_realistic_v15_PU50",
238  "Design": "90X_upgrade2017_design_IdealBS_v15"},
239  "CMSSW_9_0_0_pre6": {"default": "90X_mcRun2_asymptotic_v4"},
240  "CMSSW_9_0_0_pre6_phase1": {"default": "90X_upgrade2017_realistic_v15",
241  "fullsim_25ns_PU50": "90X_upgrade2017_realistic_v15_PU50",
242  "Design": "90X_upgrade2017_design_IdealBS_v15"},
243  "CMSSW_9_0_0": {"default": "90X_mcRun2_asymptotic_v5"},
244  "CMSSW_9_0_0_phase1": {"default": "90X_upgrade2017_realistic_v20_resub",
245  "fullsim_25ns_PU50": "90X_upgrade2017_realistic_v20_PU50_resub",
246  "Design": "90X_upgrade2017_design_IdealBS_v19_resub"},
247  "CMSSW_9_0_0_gcc630": {"default": "90X_mcRun2_asymptotic_v5_gcc630"},
248  "CMSSW_9_0_0_phase1_gcc630": {"default": "90X_upgrade2017_realistic_v20_gcc630"},
249  "CMSSW_9_0_0_cc7": {"default": "90X_mcRun2_asymptotic_v5_cc7"},
250  "CMSSW_9_0_0_phase1_cc7": {"default": "90X_upgrade2017_realistic_v20_cc7_rsb"},
251  "CMSSW_9_0_2_phase1": {"default": "90X_upgrade2017_realistic_v20",
252  "fullsim_25ns_PU50": "90X_upgrade2017_realistic_v20_PU50",
253  "Design": "90X_upgrade2017_design_IdealBS_v19"},
254  "CMSSW_9_1_0_pre1": {"default": "90X_mcRun2_asymptotic_v5"},
255  "CMSSW_9_1_0_pre1_phase1": {"default": "90X_upgrade2017_realistic_v20",
256  "fullsim_25ns_PU50": "90X_upgrade2017_realistic_v20_PU50",
257  "Design": "90X_upgrade2017_design_IdealBS_v19_resub"},
258  "CMSSW_9_1_0_pre2": {"default": "90X_mcRun2_asymptotic_v5"},
259  "CMSSW_9_1_0_pre2_phase1": {"default": "90X_upgrade2017_realistic_v20",
260  "fullsim_25ns_PU50": "90X_upgrade2017_realistic_v20_PU50",
261  "Design": "90X_upgrade2017_design_IdealBS_v19"},
262  "CMSSW_9_1_0_pre3": {"default": "91X_mcRun2_asymptotic_v2"},
263  "CMSSW_9_1_0_pre3_phase1": {"default": "91X_upgrade2017_realistic_v3",
264  "fullsim_25ns_PU50": "91X_upgrade2017_realistic_v3_PU50_resub",
265  "Design": "91X_upgrade2017_design_IdealBS_v3"},
266  "CMSSW_9_2_0": {"default": "91X_mcRun2_asymptotic_v3"},
267  "CMSSW_9_2_0_phase1": {"default": "91X_upgrade2017_realistic_v5",
268  "fullsim_25ns_PU50": "91X_upgrade2017_realistic_v5_PU50",
269  "Design": "91X_upgrade2017_design_IdealBS_v5"},
270  "CMSSW_9_2_0_phase1_PXmap": {"default": "91X_upgrade2017_realistic_v5_pixel_ideal_PXgeom"},
271  "CMSSW_9_2_1_phase1": {"default": "92X_upgrade2017_realistic_v1",
272  "fullsim_25ns_PU50": "92X_upgrade2017_realistic_v1_PU50",
273  "Design": "92X_upgrade2017_design_IdealBS_v1"},
274  "CMSSW_9_2_2": {"default": "91X_mcRun2_asymptotic_v3"},
275  "CMSSW_9_2_2_phase1": {"default": "92X_upgrade2017_realistic_v1",
276  "fullsim_25ns_PU50": "92X_upgrade2017_realistic_v1_highPU_AVE50",
277  "Design": "92X_upgrade2017_design_IdealBS_v1"},
278  "CMSSW_9_2_4_run1": {"default": "91X_mcRun1_realistic_v2"},
279  "CMSSW_9_2_4": {"default": "91X_mcRun2_asymptotic_v3"},
280  "CMSSW_9_2_7_phase1": {"default": "92X_upgrade2017_realistic_v7"},
281  "CMSSW_9_3_0_pre1": {"default": "92X_mcRun2_asymptotic_v2"},
282  "CMSSW_9_3_0_pre1_phase1": {"default": "92X_upgrade2017_realistic_v7",
283  "fullsim_25ns_PU50": "92X_upgrade2017_realistic_v7_highPU_AVE50",
284  "Design": "92X_upgrade2017_design_IdealBS_v7"},
285  "CMSSW_9_3_0_pre1_run1": {"default": "92X_mcRun1_realistic_v2"},
286  "CMSSW_9_3_0_pre2": {"default": "92X_mcRun2_asymptotic_v2"},
287  "CMSSW_9_3_0_pre2_phase1": {"default": "92X_upgrade2017_realistic_v7",
288  "fullsim_25ns_PU50": "92X_upgrade2017_realistic_v7_highPU_AVE50_resub",
289  "Design": "92X_upgrade2017_design_IdealBS_v7"},
290  "CMSSW_9_3_0_pre3": {"default": "92X_mcRun2_asymptotic_v2"},
291  "CMSSW_9_3_0_pre3_phase1": {"default": "92X_upgrade2017_realistic_v10_resub",
292  "fullsim_25ns_PU50": "92X_upgrade2017_realistic_v10_highPU_AVE50_resub",
293  "Design": "92X_upgrade2017_design_IdealBS_v10_resub"},
294  "CMSSW_9_3_0_pre3_phase1_pmx": {"default": "92X_upgrade2017_realistic_v10_resub2"},
295  "CMSSW_9_3_0_pre4": {"default": "93X_mcRun2_asymptotic_v0"},
296  "CMSSW_9_3_0_pre4_phase1": {"default": "93X_mc2017_realistic_v1",
297  "fullsim_25ns_PU50": "93X_mc2017_realistic_v1_highPU_AVE50",
298  "Design": "93X_mc2017_design_IdealBS_v1"},
299  "CMSSW_9_3_0_pre5": {"default": "93X_mcRun2_asymptotic_v0"},
300  "CMSSW_9_3_0_pre5_phase1": {"default": "93X_mc2017_realistic_v2",
301  "fullsim_25ns_PU50": "93X_mc2017_realistic_v2_highPU_AVE50",
302  "Design": "93X_mc2017_design_IdealBS_v2"},
303  "CMSSW_9_4_0_pre1": {"default": "93X_mcRun2_asymptotic_v1"},
304  "CMSSW_9_4_0_pre1_phase1": {"default": "93X_mc2017_realistic_v3",
305  "fullsim_25ns_PU50": "93X_mc2017_realistic_v3_highPU_AVE50",
306  "Design": "93X_mc2017_design_IdealBS_v3"},
307  "CMSSW_9_4_0_pre2": {"default": "93X_mcRun2_asymptotic_v2"},
308  "CMSSW_9_4_0_pre2_phase1": {"default": "94X_mc2017_realistic_v1",
309  "fullsim_25ns_PU50": "94X_mc2017_realistic_v1_highPU_AVE50",
310  "Design": "94X_mc2017_design_IdealBS_v0"},
311  "CMSSW_9_4_0_pre3": {"default": "94X_mcRun2_asymptotic_v0"},
312  "CMSSW_9_4_0_pre3_phase1": {"default": "94X_mc2017_realistic_v4",
313  "fullsim_25ns_PU50": "94X_mc2017_realistic_v4_highPU_AVE50",
314  "Design": "94X_mc2017_design_IdealBS_v4"},
315  "CMSSW_9_4_0": {"default": "94X_mcRun2_asymptotic_v0"},
316  "CMSSW_9_4_0_phase1": {"default": "94X_mc2017_realistic_v10",
317  "fullsim_25ns_PU50": "94X_mc2017_realistic_v10_highPU_AVE50",
318  "Design": "94X_mc2017_design_IdealBS_v5"},
319  "CMSSW_10_0_0_pre1": {"default": "94X_mcRun2_asymptotic_v0"},
320  "CMSSW_10_0_0_pre1_phase1": {"default": "94X_mc2017_realistic_v10",
321  "fullsim_25ns_PU50": "94X_mc2017_realistic_v10_highPU_AVE50",
322  "Design": "94X_mc2017_design_IdealBS_v5"},
323  "CMSSW_10_0_0_pre2": {"default": "100X_mcRun2_asymptotic_v2"},
324  "CMSSW_10_0_0_pre2_2017": {"default": "100X_mc2017_realistic_v1",
325  "fullsim_25ns": "100X_mc2017_realistic_v1_resub",
326  "fullsim_25ns_PU50": "100X_mc2017_realistic_v1_highPU_AVE50",
327  "Design": "100X_mc2017_design_IdealBS_v1",
328  "Design_fullsim_25ns_PU50": "Does_not_exist"}, # to avoid 2018 Design PU=50 matching to 2017 Design PU35
329  "CMSSW_10_0_0_pre2_2017_pmx": {"default": "100X_mc2017_realistic_v1"},
330  "CMSSW_10_0_0_pre2_2018": {"default": "100X_upgrade2018_realistic_v1",
331  "fullsim_25ns": "100X_upgrade2018_realistic_v1_resub",
332  "Design": "100X_upgrade2018_design_IdealBS_v1",
333  "Design_fullsim_25ns": "100X_upgrade2018_design_IdealBS_v1_resub"},
334  "CMSSW_10_0_0_pre3": {"default": "100X_mcRun2_asymptotic_v2"},
335  "CMSSW_10_0_0_pre3_2017": {"default": "100X_mc2017_realistic_v1_mahiOFF",
336  "fullsim_25ns_PU50": "100X_mc2017_realistic_v1_highPU_AVE50_mahiOFF",
337  "Design": "100X_mc2017_design_IdealBS_v1_mahiOFF"},
338  "CMSSW_10_0_0_pre3_2018": {"default": "100X_upgrade2018_realistic_v4_mahiOFF",
339  "Design": "100X_upgrade2018_design_IdealBS_v3_mahiOFF"},
340  "CMSSW_10_0_0_pre3_2018_pmx": {"default": "100X_upgrade2018_realistic_v4",
341  "Design": "100X_upgrade2018_design_IdealBS_v3"},
342  "CMSSW_10_0_0_pre3_2017_mahi": {"default": "100X_mc2017_realistic_v1_mahiON",
343  "fullsim_25ns_PU50": "100X_mc2017_realistic_v1_highPU_AVE50_mahiON",
344  "Design": "100X_mc2017_design_IdealBS_v1_mahiON"},
345  "CMSSW_10_0_0_pre3_2018_mahi": {"default": "100X_upgrade2018_realistic_v4_mahiON",
346  "Design": "100X_upgrade2018_design_IdealBS_v3_mahiON"},
347  "CMSSW_10_0_0_pre3_GEANT4_2018_mahi": {"default": "100X_upgrade2018_realistic_v4_mahiON"},
348  "CMSSW_10_0_0_pre3_G4VecGeom2_2018": {"default": "100X_upgrade2018_realistic_v4"},
349 }
350 
351 _releasePostfixes = ["_AlcaCSA14", "_PHYS14", "_TEST", "_v2", "_v3", "_pmx", "_Fall14DR", "_FIXGT", "_PU", "_PXbest", "_PXworst", "_hcal", "_tec", "_71XGENSIM", "_73XGENSIM", "_BS", "_GenSim_7113", "_extended",
352  "_25ns_asymptotic", "_50ns_startup", "_50ns_asympref", "_50ns_asymptotic", "_minimal", "_0T", "_unsch", "_noCCC", "_MT", "_GS", "_rereco", "_pythia8", "_13TeV", "_realGT", "_newGT2", "_newGT", "_phase1", "_phase2", "_2017", "_2018", "_ecal15fb", "_ecal30fb", "_ecalsrb5", "_ecalsrc1", "_ecalsrd7", "_pixDynIneff", "_PXmap", "_gcc530", "_gcc630", "_cc7", "_Tranche4GT", "_newBPixFPixHCAL", "_newBPixFPix", "_newBPixHCAL", "_newBPix", "_newHCAL", "_HIP", "_run1", "_mahi"]
353 def _stripRelease(release):
354  for pf in _releasePostfixes:
355  if pf in release:
356  return _stripRelease(release.replace(pf, ""))
357  return release
358 
359 
360 def _getGlobalTag(sample, release):
361  """Get a GlobalTag.
362 
363  Arguments:
364  sample -- Sample object
365  release -- CMSSW release string
366  """
367  if not release in _globalTags:
368  print("Release %s not found from globaltag map in validation.py" % release)
369  sys.exit(1)
370  gtmap = _globalTags[release]
371  selectedGT = None
372  if sample.hasOverrideGlobalTag():
373  ogt = sample.overrideGlobalTag()
374  if release in ogt:
375  gtmap = _globalTags[ogt[release]]
376  scenario = ""
377  if sample.hasScenario():
378  scenario = sample.scenario()
379  sims = []
380  if sample.fullsim():
381  if sample.pileupEnabled():
382  sim = "fullsim_"+sample.pileupType()
383  sims.extend([
384  sim+"_PU%d"%sample.pileupNumber(),
385  sim
386  ])
387  elif sample.fastsim():
388  sim = "fastsim"
389  if sample.pileupEnabled():
390  sim += "_"+sample.pileupType()
391  sims.append(sim+"_PU%d"%sample.pileupNumber())
392  sims.append(sim)
393 
394  selectedGT = None
395  # First try with scenario+simulation
396  if scenario != "":
397  for sim in sims:
398  selectedGT = gtmap.get(scenario+"_"+sim, None)
399  if selectedGT is not None:
400  break
401  # Then with scenario (but only if sample specifies a scenario)
402  if selectedGT is None:
403  selectedGT = gtmap.get(scenario, None)
404  # Then with simulation
405  if selectedGT is None:
406  for sim in sims:
407  selectedGT = gtmap.get(sim, None)
408  if selectedGT is not None:
409  break
410  # Finally default
411  if selectedGT is None:
412  selectedGT = gtmap["default"]
413 
414  if isinstance(selectedGT, dict):
415  return selectedGT.get(sample.name(), selectedGT["default"])
416  else:
417  return selectedGT
418 
419 # Mapping from release series to RelVal download URLs
420 _relvalUrls = {
421  "6_2_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_6_2_x/",
422  "7_0_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_0_x/",
423  "7_1_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_1_x/",
424  "7_2_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_2_x/",
425  "7_3_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_3_x/",
426  "7_4_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_4_x/",
427  "7_5_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_5_x/",
428  "7_6_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_7_6_x/",
429  "8_0_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_8_0_x/",
430  "8_1_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_8_1_x/",
431  "9_0_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_9_0_x/",
432  "9_1_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_9_1_x/",
433  "9_2_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_9_2_x/",
434  "9_3_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_9_3_x/",
435  "9_4_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_9_4_x/",
436  "10_0_X": "https://cmsweb.cern.ch/dqm/relval/data/browse/ROOT/RelVal/CMSSW_10_0_x/",
437 }
438 
439 _doElectronSamples = [
440  "RelValTTbar",
441  "RelValSingleElectronPt35",
442  "RelValSingleElectronPt10",
443 ]
444 _doConversionSamples = [
445  "RelValTTbar",
446  "RelValH125GGgluonfusion",
447 ]
448 _doBHadronSamples = [
449  "RelValTTbar"
450 ]
451 
452 def _getRelValUrl(release):
453  """Get RelVal download URL for a given release."""
454  version_re = re.compile("CMSSW_(?P<X>\d+)_(?P<Y>\d+)")
455  m = version_re.search(release)
456  if not m:
457  raise Exception("Regex %s does not match to release version %s" % (version_re.pattern, release))
458  version = "%s_%s_X" % (m.group("X"), m.group("Y"))
459  if not version in _relvalUrls:
460  print("No RelVal URL for version %s, please update _relvalUrls" % version)
461  sys.exit(1)
462  return _relvalUrls[version]
463 
464 def _processPlotsForSample(plotterFolder, sample):
465  if plotterFolder.onlyForPileup() and not sample.pileupEnabled():
466  return False
467  if plotterFolder.onlyForElectron() and not sample.doElectron():
468  return False
469  if plotterFolder.onlyForConversion() and not sample.doConversion():
470  return False
471  if plotterFolder.onlyForBHadron() and not sample.doBHadron():
472  return False
473  return True
474 
475 class Sample:
476  """Represents a RelVal sample."""
477  def __init__(self, sample, append=None, midfix=None, putype=None, punum=0,
478  fastsim=False, fastsimCorrespondingFullsimPileup=None,
479  doElectron=None, doConversion=None, doBHadron=None,
480  version="v1", dqmVersion="0001", scenario=None, overrideGlobalTag=None, appendGlobalTag=""):
481  """Constructor.
482 
483  Arguments:
484  sample -- String for name of the sample
485 
486  Keyword arguments
487  append -- String for a variable name within the DWM file names, to be directly appended to sample name (e.g. "HS"; default None)
488  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)
489  putype -- String for pileup type (e.g. "25ns"/"50ns" for FullSim, "AVE20" for FastSim; default None)
490  punum -- String for amount of pileup (default None)
491  fastsim -- Bool indicating the FastSim status (default False)
492  fastsimCorrespondingFullSimPileup -- String indicating what is the FullSim pileup sample corresponding this FastSim sample. Must be set if fastsim=True and putype!=None (default None)
493  doElectron -- Bool specifying if electron-specific plots should be produced (default depends on sample)
494  doConversion -- Bool specifying if conversion-specific plots should be produced (default depends on sample)
495  doBHadron -- Bool specifying if B-hadron-specific plots should be produced (default depends on sample)
496  version -- String for dataset/DQM file version (default "v1")
497  scenario -- Geometry scenario for upgrade samples (default None)
498  overrideGlobalTag -- GlobalTag obtained from release information (in the form of {"release": "actualRelease"}; default None)
499  appendGlobalTag -- String to append to GlobalTag (intended for one-time hacks; default "")
500  """
501  self._sample = sample
502  self._append = append
503  self._midfix = midfix
504  self._putype = putype
505  self._punum = punum
506  self._fastsim = fastsim
507  self._fastsimCorrespondingFullsimPileup = fastsimCorrespondingFullsimPileup
508  self._version = version
509  self._dqmVersion = dqmVersion
510  self._scenario = scenario
511  self._overrideGlobalTag = overrideGlobalTag
512  self._appendGlobalTag = appendGlobalTag
513 
514  if doElectron is not None:
515  self._doElectron = doElectron
516  else:
517  self._doElectron = (sample in _doElectronSamples)
518  if doConversion is not None:
519  self._doConversion = doConversion
520  else:
521  self._doConversion = (sample in _doConversionSamples)
522  if doBHadron is not None:
523  self._doBHadron = doBHadron
524  else:
525  self._doBHadron = (sample in _doBHadronSamples)
526 
527  if self._fastsim and self.hasPileup() and self._fastsimCorrespondingFullsimPileup is None:
529 
530  def digest(self):
531  """Return a tuple uniquely identifying the sample, to be used e.g. as a key to dict"""
532  return (self.name(), self.pileupNumber(), self.pileupType(), self.scenario(), self.fastsim())
533 
534  def sample(self):
535  """Get the sample name"""
536  return self._sample
537 
538  def name(self):
539  """Get the sample name"""
540  return self._sample
541 
542  def label(self):
543  return self._sample
544 
545  def hasPileup(self):
546  """Return True if sample has pileup (for HTML generation)"""
547  return self._putype is not None
548 
549  def pileupEnabled(self):
550  """Return True if pileup plots are enabled (for plot generation)"""
551  return self.hasPileup()
552 
553  def pileup(self):
554  """Return "PU"/"noPU" corresponding the pileup status"""
555  if self.hasPileup():
556  return "PU"
557  else:
558  return "noPU"
559 
560  def pileupType(self, release=None):
561  """Return the pileup type"""
562  if isinstance(self._putype, dict):
563  return self._putype.get(release, self._putype["default"])
564  else:
565  return self._putype
566 
567  def pileupNumber(self):
568  return self._punum
569 
570  def doElectron(self):
571  return self._doElectron
572 
573  def doConversion(self):
574  return self._doConversion
575 
576  def doBHadron(self):
577  return self._doBHadron
578 
579  def version(self, release=None):
580  if isinstance(self._version, dict):
581  return self._version.get(release, self._version["default"])
582  else:
583  return self._version
584 
585  def hasScenario(self):
586  return self._scenario is not None
587 
588  def scenario(self):
589  return self._scenario
590 
592  return self._overrideGlobalTag is not None
593 
594  def overrideGlobalTag(self):
595  return self._overrideGlobalTag
596 
597  def fastsim(self):
598  """Return True for FastSim sample"""
599  return self._fastsim
600 
601  def fullsim(self):
602  """Return True for FullSim sample"""
603  return not self._fastsim
604 
607 
608  def dirname(self, newRepository, newRelease, newSelection):
609  """Return the output directory name
610 
611  Arguments:
612  newRepository -- String for base directory for output files
613  newRelease -- String for CMSSW release
614  newSelection -- String for histogram selection
615  """
616  pileup = ""
617  if self.hasPileup() and not self._fastsim:
618  pileup = "_"+self._putype
619  return "{newRepository}/{newRelease}/{newSelection}{pileup}/{sample}".format(
620  newRepository=newRepository, newRelease=newRelease, newSelection=newSelection,
621  pileup=pileup, sample=sample)
622 
623  def filename(self, newRelease):
624  """Return the DQM file name
625 
626  Arguments:
627  newRelease -- String for CMSSW release
628  """
629  pileup = ""
630  fastsim = ""
631  midfix = ""
632  sample = self._sample
633  if self._append is not None:
634  midfix += self._append
635  if self._midfix is not None:
636  midfix += "_"+self._midfix
637  if self.hasPileup():
638  if self._fastsim:
639  #sample = sample.replace("RelVal", "RelValFS_")
640  # old style
641  #pileup = "PU_"
642  #midfix += "_"+self.pileupType(newRelease)
643  # new style
644  pileup = "PU"+self.pileupType(newRelease)+"_"
645  else:
646  pileup = "PU"+self.pileupType(newRelease)+"_"
647  if self._fastsim:
648  fastsim = "_FastSim"
649 
650  globalTag = _getGlobalTag(self, newRelease)
651 
652  fname = 'DQM_V{dqmVersion}_R000000001__{sample}{midfix}__{newrelease}-{pileup}{globaltag}{appendGlobalTag}{fastsim}-{version}__DQMIO.root'.format(
653  sample=sample, midfix=midfix, newrelease=_stripRelease(newRelease),
654  pileup=pileup, globaltag=globalTag, appendGlobalTag=self._appendGlobalTag, fastsim=fastsim,
655  version=self.version(newRelease), dqmVersion=self._dqmVersion
656  )
657 
658  return fname
659 
660  def datasetpattern(self, newRelease):
661  """Return the dataset pattern
662 
663  Arguments:
664  newRelease -- String for CMSSW release
665  """
666  pileup = ""
667  fastsim = ""
668  digi = ""
669  if self.hasPileup():
670  pileup = "-PU_"
671  if self._fastsim:
672  fastsim = "_FastSim-"
673  digi = "DIGI-"
674  else:
675  fastsim = "*"
676  globalTag = _getGlobalTag(self, newRelease)
677  return "{sample}/{newrelease}-{pileup}{globaltag}{fastsim}{version}/GEN-SIM-{digi}RECO".format(
678  sample=self._sample, newrelease=newRelease,
679  pileup=pileup, globaltag=globalTag, fastsim=fastsim, digi=digi,
680  version=self.version(newRelease)
681  )
682 
684  """Base class for Tracking/Vertex validation."""
685  def __init__(self, fullsimSamples, fastsimSamples, refRelease, refRepository, newRelease, newRepository, newFileModifier=None, selectionName=""):
686  """Constructor.
687 
688  Arguments:
689  fullsimSamples -- List of Sample objects for FullSim samples (may be empty)
690  fastsimSamples -- List of Sample objects for FastSim samples (may be empty)
691  refRelease -- String for reference CMSSW release (can be None for no reference release)
692  newRepository -- String for directory whete to put new files
693  newRelease -- CMSSW release to be validated
694  refRepository -- String for directory where reference root files are
695  newFileModifier -- If given, a function to modify the names of the new files (function takes a string and returns a string)
696  selectionName -- If given, use this string as the selection name (appended to GlobalTag for directory names)
697  """
698  try:
699  self._newRelease = os.environ["CMSSW_VERSION"]
700  except KeyError:
701  print('Error: CMSSW environment variables are not available.', file=sys.stderr)
702  print(' Please run cmsenv', file=sys.stderr)
703  sys.exit()
704 
705  self._fullsimSamples = fullsimSamples
706  self._fastsimSamples = fastsimSamples
707  self._refRelease = refRelease
708  self._refRepository = refRepository
709  self._newRelease = newRelease
710  self._newBaseDir = os.path.join(newRepository, self._newRelease)
711  self._newFileModifier = newFileModifier
712  self._selectionName = selectionName
713 
714  def _getDirectoryName(self, *args, **kwargs):
715  return None
716 
717  def _getSelectionName(self, *args, **kwargs):
718  return self._selectionName
719 
720  def download(self):
721  """Download DQM files. Requires grid certificate and asks your password for it."""
722  filenames = [s.filename(self._newRelease) for s in self._fullsimSamples+self._fastsimSamples]
723  if self._newFileModifier is not None:
724  filenames = list(map(self._newFileModifier, filenames))
725  filenames = [f for f in filenames if not os.path.exists(f)]
726  if len(filenames) == 0:
727  print("All files already downloaded")
728  return
729 
730  relvalUrl = _getRelValUrl(self._newRelease)
731  urls = [relvalUrl+f for f in filenames]
732  certfile = os.path.join(os.environ["HOME"], ".globus", "usercert.pem")
733  if not os.path.exists(certfile):
734  print("Certificate file {certfile} does not exist, unable to download RelVal files from {url}".format(certfile=certfile, url=relvalUrl))
735  sys.exit(1)
736  keyfile = os.path.join(os.environ["HOME"], ".globus", "userkey.pem")
737  if not os.path.exists(certfile):
738  print("Private key file {keyfile} does not exist, unable to download RelVal files from {url}".format(keyfile=keyfile, url=relvalUrl))
739  sys.exit(1)
740 
741  # curl --cert-type PEM --cert $HOME/.globus/usercert.pem --key $HOME/.globus/userkey.pem -k -O <url> -O <url>
742  cmd = ["curl", "--cert-type", "PEM", "--cert", certfile, "--key", keyfile, "-k"]
743  for u in urls:
744  cmd.extend(["-O", u])
745  print("Downloading %d files from RelVal URL %s:" % (len(filenames), relvalUrl))
746  print(" "+"\n ".join(filenames))
747  print("Please provide your private key pass phrase when curl asks it")
748  ret = subprocess.call(cmd)
749  if ret != 0:
750  print("Downloading failed with exit code %d" % ret)
751  sys.exit(1)
752 
753  # verify
754  allFine = True
755  for f in filenames:
756  p = subprocess.Popen(["file", f], stdout=subprocess.PIPE)
757  stdout = p.communicate()[0]
758  if p.returncode != 0:
759  print("file command failed with exit code %d" % p.returncode)
760  sys.exit(1)
761  if not "ROOT" in stdout:
762  print("File {f} is not ROOT, please check the correct version, GlobalTag etc. from {url}".format(f=f, url=relvalUrl))
763  allFine = False
764  if os.path.exists(f):
765  os.remove(f)
766  if not allFine:
767  sys.exit(1)
768 
769  def createHtmlReport(self):
770  return html.HtmlReport(self._newRelease, self._newBaseDir)
771 
772  def doPlots(self, plotter, plotterDrawArgs={}, limitSubFoldersOnlyTo=None, htmlReport=html.HtmlReportDummy(), doFastVsFull=True, doPhase2PU=False):
773  """Create validation plots.
774 
775  Arguments:
776  plotter -- plotting.Plotter object that does the plotting
777 
778  Keyword arguments:
779  plotterDrawArgs -- Dictionary for additional arguments to Plotter.draw() (default: {})
780  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.
781  htmlReport -- Object returned by createHtmlReport(), in case HTML report generation is desired
782  doFastVsFull -- Do FastSim vs. FullSim comparison? (default: True)
783  doPhase2PU -- Do Phase2 PU 200 vs. 140 comparison (default: False)
784  """
785  self._plotter = plotter
786  self._plotterDrawArgs = plotterDrawArgs
787 
788  # New vs. Ref
789  for sample in self._fullsimSamples+self._fastsimSamples:
790  # Check that the new DQM file exists
791  harvestedFile = sample.filename(self._newRelease)
792  if not os.path.exists(harvestedFile):
793  print("Harvested file %s does not exist!" % harvestedFile)
794  sys.exit(1)
795 
796  plotterInstance = plotter.readDirs(harvestedFile)
797  htmlReport.beginSample(sample)
798  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
799  if not _processPlotsForSample(plotterFolder, sample):
800  continue
801  plotFiles = self._doPlots(sample, harvestedFile, plotterFolder, dqmSubFolder, htmlReport)
802  htmlReport.addPlots(plotterFolder, dqmSubFolder, plotFiles)
803 
804  # Fast vs. Full
805  if doFastVsFull:
806  self._doFastsimFastVsFullPlots(limitSubFoldersOnlyTo, htmlReport)
807 
808  # Phase2 PU200 vs. PU 140
809  if doPhase2PU:
810  self._doPhase2PileupPlots(limitSubFoldersOnlyTo, htmlReport)
811 
812  def _doFastsimFastVsFullPlots(self, limitSubFoldersOnlyTo, htmlReport):
813  for fast in self._fastsimSamples:
814  correspondingFull = None
815  for full in self._fullsimSamples:
816  if fast.name() != full.name():
817  continue
818  if fast.pileupEnabled():
819  if not full.pileupEnabled():
820  continue
821  if fast.fastsimCorrespondingFullsimPileup() != full.pileupType():
822  continue
823  else:
824  if full.pileupEnabled():
825  continue
826 
827  if correspondingFull is None:
828  correspondingFull = full
829  else:
830  raise Exception("Got multiple compatible FullSim samples for FastSim sample %s %s" % (fast.name(), fast.pileup()))
831  if correspondingFull is None:
832  print("WARNING: Did not find compatible FullSim sample for FastSim sample %s %s, omitting FastSim vs. FullSim comparison" % (fast.name(), fast.pileup()))
833  continue
834 
835  # If we reach here, the harvestedFile must exist
836  harvestedFile = fast.filename(self._newRelease)
837  plotterInstance = self._plotter.readDirs(harvestedFile)
838  htmlReport.beginSample(fast, fastVsFull=True)
839  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
840  if not _processPlotsForSample(plotterFolder, fast):
841  continue
842  plotFiles = self._doPlotsFastFull(fast, correspondingFull, plotterFolder, dqmSubFolder, htmlReport)
843  htmlReport.addPlots(plotterFolder, dqmSubFolder, plotFiles)
844 
845  def _doPhase2PileupPlots(self, limitSubFoldersOnlyTo, htmlReport):
846  def _stripScenario(name):
847  puindex = name.find("PU")
848  if puindex < 0:
849  return name
850  return name[:puindex]
851 
852  pu140samples = {}
853  for sample in self._fullsimSamples:
854  if sample.pileupNumber() == 140:
855  key = (sample.name(), _stripScenario(sample.scenario()))
856  if key in pu140samples:
857  raise Exception("Duplicate entry for sample %s in scenario %s" % (sample.name(), sample.scenar()))
858  pu140samples[key] = sample
859 
860  for sample in self._fullsimSamples:
861  if sample.pileupNumber() != 200:
862  continue
863  key = (sample.name(), _stripScenario(sample.scenario()))
864  if not key in pu140samples:
865  continue
866 
867  sample_pu140 = pu140samples[key]
868 
869  # If we reach here, the harvestedFile must exist
870  harvestedFile = sample.filename(self._newRelease)
871  plotterInstance = self._plotter.readDirs(harvestedFile)
872  htmlReport.beginSample(sample, pileupComparison="vs. PU140")
873  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
874  if not _processPlotsForSample(plotterFolder, sample):
875  continue
876  plotFiles = self._doPlotsPileup(sample_pu140, sample, plotterFolder, dqmSubFolder, htmlReport)
877  htmlReport.addPlots(plotterFolder, dqmSubFolder, plotFiles)
878 
879 
880  def _getRefFileAndSelection(self, sample, plotterFolder, dqmSubFolder, selectionNameBase, valname):
881  if self._refRelease is None:
882  return (None, "")
883 
884  refGlobalTag = _getGlobalTag(sample, self._refRelease)
885  def _createRefSelection(selectionName):
886  sel = refGlobalTag+selectionNameBase+selectionName
887  if sample.pileupEnabled():
888  refPu = sample.pileupType(self._refRelease)
889  if refPu != "":
890  sel += "_"+refPu
891  return sel
892  refSelection = _createRefSelection(plotterFolder.getSelectionName(dqmSubFolder))
893 
894  # Construct reference directory name, and open reference file it it exists
895  refValFile = None
896  triedRefValFiles = []
897  tmp = [self._refRepository, self._refRelease]
898  if sample.fastsim():
899  tmp.extend(["fastsim", self._refRelease])
900  for selName in plotterFolder.getSelectionNameIterator(dqmSubFolder):
901  refSel = _createRefSelection(selName)
902  refdir = os.path.join(*(tmp+[refSel, sample.name()]))
903 
904  # Open reference file if it exists
905  refValFilePath = os.path.join(refdir, valname)
906  if os.path.exists(refValFilePath):
907  refSelection = refSel
908  refValFile = ROOT.TFile.Open(refValFilePath)
909  break
910  else:
911  triedRefValFiles.append(refValFilePath)
912  if refValFile is None:
913  if len(triedRefValFiles) == 1:
914  if plotting.verbose:
915  print("Reference file %s not found" % triedRefValFiles[0])
916  else:
917  if plotting.verbose:
918  print("None of the possible reference files %s not found" % ",".join(triedRefValFiles))
919 
920  return (refValFile, refSelection)
921 
922  def _doPlots(self, sample, harvestedFile, plotterFolder, dqmSubFolder, htmlReport):
923  """Do the real plotting work for a given sample and DQM subfolder"""
924  # Get GlobalTags
925  newGlobalTag = _getGlobalTag(sample, self._newRelease)
926 
927  # Construct selection string
928  selectionNameBase = "_"+sample.pileup()
929  newSelection = newGlobalTag+selectionNameBase+plotterFolder.getSelectionName(dqmSubFolder)
930  if sample.pileupEnabled():
931  newPu = sample.pileupType(self._newRelease)
932  if newPu != "":
933  newSelection += "_"+newPu
934 
935  valname = "val.{sample}.root".format(sample=sample.name())
936 
937  # Construct reference file and selection string
938  (refValFile, refSelection) = self._getRefFileAndSelection(sample, plotterFolder, dqmSubFolder, selectionNameBase, valname)
939 
940  # Construct new directory name
941  tmp = []
942  if sample.fastsim():
943  tmp.extend(["fastsim", self._newRelease])
944  tmp.extend([newSelection, sample.name()])
945  newsubdir = os.path.join(*tmp)
946  newdir = os.path.join(self._newBaseDir, newsubdir)
947  if not os.path.exists(newdir):
948  os.makedirs(newdir)
949  valnameFullPath = os.path.join(newdir, valname)
950 
951  # Copy the relevant histograms to a new validation root file
952  # TODO: treat the case where dqmSubFolder is empty
953  newValFile = _copySubDir(harvestedFile, valnameFullPath, plotterFolder.getPossibleDQMFolders(), dqmSubFolder.subfolder if dqmSubFolder is not None else None)
954  fileList = []
955 
956  # Do the plots
957  if plotting.verbose:
958  print("Comparing ref and new {sim} {sample} {translatedFolder}".format(
959  sim="FullSim" if not sample.fastsim() else "FastSim",
960  sample=sample.name(), translatedFolder=str(dqmSubFolder.translated) if dqmSubFolder is not None else ""))
961  rootFiles = [refValFile, newValFile]
962  legendLabels = [
963  "%s, %s %s" % (sample.name(), _stripRelease(self._refRelease), refSelection) if self._refRelease is not None else "dummy",
964  "%s, %s %s" % (sample.name(), _stripRelease(self._newRelease), newSelection)
965  ]
966  plotterFolder.create(rootFiles, legendLabels, dqmSubFolder, isPileupSample=sample.pileupEnabled())
967  fileList.extend(plotterFolder.draw(directory=newdir, **self._plotterDrawArgs))
968  # Copy val file only if there were plots
969  if len(fileList) > 0:
970  fileList.append(valnameFullPath)
971 
972  # For tables we just try them all, and see which ones succeed
973  for tableCreator in plotterFolder.getTableCreators():
974  htmlReport.addTable(tableCreator.create(rootFiles, legendLabels, dqmSubFolder))
975 
976  newValFile.Close()
977  if refValFile is not None:
978  refValFile.Close()
979 
980  if len(fileList) == 0:
981  print("No object found in %s" % plotterFolder.getName())
982  return []
983 
984  dups = _findDuplicates(fileList)
985  if len(dups) > 0:
986  print("Plotter produced multiple files with names", ", ".join(dups))
987  print("Typically this is a naming problem in the plotter configuration")
988  sys.exit(1)
989 
990  # Move plots to new directory
991  print("Created plots and %s in %s" % (valname, newdir))
992  return list(map(lambda n: n.replace(newdir, newsubdir), fileList))
993 
994  def _doPlotsFastFull(self, fastSample, fullSample, plotterFolder, dqmSubFolder, htmlReport):
995  """Do the real plotting work for FastSim vs. FullSim for a given algorithm, quality flag, and sample."""
996  # Get GlobalTags
997  fastGlobalTag = _getGlobalTag(fastSample, self._newRelease)
998  fullGlobalTag = _getGlobalTag(fullSample, self._newRelease)
999 
1000  # Construct selection string
1001  tmp = plotterFolder.getSelectionName(dqmSubFolder)
1002  fastSelection = fastGlobalTag+"_"+fastSample.pileup()+tmp
1003  fullSelection = fullGlobalTag+"_"+fullSample.pileup()+tmp
1004  if fullSample.pileupEnabled():
1005  fullSelection += "_"+fullSample.pileupType(self._newRelease)
1006  fastSelection += "_"+fastSample.pileupType(self._newRelease)
1007 
1008  # Construct directories for FastSim, FullSim, and for the results
1009  fastdir = os.path.join(self._newBaseDir, "fastsim", self._newRelease, fastSelection, fastSample.name())
1010  fulldir = os.path.join(self._newBaseDir, fullSelection, fullSample.name())
1011  newsubdir = os.path.join("fastfull", self._newRelease, fastSelection, fastSample.name())
1012  newdir = os.path.join(self._newBaseDir, newsubdir)
1013  if not os.path.exists(newdir):
1014  os.makedirs(newdir)
1015 
1016  # Open input root files
1017  valname = "val.{sample}.root".format(sample=fastSample.name())
1018  fastValFilePath = os.path.join(fastdir, valname)
1019  if not os.path.exists(fastValFilePath) and plotting.verbose:
1020  print("FastSim file %s not found" % fastValFilePath)
1021  fullValFilePath = os.path.join(fulldir, valname)
1022  if not os.path.exists(fullValFilePath) and plotting.verbose:
1023  print("FullSim file %s not found" % fullValFilePath)
1024 
1025  fastValFile = ROOT.TFile.Open(fastValFilePath)
1026  fullValFile = ROOT.TFile.Open(fullValFilePath)
1027 
1028  # Do plots
1029  if plotting.verbose:
1030  print("Comparing FullSim and FastSim {sample} {translatedFolder}".format(
1031  sample=fastSample.name(), translatedFolder=str(dqmSubFolder.translated) if dqmSubFolder is not None else ""))
1032  rootFiles = [fullValFile, fastValFile]
1033  legendLabels = [
1034  "FullSim %s, %s %s" % (fullSample.name(), _stripRelease(self._newRelease), fullSelection),
1035  "FastSim %s, %s %s" % (fastSample.name(), _stripRelease(self._newRelease), fastSelection),
1036  ]
1037  plotterFolder.create(rootFiles, legendLabels, dqmSubFolder, isPileupSample=fastSample.pileupEnabled(), requireAllHistograms=True)
1038  fileList = plotterFolder.draw(directory=newdir, **self._plotterDrawArgs)
1039 
1040  # For tables we just try them all, and see which ones succeed
1041  for tableCreator in plotterFolder.getTableCreators():
1042  htmlReport.addTable(tableCreator.create(rootFiles, legendLabels, dqmSubFolder))
1043 
1044  fullValFile.Close()
1045  fastValFile.Close()
1046 
1047  if len(fileList) == 0:
1048  print("No object found in %s" % plotterFolder.getName())
1049  return []
1050 
1051  dups = _findDuplicates(fileList)
1052  if len(dups) > 0:
1053  print("Plotter produced multiple files with names", ", ".join(dups))
1054  print("Typically this is a naming problem in the plotter configuration")
1055  sys.exit(1)
1056 
1057  # Move plots to new directory
1058  print("Created plots in %s" % (newdir))
1059  return list(map(lambda n: n.replace(newdir, newsubdir), fileList))
1060 
1061  def _doPlotsPileup(self, pu140Sample, pu200Sample, plotterFolder, dqmSubFolder, htmlReport):
1062  """Do the real plotting work for two pileup scenarios for a given algorithm, quality flag, and sample."""
1063  # Get GlobalTags
1064  pu140GlobalTag = _getGlobalTag(pu140Sample, self._newRelease)
1065  pu200GlobalTag = _getGlobalTag(pu200Sample, self._newRelease)
1066 
1067  # Construct selection string
1068  tmp = plotterFolder.getSelectionName(dqmSubFolder)
1069  pu140Selection = pu140GlobalTag+"_"+pu140Sample.pileup()+tmp+"_"+pu140Sample.pileupType(self._newRelease)
1070  pu200Selection = pu200GlobalTag+"_"+pu200Sample.pileup()+tmp+"_"+pu200Sample.pileupType(self._newRelease)
1071 
1072  # Construct directories for
1073  pu140dir = os.path.join(self._newBaseDir, pu140Selection, pu140Sample.name())
1074  pu200dir = os.path.join(self._newBaseDir, pu200Selection, pu200Sample.name())
1075  newsubdir = os.path.join("pileup", self._newRelease, pu200Selection, pu200Sample.name())
1076  newdir = os.path.join(self._newBaseDir, newsubdir)
1077  if not os.path.exists(newdir):
1078  os.makedirs(newdir)
1079 
1080  # Open input root files
1081  valname = "val.{sample}.root".format(sample=pu140Sample.name())
1082  pu140ValFilePath = os.path.join(pu140dir, valname)
1083  if not os.path.exists(pu140ValFilePath):
1084  if plotting.verbose:
1085  print("PU140 file %s not found" % pu140ValFilePath)
1086  return []
1087  pu200ValFilePath = os.path.join(pu200dir, valname)
1088  if not os.path.exists(pu200ValFilePath):
1089  if plotting.verbose:
1090  print("PU200 file %s not found" % pu200ValFilePath)
1091  return []
1092 
1093  pu140ValFile = ROOT.TFile.Open(pu140ValFilePath)
1094  pu200ValFile = ROOT.TFile.Open(pu200ValFilePath)
1095 
1096  # Do plots
1097  if plotting.verbose:
1098  print("Comparing PU140 and PU200 {sample} {translatedFolder}".format(
1099  sample=pu200Sample.name(), translatedFolder=str(dqmSubFolder.translated) if dqmSubFolder is not None else ""))
1100  rootFiles = [pu140ValFile, pu200ValFile]
1101  legendLabels = [
1102  "%s, %s %s" % (pu140Sample.name(), _stripRelease(self._newRelease), pu140Selection),
1103  "%s, %s %s" % (pu200Sample.name(), _stripRelease(self._newRelease), pu200Selection),
1104  ]
1105  plotterFolder.create(rootFiles, legendLabels, dqmSubFolder, isPileupSample=pu140Sample.pileupEnabled(), requireAllHistograms=True)
1106  fileList = plotterFolder.draw(directory=newdir, **self._plotterDrawArgs)
1107 
1108  # For tables we just try them all, and see which ones succeed
1109  for tableCreator in plotterFolder.getTableCreators():
1110  htmlReport.addTable(tableCreator.create(rootFiles, legendLabels, dqmSubFolder))
1111 
1112  pu200ValFile.Close()
1113  pu140ValFile.Close()
1114 
1115  if len(fileList) == 0:
1116  print("No object found in %s" % plotterFolder.getName())
1117  return []
1118 
1119  dups = _findDuplicates(fileList)
1120  if len(dups) > 0:
1121  print("Plotter produced multiple files with names", ", ".join(dups))
1122  print("Typically this is a naming problem in the plotter configuration")
1123  sys.exit(1)
1124 
1125  # Move plots to new directory
1126  print("Created plots in %s" % (newdir))
1127  return list(map(lambda n: n.replace(newdir, newsubdir), fileList))
1128 
1129 
1130 def _copySubDir(oldfile, newfile, basenames, dirname):
1131  """Copy a subdirectory from oldfile to newfile.
1132 
1133  Arguments:
1134  oldfile -- String for source TFile
1135  newfile -- String for destination TFile
1136  basenames -- List of strings for base directories, first existing one is picked
1137  dirname -- String for directory name under the base directory
1138  """
1139  oldf = ROOT.TFile.Open(oldfile)
1140 
1141  dirold = None
1142  for basename in basenames:
1143  dirold = oldf.GetDirectory(basename)
1144  if dirold:
1145  break
1146  if not dirold:
1147  raise Exception("Did not find any of %s directories from file %s" % (",".join(basenames), oldfile))
1148  if dirname:
1149  d = dirold.Get(dirname)
1150  if not d:
1151  raise Exception("Did not find directory %s under %s" % (dirname, dirold.GetPath()))
1152  dirold = d
1153 
1154  newf = ROOT.TFile.Open(newfile, "RECREATE")
1155  dirnew = newf
1156  for d in basenames[0].split("/"):
1157  dirnew = dirnew.mkdir(d)
1158  if dirname:
1159  dirnew = dirnew.mkdir(dirname)
1160  _copyDir(dirold, dirnew)
1161 
1162  oldf.Close()
1163  return newf
1164 
1165 def _copyDir(src, dst):
1166  """Copy non-TTree objects from src TDirectory to dst TDirectory."""
1167  keys = src.GetListOfKeys()
1168  for key in keys:
1169  classname = key.GetClassName()
1170  cl = ROOT.TClass.GetClass(classname)
1171  if not cl:
1172  continue
1173  if not (cl.InheritsFrom("TTree") and cl.InheritsFrom("TDirectory")):
1174  dst.cd()
1175  obj = key.ReadObj()
1176  obj.Write()
1177  obj.Delete()
1178 
1180  found = set()
1181  found2 = set()
1182  for x in lst:
1183  if x in found:
1184  found2.add(x)
1185  else:
1186  found.add(x)
1187  return list(found2)
1188 
1189 def _doPlotsForPlotter(self, plotter, sample, limitSubFoldersOnlyTo=None):
1190  plotterInstance = plotter.readDirs(*self._openFiles)
1191  manager = multiprocessing.Manager()
1192  return_dict = manager.dict()
1193  proc = []
1194  iProc = 0
1195 
1196  for plotterFolder, dqmSubFolder in plotterInstance.iterFolders(limitSubFoldersOnlyTo=limitSubFoldersOnlyTo):
1197  if sample is not None and not _processPlotsForSample(plotterFolder, sample):
1198  continue
1199  newsubdir = self._subdirprefix+plotterFolder.getSelectionName(dqmSubFolder)
1200  newdir = os.path.join(self._newdir, newsubdir)
1201  if not os.path.exists(newdir):
1202  os.makedirs(newdir, exist_ok=True)
1203 
1204  plotterFolder.create(self._openFiles, self._labels, dqmSubFolder)
1205  p = multiprocessing.Process(target=self._doPlots, args=(plotterFolder, dqmSubFolder, newsubdir, newdir, iProc, return_dict))
1206  proc.append((plotterFolder, dqmSubFolder, p))
1207  p.start()
1208  iProc += 1
1209 
1210  for i in range(iProc):
1211  proc[i][2].join()
1212  if len(return_dict[i]) > 0:
1213  self._htmlReport.addPlots(proc[i][0], proc[i][1], return_dict[i])
1214 
1216  def __init__(self, label, name, fileLegends, pileup=True, customPileupLabel=""):
1217  self._label = label
1218  self._name = name
1219  self._fileLegends = fileLegends
1220  self._pileup = pileup
1221  self._customPileupLabel = customPileupLabel
1222 
1223  def digest(self):
1224  # Label should be unique among the plotting run, so it serves also as the digest
1225  return self._label
1226 
1227  def label(self):
1228  return self._label
1229 
1230  def name(self):
1231  return self._name
1232 
1233  def files(self):
1234  return [t[0] for t in self._fileLegends]
1235 
1236  def legendLabels(self):
1237  return [t[1] for t in self._fileLegends]
1238 
1239  def fastsim(self):
1240  # No need to emulate the release validation fastsim behaviour here
1241  return False
1242 
1243  def pileupEnabled(self):
1244  return self._pileup
1245 
1247  return self._customPileupLabel
1248 
1249  def doElectron(self):
1250  return True
1251 
1252  def doConversion(self):
1253  return True
1254 
1255  def doBHadron(self):
1256  return True
1257 
1259  def __init__(self, samples, newdir):
1260  self._samples = samples
1261  self._newdir = newdir
1262  if not os.path.exists(newdir):
1263  os.makedirs(newdir)
1264 
1266 
1267  def createHtmlReport(self, validationName=""):
1268  if hasattr(self._htmlReport, "write"):
1269  raise Exception("HTML report object already created. There is probably some logic error in the calling code.")
1270  self._htmlReport = html.HtmlReport(validationName, self._newdir)
1271  return self._htmlReport
1272 
1273  def doPlots(self, plotters, plotterDrawArgs={}, **kwargs):
1274  self._plotterDrawArgs = plotterDrawArgs
1275 
1276  for sample in self._samples:
1277  self._subdirprefix = sample.label()
1278  self._labels = sample.legendLabels()
1279  self._htmlReport.beginSample(sample)
1280 
1281  self._openFiles = []
1282  for f in sample.files():
1283  if os.path.exists(f):
1284  self._openFiles.append(ROOT.TFile.Open(f))
1285  else:
1286  print("File %s not found (from sample %s), ignoring it" % (f, sample.name()))
1287  self._openFiles.append(None)
1288 
1289  for plotter in plotters:
1290  _doPlotsForPlotter(self, plotter, sample, **kwargs)
1291 
1292  for tf in self._openFiles:
1293  if tf is not None:
1294  tf.Close()
1295  self._openFiles = []
1296 
1297  def _doPlots(self, plotterFolder, dqmSubFolder, newsubdir, newdir, iProc, return_dict):
1298  fileList = plotterFolder.draw(directory=newdir, **self._plotterDrawArgs)
1299 
1300  if len(fileList) == 0:
1301  print("No object found in %s" % plotterFolder.getName())
1302 
1303  for tableCreator in plotterFolder.getTableCreators():
1304  self._htmlReport.addTable(tableCreator.create(self._openFiles, self._labels, dqmSubFolder))
1305 
1306  dups = _findDuplicates(fileList)
1307  if len(dups) > 0:
1308  print("Plotter produced multiple files with names", ", ".join(dups))
1309  print("Typically this is a naming problem in the plotter configuration")
1310  sys.exit(1)
1311 
1312  if self._plotterDrawArgs.get("separate", False):
1313  if not os.path.exists("%s/res"%newdir):
1314  os.makedirs("%s/res"%newdir)
1315  downloadables = ["index.php", "res/jquery-ui.js", "res/jquery.js", "res/style.css", "res/style.js", "res/theme.css"]
1316  for d in downloadables:
1317  if not os.path.exists("%s/%s" % (newdir,d)):
1318  urllib.request.urlretrieve("https://raw.githubusercontent.com/musella/php-plots/master/%s"%d, "%s/%s"%(newdir,d))
1319 
1320  print("Created plots in %s" % newdir)
1321  return_dict[iProc] = list(map(lambda n: n.replace(newdir, newsubdir), fileList))
1322 
1324  #Similar to the SimpleValidation
1325  #To be used only if `--separate` option is on
1326  def __init__(self, samples, newdir):
1327  self._samples = samples
1328  self._newdir = newdir
1329  if not os.path.exists(newdir):
1330  os.makedirs(newdir)
1331 
1333 
1334  def createHtmlReport(self, validationName=""):
1335  if hasattr(self._htmlReport, "write"):
1336  raise Exception("HTML report object already created. There is probably some logic error in the calling code.")
1337  self._htmlReport = html.HtmlReport(validationName, self._newdir)
1338  return self._htmlReport
1339 
1340  def doPlots(self, plotters, plotterDrawArgs={}, **kwargs):
1341  self._plotterDrawArgs = plotterDrawArgs
1342 
1343  for sample in self._samples:
1344  self._subdirprefix = sample.label()
1345  self._labels = sample.legendLabels()
1346  self._htmlReport.beginSample(sample)
1347 
1348  self._openFiles = []
1349  for f in sample.files():
1350  if os.path.exists(f):
1351  self._openFiles.append(ROOT.TFile.Open(f))
1352  else:
1353  print("File %s not found (from sample %s), ignoring it" % (f, sample.name()))
1354  self._openFiles.append(None)
1355 
1356  for plotter in plotters:
1357  _doPlotsForPlotter(self, plotter, sample, **kwargs)
1358 
1359  for tf in self._openFiles:
1360  if tf is not None:
1361  tf.Close()
1362  self._openFiles = []
1363 
1364  def _doPlots(self, plotterFolder, dqmSubFolder, newsubdir, newdir, iProc, return_dict):
1365  fileList = plotterFolder.draw(directory=newdir, **self._plotterDrawArgs)
1366 
1367  # check if plots are produced
1368  if len(fileList) == 0:
1369  print("No object found in %s" % plotterFolder.getName())
1370 
1371  # check if there are duplicated plot
1372  dups = _findDuplicates(fileList)
1373  if len(dups) > 0:
1374  print("Plotter produced multiple files with names", ", ".join(dups))
1375  print("Typically this is a naming problem in the plotter configuration")
1376  sys.exit(1)
1377 
1378  linkList = []
1379  for f in fileList:
1380  if f[:f.rfind("/")] not in linkList :
1381  if str(f[:f.rfind("/")]) != str(newdir) :
1382  linkList.append(f[:f.rfind("/")])
1383 
1384  for tableCreator in plotterFolder.getTableCreators():
1385  self._htmlReport.addTable(tableCreator.create(self._openFiles, self._labels, dqmSubFolder))
1386 
1387  for link in linkList :
1388  if not os.path.exists("%s/res"%link):
1389  os.makedirs("%s/res"%link)
1390  downloadables = ["index.php", "res/jquery-ui.js", "res/jquery.js", "res/style.css", "res/style.js", "res/theme.css"]
1391  for d in downloadables:
1392  if not os.path.exists("%s/%s" % (link,d)):
1393  urllib.request.urlretrieve("https://raw.githubusercontent.com/rovere/php-plots/master/%s"%d, "%s/%s"%(link,d))
1394 
1395  print("Created separated plots in %s" % newdir)
1396  return_dict[iProc] = list(map(lambda n: n.replace(newdir, newsubdir), linkList))
_fastsimCorrespondingFullsimPileup
Definition: validation.py:507
def _copySubDir
Definition: validation.py:1130
def _getGlobalTag
Definition: validation.py:360
def _stripRelease
Definition: validation.py:353
def _findDuplicates
Definition: validation.py:1179
const uint16_t range(const Frame &aFrame)
def fastsimCorrespondingFullsimPileup
Definition: validation.py:605
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
def _processPlotsForSample
Definition: validation.py:464
static std::string join(char **cmd)
Definition: RemoteFile.cc:19
#define str(s)
def _doPlotsForPlotter
Definition: validation.py:1189
def _getRelValUrl
Definition: validation.py:452