CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
generateGeometry.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, RawTextHelpFormatter, RawDescriptionHelpFormatter
3 import sys, os, operator
4 from pprint import pprint
5 import filecmp
6 
7 # convenience definition
8 # (from ConfigArgParse)
10  ArgumentDefaultsHelpFormatter,
11  RawTextHelpFormatter,
12  RawDescriptionHelpFormatter):
13  """HelpFormatter that adds default values AND doesn't do line-wrapping"""
14 pass
15 
16 class GeometryGenerator(object):
17  def __init__(self, scriptName, detectorVersionDefault, detectorPrefix, detectorYear, maxSections, allDicts, detectorVersionDict, deprecatedDets = None, deprecatedSubdets = None, detectorVersionType = int):
18  self.scriptName = scriptName
19  self.detectorVersionDefault = detectorVersionDefault
20  self.detectorPrefix = detectorPrefix
21  self.detectorYear = detectorYear
22  self.maxSections = maxSections
23  self.allDicts = allDicts
24  self.detectorVersionDict = detectorVersionDict
25  self.deprecatedDets = deprecatedDets
26  self.deprecatedSubdets = deprecatedSubdets
27  self.detectorVersionType = detectorVersionType
29 
30  def generateGeom(self, detectorTuple, args):
31  detectorVersion = self.detectorPrefix+str(args.detectorVersionManual)
32  # reverse dict search if overall D# specified
33  if args.v_detector!=self.detectorVersionNull:
34  detectorVersion = self.detectorPrefix+str(args.v_detector)
35  if detectorVersion in self.detectorVersionDict.values():
36  detectorTuple = list(self.detectorVersionDict.keys())[list(self.detectorVersionDict.values()).index(detectorVersion)]
37  else:
38  print("Unknown detector "+detectorVersion)
39  sys.exit(1)
40  elif detectorTuple in self.detectorVersionDict.keys():
41  detectorVersion = self.detectorVersionDict[detectorTuple]
42  else:
43  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))
44 
45  # check for deprecation
46  if self.deprecatedDets is not None and detectorVersion in self.deprecatedDets:
47  print("Error: "+detectorVersion+" is deprecated and cannot be used.")
48  sys.exit(1)
49  if self.deprecatedSubdets is not None:
50  for subdet in detectorTuple:
51  if subdet in self.deprecatedSubdets:
52  print("Error: "+subdet+" is deprecated and cannot be used.")
53  sys.exit(1)
54 
55  # create output files
56  xmlName = "cmsExtendedGeometry"+self.detectorYear+detectorVersion+"XML_cfi.py"
57  xmlDD4hepName = "cmsExtendedGeometry"+self.detectorYear+detectorVersion+".xml"
58  simName = "GeometryExtended"+self.detectorYear+detectorVersion+"_cff.py"
59  simDD4hepName = "GeometryDD4hepExtended"+self.detectorYear+detectorVersion+"_cff.py"
60  recoName = "GeometryExtended"+self.detectorYear+detectorVersion+"Reco_cff.py"
61  recoDD4hepName = "GeometryDD4hepExtended"+self.detectorYear+detectorVersion+"Reco_cff.py"
62 
63  # check directories
64  CMSSWBASE = os.getenv("CMSSW_BASE")
65  CMSSWRELBASE = os.getenv("CMSSW_RELEASE_BASE")
66  if CMSSWBASE is None: CMSSWBASE = ""
67  xmlDir = os.path.join(CMSSWBASE,"src","Geometry","CMSCommonData","python")
68  xmlDD4hepDir = os.path.join(CMSSWBASE,"src","Geometry","CMSCommonData","data","dd4hep")
69  simrecoDir = os.path.join(CMSSWBASE,"src","Configuration","Geometry","python")
70  simrecoDD4hepDir = os.path.join(CMSSWBASE,"src","Configuration","Geometry","python")
71  if args.doTest:
72  if not os.path.isdir(xmlDir):
73  xmlDir = os.path.join(CMSSWRELBASE,"src","Geometry","CMSCommonData","python")
74  xmlDD4hepDir = os.path.join(CMSSWRELBASE,"src","Geometry","CMSCommonData","data","dd4hep")
75  else:
76  mvCommands = ""
77  if not os.path.isdir(xmlDir):
78  mvCommands += "mv "+xmlName+" "+xmlDir+"/\n"
79  else:
80  xmlName = os.path.join(xmlDir,xmlName)
81  if not os.path.isdir(xmlDD4hepDir):
82  mvCommands += "mv "+xmlDD4hepName+" "+xmlDD4hepDir+"/\n"
83  else:
84  xmlDD4hepName = os.path.join(xmlDD4hepDir,xmlDD4hepName)
85  if not os.path.isdir(simrecoDir):
86  mvCommands += "mv "+simName+" "+simrecoDir+"/\n"
87  mvCommands += "mv "+recoName+" "+simrecoDir+"/\n"
88  else:
89  simName = os.path.join(simrecoDir,simName)
90  recoName = os.path.join(simrecoDir,recoName)
91  if not os.path.isdir(simrecoDD4hepDir):
92  mvCommands += "mv "+simDD4hepName+" "+simrecoDD4hepDir+"/\n"
93  mvCommands += "mv "+recoDD4hepName+" "+simrecoDD4hepDir+"/\n"
94  else:
95  simDD4hepName = os.path.join(simrecoDD4hepDir,simDD4hepName)
96  recoDD4hepName = os.path.join(simrecoDD4hepDir,recoDD4hepName)
97  if len(mvCommands)>0:
98  print("Warning: some geometry packages not checked out.\nOnce they are available, please execute the following commands manually:\n"+mvCommands)
99 
100  # open files
101  xmlFile = open(xmlName,'w')
102  xmlDD4hepFile = open(xmlDD4hepName,'w')
103  simFile = open(simName,'w')
104  simDD4hepFile = open(simDD4hepName,'w')
105  recoFile = open(recoName,'w')
106  recoDD4hepFile = open(recoDD4hepName,'w')
107 
108  # common preamble
109  preamble = "import FWCore.ParameterSet.Config as cms"+"\n"+"\n"
110  preamble += "# This config was generated automatically using "+self.scriptName+"\n"
111  preamble += "# If you notice a mistake, please update the generating script, not just this config"+"\n"+"\n"
112 
113  # create XML config
114  xmlFile.write(preamble)
115  # extra preamble
116  xmlFile.write("XMLIdealGeometryESSource = cms.ESSource(\"XMLIdealGeometryESSource\","+"\n")
117  xmlFile.write(" geomXMLFiles = cms.vstring("+"\n")
118  for section in range(1,self.maxSections+1):
119  # midamble
120  if section==2:
121  xmlFile.write(" )+"+"\n"+" cms.vstring("+"\n")
122  for iDict,aDict in enumerate(self.allDicts):
123  if section in aDict[detectorTuple[iDict]].keys():
124  xmlFile.write('\n'.join([ " '"+aLine+"'," for aLine in aDict[detectorTuple[iDict]][section] ])+"\n")
125  # postamble
126  xmlFile.write(" ),"+"\n"+" rootNodeName = cms.string('cms:OCMS')"+"\n"+")"+"\n")
127  xmlFile.close()
128 
129  # create DD4hep XML config
130  xmlDD4hepFile.write("<?xml version=\"1.0\"?>\n"+
131  "<DDDefinition>\n"+
132  " <open_geometry/>\n"+
133  " <close_geometry/>\n"+
134  "\n"+
135  " <IncludeSection>\n")
136  for section in range(1,self.maxSections+1):
137  # midamble
138  for iDict,aDict in enumerate(self.allDicts):
139  if section in aDict[detectorTuple[iDict]].keys():
140  xmlDD4hepFile.write('\n'.join([ " <Include ref='"+aLine+"'/>" for aLine in aDict[detectorTuple[iDict]][section] ])+"\n")
141  # postamble
142  xmlDD4hepFile.write(" </IncludeSection>\n"+
143  "</DDDefinition>"+"\n")
144  xmlDD4hepFile.close()
145 
146  # create sim config
147  simFile.write(preamble)
148  # always need XML
149  simFile.write("from Geometry.CMSCommonData."+os.path.basename(xmlName).replace(".py","")+" import *"+"\n")
150  for iDict,aDict in enumerate(self.allDicts):
151  if "sim" in aDict[detectorTuple[iDict]].keys():
152  simFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["sim"] ])+"\n")
153  simFile.close()
154 
155  # create simDD4hep config
156  simDD4hepFile.write(preamble)
157  # always need XML
158  simDD4hepFile.write("from Configuration.Geometry.GeometryDD4hep_cff"+" import *"+"\n")
159  simDD4hepFile.write("DDDetectorESProducer.confGeomXMLFiles = cms.FileInPath(\"Geometry/CMSCommonData/data/dd4hep/"+os.path.basename(xmlDD4hepName)+"\")\n\n")
160  for iDict,aDict in enumerate(self.allDicts):
161  if "sim" in aDict[detectorTuple[iDict]].keys():
162  simDD4hepFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["sim"] ])+"\n")
163  simDD4hepFile.close()
164 
165  # create reco config
166  recoFile.write(preamble)
167  # always need sim
168  recoFile.write("from Configuration.Geometry."+os.path.basename(simName).replace(".py","")+" import *"+"\n\n")
169  for iDict,aDict in enumerate(self.allDicts):
170  if "reco" in aDict[detectorTuple[iDict]].keys():
171  recoFile.write("# "+aDict["name"]+"\n")
172  recoFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["reco"] ])+"\n\n")
173  recoFile.close()
174 
175  # create recoDD4hep config
176  recoDD4hepFile.write(preamble)
177  # always need sim
178  recoDD4hepFile.write("from Configuration.Geometry."+os.path.basename(simDD4hepName).replace(".py","")+" import *"+"\n\n")
179  for iDict,aDict in enumerate(self.allDicts):
180  if "reco" in aDict[detectorTuple[iDict]].keys():
181  recoDD4hepFile.write("# "+aDict["name"]+"\n")
182  recoDD4hepFile.write('\n'.join([ aLine for aLine in aDict[detectorTuple[iDict]]["reco"] ])+"\n\n")
183  recoDD4hepFile.close()
184 
185  from Configuration.StandardSequences.GeometryConf import GeometryConf
186  if not args.doTest: # todo: include these in unit test somehow
187  # specify Era customizations
188  # must be checked manually in:
189  # Configuration/StandardSequences/python/Eras.py
190  # Configuration/Eras/python/
191  # Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py (workflow definitions)
192  eraLine = ""
193  eraLineItems = []
194  for iDict,aDict in enumerate(self.allDicts):
195  if "era" in aDict[detectorTuple[iDict]].keys():
196  eraLineItems.append(aDict[detectorTuple[iDict]]["era"])
197  eraLine += ", ".join([ eraLineItem for eraLineItem in eraLineItems ])
198  print("The Era for this detector should contain:")
199  print(eraLine)
200 
201  # specify GeometryConf
202  if not 'Extended'+self.detectorYear+detectorVersion in GeometryConf.keys():
203  print("Please add this line in Configuration/StandardSequences/python/GeometryConf.py:")
204  print(" 'Extended"+self.detectorYear+detectorVersion+"' : 'Extended"+self.detectorYear+detectorVersion+",Extended"+self.detectorYear+detectorVersion+"Reco',")
205 
206  errorList = []
207 
208  if args.doTest:
209  # tests for Configuration/Geometry
210  simFile = os.path.join(simrecoDir,simName)
211  if not os.path.isfile(simFile):
212  errorList.append(simName+" missing")
213  elif not filecmp.cmp(simName,simFile):
214  errorList.append(simName+" differs")
215  simDD4hepFile = os.path.join(simrecoDD4hepDir,simDD4hepName)
216  if not os.path.isfile(simDD4hepFile):
217  errorList.append(simDD4hepName+" missing")
218  elif not filecmp.cmp(simDD4hepName,simDD4hepFile):
219  errorList.append(simDD4hepName+" differs")
220  recoFile = os.path.join(simrecoDir,recoName)
221  if not os.path.isfile(recoFile):
222  errorList.append(recoName+" missing")
223  elif not filecmp.cmp(recoName,recoFile):
224  errorList.append(recoName+" differs")
225  recoDD4hepFile = os.path.join(simrecoDD4hepDir,recoDD4hepName)
226  if not os.path.isfile(recoDD4hepFile):
227  errorList.append(recoDD4hepName+" missing")
228  elif not filecmp.cmp(recoDD4hepName,recoDD4hepFile):
229  errorList.append(recoDD4hepName+" differs")
230  # test for Configuration/StandardSequences
231  if not 'Extended'+self.detectorYear+detectorVersion in GeometryConf.keys():
232  errorList.append('Extended'+self.detectorYear+detectorVersion+" missing from GeometryConf")
233  # test for Geometry/CMSCommonData
234  xmlFile = os.path.join(xmlDir,xmlName)
235  if not os.path.isfile(xmlFile):
236  errorList.append(xmlName+" missing")
237  elif not filecmp.cmp(xmlName,xmlFile):
238  errorList.append(xmlName+" differs")
239  # test for dd4hep xml
240  xmlDD4hepFile = os.path.join(xmlDD4hepDir,xmlDD4hepName)
241  if not os.path.exists(xmlDD4hepFile):
242  errorList.append(xmlDD4hepName+" differs")
243  elif not filecmp.cmp(xmlDD4hepName,xmlDD4hepFile):
244  errorList.append(xmlDD4hepName+" differs")
245  return errorList
246 
247  def run(self):
248  # define options
249  parser = ArgumentParser(formatter_class=ArgumentDefaultsRawHelpFormatter)
250  for aDict in self.allDicts:
251  parser.add_argument("-"+aDict["abbrev"], "--"+aDict["name"], dest="v_"+aDict["name"], default=aDict["default"], type=int, help="version for "+aDict["name"])
252  parser.add_argument("-V", "--version", dest="detectorVersionManual", default=self.detectorVersionDefault, type=int, help="manual detector version number")
253  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")
254  parser.add_argument("-l", "--list", dest="doList", default=False, action="store_true", help="list known detector versions and exit")
255  parser.add_argument("-t", "--test", dest="doTest", default=False, action="store_true", help="enable unit test mode")
256  args = parser.parse_args()
257 
258  # check options
259  if args.doList and not args.doTest:
260  pprint(sorted(self.detectorVersionDict.items(),key=operator.itemgetter(1)))
261  sys.exit(0)
262  elif args.doTest:
263  # list of errors
264  errorList = []
265  # run all known possibilities
266  for detectorTuple in self.detectorVersionDict:
267  errorTmp = self.generateGeom(detectorTuple,args)
268  errorList.extend(errorTmp)
269  if len(errorList)>0:
270  print('\n'.join([anError for anError in errorList]))
271  sys.exit(1)
272  else:
273  sys.exit(0)
274  else:
275  detectorTuple = tuple([aDict["abbrev"]+str(getattr(args,"v_"+aDict["name"])) for aDict in self.allDicts])
276  self.generateGeom(detectorTuple,args)
277  sys.exit(0)
278 
const uint16_t range(const Frame &aFrame)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
static std::string join(char **cmd)
Definition: RemoteFile.cc:19
#define str(s)