CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
offlineValidation.py
Go to the documentation of this file.
1 import os
2 import configTemplates
3 import globalDictionaries
4 from genericValidation import GenericValidationData
5 from helperFunctions import replaceByMap
6 from TkAlExceptions import AllInOneError
7 
8 
10  def __init__(self, valName, alignment,config):
11  defaults = {
12  "DMRMethod":"median,rmsNorm",
13  "DMRMinimum":"30",
14  "DMROptions":"",
15  "offlineModuleLevelHistsTransient":"False",
16  "offlineModuleLevelProfiles":"False",
17  "OfflineTreeBaseDir":"TrackHitFilter",
18  "SurfaceShapes":"none"
19  }
20  mandatories = [ "dataset", "maxevents", "trackcollection" ]
21  GenericValidationData.__init__(self, valName, alignment, config,
22  "offline", addDefaults=defaults,
23  addMandatories=mandatories)
24 
25  def createConfiguration(self, path,
26  configBaseName = "TkAlOfflineValidation" ):
27  cfgName = "%s.%s.%s_cfg.py"%( configBaseName, self.name,
28  self.alignmentToValidate.name )
29  repMap = self.getRepMap()
30 
31  cfgs = {cfgName:replaceByMap( configTemplates.offlineTemplate, repMap)}
32  self.filesToCompare[
33  GenericValidationData.defaultReferenceName ] = repMap["resultFile"]
34  GenericValidationData.createConfiguration(self, cfgs, path)
35 
36  def createScript(self, path, scriptBaseName = "TkAlOfflineValidation"):
37  scriptName = "%s.%s.%s.sh"%( scriptBaseName, self.name,
38  self.alignmentToValidate.name )
39  repMap = self.getRepMap()
40  repMap["CommandLine"]=""
41  for cfg in self.configFiles:
42  repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfg,
43  "postProcess":""
44  }
45  scripts = {scriptName: replaceByMap( configTemplates.scriptTemplate,
46  repMap ) }
47  return GenericValidationData.createScript(self, scripts, path)
48 
49  def createCrabCfg(self, path, crabCfgBaseName = "TkAlOfflineValidation"):
50  return GenericValidationData.createCrabCfg(self, path, crabCfgBaseName)
51 
52  def getRepMap(self, alignment = None):
53  repMap = GenericValidationData.getRepMap(self, alignment)
54  repMap.update({
55  "nEvents": self.general["maxevents"],
56  "outputFile": replaceByMap( ("AlignmentValidation_"
57  + self.name +
58  "_.oO[name]Oo..root"), repMap ),
59  "resultFile": replaceByMap( ("/store/caf/user/$USER/.oO[eosdir]Oo."
60  "/AlignmentValidation_"
61  + self.name +
62  "_.oO[name]Oo..root"), repMap ),
63  "TrackSelectionTemplate": configTemplates.TrackSelectionTemplate,
64  "LorentzAngleTemplate": configTemplates.LorentzAngleTemplate,
65  "offlineValidationMode": "Standalone",
66  "offlineValidationFileOutput":
67  configTemplates.offlineStandaloneFileOutputTemplate,
68  "TrackCollection": self.general["trackcollection"]
69  })
70  repMap["outputFile"] = os.path.expandvars( repMap["outputFile"] )
71  repMap["resultFile"] = os.path.expandvars( repMap["resultFile"] )
72  return repMap
73 
74  def appendToExtendedValidation( self, validationsSoFar = "" ):
75  """
76  if no argument or "" is passed a string with an instantiation is
77  returned, else the validation is appended to the list
78  """
79  repMap = self.getRepMap()
80  if validationsSoFar == "":
81  validationsSoFar = ('PlotAlignmentValidation p("%(outputFile)s",'
82  '"%(name)s", %(color)s, %(style)s);\n')%repMap
83  else:
84  validationsSoFar += ('p.loadFileList("%(outputFile)s", "%(name)s",'
85  '%(color)s, %(style)s);\n')%repMap
86  return validationsSoFar
87 
88  def appendToMerge( self, mergesSoFar = "" ):
89  """
90  append all merges here
91  """
92  repMap = self.getRepMap()
93  mergesSoFar += replaceByMap(configTemplates.mergeOfflineParallelResults,
94  repMap)
95  return mergesSoFar
96 
97 
99  def __init__(self, valName, alignment,config):
100  OfflineValidation.__init__(self, valName, alignment, config)
101  defaults = {
102  "parallelJobs":"1",
103  "jobmode":self.jobmode
104  }
105  offline = config.getResultingSection( "offline:"+self.name,
106  defaultDict = defaults )
107  self.general.update( offline )
108  self.__NJobs = self.general["parallelJobs"]
109  self.outputFiles = []
110  for index in range(int(self.general["parallelJobs"])):
111  fName = replaceByMap("AlignmentValidation_"+self.name
112  +"_.oO[name]Oo._%d.root"%(index),
113  self.getRepMap())
114  self.outputFiles.append(fName)
115 
116 
117  def createConfiguration(self, path, configBaseName = "TkAlOfflineValidation"):
118  # if offline validation uses N parallel jobs, we create here N cfg files
119  numberParallelJobs = int( self.general["parallelJobs"] )
120  # limit maximum number of parallel jobs to 40
121  # (each output file is approximately 20MB)
122  maximumNumberJobs = 40
123  if numberParallelJobs > maximumNumberJobs:
124  msg = ("Maximum allowed number of parallel jobs "
125  +str(maximumNumberJobs)+" exceeded!!!")
126  raise AllInOneError(msg)
127  # if maxevents is not specified, cannot calculate number of events for
128  # each parallel job, and therefore running only a single job
129  if int( self.general["maxevents"] ) == -1:
130  msg = ("Maximum number of events (maxevents) not specified: "
131  "cannot use parallel jobs in offline validation")
132  raise AllInOneError(msg)
133  if numberParallelJobs > 1:
134  if self.general["offlineModuleLevelHistsTransient"] == "True":
135  msg = ("To be able to merge results when running parallel jobs,"
136  " set offlineModuleLevelHistsTransient to false.")
137  raise AllInOneError(msg)
138  for index in range(numberParallelJobs):
139  cfgName = "%s.%s.%s_%s_cfg.py"%(configBaseName, self.name,
140  self.alignmentToValidate.name,
141  str(index))
142  repMap = self.getRepMap()
143  # in this parallel job, skip index*(maxEvents/nJobs) events from
144  # the beginning
145  # (first index is zero, so no skipping for a single job)
146  # and use _index_ in the name of the output file
147  repMap.update({"nIndex": str(index)})
148  # Create the result file directly to datadir since should not use /tmp/
149  # see https://cern.service-now.com/service-portal/article.do?n=KB0000484
150  repMap.update({"outputFile": self.outputFiles[index]})
151  repMap["outputFile"] = os.path.expandvars( repMap["outputFile"] )
152 
153  cfgs = {cfgName:replaceByMap(configTemplates.offlineParallelTemplate,
154  repMap)}
155  self.filesToCompare[GenericValidationData.defaultReferenceName] = repMap["resultFile"]
156  GenericValidationData.createConfiguration(self, cfgs, path)
157  # here is a small problem. only the last cfgs is saved
158  # it requires a bit ugly solution later
159 
160  def createScript(self, path, scriptBaseName = "TkAlOfflineValidation"):
161  # A separate script is created for each parallel jobs.
162  # Since only one cfg is saved a bit ugly solution is needed in the loop.
163  returnValue = []
164  numJobs = int( self.general["parallelJobs"] )
165  for index in range(numJobs):
166  scriptName = "%s.%s.%s_%s.sh"%(scriptBaseName, self.name,
167  self.alignmentToValidate.name,
168  str(index))
169  repMap = self.getRepMap()
170  repMap["nIndex"]=""
171  repMap["nIndex"]=str(index)
172  repMap["CommandLine"]=""
173  repMap.update({"outputFile": self.outputFiles[index]})
174  for cfg in self.configFiles:
175  # The ugly solution here is to change the name for each parallel job
176  cfgtemp = cfg.replace(str(numJobs-1)+"_cfg.py",
177  str(index)+"_cfg.py")
178  repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfgtemp,
179  "postProcess":""
180  }
181  scripts = {scriptName: replaceByMap(configTemplates.parallelScriptTemplate,
182  repMap ) }
183  returnValue.extend(GenericValidationData.createScript(self,
184  scripts,
185  path) )
186  return returnValue
187 
188  def getRepMap(self, alignment = None):
189  repMap = OfflineValidation.getRepMap(self, alignment)
190  repMap.update({
191  "nJobs": self.general["parallelJobs"],
192  "offlineValidationFileOutput":
193  configTemplates.offlineParallelFileOutputTemplate,
194  "nameValidation": self.name
195  })
196  # In case maxevents==-1, set number of parallel jobs to 1
197  # since we cannot calculate number of events for each
198  # parallel job
199  if str(self.general["maxevents"]) == "-1":
200  repMap.update({ "nJobs": "1" })
201  return repMap
202 
203  def appendToMergeParJobs( self, validationsSoFar = "" ):
204  """
205  if no argument or "" is passed a string with an instantiation is returned,
206  else the validation is appended to the list
207  """
208  repMap = self.getRepMap()
209 
210  parameters = ""
211  fileToAdd = ""
212  for index in range(int(self.__NJobs)):
213  fileToAdd = '%(outputFile)s'%repMap
214  fileToAdd = fileToAdd.replace('.root','_'+str(index)+'.root')
215  if index < int( self.general["parallelJobs"] )-1:
216  parameters = parameters+fileToAdd+','
217  else:
218  parameters = parameters+fileToAdd
219 
220  mergedoutputfile = ("AlignmentValidation_" + self.name + "_"
221  + '%(name)s'%repMap + ".root")
222  validationsSoFar += ('root -x -b -q "TkAlOfflineJobsMerge.C(\\\"'
223  +parameters+'\\\",\\\"'+mergedoutputfile+'\\\")"'
224  +"\n")
225  return validationsSoFar
226 
227  def createCrabCfg( self ):
228  msg = ("jobmode 'crab' not supported for 'offlineParallel' validation."
229  " Please choose another 'jobmode'.")
230  raise AllInOneError(msg)
231 
232 
234  def __init__(self, valName, alignment, config):
235  OfflineValidation.__init__(self, valName, alignment, config)
236  if not config.has_section("DQM"):
237  msg = "You need to have a DQM section in your configfile!"
238  raise AllInOneError(msg)
239 
240  self.__PrimaryDataset = config.get("DQM", "primaryDataset")
241  self.__firstRun = int(config.get("DQM", "firstRun"))
242  self.__lastRun = int(config.get("DQM", "lastRun"))
243 
244  def createConfiguration(self, path):
245  OfflineValidation.createConfiguration(self, path,
246  "TkAlOfflineValidationDQM")
247 
248  def createScript(self, path):
249  return OfflineValidation.createScript(self, path,
250  "TkAlOfflineValidationDQM")
251 
252  def getRepMap(self, alignment = None):
253  repMap = OfflineValidation.getRepMap(self, alignment)
254  repMap.update({
255  "workdir": os.path.expandvars(repMap["workdir"]),
256  "offlineValidationMode": "Dqm",
257  "offlineValidationFileOutput": configTemplates.offlineDqmFileOutputTemplate,
258  "workflow": ("/%s/TkAl%s-.oO[alignmentName]Oo._R%09i_R%09i_"
259  "ValSkim-v1/ALCARECO"
260  %(self.__PrimaryDataset,
261  datetime.datetime.now().strftime("%y"),
262  self.__firstRun, self.__lastRun)),
263  "firstRunNumber": "%i"% self.__firstRun
264  })
265  if "__" in repMap["workflow"]:
266  msg = ("the DQM workflow specefication must not contain '__'. "
267  "it is: %s"%repMap["workflow"])
268  raise AllInOneError(msg)
269  return repMap
def replaceByMap
— Helpers —############################