10 import Alignment.OfflineValidation.TkAlAllInOneTool.configTemplates \
12 import Alignment.OfflineValidation.TkAlAllInOneTool.crabWrapper
as crabWrapper
13 from Alignment.OfflineValidation.TkAlAllInOneTool.TkAlExceptions \
15 from Alignment.OfflineValidation.TkAlAllInOneTool.helperFunctions \
16 import replaceByMap, getCommandOutput2, addIndex
17 from Alignment.OfflineValidation.TkAlAllInOneTool.betterConfigParser \
18 import BetterConfigParser
19 from Alignment.OfflineValidation.TkAlAllInOneTool.alignment
import Alignment
22 import GenericValidation, ParallelValidation, ValidationWithComparison, ValidationWithPlots
23 from Alignment.OfflineValidation.TkAlAllInOneTool.geometryComparison \
24 import GeometryComparison
26 import OfflineValidation, OfflineValidationDQM
27 from Alignment.OfflineValidation.TkAlAllInOneTool.monteCarloValidation \
28 import MonteCarloValidation
30 import TrackSplittingValidation
32 import ZMuMuValidation
34 import PrimaryVertexValidation
35 from Alignment.OfflineValidation.TkAlAllInOneTool.preexistingValidation \
37 from Alignment.OfflineValidation.TkAlAllInOneTool.plottingOptions \
38 import PlottingOptions
39 import Alignment.OfflineValidation.TkAlAllInOneTool.globalDictionaries \
53 def __init__( self, validation, config, options ):
54 if validation[1] ==
"":
56 valString = validation[0].
split(
"->" )[0]
57 alignments = validation[0].
split(
"->" )[1]
59 if "->" in validation[0]:
60 msg = (
"Instead of using the intermediate syntax\n'" 61 +valString.strip()+
"-> "+alignments.strip()
62 +
":'\nyou have to use the now fully supported syntax \n'" 63 +valString.strip()+
": " 64 +alignments.strip()+
"'.")
65 raise AllInOneError(msg)
67 valString = validation[0]
68 alignments = validation[1]
69 valString = valString.split()
81 print (
"offlineParallel and offline are now the same. To run an offline parallel validation,\n" 82 "just set parallelJobs to something > 1. There is no reason to call it offlineParallel anymore.")
85 if not self.__config.has_section( section ):
86 raise AllInOneError(
"Validation '%s' of type '%s' is requested in" 87 " '[validation]' section, but is not defined." 88 "\nYou have to add a '[%s]' section." 95 if valType ==
"compare":
96 alignmentsList = alignments.split(
"," )
97 firstAlignList = alignmentsList[0].
split()
98 firstAlignName = firstAlignList[0].
strip()
99 if firstAlignName ==
"IDEAL":
100 raise AllInOneError(
"'IDEAL' has to be the second (reference)" 101 " alignment in 'compare <val_name>: " 102 "<alignment> <reference>'.")
103 if len( firstAlignList ) > 1:
104 firstRun = firstAlignList[1]
108 firstAlignName = firstAlign.name
109 secondAlignList = alignmentsList[1].
split()
110 secondAlignName = secondAlignList[0].
strip()
111 if len( secondAlignList ) > 1:
112 secondRun = secondAlignList[1]
115 if secondAlignName ==
"IDEAL":
116 secondAlign = secondAlignName
120 secondAlignName = secondAlign.name
122 validation = GeometryComparison( name, firstAlign, secondAlign,
124 self.__commandLineOptions.getImages)
125 elif valType ==
"offline":
126 validation = OfflineValidation( name,
128 elif valType ==
"preexistingoffline":
129 validation = PreexistingOfflineValidation(name, self.
__config)
130 elif valType ==
"offlineDQM":
131 validation = OfflineValidationDQM( name,
133 elif valType ==
"mcValidate":
134 validation = MonteCarloValidation( name,
136 elif valType ==
"preexistingmcValidate":
137 validation = PreexistingMonteCarloValidation(name, self.
__config)
138 elif valType ==
"split":
139 validation = TrackSplittingValidation( name,
141 elif valType ==
"preexistingsplit":
142 validation = PreexistingTrackSplittingValidation(name, self.
__config)
143 elif valType ==
"zmumu":
144 validation = ZMuMuValidation( name,
146 elif valType ==
"primaryvertex":
150 raise AllInOneError(
"Unknown validation mode '%s'"%valType)
155 """This private method creates the needed files for the validation job. 157 self.validation.createConfiguration( outpath )
160 self.
__scripts = sum([
addIndex(script, self.validation.NJobs)
for script
in self.validation.createScript( outpath )], [])
161 if jobMode.split(
',' )[0] ==
"crab":
162 self.validation.createCrabCfg( outpath )
166 """This is the method called to create the job files.""" 168 os.path.abspath( self.__commandLineOptions.Name) )
172 if self.validation.jobid:
173 self.batchJobIds.append(self.validation.jobid)
174 log =
"> " + self.validation.name +
" is already validated." 178 if self.validation.jobid:
179 print "jobid {} will be ignored, since the validation {} is not preexisting".
format(self.validation.jobid, self.validation.name)
181 general = self.__config.getGeneral()
184 name = os.path.splitext( os.path.basename( script) )[0]
185 ValidationJob.jobCount += 1
186 if self.__commandLineOptions.dryRun:
187 print "%s would run: %s"%( name, os.path.basename( script) )
189 log =
"> Validating "+name
190 print "> Validating "+name
191 if self.validation.jobmode ==
"interactive":
193 ValidationJob.interactCount += 1
194 elif self.validation.jobmode.split(
",")[0] ==
"lxBatch":
196 "commands": self.validation.jobmode.split(
",")[1],
197 "logDir": general[
"logdir"],
200 "bsub":
"/afs/cern.ch/cms/caf/scripts/cmsbsub" 202 for ext
in (
"stdout",
"stderr",
"stdout.gz",
"stderr.gz"):
203 oldlog =
"%(logDir)s/%(jobName)s."%repMap + ext
204 if os.path.exists(oldlog):
208 "-o %(logDir)s/%(jobName)s.stdout " 209 "-e %(logDir)s/%(jobName)s.stderr " 213 ValidationJob.batchJobIds.append(bsubOut.split(
"<")[1].
split(
">")[0])
215 ValidationJob.batchCount += 1
216 elif self.validation.jobmode.split(
"," )[0] ==
"crab":
217 os.chdir( general[
"logdir"] )
218 crabName =
"crab." + os.path.basename( script )[:-3]
220 options = {
"-create":
"",
221 "-cfg": crabName +
".cfg",
224 theCrab.run( options )
225 except AllInOneError
as e:
226 print "crab:",
str(e).
split(
"\n")[0]
228 ValidationJob.crabCount += 1
231 raise AllInOneError(
"Unknown 'jobmode'!\n" 232 "Please change this parameter either in " 233 "the [general] or in the [" 235 +
"] section to one of the following " 237 "\tinteractive\n\tlxBatch, -q <queue>\n" 238 "\tcrab, -q <queue>")
247 return self.validation.needsproxy
and not self.
__preexisting and not self.__commandLineOptions.dryRun
252 if(len(validations) == 0):
253 raise AllInOneError(
"Cowardly refusing to merge nothing!")
255 config = validations[0].config
256 repMap = config.getGeneral()
259 "CompareAlignments":
"",
260 "RunValidationPlots":
"",
261 "CMSSW_BASE": os.environ[
"CMSSW_BASE"],
262 "SCRAM_ARCH": os.environ[
"SCRAM_ARCH"],
263 "CMSSW_RELEASE_BASE": os.environ[
"CMSSW_RELEASE_BASE"],
267 for validation
in validations:
268 for referenceName
in validation.filesToCompare:
269 validationtype = type(validation)
270 if isinstance(validationtype, PreexistingValidation):
272 for parentclass
in validationtype.mro():
273 if not issubclass(parentclass, PreexistingValidation):
274 validationtype = parentclass
276 key = (validationtype, referenceName)
277 if key
in comparisonLists:
278 comparisonLists[key].
append(validation)
280 comparisonLists[key] = [validation]
284 repMap[
"doMerge"] =
"mergeRetCode=0\n" 285 repMap[
"rmUnmerged"] = (
"if [[ mergeRetCode -eq 0 ]]; then\n" 286 " echo -e \\n\"Merging succeeded, removing original files.\"\n")
287 repMap[
"beforeMerge"] =
"" 288 repMap[
"mergeParallelFilePrefixes"] =
"" 292 for (validationType, referencename), validations
in comparisonLists.iteritems():
293 for validation
in validations:
294 if (isinstance(validation, PreexistingValidation)
295 or validation.NJobs == 1
296 or not isinstance(validation, ParallelValidation)):
298 if validationType
not in anythingToMerge:
299 anythingToMerge += [validationType]
300 repMap[
"doMerge"] +=
'\n\n\n\necho -e "\n\nMerging results from %s jobs"\n\n' % validationType.valType
301 repMap[
"beforeMerge"] += validationType.doInitMerge()
302 repMap[
"doMerge"] += validation.doMerge()
303 for f
in validation.getRepMap()[
"outputFiles"]:
304 longName = os.path.join(
"/store/caf/user/$USER/",
305 validation.getRepMap()[
"eosdir"], f)
306 repMap[
"rmUnmerged"] +=
" $eos rm "+longName+
"\n" 307 repMap[
"rmUnmerged"] += (
"else\n" 308 " echo -e \\n\"WARNING: Merging failed, unmerged" 309 " files won't be deleted.\\n" 310 "(Ignore this warning if merging was done earlier)\"\n" 314 repMap[
"DownloadData"] +=
replaceByMap( configTemplates.mergeParallelResults, repMap )
316 repMap[
"DownloadData"] =
"" 318 repMap[
"RunValidationPlots"] =
"" 319 for (validationType, referencename), validations
in comparisonLists.iteritems():
320 if issubclass(validationType, ValidationWithPlots):
321 repMap[
"RunValidationPlots"] += validationType.doRunPlots(validations)
323 repMap[
"CompareAlignments"] =
"#run comparisons" 324 for (validationType, referencename), validations
in comparisonLists.iteritems():
325 if issubclass(validationType, ValidationWithComparison):
326 repMap[
"CompareAlignments"] += validationType.doComparison(validations)
328 filePath = os.path.join(path,
"TkAlMerge.sh")
329 theFile = open( filePath,
"w" )
330 theFile.write(
replaceByMap( configTemplates.mergeTemplate, repMap ) )
332 os.chmod(filePath,0o755)
337 if config.has_section(
"alternateTemplates"):
338 for templateName
in config.options(
"alternateTemplates"):
339 if templateName ==
"AutoAlternates":
341 newTemplateName = config.get(
"alternateTemplates", templateName )
350 optParser = optparse.OptionParser()
351 optParser.description =
"""All-in-one Alignment Validation. 352 This will run various validation procedures either on batch queues or interactively. 353 If no name is given (-N parameter) a name containing time and date is created automatically. 354 To merge the outcome of all validation procedures run TkAlMerge.sh in your validation's directory. 356 optParser.add_option(
"-n",
"--dryRun", dest=
"dryRun", action=
"store_true", default=
False,
357 help=
"create all scripts and cfg File but do not start jobs (default=False)")
358 optParser.add_option(
"--getImages", dest=
"getImages", action=
"store_true", default=
True,
359 help=
"get all Images created during the process (default= True)")
360 defaultConfig =
"TkAlConfig.ini" 361 optParser.add_option(
"-c",
"--config", dest=
"config", default = defaultConfig,
362 help=
"configuration to use (default TkAlConfig.ini) this can be a comma-seperated list of all .ini file you want to merge", metavar=
"CONFIG")
363 optParser.add_option(
"-N",
"--Name", dest=
"Name",
364 help=
"Name of this validation (default: alignmentValidation_DATE_TIME)", metavar=
"NAME")
365 optParser.add_option(
"-r",
"--restrictTo", dest=
"restrictTo",
366 help=
"restrict validations to given modes (comma seperated) (default: no restriction)", metavar=
"RESTRICTTO")
367 optParser.add_option(
"-s",
"--status", dest=
"crabStatus", action=
"store_true", default =
False,
368 help=
"get the status of the crab jobs", metavar=
"STATUS")
369 optParser.add_option(
"-d",
"--debug", dest=
"debugMode", action=
"store_true",
371 help=
"run the tool to get full traceback of errors",
373 optParser.add_option(
"-m",
"--autoMerge", dest=
"autoMerge", action=
"store_true", default =
False,
374 help=
"submit TkAlMerge.sh to run automatically when all jobs have finished (default=False)." 375 " Works only for batch jobs")
377 (options, args) = optParser.parse_args(argv)
379 if not options.restrictTo ==
None:
380 options.restrictTo = options.restrictTo.split(
",")
382 options.config = [ os.path.abspath( iniFile )
for iniFile
in \
383 options.config.split(
"," ) ]
384 config = BetterConfigParser()
385 outputIniFileSet = set( config.read( options.config ) )
386 failedIniFiles = [ iniFile
for iniFile
in options.config
if iniFile
not in outputIniFileSet ]
389 if options.config == [ os.path.abspath( defaultConfig ) ]:
390 if (
not options.crabStatus )
and \
391 (
not os.path.exists( defaultConfig ) ):
392 raise AllInOneError(
"Default 'ini' file '%s' not found!\n" 393 "You can specify another name with the " 394 "command line option '-c'/'--config'." 397 for iniFile
in failedIniFiles:
398 if not os.path.exists( iniFile ):
399 raise AllInOneError(
"'%s' does not exist. Please check for " 400 "typos in the filename passed to the " 401 "'-c'/'--config' option!" 404 raise AllInOneError((
"'%s' does exist, but parsing of the " 405 "content failed!" ) % iniFile)
408 if options.Name ==
None:
409 if not options.crabStatus:
410 options.Name =
"alignmentValidation_%s"%(datetime.datetime.now().strftime(
"%y%m%d_%H%M%S"))
412 existingValDirs = fnmatch.filter( os.walk(
'.' ).
next()[1],
413 "alignmentValidation_*" )
414 if len( existingValDirs ) > 0:
415 options.Name = existingValDirs[-1]
417 print "Cannot guess last working directory!" 418 print (
"Please use the parameter '-N' or '--Name' to specify " 419 "the task for which you want a status report." )
423 outPath = os.path.abspath( options.Name )
426 if options.crabStatus:
428 crabLogDirs = fnmatch.filter( os.walk(
'.').
next()[1],
"crab.*" )
429 if len( crabLogDirs ) == 0:
430 print "Found no crab tasks for job name '%s'"%( options.Name )
433 for crabLogDir
in crabLogDirs:
435 print "*" +
"=" * 78 +
"*" 436 print (
"| Status report and output retrieval for:" 437 +
" " * (77 - len(
"Status report and output retrieval for:" ) )
439 taskName = crabLogDir.replace(
"crab.",
"" )
440 print "| " + taskName +
" " * (77 - len( taskName ) ) +
"|" 441 print "*" +
"=" * 78 +
"*" 443 crabOptions = {
"-getoutput":
"",
446 theCrab.run( crabOptions )
447 except AllInOneError
as e:
448 print "crab: No output retrieved for this task." 449 crabOptions = {
"-status":
"",
451 theCrab.run( crabOptions )
454 general = config.getGeneral()
455 config.set(
"internals",
"workdir",os.path.join(general[
"workdir"],options.Name) )
456 config.set(
"internals",
"scriptsdir",outPath)
457 config.set(
"general",
"datadir",os.path.join(general[
"datadir"],options.Name) )
458 config.set(
"general",
"logdir",os.path.join(general[
"logdir"],options.Name) )
459 config.set(
"general",
"eosdir",os.path.join(
"AlignmentValidation", general[
"eosdir"], options.Name) )
461 if not os.path.exists( outPath ):
462 os.makedirs( outPath )
463 elif not os.path.isdir( outPath ):
464 raise AllInOneError(
"the file %s is in the way rename the Job or move it away"%outPath)
470 backupConfigFile = open( os.path.join( outPath,
"usedConfiguration.ini" ) ,
"w" )
471 config.write( backupConfigFile )
480 shutil.copyfile(
getCommandOutput2(
"voms-proxy-info --path").
strip(), os.path.join(outPath,
".user_proxy"))
483 for validation
in config.items(
"validation"):
484 alignmentList = [validation[1]]
485 validationsToAdd = [(validation[0],alignment) \
486 for alignment
in alignmentList]
487 validations.extend(validationsToAdd)
489 for validation
in validations ]
491 if job.needsproxy
and not proxyexists:
492 raise AllInOneError(
"At least one job needs a grid proxy, please init one.")
493 map(
lambda job: job.createJob(), jobs )
494 validations = [ job.getValidation()
for job
in jobs ]
499 map(
lambda job: job.runJob(), jobs )
501 if options.autoMerge:
504 if ValidationJob.jobCount == ValidationJob.batchCount
and config.getGeneral()[
"jobmode"].
split(
",")[0] ==
"lxBatch":
505 print "> Automatically merging jobs when they have ended" 507 "commands": config.getGeneral()[
"jobmode"].
split(
",")[1],
508 "jobName":
"TkAlMerge",
509 "logDir": config.getGeneral()[
"logdir"],
510 "script":
"TkAlMerge.sh",
511 "bsub":
"/afs/cern.ch/cms/caf/scripts/cmsbsub",
512 "conditions":
'"' +
" && ".
join([
"ended(" + jobId +
")" for jobId
in ValidationJob.batchJobIds]) +
'"' 514 for ext
in (
"stdout",
"stderr",
"stdout.gz",
"stderr.gz"):
515 oldlog =
"%(logDir)s/%(jobName)s."%repMap + ext
516 if os.path.exists(oldlog):
520 "-o %(logDir)s/%(jobName)s.stdout " 521 "-e %(logDir)s/%(jobName)s.stderr " 523 "%(logDir)s/%(script)s"%repMap)
525 if __name__ ==
"__main__":
527 if "-d" in sys.argv[1:]
or "--debug" in sys.argv[1:]:
532 except AllInOneError
as e:
533 print "\nAll-In-One Tool:",
str(e)
— Classes —############################
def main(argv=None)
— Main —############################
def loadTemplates(config)
def createMergeScript(path, validations)
def getCommandOutput2(command)
def addIndex(filename, njobs, index=None)
def __getValidation(self, valType, name, alignments, config, options)
def replaceByMap(target, the_map)
— Helpers —############################
def __createJob(self, jobMode, outpath)
static std::string join(char **cmd)
def alternateTemplate(templateName, alternateTemplateName)
Alternate Templates ###
def __init__(self, validation, config, options)