Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
import copy
import os
import pprint

def PV(config, validationDir):
    ##List with all jobs
    jobs, singleJobs = [], [] 
    pvType = "single"

    ##Dictionary of lists of all IOVs (can be different per each single job)
    IOVs = {}

    ##Auxilliary dictionary of isData flags per each merged job
    isDataMerged = {}

    ##Start with single PV jobs
    if not pvType in config["validations"]["PV"]: 
        raise Exception("No 'single' key word in config for PV") 

    for singleName in config["validations"]["PV"][pvType]:
        #print("Reading singleName = {}".format(singleName))
        aux_IOV = config["validations"]["PV"][pvType][singleName]["IOV"]
        if not isinstance(aux_IOV, list) and aux_IOV.endswith(".txt"):
            config["validations"]["PV"][pvType][singleName]["IOV"] = []
            with open(aux_IOV, 'r') as IOVfile:
                for line in IOVfile.readlines():
                    if len(line) != 0: config["validations"]["PV"][pvType][singleName]["IOV"].append(int(line))
        for IOV in config["validations"]["PV"][pvType][singleName]["IOV"]:
            ##Save IOV to loop later for merge jobs
            if singleName not in IOVs.keys():
                IOVs[singleName] = []
            if IOV not in IOVs[singleName]:
                IOVs[singleName].append(IOV) 

            for alignment in config["validations"]["PV"][pvType][singleName]["alignments"]:
                ##Work directory for each IOV
                workDir = "{}/PV/{}/{}/{}/{}".format(validationDir, pvType, singleName, alignment, IOV)

                ##Write local config
                local = {}
                local["output"] = "{}/{}/PV/{}/{}/{}/{}".format(config["LFS"], config["name"], pvType, alignment, singleName, IOV)
                local["alignment"] = copy.deepcopy(config["alignments"][alignment])
                local["alignment"]["name"] = alignment
                local["validation"] = copy.deepcopy(config["validations"]["PV"][pvType][singleName])
                local["validation"].pop("alignments")
                local["validation"]["IOV"] = IOV
                if "dataset" in local["validation"]:
                    local["validation"]["dataset"] = local["validation"]["dataset"].format(IOV)
                if "goodlumi" in local["validation"]:
                    local["validation"]["goodlumi"] = local["validation"]["goodlumi"].format(IOV)

                ##Write job info
                job = {
                    "name": "PV_{}_{}_{}_{}".format(pvType, alignment, singleName, IOV),
                    "dir": workDir,
                    "exe": "cmsRun",
                    "cms-config": "{}/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/PV_cfg.py".format(os.environ["CMSSW_BASE"]),
                    "run-mode": "Condor",
                    "dependencies": [],
                    "config": local, 
                }

                #jobs.append(job)
                singleJobs.append(job)

    jobs.extend(singleJobs)

    ##Do merge PV if wished
    if "merge" in config["validations"]["PV"]:
        ##List with merge jobs, will be expanded to jobs after looping
        mergeJobs = []
        pvType = "merge"

        ##Loop over all merge jobs/IOVs which are wished
        for mergeName in config["validations"]["PV"][pvType]:
            ##Search for MC single(s)
            singlesMC = []
            for singleName in config["validations"]["PV"][pvType][mergeName]['singles']:
                if len(IOVs[singleName]) == 1 and int(IOVs[singleName][0]) == 1: singlesMC.append(singleName)
            isMConly = (len(singlesMC) == len(config["validations"]["PV"][pvType][mergeName]['singles']))
            if isMConly:
                isDataMerged[mergeName] = 0
            elif len(singlesMC) == 0:
                isDataMerged[mergeName] = 1
            else:
                isDataMerged[mergeName] = -1 

            ##Loop over singles
            for iname,singleName in enumerate(config["validations"]["PV"][pvType][mergeName]['singles']):
                isMC = (singleName in singlesMC)
                if isMConly and iname > 0: continue #special case for MC only comparison
                elif isMConly: singlesMC.pop(singlesMC.index(singleName))

                for IOV in IOVs[singleName]:
                    if isMC and not isMConly: continue #ignore IOV=1 as it is automatically added to each DATA IOV unless MC only comparison            
                    #print("mergeName = {}".format(mergeName))

                    ##Work directory for each IOV
                    workDir = "{}/PV/{}/{}/{}".format(validationDir, pvType, mergeName, IOV) #Different (DATA) single jobs must contain different set of IOVs

                    ##Write job info
                    local = {}

                    job = {
                        "name": "PV_{}_{}_{}".format(pvType, mergeName, IOV),
                        "dir": workDir,
                        "exe": "PVmerge",
                        "run-mode": "Condor",
                        "dependencies": [],
                        "config": local, 
                    }

                    ##Deep copy necessary things from global config + assure plot order
                    for alignment in config["alignments"]:
                        idxIncrement = 0
                        local.setdefault("alignments", {})
                        if alignment in config["validations"]["PV"]["single"][singleName]["alignments"]: #Cover all DATA validations
                            local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
                            local["alignments"][alignment]['index'] = config["validations"]["PV"]["single"][singleName]["alignments"].index(alignment)
                            local["alignments"][alignment]['isMC'] = False
                        for singleMCname in singlesMC:
                            if alignment in config["validations"]["PV"]["single"][singleMCname]["alignments"]: #Add MC objects
                                local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
                                local["alignments"][alignment]['index']  = len(config["validations"]["PV"]["single"][singleName]["alignments"])
                                local["alignments"][alignment]['index'] += idxIncrement + config["validations"]["PV"]["single"][singleMCname]["alignments"].index(alignment)
                                local["alignments"][alignment]['isMC'] = True
                            idxIncrement += len(config["validations"]["PV"]["single"][singleMCname]["alignments"]) 
                    local["validation"] = copy.deepcopy(config["validations"]["PV"][pvType][mergeName])
                    local["validation"]["IOV"] = IOV
                    if "customrighttitle" in local["validation"].keys():
                        if "IOV" in local["validation"]["customrighttitle"]:
                            local["validation"]["customrighttitle"] = local["validation"]["customrighttitle"].replace("IOV",str(IOV)) 
                    local["output"] = "{}/{}/PV/{}/{}/{}".format(config["LFS"], config["name"], pvType, mergeName, IOV)

                    ##Add global plotting options
                    if "style" in config.keys():
                        if "PV" in config['style'].keys():
                            if pvType in config['style']['PV'].keys():
                                local["style"] = copy.deepcopy(config["style"]["PV"][pvType])
                                if "Rlabel" in local["style"] and "customrighttitle" in local["validation"].keys():
                                    print("WARNING: custom right label is overwritten by global settings")

                    ##Loop over all single jobs
                    for singleJob in jobs:
                        ##Get single job info and append to merge job if requirements fullfilled
                        _alignment, _singleName, _singleIOV = singleJob["name"].split("_")[2:]
                        if _singleName in config["validations"]["PV"][pvType][mergeName]["singles"]:
                            if int(_singleIOV) == IOV or (int(_singleIOV) == 1 and _singleName in singlesMC): #matching DATA job or any MC single job 
                                local["alignments"][_alignment]["file"] = singleJob["config"]["output"]
                                job["dependencies"].append(singleJob["name"])
                            
                    mergeJobs.append(job)

        jobs.extend(mergeJobs)

    if "trends" in config["validations"]["PV"]:

        ##List with merge jobs, will be expanded to jobs after looping
        trendJobs = []
        pvType = "trends"

        for trendName in config["validations"]["PV"][pvType]:
            #print("trendName = {}".format(trendName))
            
            ##Work directory for each IOV
            workDir = "{}/PV/{}/{}".format(validationDir, pvType, trendName)

            ##Write general job info
            local = {}

            job = {
                "name": "PV_{}_{}".format(pvType, trendName),
                "dir": workDir,
                "exe": "PVtrends",
                "run-mode": "Condor",
                "dependencies": [],
                "config": local,
            }

            ##Loop over singles
            if 'merges' in config["validations"]["PV"][pvType][trendName].keys()\
               or 'singles' not in config["validations"]["PV"][pvType][trendName].keys():
                raise Exception("Specify list of \'singles\' to run PV trends.")
                #TODO: possible also to run over merges for consistency with DMR jobs
            trendIOVs = [] #TODO: allow different IOV list for each single job? 
            alignmentList = []
            for iname, singleName in enumerate(config["validations"]["PV"][pvType][trendName]["singles"]):
                isMC = (len(IOVs[singleName]) == 1 and int(IOVs[singleName][0]) == 1)
                if isMC:
                    raise Exception("Trend jobs are not implemented for treating MC.")  
                if iname == 0: 
                    trendIOVs = IOVs[singleName] 
                else:
                    for IOV in IOVs[singleName]:
                        if IOV not in trendIOVs or (len(IOVs[singleName]) != len(trendIOVs)):
                            raise Exception("List of IOVs must be the same for each single job.")
                for alignment in config["validations"]["PV"]["single"][singleName]["alignments"]:        
                    if alignment not in alignmentList and alignment in config["alignments"]:
                        local.setdefault("alignments", {})
                        alignmentList.append(alignment)
                        local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment])
                        local["alignments"][alignment]["file"] = "{}/{}/PV/{}/{}/{}/{}".format(config["LFS"], config["name"], "single", alignment, singleName, "{}")
            trendIOVs.sort()
            local["validation"] = copy.deepcopy(config["validations"]["PV"][pvType][trendName])
            local["validation"]["IOV"] = trendIOVs
            if "label" in config["validations"]["PV"][pvType][trendName]:
                local["validation"]["label"] = copy.deepcopy(config["validations"]["PV"][pvType][trendName]["label"])
            local["output"] = "{}/{}/PV/{}/{}/".format(config["LFS"], config["name"], pvType, trendName)
            if "style" in config.keys() and "trends" in config["style"].keys():
                local["style"] = copy.deepcopy(config["style"])
                if "PV" in local["style"].keys(): local["style"].pop("PV")
                if "CMSlabel" in config["style"]["trends"].keys(): local["style"]["CMSlabel"] = config["style"]["trends"]["CMSlabel"]
                if "Rlabel" in config["style"]["trends"].keys():
                    local["style"]["trends"].pop("Rlabel")
                    local["style"]["trends"]["TitleCanvas"] = config["style"]["trends"]["Rlabel"]
            else:
                raise Exception("You want to create 'trends' jobs, but there are no 'lines' section in the config for pixel updates!")

            #Loop over all single jobs
            for singleJob in singleJobs:
                #Get single job info and append to job if requirements fullfilled
                alignment, singleName, singleIOV = singleJob["name"].split("_")[2:]
                
                if singleName in config["validations"]["PV"][pvType][trendName]["singles"]\
                  and int(singleIOV) in trendIOVs:
                    job["dependencies"].append(singleJob["name"])

            trendJobs.append(job)

        jobs.extend(trendJobs)

    return jobs