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 
110  def createConfiguration(self, path, configBaseName = "TkAlOfflineValidation"):
111  # if offline validation uses N parallel jobs, we create here N cfg files
112  numberParallelJobs = int( self.general["parallelJobs"] )
113  # limit maximum number of parallel jobs to 40
114  # (each output file is approximately 20MB)
115  maximumNumberJobs = 40
116  if numberParallelJobs > maximumNumberJobs:
117  msg = ("Maximum allowed number of parallel jobs "
118  +str(maximumNumberJobs)+" exceeded!!!")
119  raise AllInOneError(msg)
120  # if maxevents is not specified, cannot calculate number of events for
121  # each parallel job, and therefore running only a single job
122  if int( self.general["maxevents"] ) == -1:
123  msg = ("Maximum number of events (maxevents) not specified: "
124  "cannot use parallel jobs in offline validation")
125  raise AllInOneError(msg)
126  if numberParallelJobs > 1:
127  if self.general["offlineModuleLevelHistsTransient"] == "True":
128  msg = ("To be able to merge results when running parallel jobs,"
129  " set offlineModuleLevelHistsTransient to false.")
130  raise AllInOneError(msg)
131  for index in range(numberParallelJobs):
132  cfgName = "%s.%s.%s_%s_cfg.py"%(configBaseName, self.name,
133  self.alignmentToValidate.name,
134  str(index))
135  repMap = self.getRepMap()
136  # in this parallel job, skip index*(maxEvents/nJobs) events from
137  # the beginning
138  # (first index is zero, so no skipping for a single job)
139  # and use _index_ in the name of the output file
140  repMap.update({"nIndex": str(index)})
141  # Create the result file directly to datadir since should not use /tmp/
142  # see https://cern.service-now.com/service-portal/article.do?n=KB0000484
143  repMap.update({
144  "outputFile": replaceByMap("AlignmentValidation_"
145  + self.name +
146  "_.oO[name]Oo._.oO[nIndex]Oo..root",
147  repMap )
148  })
149  repMap["outputFile"] = os.path.expandvars( repMap["outputFile"] )
150 
151  cfgs = {cfgName:replaceByMap(configTemplates.offlineParallelTemplate,
152  repMap)}
153  self.filesToCompare[GenericValidationData.defaultReferenceName] = repMap["resultFile"]
154  GenericValidationData.createConfiguration(self, cfgs, path)
155  # here is a small problem. only the last cfgs is saved
156  # it requires a bit ugly solution later
157 
158  def createScript(self, path, scriptBaseName = "TkAlOfflineValidation"):
159  # A separate script is created for each parallel jobs.
160  # Since only one cfg is saved a bit ugly solution is needed in the loop.
161  returnValue = []
162  numJobs = int( self.general["parallelJobs"] )
163  for index in range(numJobs):
164  scriptName = "%s.%s.%s_%s.sh"%(scriptBaseName, self.name,
165  self.alignmentToValidate.name,
166  str(index))
167  repMap = self.getRepMap()
168  repMap["nIndex"]=""
169  repMap["nIndex"]=str(index)
170  repMap["CommandLine"]=""
171  repMap.update({
172  "outputFile": replaceByMap("AlignmentValidation_"
173  + self.name +
174  "_.oO[name]Oo._.oO[nIndex]Oo..root",
175  repMap )
176  })
177  for cfg in self.configFiles:
178  # The ugly solution here is to change the name for each parallel job
179  cfgtemp = cfg.replace(str(numJobs-1)+"_cfg.py",
180  str(index)+"_cfg.py")
181  repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfgtemp,
182  "postProcess":""
183  }
184  scripts = {scriptName: replaceByMap(configTemplates.parallelScriptTemplate,
185  repMap ) }
186  returnValue.extend(GenericValidationData.createScript(self,
187  scripts,
188  path) )
189  return returnValue
190 
191  def getRepMap(self, alignment = None):
192  repMap = OfflineValidation.getRepMap(self, alignment)
193  repMap.update({
194  "nJobs": self.general["parallelJobs"],
195  "offlineValidationFileOutput":
196  configTemplates.offlineParallelFileOutputTemplate,
197  "nameValidation": self.name
198  })
199  # In case maxevents==-1, set number of parallel jobs to 1
200  # since we cannot calculate number of events for each
201  # parallel job
202  if str(self.general["maxevents"]) == "-1":
203  repMap.update({ "nJobs": "1" })
204  return repMap
205 
206  def appendToMergeParJobs( self, validationsSoFar = "" ):
207  """
208  if no argument or "" is passed a string with an instantiation is returned,
209  else the validation is appended to the list
210  """
211  repMap = self.getRepMap()
212 
213  parameters = ""
214  fileToAdd = ""
215  for index in range(int(self.__NJobs)):
216  fileToAdd = '%(outputFile)s'%repMap
217  fileToAdd = fileToAdd.replace('.root','_'+str(index)+'.root')
218  if index < int( self.general["parallelJobs"] )-1:
219  parameters = parameters+fileToAdd+','
220  else:
221  parameters = parameters+fileToAdd
222 
223  mergedoutputfile = ("AlignmentValidation_" + self.name + "_"
224  + '%(name)s'%repMap + ".root")
225  validationsSoFar += ('root -x -b -q "TkAlOfflineJobsMerge.C(\\\"'
226  +parameters+'\\\",\\\"'+mergedoutputfile+'\\\")"'
227  +"\n")
228  return validationsSoFar
229 
230  def createCrabCfg( self ):
231  msg = ("jobmode 'crab' not supported for 'offlineParallel' validation."
232  " Please choose another 'jobmode'.")
233  raise AllInOneError(msg)
234 
235 
237  def __init__(self, valName, alignment, config):
238  OfflineValidation.__init__(self, valName, alignment, config)
239  if not config.has_section("DQM"):
240  msg = "You need to have a DQM section in your configfile!"
241  raise AllInOneError(msg)
242 
243  self.__PrimaryDataset = config.get("DQM", "primaryDataset")
244  self.__firstRun = int(config.get("DQM", "firstRun"))
245  self.__lastRun = int(config.get("DQM", "lastRun"))
246 
247  def createConfiguration(self, path):
248  OfflineValidation.createConfiguration(self, path,
249  "TkAlOfflineValidationDQM")
250 
251  def createScript(self, path):
252  return OfflineValidation.createScript(self, path,
253  "TkAlOfflineValidationDQM")
254 
255  def getRepMap(self, alignment = None):
256  repMap = OfflineValidation.getRepMap(self, alignment)
257  repMap.update({
258  "workdir": os.path.expandvars(repMap["workdir"]),
259  "offlineValidationMode": "Dqm",
260  "offlineValidationFileOutput": configTemplates.offlineDqmFileOutputTemplate,
261  "workflow": ("/%s/TkAl%s-.oO[alignmentName]Oo._R%09i_R%09i_"
262  "ValSkim-v1/ALCARECO"
263  %(self.__PrimaryDataset,
264  datetime.datetime.now().strftime("%y"),
265  self.__firstRun, self.__lastRun)),
266  "firstRunNumber": "%i"% self.__firstRun
267  })
268  if "__" in repMap["workflow"]:
269  msg = ("the DQM workflow specefication must not contain '__'. "
270  "it is: %s"%repMap["workflow"])
271  raise AllInOneError(msg)
272  return repMap
def replaceByMap
— Helpers —############################