CMS 3D CMS Logo

alignment.py
Go to the documentation of this file.
1 from __future__ import absolute_import
2 import collections
3 import os
4 import re
5 
6 from . import configTemplates
7 from .helperFunctions import conddb, parsecolor, parsestyle, replaceByMap, clean_name
8 from .TkAlExceptions import AllInOneError
9 import six
10 
12  condShorts = {
13  "TrackerAlignmentErrorExtendedRcd": {
14  "zeroAPE_phase0": {
15  "connectString":("frontier://FrontierProd"
16  "/CMS_CONDITIONS"),
17  "tagName": "TrackerIdealGeometryErrorsExtended210_mc",
18  "labelName": ""
19  },
20  "zeroAPE_phase1": {
21  "connectString":("frontier://FrontierProd"
22  "/CMS_CONDITIONS"),
23  "tagName": "TrackerAlignmentErrorsExtended_Upgrade2017_design_v0",
24  "labelName": ""
25  },
26  },
27  "TrackerSurfaceDeformationRcd": {
28  "zeroDeformations": {
29  "connectString":("frontier://FrontierProd"
30  "/CMS_CONDITIONS"),
31  "tagName": "TrackerSurfaceDeformations_zero",
32  "labelName": ""
33  },
34  },
35  }
36  def __init__(self, name, config, runGeomComp = "1"):
37  section = "alignment:%s"%name
38  if not config.has_section( section ):
39  raise AllInOneError("section %s not found. Please define the "
40  "alignment!"%section)
41  config.checkInput(section,
42  knownSimpleOptions = ['globaltag', 'style', 'color', 'title', 'mp', 'mp_alignments', 'mp_deformations', 'mp_APEs', 'hp', 'hp_alignments', 'hp_deformations', 'sm', 'sm_alignments', 'sm_deformations'],
43  knownKeywords = ['condition'])
44  self.name = clean_name(name)
45  if config.exists(section,"title"):
46  self.title = config.get(section,"title")
47  else:
48  self.title = self.name
49  if (int(runGeomComp) != 1):
50  self.name += "_run" + runGeomComp
51  self.title += " run " + runGeomComp
52  if "|" in self.title or "," in self.title or '"' in self.title:
53  msg = "The characters '|', '\"', and ',' cannot be used in the alignment title!"
54  raise AllInOneError(msg)
55  self.runGeomComp = runGeomComp
56  self.globaltag = config.get( section, "globaltag" )
57  self.conditions = self.__getConditions( config, section )
58 
59  self.color = config.get(section,"color")
60  self.style = config.get(section,"style")
61 
62  self.color = str(parsecolor(self.color))
63  self.style = str(parsestyle(self.style))
64 
65  def __shorthandExists(self, theRcdName, theShorthand):
66  """Method which checks, if `theShorthand` is a valid shorthand for the
67  given `theRcdName`.
68 
69  Arguments:
70  - `theRcdName`: String which specifies the database record.
71  - `theShorthand`: String which specifies the shorthand to check.
72  """
73 
74  if (theRcdName in self.condShorts) and \
75  (theShorthand in self.condShorts[theRcdName]):
76  return True
77  else:
78  return False
79 
80  def __getConditions( self, theConfig, theSection ):
81  conditions = []
82  for option in theConfig.options( theSection ):
83  if option in ("mp", "mp_alignments", "mp_deformations", "mp_APEs", "hp", "hp_alignments", "hp_deformations", "sm", "sm_alignments", "sm_deformations"):
84  matches = [re.match(_, option) for _ in ("^(..)$", "^(..)_alignments$", "^(..)_deformations$", "^(..)_APEs$")]
85  assert sum(bool(_) for _ in matches) == 1, option
86  condPars = theConfig.get(theSection, option).split(",")
87  condPars = [_.strip() for _ in condPars]
88  if matches[0]:
89  alignments = True
90  deformations = True
91  APEs = {"hp": False, "mp": True}[option]
92  elif matches[1]:
93  alignments = True
94  deformations = False
95  APEs = False
96  option = matches[1].group(1)
97  elif matches[2]:
98  alignments = False
99  deformations = True
100  APEs = False
101  option = matches[2].group(1)
102  elif matches[3]:
103  alignments = False
104  deformations = False
105  APEs = True
106  option = matches[3].group(1)
107  else:
108  assert False
109 
110  if option == "mp":
111  if len(condPars) == 1:
112  number, = condPars
113  jobm = None
114  elif len(condPars) == 2:
115  number, jobm = condPars
116  else:
117  raise AllInOneError("Up to 2 arguments accepted for {} (job number, and optionally jobm index)".format(option))
118 
119  folder = "/afs/cern.ch/cms/CAF/CMSALCA/ALCA_TRACKERALIGN/MP/MPproduction/{}{}/".format(option, number)
120  if not os.path.exists(folder):
121  raise AllInOneError(folder+" does not exist.")
122  folder = os.path.join(folder, "jobData")
123  jobmfolders = set()
124  if jobm is None:
125  for filename in os.listdir(folder):
126  if re.match("jobm([0-9]*)", filename) and os.path.isdir(os.path.join(folder, filename)):
127  jobmfolders.add(filename)
128  if len(jobmfolders) == 0:
129  raise AllInOneError("No jobm or jobm(number) folder in {}".format(folder))
130  elif len(jobmfolders) == 1:
131  folder = os.path.join(folder, jobmfolders.pop())
132  else:
133  raise AllInOneError(
134  "Multiple jobm or jobm(number) folders in {}\n".format(folder)
135  + ", ".join(jobmfolders) + "\n"
136  + "Please specify 0 for jobm, or a number for one of the others."
137  )
138  elif jobm == "0":
139  folder = os.path.join(folder, "jobm")
140  if os.path.exists(folder + "0"):
141  raise AllInOneError("Not set up to handle a folder named jobm0")
142  else:
143  folder = os.path.join(folder, "jobm{}".format(jobm))
144 
145  dbfile = os.path.join(folder, "alignments_MP.db")
146  if not os.path.exists(dbfile):
147  raise AllInOneError("No file {}. Maybe your alignment folder is corrupted, or maybe you specified the wrong jobm?".format(dbfile))
148 
149  elif option in ("hp", "sm"):
150  if len(condPars) == 1:
151  number, = condPars
152  iteration = None
153  elif len(condPars) == 2:
154  number, iteration = condPars
155  else:
156  raise AllInOneError("Up to 2 arguments accepted for {} (job number, and optionally iteration)".format(option))
157  folder = "/afs/cern.ch/cms/CAF/CMSALCA/ALCA_TRACKERALIGN2/HipPy/alignments/{}{}".format(option, number)
158  if not os.path.exists(folder):
159  raise AllInOneError(folder+" does not exist.")
160  if iteration is None:
161  for filename in os.listdir(folder):
162  match = re.match("alignments_iter([0-9]*).db", filename)
163  if match:
164  if iteration is None or int(match.group(1)) > iteration:
165  iteration = int(match.group(1))
166  if iteration is None:
167  raise AllInOneError("No alignments in {}".format(folder))
168  dbfile = os.path.join(folder, "alignments_iter{}.db".format(iteration))
169  if not os.path.exists(dbfile):
170  raise AllInOneError("No file {}.".format(dbfile))
171 
172  if "\nDeformations" not in conddb("--db", dbfile, "listTags"):
173  deformations = False #so that hp = XXXX works whether or not deformations were aligned
174  if not alignments: #then it's specified with hp_deformations, which is a mistake
175  raise AllInOneError("{}{} has no deformations".format(option, number))
176 
177  else:
178  assert False, option
179 
180  if alignments:
181  conditions.append({"rcdName": "TrackerAlignmentRcd",
182  "connectString": "sqlite_file:"+dbfile,
183  "tagName": "Alignments",
184  "labelName": ""})
185  if deformations:
186  conditions.append({"rcdName": "TrackerSurfaceDeformationRcd",
187  "connectString": "sqlite_file:"+dbfile,
188  "tagName": "Deformations",
189  "labelName": ""})
190  if APEs:
191  conditions.append({"rcdName": "TrackerAlignmentErrorExtendedRcd",
192  "connectString": "sqlite_file:"+dbfile,
193  "tagName": "AlignmentErrorsExtended",
194  "labelName": ""})
195 
196  elif option.startswith( "condition " ):
197  rcdName = option.split( "condition " )[1]
198  condPars = theConfig.get( theSection, option ).split( "," )
199  if len(condPars) == 1:
200  if len(condPars[0])==0:
201  msg = ("In section [%s]: '%s' is used with too few "
202  "arguments. A connect_string and a tag are "
203  "required!"%(theSection, option))
204  raise AllInOneError(msg)
205  elif self.__shorthandExists(rcdName, condPars[0]):
206  shorthand = condPars[0]
207  condPars = [
208  self.condShorts[rcdName][shorthand]["connectString"],
209  self.condShorts[rcdName][shorthand]["tagName"],
210  self.condShorts[rcdName][shorthand]["labelName"]]
211  elif rcdName == "TrackerAlignmentErrorExtendedRcd" and condPars[0] == "zeroAPE":
212  raise AllInOneError("Please specify either zeroAPE_phase0 or zeroAPE_phase1")
213  #can probably make zeroAPE an alias of zeroAPE_phase1 at some point,
214  #but not sure if now is the time
215  else:
216  msg = ("In section [%s]: '%s' is used with '%s', "
217  "which is an unknown shorthand for '%s'. Either "
218  "provide at least a connect_string and a tag or "
219  "use a known shorthand.\n"
220  %(theSection, option, condPars[0], rcdName))
221  if rcdName in self.condShorts:
222  msg += "Known shorthands for '%s':\n"%(rcdName)
223  theShorts = self.condShorts[rcdName]
224  knownShorts = [("\t"+key+": "
225  +theShorts[key]["connectString"]+","
226  +theShorts[key]["tagName"]+","
227  +theShorts[key]["labelName"]) \
228  for key in theShorts]
229  msg+="\n".join(knownShorts)
230  else:
231  msg += ("There are no known shorthands for '%s'."
232  %(rcdName))
233  raise AllInOneError(msg)
234  if len( condPars ) == 2:
235  condPars.append( "" )
236  if len(condPars) > 3:
237  msg = ("In section [%s]: '%s' is used with too many "
238  "arguments. A maximum of 3 arguments is allowed."
239  %(theSection, option))
240  raise AllInOneError(msg)
241  conditions.append({"rcdName": rcdName.strip(),
242  "connectString": condPars[0].strip(),
243  "tagName": condPars[1].strip(),
244  "labelName": condPars[2].strip()})
245 
246  rcdnames = collections.Counter(condition["rcdName"] for condition in conditions)
247  if rcdnames and max(rcdnames.values()) >= 2:
248  raise AllInOneError("Some conditions are specified multiple times (possibly through mp or hp options)!\n"
249  + ", ".join(rcdname for rcdname, count in six.iteritems(rcdnames) if count >= 2))
250 
251  for condition in conditions:
252  self.__testDbExist(condition["connectString"], condition["tagName"])
253 
254  return conditions
255 
256  def __testDbExist(self, dbpath, tagname):
257  if dbpath.startswith("sqlite_file:"):
258  if not os.path.exists( dbpath.split("sqlite_file:")[1] ):
259  raise AllInOneError("could not find file: '%s'"%dbpath.split("sqlite_file:")[1])
260  elif "\n"+tagname not in conddb("--db", dbpath.split("sqlite_file:")[1], "listTags"):
261  raise AllInOneError("{} does not exist in {}".format(tagname, dbpath))
262 
263  def restrictTo( self, restriction ):
264  result = []
265  if not restriction == None:
266  for mode in self.mode:
267  if mode in restriction:
268  result.append( mode )
269  self.mode = result
270 
271  def getRepMap( self ):
272  result = {
273  "name": self.name,
274  "title": self.title,
275  "color": self.color,
276  "style": self.style,
277  "runGeomComp": self.runGeomComp,
278  "GlobalTag": self.globaltag
279  }
280  return result
281 
282  def getConditions(self):
283  """This function creates the configuration snippet to override
284  global tag conditions.
285  """
286  if len( self.conditions ):
287  loadCond = ("\nimport CalibTracker.Configuration."
288  "Common.PoolDBESSource_cfi\n")
289  for cond in self.conditions:
290  if not cond["labelName"] == "":
291  temp = configTemplates.conditionsTemplate.replace(
292  "tag = cms.string('.oO[tagName]Oo.')",
293  ("tag = cms.string('.oO[tagName]Oo.'),"
294  "\nlabel = cms.untracked.string('.oO[labelName]Oo.')"))
295  else:
296  temp = configTemplates.conditionsTemplate
297  loadCond += replaceByMap( temp, cond )
298  else:
299  loadCond = ""
300  return loadCond
dictionary condShorts
Definition: alignment.py:12
std::vector< std::string_view > split(std::string_view, const char *)
def __getConditions(self, theConfig, theSection)
Definition: alignment.py:80
def parsestyle(style)
def __testDbExist(self, dbpath, tagname)
Definition: alignment.py:256
def restrictTo(self, restriction)
Definition: alignment.py:263
def __shorthandExists(self, theRcdName, theShorthand)
Definition: alignment.py:65
def replaceByMap(target, the_map)
— Helpers —############################
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
def parsecolor(color)
def getRepMap(self)
Definition: alignment.py:271
#define str(s)
def __init__(self, name, config, runGeomComp="1")
Definition: alignment.py:36
def getConditions(self)
Definition: alignment.py:282