Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-01 23:40:06

0001 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, RawTextHelpFormatter, RawDescriptionHelpFormatter
0002 import sys, os, operator
0003 from pprint import pprint
0004 import filecmp
0005 
0006 # convenience definition
0007 # (from ConfigArgParse)
0008 class ArgumentDefaultsRawHelpFormatter(
0009     ArgumentDefaultsHelpFormatter,
0010     RawTextHelpFormatter,
0011     RawDescriptionHelpFormatter):
0012     """HelpFormatter that adds default values AND doesn't do line-wrapping"""
0013 pass
0014 
0015 class GeometryGenerator(object):
0016     def __init__(self, scriptName, detectorVersionDefault, detectorPrefix, detectorYear, maxSections, allDicts, detectorVersionDict, deprecatedDets = None, deprecatedSubdets = None, detectorVersionType = int):
0017         self.scriptName = scriptName
0018         self.detectorVersionDefault = detectorVersionDefault
0019         self.detectorPrefix = detectorPrefix
0020         self.detectorYear = detectorYear
0021         self.maxSections = maxSections
0022         self.allDicts = allDicts
0023         self.detectorVersionDict = detectorVersionDict
0024         self.deprecatedDets = deprecatedDets
0025         self.deprecatedSubdets = deprecatedSubdets
0026         self.detectorVersionType = detectorVersionType
0027         self.detectorVersionNull = self.detectorVersionType(0)
0028         self.dd4hepDetectorVersion = 91 #If detectorVersion > 91, add warning to add also DD4hep in Configuration/StandardSequences/python/GeometryConf.py
0029 
0030     def generateGeom(self, detectorTuple, args):
0031         detectorVersion = self.detectorPrefix+str(args.detectorVersionManual)
0032         # reverse dict search if overall D# specified
0033         if args.v_detector!=self.detectorVersionNull:
0034             detectorVersion = self.detectorPrefix+str(args.v_detector)
0035             if detectorVersion in self.detectorVersionDict.values():
0036                 detectorTuple = list(self.detectorVersionDict.keys())[list(self.detectorVersionDict.values()).index(detectorVersion)]
0037             else:
0038                 print("Unknown detector "+detectorVersion)
0039                 sys.exit(1)
0040         elif detectorTuple in self.detectorVersionDict.keys():
0041             detectorVersion = self.detectorVersionDict[detectorTuple]
0042         else:
0043             if not args.doTest: print("Detector "+str(detectorTuple)+" not found in dictionary, using "+("default" if args.detectorVersionManual==self.detectorVersionDefault else "provided")+" version number "+str(detectorVersion))
0044 
0045         # check for deprecation
0046         if self.deprecatedDets is not None and detectorVersion in self.deprecatedDets:
0047             print("Error: "+detectorVersion+" is deprecated and cannot be used.")
0048             sys.exit(1)
0049         if self.deprecatedSubdets is not None:
0050             for subdet in detectorTuple:
0051                 if subdet in self.deprecatedSubdets:
0052                     print("Error: "+subdet+" is deprecated and cannot be used.")
0053                     sys.exit(1)
0054 
0055         # create output files
0056         xmlName = "cmsExtendedGeometry"+self.detectorYear+detectorVersion+"XML_cfi.py"
0057         xmlDD4hepName = "cmsExtendedGeometry"+self.detectorYear+detectorVersion+".xml"
0058         simName = "GeometryExtended"+self.detectorYear+detectorVersion+"_cff.py"
0059         simDD4hepName = "GeometryDD4hepExtended"+self.detectorYear+detectorVersion+"_cff.py"
0060         recoName = "GeometryExtended"+self.detectorYear+detectorVersion+"Reco_cff.py"
0061         recoDD4hepName = "GeometryDD4hepExtended"+self.detectorYear+detectorVersion+"Reco_cff.py"
0062 
0063         # check directories
0064         CMSSWBASE = os.getenv("CMSSW_BASE")
0065         CMSSWRELBASE = os.getenv("CMSSW_RELEASE_BASE")
0066         if CMSSWBASE is None: CMSSWBASE = ""
0067         xmlDir = os.path.join(CMSSWBASE,"src","Geometry","CMSCommonData","python")
0068         xmlDD4hepDir = os.path.join(CMSSWBASE,"src","Geometry","CMSCommonData","data","dd4hep")
0069         simrecoDir = os.path.join(CMSSWBASE,"src","Configuration","Geometry","python")
0070         simrecoDD4hepDir = os.path.join(CMSSWBASE,"src","Configuration","Geometry","python")
0071         if args.doTest:
0072             if not os.path.isdir(xmlDir):
0073                 xmlDir = os.path.join(CMSSWRELBASE,"src","Geometry","CMSCommonData","python")
0074                 xmlDD4hepDir = os.path.join(CMSSWRELBASE,"src","Geometry","CMSCommonData","data","dd4hep")
0075         else:
0076             mvCommands = ""
0077             if not os.path.isdir(xmlDir):
0078                 mvCommands += "mv "+xmlName+" "+xmlDir+"/\n"
0079             else:
0080                 xmlName = os.path.join(xmlDir,xmlName)
0081             if not os.path.isdir(xmlDD4hepDir):
0082                 mvCommands += "mv "+xmlDD4hepName+" "+xmlDD4hepDir+"/\n"
0083             else:
0084                 xmlDD4hepName = os.path.join(xmlDD4hepDir,xmlDD4hepName)
0085             if not os.path.isdir(simrecoDir):
0086                 mvCommands += "mv "+simName+" "+simrecoDir+"/\n"
0087                 mvCommands += "mv "+recoName+" "+simrecoDir+"/\n"
0088             else:
0089                 simName = os.path.join(simrecoDir,simName)
0090                 recoName = os.path.join(simrecoDir,recoName)
0091             if not os.path.isdir(simrecoDD4hepDir):
0092                 mvCommands += "mv "+simDD4hepName+" "+simrecoDD4hepDir+"/\n"
0093                 mvCommands += "mv "+recoDD4hepName+" "+simrecoDD4hepDir+"/\n"
0094             else:
0095                 simDD4hepName = os.path.join(simrecoDD4hepDir,simDD4hepName)
0096                 recoDD4hepName = os.path.join(simrecoDD4hepDir,recoDD4hepName)
0097             if len(mvCommands)>0:
0098                 print("Warning: some geometry packages not checked out.\nOnce they are available, please execute the following commands manually:\n"+mvCommands)
0099 
0100         # open files
0101         xmlFile = open(xmlName,'w')
0102         xmlDD4hepFile = open(xmlDD4hepName,'w')
0103         simFile = open(simName,'w')
0104         simDD4hepFile = open(simDD4hepName,'w')
0105         recoFile = open(recoName,'w')
0106         recoDD4hepFile = open(recoDD4hepName,'w')
0107 
0108         # common preamble
0109         preamble = "import FWCore.ParameterSet.Config as cms"+"\n"+"\n"
0110         preamble += "# This config was generated automatically using "+self.scriptName+"\n"
0111         preamble += "# If you notice a mistake, please update the generating script, not just this config"+"\n"+"\n"
0112 
0113         # create XML config
0114         xmlFile.write(preamble)
0115         # extra preamble
0116         xmlFile.write("XMLIdealGeometryESSource = cms.ESSource(\"XMLIdealGeometryESSource\","+"\n")
0117         xmlFile.write("    geomXMLFiles = cms.vstring("+"\n")
0118         for section in range(1,self.maxSections+1):
0119             # midamble
0120             if section==2:
0121                 xmlFile.write("    )+"+"\n"+"    cms.vstring("+"\n")
0122             for iDict,aDict in enumerate(self.allDicts):
0123                 if section in aDict[detectorTuple[iDict]].keys():
0124                     xmlFile.write('\n'.join([ "        '"+aLine+"'," for aLine in aDict[detectorTuple[iDict]][section] ])+"\n")
0125         # postamble
0126         xmlFile.write("    ),"+"\n"+"    rootNodeName = cms.string('cms:OCMS')"+"\n"+")"+"\n")
0127         xmlFile.close()
0128 
0129         # create DD4hep XML config
0130         xmlDD4hepFile.write("<?xml version=\"1.0\"?>\n"+
0131                             "<DDDefinition>\n"+
0132                             "  <open_geometry/>\n"+
0133                             "  <close_geometry/>\n"+
0134                             "\n"+
0135                             "  <IncludeSection>\n")
0136         for section in range(1,self.maxSections+1):
0137             # midamble
0138             for iDict,aDict in enumerate(self.allDicts):
0139                 if section in aDict[detectorTuple[iDict]].keys():
0140                     xmlDD4hepFile.write('\n'.join([ "    <Include ref='"+aLine+"'/>" for aLine in aDict[detectorTuple[iDict]][section] ])+"\n")
0141         # postamble
0142         xmlDD4hepFile.write("  </IncludeSection>\n"+
0143                             "</DDDefinition>"+"\n")
0144         xmlDD4hepFile.close()
0145 
0146         # create sim config
0147         simFile.write(preamble)
0148         # always need XML
0149         simFile.write("from Geometry.CMSCommonData."+os.path.basename(xmlName).replace(".py","")+" import *"+"\n")
0150         for iDict,aDict in enumerate(self.allDicts):
0151             if "sim" in aDict[detectorTuple[iDict]].keys():
0152                 simFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["sim"] ])+"\n")
0153         simFile.close()
0154 
0155         # create simDD4hep config
0156         simDD4hepFile.write(preamble)
0157         # always need XML
0158         simDD4hepFile.write("from Configuration.Geometry.GeometryDD4hep_cff"+" import *"+"\n")
0159         simDD4hepFile.write("DDDetectorESProducer.confGeomXMLFiles = cms.FileInPath(\"Geometry/CMSCommonData/data/dd4hep/"+os.path.basename(xmlDD4hepName)+"\")\n\n")
0160         for iDict,aDict in enumerate(self.allDicts):
0161             if "sim" in aDict[detectorTuple[iDict]].keys():
0162                 simDD4hepFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["sim"] ])+"\n")
0163         simDD4hepFile.close()
0164 
0165         # create reco config
0166         recoFile.write(preamble)
0167         # always need sim
0168         recoFile.write("from Configuration.Geometry."+os.path.basename(simName).replace(".py","")+" import *"+"\n\n")
0169         for iDict,aDict in enumerate(self.allDicts):
0170             if "reco" in aDict[detectorTuple[iDict]].keys():
0171                recoFile.write("# "+aDict["name"]+"\n")
0172                recoFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["reco"] ])+"\n\n")
0173         recoFile.close()
0174 
0175         # create recoDD4hep config
0176         recoDD4hepFile.write(preamble)
0177         # always need sim
0178         recoDD4hepFile.write("from Configuration.Geometry."+os.path.basename(simDD4hepName).replace(".py","")+" import *"+"\n\n")
0179         for iDict,aDict in enumerate(self.allDicts):
0180             if "reco" in aDict[detectorTuple[iDict]].keys():
0181                 recoDD4hepFile.write("# "+aDict["name"]+"\n")
0182                 recoDD4hepFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["reco"] ])+"\n\n")
0183         recoDD4hepFile.close()
0184 
0185         from Configuration.StandardSequences.GeometryConf import GeometryConf
0186         if not args.doTest: # todo: include these in unit test somehow
0187             # specify Era customizations
0188             # must be checked manually in:
0189             # Configuration/StandardSequences/python/Eras.py
0190             # Configuration/Eras/python/
0191             # Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py (workflow definitions)
0192             eraLine = ""
0193             eraLineItems = []
0194             for iDict,aDict in enumerate(self.allDicts):
0195                 if "era" in aDict[detectorTuple[iDict]].keys():
0196                     eraLineItems.append(aDict[detectorTuple[iDict]]["era"])
0197             eraLine += ", ".join([ eraLineItem for eraLineItem in eraLineItems ])
0198             print("The Era for this detector should contain:")
0199             print(eraLine)
0200 
0201             # specify GeometryConf
0202             if not 'Extended'+self.detectorYear+detectorVersion in GeometryConf.keys():
0203                 print("Please add this line in Configuration/StandardSequences/python/GeometryConf.py:")
0204                 print("    'Extended"+self.detectorYear+detectorVersion+"' : 'Extended"+self.detectorYear+detectorVersion+",Extended"+self.detectorYear+detectorVersion+"Reco',")
0205                 if self.detectorYear == "Run4" and int(args.v_detector) > self.dd4hepDetectorVersion:
0206                     print("    'DD4hepExtended"+self.detectorYear+detectorVersion+"' : 'DD4hepExtended"+self.detectorYear+detectorVersion+",DD4hepExtended"+self.detectorYear+detectorVersion+"Reco',")
0207 
0208         errorList = []
0209 
0210         if args.doTest:
0211             # tests for Configuration/Geometry
0212             simFile = os.path.join(simrecoDir,simName)
0213             if not os.path.isfile(simFile):
0214                 errorList.append(simName+" missing")
0215             elif not filecmp.cmp(simName,simFile):
0216                 errorList.append(simName+" differs")
0217             simDD4hepFile = os.path.join(simrecoDD4hepDir,simDD4hepName)
0218             if not os.path.isfile(simDD4hepFile):
0219                 errorList.append(simDD4hepName+" missing")
0220             elif not filecmp.cmp(simDD4hepName,simDD4hepFile):
0221                 errorList.append(simDD4hepName+" differs")
0222             recoFile = os.path.join(simrecoDir,recoName)
0223             if not os.path.isfile(recoFile):
0224                 errorList.append(recoName+" missing")
0225             elif not filecmp.cmp(recoName,recoFile):
0226                 errorList.append(recoName+" differs")
0227             recoDD4hepFile = os.path.join(simrecoDD4hepDir,recoDD4hepName)
0228             if not os.path.isfile(recoDD4hepFile):
0229                 errorList.append(recoDD4hepName+" missing")
0230             elif not filecmp.cmp(recoDD4hepName,recoDD4hepFile):
0231                 errorList.append(recoDD4hepName+" differs")
0232             # test for Configuration/StandardSequences
0233             if not 'Extended'+self.detectorYear+detectorVersion in GeometryConf.keys():
0234                 errorList.append('Extended'+self.detectorYear+detectorVersion+" missing from GeometryConf")
0235             # test for Geometry/CMSCommonData
0236             xmlFile = os.path.join(xmlDir,xmlName)
0237             if not os.path.isfile(xmlFile):
0238                 errorList.append(xmlName+" missing")
0239             elif not filecmp.cmp(xmlName,xmlFile):
0240                 errorList.append(xmlName+" differs")
0241             # test for dd4hep xml
0242             xmlDD4hepFile = os.path.join(xmlDD4hepDir,xmlDD4hepName)
0243             if not os.path.exists(xmlDD4hepFile):
0244                 errorList.append(xmlDD4hepName+" differs")
0245             elif not filecmp.cmp(xmlDD4hepName,xmlDD4hepFile):
0246                 errorList.append(xmlDD4hepName+" differs")
0247         return errorList
0248 
0249     def run(self):
0250         # define options
0251         parser = ArgumentParser(formatter_class=ArgumentDefaultsRawHelpFormatter)
0252         for aDict in self.allDicts:
0253             parser.add_argument("-"+aDict["abbrev"], "--"+aDict["name"], dest="v_"+aDict["name"], default=aDict["default"], type=int, help="version for "+aDict["name"])
0254         parser.add_argument("-V", "--version", dest="detectorVersionManual", default=self.detectorVersionDefault, type=int, help="manual detector version number")
0255         parser.add_argument("-D", "--detector", dest="v_detector", default=self.detectorVersionNull, type=self.detectorVersionType, help="version for whole detector, ignored if 0, overrides subdet versions otherwise")
0256         parser.add_argument("-l", "--list", dest="doList", default=False, action="store_true", help="list known detector versions and exit")
0257         parser.add_argument("-t", "--test", dest="doTest", default=False, action="store_true", help="enable unit test mode")
0258         args = parser.parse_args()
0259 
0260         # check options
0261         if args.doList and not args.doTest:
0262             pprint(sorted(self.detectorVersionDict.items(),key=operator.itemgetter(1)))
0263             sys.exit(0)
0264         elif args.doTest:
0265             # list of errors
0266             errorList = []
0267             # run all known possibilities
0268             for detectorTuple in self.detectorVersionDict:
0269                 errorTmp = self.generateGeom(detectorTuple,args)
0270                 errorList.extend(errorTmp)
0271             if len(errorList)>0:
0272                 print('\n'.join([anError for anError in errorList]))
0273                 sys.exit(1)
0274             else:
0275                 sys.exit(0)
0276         else:
0277             detectorTuple = tuple([aDict["abbrev"]+str(getattr(args,"v_"+aDict["name"])) for aDict in self.allDicts])
0278             self.generateGeom(detectorTuple,args)
0279             sys.exit(0)
0280