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