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
17 from Alignment.OfflineValidation.TkAlAllInOneTool.betterConfigParser \
18 import BetterConfigParser
19 from Alignment.OfflineValidation.TkAlAllInOneTool.alignment
import Alignment
21 from Alignment.OfflineValidation.TkAlAllInOneTool.genericValidation \
22 import GenericValidation
23 from Alignment.OfflineValidation.TkAlAllInOneTool.geometryComparison \
24 import GeometryComparison
25 from Alignment.OfflineValidation.TkAlAllInOneTool.offlineValidation \
26 import OfflineValidation, OfflineValidationDQM, OfflineValidationParallel
27 from Alignment.OfflineValidation.TkAlAllInOneTool.monteCarloValidation \
28 import MonteCarloValidation
29 from Alignment.OfflineValidation.TkAlAllInOneTool.trackSplittingValidation \
30 import TrackSplittingValidation
31 from Alignment.OfflineValidation.TkAlAllInOneTool.zMuMuValidation \
32 import ZMuMuValidation
33 import Alignment.OfflineValidation.TkAlAllInOneTool.globalDictionaries \
47 def __init__( self, validation, config, options ):
48 if validation[1] ==
"":
50 valString = validation[0].
split(
"->" )[0]
51 alignments = validation[0].
split(
"->" )[1]
53 if "->" in validation[0]:
54 msg = (
"Instead of using the intermediate syntax\n'"
55 +valString.strip()+
"-> "+alignments.strip()
56 +
":'\nyou have to use the now fully supported syntax \n'"
57 +valString.strip()+
": "
58 +alignments.strip()+
"'.")
59 raise AllInOneError(msg)
61 valString = validation[0]
62 alignments = validation[1]
63 valString = valString.split()
70 section =
"offline" +
":" + self.
__valName
73 if not self.__config.has_section( section ):
74 raise AllInOneError, (
"Validation '%s' of type '%s' is requested in"
75 " '[validation]' section, but is not defined."
76 "\nYou have to add a '[%s]' section."
83 if valType ==
"compare":
84 alignmentsList = alignments.split(
"," )
85 firstAlignList = alignmentsList[0].
split()
86 firstAlignName = firstAlignList[0].
strip()
87 if firstAlignName ==
"IDEAL":
88 raise AllInOneError, (
"'IDEAL' has to be the second (reference)"
89 " alignment in 'compare <val_name>: "
90 "<alignment> <reference>'.")
91 if len( firstAlignList ) > 1:
92 firstRun = firstAlignList[1]
95 firstAlign = Alignment( firstAlignName, self.
__config, firstRun )
96 secondAlignList = alignmentsList[1].
split()
97 secondAlignName = secondAlignList[0].
strip()
98 if len( secondAlignList ) > 1:
99 secondRun = secondAlignList[1]
102 if secondAlignName ==
"IDEAL":
103 secondAlign = secondAlignName
105 secondAlign = Alignment( secondAlignName, self.
__config,
109 randomWorkdirPart = \
110 globalDictionaries.alignRandDict[firstAlignName]
112 randomWorkdirPart =
None
114 validation = GeometryComparison( name, firstAlign, secondAlign,
116 self.__commandLineOptions.getImages,
118 globalDictionaries.alignRandDict[firstAlignName] = \
119 validation.randomWorkdirPart
120 if not secondAlignName ==
"IDEAL":
121 globalDictionaries.alignRandDict[secondAlignName] = \
122 validation.randomWorkdirPart
123 elif valType ==
"offline":
124 validation = OfflineValidation( name,
126 elif valType ==
"offlineDQM":
127 validation = OfflineValidationDQM( name,
129 elif valType ==
"offlineParallel":
130 validation = OfflineValidationParallel( name,
132 elif valType ==
"mcValidate":
133 validation = MonteCarloValidation( name,
135 elif valType ==
"split":
136 validation = TrackSplittingValidation( name,
138 elif valType ==
"zmumu":
139 validation = ZMuMuValidation( name,
142 raise AllInOneError,
"Unknown validation mode '%s'"%valType
146 """This private method creates the needed files for the validation job.
148 self.validation.createConfiguration( outpath )
149 self.
__scripts = self.validation.createScript( outpath )
150 if jobMode.split(
',' )[0] ==
"crab":
151 self.validation.createCrabCfg( outpath )
155 """This is the method called to create the job files."""
157 os.path.abspath( self.__commandLineOptions.Name) )
160 general = self.__config.getGeneral()
163 name = os.path.splitext( os.path.basename( script) )[0]
164 ValidationJob.jobCount += 1
165 if self.__commandLineOptions.dryRun:
166 print "%s would run: %s"%( name, os.path.basename( script) )
168 log =
"> Validating "+name
169 print "> Validating "+name
170 if self.validation.jobmode ==
"interactive":
172 ValidationJob.interactCount += 1
173 elif self.validation.jobmode.split(
",")[0] ==
"lxBatch":
175 "commands": self.validation.jobmode.split(
",")[1],
176 "logDir": general[
"logdir"],
179 "bsub":
"/afs/cern.ch/cms/caf/scripts/cmsbsub"
183 "-o %(logDir)s/%(jobName)s.stdout "
184 "-e %(logDir)s/%(jobName)s.stderr "
188 ValidationJob.batchJobIds.append(bsubOut.split(
"<")[1].
split(
">")[0])
190 ValidationJob.batchCount += 1
191 elif self.validation.jobmode.split(
"," )[0] ==
"crab":
192 os.chdir( general[
"logdir"] )
193 crabName =
"crab." + os.path.basename( script )[:-3]
195 options = {
"-create":
"",
196 "-cfg": crabName +
".cfg",
199 theCrab.run( options )
200 except AllInOneError, e:
201 print "crab:", str(e).
split(
"\n")[0]
203 ValidationJob.crabCount += 1
206 raise AllInOneError, (
"Unknown 'jobmode'!\n"
207 "Please change this parameter either in "
208 "the [general] or in the ["
210 +
"] section to one of the following "
212 "\tinteractive\n\tlxBatch, -q <queue>\n"
213 "\tcrab, -q <queue>")
223 repMap = offlineValidationList[0].getRepMap()
224 repMap[
"mergeOfflinParJobsInstantiation" ] =
""
226 theFile = open( outFilePath,
"w" )
227 theFile.write(
replaceByMap( configTemplates.mergeOfflineParJobsTemplate ,repMap ) )
231 repMap = offlineValidationList[0].getRepMap()
232 repMap[
"resultPlotFile" ] = resultPlotFile
233 repMap[
"extendedInstantiation" ] =
""
235 for validation
in offlineValidationList:
236 repMap[
"extendedInstantiation" ] = validation.appendToExtendedValidation( repMap[
"extendedInstantiation" ] )
238 theFile = open( outFilePath,
"w" )
240 theFile.write(
replaceByMap( configTemplates.extendedValidationTemplate ,repMap ) )
244 repMap = trackSplittingValidationList[0].getRepMap()
245 repMap[
"trackSplitPlotInstantiation" ] =
""
247 for validation
in trackSplittingValidationList:
248 repMap[
"trackSplitPlotInstantiation" ] = validation.appendToExtendedValidation( repMap[
"trackSplitPlotInstantiation" ] )
250 theFile = open( outFilePath,
"w" )
252 theFile.write(
replaceByMap( configTemplates.trackSplitPlotTemplate ,repMap ) )
256 if(len(validations) == 0):
257 msg =
"Cowardly refusing to merge nothing!"
258 raise AllInOneError(msg)
260 repMap = validations[0].getRepMap()
263 "CompareAlignments":
"",
264 "RunExtendedOfflineValidation":
"",
265 "RunTrackSplitPlot":
""
269 for validation
in validations:
270 for referenceName
in validation.filesToCompare:
271 validationName =
"%s.%s"%(validation.__class__.__name__, referenceName)
272 validationName = validationName.split(
".%s"%GenericValidation.defaultReferenceName )[0]
273 if validationName
in comparisonLists:
274 comparisonLists[ validationName ].
append( validation )
276 comparisonLists[ validationName ] = [ validation ]
278 if "OfflineValidation" in comparisonLists:
279 repMap[
"extendeValScriptPath"] = \
280 os.path.join(path,
"TkAlExtendedOfflineValidation.C")
282 repMap[
"extendeValScriptPath"],
284 repMap[
"RunExtendedOfflineValidation"] = \
285 replaceByMap(configTemplates.extendedValidationExecution, repMap)
287 if "TrackSplittingValidation" in comparisonLists:
288 repMap[
"trackSplitPlotScriptPath"] = \
289 os.path.join(path,
"TkAlTrackSplitPlot.C")
291 repMap[
"trackSplitPlotScriptPath"] )
292 repMap[
"RunTrackSplitPlot"] = \
293 replaceByMap(configTemplates.trackSplitPlotExecution, repMap)
295 repMap[
"CompareAlignments"] =
"#run comparisons"
296 for validationId
in comparisonLists:
297 compareStrings = [ val.getCompareStrings(validationId)
for val
in comparisonLists[validationId] ]
298 compareStringsPlain = [ val.getCompareStrings(validationId, plain=
True)
for val
in comparisonLists[validationId] ]
300 repMap.update({
"validationId": validationId,
301 "compareStrings":
" , ".
join(compareStrings),
302 "compareStringsPlain":
" ".
join(compareStringsPlain) })
304 repMap[
"CompareAlignments"] += \
305 replaceByMap(configTemplates.compareAlignmentsExecution, repMap)
307 filePath = os.path.join(path,
"TkAlMerge.sh")
308 theFile = open( filePath,
"w" )
309 theFile.write(
replaceByMap( configTemplates.mergeTemplate, repMap ) )
311 os.chmod(filePath,0755)
316 if( len(validations) == 0 ):
317 raise AllInOneError,
"cowardly refusing to merge nothing!"
319 repMap = validations[0].getRepMap()
322 "CompareAlignments":
"",
323 "RunExtendedOfflineValidation":
"",
324 "RunTrackSplitPlot":
""
328 for validation
in validations:
329 for referenceName
in validation.filesToCompare:
330 validationName =
"%s.%s"%(validation.__class__.__name__, referenceName)
331 validationName = validationName.split(
".%s"%GenericValidation.defaultReferenceName )[0]
332 if validationName
in comparisonLists:
333 comparisonLists[ validationName ].
append( validation )
335 comparisonLists[ validationName ] = [ validation ]
337 if "OfflineValidationParallel" in comparisonLists:
338 repMap[
"extendeValScriptPath"] = os.path.join(path,
"TkAlExtendedOfflineValidation.C")
339 repMap[
"mergeOfflineParJobsScriptPath"] = os.path.join(path,
"TkAlOfflineJobsMerge.C")
341 repMap[
"mergeOfflineParJobsScriptPath"] )
345 repMap[
"haddLoop"] =
"mergeRetCode=0\n"
346 repMap[
"rmUnmerged"] = (
"if [[ mergeRetCode -eq 0 ]]; then\n"
347 " echo -e \\n\"Merging succeeded, removing original files.\"\n")
348 for validation
in comparisonLists[
"OfflineValidationParallel"]:
349 repMap[
"haddLoop"] = validation.appendToMergeParJobs(repMap[
"haddLoop"])
350 repMap[
"haddLoop"] +=
"tmpMergeRetCode=${?}\n"
351 repMap[
"haddLoop"] += (
"if [[ tmpMergeRetCode -eq 0 ]]; then "
353 +validation.getRepMap()[
"outputFile"]
355 +validation.getRepMap()[
"resultFile"]
357 repMap[
"haddLoop"] += (
"if [[ ${tmpMergeRetCode} -gt ${mergeRetCode} ]]; then "
358 "mergeRetCode=${tmpMergeRetCode}; fi\n")
359 for f
in validation.outputFiles:
360 longName = os.path.join(
"/store/caf/user/$USER/",
361 validation.getRepMap()[
"eosdir"], f)
362 repMap[
"rmUnmerged"] +=
" cmsRm "+longName+
"\n"
363 repMap[
"rmUnmerged"] += (
"else\n"
364 " echo -e \\n\"WARNING: Merging failed, unmerged"
365 " files won't be deleted.\\n"
366 "(Ignore this warning if merging was done earlier)\"\n"
369 repMap[
"RunExtendedOfflineValidation"] = \
370 replaceByMap(configTemplates.extendedValidationExecution, repMap)
374 repMap[
"DownloadData"] +=
replaceByMap(
"rfcp .oO[mergeOfflineParJobsScriptPath]Oo. .", repMap)
375 repMap[
"DownloadData"] +=
replaceByMap( configTemplates.mergeOfflineParallelResults, repMap )
379 if "OfflineValidation" in comparisonLists:
380 comparisonLists[
"OfflineValidationParallel"].extend(comparisonLists[
"OfflineValidation"])
381 del comparisonLists[
"OfflineValidation"]
383 repMap[
"extendeValScriptPath"],
384 "OfflineValidationParallel")
386 repMap[
"CompareAlignments"] =
"#run comparisons"
387 for validationId
in comparisonLists:
388 compareStrings = [ val.getCompareStrings(validationId)
for val
in comparisonLists[validationId] ]
389 compareStringsPlain = [ val.getCompareStrings(validationId, plain=
True)
for val
in comparisonLists[validationId] ]
391 repMap.update({
"validationId": validationId,
392 "compareStrings":
" , ".
join(compareStrings),
393 "compareStringsPlain":
" ".
join(compareStringsPlain) })
395 repMap[
"CompareAlignments"] += \
396 replaceByMap(configTemplates.compareAlignmentsExecution, repMap)
398 filePath = os.path.join(path,
"TkAlMerge.sh")
399 theFile = open( filePath,
"w" )
400 theFile.write(
replaceByMap( configTemplates.mergeTemplate, repMap ) )
402 os.chmod(filePath,0755)
407 if config.has_section(
"alternateTemplates"):
408 for templateName
in config.options(
"alternateTemplates"):
409 newTemplateName = config.get(
"alternateTemplates", templateName )
418 optParser = optparse.OptionParser()
419 optParser.description =
"""All-in-one Alignment Validation.
420 This will run various validation procedures either on batch queues or interactviely.
421 If no name is given (-N parameter) a name containing time and date is created automatically.
422 To merge the outcome of all validation procedures run TkAlMerge.sh in your validation's directory.
424 optParser.add_option(
"-n",
"--dryRun", dest=
"dryRun", action=
"store_true", default=
False,
425 help=
"create all scripts and cfg File but do not start jobs (default=False)")
426 optParser.add_option(
"--getImages", dest=
"getImages", action=
"store_true", default=
False,
427 help=
"get all Images created during the process (default= False)")
428 defaultConfig =
"TkAlConfig.ini"
429 optParser.add_option(
"-c",
"--config", dest=
"config", default = defaultConfig,
430 help=
"configuration to use (default TkAlConfig.ini) this can be a comma-seperated list of all .ini file you want to merge", metavar=
"CONFIG")
431 optParser.add_option(
"-N",
"--Name", dest=
"Name",
432 help=
"Name of this validation (default: alignmentValidation_DATE_TIME)", metavar=
"NAME")
433 optParser.add_option(
"-r",
"--restrictTo", dest=
"restrictTo",
434 help=
"restrict validations to given modes (comma seperated) (default: no restriction)", metavar=
"RESTRICTTO")
435 optParser.add_option(
"-s",
"--status", dest=
"crabStatus", action=
"store_true", default =
False,
436 help=
"get the status of the crab jobs", metavar=
"STATUS")
437 optParser.add_option(
"-d",
"--debug", dest=
"debugMode", action=
"store_true",
439 help=
"run the tool to get full traceback of errors",
441 optParser.add_option(
"-m",
"--autoMerge", dest=
"autoMerge", action=
"store_true", default =
False,
442 help=
"submit TkAlMerge.sh to run automatically when all jobs have finished (default=False)."
443 " Works only for batch jobs")
445 (options, args) = optParser.parse_args(argv)
447 if not options.restrictTo ==
None:
448 options.restrictTo = options.restrictTo.split(
",")
450 options.config = [ os.path.abspath( iniFile )
for iniFile
in \
451 options.config.split(
"," ) ]
452 config = BetterConfigParser()
453 outputIniFileSet =
set( config.read( options.config ) )
454 failedIniFiles = [ iniFile
for iniFile
in options.config
if iniFile
not in outputIniFileSet ]
457 if options.config == [ os.path.abspath( defaultConfig ) ]:
458 if (
not options.crabStatus )
and \
459 (
not os.path.exists( defaultConfig ) ):
460 raise AllInOneError, (
"Default 'ini' file '%s' not found!\n"
461 "You can specify another name with the "
462 "command line option '-c'/'--config'."
465 for iniFile
in failedIniFiles:
466 if not os.path.exists( iniFile ):
467 raise AllInOneError, (
"'%s' does not exist. Please check for "
468 "typos in the filename passed to the "
469 "'-c'/'--config' option!"
472 raise AllInOneError, (
"'%s' does exist, but parsing of the "
476 if options.Name ==
None:
477 if not options.crabStatus:
478 options.Name =
"alignmentValidation_%s"%(datetime.datetime.now().strftime(
"%y%m%d_%H%M%S"))
480 existingValDirs = fnmatch.filter( os.walk(
'.' ).
next()[1],
481 "alignmentValidation_*" )
482 if len( existingValDirs ) > 0:
483 options.Name = existingValDirs[-1]
485 print "Cannot guess last working directory!"
486 print (
"Please use the parameter '-N' or '--Name' to specify "
487 "the task for which you want a status report." )
491 outPath = os.path.abspath( options.Name )
494 if options.crabStatus:
496 crabLogDirs = fnmatch.filter( os.walk(
'.').
next()[1],
"crab.*" )
497 if len( crabLogDirs ) == 0:
498 print "Found no crab tasks for job name '%s'"%( options.Name )
501 for crabLogDir
in crabLogDirs:
503 print "*" +
"=" * 78 +
"*"
504 print (
"| Status report and output retrieval for:"
505 +
" " * (77 - len(
"Status report and output retrieval for:" ) )
507 taskName = crabLogDir.replace(
"crab.",
"" )
508 print "| " + taskName +
" " * (77 - len( taskName ) ) +
"|"
509 print "*" +
"=" * 78 +
"*"
511 crabOptions = {
"-getoutput":
"",
514 theCrab.run( crabOptions )
515 except AllInOneError, e:
516 print "crab: No output retrieved for this task."
517 crabOptions = {
"-status":
"",
519 theCrab.run( crabOptions )
522 general = config.getGeneral()
523 config.set(
"internals",
"workdir",os.path.join(general[
"workdir"],options.Name) )
524 config.set(
"general",
"datadir",os.path.join(general[
"datadir"],options.Name) )
525 config.set(
"general",
"logdir",os.path.join(general[
"logdir"],options.Name) )
526 config.set(
"general",
"eosdir",os.path.join(
"AlignmentValidation", general[
"eosdir"], options.Name) )
530 if os.path.isdir( outPath ):
531 shutil.rmtree( outPath )
533 if not os.path.exists( outPath ):
534 os.makedirs( outPath )
535 elif not os.path.isdir( outPath ):
536 raise AllInOneError,
"the file %s is in the way rename the Job or move it away"%outPath
542 backupConfigFile = open( os.path.join( outPath,
"usedConfiguration.ini" ) ,
"w" )
543 config.write( backupConfigFile )
546 for validation
in config.items(
"validation"):
547 alignmentList = validation[1].
split(config.getSep())
548 validationsToAdd = [(validation[0],alignment) \
549 for alignment
in alignmentList]
550 validations.extend(validationsToAdd)
552 for validation
in validations ]
553 map(
lambda job: job.createJob(), jobs )
554 validations = [ job.getValidation()
for job
in jobs ]
556 if "OfflineValidationParallel" not in [val.__class__.__name__
for val
in validations]:
562 map(
lambda job: job.runJob(), jobs )
564 if options.autoMerge:
567 if ValidationJob.jobCount == ValidationJob.batchCount
and config.getGeneral()[
"jobmode"].
split(
",")[0] ==
"lxBatch":
568 print "> Automatically merging jobs when they have ended"
570 "commands": config.getGeneral()[
"jobmode"].
split(
",")[1],
571 "jobName":
"TkAlMerge",
572 "logDir": config.getGeneral()[
"logdir"],
573 "script":
"TkAlMerge.sh",
574 "bsub":
"/afs/cern.ch/cms/caf/scripts/cmsbsub",
575 "conditions":
'"' +
" && ".
join([
"ended(" + jobId +
")" for jobId
in ValidationJob.batchJobIds]) +
'"'
578 "-o %(logDir)s/%(jobName)s.stdout "
579 "-e %(logDir)s/%(jobName)s.stderr "
581 "%(logDir)s/%(script)s"%repMap)
583 if __name__ ==
"__main__":
585 if "-d" in sys.argv[1:]
or "--debug" in sys.argv[1:]:
590 except AllInOneError, e:
591 print "\nAll-In-One Tool:", str(e)
def createOfflineJobsMergeScript
def createParallelMergeScript
def createTrackSplitPlotScript
— Classes —############################
def main
— Main —############################
def createExtendedValidationScript
def alternateTemplate
### Alternate Templates ###
static std::string join(char **cmd)
def replaceByMap
— Helpers —############################
perl if(1 lt scalar(@::datatypes))
void set(const std::string &name, int value)
set the flag, with a run-time name