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