File indexing completed on 2023-03-17 10:40:23
0001 from __future__ import absolute_import
0002 import collections
0003 import os
0004 import re
0005
0006 from . import configTemplates
0007 from .helperFunctions import parsecolor, parsestyle, replaceByMap, clean_name, getTagsMap
0008 from .TkAlExceptions import AllInOneError
0009
0010 class Alignment(object):
0011 condShorts = {
0012 "TrackerAlignmentErrorExtendedRcd": {
0013 "zeroAPE_phase0": {
0014 "connectString":("frontier://FrontierProd"
0015 "/CMS_CONDITIONS"),
0016 "tagName": "TrackerIdealGeometryErrorsExtended210_mc",
0017 "labelName": ""
0018 },
0019 "zeroAPE_phase1": {
0020 "connectString":("frontier://FrontierProd"
0021 "/CMS_CONDITIONS"),
0022 "tagName": "TrackerAlignmentErrorsExtended_Upgrade2017_design_v0",
0023 "labelName": ""
0024 },
0025 },
0026 "TrackerSurfaceDeformationRcd": {
0027 "zeroDeformations": {
0028 "connectString":("frontier://FrontierProd"
0029 "/CMS_CONDITIONS"),
0030 "tagName": "TrackerSurfaceDeformations_zero",
0031 "labelName": ""
0032 },
0033 },
0034 }
0035 def __init__(self, name, config, runGeomComp = "1"):
0036 section = "alignment:%s"%name
0037 if not config.has_section( section ):
0038 raise AllInOneError("section %s not found. Please define the "
0039 "alignment!"%section)
0040 config.checkInput(section,
0041 knownSimpleOptions = ['globaltag', 'style', 'color', 'title', 'mp', 'mp_alignments', 'mp_deformations', 'mp_APEs', 'hp', 'hp_alignments', 'hp_deformations', 'sm', 'sm_alignments', 'sm_deformations'],
0042 knownKeywords = ['condition'])
0043 self.name = clean_name(name)
0044 if config.exists(section,"title"):
0045 self.title = config.get(section,"title")
0046 else:
0047 self.title = self.name
0048 if (int(runGeomComp) != 1):
0049 self.name += "_run" + runGeomComp
0050 self.title += " run " + runGeomComp
0051 if "|" in self.title or "," in self.title or '"' in self.title:
0052 msg = "The characters '|', '\"', and ',' cannot be used in the alignment title!"
0053 raise AllInOneError(msg)
0054 self.runGeomComp = runGeomComp
0055 self.globaltag = config.get( section, "globaltag" )
0056 self.conditions = self.__getConditions( config, section )
0057
0058 self.color = config.get(section,"color")
0059 self.style = config.get(section,"style")
0060
0061 self.color = str(parsecolor(self.color))
0062 self.style = str(parsestyle(self.style))
0063
0064 def __shorthandExists(self, theRcdName, theShorthand):
0065 """Method which checks, if `theShorthand` is a valid shorthand for the
0066 given `theRcdName`.
0067
0068 Arguments:
0069 - `theRcdName`: String which specifies the database record.
0070 - `theShorthand`: String which specifies the shorthand to check.
0071 """
0072
0073 if (theRcdName in self.condShorts) and \
0074 (theShorthand in self.condShorts[theRcdName]):
0075 return True
0076 else:
0077 return False
0078
0079 def __getConditions( self, theConfig, theSection ):
0080 conditions = []
0081 for option in theConfig.options( theSection ):
0082 if option in ("mp", "mp_alignments", "mp_deformations", "mp_APEs", "hp", "hp_alignments", "hp_deformations", "sm", "sm_alignments", "sm_deformations"):
0083 matches = [re.match(_, option) for _ in ("^(..)$", "^(..)_alignments$", "^(..)_deformations$", "^(..)_APEs$")]
0084 assert sum(bool(_) for _ in matches) == 1, option
0085 condPars = theConfig.get(theSection, option).split(",")
0086 condPars = [_.strip() for _ in condPars]
0087 if matches[0]:
0088 alignments = True
0089 deformations = True
0090 APEs = {"hp": False, "mp": True}[option]
0091 elif matches[1]:
0092 alignments = True
0093 deformations = False
0094 APEs = False
0095 option = matches[1].group(1)
0096 elif matches[2]:
0097 alignments = False
0098 deformations = True
0099 APEs = False
0100 option = matches[2].group(1)
0101 elif matches[3]:
0102 alignments = False
0103 deformations = False
0104 APEs = True
0105 option = matches[3].group(1)
0106 else:
0107 assert False
0108
0109 if option == "mp":
0110 if len(condPars) == 1:
0111 number, = condPars
0112 jobm = None
0113 elif len(condPars) == 2:
0114 number, jobm = condPars
0115 else:
0116 raise AllInOneError("Up to 2 arguments accepted for {} (job number, and optionally jobm index)".format(option))
0117
0118 folder = "/afs/cern.ch/cms/CAF/CMSALCA/ALCA_TRACKERALIGN/MP/MPproduction/{}{}/".format(option, number)
0119 if not os.path.exists(folder):
0120 raise AllInOneError(folder+" does not exist.")
0121 folder = os.path.join(folder, "jobData")
0122 jobmfolders = set()
0123 if jobm is None:
0124 for filename in os.listdir(folder):
0125 if re.match("jobm([0-9]*)", filename) and os.path.isdir(os.path.join(folder, filename)):
0126 jobmfolders.add(filename)
0127 if len(jobmfolders) == 0:
0128 raise AllInOneError("No jobm or jobm(number) folder in {}".format(folder))
0129 elif len(jobmfolders) == 1:
0130 folder = os.path.join(folder, jobmfolders.pop())
0131 else:
0132 raise AllInOneError(
0133 "Multiple jobm or jobm(number) folders in {}\n".format(folder)
0134 + ", ".join(jobmfolders) + "\n"
0135 + "Please specify 0 for jobm, or a number for one of the others."
0136 )
0137 elif jobm == "0":
0138 folder = os.path.join(folder, "jobm")
0139 if os.path.exists(folder + "0"):
0140 raise AllInOneError("Not set up to handle a folder named jobm0")
0141 else:
0142 folder = os.path.join(folder, "jobm{}".format(jobm))
0143
0144 dbfile = os.path.join(folder, "alignments_MP.db")
0145 if not os.path.exists(dbfile):
0146 raise AllInOneError("No file {}. Maybe your alignment folder is corrupted, or maybe you specified the wrong jobm?".format(dbfile))
0147
0148 elif option in ("hp", "sm"):
0149 if len(condPars) == 1:
0150 number, = condPars
0151 iteration = None
0152 elif len(condPars) == 2:
0153 number, iteration = condPars
0154 else:
0155 raise AllInOneError("Up to 2 arguments accepted for {} (job number, and optionally iteration)".format(option))
0156 folder = "/afs/cern.ch/cms/CAF/CMSALCA/ALCA_TRACKERALIGN2/HipPy/alignments/{}{}".format(option, number)
0157 if not os.path.exists(folder):
0158 raise AllInOneError(folder+" does not exist.")
0159 if iteration is None:
0160 for filename in os.listdir(folder):
0161 match = re.match("alignments_iter([0-9]*).db", filename)
0162 if match:
0163 if iteration is None or int(match.group(1)) > iteration:
0164 iteration = int(match.group(1))
0165 if iteration is None:
0166 raise AllInOneError("No alignments in {}".format(folder))
0167 dbfile = os.path.join(folder, "alignments_iter{}.db".format(iteration))
0168 if not os.path.exists(dbfile):
0169 raise AllInOneError("No file {}.".format(dbfile))
0170
0171 if "Deformations" not in getTagsMap(dbfile).keys():
0172 deformations = False
0173 if not alignments:
0174 raise AllInOneError("{}{} has no deformations".format(option, number))
0175
0176 else:
0177 assert False, option
0178
0179 if alignments:
0180 conditions.append({"rcdName": "TrackerAlignmentRcd",
0181 "connectString": "sqlite_file:"+dbfile,
0182 "tagName": "Alignments",
0183 "labelName": ""})
0184 if deformations:
0185 conditions.append({"rcdName": "TrackerSurfaceDeformationRcd",
0186 "connectString": "sqlite_file:"+dbfile,
0187 "tagName": "Deformations",
0188 "labelName": ""})
0189 if APEs:
0190 conditions.append({"rcdName": "TrackerAlignmentErrorExtendedRcd",
0191 "connectString": "sqlite_file:"+dbfile,
0192 "tagName": "AlignmentErrorsExtended",
0193 "labelName": ""})
0194
0195 elif option.startswith( "condition " ):
0196 rcdName = option.split( "condition " )[1]
0197 condPars = theConfig.get( theSection, option ).split( "," )
0198 if len(condPars) == 1:
0199 if len(condPars[0])==0:
0200 msg = ("In section [%s]: '%s' is used with too few "
0201 "arguments. A connect_string and a tag are "
0202 "required!"%(theSection, option))
0203 raise AllInOneError(msg)
0204 elif self.__shorthandExists(rcdName, condPars[0]):
0205 shorthand = condPars[0]
0206 condPars = [
0207 self.condShorts[rcdName][shorthand]["connectString"],
0208 self.condShorts[rcdName][shorthand]["tagName"],
0209 self.condShorts[rcdName][shorthand]["labelName"]]
0210 elif rcdName == "TrackerAlignmentErrorExtendedRcd" and condPars[0] == "zeroAPE":
0211 raise AllInOneError("Please specify either zeroAPE_phase0 or zeroAPE_phase1")
0212
0213
0214 else:
0215 msg = ("In section [%s]: '%s' is used with '%s', "
0216 "which is an unknown shorthand for '%s'. Either "
0217 "provide at least a connect_string and a tag or "
0218 "use a known shorthand.\n"
0219 %(theSection, option, condPars[0], rcdName))
0220 if rcdName in self.condShorts:
0221 msg += "Known shorthands for '%s':\n"%(rcdName)
0222 theShorts = self.condShorts[rcdName]
0223 knownShorts = [("\t"+key+": "
0224 +theShorts[key]["connectString"]+","
0225 +theShorts[key]["tagName"]+","
0226 +theShorts[key]["labelName"]) \
0227 for key in theShorts]
0228 msg+="\n".join(knownShorts)
0229 else:
0230 msg += ("There are no known shorthands for '%s'."
0231 %(rcdName))
0232 raise AllInOneError(msg)
0233 if len( condPars ) == 2:
0234 condPars.append( "" )
0235 if len(condPars) > 3:
0236 msg = ("In section [%s]: '%s' is used with too many "
0237 "arguments. A maximum of 3 arguments is allowed."
0238 %(theSection, option))
0239 raise AllInOneError(msg)
0240 conditions.append({"rcdName": rcdName.strip(),
0241 "connectString": condPars[0].strip(),
0242 "tagName": condPars[1].strip(),
0243 "labelName": condPars[2].strip()})
0244
0245 rcdnames = collections.Counter(condition["rcdName"] for condition in conditions)
0246 if rcdnames and max(rcdnames.values()) >= 2:
0247 raise AllInOneError("Some conditions are specified multiple times (possibly through mp or hp options)!\n"
0248 + ", ".join(rcdname for rcdname, count in rcdnames.items() if count >= 2))
0249
0250 for condition in conditions:
0251 self.__testDbExist(condition["connectString"], condition["tagName"])
0252
0253 return conditions
0254
0255 def __testDbExist(self, dbpath, tagname):
0256 if dbpath.startswith("sqlite_file:"):
0257 if not os.path.exists( dbpath.split("sqlite_file:")[1] ):
0258 raise AllInOneError("could not find file: '%s'"%dbpath.split("sqlite_file:")[1])
0259 elif tagname not in getTagsMap(dbpath).values():
0260 raise AllInOneError("{} does not exist in {}".format(tagname, dbpath))
0261
0262 def restrictTo( self, restriction ):
0263 result = []
0264 if not restriction == None:
0265 for mode in self.mode:
0266 if mode in restriction:
0267 result.append( mode )
0268 self.mode = result
0269
0270 def getRepMap( self ):
0271 result = {
0272 "name": self.name,
0273 "title": self.title,
0274 "color": self.color,
0275 "style": self.style,
0276 "runGeomComp": self.runGeomComp,
0277 "GlobalTag": self.globaltag
0278 }
0279 return result
0280
0281 def getConditions(self):
0282 """This function creates the configuration snippet to override
0283 global tag conditions.
0284 """
0285 if len( self.conditions ):
0286 loadCond = ("\nimport CalibTracker.Configuration."
0287 "Common.PoolDBESSource_cfi\n")
0288 for cond in self.conditions:
0289 if not cond["labelName"] == "":
0290 temp = configTemplates.conditionsTemplate.replace(
0291 "tag = cms.string('.oO[tagName]Oo.')",
0292 ("tag = cms.string('.oO[tagName]Oo.'),"
0293 "\nlabel = cms.untracked.string('.oO[labelName]Oo.')"))
0294 else:
0295 temp = configTemplates.conditionsTemplate
0296 loadCond += replaceByMap( temp, cond )
0297 else:
0298 loadCond = ""
0299 return loadCond