CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_10_patch2/src/Alignment/OfflineValidation/scripts/validateAlignments.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #test execute: export CMSSW_BASE=/tmp/CMSSW && ./validateAlignments.py -c defaultCRAFTValidation.ini,test.ini -n -N test
00003 import os
00004 import sys
00005 import ConfigParser
00006 import optparse
00007 import datetime
00008 from pprint import pprint
00009 
00010 import configTemplates #BETA as configTemplates
00011 
00012 ####################--- Helpers ---############################
00013 #replaces .oO[id]Oo. by map[id] in target
00014 def replaceByMap(target, map):
00015     result = target
00016     for id in map:
00017         #print "  "+id+": "+map[id]
00018         lifeSaver = 10e3
00019         iteration = 0
00020         while ".oO[" in result and "]Oo." in result:
00021             for id in map:
00022                 result = result.replace(".oO["+id+"]Oo.",map[id])
00023                 iteration += 1
00024             if iteration > lifeSaver:
00025                 problematicLines = ""
00026                 print map.keys()
00027                 for line in result.splitlines():
00028                     if  ".oO[" in result and "]Oo." in line:
00029                         problematicLines += "%s\n"%line
00030                 raise StandardError, "Oh Dear, there seems to be an endless loop in replaceByMap!!\n%s\nrepMap"%problematicLines
00031     return result
00032 
00033 #excute [command] and return output
00034 def getCommandOutput2(command):
00035     child = os.popen(command)
00036     data = child.read()
00037     err = child.close()
00038     if err:
00039         raise RuntimeError, '%s failed w/ exit code %d' % (command, err)
00040     return data
00041 
00042 #check if a directory exsits on castor
00043 def castorDirExists(path):
00044     if path[-1] == "/":
00045         path = path[:-1]
00046     containingPath = os.path.join( *path.split("/")[:-1] )
00047     dirInQuestion = path.split("/")[-1]
00048     try:
00049         rawLines =getCommandOutput2("rfdir /"+containingPath).splitlines()
00050     except RuntimeError:
00051         return False
00052     for line in rawLines:
00053         if line.split()[0][0] == "d":
00054             if line.split()[8] == dirInQuestion:
00055                 return True
00056     return False
00057 
00058 ####################--- Classes ---############################
00059 class BetterConfigParser(ConfigParser.ConfigParser):
00060     def optionxform(self, optionstr):
00061         return optionstr
00062     
00063     def exists( self, section, option):
00064         try:
00065             items = self.items(section) 
00066         except ConfigParser.NoSectionError:
00067             return False
00068         for item in items:
00069             if item[0] == option:
00070                 return True
00071         return False
00072 
00073 class Alignment:
00074     def __init__(self, name, config):
00075         section = "alignment:%s"%name
00076         self.name = name
00077         if not config.has_section( section ):
00078             raise StandardError, "section %s not found. Please define the alignment!"%section
00079         self.mode = config.get(section, "mode").split()
00080         self.dbpath = config.get(section, "dbpath")
00081         self.__testDbExist( self.dbpath )
00082  
00083         self.errordbpath = "frontier://FrontierProd/CMS_COND_21X_ALIGNMENT"
00084         self.errortag = "TrackerIdealGeometryErrors210_mc"
00085         if config.has_option(section,"errordbpath") and config.has_option(section,"errortag"):
00086             self.errordbpath = config.get(section, "errordbpath")
00087             self.__testDbExist( self.errordbpath )
00088             self.errortag = config.get(section,"errortag")
00089         else:
00090             if config.has_option(section,"errordbpath") or config.has_option(section,"errortag"):
00091                 raise StandardError, "in alignment:%s you have to provide either both errordbpath _and_ errortag or none of both."%name
00092         self.tag = config.get(section,"tag")
00093         
00094         self.color = config.get(section,"color")
00095         self.style = config.get(section,"style")
00096         self.compareTo = {}
00097         for option in config.options( section ):
00098             if option.startswith("compare|"):
00099                 alignmentName = option.split("compare|")[1]
00100                 comparisonList = config.get( section, option ).split()
00101                 if len(comparisonList) == 0:
00102                     raise StandardError, "empty comaprison list '%s' given for %s"%(config.get( section, option ), alignmentName )
00103                 self.compareTo[ alignmentName ] = comparisonList
00104         if self.compareTo == {}:
00105             self.compareTo = {
00106                 "IDEAL":["Tracker","SubDets"]
00107                 }       
00108 
00109     def __testDbExist(self, dbpath):
00110         #FIXME delete return to end train debuging
00111         return
00112         if not dbpath.startswith("sqlite_file:"):
00113             print "WARNING: could not check existence for",dbpath
00114         else:
00115             if not os.path.exists( dbpath.split("sqlite_file:")[1] ):
00116                 raise "could not find file: '%s'"%dbpath.split("sqlite_file:")[1]
00117  
00118     def restrictTo( self, restriction ):
00119         result = []
00120         if not restriction == None:
00121             for mode in self.mode:
00122                 if mode in restriction:
00123                     result.append( mode )
00124             self.mode = result
00125         
00126     def getRepMap( self ):
00127         result = {
00128             "name": self.name,
00129             "dbpath": self.dbpath,
00130             "errordbpath": self.errordbpath,
00131             "tag": self.tag,
00132             "errortag": self.errortag,
00133             "color": self.color,
00134             "style": self.style
00135             
00136             }
00137         return result  
00138 
00139     def getLoadTemplate(self):
00140         return replaceByMap( configTemplates.dbLoadTemplate, self.getRepMap() )
00141 
00142     def createValidations(self, config, options, allAlignments=[]):
00143         """
00144 config is the overall configuration
00145 options are the options as paresed from command line
00146 allAlignemts is a list of Alignment objects the is used to generate Alignment_vs_Alignemnt jobs
00147 """
00148         result = []
00149         for validationName in self.mode:
00150             if validationName == "compare":
00151                 randomWorkdirPart = None #use only one ranom numberr for all geom. comparisions for one alignment
00152                 #test if all needed alignments are defined
00153                 for alignmentName in self.compareTo:
00154                     referenceAlignment = 'IDEAL'
00155                     if not alignmentName == "IDEAL":
00156                         foundAlignment = False
00157                         for alignment in allAlignments:
00158                             if alignment.name == alignmentName:
00159                                 referenceAlignment = alignment
00160                                 foundAlignment = True
00161                         if not foundAlignment:
00162                             raise StandardError, " could not find alignment called '%s'"%alignmentName
00163                     result.append( GeometryComparision( self, referenceAlignment, config, options.getImages, randomWorkdirPart ) )
00164                     if randomWorkdirPart == None:
00165                         randomWorkdirPart = result[-1].randomWorkdirPart
00166             elif validationName == "offline":
00167                 result.append( OfflineValidation( self, config ) )
00168             elif validationName == "offlineDQM":
00169                 result.append( OfflineValidationDQM( self, config ) )
00170             elif validationName == "mcValidate":
00171                 result.append( MonteCarloValidation( self, config ) )
00172             elif validationName == "split":
00173                 result.append( TrackSplittingValidation( self, config ) )
00174             else:
00175                 raise StandardError, "unknown validation mode '%s'"%validationName
00176         return result
00177 
00178 class GenericValidation:
00179     defaultReferenceName = "DEFAULT"
00180 
00181     def __init__(self, alignment, config):
00182         import random
00183         self.alignmentToValidate = alignment
00184         self.__general = readGeneral( config )
00185         self.randomWorkdirPart = "%0i"%random.randint(1,10e9)
00186         self.configFiles = []
00187         self.filesToCompare = {}
00188 #        self.configFileSchedule = None
00189 
00190     def getRepMap(self, alignment = None):
00191         if alignment == None:
00192             alignment = self.alignmentToValidate
00193         result = alignment.getRepMap()
00194         result.update({
00195                 "nEvents": str(self.__general["maxevents"]),
00196                 "dataset": str(self.__general["dataset"]),
00197                 "superPointingDataset": str(self.__general["superPointingDataset"]),
00198                 "RelValSample": self.__general["relvalsample"],
00199                 "TrackCollection": str(self.__general["trackcollection"]),
00200                 "workdir": str(os.path.join(self.__general["workdir"],self.randomWorkdirPart)),
00201                 "datadir": str(self.__general["datadir"]),
00202                 "logdir": str(self.__general["logdir"]),
00203                 "dbLoad": alignment.getLoadTemplate(),
00204                 "CommandLineTemplate": """#run configfile and post-proccess it
00205 cmsRun %(cfgFile)s
00206 %(postProcess)s """,
00207                 "GlobalTag": self.__general["globaltag"],
00208                 "CMSSW_BASE": os.environ['CMSSW_BASE'],
00209                 "alignmentName": alignment.name,
00210                 "offlineModuleLevelHistsTransient":  self.__general["offlineModuleLevelHistsTransient"]
00211                 })
00212         #TODO catch missing delcalration of i.e. dataset or relvalsample here and rethrow to be catched by 
00213         #     individual validation.
00214         return result
00215 
00216     def getCompareStrings( self, requestId = None ):
00217         result = {}
00218         repMap = self.alignmentToValidate.getRepMap()
00219         for validationId in self.filesToCompare:
00220             repMap["file"] = self.filesToCompare[ validationId ]
00221             if repMap["file"].startswith( "/castor/" ):
00222                 repMap["file"] = "rfio:%(file)s"%repMap
00223             result[ validationId ]=  "%(file)s=%(name)s|%(color)s|%(style)s"%repMap 
00224         if requestId == None:
00225             return result
00226         else:
00227             if not "." in requestId:
00228                 requestId += ".%s"%GenericValidation.defaultReferenceName
00229             if not requestId.split(".")[-1] in result:
00230                 raise StandardError, "could not find %s in reference Objects!"%requestId.split(".")[-1]
00231             return result[ requestId.split(".")[-1] ]
00232 
00233     def createFiles( self, fileContents, path ):
00234         result = []
00235         for fileName in fileContents:
00236             filePath = os.path.join( path, fileName)
00237             theFile = open( filePath, "w" )
00238             theFile.write( fileContents[ fileName ] )
00239             theFile.close()
00240             result.append( filePath )
00241         return result
00242 
00243     def createConfiguration(self, fileContents, path, schedule= None):
00244         self.configFiles = GenericValidation.createFiles( self, fileContents, path ) 
00245         if not schedule == None:
00246             schedule = [  os.path.join( path, cfgName) for cfgName in schedule]
00247             for cfgName in schedule:
00248                 if not cfgName in self.configFiles:
00249                     raise StandardError, "scheduled %s missing in generated configfiles: %s"% (cfgName, self.configFiles)
00250             for cfgName in self.configFiles:
00251                 if not cfgName in schedule:
00252                     raise StandardError, "generated configuration %s not scheduled: %s"% (cfgName, schedule)
00253             self.configFiles = schedule
00254         return self.configFiles
00255 
00256     def createScript(self, fileContents, path, downloadFiles=[] ):        
00257         self.scriptFiles =  GenericValidation.createFiles( self, fileContents, path )
00258         for script in self.scriptFiles:
00259             os.chmod(script,0755)
00260         return self.scriptFiles
00261 
00262     
00263 class GeometryComparision(GenericValidation):
00264     """
00265 object representing a geometry comparison job
00266 alignemnt is the alignment to analyse
00267 config is the overall configuration
00268 copyImages indicates wether plot*.eps files should be copied back from the farm
00269 """
00270     def __init__(self, alignment, referenceAlignment, config, copyImages = True, randomWorkdirPart = None):
00271         GenericValidation.__init__(self, alignment, config)
00272         if not randomWorkdirPart == None:
00273             self.randomWorkdirPart = randomWorkdirPart
00274         self.referenceAlignment = referenceAlignment
00275         self.__compares = {}
00276         allCompares = readCompare(config)
00277         referenceName = "IDEAL"
00278         if not self.referenceAlignment == "IDEAL":
00279             referenceName = self.referenceAlignment.name
00280 
00281         #test if all compare sections are present
00282         for compareName in self.alignmentToValidate.compareTo[ referenceName ]:
00283             if compareName in allCompares:
00284                 self.__compares[compareName] = allCompares[compareName]
00285             else:
00286                 raise StandardError, "could not find compare section '%s' in '%s'"%(compareName, allCompares)                  
00287         self.copyImages = copyImages
00288     
00289     def getRepMap(self, alignment = None):
00290         if alignment == None:
00291             alignment = self.alignmentToValidate
00292         repMap = GenericValidation.getRepMap( self, alignment )
00293         referenceName = "IDEAL"
00294         if not self.referenceAlignment == "IDEAL":
00295             referenceName = self.referenceAlignment.name
00296         
00297         repMap.update({"comparedGeometry": ".oO[workdir]Oo./.oO[alignmentName]Oo.ROOTGeometry.root",
00298                        "referenceGeometry": "IDEAL",#will be replaced later if not compared to IDEAL
00299                        "reference": referenceName,
00300                        "APE": configTemplates.APETemplate
00301                        })
00302         if not referenceName == "IDEAL":
00303             repMap["referenceGeometry"] = ".oO[workdir]Oo./.oO[reference]Oo.ROOTGeometry.root"
00304         repMap["name"] += "_vs_.oO[reference]Oo."
00305         return repMap
00306 
00307     def createConfiguration(self, path ):
00308         # self.__compares
00309         repMap = self.getRepMap()
00310         cfgs = {"TkAlCompareToNTuple.%s_cfg.py"%self.alignmentToValidate.name:
00311                     replaceByMap( configTemplates.intoNTuplesTemplate, repMap)}
00312         if not self.referenceAlignment == "IDEAL":
00313             referenceRepMap = self.getRepMap( self.referenceAlignment )
00314             cfgFileName = "TkAlCompareToNTuple.%s.%s_cfg.py"%(self.referenceAlignment.name, self.randomWorkdirPart)
00315             cfgs[ cfgFileName ] = replaceByMap( configTemplates.intoNTuplesTemplate, referenceRepMap)
00316 
00317         cfgSchedule = cfgs.keys()
00318         for common in self.__compares:
00319             repMap.update({"common": common,
00320                            "levels": self.__compares[common][0],
00321                            "dbOutput": self.__compares[common][1]
00322                            })
00323             if self.__compares[common][1].split()[0] == "true":
00324                 repMap["dbOutputService"] = configTemplates.dbOutputTemplate
00325             else:
00326                 repMap["dbOutputService"] = ""
00327             cfgName = replaceByMap("TkAlCompareCommon.oO[common]Oo...oO[name]Oo._cfg.py",repMap)
00328             cfgs[ cfgName ] = replaceByMap(configTemplates.compareTemplate, repMap)
00329             
00330             cfgSchedule.append( cfgName )
00331         GenericValidation.createConfiguration(self, cfgs, path, cfgSchedule)
00332 
00333     def createScript(self, path):    
00334         repMap = self.getRepMap()    
00335         repMap["runComparisonScripts"] = ""
00336         scriptName = replaceByMap("TkAlGeomCompare..oO[name]Oo..sh",repMap)
00337         for name in self.__compares:
00338             if  '"DetUnit"' in self.__compares[name][0].split(","):
00339                 repMap["runComparisonScripts"] += "root -b -q 'comparisonScript.C(\".oO[workdir]Oo./.oO[name]Oo..Comparison_common"+name+".root\",\".oO[workdir]Oo./\")'\n"
00340                 if  self.copyImages:
00341                    repMap["runComparisonScripts"] += "rfmkdir -p .oO[datadir]Oo./.oO[name]Oo..Comparison_common"+name+"_Images\n"
00342                    repMap["runComparisonScripts"] += "find .oO[workdir]Oo. -maxdepth 1 -name \"plot*.eps\" -print | xargs -I {} bash -c \"rfcp {} .oO[datadir]Oo./.oO[name]Oo..Comparison_common"+name+"_Images/\" \n"
00343                    repMap["runComparisonScripts"] += "rfmkdir -p .oO[workdir]Oo./.oO[name]Oo.."+name+"_ArrowPlots\n"
00344                    repMap["runComparisonScripts"] += "root -b -q 'makeArrowPlots.C(\".oO[workdir]Oo./.oO[name]Oo..Comparison_common"+name+".root\",\".oO[workdir]Oo./.oO[name]Oo.."+name+"_ArrowPlots\")'\n"
00345                    repMap["runComparisonScripts"] += "rfmkdir -p .oO[datadir]Oo./.oO[name]Oo..Comparison_common"+name+"_Images/ArrowPlots\n"
00346                    repMap["runComparisonScripts"] += "find .oO[workdir]Oo./.oO[name]Oo.."+name+"_ArrowPlots -maxdepth 1 -name \"*.png\" -print | xargs -I {} bash -c \"rfcp {} .oO[datadir]Oo./.oO[name]Oo..Comparison_common"+name+"_Images/ArrowPlots\"\n"
00347                    
00348                 resultingFile = replaceByMap(".oO[datadir]Oo./compared%s_.oO[name]Oo..root"%name,repMap)
00349                 resultingFile = os.path.expandvars( resultingFile )
00350                 resultingFile = os.path.abspath( resultingFile )
00351                 repMap["runComparisonScripts"] += "rfcp .oO[workdir]Oo./OUTPUT_comparison.root %s\n"%resultingFile
00352                 self.filesToCompare[ name ] = resultingFile
00353                 
00354         repMap["CommandLine"]=""
00355 
00356         for cfg in self.configFiles:
00357 #find . -maxdepth 1 -name \"LOGFILE_*_.oO[name]Oo..log\" -print | xargs -I {} bash -c 'echo \"*** \";echo \"**   {}\";echo \"***\" ; cat {}' > .oO[workdir]Oo./LOGFILE_GeomComparision_.oO[name]Oo..log
00358 #cd .oO[workdir]Oo.
00359             postProcess = "rfcp .oO[workdir]Oo./*.db .oO[datadir]Oo.\n"
00360             repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfg,
00361                                                                    "postProcess":postProcess
00362                                                                    }
00363         repMap["CommandLine"]+= """# overall postprocessing
00364 cd .oO[CMSSW_BASE]Oo./src/Alignment/OfflineValidation/scripts/
00365 .oO[runComparisonScripts]Oo.
00366 cd .oO[workdir]Oo.
00367 """
00368         scripts = {scriptName: replaceByMap( configTemplates.scriptTemplate, repMap ) }  
00369         return GenericValidation.createScript(self, scripts, path)
00370         
00371 class OfflineValidation(GenericValidation):
00372     def __init__(self, alignment,config):
00373         GenericValidation.__init__(self, alignment, config)
00374         general = readGeneral( config )
00375         self.__DMRMethod = general["DMRMethod"]
00376         self.__DMRMinimum = general["DMRMinimum"]
00377         self.__OfflineTreeBaseDir = general["OfflineTreeBaseDir"]
00378     
00379     def createConfiguration(self, path, configBaseName = "TkAlOfflineValidation" ):
00380         cfgName = "%s.%s_cfg.py"%( configBaseName, self.alignmentToValidate.name )
00381         repMap = self.getRepMap()
00382           
00383         cfgs = {cfgName:replaceByMap( configTemplates.offlineTemplate, repMap)}
00384         self.filesToCompare[ GenericValidation.defaultReferenceName ] = repMap["resultFile"] 
00385         GenericValidation.createConfiguration(self, cfgs, path)
00386         
00387     def createScript(self, path, scriptBaseName = "TkAlOfflineValidation"):
00388         scriptName = "%s.%s.sh"%(scriptBaseName, self.alignmentToValidate.name )
00389         repMap = GenericValidation.getRepMap(self)
00390         repMap["CommandLine"]=""
00391         for cfg in self.configFiles:
00392             repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfg,
00393                                                   "postProcess":""
00394                                                   }
00395         scripts = {scriptName: replaceByMap( configTemplates.scriptTemplate, repMap ) }
00396         return GenericValidation.createScript(self, scripts, path)
00397 
00398     def getRepMap(self, alignment = None):
00399         repMap = GenericValidation.getRepMap(self, alignment) 
00400         repMap.update({
00401                 "OfflineTreeBaseDir": self.__OfflineTreeBaseDir,
00402                 "DMRMethod":self.__DMRMethod,
00403                 "DMRMinimum":self.__DMRMinimum,
00404                 "APE": configTemplates.APETemplate,
00405                 "outputFile": replaceByMap( ".oO[workdir]Oo./AlignmentValidation_.oO[name]Oo..root", repMap ),
00406                 "resultFile": replaceByMap( ".oO[datadir]Oo./AlignmentValidation_.oO[name]Oo..root", repMap ),
00407                 "TrackSelectionTemplate": configTemplates.TrackSelectionTemplate,
00408                 "LorentzAngleTemplate": configTemplates.LorentzAngleTemplate,
00409                 "offlineValidationMode": "Standalone",
00410                 "offlineValidationFileOutput": configTemplates.offlineStandaloneFileOutputTemplate
00411                 })
00412         repMap["outputFile"] = os.path.expandvars( repMap["outputFile"] )
00413         repMap["outputFile"] = os.path.abspath( repMap["outputFile"] )
00414         repMap["resultFile"] = os.path.expandvars( repMap["resultFile"] )
00415         repMap["resultFile"] = os.path.abspath( repMap["resultFile"] )
00416         
00417         return repMap
00418 
00419     
00420     def appendToExtendedValidation( self, validationsSoFar = "" ):
00421         """
00422         if no argument or "" is passed a string with an instantiation is returned, 
00423         else the validation is appended to the list
00424         """
00425         repMap = self.getRepMap()
00426         if validationsSoFar == "":
00427             validationsSoFar = 'PlotAlignmentValidation p("%(resultFile)s", "%(name)s", %(color)s, %(style)s);\n'%repMap
00428         else:
00429             validationsSoFar +='p.loadFileList("%(resultFile)s", "%(name)s", %(color)s, %(style)s);\n'%repMap
00430 
00431 #          PlotAlignmentValidation p(".oO[firstFile]Oo.",".oO[firstLegendEntry]Oo.");
00432 #  p.loadFileList("rfio:/castor/cern.ch/user/j/jdraeger/Validation/MCfromCRAFT/new/Validation_MC_Adun1_CosmicTF.root","Brot ist lecker2");
00433         return validationsSoFar
00434 
00435 class OfflineValidationDQM(OfflineValidation):
00436     def __init__(self, alignment, config):
00437         OfflineValidation.__init__(self, alignment, config)
00438         if not config.has_section("DQM"):
00439             raise StandardError, "You need to have a DQM section in your configfile!"
00440         
00441         self.__PrimaryDataset = config.get("DQM", "primaryDataset")
00442         self.__firstRun = int(config.get("DQM", "firstRun"))
00443         self.__lastRun = int(config.get("DQM", "lastRun"))
00444 
00445     def createConfiguration(self, path):
00446         OfflineValidation.createConfiguration(self, path, "TkAlOfflineValidationDQM")
00447         
00448     def createScript(self, path):
00449         return OfflineValidation.createScript(self, path, "TkAlOfflineValidationDQM")
00450 
00451     def getRepMap(self, alignment = None):
00452         repMap = OfflineValidation.getRepMap(self, alignment)
00453         repMap.update({
00454                 "workdir": os.path.expandvars(repMap["workdir"]),
00455                 "offlineValidationMode": "Dqm",
00456                 "offlineValidationFileOutput": configTemplates.offlineDqmFileOutputTemplate,
00457                 "workflow": "/%s/TkAl%s-.oO[alignmentName]Oo._R%09i_R%09i_ValSkim-v1/ALCARECO"%(self.__PrimaryDataset, datetime.datetime.now().strftime("%y"), self.__firstRun, self.__lastRun),
00458                 "firstRunNumber": "%i"% self.__firstRun
00459                 }
00460             )
00461         if "__" in repMap["workflow"]:
00462             raise StandardError, "the DQM workflow specefication must not contain '__'. it is: %s"%repMap["workflow"]
00463         return repMap
00464 
00465 class MonteCarloValidation(GenericValidation):
00466     def __init__(self, alignment, config):
00467         GenericValidation.__init__(self, alignment, config)
00468 
00469     def createConfiguration(self, path ):
00470         cfgName = "TkAlMcValidation.%s_cfg.py"%( self.alignmentToValidate.name )
00471         repMap = GenericValidation.getRepMap(self)
00472         repMap.update({
00473                 "APE": configTemplates.APETemplate,
00474                 "outputFile": replaceByMap( ".oO[workdir]Oo./McValidation_.oO[name]Oo..root", repMap )
00475                 })
00476         repMap["outputFile"] = os.path.expandvars( repMap["outputFile"] )
00477         repMap["outputFile"] = os.path.abspath( repMap["outputFile"] )
00478         cfgs = {cfgName:replaceByMap( configTemplates.mcValidateTemplate, repMap)}
00479         self.filesToCompare[ GenericValidation.defaultReferenceName ] = repMap["outputFile"]
00480         GenericValidation.createConfiguration(self, cfgs, path)
00481 
00482     def createScript(self, path):
00483         scriptName = "TkAlMcValidate.%s.sh"%( self.alignmentToValidate.name )
00484         repMap = GenericValidation.getRepMap(self)
00485         repMap["CommandLine"]=""
00486         for cfg in self.configFiles:
00487             repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfg,
00488                                                   "postProcess":""
00489                                                   }
00490 
00491         scripts = {scriptName: replaceByMap( configTemplates.scriptTemplate, repMap ) }
00492         return GenericValidation.createScript(self, scripts, path)
00493 
00494 class TrackSplittingValidation(GenericValidation):
00495     def __init__(self, alignment, config):
00496         GenericValidation.__init__(self, alignment, config)
00497 
00498     def createConfiguration(self, path ):
00499         cfgName = "TkAlTrackSplitting.%s_cfg.py"%( self.alignmentToValidate.name )
00500         repMap = GenericValidation.getRepMap(self)
00501         repMap.update({
00502                 "APE": configTemplates.APETemplate,
00503                 "outputFile": replaceByMap( ".oO[workdir]Oo./TrackSplitting_.oO[name]Oo..root", repMap )
00504                 })
00505         repMap["outputFile"] = os.path.expandvars( repMap["outputFile"] )
00506         repMap["outputFile"] = os.path.abspath( repMap["outputFile"] )
00507         cfgs = {cfgName:replaceByMap( configTemplates.TrackSplittingTemplate, repMap)}
00508         self.filesToCompare[ GenericValidation.defaultReferenceName ] = repMap["outputFile"]
00509         GenericValidation.createConfiguration(self, cfgs, path)
00510 
00511     def createScript(self, path):
00512         scriptName = "TkAlTrackSplitting.%s.sh"%( self.alignmentToValidate.name )
00513         repMap = GenericValidation.getRepMap(self)
00514         repMap["CommandLine"]=""
00515         for cfg in self.configFiles:
00516             repMap["CommandLine"]+= repMap["CommandLineTemplate"]%{"cfgFile":cfg,
00517                                                   "postProcess":""
00518                                                   }
00519 
00520         scripts = {scriptName: replaceByMap( configTemplates.scriptTemplate, repMap ) }
00521         return GenericValidation.createScript(self, scripts, path)
00522 
00523 ####################--- Read Configfiles ---############################
00524 def readAlignments( config ):
00525     result = []
00526     for section in config.sections():
00527         if "alignment:" in section:
00528             result.append( Alignment( section.split("alignment:")[1], config ) )
00529     return result
00530 
00531 def readCompare( config ):
00532     result = {}
00533     for section in config.sections():
00534         if "compare:" in section:
00535             levels =  config.get(section, "levels")
00536             dbOutput = config.get(section, "dbOutput")
00537             result[section.split(":")[1]] =(levels,dbOutput)
00538     return result
00539 
00540 def readGeneral( config ):
00541     result = {
00542         "jobmode":"interactive",
00543         "superPointingDataset":"",# see remark about rethroughung missing entries in general. this is needed to be backward compatible
00544         "workdir":os.getcwd(),
00545         "datadir":os.getcwd(),
00546         "logdir":os.getcwd(),
00547         "offlineModuleLevelHistsTransient":"False",
00548         "OfflineTreeBaseDir":"TrackHitFilter",
00549         "DMRMethod":"medianX",
00550         "DMRMinimum":"30"
00551         }
00552     try:
00553        for option in config.options("general"):
00554           result[option] = config.get("general",option)
00555            
00556        if "localGeneral" in config.sections():
00557           for option in result:
00558              if option in [item[0] for item in config.items("localGeneral")]:
00559                 result[ option ] = config.get("localGeneral", option)
00560     except ConfigParser.NoSectionError, section:
00561        raise StandardError, "missing section '%s' in configuration files. This section is mandatory."%section
00562     return result
00563 
00564 def runJob(jobName, script, config):
00565     general = readGeneral( config )
00566     log = ">             Validating "+jobName
00567     print ">             Validating "+jobName
00568     if general["jobmode"] == "interactive":
00569         log += getCommandOutput2( script )
00570     if general["jobmode"].split(",")[0] == "lxBatch":
00571         repMap = { 
00572             "commands": general["jobmode"].split(",")[1],
00573             "logDir": general["logdir"],
00574             "jobName": jobName,
00575             "script": script,
00576             "bsub": "/afs/cern.ch/cms/caf/scripts/cmsbsub"
00577             }
00578         
00579         log+=getCommandOutput2("%(bsub)s %(commands)s -J %(jobName)s -o %(logDir)s/%(jobName)s.stdout -e %(logDir)s/%(jobName)s.stderr %(script)s"%repMap)
00580     return log
00581 
00582 def createExtendedValidationScript(offlineValidationList, outFilePath):
00583     repMap = offlineValidationList[0].getRepMap() # bit ugly since some special features are filled
00584     repMap[ "extendedInstantiation" ] = "" #give it a "" at first in order to get the initialisation back
00585 
00586     for validation in offlineValidationList:
00587         repMap[ "extendedInstantiation" ] = validation.appendToExtendedValidation( repMap[ "extendedInstantiation" ] )
00588     
00589     theFile = open( outFilePath, "w" )
00590     theFile.write( replaceByMap( configTemplates.extendedVaidationTemplate ,repMap ) )
00591     theFile.close()
00592     
00593 def createMergeScript( path, validations ):
00594     if( len(validations) == 0 ):
00595         raise StandardError, "cowardly refusing to merge nothing!"
00596 
00597     repMap = validations[0].getRepMap() #FIXME - not nice this way
00598     repMap.update({
00599             "DownloadData":"",
00600             "CompareAllignments":"",
00601             "RunExtendedOfflineValidation":""
00602             })
00603 
00604     comparisonLists = {} # directory of lists containing the validations that are comparable
00605     for validation in validations:
00606         for referenceName in validation.filesToCompare:    
00607             validationName = "%s.%s"%(validation.__class__.__name__, referenceName)
00608             validationName = validationName.split(".%s"%GenericValidation.defaultReferenceName )[0]
00609             if validationName in comparisonLists:
00610                 comparisonLists[ validationName ].append( validation )
00611             else:
00612                 comparisonLists[ validationName ] = [ validation ]
00613 
00614     if "OfflineValidation" in comparisonLists:
00615         repMap["extendeValScriptPath"] = os.path.join(path, "TkAlExtendedOfflineValidation.C")
00616         createExtendedValidationScript( comparisonLists["OfflineValidation"], repMap["extendeValScriptPath"] )
00617         repMap["RunExtendedOfflineValidation"] = replaceByMap(configTemplates.extendedVaidationExecution, repMap)
00618 
00619     repMap["CompareAllignments"] = "#run comparisons"
00620     for validationId in comparisonLists:
00621         compareStrings = [ val.getCompareStrings(validationId) for val in comparisonLists[validationId] ]
00622             
00623         repMap.update({"validationId": validationId,
00624                        "compareStrings": " , ".join(compareStrings) })
00625         
00626         repMap["CompareAllignments"] += replaceByMap( configTemplates.compareAlignmentsExecution, repMap )
00627       
00628     filePath = os.path.join(path, "TkAlMerge.sh")
00629     theFile = open( filePath, "w" )
00630     theFile.write( replaceByMap( configTemplates.mergeTemplate, repMap ) )
00631     theFile.close()
00632     os.chmod(filePath,0755)
00633     
00634     return filePath
00635     
00636 def loadTemplates( config ):
00637     if config.has_section("alternateTemplates"):
00638         for templateName in config.options("alternateTemplates"):
00639             newTemplateName = config.get("alternateTemplates", templateName )
00640             #print "replacing default %s template by %s"%( templateName, newTemplateName)
00641             configTemplates.alternateTemplate(templateName, newTemplateName)
00642     
00643 ####################--- Main ---############################
00644 def main(argv = None):
00645     if argv == None:
00646        argv = sys.argv[1:]
00647     optParser = optparse.OptionParser()
00648     optParser.description = """ all-in-one alignment Validation 
00649     This will run various validation procedures either on batch queues or interactviely. 
00650     
00651     If no name is given (-N parameter) a name containing time and date is created automatically
00652     
00653     To merge the outcome of all validation procedures run TkAlMerge.sh in your validation's directory.
00654     """
00655     optParser.add_option("-n", "--dryRun", dest="dryRun", action="store_true", default=False,
00656                          help="create all scripts and cfg File but do not start jobs (default=False)")
00657     optParser.add_option( "--getImages", dest="getImages", action="store_true", default=False,
00658                           help="get all Images created during the process (default= False)")
00659     optParser.add_option("-c", "--config", dest="config",
00660                          help="configuration to use (default compareConfig.ini) this can be a comma-seperated list of all .ini file you want to merge", metavar="CONFIG")
00661     optParser.add_option("-N", "--Name", dest="Name",
00662                          help="Name of this validation (default: alignmentValidation_DATE_TIME)", metavar="NAME")
00663     optParser.add_option("-r", "--restrictTo", dest="restrictTo",
00664                          help="restrict validations to given modes (comma seperated) (default: no restriction)", metavar="RESTRICTTO")
00665 
00666     (options, args) = optParser.parse_args(argv)
00667 
00668     if not options.restrictTo == None:
00669         options.restrictTo = options.restrictTo.split(",")
00670     if options.config == None:
00671         options.config = "compareConfig.ini"
00672     else:
00673         options.config = options.config.split(",")
00674         result = []
00675         for iniFile in options.config:
00676             result.append( os.path.abspath(iniFile) )
00677         options.config = result
00678     config = BetterConfigParser()
00679     config.read( options.config )
00680 
00681     if options.Name == None:
00682         options.Name = "alignmentValidation_%s"%(datetime.datetime.now().strftime("%y%m%d_%H%M%S"))
00683 
00684     outPath = os.path.abspath( options.Name )
00685     general = readGeneral( config )
00686     config.set("general","workdir",os.path.join(general["workdir"],options.Name) )
00687     config.set("general","datadir",os.path.join(general["datadir"],options.Name) )
00688     config.set("general","logdir",os.path.join(general["logdir"],options.Name) )
00689     if not os.path.exists( outPath ):
00690         os.makedirs( outPath )
00691     elif not os.path.isdir( outPath ):
00692         raise StandardError,"the file %s is in the way rename the Job or move it away"%outPath
00693 
00694     #replace default templates by the once specified in the "alternateTemplates" section
00695     loadTemplates( config )
00696 
00697     log = ""
00698     alignments = readAlignments( config )
00699     validations = []
00700     for alignment in alignments:
00701         alignment.restrictTo( options.restrictTo )
00702         validations.extend( alignment.createValidations( config, options, alignments ) )
00703 
00704     scripts = []
00705     for validation in validations:
00706         validation.createConfiguration( outPath )
00707         scripts.extend( validation.createScript( outPath ) )
00708     
00709     createMergeScript( outPath, validations )
00710 
00711     #save backup configuration file
00712     backupConfigFile = open( os.path.join( outPath, "usedConfiguration.ini" ) , "w"  )
00713     config.write( backupConfigFile )
00714 
00715     for script in scripts:
00716         name = os.path.splitext( os.path.basename( script ) )[0]
00717         if options.dryRun:
00718             print "%s would run: %s"%( name, script)
00719         else:
00720             runJob( name, script, config)
00721 
00722 if __name__ == "__main__":        
00723    # main(["-n","-N","test","-c","defaultCRAFTValidation.ini,latestObjects.ini","--getImages"])
00724    main()
00725