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