Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:32:51

0001 import copy
0002 import os
0003 
0004 def DMR(config, validationDir):
0005     ##List with all jobs
0006     jobs = []
0007     dmrType = "single"
0008 
0009     ##Dictionary of lists of all IOVs (can be different per each single job)
0010     IOVs = {}
0011 
0012     ##Auxilliary dictionary of isData flags per each merged job
0013     isDataMerged = {} 
0014 
0015     ##Start with single DMR jobs
0016     if not dmrType in config["validations"]["DMR"]: 
0017         raise Exception("No 'single' key word in config for DMR") 
0018 
0019     for singleName in config["validations"]["DMR"][dmrType]:
0020         aux_IOV = config["validations"]["DMR"][dmrType][singleName]["IOV"]
0021         if not isinstance(aux_IOV, list) and aux_IOV.endswith(".txt"):
0022             config["validations"]["DMR"][dmrType][singleName]["IOV"] = []
0023             with open(aux_IOV, 'r') as IOVfile:
0024                 for line in IOVfile.readlines():
0025                     if len(line) != 0: config["validations"]["DMR"][dmrType][singleName]["IOV"].append(int(line))
0026         for IOV in config["validations"]["DMR"][dmrType][singleName]["IOV"]:
0027             ##Save IOV to loop later for merge jobs
0028             if singleName not in IOVs.keys():
0029                 IOVs[singleName] = [] 
0030             if IOV not in IOVs[singleName]:
0031                 IOVs[singleName].append(IOV)
0032 
0033             for alignment in config["validations"]["DMR"][dmrType][singleName]["alignments"]:
0034                 ##Work directory for each IOV
0035                 workDir = "{}/DMR/{}/{}/{}/{}".format(validationDir, dmrType, singleName, alignment, IOV)
0036 
0037                 ##Write local config
0038                 local = {}
0039                 local["output"] = "{}/{}/DMR/{}/{}/{}/{}".format(config["LFS"], config["name"], dmrType, alignment, singleName, IOV)
0040                 local["alignment"] = copy.deepcopy(config["alignments"][alignment])
0041                 local["validation"] = copy.deepcopy(config["validations"]["DMR"][dmrType][singleName])
0042                 local["validation"].pop("alignments")
0043                 local["validation"]["IOV"] = IOV
0044                 if "dataset" in local["validation"]:
0045                     local["validation"]["dataset"] = local["validation"]["dataset"].format(IOV)
0046                 if "goodlumi" in local["validation"]:
0047                     local["validation"]["goodlumi"] = local["validation"]["goodlumi"].format(IOV)
0048 
0049                 ##Write job info
0050                 job = {
0051                     "name": "DMR_{}_{}_{}_{}".format(dmrType, alignment, singleName, IOV),
0052                     "dir": workDir,
0053                     "exe": "cmsRun",
0054                     "cms-config": "{}/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/DMR_cfg.py".format(os.environ["CMSSW_BASE"]),
0055                     "run-mode": "Condor",
0056                     "dependencies": [],
0057                     "config": local, 
0058                 }
0059 
0060                 jobs.append(job)
0061 
0062     ##Do merge DMR if wished
0063     if "merge" in config["validations"]["DMR"]:
0064         ##List with merge jobs, will be expanded to jobs after looping
0065         mergeJobs = []
0066         dmrType = "merge"
0067 
0068         ##Loop over all merge jobs
0069         for mergeName in config["validations"]["DMR"][dmrType]:
0070             ##Search for MC single(s)
0071             singlesMC = []
0072             for singleName in config["validations"]["DMR"][dmrType][mergeName]['singles']:
0073                 if len(IOVs[singleName]) == 1 and int(IOVs[singleName][0]) == 1: singlesMC.append(singleName) 
0074             isMConly = (len(singlesMC) == len(config["validations"]["DMR"][dmrType][mergeName]['singles']))
0075             if isMConly:
0076                 isDataMerged[mergeName] = 0
0077             elif len(singlesMC) == 0:
0078                 isDataMerged[mergeName] = 1
0079             else:
0080                 isDataMerged[mergeName] = -1   
0081 
0082             ##Loop over singles 
0083             for iname,singleName in enumerate(config["validations"]["DMR"][dmrType][mergeName]['singles']):
0084                 isMC = (singleName in singlesMC)
0085                 if isMConly and iname > 0: continue #special case for MC only comparison
0086                 elif isMConly: singlesMC.pop(singlesMC.index(singleName))
0087   
0088                 for IOV in IOVs[singleName]:
0089                     if isMC and not isMConly: continue #ignore IOV=1 as it is automatically added to each DATA IOV unless MC only comparison
0090  
0091                     ##Work directory for each IOV
0092                     workDir = "{}/DMR/{}/{}/{}".format(validationDir, dmrType, mergeName, IOV) #Different (DATA) single jobs must contain different set of IOVs
0093 
0094                     ##Write job info
0095                     local = {}
0096 
0097                     job = {
0098                         "name": "DMR_{}_{}_{}".format(dmrType, mergeName, IOV),
0099                         "dir": workDir,
0100                         "exe": "DMRmerge",
0101                         "run-mode": "Condor",
0102                         "dependencies": [],
0103                         "config": local, 
0104                     }
0105 
0106                     ##Deep copy necessary things from global config + assure plot order
0107                     for alignment in config["alignments"]:
0108                         idxIncrement = 0
0109                         local.setdefault("alignments", {})
0110                         if alignment in config["validations"]["DMR"]["single"][singleName]["alignments"]: #Cover all DATA validations
0111                             local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
0112                             local["alignments"][alignment]['index'] = config["validations"]["DMR"]["single"][singleName]["alignments"].index(alignment)
0113                         for singleMCname in singlesMC:
0114                             if alignment in config["validations"]["DMR"]["single"][singleMCname]["alignments"]: #Add MC objects
0115                                 local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
0116                                 local["alignments"][alignment]['index']  = len(config["validations"]["DMR"]["single"][singleName]["alignments"])
0117                                 local["alignments"][alignment]['index'] += idxIncrement + config["validations"]["DMR"]["single"][singleMCname]["alignments"].index(alignment)                           
0118                             idxIncrement += len(config["validations"]["DMR"]["single"][singleMCname]["alignments"])   
0119                     local["validation"] = copy.deepcopy(config["validations"]["DMR"][dmrType][mergeName])
0120                     local["validation"]["IOV"] = IOV #is it really needed here?
0121                     if "customrighttitle" in local["validation"].keys():
0122                         if "IOV" in local["validation"]["customrighttitle"]:
0123                             local["validation"]["customrighttitle"] = local["validation"]["customrighttitle"].replace("IOV",str(IOV)) 
0124                     local["output"] = "{}/{}/DMR/{}/{}/{}".format(config["LFS"], config["name"], dmrType, mergeName, IOV)
0125 
0126                     ##Add global plotting options
0127                     if "style" in config.keys():
0128                         if "DMR" in config['style'].keys():
0129                             if dmrType in config['style']['DMR'].keys():
0130                                 local["style"] = copy.deepcopy(config["style"]["DMR"][dmrType])
0131                                 if "Rlabel" in local["style"] and "customrighttitle" in local["validation"].keys():
0132                                     print("WARNING: custom right label is overwritten by global settings") 
0133  
0134                     ##Loop over all single jobs
0135                     for singleJob in jobs:
0136                         ##Get single job info and append to merge job if requirements fullfilled
0137                         _alignment, _singleName, _singleIOV = singleJob["name"].split("_")[2:]
0138                         if _singleName in config["validations"]["DMR"][dmrType][mergeName]["singles"]:
0139                             if int(_singleIOV) == IOV or (int(_singleIOV) == 1 and _singleName in singlesMC): #matching DATA job or any MC single job 
0140                                 local["alignments"][_alignment]["file"] = singleJob["config"]["output"]
0141                                 job["dependencies"].append(singleJob["name"])
0142                                 
0143                     ##Append to merge jobs  
0144                     mergeJobs.append(job)
0145 
0146         ##Append to all jobs
0147         jobs.extend(mergeJobs)
0148 
0149     if "trends" in config["validations"]["DMR"]:
0150 
0151         ##List with merge jobs, will be expanded to jobs after looping
0152         trendJobs = []
0153         dmrType = "trends"
0154 
0155         for trendName in config["validations"]["DMR"][dmrType]:
0156             #print("trendName = {}".format(trendName))
0157             ##Work directory for each IOV
0158             workDir = "{}/DMR/{}/{}".format(validationDir, dmrType, trendName)
0159  
0160             ##Write general job info
0161             local = {}
0162             job = {
0163                 "name": "DMR_{}_{}".format(dmrType, trendName),
0164                 "dir": workDir,
0165                 "exe": "DMRtrends",
0166                 "run-mode": "Condor",
0167                 "dependencies": [],
0168                 "config": local,
0169             }
0170 
0171             ###Loop over merge steps (merge step can contain only DATA)
0172             mergesDATA = []
0173             for mergeName in config["validations"]["DMR"][dmrType][trendName]["merges"]:
0174                 ##Validate merge step
0175                 if isDataMerged[mergeName] < 0:
0176                     raise Exception("Trend jobs cannot process merge jobs containing both DATA and MC objects.")
0177                 elif isDataMerged[mergeName] == 1:
0178                     mergesDATA.append(mergeName)
0179                 else:
0180                     if "doUnitTest" in config["validations"]["DMR"][dmrType][trendName].keys() and config["validations"]["DMR"][dmrType][trendName]["doUnitTest"]:
0181                         local.setdefault("alignments", {})
0182                         continue
0183                     else: 
0184                         raise Exception("Trend jobs are not implemented for treating MC.")
0185 
0186             ###Loop over DATA singles included in merge steps
0187             trendIOVs = []
0188             _mergeFiles = []
0189             for mergeName in mergesDATA:
0190                 for iname,singleName in enumerate(config["validations"]["DMR"]['merge'][mergeName]['singles']): 
0191                     trendIOVs += [IOV for IOV in IOVs[singleName]]
0192                     ##Deep copy necessary things from global config + ensure plot order
0193                     for alignment in config["alignments"]:
0194                         local.setdefault("alignments", {})
0195                         if alignment in config["validations"]["DMR"]["single"][singleName]["alignments"]: #Cover all DATA validations
0196                             local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
0197                             local["alignments"][alignment]['index'] = config["validations"]["DMR"]["single"][singleName]["alignments"].index(alignment)
0198                 _mergeFiles.append("{}/{}/DMR/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}")) 
0199             trendIOVs.sort() 
0200             local["validation"] = copy.deepcopy(config["validations"]["DMR"][dmrType][trendName])
0201             if len(_mergeFiles) == 1:
0202                 local["validation"]["mergeFile"] = _mergeFiles[0]
0203             else:
0204                 local["validation"]["mergeFile"] = _mergeFiles #FIXME for multiple merge files in backend
0205             local["validation"]["IOV"] = trendIOVs
0206             local["output"] = "{}/{}/DMR/{}/{}/".format(config["LFS"], config["name"], dmrType, trendName)
0207             if "style" in config.keys() and "trends" in config["style"].keys():
0208                 local["style"] = copy.deepcopy(config["style"])
0209                 if "DMR" in local["style"].keys(): local["style"].pop("DMR") 
0210                 if "CMSlabel" in config["style"]["trends"].keys(): local["style"]["CMSlabel"] = config["style"]["trends"]["CMSlabel"]
0211                 if "Rlabel" in config["style"]["trends"].keys(): 
0212                     local["style"]["trends"].pop("Rlabel")
0213                     local["style"]["trends"]["TitleCanvas"] = config["style"]["trends"]["Rlabel"]
0214             else:
0215                 raise Exception("You want to create 'trends' jobs, but there are no 'lines' section in the config for pixel updates!")
0216 
0217             #Loop over all merge jobs
0218             for mergeName in mergesDATA:
0219                 for mergeJob in mergeJobs:
0220                     alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:]
0221                     if mergeJobName == mergeName and int(mergeIOV) in trendIOVs:
0222                         job["dependencies"].append(mergeJob["name"])
0223 
0224             trendJobs.append(job)
0225 
0226         jobs.extend(trendJobs)
0227 
0228     if "averaged" in config["validations"]["DMR"]:
0229 
0230         ####Finally, list of jobs is expanded for luminosity-averaged plot (avp) job
0231         avpJobs = []
0232         dmrType = "averaged"
0233         for avpName in config["validations"]["DMR"][dmrType]:
0234             ###Main workdir for each combination of displayed lumi-averaged validation objects to be plotted
0235             workDir = "{}/DMR/{}/{}".format(validationDir, dmrType, avpName) 
0236             output  = "{}/{}/DMR/{}/{}".format(config["LFS"], config["name"], dmrType, avpName)
0237             
0238             ###Loop over merge steps (one merge step can contain only DATA or only MC singles but not mix)
0239             mergesDATA = []
0240             mergesMC   = []
0241             for mergeName in config["validations"]["DMR"][dmrType][avpName]["merges"]:
0242                 ##Validate merge step
0243                 if isDataMerged[mergeName] < 0:
0244                     raise Exception("Average jobs cannot process merge jobs containing both DATA and MC objects.")
0245                 elif isDataMerged[mergeName] == 1: 
0246                     mergesDATA.append(mergeName)
0247                 else:
0248                     mergesMC.append(mergeName) 
0249 
0250             lumiPerRun = []
0251             lumiPerIoV = []
0252             lumiMC     = [] 
0253             if len(mergesDATA) > 0:  
0254                 if "lumiPerRun" in config["validations"]["DMR"][dmrType][avpName].keys(): 
0255                     for lumifile in config["validations"]["DMR"][dmrType][avpName]['lumiPerRun']:
0256                         if lumifile.split(".")[-1] in ["txt","csv"]:
0257                             lumiPerRun.append(lumifile)
0258                 if "lumiPerIoV" in config["validations"]["DMR"][dmrType][avpName].keys():
0259                     for lumifile in config["validations"]["DMR"][dmrType][avpName]['lumiPerIoV']:
0260                         if lumifile.split(".")[-1] in ["txt","csv"]:
0261                             lumiPerIoV.append(lumifile)
0262                 if len(lumiPerRun) == 0 and len(lumiPerIoV) == 0: 
0263                     raise Exception("No lumi per run/IoV file found or not specified in .csv/.txt format.")
0264             if len(mergesMC) > 0: 
0265                 if 'lumiMC' in config["validations"]["DMR"][dmrType][avpName].keys():
0266                     lumiMC = config["validations"]["DMR"][dmrType][avpName]['lumiMC']
0267  
0268             ###Store information about plotting job in this dictionary
0269             plotJob = {}
0270             plotJob['workdir'] = "{}/{}".format(workDir,"plots")
0271             plotJob['output'] = "{}/{}".format(output,"plots")
0272             plotJob['inputData'] = []
0273             plotJob['inputMC'] = []
0274             plotJob['dependencies'] = []
0275 
0276             ###First loop over DATA 
0277             for mergeName in mergesDATA:
0278                 ##Adapt workdir per merge step
0279                 workDirMerge = "{}/{}".format(workDir, mergeName)
0280                 outputMerge  = "{}/{}".format(output, mergeName)
0281 
0282                 ##Create local config per merge step
0283                 local = {}
0284                 local["type"]   = "DMR"
0285                 local["mode"]   = "merge"
0286                 local["isData"] = True
0287                 local["isMC"]   = False
0288 
0289                 ##Deep copy necessary things from global config
0290                 for alignment in config["alignments"]:
0291                     local.setdefault("alignments", {})
0292                     for singleName in config["validations"]["DMR"]["merge"][mergeName]["singles"]:
0293                         if alignment in config["validations"]["DMR"]["single"][singleName]['alignments']:
0294                             local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])        
0295                 local["validation"] = copy.deepcopy(config["validations"]["DMR"][dmrType][avpName])
0296                 local["validation"]["mergeFile"] = "{}/{}/DMR/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}")
0297                 local["validation"]["lumiPerRun"] = lumiPerRun
0298                 local["validation"]["lumiPerIoV"] = lumiPerIoV
0299                 local["validation"]["lumiMC"]     = lumiMC
0300                 local["validation"]["firstFromNext"] = [] 
0301 
0302                 ##Determine list of IOVs in merge step (generally different than total list of IOVs)
0303                 IOVsPerMergeStep = []
0304                 for singleName in config["validations"]["DMR"]["merge"][mergeName]["singles"]:
0305                     for IOV in IOVs[singleName]: 
0306                         if IOV not in IOVsPerMergeStep:
0307                             IOVsPerMergeStep.append(IOV) 
0308                 IOVsPerMergeStep.sort()
0309  
0310                 ##Divide average step job to subjobs to prevent memory issues
0311                 extra_part = 0
0312                 maxfiles = int(config["validations"]["DMR"][dmrType][avpName]['maxfiles'])
0313                 if len(IOVsPerMergeStep)%maxfiles >= 2:
0314                     extra_part = 1
0315                 parts = extra_part+len(IOVsPerMergeStep)//maxfiles
0316 
0317                 subJob = {'name' : [], 'output' : [], 'lumiPerFile' : []}
0318                 for ipart in range(0,parts):
0319                     #Adapt workdir per each subjob
0320                     workDirSub = workDirMerge+"_"+str(ipart)
0321                     outputSub = outputMerge+"_"+str(ipart)  
0322 
0323                     #Define IOV group  
0324                     IOVGroup = []
0325                     lastIndex = 0
0326                     for iIOV,IOV in enumerate(IOVsPerMergeStep):
0327                         if (iIOV//maxfiles == ipart) or (ipart == parts-1 and iIOV//maxfiles > ipart):
0328                             IOVGroup.append(IOV)
0329                             lastIndex = iIOV
0330                     firstFromNext = []
0331                     if lastIndex != len(IOVsPerMergeStep)-1:
0332                         firstFromNext.append(IOVsPerMergeStep[lastIndex+1]) 
0333 
0334                     #Write job info
0335                     _local = copy.deepcopy(local)
0336                     _local["output"] = outputSub
0337                     _local["validation"]["IOV"] = IOVGroup 
0338                     _local["validation"]["firstFromNext"] = firstFromNext
0339                     job = {
0340                         "name": "DMR_{}_{}_{}".format(dmrType, avpName, mergeName+"_"+str(ipart)),
0341                         "dir": workDirSub,
0342                         "exe": "mkLumiAveragedPlots.py",
0343                         "run-mode": "Condor",
0344                         "dependencies": [],
0345                         "config": _local,
0346                     } 
0347                     subJob['output'].append(outputSub)    
0348                     subJob['name'].append("DMR_{}_{}_{}".format(dmrType, avpName, mergeName+"_"+str(ipart)))
0349                     subJob['lumiPerFile'].append(os.path.join(outputSub,"lumiPerFile.csv"))                
0350                     if parts == 1:
0351                         plotJob['inputData'].append(outputSub)  
0352                         plotJob['dependencies'].append(job['name'])
0353 
0354                     #Set average job dependencies from the list of all merge jobs
0355                     for mergeJob in mergeJobs:
0356                         alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:]
0357                         if mergeJobName == mergeName and int(mergeIOV) in IOVGroup:
0358                             job["dependencies"].append(mergeJob["name"]) 
0359                         #if mergeJobName in config["validations"]["DMR"][dmrType][avpName]["merges"]:
0360                         #    job["dependencies"].append(mergeJob["name"])
0361 
0362                     #Add to queue 
0363                     avpJobs.append(job) 
0364 
0365                 ##Add finalization job to merge all subjobs 
0366                 if parts > 1:
0367                     localFinalize = copy.deepcopy(local)
0368                     localFinalize['mode'] = "finalize"
0369                     localFinalize['output'] = outputMerge
0370                     localFinalize["validation"]["IOV"] = []
0371                     localFinalize["validation"]["mergeFile"] = subJob['output'] 
0372                     localFinalize["validation"]["lumiPerRun"] = []
0373                     localFinalize["validation"]["lumiPerIoV"] = subJob['lumiPerFile']
0374                     job = {
0375                     "name": "DMR_{}_{}_{}".format(dmrType, avpName, mergeName+"_finalize"),
0376                     "dir": workDirMerge,
0377                     "exe": "mkLumiAveragedPlots.py",
0378                     "run-mode": "Condor",
0379                     "dependencies": subJob['name'],
0380                     "config": localFinalize,
0381                     }
0382                     avpJobs.append(job)
0383                     plotJob['inputData'].append(outputMerge)
0384                     plotJob['dependencies'].append(job['name']) 
0385 
0386             #Second create one averager job per all MC merge jobs
0387             if len(mergesMC) != 0: 
0388                 ##Adapt workdir per merge step
0389                 workDirMerge = "{}/{}".format(workDir, "MC")
0390                 outputMerge  = "{}/{}".format(output, "MC")
0391 
0392                 ##Create local config for MC average job
0393                 local = {}
0394                 local["type"]   = "DMR"
0395                 local["mode"]   = "merge" 
0396                 local["isData"] = False
0397                 local["isMC"] = True
0398                 local["output"] = outputMerge        
0399 
0400                 ##Deep copy necessary things from global config
0401                 local["validation"] = copy.deepcopy(config["validations"]["DMR"][dmrType][avpName])
0402                 local["validation"]["mergeFile"] = []
0403                 for mergeName in mergesMC:
0404                     for alignment in config["alignments"]:
0405                         local.setdefault("alignments", {})
0406                         for singleName in config["validations"]["DMR"]["merge"][mergeName]["singles"]:
0407                             if alignment in config["validations"]["DMR"]["single"][singleName]['alignments']:
0408                                 local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
0409                     local["validation"]["mergeFile"].append("{}/{}/DMR/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}"))
0410                 local["validation"]["lumiPerRun"] = lumiPerRun
0411                 local["validation"]["lumiPerIoV"] = lumiPerIoV
0412                 local["validation"]["lumiMC"]     = lumiMC 
0413                 local["validation"]["IOV"] = [1]
0414 
0415                 ##Write job info
0416                 job = {
0417                             "name": "DMR_{}_{}_{}".format(dmrType, avpName, mergeName+"_MC"),
0418                             "dir": workDirMerge,
0419                             "exe": "mkLumiAveragedPlots.py",
0420                             "run-mode": "Condor",
0421                             "dependencies": [],
0422                             "config": local,
0423                         }
0424                 plotJob['inputMC'].append(outputMerge)
0425                 plotJob['dependencies'].append(job['name']) 
0426 
0427                 ##Set average job dependencies from the list of all merge jobs
0428                 for mergeJob in mergeJobs:
0429                     alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:]
0430                     if mergeJobName in mergesMC:
0431                         job["dependencies"].append(mergeJob["name"])
0432 
0433                 ##Add to queue 
0434                 avpJobs.append(job) 
0435                   
0436             ##Finally add job to plot averaged distributions
0437             if len(plotJob['inputData'])+len(plotJob['inputMC']) > 0:
0438                 local = {}
0439                 local["type"] = "DMR"
0440                 local["mode"]   = "plot"
0441                 local["isData"] = True if len(plotJob['inputData']) > 0 else False
0442                 local["isMC"] = True if len(plotJob['inputMC']) > 0 else False
0443                 local["output"] = plotJob['output']
0444                 local["plot"] = { "inputData" : plotJob['inputData'], 
0445                                   "inputMC" : plotJob['inputMC'],
0446                                   "alignments" : [],
0447                                   "objects" : [],
0448                                   "labels"  : [],
0449                                   "colors"  : [],
0450                                   "styles"  : [],
0451                                   "useFit"        : True,
0452                                   "useFitError"   : False,
0453                                   "showMean"      : True,
0454                                   "showMeanError" : False,
0455                                   "showRMS"       : False,
0456                                   "showRMSError"  : False}
0457                 ##Copy alignment objects info from global config
0458                 for mergeName in mergesDATA+mergesMC:
0459                     for singleName in config["validations"]["DMR"]["merge"][mergeName]["singles"]:
0460                         for alignment in config["validations"]["DMR"]["single"][singleName]['alignments']:
0461                             if alignment in config['alignments'] and alignment not in local["plot"]["alignments"]:
0462                                 local["plot"]["alignments"].append(alignment)
0463                                 objectName = config["alignments"][alignment]["title"].replace(" ","_")
0464                                 if objectName not in local["plot"]["objects"]: #can happen for MC
0465                                     local["plot"]["objects"].append(objectName)
0466                                     local["plot"]["labels"].append(config["alignments"][alignment]["title"])
0467                                     local["plot"]["colors"].append(config["alignments"][alignment]["color"])
0468                                     local["plot"]["styles"].append(config["alignments"][alignment]["style"])
0469                 ##Overwrite if needed 
0470                 for extraKey in ["objects","labels","colors","styles","useFit","useFitError","showMean","showMeamError","showRMS","showRMSError"]:
0471                     if extraKey in config["validations"]["DMR"][dmrType][avpName].keys():
0472                         local["plot"][extraKey] = config["validations"]["DMR"][dmrType][avpName][extraKey]
0473                 ##Add global plotting options
0474                 if "style" in config.keys():
0475                     if "DMR" in config['style'].keys():
0476                         if dmrType in config['style']['DMR'].keys():
0477                             local["plotGlobal"] = copy.deepcopy(config["style"]['DMR'][dmrType])  
0478                 
0479                 ##Write job info 
0480                 job = {
0481                             "name": "DMR_{}_{}_{}".format(dmrType, avpName, "plot"),
0482                             "dir": plotJob['workdir'],
0483                             "exe": "mkLumiAveragedPlots.py",
0484                             "run-mode": "Condor",
0485                             "dependencies": plotJob['dependencies'],
0486                             "config": local,
0487                         }
0488                 avpJobs.append(job) 
0489 
0490         #Finally extend main job collection
0491         jobs.extend(avpJobs)
0492 
0493     return jobs