CMS 3D CMS Logo

validateAlignments.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #test execute: export CMSSW_BASE=/tmp/CMSSW && ./validateAlignments.py -c defaultCRAFTValidation.ini,test.ini -n -N test
3 from __future__ import print_function
4 import os
5 import sys
6 import optparse
7 import datetime
8 import shutil
9 import fnmatch
10 
11 import six
12 import Alignment.OfflineValidation.TkAlAllInOneTool.configTemplates \
13  as configTemplates
14 import Alignment.OfflineValidation.TkAlAllInOneTool.crabWrapper as crabWrapper
15 from Alignment.OfflineValidation.TkAlAllInOneTool.TkAlExceptions \
16  import AllInOneError
17 from Alignment.OfflineValidation.TkAlAllInOneTool.helperFunctions \
18  import replaceByMap, getCommandOutput2, addIndex
19 from Alignment.OfflineValidation.TkAlAllInOneTool.betterConfigParser \
20  import BetterConfigParser
21 from Alignment.OfflineValidation.TkAlAllInOneTool.alignment import Alignment
22 
24  import GenericValidation, ParallelValidation, ValidationWithComparison, ValidationWithPlots
25 from Alignment.OfflineValidation.TkAlAllInOneTool.geometryComparison \
26  import GeometryComparison
28  import OfflineValidation, OfflineValidationDQM
29 from Alignment.OfflineValidation.TkAlAllInOneTool.monteCarloValidation \
30  import MonteCarloValidation
32  import TrackSplittingValidation
34  import ZMuMuValidation
36  import PrimaryVertexValidation
37 from Alignment.OfflineValidation.TkAlAllInOneTool.preexistingValidation \
38  import *
39 from Alignment.OfflineValidation.TkAlAllInOneTool.plottingOptions \
40  import PlottingOptions
41 import Alignment.OfflineValidation.TkAlAllInOneTool.globalDictionaries \
42  as globalDictionaries
43 from Alignment.OfflineValidation.TkAlAllInOneTool.overlapValidation \
44  import OverlapValidation
45 
46 ####################--- Classes ---############################
48 
49  def __init__(self, _name, _path, _dependency):
50  self.name=_name
51  self.path=_path
52  self.dependencies=_dependency
53  def addDependency(self,dependency):
54  if isinstance(dependency,list):
55  self.dependencies.extend(dependency)
56  else:
57  self.dependencies.append(dependency)
58  def runJob(self, config):
59  repMap = {
60  "commands": config.getGeneral()["jobmode"].split(",")[1],
61  "jobName": self.name,
62  "logDir": config.getGeneral()["logdir"],
63  "script": self.path,
64  "bsub": "/afs/cern.ch/cms/caf/scripts/cmsbsub",
65  "conditions": '"' + " && ".join(["ended(" + jobId + ")" for jobId in self.dependencies]) + '"'
66  }
67  return getCommandOutput2("%(bsub)s %(commands)s "
68  "-J %(jobName)s "
69  "-o %(logDir)s/%(jobName)s.stdout "
70  "-e %(logDir)s/%(jobName)s.stderr "
71  "-w %(conditions)s "
72  "%(script)s"%repMap)
73 
75 
76  # these count the jobs of different varieties that are being run
77  crabCount = 0
78  interactCount = 0
79  batchCount = 0
80  batchJobIds = []
81  jobCount = 0
82 
83  def __init__( self, validation, config, options ):
84  self.JobId=[]
85  if validation[1] == "":
86  # intermediate syntax
87  valString = validation[0].split( "->" )[0]
88  alignments = validation[0].split( "->" )[1]
89  # force user to use the normal syntax
90  if "->" in validation[0]:
91  msg = ("Instead of using the intermediate syntax\n'"
92  +valString.strip()+"-> "+alignments.strip()
93  +":'\nyou have to use the now fully supported syntax \n'"
94  +valString.strip()+": "
95  +alignments.strip()+"'.")
96  raise AllInOneError(msg)
97  else:
98  valString = validation[0]
99  alignments = validation[1]
100  valString = valString.split()
101  self.__valType = valString[0]
102  self.__valName = valString[1]
103  self.__commandLineOptions = options
104  self.__config = config
105  self.__preexisting = ("preexisting" in self.__valType)
106  if self.__valType[0] == "*":
107  self.__valType = self.__valType[1:]
108  self.__preexisting = True
109 
110  # workaround for intermediate parallel version
111  if self.__valType == "offlineParallel":
112  print ("offlineParallel and offline are now the same. To run an offline parallel validation,\n"
113  "just set parallelJobs to something > 1. There is no reason to call it offlineParallel anymore.")
114  self.__valType = "offline"
115  section = self.__valType + ":" + self.__valName
116  if not self.__config.has_section( section ):
117  raise AllInOneError("Validation '%s' of type '%s' is requested in"
118  " '[validation]' section, but is not defined."
119  "\nYou have to add a '[%s]' section."
120  %( self.__valName, self.__valType, section ))
122  alignments, self.__config,
123  options )
124 
125  def __getValidation( self, valType, name, alignments, config, options ):
126  if valType == "compare":
127  alignmentsList = alignments.split( "," )
128  firstAlignList = alignmentsList[0].split()
129  firstAlignName = firstAlignList[0].strip()
130  if firstAlignName == "IDEAL":
131  raise AllInOneError("'IDEAL' has to be the second (reference)"
132  " alignment in 'compare <val_name>: "
133  "<alignment> <reference>'.")
134  if len( firstAlignList ) > 1:
135  firstRun = firstAlignList[1]
136  else:
137  raise AllInOneError("Have to provide a run number for geometry comparison")
138  firstAlign = Alignment( firstAlignName, self.__config, firstRun )
139  firstAlignName = firstAlign.name
140  secondAlignList = alignmentsList[1].split()
141  secondAlignName = secondAlignList[0].strip()
142  if secondAlignName == "IDEAL":
143  secondAlign = secondAlignName
144  else:
145  if len( secondAlignList ) > 1:
146  secondRun = secondAlignList[1]
147  else:
148  raise AllInOneError("Have to provide a run number for geometry comparison")
149  secondAlign = Alignment( secondAlignName, self.__config,
150  secondRun )
151  secondAlignName = secondAlign.name
152 
153  validation = GeometryComparison( name, firstAlign, secondAlign,
154  self.__config,
155  self.__commandLineOptions.getImages)
156  elif valType == "offline":
157  validation = OfflineValidation( name,
158  Alignment( alignments.strip(), self.__config ), self.__config )
159  elif valType == "preexistingoffline":
160  validation = PreexistingOfflineValidation(name, self.__config)
161  elif valType == "offlineDQM":
162  validation = OfflineValidationDQM( name,
163  Alignment( alignments.strip(), self.__config ), self.__config )
164  elif valType == "mcValidate":
165  validation = MonteCarloValidation( name,
166  Alignment( alignments.strip(), self.__config ), self.__config )
167  elif valType == "preexistingmcValidate":
168  validation = PreexistingMonteCarloValidation(name, self.__config)
169  elif valType == "split":
170  validation = TrackSplittingValidation( name,
171  Alignment( alignments.strip(), self.__config ), self.__config )
172  elif valType == "preexistingsplit":
173  validation = PreexistingTrackSplittingValidation(name, self.__config)
174  elif valType == "zmumu":
175  validation = ZMuMuValidation( name,
176  Alignment( alignments.strip(), self.__config ), self.__config )
177  elif valType == "primaryvertex":
178  validation = PrimaryVertexValidation( name,
179  Alignment( alignments.strip(), self.__config ), self.__config )
180  elif valType == "preexistingprimaryvertex":
181  validation = PreexistingPrimaryVertexValidation(name, self.__config)
182  elif valType == "overlap":
183  validation = OverlapValidation( name,
184  Alignment( alignments.strip(), self.__config ), self.__config )
185  else:
186  raise AllInOneError("Unknown validation mode '%s'"%valType)
187 
188  return validation
189 
190  def __createJob( self, jobMode, outpath ):
191  """This private method creates the needed files for the validation job.
192  """
193  self.validation.createConfiguration( outpath )
194  if self.__preexisting:
195  return
196  self.__scripts = sum([addIndex(script, self.validation.NJobs) for script in self.validation.createScript( outpath )], [])
197  if jobMode.split( ',' )[0] == "crab":
198  self.validation.createCrabCfg( outpath )
199  return None
200 
201  def createJob(self):
202  """This is the method called to create the job files."""
203  self.__createJob( self.validation.jobmode,
204  os.path.abspath( self.__commandLineOptions.Name) )
205 
206  def runJob( self ):
207  if self.__preexisting:
208  if self.validation.jobid:
209  self.batchJobIds.append(self.validation.jobid)
210  log = "> " + self.validation.name + " is already validated."
211  print(log)
212  return log
213  else:
214  if self.validation.jobid:
215  print("jobid {} will be ignored, since the validation {} is not preexisting".format(self.validation.jobid, self.validation.name))
216 
217  general = self.__config.getGeneral()
218  log = ""
219  for script in self.__scripts:
220  name = os.path.splitext( os.path.basename( script) )[0]
221  ValidationJob.jobCount += 1
222  if self.__commandLineOptions.dryRun:
223  print("%s would run: %s"%( name, os.path.basename( script) ))
224  continue
225  log = "> Validating "+name
226  print("> Validating "+name)
227  if self.validation.jobmode == "interactive":
228  log += getCommandOutput2( script )
229  ValidationJob.interactCount += 1
230  elif self.validation.jobmode.split(",")[0] == "lxBatch":
231  repMap = {
232  "commands": self.validation.jobmode.split(",")[1],
233  "logDir": general["logdir"],
234  "jobName": name,
235  "script": script,
236  "bsub": "/afs/cern.ch/cms/caf/scripts/cmsbsub"
237  }
238  for ext in ("stdout", "stderr", "stdout.gz", "stderr.gz"):
239  oldlog = "%(logDir)s/%(jobName)s."%repMap + ext
240  if os.path.exists(oldlog):
241  os.remove(oldlog)
242  bsubOut=getCommandOutput2("%(bsub)s %(commands)s "
243  "-J %(jobName)s "
244  "-o %(logDir)s/%(jobName)s.stdout "
245  "-e %(logDir)s/%(jobName)s.stderr "
246  "%(script)s"%repMap)
247  #Attention: here it is assumed that bsub returns a string
248  #containing a job id like <123456789>
249  jobid=bsubOut.split("<")[1].split(">")[0]
250  self.JobId.append(jobid)
251  ValidationJob.batchJobIds.append(jobid)
252  log+=bsubOut
253  ValidationJob.batchCount += 1
254  elif self.validation.jobmode.split( "," )[0] == "crab":
255  os.chdir( general["logdir"] )
256  crabName = "crab." + os.path.basename( script )[:-3]
257  theCrab = crabWrapper.CrabWrapper()
258  options = { "-create": "",
259  "-cfg": crabName + ".cfg",
260  "-submit": "" }
261  try:
262  theCrab.run( options )
263  except AllInOneError as e:
264  print("crab:", str(e).split("\n")[0])
265  exit(1)
266  ValidationJob.crabCount += 1
267 
268  else:
269  raise AllInOneError("Unknown 'jobmode'!\n"
270  "Please change this parameter either in "
271  "the [general] or in the ["
272  + self.__valType + ":" + self.__valName
273  + "] section to one of the following "
274  "values:\n"
275  "\tinteractive\n\tlxBatch, -q <queue>\n"
276  "\tcrab, -q <queue>")
277 
278  return log
279 
280  def getValidation( self ):
281  return self.validation
282 
283  @property
284  def needsproxy(self):
285  return self.validation.needsproxy and not self.__preexisting and not self.__commandLineOptions.dryRun
286 
287 
288 ####################--- Functions ---############################
289 def createMergeScript( path, validations, options ):
290  if(len(validations) == 0):
291  raise AllInOneError("Cowardly refusing to merge nothing!")
292 
293  config = validations[0].config
294  repMap = config.getGeneral()
295  repMap.update({
296  "DownloadData":"",
297  "CompareAlignments":"",
298  "RunValidationPlots":"",
299  "CMSSW_BASE": os.environ["CMSSW_BASE"],
300  "SCRAM_ARCH": os.environ["SCRAM_ARCH"],
301  "CMSSW_RELEASE_BASE": os.environ["CMSSW_RELEASE_BASE"],
302  })
303 
304  comparisonLists = {} # directory of lists containing the validations that are comparable
305  for validation in validations:
306  for referenceName in validation.filesToCompare:
307  validationtype = type(validation)
308  if issubclass(validationtype, PreexistingValidation):
309  #find the actual validationtype
310  for parentclass in validationtype.mro():
311  if not issubclass(parentclass, PreexistingValidation):
312  validationtype = parentclass
313  break
314  key = (validationtype, referenceName)
315  if key in comparisonLists:
316  comparisonLists[key].append(validation)
317  else:
318  comparisonLists[key] = [validation]
319 
320  # introduced to merge individual validation outputs separately
321  # -> avoids problems with merge script
322  repMap["doMerge"] = "mergeRetCode=0\n"
323  repMap["rmUnmerged"] = ("if [[ mergeRetCode -eq 0 ]]; then\n"
324  " echo -e \\n\"Merging succeeded, removing original files.\"\n")
325  repMap["beforeMerge"] = ""
326  repMap["mergeParallelFilePrefixes"] = ""
327  repMap["createResultsDirectory"]=""
328 
329 
330  anythingToMerge = []
331 
332 
333  #prepare dictionary containing handle objects for parallel merge batch jobs
334  if options.mergeOfflineParallel:
335  parallelMergeObjects={}
336  for (validationType, referencename), validations in six.iteritems(comparisonLists):
337  for validation in validations:
338  #parallel merging
339  if (isinstance(validation, PreexistingValidation)
340  or validation.NJobs == 1
341  or not isinstance(validation, ParallelValidation)):
342  continue
343  if options.mergeOfflineParallel and validationType.valType=='offline' and validation.jobmode.split(",")[0]=="lxBatch":
344  repMapTemp=repMap.copy()
345  if validationType not in anythingToMerge:
346  anythingToMerge += [validationType]
347  #create init script
348  fileName="TkAlMergeInit"
349  filePath = os.path.join(path, fileName+".sh")
350  theFile = open( filePath, "w" )
351  repMapTemp["createResultsDirectory"]="#!/bin/bash"
352  repMapTemp["createResultsDirectory"]+=replaceByMap(configTemplates.createResultsDirectoryTemplate, repMapTemp)
353  theFile.write( replaceByMap( configTemplates.createResultsDirectoryTemplate, repMapTemp ) )
354  theFile.close()
355  os.chmod(filePath,0o755)
356  #create handle
357  parallelMergeObjects["init"]=ParallelMergeJob(fileName, filePath,[])
358  #clear 'create result directory' code
359  repMapTemp["createResultsDirectory"]=""
360 
361  #edit repMapTmp as necessary:
362  #fill contents of mergeParallelResults
363  repMapTemp["beforeMerge"] += validationType.doInitMerge()
364  repMapTemp["doMerge"] += '\n\n\n\necho -e "\n\nMerging results from %s jobs with alignment %s"\n\n' % (validationType.valType,validation.alignmentToValidate.name)
365  repMapTemp["doMerge"] += validation.doMerge()
366  for f in validation.getRepMap()["outputFiles"]:
367  longName = os.path.join("/eos/cms/store/group/alca_trackeralign/AlignmentValidation/",
368  validation.getRepMap()["eosdir"], f)
369  repMapTemp["rmUnmerged"] += " rm "+longName+"\n"
370 
371  repMapTemp["rmUnmerged"] += ("else\n"
372  " echo -e \\n\"WARNING: Merging failed, unmerged"
373  " files won't be deleted.\\n"
374  "(Ignore this warning if merging was done earlier)\"\n"
375  "fi\n")
376 
377  #fill mergeParallelResults area of mergeTemplate
378  repMapTemp["DownloadData"] = replaceByMap( configTemplates.mergeParallelResults, repMapTemp )
379  #fill runValidationPlots area of mergeTemplate
380  repMapTemp["RunValidationPlots"] = validationType.doRunPlots(validations)
381 
382  #create script file
383  fileName="TkAlMergeOfflineValidation"+validation.name+validation.alignmentToValidate.name
384  filePath = os.path.join(path, fileName+".sh")
385  theFile = open( filePath, "w" )
386  theFile.write( replaceByMap( configTemplates.mergeParallelOfflineTemplate, repMapTemp ) )
387  theFile.close()
388  os.chmod(filePath,0o755)
389  #create handle object
390  if "parallel" in parallelMergeObjects:
391  parallelMergeObjects["parallel"].append(ParallelMergeJob(fileName, filePath,[]))
392  else:
393  parallelMergeObjects["parallel"]=[ParallelMergeJob(fileName, filePath,[])]
394  continue
395 
396 
397  else:
398  if validationType not in anythingToMerge:
399  anythingToMerge += [validationType]
400  repMap["doMerge"] += '\n\n\n\necho -e "\n\nMerging results from %s jobs"\n\n' % validationType.valType
401  repMap["beforeMerge"] += validationType.doInitMerge()
402  repMap["doMerge"] += validation.doMerge()
403  for f in validation.getRepMap()["outputFiles"]:
404  longName = os.path.join("/eos/cms/store/group/alca_trackeralign/AlignmentValidation/",
405  validation.getRepMap()["eosdir"], f)
406  repMap["rmUnmerged"] += " rm "+longName+"\n"
407 
408 
409 
410  repMap["rmUnmerged"] += ("else\n"
411  " echo -e \\n\"WARNING: Merging failed, unmerged"
412  " files won't be deleted.\\n"
413  "(Ignore this warning if merging was done earlier)\"\n"
414  "fi\n")
415 
416 
417 
418  if anythingToMerge:
419  repMap["DownloadData"] += replaceByMap( configTemplates.mergeParallelResults, repMap )
420  else:
421  repMap["DownloadData"] = ""
422 
423  repMap["RunValidationPlots"] = ""
424  for (validationType, referencename), validations in six.iteritems(comparisonLists):
425  if issubclass(validationType, ValidationWithPlots):
426  repMap["RunValidationPlots"] += validationType.doRunPlots(validations)
427 
428  repMap["CompareAlignments"] = "#run comparisons"
429  for (validationType, referencename), validations in six.iteritems(comparisonLists):
430  if issubclass(validationType, ValidationWithComparison):
431  repMap["CompareAlignments"] += validationType.doComparison(validations)
432 
433  #if user wants to merge parallely and if there are valid parallel scripts, create handle for plotting job and set merge script name accordingly
434  if options.mergeOfflineParallel and parallelMergeObjects!={}:
435  parallelMergeObjects["continue"]=ParallelMergeJob("TkAlMergeFinal",os.path.join(path, "TkAlMergeFinal.sh"),[])
436  filePath = os.path.join(path, "TkAlMergeFinal.sh")
437  #if not merging parallel, add code to create results directory and set merge script name accordingly
438  else:
439  repMap["createResultsDirectory"]=replaceByMap(configTemplates.createResultsDirectoryTemplate, repMap)
440  filePath = os.path.join(path, "TkAlMerge.sh")
441 
442 
443  #filePath = os.path.join(path, "TkAlMerge.sh")
444  theFile = open( filePath, "w" )
445  theFile.write( replaceByMap( configTemplates.mergeTemplate, repMap ) )
446  theFile.close()
447  os.chmod(filePath,0o755)
448 
449  if options.mergeOfflineParallel:
450  return {'TkAlMerge.sh':filePath, 'parallelMergeObjects':parallelMergeObjects}
451  else:
452  return filePath
453 
454 def loadTemplates( config ):
455  if config.has_section("alternateTemplates"):
456  for templateName in config.options("alternateTemplates"):
457  if templateName == "AutoAlternates":
458  continue
459  newTemplateName = config.get("alternateTemplates", templateName )
460  #print "replacing default %s template by %s"%( templateName, newTemplateName)
461  configTemplates.alternateTemplate(templateName, newTemplateName)
462 
463 
464 ####################--- Main ---############################
465 def main(argv = None):
466  if argv == None:
467  argv = sys.argv[1:]
468  optParser = optparse.OptionParser()
469  optParser.description = """All-in-one Alignment Validation.
470 This will run various validation procedures either on batch queues or interactively.
471 If no name is given (-N parameter) a name containing time and date is created automatically.
472 To merge the outcome of all validation procedures run TkAlMerge.sh in your validation's directory.
473 """
474  optParser.add_option("-n", "--dryRun", dest="dryRun", action="store_true", default=False,
475  help="create all scripts and cfg File but do not start jobs (default=False)")
476  optParser.add_option( "--getImages", dest="getImages", action="store_true", default=True,
477  help="get all Images created during the process (default= True)")
478  defaultConfig = "TkAlConfig.ini"
479  optParser.add_option("-c", "--config", dest="config", default = defaultConfig,
480  help="configuration to use (default TkAlConfig.ini) this can be a comma-seperated list of all .ini file you want to merge", metavar="CONFIG")
481  optParser.add_option("-N", "--Name", dest="Name",
482  help="Name of this validation (default: alignmentValidation_DATE_TIME)", metavar="NAME")
483  optParser.add_option("-r", "--restrictTo", dest="restrictTo",
484  help="restrict validations to given modes (comma seperated) (default: no restriction)", metavar="RESTRICTTO")
485  optParser.add_option("-s", "--status", dest="crabStatus", action="store_true", default = False,
486  help="get the status of the crab jobs", metavar="STATUS")
487  optParser.add_option("-d", "--debug", dest="debugMode", action="store_true",
488  default = False,
489  help="run the tool to get full traceback of errors",
490  metavar="DEBUG")
491  optParser.add_option("-m", "--autoMerge", dest="autoMerge", action="store_true", default = False,
492  help="submit TkAlMerge.sh to run automatically when all jobs have finished (default=False)."
493  " Works only for batch jobs")
494  optParser.add_option("--mergeOfflineParallel", dest="mergeOfflineParallel", action="store_true", default = False,
495  help="Enable parallel merging of offline data. Best used with -m option. Only works with lxBatch-jobmode", metavar="MERGE_PARALLEL")
496 
497 
498  (options, args) = optParser.parse_args(argv)
499 
500  if not options.restrictTo == None:
501  options.restrictTo = options.restrictTo.split(",")
502 
503  options.config = [ os.path.abspath( iniFile ) for iniFile in \
504  options.config.split( "," ) ]
505  config = BetterConfigParser()
506  outputIniFileSet = set( config.read( options.config ) )
507  failedIniFiles = [ iniFile for iniFile in options.config if iniFile not in outputIniFileSet ]
508 
509  # Check for missing ini file
510  if options.config == [ os.path.abspath( defaultConfig ) ]:
511  if ( not options.crabStatus ) and \
512  ( not os.path.exists( defaultConfig ) ):
513  raise AllInOneError( "Default 'ini' file '%s' not found!\n"
514  "You can specify another name with the "
515  "command line option '-c'/'--config'."
516  %( defaultConfig ))
517  else:
518  for iniFile in failedIniFiles:
519  if not os.path.exists( iniFile ):
520  raise AllInOneError( "'%s' does not exist. Please check for "
521  "typos in the filename passed to the "
522  "'-c'/'--config' option!"
523  %( iniFile ))
524  else:
525  raise AllInOneError(( "'%s' does exist, but parsing of the "
526  "content failed!" ) % iniFile)
527 
528  # get the job name
529  if options.Name == None:
530  if not options.crabStatus:
531  options.Name = "alignmentValidation_%s"%(datetime.datetime.now().strftime("%y%m%d_%H%M%S"))
532  else:
533  existingValDirs = fnmatch.filter( os.walk( '.' ).next()[1],
534  "alignmentValidation_*" )
535  if len( existingValDirs ) > 0:
536  options.Name = existingValDirs[-1]
537  else:
538  print("Cannot guess last working directory!")
539  print ( "Please use the parameter '-N' or '--Name' to specify "
540  "the task for which you want a status report." )
541  return 1
542 
543  # set output path
544  outPath = os.path.abspath( options.Name )
545 
546  # Check status of submitted jobs and return
547  if options.crabStatus:
548  os.chdir( outPath )
549  crabLogDirs = fnmatch.filter( os.walk('.').next()[1], "crab.*" )
550  if len( crabLogDirs ) == 0:
551  print("Found no crab tasks for job name '%s'"%( options.Name ))
552  return 1
553  theCrab = crabWrapper.CrabWrapper()
554  for crabLogDir in crabLogDirs:
555  print()
556  print("*" + "=" * 78 + "*")
557  print ( "| Status report and output retrieval for:"
558  + " " * (77 - len( "Status report and output retrieval for:" ) )
559  + "|" )
560  taskName = crabLogDir.replace( "crab.", "" )
561  print("| " + taskName + " " * (77 - len( taskName ) ) + "|")
562  print("*" + "=" * 78 + "*")
563  print()
564  crabOptions = { "-getoutput":"",
565  "-c": crabLogDir }
566  try:
567  theCrab.run( crabOptions )
568  except AllInOneError as e:
569  print("crab: No output retrieved for this task.")
570  crabOptions = { "-status": "",
571  "-c": crabLogDir }
572  theCrab.run( crabOptions )
573  return
574 
575  general = config.getGeneral()
576  config.set("internals","workdir",os.path.join(general["workdir"],options.Name) )
577  config.set("internals","scriptsdir",outPath)
578  config.set("general","datadir",os.path.join(general["datadir"],options.Name) )
579  config.set("general","logdir",os.path.join(general["logdir"],options.Name) )
580  config.set("general","eosdir",os.path.join("AlignmentValidation", general["eosdir"], options.Name) )
581 
582  if not os.path.exists( outPath ):
583  os.makedirs( outPath )
584  elif not os.path.isdir( outPath ):
585  raise AllInOneError("the file %s is in the way rename the Job or move it away"%outPath)
586 
587  # replace default templates by the ones specified in the "alternateTemplates" section
588  loadTemplates( config )
589 
590  #save backup configuration file
591  backupConfigFile = open( os.path.join( outPath, "usedConfiguration.ini" ) , "w" )
592  config.write( backupConfigFile )
593 
594  #copy proxy, if there is one
595  try:
596  proxyexists = int(getCommandOutput2("voms-proxy-info --timeleft")) > 10
597  except RuntimeError:
598  proxyexists = False
599 
600  if proxyexists:
601  shutil.copyfile(getCommandOutput2("voms-proxy-info --path").strip(), os.path.join(outPath, ".user_proxy"))
602 
603  validations = []
604  for validation in config.items("validation"):
605  alignmentList = [validation[1]]
606  validationsToAdd = [(validation[0],alignment) \
607  for alignment in alignmentList]
608  validations.extend(validationsToAdd)
609  jobs = [ ValidationJob( validation, config, options) \
610  for validation in validations ]
611  for job in jobs:
612  if job.needsproxy and not proxyexists:
613  raise AllInOneError("At least one job needs a grid proxy, please init one.")
614  map( lambda job: job.createJob(), jobs )
615  validations = [ job.getValidation() for job in jobs ]
616 
617  if options.mergeOfflineParallel:
618  parallelMergeObjects=createMergeScript(outPath, validations, options)['parallelMergeObjects']
619  else:
620  createMergeScript(outPath, validations, options)
621 
622 
623  print()
624  map( lambda job: job.runJob(), jobs )
625 
626  if options.autoMerge and ValidationJob.jobCount == ValidationJob.batchCount and config.getGeneral()["jobmode"].split(",")[0] == "lxBatch":
627  print("> Automatically merging jobs when they have ended")
628  # if everything is done as batch job, also submit TkAlMerge.sh to be run
629  # after the jobs have finished
630 
631  #if parallel merge scripts: manage dependencies
632  if options.mergeOfflineParallel and parallelMergeObjects!={}:
633  initID=parallelMergeObjects["init"].runJob(config).split("<")[1].split(">")[0]
634  parallelIDs=[]
635  for parallelMergeScript in parallelMergeObjects["parallel"]:
636  parallelMergeScript.addDependency(initID)
637  for job in jobs:
638  if isinstance(job.validation, OfflineValidation) and "TkAlMerge"+job.validation.alignmentToValidate.name==parallelMergeScript.name:
639  parallelMergeScript.addDependency(job.JobId)
640  parallelIDs.append(parallelMergeScript.runJob(config).split("<")[1].split(">")[0])
641  parallelMergeObjects["continue"].addDependency(parallelIDs)
642  parallelMergeObjects["continue"].addDependency(ValidationJob.batchJobIds)
643  parallelMergeObjects["continue"].runJob(config)
644 
645 
646 
647 
648  else:
649  repMap = {
650  "commands": config.getGeneral()["jobmode"].split(",")[1],
651  "jobName": "TkAlMerge",
652  "logDir": config.getGeneral()["logdir"],
653  "script": "TkAlMerge.sh",
654  "bsub": "/afs/cern.ch/cms/caf/scripts/cmsbsub",
655  "conditions": '"' + " && ".join(["ended(" + jobId + ")" for jobId in ValidationJob.batchJobIds]) + '"'
656  }
657  for ext in ("stdout", "stderr", "stdout.gz", "stderr.gz"):
658  oldlog = "%(logDir)s/%(jobName)s."%repMap + ext
659  if os.path.exists(oldlog):
660  os.remove(oldlog)
661 
662  #issue job
663  getCommandOutput2("%(bsub)s %(commands)s "
664  "-o %(logDir)s/%(jobName)s.stdout "
665  "-e %(logDir)s/%(jobName)s.stderr "
666  "-w %(conditions)s "
667  "%(logDir)s/%(script)s"%repMap)
668 
669 if __name__ == "__main__":
670  # main(["-n","-N","test","-c","defaultCRAFTValidation.ini,latestObjects.ini","--getImages"])
671  if "-d" in sys.argv[1:] or "--debug" in sys.argv[1:]:
672  main()
673  else:
674  try:
675  main()
676  except AllInOneError as e:
677  print("\nAll-In-One Tool:", str(e))
678  exit(1)
def main(argv=None)
— Main —############################
def __init__(self, _name, _path, _dependency)
def createMergeScript(path, validations, options)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def getCommandOutput2(command)
— Classes —############################
def addIndex(filename, njobs, index=None)
def __getValidation(self, valType, name, alignments, config, options)
def replaceByMap(target, the_map)
— Helpers —############################
def __createJob(self, jobMode, outpath)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def alternateTemplate(templateName, alternateTemplateName)
Alternate Templates ###
def __init__(self, validation, config, options)
Definition: main.py:1
#define str(s)
double split
Definition: MVATrainer.cc:139