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