CMS 3D CMS Logo

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