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 
558 
559  repMap[(validationtype, validationName, referenceName)]["rmUnmerged"] += ("else\n"
560  " echo -e \\n\"WARNING: Merging failed, unmerged"
561  " files won't be deleted.\\n"
562  "(Ignore this warning if merging was done earlier)\"\n"
563  "fi\n")
564 
565 
566  if anythingToMerge:
567  repMap[(validationtype, validationName, referenceName)]["DownloadData"] += replaceByMap( configTemplates.mergeParallelResults, repMap[(validationtype, validationName, referenceName)] )
568  else:
569  repMap[(validationtype, validationName, referenceName)]["DownloadData"] = ""
570 
571  repMap[(validationtype, validationName, referenceName)]["RunValidationPlots"] = ""
572  repMap[(validationtype, validationName, referenceName)]["plottingscriptpath"] = ""
573  if issubclass(validationtype, ValidationWithPlots):
574  repMap[(validationtype, validationName, referenceName)]["RunValidationPlots"] = validationtype.doRunPlots(validations)
575 
576  repMap[(validationtype, validationName, referenceName)]["CompareAlignments"] = "#run comparisons"
577  if issubclass(validationtype, ValidationWithComparison):
578  repMap[(validationtype, validationName, referenceName)]["CompareAlignments"] += validationtype.doComparison(validations)
579 
580  #if not merging parallel, add code to create results directory and set merge script name accordingly
581  if validations[0].config.has_section("IOV"):
582  repMap[(validationtype, validationName, referenceName)]["createResultsDirectory"]=replaceByMap(configTemplates.createResultsDirectoryTemplate, repMap[(validationtype, validationName, referenceName)])
583  filePath = os.path.join(repMap[(validationtype, validationName, referenceName)]["scriptsdir"], "TkAlMerge.sh")
584  else:
585  repMap[(validationtype, validationName, referenceName)]["createResultsDirectory"]=replaceByMap(configTemplates.createResultsDirectoryTemplate, repMap[(validationtype, validationName, referenceName)])
586  filePath = os.path.join(path, "TkAlMerge.sh")
587 
588  theFile = open( filePath, "w" )
589  theFile.write( replaceByMap( configTemplates.mergeTemplate, repMap[(validationtype, validationName, referenceName)]) )
590  theFile.close()
591  os.chmod(filePath,0o755)
592 
593 def loadTemplates( config ):
594  if config.has_section("alternateTemplates"):
595  for templateName in config.options("alternateTemplates"):
596  if templateName == "AutoAlternates":
597  continue
598  newTemplateName = config.get("alternateTemplates", templateName )
599  #print "replacing default %s template by %s"%( templateName, newTemplateName)
600  configTemplates.alternateTemplate(templateName, newTemplateName)
601 
602 def flatten(l):
603  flattenList = []
604 
605  for item in l:
606  if type(item) == list:
607  flattenList.extend(flatten(item))
608 
609  else:
610  flattenList.append(item)
611 
612  return flattenList
613 
614 
615 ####################--- Main ---############################
616 def main(argv = None):
617  if argv == None:
618  argv = sys.argv[1:]
619  optParser = optparse.OptionParser()
620  optParser.description = """All-in-one Alignment Validation.
621 This will run various validation procedures either on batch queues or interactively.
622 If no name is given (-N parameter) a name containing time and date is created automatically.
623 To merge the outcome of all validation procedures run TkAlMerge.sh in your validation's directory.
624 """
625  optParser.add_option("-n", "--dryRun", dest="dryRun", action="store_true", default=False,
626  help="create all scripts and cfg File but do not start jobs (default=False)")
627  optParser.add_option( "--getImages", dest="getImages", action="store_true", default=True,
628  help="get all Images created during the process (default= True)")
629  defaultConfig = "TkAlConfig.ini"
630  optParser.add_option("-c", "--config", dest="config", default = defaultConfig,
631  help="configuration to use (default TkAlConfig.ini) this can be a comma-seperated list of all .ini file you want to merge", metavar="CONFIG")
632  optParser.add_option("-N", "--Name", dest="Name",
633  help="Name of this validation (default: alignmentValidation_DATE_TIME)", metavar="NAME")
634  optParser.add_option("-r", "--restrictTo", dest="restrictTo",
635  help="restrict validations to given modes (comma seperated) (default: no restriction)", metavar="RESTRICTTO")
636  optParser.add_option("-d", "--debug", dest="debugMode", action="store_true",
637  default = False,
638  help="run the tool to get full traceback of errors",
639  metavar="DEBUG")
640 
641 
642  (options, args) = optParser.parse_args(argv)
643 
644 
645  if not options.restrictTo == None:
646  options.restrictTo = options.restrictTo.split(",")
647 
648  options.config = [ os.path.abspath( iniFile ) for iniFile in \
649  options.config.split( "," )]
650 
651  config = BetterConfigParser()
652  outputIniFileSet = set( config.read( options.config ) )
653  failedIniFiles = [ iniFile for iniFile in options.config if iniFile not in outputIniFileSet ]
654 
655  # Check for missing ini file
656  if options.config == [ os.path.abspath( defaultConfig ) ]:
657  if ( not os.path.exists( defaultConfig ) ):
658  raise AllInOneError( "Default 'ini' file '%s' not found!\n"
659  "You can specify another name with the "
660  "command line option '-c'/'--config'."
661  %( defaultConfig ))
662  else:
663  for iniFile in failedIniFiles:
664  if not os.path.exists( iniFile ):
665  raise AllInOneError( "'%s' does not exist. Please check for "
666  "typos in the filename passed to the "
667  "'-c'/'--config' option!"
668  %( iniFile ))
669  else:
670  raise AllInOneError(( "'%s' does exist, but parsing of the "
671  "content failed!" ) % iniFile)
672 
673  # get the job name
674  if options.Name == None:
675  existingValDirs = fnmatch.filter( os.walk( '.' ).next()[1],
676  "alignmentValidation_*" )
677  if len( existingValDirs ) > 0:
678  options.Name = existingValDirs[-1]
679  else:
680  print("Cannot guess last working directory!")
681  print ( "Please use the parameter '-N' or '--Name' to specify "
682  "the task for which you want a status report." )
683  return 1
684 
685  # set output path
686  outPath = os.path.abspath( options.Name )
687 
688  general = config.getGeneral()
689  config.set("internals","workdir",os.path.join(general["workdir"],options.Name) )
690  config.set("internals","scriptsdir",outPath)
691  config.set("general","datadir",os.path.join(general["datadir"],options.Name) )
692  config.set("general","logdir",os.path.join(general["logdir"],options.Name) )
693  config.set("general","eosdir",os.path.join("AlignmentValidation", general["eosdir"], options.Name) )
694 
695  if not os.path.exists( outPath ):
696  os.makedirs( outPath )
697  elif not os.path.isdir( outPath ):
698  raise AllInOneError("the file %s is in the way rename the Job or move it away"%outPath)
699 
700  # replace default templates by the ones specified in the "alternateTemplates" section
701  loadTemplates( config )
702 
703  #save backup configuration file
704  backupConfigFile = open( os.path.join( outPath, "usedConfiguration.ini" ) , "w" )
705  config.write( backupConfigFile )
706 
707  #copy proxy, if there is one
708  try:
709  proxyexists = int(getCommandOutput2("voms-proxy-info --timeleft")) > 10
710  except RuntimeError:
711  proxyexists = False
712 
713  if proxyexists:
714  shutil.copyfile(getCommandOutput2("voms-proxy-info --path").strip(), os.path.join(outPath, ".user_proxy"))
715 
716  validations = []
717  jobs = []
718  for validation in config.items("validation"):
719  alignmentList = [validation[1]]
720  validationsToAdd = [(validation[0],alignment) \
721  for alignment in alignmentList]
722  validations.extend(validationsToAdd)
723 
724 
725  for validation in validations:
726  job = ValidationJobMultiIOV(validation, config, options, outPath, len(validations))
727  if (job.optionMultiIOV == True):
728  jobs.extend(job)
729  else:
730  jobs.extend( ValidationJob(validation, config, options, 1) )
731 
732  for job in jobs:
733  if job.needsproxy and not proxyexists:
734  raise AllInOneError("At least one job needs a grid proxy, please init one.")
735 
736  map( lambda job: job.createJob(), jobs )
737 
738  validations = [ job.getValidation() for job in jobs ]
739  validations = flatten(validations)
740 
741  createMergeScript(outPath, validations, options)
742 
743 
744  map( lambda job: job.runJob(), jobs )
745 
746  if options.dryRun:
747  pass
748  else:
749  ValidationJobMultiIOV.runCondorJobs(outPath)
750 
751 
752 if __name__ == "__main__":
753  # main(["-n","-N","test","-c","defaultCRAFTValidation.ini,latestObjects.ini","--getImages"])
754  if "-d" in sys.argv[1:] or "--debug" in sys.argv[1:]:
755  main()
756  else:
757  try:
758  main()
759  except AllInOneError as e:
760  print("\nAll-In-One Tool:", str(e))
761  exit(1)
std::vector< std::string_view > split(std::string_view, const char *)
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:17
def alternateTemplate(templateName, alternateTemplateName)
Alternate Templates ###
#define update(a, b)
Definition: main.py:1
#define str(s)
def exit(msg="")