File indexing completed on 2023-03-17 10:40:24
0001 from __future__ import absolute_import
0002 from builtins import range
0003 import os
0004 import random
0005
0006 from . import globalDictionaries
0007 from . import configTemplates
0008
0009 from .genericValidation import ValidationMetaClass, ValidationWithComparison, ValidationWithPlots
0010 from .helperFunctions import getCommandOutput2, replaceByMap, cppboolstring
0011 from .offlineValidation import OfflineValidation
0012 from .primaryVertexValidation import PrimaryVertexValidation
0013 from .primaryVertexResolution import PrimaryVertexResolution
0014 from .TkAlExceptions import AllInOneError
0015 from .trackSplittingValidation import TrackSplittingValidation
0016 from .zMuMuValidation import ZMuMuValidation
0017 from .overlapValidation import OverlapValidation
0018
0019 class BasePlottingOptions(object, metaclass=ValidationMetaClass):
0020 defaults = {
0021 "cmssw" : os.environ["CMSSW_BASE"],
0022 "publicationstatus" : "",
0023 "customtitle" : "",
0024 "customrighttitle" : "",
0025 "era" : "NONE",
0026 "legendheader" : "",
0027 "legendoptions":"all",
0028 }
0029 mandatories = set()
0030 needpackages = {"Alignment/OfflineValidation"}
0031 def __init__(self, config, valType):
0032 import random
0033 self.type = valType
0034 self.general = config.getGeneral()
0035 self.randomWorkdirPart = "%0i"%random.randint(1,10e9)
0036 self.config = config
0037
0038 theUpdate = config.getResultingSection("plots:"+self.type,
0039 defaultDict = self.defaults,
0040 demandPars = self.mandatories)
0041 self.general.update(theUpdate)
0042
0043 self.cmssw = self.general["cmssw"]
0044 badcharacters = r"\'"
0045 for character in badcharacters:
0046 if character in self.cmssw:
0047 raise AllInOneError("The bad characters " + badcharacters + " are not allowed in the cmssw\n"
0048 "path name. If you really have it in such a ridiculously named location,\n"
0049 "try making a symbolic link somewhere with a decent name.")
0050 try:
0051 os.listdir(self.cmssw)
0052 except OSError:
0053 raise AllInOneError("Your cmssw release " + self.cmssw + ' does not exist')
0054
0055 if self.cmssw == os.environ["CMSSW_BASE"]:
0056 self.scramarch = os.environ["SCRAM_ARCH"]
0057 self.cmsswreleasebase = os.environ["CMSSW_RELEASE_BASE"]
0058 else:
0059 command = ("cd '" + self.cmssw + "' && eval `scramv1 ru -sh 2> /dev/null`"
0060 ' && echo "$CMSSW_BASE\n$SCRAM_ARCH\n$CMSSW_RELEASE_BASE"')
0061 commandoutput = getCommandOutput2(command).split('\n')
0062 self.cmssw = commandoutput[0]
0063 self.scramarch = commandoutput[1]
0064 self.cmsswreleasebase = commandoutput[2]
0065
0066 for package in self.needpackages:
0067 for placetolook in self.cmssw, self.cmsswreleasebase:
0068 pkgpath = os.path.join(placetolook, "src", package)
0069 if os.path.exists(pkgpath):
0070 self.general[package] = pkgpath
0071 break
0072 else:
0073 raise AllInOneError("Package {} does not exist in {} or {}!".format(package, self.cmssw, self.cmsswreleasebase))
0074
0075 self.general["publicationstatus"] = self.general["publicationstatus"].upper()
0076 self.general["era"] = self.general["era"].upper()
0077
0078 if not self.general["publicationstatus"] and not self.general["customtitle"]:
0079 self.general["publicationstatus"] = "INTERNAL"
0080 if self.general["customtitle"] and not self.general["publicationstatus"]:
0081 self.general["publicationstatus"] = "CUSTOM"
0082
0083 if self.general["publicationstatus"] != "CUSTOM" and self.general["customtitle"]:
0084 raise AllInOneError("If you would like to use a custom title, please leave out the 'publicationstatus' parameter")
0085 if self.general["publicationstatus"] == "CUSTOM" and not self.general["customtitle"]:
0086 raise AllInOneError("If you want to use a custom title, you should provide it using 'customtitle' in the [plots:%s] section" % valType)
0087
0088 if self.general["era"] != "NONE" and self.general["customrighttitle"]:
0089 raise AllInOneError("If you would like to use a custom right title, please leave out the 'era' parameter")
0090
0091 publicationstatusenum = ["INTERNAL", "INTERNAL_SIMULATION", "PRELIMINARY", "PUBLIC", "SIMULATION", "UNPUBLISHED", "CUSTOM"]
0092 eraenum = ["NONE", "CRUZET15", "CRAFT15", "COLL0T15"]
0093 if self.general["publicationstatus"] not in publicationstatusenum:
0094 raise AllInOneError("Publication status must be one of " + ", ".join(publicationstatusenum) + "!")
0095 if self.general["era"] not in eraenum:
0096 raise AllInOneError("Era must be one of " + ", ".join(eraenum) + "!")
0097
0098 knownOpts = set(self.defaults.keys())|self.mandatories|self.optionals
0099 ignoreOpts = []
0100 config.checkInput("plots:"+self.type,
0101 knownSimpleOptions = knownOpts,
0102 ignoreOptions = ignoreOpts)
0103
0104 def getRepMap(self):
0105 result = self.general
0106 result.update({
0107 "workdir": os.path.join(self.general["workdir"],
0108 self.randomWorkdirPart),
0109 "datadir": self.general["datadir"],
0110 "logdir": self.general["logdir"],
0111 "CMSSW_BASE": self.cmssw,
0112 "SCRAM_ARCH": self.scramarch,
0113 "CMSSW_RELEASE_BASE": self.cmsswreleasebase,
0114 "validationId": self.validationclass.__name__,
0115 })
0116 if issubclass(self.validationclass, ValidationWithPlots):
0117 result["plottingscriptname"] = self.validationclass.plottingscriptname()
0118 result["plottingscriptpath"] = ".oO[scriptsdir]Oo./.oO[plottingscriptname]Oo."
0119 result["PlotsDirName"] = self.validationclass.plotsdirname()
0120 if issubclass(self.validationclass, ValidationWithComparison):
0121 result["compareAlignmentsPath"] = self.validationclass.comparealignmentspath()
0122 result["compareAlignmentsName"] = self.validationclass.comparealignmentsname()
0123 return result
0124
0125 class PlottingOptionsTrackSplitting(BasePlottingOptions):
0126 defaults = {
0127 "outliercut": "-1.0",
0128 "subdetector": "none",
0129 }
0130 needpackages = {"Alignment/CommonAlignmentProducer"}
0131 validationclass = TrackSplittingValidation
0132 def __init__(self, config):
0133 super(PlottingOptionsTrackSplitting, self).__init__(config, "split")
0134 validsubdets = self.validsubdets()
0135 if self.general["subdetector"] not in validsubdets:
0136 raise AllInOneError("'%s' is not a valid subdetector!\n" % self.general["subdetector"] + "The options are: " + ", ".join(validsubdets))
0137
0138 def validsubdets(self):
0139 filename = replaceByMap(".oO[Alignment/CommonAlignmentProducer]Oo./python/AlignmentTrackSelector_cfi.py", self.getRepMap())
0140 with open(filename) as f:
0141 trackselector = f.read()
0142
0143 minhitspersubdet = trackselector.split("minHitsPerSubDet")[1].split("(",1)[1]
0144
0145 parenthesesdepth = 0
0146 i = 0
0147 for character in minhitspersubdet:
0148 if character == "(":
0149 parenthesesdepth += 1
0150 if character == ")":
0151 parenthesesdepth -= 1
0152 if parenthesesdepth < 0:
0153 break
0154 i += 1
0155 minhitspersubdet = minhitspersubdet[0:i]
0156
0157 results = minhitspersubdet.split(",")
0158 empty = []
0159 for i in range(len(results)):
0160 results[i] = results[i].split("=")[0].strip().replace("in", "", 1)
0161
0162 results.append("none")
0163
0164 return [a for a in results if a]
0165
0166 class PlottingOptionsZMuMu(BasePlottingOptions):
0167 defaults = {
0168 "resonance": "Z",
0169 "switchONfit": "false",
0170 "rebinphi": "4",
0171 "rebinetadiff": "2",
0172 "rebineta": "2",
0173 "rebinpt": "8",
0174 "AutoSetRange": "false",
0175 }
0176 needpackages = {"MuonAnalysis/MomentumScaleCalibration"}
0177 validationclass = ZMuMuValidation
0178 def __init__(self, config):
0179 super(PlottingOptionsZMuMu, self).__init__(config, "zmumu")
0180 self.general["switchONfit"] = cppboolstring(self.general["switchONfit"], "switchONfit")
0181
0182 class PlottingOptionsOffline(BasePlottingOptions):
0183 defaults = {
0184 "DMRMethod":"median,rmsNorm",
0185 "DMRMinimum":"30",
0186 "DMROptions":"",
0187 "OfflineTreeBaseDir":"TrackHitFilter",
0188 "SurfaceShapes":"coarse",
0189 "bigtext":"false",
0190 "mergeOfflineParJobsScriptPath": ".oO[scriptsdir]Oo./TkAlOfflineJobsMerge.C",
0191 "usefit": "false","moduleid": ""
0192 }
0193 validationclass = OfflineValidation
0194 def __init__(self, config):
0195 super(PlottingOptionsOffline, self).__init__(config, "offline")
0196 for name in "usefit", "bigtext":
0197 self.general[name] = cppboolstring(self.general[name], name)
0198
0199
0200 class PlottingOptionsPrimaryVertex(BasePlottingOptions):
0201 defaults = {
0202 "autoLimits":"false",
0203 "doMaps":"false",
0204 "stdResiduals":"true",
0205 "m_dxyPhiMax":"40",
0206 "m_dzPhiMax":"40",
0207 "m_dxyEtaMax":"40",
0208 "m_dzEtaMax":"40",
0209 "m_dxyPhiNormMax":"0.5",
0210 "m_dzPhiNormMax":"0.5",
0211 "m_dxyEtaNormMax":"0.5",
0212 "m_dzEtaNormMax":"0.5",
0213 "w_dxyPhiMax":"150",
0214 "w_dzPhiMax":"150",
0215 "w_dxyEtaMax":"150",
0216 "w_dzEtaMax":"1000",
0217 "w_dxyPhiNormMax":"1.8",
0218 "w_dzPhiNormMax":"1.8",
0219 "w_dxyEtaNormMax":"1.8",
0220 "w_dzEtaNormMax":"1.8",
0221 }
0222 validationclass = PrimaryVertexValidation
0223 def __init__(self, config):
0224 super(PlottingOptionsPrimaryVertex, self).__init__(config, "primaryvertex")
0225 for name in "autoLimits", "doMaps", "stdResiduals":
0226 self.general[name] = cppboolstring(self.general[name], name)
0227
0228 class PlottingOptionsOverlap(BasePlottingOptions):
0229 validationclass = OverlapValidation
0230 def __init__(self, config):
0231 super(PlottingOptionsOverlap, self).__init__(config, "overlap")
0232
0233 class PlottingOptionsPVResolution(BasePlottingOptions):
0234 defaults = {}
0235 validationclass = PrimaryVertexResolution
0236 def __init__(self, config):
0237 super(PlottingOptionsPVResolution, self).__init__(config, "pvresolution")
0238
0239 def PlottingOptions(config, valType):
0240 plottingOptionsClasses = {
0241 "offline": PlottingOptionsOffline,
0242 "split": PlottingOptionsTrackSplitting,
0243 "zmumu": PlottingOptionsZMuMu,
0244 "primaryvertex": PlottingOptionsPrimaryVertex,
0245 "overlap": PlottingOptionsOverlap,
0246 "pvresolution": PlottingOptionsPVResolution,
0247 }
0248 if isinstance(valType, type):
0249 valType = valType.valType
0250
0251 if valType not in globalDictionaries.plottingOptions:
0252 if config is None:
0253 raise ValueError("Have to provide a config the first time you call PlottingOptions for {}".format(valType))
0254 globalDictionaries.plottingOptions[valType] = plottingOptionsClasses[valType](config)
0255 return globalDictionaries.plottingOptions[valType].getRepMap()
0256
0257
0258