Back to home page

Project CMSSW displayed by LXR

 
 

    


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  #so that hp = XXXX works whether or not deformations were aligned
0173                         if not alignments:    #then it's specified with hp_deformations, which is a mistake
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                         #can probably make zeroAPE an alias of zeroAPE_phase1 at some point,
0213                         #but not sure if now is the time
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