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 subprocess
5 import os
6 import sys
7 import optparse
8 import datetime
9 import shutil
10 import fnmatch
11 import fileinput
12 import fileinput
13 from abc import ABCMeta, abstractmethod
14 import copy
15 import itertools
16 import pprint
17 import re
18 
19 import six
20 import Alignment.OfflineValidation.TkAlAllInOneTool.configTemplates \
21  as configTemplates
22 from Alignment.OfflineValidation.TkAlAllInOneTool.TkAlExceptions \
23  import AllInOneError
24 from Alignment.OfflineValidation.TkAlAllInOneTool.helperFunctions \
25  import replaceByMap, getCommandOutput2, addIndex
26 from Alignment.OfflineValidation.TkAlAllInOneTool.betterConfigParser \
27  import BetterConfigParser
28 from Alignment.OfflineValidation.TkAlAllInOneTool.alignment import Alignment
29 
31  import GenericValidation, ParallelValidation, ValidationWithComparison, ValidationWithPlots
32 from Alignment.OfflineValidation.TkAlAllInOneTool.geometryComparison \
33  import GeometryComparison
35  import OfflineValidation, OfflineValidationDQM
36 from Alignment.OfflineValidation.TkAlAllInOneTool.monteCarloValidation \
37  import MonteCarloValidation
39  import TrackSplittingValidation
41  import ZMuMuValidation
43  import PrimaryVertexValidation
44 from Alignment.OfflineValidation.TkAlAllInOneTool.preexistingValidation \
45  import *
46 from Alignment.OfflineValidation.TkAlAllInOneTool.plottingOptions \
47  import PlottingOptions
48 import Alignment.OfflineValidation.TkAlAllInOneTool.globalDictionaries \
49  as globalDictionaries
50 from Alignment.OfflineValidation.TkAlAllInOneTool.overlapValidation \
51  import OverlapValidation
52 
53 ####################--- Classes ---############################
54 #
56 
57  __metaclass__ = ABCMeta
58 
59  def __init__( self, validation, config, options ):
60 
61  if validation[1] == "":
62  # intermediate syntax
63  valString = validation[0].split( "->" )[0]
64  self.alignments = validation[0].split( "->" )[1]
65  # force user to use the normal syntax
66  if "->" in validation[0]:
67  msg = ("Instead of using the intermediate syntax\n'"
68  +valString.strip()+"-> "+alignments.strip()
69  +":'\nyou have to use the now fully supported syntax \n'"
70  +valString.strip()+": "
71  +alignments.strip()+"'.")
72  raise AllInOneError(msg)
73  else:
74  valString = validation[0]
75  self.alignments = validation[1]
76  valString = valString.split()
77  self.valType = valString[0]
78  self.valName = valString[1]
79  self.commandLineOptions = options
80  self.config = config
81  self.preexisting = ("preexisting" in self.valType)
82  if self.valType[0] == "*":
83  self.valType = self.valType[1:]
84  self.preexisting = True
85 
86  # workaround for intermediate parallel version
87  if self.valType == "offlineParallel":
88  print ("offlineParallel and offline are now the same. To run an offline parallel validation,\n"
89  "just set parallelJobs to something > 1. There is no reason to call it offlineParallel anymore.")
90  self.valType = "offline"
91  self.valSection = self.valType + ":" + self.valName
92  if not self.config.has_section( self.valSection ):
93  raise AllInOneError("Validation '%s' of type '%s' is requested in"
94  " '[validation]' section, but is not defined."
95  "\nYou have to add a '[%s]' section."
96  %( self.valName, self.valType, self.valSection ))
97 
98 
99  @abstractmethod
100  def createJob( self ):
101  pass
102 
103  @abstractmethod
104  def runJob( self ):
105  pass
106 
107  @abstractmethod
108  def getValidation( self ):
109  pass
110 
111  @abstractmethod
112  def needsproxy(self):
113  pass
114 
115 
116 class ValidationJob(ValidationBase):
117 
118  # these count the jobs of different varieties that are being run
119  interactCount = 0
120  jobCount = 0
121  condorConf = {}
122 
123  def __init__( self, validation, config, options, *args, **kwargs ):
124 
125  self.start = 0
126  self.end = args
127  self.JobId=[]
128  super(ValidationJob, self).__init__( validation, config, options )
129  self.validation = self.__getValidation( self.valType, self.valName,
130  self.alignments, config,
131  options )
132 
133  def __getValidation( self, valType, name, alignments, config, options ):
134  if valType == "compare":
135  alignmentsList = alignments.split( "," )
136  firstAlignList = alignmentsList[0].split()
137  firstAlignName = firstAlignList[0].strip()
138  if firstAlignName == "IDEAL":
139  raise AllInOneError("'IDEAL' has to be the second (reference)"
140  " alignment in 'compare <val_name>: "
141  "<alignment> <reference>'.")
142  if len( firstAlignList ) > 1:
143  firstRun = firstAlignList[1]
144  elif config.has_section("IOV"):
145  firstRun = config.get("IOV", "iov")
146  else:
147  raise AllInOneError("Have to provide a run number for geometry comparison")
148  firstAlign = Alignment( firstAlignName, config, firstRun )
149  firstAlignName = firstAlign.name
150  secondAlignList = alignmentsList[1].split()
151  secondAlignName = secondAlignList[0].strip()
152  if secondAlignName == "IDEAL":
153  secondAlign = secondAlignName
154  else:
155  if len( secondAlignList ) > 1:
156  secondRun = secondAlignList[1]
157  elif config.has_section("IOV"):
158  secondRun = config.get("IOV", "iov")
159  else:
160  raise AllInOneError("Have to provide a run number for geometry comparison")
161  secondAlign = Alignment( secondAlignName, config,
162  secondRun )
163  secondAlignName = secondAlign.name
164 
165  validation = GeometryComparison( name, firstAlign, secondAlign,
166  config,
167  self.commandLineOptions.getImages)
168  elif valType == "offline":
169  validation = OfflineValidation( name,
170  Alignment( alignments.strip(), config ), config )
171  elif valType == "preexistingoffline":
172  validation = PreexistingOfflineValidation(name, config)
173  elif valType == "offlineDQM":
174  validation = OfflineValidationDQM( name,
175  Alignment( alignments.strip(), config ), config )
176  elif valType == "mcValidate":
177  validation = MonteCarloValidation( name,
178  Alignment( alignments.strip(), config ), config )
179  elif valType == "preexistingmcValidate":
180  validation = PreexistingMonteCarloValidation(name, config)
181  elif valType == "split":
182  validation = TrackSplittingValidation( name,
183  Alignment( alignments.strip(), config ), config )
184  elif valType == "preexistingsplit":
185  validation = PreexistingTrackSplittingValidation(name, config)
186  elif valType == "zmumu":
187  validation = ZMuMuValidation( name,
188  Alignment( alignments.strip(), config ), config )
189  elif valType == "primaryvertex":
190  validation = PrimaryVertexValidation( name,
191  Alignment( alignments.strip(), config ), config )
192  elif valType == "preexistingprimaryvertex":
193  validation = PreexistingPrimaryVertexValidation(name, self.__config)
194  elif valType == "overlap":
195  validation = OverlapValidation( name,
196  Alignment( alignments.strip(), self.__config ), self.__config )
197  else:
198  raise AllInOneError("Unknown validation mode '%s'"%valType)
199 
200  return validation
201 
202  def __createJob( self, jobMode, outpath ):
203  """This private method creates the needed files for the validation job.
204  """
205  self.validation.createConfiguration( outpath )
206  if self.preexisting:
207  return
208  self.scripts = sum([addIndex(script, self.validation.NJobs) for script in self.validation.createScript( outpath )], [])
209  return None
210 
211  def createJob(self):
212  """This is the method called to create the job files."""
213  self.__createJob( self.validation.jobmode,
214  os.path.abspath( self.commandLineOptions.Name) )
215 
216  def runJob( self ):
217  general = self.config.getGeneral()
218  log = ""
219 
220  if self.preexisting:
221  if self.validation.config.has_section("IOV"):
222  iov = self.validation.config.get("IOV", "iov")
223  else:
224  iov = "singleIOV"
225  preexistingValType = self.valType
226  originalValType = preexistingValType.replace('preexisting', '')
227  key = (originalValType, self.validation.originalValName, iov)
228  if key in ValidationJob.condorConf:
229  ValidationJob.condorConf[key].append(("preexisting", "", general["logdir"]))
230  else:
231  ValidationJob.condorConf[key] = [("preexisting", "", general["logdir"])]
232  log = "> " + self.validation.name + " is already validated."
233  return log
234 
235  for script in self.scripts:
236  name = os.path.splitext( os.path.basename( script) )[0]
237  ValidationJob.jobCount += 1
238  if self.commandLineOptions.dryRun:
239  print("%s would run: %s"%( name, os.path.basename( script) ))
240  continue
241  log = "> Validating "+name
242  print("> Validating "+name)
243  if self.validation.jobmode == "interactive":
244  log += getCommandOutput2( script )
245  ValidationJob.interactCount += 1
246  elif self.validation.jobmode.split( "," )[0] == "condor":
247  if self.validation.config.has_section("IOV"):
248  iov = self.validation.config.get("IOV", "iov")
249  else:
250  iov = "singleIOV"
251  scriptPaths = script.split("/")
252  scriptName = scriptPaths[-1]
253  scriptName = scriptName.split(".")
254  jobName = "%s"%scriptName[0] + "_%s"%scriptName[1]+"_%s"%scriptName[2]
255  key = (self.valType, self.valName, iov)
256  if key in ValidationJob.condorConf:
257  ValidationJob.condorConf[key].append((jobName, script, general["logdir"]))
258  else:
259  ValidationJob.condorConf[key] = [(jobName, script, general["logdir"])]
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\tcondor, -q <queue>\n")
268 
269  return log
270 
271  def getValidation( self ):
272  return self.validation
273 
274  def needsproxy(self):
275  return self.validation.needsproxy and not self.preexisting and not self.commandLineOptions.dryRun
276 
277  def __iter__(self):
278  yield self
279 
280  def __next__(self):
281  if self.start >= len(self.end):
282  raise StopIteration
283  else:
284  self.start += 1
285  return self.end[self.start-1]
286 
287 
289 
290  def __init__( self, validation, config, options, outPath, *args, **kwargs):
291  self.start = 0
292  self.end = args
293  super(ValidationJobMultiIOV, self).__init__( validation, config, options )
294  self.optionMultiIOV = self.config.getboolean( self.valSection, "multiIOV" )
295  if self.optionMultiIOV == True:
296  self.validation = validation
297  self.config = config
298  self.options = options
299  self.outPath = outPath
301  self.options, self.outPath)
302 
303 
304  def __performMultiIOV(self, validation, alignments, config, options, outPath):
305  validations = []
306  if self.valType == "compare":
307  alignmentsList = alignments.split( "," )
308  firstAlignList = alignmentsList[0].split()
309  firstAlignName = firstAlignList[0].strip()
310  secondAlignList = alignmentsList[1].split()
311  secondAlignName = secondAlignList[0].strip()
312  compareAlignments = "%s"%firstAlignName + "_vs_%s"%secondAlignName
313  sectionMultiIOV = "multiIOV:compare"
314  if not self.config.has_section(sectionMultiIOV):
315  raise AllInOneError("section'[%s]' not found. Please define the dataset"%sectionMultiIOV)
316  iovList = self.config.get( sectionMultiIOV, "iovs" )
317  iovList = re.sub(r"\s+", "", iovList, flags=re.UNICODE).split( "," )
318  for iov in iovList:
319  tmpConfig = BetterConfigParser()
320  tmpConfig.read( options.config )
321  general = tmpConfig.getGeneral()
322  tmpConfig.add_section("IOV")
323  tmpConfig.set("IOV", "iov", iov)
324  tmpConfig.set("internals","workdir",os.path.join(general["workdir"], options.Name, self.valType + "_%s"%compareAlignments + "_%s"%iov) )
325  tmpConfig.set("internals","scriptsdir",os.path.join(outPath, self.valType + "_%s"%compareAlignments + "_%s"%iov) )
326  tmpConfig.set("general","datadir",os.path.join(general["datadir"], options.Name, self.valType + "_%s"%compareAlignments + "_%s"%iov) )
327  tmpConfig.set("general","logdir",os.path.join(general["logdir"], options.Name, self.valType + "_%s"%compareAlignments + "_%s"%iov) )
328  tmpConfig.set("general","eosdir",os.path.join("AlignmentValidation", general["eosdir"], options.Name, self.valType + "_%s"%compareAlignments + "_%s"%iov) )
329  tmpOptions = copy.deepcopy(options)
330  tmpOptions.Name = os.path.join(options.Name, self.valType + "_%s"%compareAlignments + "_%s"%iov)
331  tmpOptions.config = tmpConfig
332  newOutPath = os.path.abspath( tmpOptions.Name )
333  if not os.path.exists( newOutPath ):
334  os.makedirs( newOutPath )
335  elif not os.path.isdir( newOutPath ):
336  raise AllInOneError("the file %s is in the way rename the Job or move it away"%newOutPath)
337  job = ValidationJob( validation, tmpConfig, tmpOptions, len(iovList) )
338  validations.append(job)
339 
340  return validations
341 
342  if "preexisting" in self.valType:
343  preexistingValType = self.valType
344  preexistingValSection = self.valSection
345  preexistingEosdir = self.config.get( self.valSection, "eosdirName" )
346  originalValType = preexistingValType.replace('preexisting', '')
347  originalValName = self.config.get( self.valSection, "originalValName" )
348  self.valSection = originalValType + ":" + originalValName
349  originalAlignment = self.valName
350 
351  datasetList = self.config.get( self.valSection, "dataset" )
352  datasetList = re.sub(r"\s+", "", datasetList, flags=re.UNICODE).split( "," )
353  for dataset in datasetList:
354  sectionMultiIOV = "multiIOV:%s"%dataset
355  if not self.config.has_section(sectionMultiIOV):
356  raise AllInOneError("section'[%s]' not found. Please define the dataset"%sectionMultiIOV)
357  else:
358  datasetBaseName = self.config.get( sectionMultiIOV, "dataset" )
359  iovList = self.config.get( sectionMultiIOV, "iovs" )
360  iovList = re.sub(r"\s+", "", iovList, flags=re.UNICODE).split( "," )
361  for iov in iovList:
362  datasetName = datasetBaseName+"_since%s"%iov
363  tmpConfig = BetterConfigParser()
364  tmpConfig.read( options.config )
365  general = tmpConfig.getGeneral()
366  if "preexisting" in self.valType:
367  valType = originalValType
368  valName = originalValName
369  else:
370  valType = self.valType
371  valName = self.valName
372  tmpConfig.add_section("IOV")
373  tmpConfig.set("IOV", "iov", iov)
374  tmpConfig.set( self.valSection, "dataset", datasetName )
375  tmpConfig.set("internals","workdir",os.path.join(general["workdir"], options.Name, valType + "_" + valName + "_%s"%iov) )
376  tmpConfig.set("internals","scriptsdir",os.path.join(outPath, valType + "_" + valName + "_%s"%iov) )
377  tmpConfig.set("general","datadir",os.path.join(general["datadir"], options.Name, valType + "_" + valName + "_%s"%iov) )
378  tmpConfig.set("general","logdir",os.path.join(general["logdir"], options.Name, valType + "_" + valName + "_%s"%iov) )
379  tmpConfig.set("general","eosdir",os.path.join("AlignmentValidation", general["eosdir"], options.Name, valType + "_" + valName + "_%s"%iov) )
380  if "preexisting" in self.valType:
381  if self.valType == "preexistingoffline":
382  validationClassName = "AlignmentValidation"
383  #elif self.valType == "preexistingmcValidate":
384  # validationClassName = "MonteCarloValidation"
385  #elif self.valType == "preexistingsplit":
386  # validationClassName = "TrackSplittingValidation"
387  #elif self.valType == "preexistingprimaryvertex":
388  # validationClassName = "PrimaryVertexValidation"
389  else:
390  raise AllInOneError("Unknown validation mode for preexisting option:'%s'"%self.valType)
391  preexistingEosdirPath = os.path.join("AlignmentValidation", preexistingEosdir, valType + "_" + valName + "_%s"%iov)
392  file = "/eos/cms/store/group/alca_trackeralign/AlignmentValidation/" + "%s"%preexistingEosdirPath + "/%s"%validationClassName + "_%s"%originalValName + "_%s"%originalAlignment + ".root"
393  tmpConfig.set(preexistingValSection, "file", file)
394  tmpOptions = copy.deepcopy(options)
395  tmpOptions.Name = os.path.join(options.Name, valType + "_" + valName + "_%s"%iov)
396  tmpOptions.config = tmpConfig
397  newOutPath = os.path.abspath( tmpOptions.Name )
398  if not os.path.exists( newOutPath ):
399  os.makedirs( newOutPath )
400  elif not os.path.isdir( newOutPath ):
401  raise AllInOneError("the file %s is in the way rename the Job or move it away"%newOutPath)
402  job = ValidationJob( validation, tmpConfig, tmpOptions, len(iovList) )
403  validations.append(job)
404 
405  return validations
406 
407  def createJob( self ):
408  map( lambda validation: validation.createJob(), self.validations )
409 
410  def runJob( self ):
411  return [validation.runJob() for validation in self.validations]
412 
413  @staticmethod
414  def runCondorJobs(outdir):
415  dagmanLog = "{}/daglogs".format(outdir)
416  os.system("mkdir -p {}".format(dagmanLog))
417 
418 
419  with open("{}/validation.condor".format(outdir), "w") as condor:
420  condor.write("universe = vanilla" + "\n")
421  condor.write("executable = $(scriptName).sh" + "\n")
422  condor.write("log = $(scriptName).log" + "\n")
423  condor.write("error = $(scriptName).stderr" + "\n")
424  condor.write("output = $(scriptName).stdout" + "\n")
425  condor.write('requirements = (OpSysAndVer =?= "CentOS7")' + '\n')
426  condor.write('+JobFlavour = "tomorrow"' + "\n")
427  condor.write('+RequestMemory = {}'.format(1540) + "\n")
428  condor.write('+FileTransferDownloadBytes = {}'.format(1540) + "\n")
429  condor.write('+AccountingGroup = "group_u_CMS.CAF.ALCA"' + '\n')
430  condor.write("queue")
431 
432  with open("{}/validation.dagman".format(outdir), "w") as dagman:
433  parents = {}
434  for (valType, valName, iov), alignments in six.iteritems(ValidationJob.condorConf):
435 
436  parents[(valType, valName, iov)] = []
437  for jobInfo in alignments:
438  if not "preexisting" in jobInfo[0]:
439  dagman.write("JOB {}_{} {}/validation.condor".format(jobInfo[0], iov, outdir) + "\n")
440  dagman.write('VARS {}_{} '.format(jobInfo[0], iov) + 'scriptName="{}"'.format('.'.join(jobInfo[1].split('.')[:-1])) + "\n")
441  parents[(valType, valName, iov)].append('{}_{}'.format(jobInfo[0], iov))
442  dagman.write("\n")
443 
444  path = os.path.join(jobInfo[2], "TkAlMerge.sh")
445  if os.path.exists( path ):
446  dagman.write("JOB Merge_{}_{}_{} {}/validation.condor".format(valType, valName, iov, outdir) + "\n")
447  dagman.write("VARS Merge_{}_{}_{} ".format(valType, valName, iov) + 'scriptName="{}"'.format(os.path.join(jobInfo[2], "TkAlMerge")) + "\n")
448  dagman.write("\n")
449  else:
450  raise AllInOneError("Merge script '[%s]' not found!"%path)
451 
452  for (valType, valName, iov), alignments in six.iteritems(ValidationJob.condorConf):
453  if len(parents[(valType, valName, iov)]) != 0:
454  dagman.write('PARENT {} '.format(" ".join([parent for parent in parents[(valType, valName, iov)]])) + 'CHILD Merge_{}_{}_{}'.format(valType, valName, iov) + "\n")
455 
456  submitCommands = ["condor_submit_dag -no_submit -outfile_dir {} {}/validation.dagman".format(dagmanLog, outdir), "condor_submit {}/validation.dagman.condor.sub".format(outdir)]
457 
458  for command in submitCommands:
459  subprocess.call(command.split(" "))
460 
461  def getValidation( self ):
462  return [validation.getValidation() for validation in self.validations]
463 
464  def needsproxy( self ):
465  return [validation.needsproxy() for validation in self.validations].join("and") and not self.preexisting and not self.commandLineOptions.dryRun
466 
467  def __iter__(self):
468  yield self
469 
470  def __next__(self):
471  if self.start >= len(self.end):
472  raise StopIteration
473  else:
474  self.start += 1
475  return self.end[self.start-1]
476 
477 
478 ####################--- Functions ---############################
479 def createMergeScript( path, validations, options ):
480  if(len(validations) == 0):
481  raise AllInOneError("Cowardly refusing to merge nothing!")
482 
483  repMap = {}
484 
485  comparisonLists = {} # directory of lists containing the validations that are comparable
486  for validation in validations:
487  if validation.config.has_section("IOV"):
488  iov = validation.config.get("IOV", "iov")
489  validation.defaultReferenceName = iov
490  for referenceName in validation.filesToCompare:
491  validationtype = type(validation)
492  validationName = validation.name
493  if validation.config.has_section("IOV") and (referenceName == "Tracker_defaultRange" or referenceName == "Tracker_autoRange"):
494  referenceName = iov
495  if issubclass(validationtype, PreexistingValidation):
496  validationName = validation.originalValName
497  #find the actual validationtype
498  for parentclass in validationtype.mro():
499  if not issubclass(parentclass, PreexistingValidation):
500  validationtype = parentclass
501  break
502  key = (validationtype, validationName, referenceName)
503 
504 
505  if key in comparisonLists:
506  comparisonLists[key].append(validation)
507  else:
508  comparisonLists[key] = [validation]
509  repMap[key] = validation.config.getGeneral()
510  repMap[key].update({
511  "DownloadData":"",
512  "CompareAlignments":"",
513  "RunValidationPlots":"",
514  "CMSSW_BASE": os.environ["CMSSW_BASE"],
515  "SCRAM_ARCH": os.environ["SCRAM_ARCH"],
516  "CMSSW_RELEASE_BASE": os.environ["CMSSW_RELEASE_BASE"],
517  })
518 
519  # introduced to merge individual validation outputs separately
520  # -> avoids problems with merge script
521  repMap[key]["doMerge"] = "mergeRetCode=0\n"
522  repMap[key]["rmUnmerged"] = ("if [[ mergeRetCode -eq 0 ]]; then\n"
523  " echo -e \\n\"Merging succeeded, removing original files.\"\n")
524  repMap[key]["beforeMerge"] = ""
525  repMap[key]["mergeParallelFilePrefixes"] = ""
526  repMap[key]["createResultsDirectory"]=""
527 
528  #print("comparisonLists")
529  #pprint.pprint(comparisonLists)
530  anythingToMerge = []
531 
532  for (validationtype, validationName, referenceName), validations in comparisonLists.iteritems():
533  #pprint.pprint("validations")
534  #pprint.pprint(validations)
535  globalDictionaries.plottingOptions = {}
536  map( lambda validation: validation.getRepMap(), validations )
537  #plotInfo = "plots:offline"
538  #allPlotInfo = dict(validations[0].config.items(plotInfo))
539  #repMap[(validationtype, validationName, referenceName)].update(allPlotInfo)
540 
541  for validation in validations:
542  validation.getRepMap()
543  #pprint.pprint("validation in validations")
544  #pprint.pprint(validation)
545  #parallel merging
546  if not (isinstance(validation, PreexistingValidation) or validation.NJobs == 1 or not isinstance(validation, ParallelValidation)):
547  if (validationtype, validationName, referenceName) not in anythingToMerge:
548  anythingToMerge.append((validationtype, validationName, referenceName))
549  repMap[(validationtype, validationName, referenceName)]["doMerge"] += '\n\n\n\necho -e "\n\nMerging results from %s jobs"\n\n' % validationtype.valType
550  repMap[(validationtype, validationName, referenceName)]["beforeMerge"] += validationtype.doInitMerge()
551  repMap[(validationtype, validationName, referenceName)]["doMerge"] += validation.doMerge()
552  for f in validation.getRepMap()["outputFiles"]:
553  longName = os.path.join("/eos/cms/store/group/alca_trackeralign/AlignmentValidation/",
554  validation.getRepMap()["eosdir"], f)
555  repMap[(validationtype, validationName, referenceName)]["rmUnmerged"] += " rm "+longName+"\n"
556 
557  repMap[(validationtype, validationName, referenceName)]["rmUnmerged"] += ("else\n"
558  " echo -e \\n\"WARNING: Merging failed, unmerged"
559  " files won't be deleted.\\n"
560  "(Ignore this warning if merging was done earlier)\"\n"
561  "fi\n")
562 
563 
564  if anythingToMerge:
565  repMap[(validationtype, validationName, referenceName)]["DownloadData"] += replaceByMap( configTemplates.mergeParallelResults, repMap[(validationtype, validationName, referenceName)] )
566  else:
567  repMap[(validationtype, validationName, referenceName)]["DownloadData"] = ""
568 
569  repMap[(validationtype, validationName, referenceName)]["RunValidationPlots"] = ""
570  repMap[(validationtype, validationName, referenceName)]["plottingscriptpath"] = ""
571  if issubclass(validationtype, ValidationWithPlots):
572  repMap[(validationtype, validationName, referenceName)]["RunValidationPlots"] = validationtype.doRunPlots(validations)
573 
574  repMap[(validationtype, validationName, referenceName)]["CompareAlignments"] = "#run comparisons"
575  if issubclass(validationtype, ValidationWithComparison):
576  repMap[(validationtype, validationName, referenceName)]["CompareAlignments"] += validationtype.doComparison(validations)
577 
578  #if not merging parallel, add code to create results directory and set merge script name accordingly
579  if validations[0].config.has_section("IOV"):
580  repMap[(validationtype, validationName, referenceName)]["createResultsDirectory"]=replaceByMap(configTemplates.createResultsDirectoryTemplate, repMap[(validationtype, validationName, referenceName)])
581  filePath = os.path.join(repMap[(validationtype, validationName, referenceName)]["scriptsdir"], "TkAlMerge.sh")
582  else:
583  repMap[(validationtype, validationName, referenceName)]["createResultsDirectory"]=replaceByMap(configTemplates.createResultsDirectoryTemplate, repMap[(validationtype, validationName, referenceName)])
584  filePath = os.path.join(path, "TkAlMerge.sh")
585 
586  theFile = open( filePath, "w" )
587  theFile.write( replaceByMap( configTemplates.mergeTemplate, repMap[(validationtype, validationName, referenceName)]) )
588  theFile.close()
589  os.chmod(filePath,0o755)
590 
591 def loadTemplates( config ):
592  if config.has_section("alternateTemplates"):
593  for templateName in config.options("alternateTemplates"):
594  if templateName == "AutoAlternates":
595  continue
596  newTemplateName = config.get("alternateTemplates", templateName )
597  #print "replacing default %s template by %s"%( templateName, newTemplateName)
598  configTemplates.alternateTemplate(templateName, newTemplateName)
599 
600 def flatten(l):
601  flattenList = []
602 
603  for item in l:
604  if type(item) == list:
605  flattenList.extend(flatten(item))
606 
607  else:
608  flattenList.append(item)
609 
610  return flattenList
611 
612 
613 ####################--- Main ---############################
614 def main(argv = None):
615  if argv == None:
616  argv = sys.argv[1:]
617  optParser = optparse.OptionParser()
618  optParser.description = """All-in-one Alignment Validation.
619 This will run various validation procedures either on batch queues or interactively.
620 If no name is given (-N parameter) a name containing time and date is created automatically.
621 To merge the outcome of all validation procedures run TkAlMerge.sh in your validation's directory.
622 """
623  optParser.add_option("-n", "--dryRun", dest="dryRun", action="store_true", default=False,
624  help="create all scripts and cfg File but do not start jobs (default=False)")
625  optParser.add_option( "--getImages", dest="getImages", action="store_true", default=True,
626  help="get all Images created during the process (default= True)")
627  defaultConfig = "TkAlConfig.ini"
628  optParser.add_option("-c", "--config", dest="config", default = defaultConfig,
629  help="configuration to use (default TkAlConfig.ini) this can be a comma-seperated list of all .ini file you want to merge", metavar="CONFIG")
630  optParser.add_option("-N", "--Name", dest="Name",
631  help="Name of this validation (default: alignmentValidation_DATE_TIME)", metavar="NAME")
632  optParser.add_option("-r", "--restrictTo", dest="restrictTo",
633  help="restrict validations to given modes (comma seperated) (default: no restriction)", metavar="RESTRICTTO")
634  optParser.add_option("-d", "--debug", dest="debugMode", action="store_true",
635  default = False,
636  help="run the tool to get full traceback of errors",
637  metavar="DEBUG")
638 
639 
640  (options, args) = optParser.parse_args(argv)
641 
642 
643  if not options.restrictTo == None:
644  options.restrictTo = options.restrictTo.split(",")
645 
646  options.config = [ os.path.abspath( iniFile ) for iniFile in \
647  options.config.split( "," )]
648 
649  config = BetterConfigParser()
650  outputIniFileSet = set( config.read( options.config ) )
651  failedIniFiles = [ iniFile for iniFile in options.config if iniFile not in outputIniFileSet ]
652 
653  # Check for missing ini file
654  if options.config == [ os.path.abspath( defaultConfig ) ]:
655  if ( not os.path.exists( defaultConfig ) ):
656  raise AllInOneError( "Default 'ini' file '%s' not found!\n"
657  "You can specify another name with the "
658  "command line option '-c'/'--config'."
659  %( defaultConfig ))
660  else:
661  for iniFile in failedIniFiles:
662  if not os.path.exists( iniFile ):
663  raise AllInOneError( "'%s' does not exist. Please check for "
664  "typos in the filename passed to the "
665  "'-c'/'--config' option!"
666  %( iniFile ))
667  else:
668  raise AllInOneError(( "'%s' does exist, but parsing of the "
669  "content failed!" ) % iniFile)
670 
671  # get the job name
672  if options.Name == None:
673  existingValDirs = fnmatch.filter( os.walk( '.' ).next()[1],
674  "alignmentValidation_*" )
675  if len( existingValDirs ) > 0:
676  options.Name = existingValDirs[-1]
677  else:
678  print("Cannot guess last working directory!")
679  print ( "Please use the parameter '-N' or '--Name' to specify "
680  "the task for which you want a status report." )
681  return 1
682 
683  # set output path
684  outPath = os.path.abspath( options.Name )
685 
686  general = config.getGeneral()
687  config.set("internals","workdir",os.path.join(general["workdir"],options.Name) )
688  config.set("internals","scriptsdir",outPath)
689  config.set("general","datadir",os.path.join(general["datadir"],options.Name) )
690  config.set("general","logdir",os.path.join(general["logdir"],options.Name) )
691  config.set("general","eosdir",os.path.join("AlignmentValidation", general["eosdir"], options.Name) )
692 
693  if not os.path.exists( outPath ):
694  os.makedirs( outPath )
695  elif not os.path.isdir( outPath ):
696  raise AllInOneError("the file %s is in the way rename the Job or move it away"%outPath)
697 
698  # replace default templates by the ones specified in the "alternateTemplates" section
699  loadTemplates( config )
700 
701  #save backup configuration file
702  backupConfigFile = open( os.path.join( outPath, "usedConfiguration.ini" ) , "w" )
703  config.write( backupConfigFile )
704 
705  #copy proxy, if there is one
706  try:
707  proxyexists = int(getCommandOutput2("voms-proxy-info --timeleft")) > 10
708  except RuntimeError:
709  proxyexists = False
710 
711  if proxyexists:
712  shutil.copyfile(getCommandOutput2("voms-proxy-info --path").strip(), os.path.join(outPath, ".user_proxy"))
713 
714  validations = []
715  jobs = []
716  for validation in config.items("validation"):
717  alignmentList = [validation[1]]
718  validationsToAdd = [(validation[0],alignment) \
719  for alignment in alignmentList]
720  validations.extend(validationsToAdd)
721 
722 
723  for validation in validations:
724  job = ValidationJobMultiIOV(validation, config, options, outPath, len(validations))
725  if (job.optionMultiIOV == True):
726  jobs.extend(job)
727  else:
728  jobs.extend( ValidationJob(validation, config, options, 1) )
729 
730  for job in jobs:
731  if job.needsproxy and not proxyexists:
732  raise AllInOneError("At least one job needs a grid proxy, please init one.")
733 
734  map( lambda job: job.createJob(), jobs )
735 
736  validations = [ job.getValidation() for job in jobs ]
737  validations = flatten(validations)
738 
739  createMergeScript(outPath, validations, options)
740 
741 
742  map( lambda job: job.runJob(), jobs )
743 
744  if options.dryRun:
745  pass
746  else:
747  ValidationJobMultiIOV.runCondorJobs(outPath)
748 
749 
750 if __name__ == "__main__":
751  # main(["-n","-N","test","-c","defaultCRAFTValidation.ini,latestObjects.ini","--getImages"])
752  if "-d" in sys.argv[1:] or "--debug" in sys.argv[1:]:
753  main()
754  else:
755  try:
756  main()
757  except AllInOneError as e:
758  print("\nAll-In-One Tool:", str(e))
759  exit(1)
def main(argv=None)
— Main —############################
def __init__(self, validation, config, options)
def __init__(self, validation, config, options, outPath, args, kwargs)
def createMergeScript(path, validations, options)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def getCommandOutput2(command)
def __performMultiIOV(self, validation, alignments, config, options, outPath)
def addIndex(filename, njobs, index=None)
def __init__(self, validation, config, options, args, kwargs)
def __getValidation(self, valType, name, alignments, config, options)
— Classes —############################
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 ###
#define update(a, b)
Definition: main.py:1
#define str(s)
double split
Definition: MVATrainer.cc:139