From 76f11ab809e3eed0a51472227d2f0769a5d3c773 Mon Sep 17 00:00:00 2001 From: Federico Vazzoler Date: Fri, 5 May 2023 14:39:23 +0200 Subject: [PATCH 1/6] First implementation of Muon Track Splitting validation in the new all-in-one tool: - code-checks & code-format - fix deleteCanvas and code-format --- Alignment/OfflineValidation/README_MTS.md | 47 ++ .../OfflineValidation/macros/trackSplitPlot.C | 4 +- .../python/TkAlAllInOneTool/MTS.py | 499 ++++++++++++++++++ .../python/TkAlAllInOneTool/MTS_cfg.py | 203 +++++++ .../TkAlAllInOneTool/defaultInputFiles_cff.py | 2 + .../scripts/validateAlignments.py | 5 +- 6 files changed, 755 insertions(+), 5 deletions(-) create mode 100644 Alignment/OfflineValidation/README_MTS.md create mode 100644 Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py create mode 100644 Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS_cfg.py diff --git a/Alignment/OfflineValidation/README_MTS.md b/Alignment/OfflineValidation/README_MTS.md new file mode 100644 index 0000000000000..e818168e24d78 --- /dev/null +++ b/Alignment/OfflineValidation/README_MTS.md @@ -0,0 +1,47 @@ +## PV validation + +### General info + +``` +validations: + MTS: + : + : + +``` + +MTS validation runs in 1 possible type of steps: + - single (validation analysis by MTS_cfg.py) +Step name is arbitrary string which will be used as a reference for consequent steps. +Merge and trend jobs are not yet implemented. + +### Single PV jobs + +Single jobs can be specified per run (IoV as well). In case of MC, IoV is specified to arbitrary 1. + +**Parameters below to be updated** +Variable | Default value | Explanation/Options +-------- | ------------- | -------------------- +IOV | None | List of IOVs/runs defined by integer value. IOV 1 is reserved for MC. +Alignments | None | List of alignments. Will create separate directory for each. +dataset | See defaultInputFiles_cff.py | Path to txt file containing list of datasets to be used. If file is missing at EOS or is corrupted - job will eventually fail (most common issue). +goodlumi | cms.untracked.VLuminosityBlockRange() | Path to json file containing lumi information about selected IoV - must contain list of runs under particular IoV with lumiblock info. Format: `IOV_Vali_{}.json` +maxevents | 1 | Maximum number of events before cmsRun terminates. +maxtracks | 1 | Maximum number of tracks per event before next event is processed. +trackcollection | "generalTracks" | Track collection to be specified here, e.g. "ALCARECOTkAlMuonIsolated" or "ALCARECOTkAlMinBias" ... +tthrbuilder | "WithAngleAndTemplate" | Specify TTRH Builder +usePixelQualityFlag | True | Use pixel quality flag? +cosmicsZeroTesla | False | Is this validation for cosmics with zero magnetic field? +vertexcollection | "offlinePrimaryVertices" | Specify vertex collection to be used. +isda | True | Use DA algorithm (True) or GAP algorithm (False) +ismc | True | Is validation for MC (True) or Data (False)? +runboundary | 1 | Specify starting run number (can be also list of starting numbers in multirun approach). +runControl | False | Enable run control +ptCut | 3. | Probe tracks with pT > 3GeV +etaCut | 2.5 | Probe tracks in abs(eta) < 2.5 region +minPt | 1. | Define minimal track pT +maxPt | 30. | Define maximum track pT +doBPix | True | Do not run validation for BPix if needed +doFPix | True | Do not run validation for FPix if needed +forceBeamSpot | False | Force beam spot +numberOfBins | 48 | Define histogram granularity diff --git a/Alignment/OfflineValidation/macros/trackSplitPlot.C b/Alignment/OfflineValidation/macros/trackSplitPlot.C index 9b1d5c958a439..1e1adf6c65988 100644 --- a/Alignment/OfflineValidation/macros/trackSplitPlot.C +++ b/Alignment/OfflineValidation/macros/trackSplitPlot.C @@ -167,6 +167,7 @@ TCanvas *trackSplitPlot(Int_t nFiles, Double_t x = 0, y = 0, rel = 1, sigma1 = 1; Double_t sigma2 = 1; //if !pull, we want to divide by sqrt(2) because we want the error from 1 track Double_t sigmaorg = 0; + Int_t xint = 0, xint2 = 0; Int_t runNumber = 0; double pt1 = 0, maxpt1 = 0; @@ -644,9 +645,6 @@ void deleteCanvas(TObject *canvas) { return; } TCanvas *c1 = (TCanvas *)canvas; - TList *list = c1->GetListOfPrimitives(); - list->SetOwner(true); - list->Clear(); delete c1; } diff --git a/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py b/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py new file mode 100644 index 0000000000000..47fb4a959bee3 --- /dev/null +++ b/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py @@ -0,0 +1,499 @@ +import copy +import os + +def MTS(config, validationDir): + ##List with all jobs + jobs = [] + mtsType = "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 MTS jobs + if not mtsType in config["validations"]["MTS"]: + raise Exception("No 'single' key word in config for MTS") + + for singleName in config["validations"]["MTS"][mtsType]: + aux_IOV = config["validations"]["MTS"][mtsType][singleName]["IOV"] + if not isinstance(aux_IOV, list) and aux_IOV.endswith(".txt"): + config["validations"]["MTS"][mtsType][singleName]["IOV"] = [] + with open(aux_IOV, 'r') as IOVfile: + for line in IOVfile.readlines(): + if len(line) != 0: config["validations"]["MTS"][mtsType][singleName]["IOV"].append(int(line)) + for IOV in config["validations"]["MTS"][mtsType][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"]["MTS"][mtsType][singleName]["alignments"]: + ##Work directory for each IOV + workDir = "{}/MTS/{}/{}/{}/{}".format(validationDir, mtsType, singleName, alignment, IOV) + + ##Write local config + local = {} + local["output"] = "{}/{}/MTS/{}/{}/{}/{}".format(config["LFS"], config["name"], mtsType, alignment, singleName, IOV) + local["alignment"] = copy.deepcopy(config["alignments"][alignment]) + local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][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": "MTS_{}_{}_{}_{}".format(mtsType, alignment, singleName, IOV), + "dir": workDir, + "exe": "cmsRun", + "cms-config": "{}/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS_cfg.py".format(os.environ["CMSSW_BASE"]), + "run-mode": "Condor", + "dependencies": [], + "config": local, + } + + jobs.append(job) + +# FIXME%START: uncomment when the following modes will be available + if "merge" in config["validations"]["MTS"] or \ + "trends" in config["validations"]["MTS"] or \ + "averaged" in config["validations"]["MTS"]: + print("WARNING: 'merge', 'trends' and 'averaged' not yet supported. Will do nothing for them.") +# ##Do merge MTS if wished +# if "merge" in config["validations"]["MTS"]: +# ##List with merge jobs, will be expanded to jobs after looping +# mergeJobs = [] +# mtsType = "merge" +# +# ##Loop over all merge jobs +# for mergeName in config["validations"]["MTS"][mtsType]: +# ##Search for MC single(s) +# singlesMC = [] +# for singleName in config["validations"]["MTS"][mtsType][mergeName]['singles']: +# if len(IOVs[singleName]) == 1 and int(IOVs[singleName][0]) == 1: singlesMC.append(singleName) +# isMConly = (len(singlesMC) == len(config["validations"]["MTS"][mtsType][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"]["MTS"][mtsType][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 +# +# ##Work directory for each IOV +# workDir = "{}/MTS/{}/{}/{}".format(validationDir, mtsType, mergeName, IOV) #Different (DATA) single jobs must contain different set of IOVs +# +# ##Write job info +# local = {} +# +# job = { +# "name": "MTS_{}_{}_{}".format(mtsType, mergeName, IOV), +# "dir": workDir, +# "exe": "MTSmerge", +# "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"]["MTS"]["single"][singleName]["alignments"]: #Cover all DATA validations +# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) +# local["alignments"][alignment]['index'] = config["validations"]["MTS"]["single"][singleName]["alignments"].index(alignment) +# for singleMCname in singlesMC: +# if alignment in config["validations"]["MTS"]["single"][singleMCname]["alignments"]: #Add MC objects +# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) +# local["alignments"][alignment]['index'] = len(config["validations"]["MTS"]["single"][singleName]["alignments"]) +# local["alignments"][alignment]['index'] += idxIncrement + config["validations"]["MTS"]["single"][singleMCname]["alignments"].index(alignment) +# idxIncrement += len(config["validations"]["MTS"]["single"][singleMCname]["alignments"]) +# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][mergeName]) +# local["validation"]["IOV"] = IOV #is it really needed here? +# if "customrighttitle" in local["validation"].keys(): +# if "IOV" in local["validation"]["customrighttitle"]: +# local["validation"]["customrighttitle"] = local["validation"]["customrighttitle"].replace("IOV",str(IOV)) +# local["output"] = "{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], mtsType, mergeName, IOV) +# +# ##Add global plotting options +# if "style" in config.keys(): +# if "MTS" in config['style'].keys(): +# if mtsType in config['style']['MTS'].keys(): +# local["style"] = copy.deepcopy(config["style"]["MTS"][mtsType]) +# 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"]["MTS"][mtsType][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"]) +# +# ##Append to merge jobs +# mergeJobs.append(job) +# +# ##Append to all jobs +# jobs.extend(mergeJobs) +# +# if "trends" in config["validations"]["MTS"]: +# +# ##List with merge jobs, will be expanded to jobs after looping +# trendJobs = [] +# mtsType = "trends" +# +# for trendName in config["validations"]["MTS"][mtsType]: +# #print("trendName = {}".format(trendName)) +# ##Work directory for each IOV +# workDir = "{}/MTS/{}/{}".format(validationDir, mtsType, trendName) +# +# ##Write general job info +# local = {} +# job = { +# "name": "MTS_{}_{}".format(mtsType, trendName), +# "dir": workDir, +# "exe": "MTStrends", +# "run-mode": "Condor", +# "dependencies": [], +# "config": local, +# } +# +# ###Loop over merge steps (merge step can contain only DATA) +# mergesDATA = [] +# for mergeName in config["validations"]["MTS"][mtsType][trendName]["merges"]: +# ##Validate merge step +# if isDataMerged[mergeName] < 0: +# raise Exception("Trend jobs cannot process merge jobs containing both DATA and MC objects.") +# elif isDataMerged[mergeName] == 1: +# mergesDATA.append(mergeName) +# else: +# if "doUnitTest" in config["validations"]["MTS"][mtsType][trendName].keys() and config["validations"]["MTS"][mtsType][trendName]["doUnitTest"]: +# local.setdefault("alignments", {}) +# continue +# else: +# raise Exception("Trend jobs are not implemented for treating MC.") +# +# ###Loop over DATA singles included in merge steps +# trendIOVs = [] +# _mergeFiles = [] +# for mergeName in mergesDATA: +# for iname,singleName in enumerate(config["validations"]["MTS"]['merge'][mergeName]['singles']): +# trendIOVs += [IOV for IOV in IOVs[singleName]] +# ##Deep copy necessary things from global config + ensure plot order +# for alignment in config["alignments"]: +# local.setdefault("alignments", {}) +# if alignment in config["validations"]["MTS"]["single"][singleName]["alignments"]: #Cover all DATA validations +# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) +# local["alignments"][alignment]['index'] = config["validations"]["MTS"]["single"][singleName]["alignments"].index(alignment) +# _mergeFiles.append("{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}")) +# trendIOVs.sort() +# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][trendName]) +# if len(_mergeFiles) == 1: +# local["validation"]["mergeFile"] = _mergeFiles[0] +# else: +# local["validation"]["mergeFile"] = _mergeFiles #FIXME for multiple merge files in backend +# local["validation"]["IOV"] = trendIOVs +# local["output"] = "{}/{}/MTS/{}/{}/".format(config["LFS"], config["name"], mtsType, trendName) +# if "style" in config.keys() and "trends" in config["style"].keys(): +# local["style"] = copy.deepcopy(config["style"]) +# if "MTS" in local["style"].keys(): local["style"].pop("MTS") +# 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 merge jobs +# for mergeName in mergesDATA: +# for mergeJob in mergeJobs: +# alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:] +# if mergeJobName == mergeName and int(mergeIOV) in trendIOVs: +# job["dependencies"].append(mergeJob["name"]) +# +# trendJobs.append(job) +# +# jobs.extend(trendJobs) +# +# if "averaged" in config["validations"]["MTS"]: +# +# ####Finally, list of jobs is expanded for luminosity-averaged plot (avp) job +# avpJobs = [] +# mtsType = "averaged" +# for avpName in config["validations"]["MTS"][mtsType]: +# ###Main workdir for each combination of displayed lumi-averaged validation objects to be plotted +# workDir = "{}/MTS/{}/{}".format(validationDir, mtsType, avpName) +# output = "{}/{}/MTS/{}/{}".format(config["LFS"], config["name"], mtsType, avpName) +# +# ###Loop over merge steps (one merge step can contain only DATA or only MC singles but not mix) +# mergesDATA = [] +# mergesMC = [] +# for mergeName in config["validations"]["MTS"][mtsType][avpName]["merges"]: +# ##Validate merge step +# if isDataMerged[mergeName] < 0: +# raise Exception("Average jobs cannot process merge jobs containing both DATA and MC objects.") +# elif isDataMerged[mergeName] == 1: +# mergesDATA.append(mergeName) +# else: +# mergesMC.append(mergeName) +# +# lumiPerRun = [] +# lumiPerIoV = [] +# lumiMC = [] +# if len(mergesDATA) > 0: +# if "lumiPerRun" in config["validations"]["MTS"][mtsType][avpName].keys(): +# for lumifile in config["validations"]["MTS"][mtsType][avpName]['lumiPerRun']: +# if lumifile.split(".")[-1] in ["txt","csv"]: +# lumiPerRun.append(lumifile) +# if "lumiPerIoV" in config["validations"]["MTS"][mtsType][avpName].keys(): +# for lumifile in config["validations"]["MTS"][mtsType][avpName]['lumiPerIoV']: +# if lumifile.split(".")[-1] in ["txt","csv"]: +# lumiPerIoV.append(lumifile) +# if len(lumiPerRun) == 0 and len(lumiPerIoV) == 0: +# raise Exception("No lumi per run/IoV file found or not specified in .csv/.txt format.") +# if len(mergesMC) > 0: +# if 'lumiMC' in config["validations"]["MTS"][mtsType][avpName].keys(): +# lumiMC = config["validations"]["MTS"][mtsType][avpName]['lumiMC'] +# +# ###Store information about plotting job in this dictionary +# plotJob = {} +# plotJob['workdir'] = "{}/{}".format(workDir,"plots") +# plotJob['output'] = "{}/{}".format(output,"plots") +# plotJob['inputData'] = [] +# plotJob['inputMC'] = [] +# plotJob['dependencies'] = [] +# +# ###First loop over DATA +# for mergeName in mergesDATA: +# ##Adapt workdir per merge step +# workDirMerge = "{}/{}".format(workDir, mergeName) +# outputMerge = "{}/{}".format(output, mergeName) +# +# ##Create local config per merge step +# local = {} +# local["type"] = "MTS" +# local["mode"] = "merge" +# local["isData"] = True +# local["isMC"] = False +# +# ##Deep copy necessary things from global config +# for alignment in config["alignments"]: +# local.setdefault("alignments", {}) +# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: +# if alignment in config["validations"]["MTS"]["single"][singleName]['alignments']: +# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) +# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][avpName]) +# local["validation"]["mergeFile"] = "{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}") +# local["validation"]["lumiPerRun"] = lumiPerRun +# local["validation"]["lumiPerIoV"] = lumiPerIoV +# local["validation"]["lumiMC"] = lumiMC +# local["validation"]["firstFromNext"] = [] +# +# ##Determine list of IOVs in merge step (generally different than total list of IOVs) +# IOVsPerMergeStep = [] +# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: +# for IOV in IOVs[singleName]: +# if IOV not in IOVsPerMergeStep: +# IOVsPerMergeStep.append(IOV) +# IOVsPerMergeStep.sort() +# +# ##Divide average step job to subjobs to prevent memory issues +# extra_part = 0 +# maxfiles = int(config["validations"]["MTS"][mtsType][avpName]['maxfiles']) +# if len(IOVsPerMergeStep)%maxfiles >= 2: +# extra_part = 1 +# parts = extra_part+len(IOVsPerMergeStep)//maxfiles +# +# subJob = {'name' : [], 'output' : [], 'lumiPerFile' : []} +# for ipart in range(0,parts): +# #Adapt workdir per each subjob +# workDirSub = workDirMerge+"_"+str(ipart) +# outputSub = outputMerge+"_"+str(ipart) +# +# #Define IOV group +# IOVGroup = [] +# lastIndex = 0 +# for iIOV,IOV in enumerate(IOVsPerMergeStep): +# if (iIOV//maxfiles == ipart) or (ipart == parts-1 and iIOV//maxfiles > ipart): +# IOVGroup.append(IOV) +# lastIndex = iIOV +# firstFromNext = [] +# if lastIndex != len(IOVsPerMergeStep)-1: +# firstFromNext.append(IOVsPerMergeStep[lastIndex+1]) +# +# #Write job info +# _local = copy.deepcopy(local) +# _local["output"] = outputSub +# _local["validation"]["IOV"] = IOVGroup +# _local["validation"]["firstFromNext"] = firstFromNext +# job = { +# "name": "MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_"+str(ipart)), +# "dir": workDirSub, +# "exe": "mkLumiAveragedPlots.py", +# "run-mode": "Condor", +# "dependencies": [], +# "config": _local, +# } +# subJob['output'].append(outputSub) +# subJob['name'].append("MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_"+str(ipart))) +# subJob['lumiPerFile'].append(os.path.join(outputSub,"lumiPerFile.csv")) +# if parts == 1: +# plotJob['inputData'].append(outputSub) +# plotJob['dependencies'].append(job['name']) +# +# #Set average job dependencies from the list of all merge jobs +# for mergeJob in mergeJobs: +# alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:] +# if mergeJobName == mergeName and int(mergeIOV) in IOVGroup: +# job["dependencies"].append(mergeJob["name"]) +# #if mergeJobName in config["validations"]["MTS"][mtsType][avpName]["merges"]: +# # job["dependencies"].append(mergeJob["name"]) +# +# #Add to queue +# avpJobs.append(job) +# +# ##Add finalization job to merge all subjobs +# if parts > 1: +# localFinalize = copy.deepcopy(local) +# localFinalize['mode'] = "finalize" +# localFinalize['output'] = outputMerge +# localFinalize["validation"]["IOV"] = [] +# localFinalize["validation"]["mergeFile"] = subJob['output'] +# localFinalize["validation"]["lumiPerRun"] = [] +# localFinalize["validation"]["lumiPerIoV"] = subJob['lumiPerFile'] +# job = { +# "name": "MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_finalize"), +# "dir": workDirMerge, +# "exe": "mkLumiAveragedPlots.py", +# "run-mode": "Condor", +# "dependencies": subJob['name'], +# "config": localFinalize, +# } +# avpJobs.append(job) +# plotJob['inputData'].append(outputMerge) +# plotJob['dependencies'].append(job['name']) +# +# #Second create one averager job per all MC merge jobs +# if len(mergesMC) != 0: +# ##Adapt workdir per merge step +# workDirMerge = "{}/{}".format(workDir, "MC") +# outputMerge = "{}/{}".format(output, "MC") +# +# ##Create local config for MC average job +# local = {} +# local["type"] = "MTS" +# local["mode"] = "merge" +# local["isData"] = False +# local["isMC"] = True +# local["output"] = outputMerge +# +# ##Deep copy necessary things from global config +# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][avpName]) +# local["validation"]["mergeFile"] = [] +# for mergeName in mergesMC: +# for alignment in config["alignments"]: +# local.setdefault("alignments", {}) +# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: +# if alignment in config["validations"]["MTS"]["single"][singleName]['alignments']: +# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) +# local["validation"]["mergeFile"].append("{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}")) +# local["validation"]["lumiPerRun"] = lumiPerRun +# local["validation"]["lumiPerIoV"] = lumiPerIoV +# local["validation"]["lumiMC"] = lumiMC +# local["validation"]["IOV"] = [1] +# +# ##Write job info +# job = { +# "name": "MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_MC"), +# "dir": workDirMerge, +# "exe": "mkLumiAveragedPlots.py", +# "run-mode": "Condor", +# "dependencies": [], +# "config": local, +# } +# plotJob['inputMC'].append(outputMerge) +# plotJob['dependencies'].append(job['name']) +# +# ##Set average job dependencies from the list of all merge jobs +# for mergeJob in mergeJobs: +# alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:] +# if mergeJobName in mergesMC: +# job["dependencies"].append(mergeJob["name"]) +# +# ##Add to queue +# avpJobs.append(job) +# +# ##Finally add job to plot averaged distributions +# if len(plotJob['inputData'])+len(plotJob['inputMC']) > 0: +# local = {} +# local["type"] = "MTS" +# local["mode"] = "plot" +# local["isData"] = True if len(plotJob['inputData']) > 0 else False +# local["isMC"] = True if len(plotJob['inputMC']) > 0 else False +# local["output"] = plotJob['output'] +# local["plot"] = { "inputData" : plotJob['inputData'], +# "inputMC" : plotJob['inputMC'], +# "alignments" : [], +# "objects" : [], +# "labels" : [], +# "colors" : [], +# "styles" : [], +# "useFit" : True, +# "useFitError" : False, +# "showMean" : True, +# "showMeanError" : False, +# "showRMS" : False, +# "showRMSError" : False} +# ##Copy alignment objects info from global config +# for mergeName in mergesDATA+mergesMC: +# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: +# for alignment in config["validations"]["MTS"]["single"][singleName]['alignments']: +# if alignment in config['alignments'] and alignment not in local["plot"]["alignments"]: +# local["plot"]["alignments"].append(alignment) +# objectName = config["alignments"][alignment]["title"].replace(" ","_") +# if objectName not in local["plot"]["objects"]: #can happen for MC +# local["plot"]["objects"].append(objectName) +# local["plot"]["labels"].append(config["alignments"][alignment]["title"]) +# local["plot"]["colors"].append(config["alignments"][alignment]["color"]) +# local["plot"]["styles"].append(config["alignments"][alignment]["style"]) +# ##Overwrite if needed +# for extraKey in ["objects","labels","colors","styles","useFit","useFitError","showMean","showMeamError","showRMS","showRMSError"]: +# if extraKey in config["validations"]["MTS"][mtsType][avpName].keys(): +# local["plot"][extraKey] = config["validations"]["MTS"][mtsType][avpName][extraKey] +# ##Add global plotting options +# if "style" in config.keys(): +# if "MTS" in config['style'].keys(): +# if mtsType in config['style']['MTS'].keys(): +# local["plotGlobal"] = copy.deepcopy(config["style"]['MTS'][mtsType]) +# +# ##Write job info +# job = { +# "name": "MTS_{}_{}_{}".format(mtsType, avpName, "plot"), +# "dir": plotJob['workdir'], +# "exe": "mkLumiAveragedPlots.py", +# "run-mode": "Condor", +# "dependencies": plotJob['dependencies'], +# "config": local, +# } +# avpJobs.append(job) +# +# #Finally extend main job collection +# jobs.extend(avpJobs) +# +# FIXME%END + return jobs diff --git a/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS_cfg.py b/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS_cfg.py new file mode 100644 index 0000000000000..f5aaedc8414fa --- /dev/null +++ b/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS_cfg.py @@ -0,0 +1,203 @@ +import json +import yaml +import os +import FWCore.ParameterSet.Config as cms +import FWCore.PythonUtilities.LumiList as LumiList +from Alignment.OfflineValidation.TkAlAllInOneTool.defaultInputFiles_cff import filesDefaultData_Cosmics_string +from FWCore.ParameterSet.VarParsing import VarParsing +from Alignment.OfflineValidation.TkAlAllInOneTool.utils import _byteify +import pdb + +################################################################### +# Define process +################################################################### +process = cms.Process("splitter") + +################################################################### +# Argument parsing +################################################################### +options = VarParsing() +options.register("config", "", VarParsing.multiplicity.singleton, VarParsing.varType.string , "AllInOne config") +options.parseArguments() + +################################################################### +# Read in AllInOne config in JSON format +################################################################### +if options.config == "": + config = {"validation": {}, + "alignment": {}} +else: + with open(options.config, "r") as configFile: + if options.config.endswith(".json"): + config = json.load(configFile) + elif options.config.endswith(".yaml"): + config = yaml.safe_load(configFile) + +################################################################### +# Read filenames from given TXT file and define input source +################################################################### +readFiles = [] + +if "dataset" in config["validation"]: + with open(config["validation"]["dataset"], "r") as datafiles: + for fileName in datafiles.readlines(): + readFiles.append(fileName.replace("\n", "")) + + process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring(readFiles), + skipEvents = cms.untracked.uint32(0) + ) +else: + print(">>>>>>>>>> MTS_cfg.py: msg%-i: dataset not specified! Loading default file -> filesDefaultData_Cosmics_string!") + process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring(filesDefaultData_Cosmics_string), + skipEvents = cms.untracked.uint32(0) + ) + +################################################################### +# Get good lumi section and load data or handle MC +################################################################### +if "goodlumi" in config["validation"]: + if os.path.isfile(config["validation"]["goodlumi"]): + goodLumiSecs = cms.untracked.VLuminosityBlockRange(LumiList.LumiList(filename = config["validation"]["goodlumi"]).getCMSSWString().split(',')) + else: + print("Does not exist: {}. Continue without good lumi section file.") + goodLumiSecs = cms.untracked.VLuminosityBlockRange() + +else: + goodLumiSecs = cms.untracked.VLuminosityBlockRange() + +################################################################### +# Runs and events +################################################################### +runboundary = config["validation"].get("runboundary", 1) +isMultipleRuns=False +if(isinstance(runboundary, (list, tuple))): + isMultipleRuns=True + print("Multiple Runs are selected") +if(isMultipleRuns): + process.source.firstRun = cms.untracked.uint32(runboundary[0]) +else: + process.source.firstRun = cms.untracked.uint32(runboundary) + +################################################################### +# Default set to 1 for unit tests +################################################################### +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(config["validation"].get("maxevents", 1))) + +################################################################### +# Bookeeping +################################################################### +process.options = cms.untracked.PSet( + wantSummary = cms.untracked.bool(False), + Rethrow = cms.untracked.vstring("ProductNotFound"), # make this exception fatal + fileMode = cms.untracked.string('NOMERGE'), # no ordering needed, but calls endRun/beginRun etc. at file boundaries +) + +################################################################### +# Messages +################################################################### +process.load("FWCore.MessageLogger.MessageLogger_cfi") +process.MessageLogger.cerr.FwkReport.reportEvery = 1000 +process.MessageLogger.cout.enableStatistics = cms.untracked.bool(True) + +################################################################### +# Basic modules +################################################################### +process.load("RecoVertex.BeamSpotProducer.BeamSpot_cff") +process.load("Configuration.Geometry.GeometryDB_cff") +process.load('Configuration.StandardSequences.Services_cff') +process.load("Configuration.StandardSequences.MagneticField_cff") + +#################################################################### +# Load and Configure Track refitter +#################################################################### +import Alignment.CommonAlignment.tools.trackselectionRefitting as trackselRefit +process.seqTrackselRefit = trackselRefit.getSequence( + process, + config["validation"].get("trackcollection", "ALCARECOTkAlCosmicsCTF0T"), + isPVValidation = False, + TTRHBuilder = config["validation"].get("tthrbuilder", "WithAngleAndTemplate"), + usePixelQualityFlag=config["validation"].get("usePixelQualityFlag", True), + openMassWindow = False, + cosmicsDecoMode = True, + cosmicsZeroTesla=config["validation"].get("cosmicsZeroTesla", False), + momentumConstraint = None, + cosmicTrackSplitting = True, + use_d0cut = False +) + +#################################################################### +# Global tag +#################################################################### +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, config["alignment"].get("globaltag", "124X_dataRun3_Prompt_v10")) + +#################################################################### +# Load conditions if wished +#################################################################### +if "conditions" in config["alignment"]: + from CalibTracker.Configuration.Common.PoolDBESSource_cfi import poolDBESSource + + for condition in config["alignment"]["conditions"]: + setattr( + process, + "conditionsIn{}".format(condition), + poolDBESSource.clone( + # FIXME%START + connect = cms.string("sqlite_file:" + str(config["alignment"]["conditions"][condition]["connect"]) if "alignments_MP.db" in str(config["alignment"]["conditions"][condition]["connect"]) else str(config["alignment"]["conditions"][condition]["connect"])), + #FIXME%END + toGet = cms.VPSet( + cms.PSet( + record = cms.string(str(condition)), + tag = cms.string(str(config["alignment"]["conditions"][condition]["tag"])) + ) + ) + ) + ) + + setattr( + process, + "prefer_conditionsIn{}".format(condition), + cms.ESPrefer("PoolDBESSource", "conditionsIn{}".format(condition)) + ) + +#################################################################### +# Configure the Analyzer module +#################################################################### + +process.FittingSmootherRKP5.EstimateCut = -1 +process.AlignmentTrackSelector.minHitsPerSubDet.inPIXEL = 2 +# Use compressions settings of TFile +# see https://root.cern.ch/root/html534/TFile.html#TFile:SetCompressionSet tings +# settings = 100 * algorithm + level +# level is from 1 (small) to 9 (large compression) +# algo: 1 (ZLIB), 2 (LMZA) +# see more about compression & performance: https://root.cern.ch/root/html534/guides/users-guide/InputOutput.html#compression-and-performance +compressionSettings = 207 +process.cosmicValidation = cms.EDAnalyzer( + "CosmicSplitterValidation", + compressionSettings = cms.untracked.int32(compressionSettings), + ifSplitMuons = cms.bool(False), + checkIfGolden = cms.bool(False), + splitTracks = cms.InputTag("FinalTrackRefitter","","splitter"), + splitGlobalMuons = cms.InputTag("muons","","splitter"), + originalTracks = cms.InputTag("FirstTrackRefitter","","splitter"), + originalGlobalMuons = cms.InputTag("muons","","Rec") +) + +#################################################################### +# Output file +#################################################################### +process.TFileService = cms.Service("TFileService", + fileName = cms.string("{}/MTSValidation_{}_{}.root".format(config.get("output", os.getcwd()), config["alignment"].get("name", ""), config["validation"].get("IOV", 1.))), + closeFileFast = cms.untracked.bool(True), + ) + +#################################################################### +# Path +#################################################################### +process.p = cms.Path(process.seqTrackselRefit*process.cosmicValidation) + +print("Done") diff --git a/Alignment/OfflineValidation/python/TkAlAllInOneTool/defaultInputFiles_cff.py b/Alignment/OfflineValidation/python/TkAlAllInOneTool/defaultInputFiles_cff.py index d0bc9b7de5e5b..498441f5ac464 100644 --- a/Alignment/OfflineValidation/python/TkAlAllInOneTool/defaultInputFiles_cff.py +++ b/Alignment/OfflineValidation/python/TkAlAllInOneTool/defaultInputFiles_cff.py @@ -56,3 +56,5 @@ filesDefaultData_MinBias2018B = cms.untracked.vstring( '/store/express/Run2018B/StreamExpress/ALCARECO/TkAlMinBias-Express-v1/000/317/212/00000/00F0EFA7-8D64-E811-A594-FA163EFC96CC.root' ) + +filesDefaultData_Cosmics_string = "/store/data/Run2022G/Cosmics/ALCARECO/TkAlCosmics0T-PromptReco-v1/000/362/440/00000/47f31eaa-1c00-4f39-902b-a09fa19c27f2.root" diff --git a/Alignment/OfflineValidation/scripts/validateAlignments.py b/Alignment/OfflineValidation/scripts/validateAlignments.py index 6d8e7b9e0a26a..64cb7f455d3f0 100755 --- a/Alignment/OfflineValidation/scripts/validateAlignments.py +++ b/Alignment/OfflineValidation/scripts/validateAlignments.py @@ -19,6 +19,7 @@ import Alignment.OfflineValidation.TkAlAllInOneTool.SplitV as SplitV import Alignment.OfflineValidation.TkAlAllInOneTool.JetHT as JetHT import Alignment.OfflineValidation.TkAlAllInOneTool.DiMuonV as DiMuonV +import Alignment.OfflineValidation.TkAlAllInOneTool.MTS as MTS ############################################## def parser(): @@ -263,10 +264,10 @@ def main(): elif validation == "JetHT": jobs.extend(JetHT.JetHT(config, validationDir)) - elif validation == "DiMuonV": jobs.extend(DiMuonV.DiMuonV(config, validationDir)) - + elif validation == "MTS": + jobs.extend(MTS.MTS(config, validationDir)) else: raise Exception("Unknown validation method: {}".format(validation)) From f84625c28ddf06579114c6134979a7c6a577967a Mon Sep 17 00:00:00 2001 From: mmusich Date: Mon, 8 Jan 2024 17:42:56 +0100 Subject: [PATCH 2/6] implement merge step for MTS validation --- Alignment/OfflineValidation/bin/BuildFile.xml | 1 + Alignment/OfflineValidation/bin/MTSmerge.cc | 87 +++ .../OfflineValidation/macros/trackSplitPlot.C | 13 +- .../OfflineValidation/macros/trackSplitPlot.h | 14 +- .../python/TkAlAllInOneTool/MTS.py | 505 +++--------------- 5 files changed, 167 insertions(+), 453 deletions(-) create mode 100644 Alignment/OfflineValidation/bin/MTSmerge.cc diff --git a/Alignment/OfflineValidation/bin/BuildFile.xml b/Alignment/OfflineValidation/bin/BuildFile.xml index 2f5b984819312..6578fd9b70855 100644 --- a/Alignment/OfflineValidation/bin/BuildFile.xml +++ b/Alignment/OfflineValidation/bin/BuildFile.xml @@ -18,5 +18,6 @@ + diff --git a/Alignment/OfflineValidation/bin/MTSmerge.cc b/Alignment/OfflineValidation/bin/MTSmerge.cc new file mode 100644 index 0000000000000..c94e55a6d8e26 --- /dev/null +++ b/Alignment/OfflineValidation/bin/MTSmerge.cc @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include + +#include "exceptions.h" +#include "toolbox.h" +#include "Options.h" + +#include "boost/filesystem.hpp" +#include "boost/property_tree/ptree.hpp" +#include "boost/property_tree/json_parser.hpp" +#include "boost/optional.hpp" + +#include "TString.h" +#include "TASImage.h" + +#include "Alignment/OfflineValidation/macros/trackSplitPlot.h" +#include "Alignment/OfflineValidation/macros/trackSplitPlot.C" +#include "Alignment/OfflineValidation/interface/TkAlStyle.h" + +using namespace std; +using namespace AllInOneConfig; + +namespace pt = boost::property_tree; + +int merge(int argc, char* argv[]) { + // parse the command line + + Options options; + options.helper(argc, argv); + options.parser(argc, argv); + + //Read in AllInOne json config + pt::ptree main_tree; + pt::read_json(options.config, main_tree); + + pt::ptree alignments = main_tree.get_child("alignments"); + pt::ptree validation = main_tree.get_child("validation"); + pt::ptree global_style; + pt::ptree merge_style; + + int iov = validation.count("IOV") ? validation.get("IOV") : 1; + std::string rlabel = validation.count("customrighttitle") ? validation.get("customrighttitle") : ""; + rlabel = merge_style.count("Rlabel") ? merge_style.get("Rlabel") : rlabel; + std::string cmslabel = merge_style.count("CMSlabel") ? merge_style.get("CMSlabel") : "INTERNAL"; + if (TkAlStyle::toStatus(cmslabel) == CUSTOM) + TkAlStyle::set(CUSTOM, NONE, cmslabel, rlabel); + else + TkAlStyle::set(TkAlStyle::toStatus(cmslabel), NONE, "", rlabel); + + TString filesAndLabels; + for (const auto& childTree : alignments) { + // Print node name and its attributes + std::cout << "Node: " << childTree.first << std::endl; + for (const auto& attr : childTree.second) { + std::cout << " Attribute: " << attr.first << " = " << attr.second.data() << std::endl; + } + + //std::cout << childTree.second.get("file") << std::endl; + //std::cout << childTree.second.get("title") << std::endl; + //std::cout << childTree.second.get("color") << std::endl; + //std::cout << childTree.second.get("style") << std::endl; + + std::string toAdd = childTree.second.get("file") + + Form("/MTSValidation_%s_%d.root=", childTree.first.c_str(), iov) + + childTree.second.get("title") + + Form("|%i|%i,", childTree.second.get("color"), childTree.second.get("style")); + filesAndLabels += toAdd; + } + + std::cout << "filesAndLabels: " << filesAndLabels << std::endl; + + TkAlStyle::legendheader = ""; + TkAlStyle::legendoptions = "all"; + outliercut = -1.0; + //fillmatrix(); + subdetector = "PIXEL"; + makePlots(filesAndLabels, "./"); + + return EXIT_SUCCESS; +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +int main(int argc, char* argv[]) { return exceptions(argc, argv); } +#endif diff --git a/Alignment/OfflineValidation/macros/trackSplitPlot.C b/Alignment/OfflineValidation/macros/trackSplitPlot.C index 1e1adf6c65988..9cdcf2b7e95cb 100644 --- a/Alignment/OfflineValidation/macros/trackSplitPlot.C +++ b/Alignment/OfflineValidation/macros/trackSplitPlot.C @@ -8,6 +8,7 @@ Table Of Contents 5. Place Legend ***********************************/ +using namespace std; #include "trackSplitPlot.h" #include "Alignment/OfflineValidation/interface/TkAlStyle.h" @@ -1869,12 +1870,12 @@ void makePlots(TString file, Bool_t matrix[xsize][ysize]) { setupcolors(); file.Remove(TString::kTrailing, ','); - int n = file.CountChar(',') + 1; + unsigned int n = file.CountChar(',') + 1; TString *files = new TString[n]; TString *names = new TString[n]; vector tempcolors = colors; vector tempstyles = styles; - for (int i = 0; i < n; i++) { + for (unsigned int i = 0; i < n; i++) { TString thisfile = nPart(i + 1, file, ","); int numberofpipes = thisfile.CountChar('|'); if (numberofpipes >= 0 && nPart(numberofpipes + 1, thisfile, "|").IsDigit()) { @@ -1951,12 +1952,12 @@ void makePlots(TString file, TString yvar) { setupcolors(); file.Remove(TString::kTrailing, ','); - int n = file.CountChar(',') + 1; + unsigned int n = file.CountChar(',') + 1; TString *files = new TString[n]; TString *names = new TString[n]; vector tempcolors = colors; vector tempstyles = styles; - for (int i = 0; i < n; i++) { + for (unsigned int i = 0; i < n; i++) { TString thisfile = nPart(i + 1, file, ","); int numberofpipes = thisfile.CountChar('|'); if (numberofpipes >= 0 && nPart(numberofpipes + 1, thisfile, "|").IsDigit()) { @@ -2008,12 +2009,12 @@ void makePlots(Int_t nFiles, TString *files, TString *names, TString directory) void makePlots(TString file, TString misalignment, Double_t *values, Double_t *phases, TString directory) { setupcolors(); file.Remove(TString::kTrailing, ','); - int n = file.CountChar(',') + 1; + unsigned int n = file.CountChar(',') + 1; TString *files = new TString[n]; TString *names = new TString[n]; vector tempcolors = colors; vector tempstyles = styles; - for (int i = 0; i < n; i++) { + for (unsigned int i = 0; i < n; i++) { TString thisfile = nPart(i + 1, file, ","); int numberofpipes = thisfile.CountChar('|'); if (numberofpipes >= 0 && nPart(numberofpipes + 1, thisfile, "|").IsDigit()) { diff --git a/Alignment/OfflineValidation/macros/trackSplitPlot.h b/Alignment/OfflineValidation/macros/trackSplitPlot.h index f861dcfd3b8b7..0f2d5d4b17972 100644 --- a/Alignment/OfflineValidation/macros/trackSplitPlot.h +++ b/Alignment/OfflineValidation/macros/trackSplitPlot.h @@ -34,8 +34,8 @@ enum PlotType { ScatterPlot, Profile, Histogram, OrgHistogram, Resolution }; enum Statistic { Minimum, Maximum, Average, RMS }; const Double_t pi = TMath::Pi(); -vector colors; -vector styles; +std::vector colors; +std::vector styles; bool colorsset = false; Int_t minrun = -1; Int_t maxrun = -1; @@ -67,7 +67,7 @@ Table Of Contents #include "trackSplitPlot.h" -ofstream devnull("/dev/null"); +std::ofstream devnull("/dev/null"); template T identity(T t) { return t; @@ -86,7 +86,7 @@ TCanvas *trackSplitPlot(Int_t nFiles, Bool_t resolution = false, Bool_t pull = false, TString saveas = "", - ostream &summaryfile = devnull); + std::ostream &summaryfile = devnull); TCanvas *trackSplitPlot(Int_t nFiles, TString *files, TString *names, @@ -94,7 +94,7 @@ TCanvas *trackSplitPlot(Int_t nFiles, Bool_t relative = false, Bool_t pull = false, TString saveas = "", - ostream &summaryfile = devnull); + std::ostream &summaryfile = devnull); TCanvas *trackSplitPlot(TString file, TString xvar, TString yvar, @@ -103,13 +103,13 @@ TCanvas *trackSplitPlot(TString file, Bool_t resolution = false, Bool_t pull = false, TString saveas = "", - ostream &summaryfile = devnull); + std::ostream &summaryfile = devnull); TCanvas *trackSplitPlot(TString file, TString var, Bool_t relative = false, Bool_t pull = false, TString saveas = "", - ostream &summaryfile = devnull); + std::ostream &summaryfile = devnull); void placeholder(TString saveas = "", Bool_t wide = false); void saveplot(TCanvas *c1, TString saveas); void deleteCanvas(TObject *canvas); diff --git a/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py b/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py index 47fb4a959bee3..ae0d9a44a6bcb 100644 --- a/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py +++ b/Alignment/OfflineValidation/python/TkAlAllInOneTool/MTS.py @@ -26,10 +26,10 @@ def MTS(config, validationDir): for IOV in config["validations"]["MTS"][mtsType][singleName]["IOV"]: ##Save IOV to loop later for merge jobs if singleName not in IOVs.keys(): - IOVs[singleName] = [] + IOVs[singleName] = [] if IOV not in IOVs[singleName]: - IOVs[singleName].append(IOV) - + IOVs[singleName].append(IOV) + for alignment in config["validations"]["MTS"][mtsType][singleName]["alignments"]: ##Work directory for each IOV workDir = "{}/MTS/{}/{}/{}/{}".format(validationDir, mtsType, singleName, alignment, IOV) @@ -59,441 +59,66 @@ def MTS(config, validationDir): jobs.append(job) -# FIXME%START: uncomment when the following modes will be available - if "merge" in config["validations"]["MTS"] or \ - "trends" in config["validations"]["MTS"] or \ - "averaged" in config["validations"]["MTS"]: - print("WARNING: 'merge', 'trends' and 'averaged' not yet supported. Will do nothing for them.") -# ##Do merge MTS if wished -# if "merge" in config["validations"]["MTS"]: -# ##List with merge jobs, will be expanded to jobs after looping -# mergeJobs = [] -# mtsType = "merge" -# -# ##Loop over all merge jobs -# for mergeName in config["validations"]["MTS"][mtsType]: -# ##Search for MC single(s) -# singlesMC = [] -# for singleName in config["validations"]["MTS"][mtsType][mergeName]['singles']: -# if len(IOVs[singleName]) == 1 and int(IOVs[singleName][0]) == 1: singlesMC.append(singleName) -# isMConly = (len(singlesMC) == len(config["validations"]["MTS"][mtsType][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"]["MTS"][mtsType][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 -# -# ##Work directory for each IOV -# workDir = "{}/MTS/{}/{}/{}".format(validationDir, mtsType, mergeName, IOV) #Different (DATA) single jobs must contain different set of IOVs -# -# ##Write job info -# local = {} -# -# job = { -# "name": "MTS_{}_{}_{}".format(mtsType, mergeName, IOV), -# "dir": workDir, -# "exe": "MTSmerge", -# "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"]["MTS"]["single"][singleName]["alignments"]: #Cover all DATA validations -# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) -# local["alignments"][alignment]['index'] = config["validations"]["MTS"]["single"][singleName]["alignments"].index(alignment) -# for singleMCname in singlesMC: -# if alignment in config["validations"]["MTS"]["single"][singleMCname]["alignments"]: #Add MC objects -# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) -# local["alignments"][alignment]['index'] = len(config["validations"]["MTS"]["single"][singleName]["alignments"]) -# local["alignments"][alignment]['index'] += idxIncrement + config["validations"]["MTS"]["single"][singleMCname]["alignments"].index(alignment) -# idxIncrement += len(config["validations"]["MTS"]["single"][singleMCname]["alignments"]) -# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][mergeName]) -# local["validation"]["IOV"] = IOV #is it really needed here? -# if "customrighttitle" in local["validation"].keys(): -# if "IOV" in local["validation"]["customrighttitle"]: -# local["validation"]["customrighttitle"] = local["validation"]["customrighttitle"].replace("IOV",str(IOV)) -# local["output"] = "{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], mtsType, mergeName, IOV) -# -# ##Add global plotting options -# if "style" in config.keys(): -# if "MTS" in config['style'].keys(): -# if mtsType in config['style']['MTS'].keys(): -# local["style"] = copy.deepcopy(config["style"]["MTS"][mtsType]) -# 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"]["MTS"][mtsType][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"]) -# -# ##Append to merge jobs -# mergeJobs.append(job) -# -# ##Append to all jobs -# jobs.extend(mergeJobs) -# -# if "trends" in config["validations"]["MTS"]: -# -# ##List with merge jobs, will be expanded to jobs after looping -# trendJobs = [] -# mtsType = "trends" -# -# for trendName in config["validations"]["MTS"][mtsType]: -# #print("trendName = {}".format(trendName)) -# ##Work directory for each IOV -# workDir = "{}/MTS/{}/{}".format(validationDir, mtsType, trendName) -# -# ##Write general job info -# local = {} -# job = { -# "name": "MTS_{}_{}".format(mtsType, trendName), -# "dir": workDir, -# "exe": "MTStrends", -# "run-mode": "Condor", -# "dependencies": [], -# "config": local, -# } -# -# ###Loop over merge steps (merge step can contain only DATA) -# mergesDATA = [] -# for mergeName in config["validations"]["MTS"][mtsType][trendName]["merges"]: -# ##Validate merge step -# if isDataMerged[mergeName] < 0: -# raise Exception("Trend jobs cannot process merge jobs containing both DATA and MC objects.") -# elif isDataMerged[mergeName] == 1: -# mergesDATA.append(mergeName) -# else: -# if "doUnitTest" in config["validations"]["MTS"][mtsType][trendName].keys() and config["validations"]["MTS"][mtsType][trendName]["doUnitTest"]: -# local.setdefault("alignments", {}) -# continue -# else: -# raise Exception("Trend jobs are not implemented for treating MC.") -# -# ###Loop over DATA singles included in merge steps -# trendIOVs = [] -# _mergeFiles = [] -# for mergeName in mergesDATA: -# for iname,singleName in enumerate(config["validations"]["MTS"]['merge'][mergeName]['singles']): -# trendIOVs += [IOV for IOV in IOVs[singleName]] -# ##Deep copy necessary things from global config + ensure plot order -# for alignment in config["alignments"]: -# local.setdefault("alignments", {}) -# if alignment in config["validations"]["MTS"]["single"][singleName]["alignments"]: #Cover all DATA validations -# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) -# local["alignments"][alignment]['index'] = config["validations"]["MTS"]["single"][singleName]["alignments"].index(alignment) -# _mergeFiles.append("{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}")) -# trendIOVs.sort() -# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][trendName]) -# if len(_mergeFiles) == 1: -# local["validation"]["mergeFile"] = _mergeFiles[0] -# else: -# local["validation"]["mergeFile"] = _mergeFiles #FIXME for multiple merge files in backend -# local["validation"]["IOV"] = trendIOVs -# local["output"] = "{}/{}/MTS/{}/{}/".format(config["LFS"], config["name"], mtsType, trendName) -# if "style" in config.keys() and "trends" in config["style"].keys(): -# local["style"] = copy.deepcopy(config["style"]) -# if "MTS" in local["style"].keys(): local["style"].pop("MTS") -# 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 merge jobs -# for mergeName in mergesDATA: -# for mergeJob in mergeJobs: -# alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:] -# if mergeJobName == mergeName and int(mergeIOV) in trendIOVs: -# job["dependencies"].append(mergeJob["name"]) -# -# trendJobs.append(job) -# -# jobs.extend(trendJobs) -# -# if "averaged" in config["validations"]["MTS"]: -# -# ####Finally, list of jobs is expanded for luminosity-averaged plot (avp) job -# avpJobs = [] -# mtsType = "averaged" -# for avpName in config["validations"]["MTS"][mtsType]: -# ###Main workdir for each combination of displayed lumi-averaged validation objects to be plotted -# workDir = "{}/MTS/{}/{}".format(validationDir, mtsType, avpName) -# output = "{}/{}/MTS/{}/{}".format(config["LFS"], config["name"], mtsType, avpName) -# -# ###Loop over merge steps (one merge step can contain only DATA or only MC singles but not mix) -# mergesDATA = [] -# mergesMC = [] -# for mergeName in config["validations"]["MTS"][mtsType][avpName]["merges"]: -# ##Validate merge step -# if isDataMerged[mergeName] < 0: -# raise Exception("Average jobs cannot process merge jobs containing both DATA and MC objects.") -# elif isDataMerged[mergeName] == 1: -# mergesDATA.append(mergeName) -# else: -# mergesMC.append(mergeName) -# -# lumiPerRun = [] -# lumiPerIoV = [] -# lumiMC = [] -# if len(mergesDATA) > 0: -# if "lumiPerRun" in config["validations"]["MTS"][mtsType][avpName].keys(): -# for lumifile in config["validations"]["MTS"][mtsType][avpName]['lumiPerRun']: -# if lumifile.split(".")[-1] in ["txt","csv"]: -# lumiPerRun.append(lumifile) -# if "lumiPerIoV" in config["validations"]["MTS"][mtsType][avpName].keys(): -# for lumifile in config["validations"]["MTS"][mtsType][avpName]['lumiPerIoV']: -# if lumifile.split(".")[-1] in ["txt","csv"]: -# lumiPerIoV.append(lumifile) -# if len(lumiPerRun) == 0 and len(lumiPerIoV) == 0: -# raise Exception("No lumi per run/IoV file found or not specified in .csv/.txt format.") -# if len(mergesMC) > 0: -# if 'lumiMC' in config["validations"]["MTS"][mtsType][avpName].keys(): -# lumiMC = config["validations"]["MTS"][mtsType][avpName]['lumiMC'] -# -# ###Store information about plotting job in this dictionary -# plotJob = {} -# plotJob['workdir'] = "{}/{}".format(workDir,"plots") -# plotJob['output'] = "{}/{}".format(output,"plots") -# plotJob['inputData'] = [] -# plotJob['inputMC'] = [] -# plotJob['dependencies'] = [] -# -# ###First loop over DATA -# for mergeName in mergesDATA: -# ##Adapt workdir per merge step -# workDirMerge = "{}/{}".format(workDir, mergeName) -# outputMerge = "{}/{}".format(output, mergeName) -# -# ##Create local config per merge step -# local = {} -# local["type"] = "MTS" -# local["mode"] = "merge" -# local["isData"] = True -# local["isMC"] = False -# -# ##Deep copy necessary things from global config -# for alignment in config["alignments"]: -# local.setdefault("alignments", {}) -# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: -# if alignment in config["validations"]["MTS"]["single"][singleName]['alignments']: -# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) -# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][avpName]) -# local["validation"]["mergeFile"] = "{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}") -# local["validation"]["lumiPerRun"] = lumiPerRun -# local["validation"]["lumiPerIoV"] = lumiPerIoV -# local["validation"]["lumiMC"] = lumiMC -# local["validation"]["firstFromNext"] = [] -# -# ##Determine list of IOVs in merge step (generally different than total list of IOVs) -# IOVsPerMergeStep = [] -# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: -# for IOV in IOVs[singleName]: -# if IOV not in IOVsPerMergeStep: -# IOVsPerMergeStep.append(IOV) -# IOVsPerMergeStep.sort() -# -# ##Divide average step job to subjobs to prevent memory issues -# extra_part = 0 -# maxfiles = int(config["validations"]["MTS"][mtsType][avpName]['maxfiles']) -# if len(IOVsPerMergeStep)%maxfiles >= 2: -# extra_part = 1 -# parts = extra_part+len(IOVsPerMergeStep)//maxfiles -# -# subJob = {'name' : [], 'output' : [], 'lumiPerFile' : []} -# for ipart in range(0,parts): -# #Adapt workdir per each subjob -# workDirSub = workDirMerge+"_"+str(ipart) -# outputSub = outputMerge+"_"+str(ipart) -# -# #Define IOV group -# IOVGroup = [] -# lastIndex = 0 -# for iIOV,IOV in enumerate(IOVsPerMergeStep): -# if (iIOV//maxfiles == ipart) or (ipart == parts-1 and iIOV//maxfiles > ipart): -# IOVGroup.append(IOV) -# lastIndex = iIOV -# firstFromNext = [] -# if lastIndex != len(IOVsPerMergeStep)-1: -# firstFromNext.append(IOVsPerMergeStep[lastIndex+1]) -# -# #Write job info -# _local = copy.deepcopy(local) -# _local["output"] = outputSub -# _local["validation"]["IOV"] = IOVGroup -# _local["validation"]["firstFromNext"] = firstFromNext -# job = { -# "name": "MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_"+str(ipart)), -# "dir": workDirSub, -# "exe": "mkLumiAveragedPlots.py", -# "run-mode": "Condor", -# "dependencies": [], -# "config": _local, -# } -# subJob['output'].append(outputSub) -# subJob['name'].append("MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_"+str(ipart))) -# subJob['lumiPerFile'].append(os.path.join(outputSub,"lumiPerFile.csv")) -# if parts == 1: -# plotJob['inputData'].append(outputSub) -# plotJob['dependencies'].append(job['name']) -# -# #Set average job dependencies from the list of all merge jobs -# for mergeJob in mergeJobs: -# alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:] -# if mergeJobName == mergeName and int(mergeIOV) in IOVGroup: -# job["dependencies"].append(mergeJob["name"]) -# #if mergeJobName in config["validations"]["MTS"][mtsType][avpName]["merges"]: -# # job["dependencies"].append(mergeJob["name"]) -# -# #Add to queue -# avpJobs.append(job) -# -# ##Add finalization job to merge all subjobs -# if parts > 1: -# localFinalize = copy.deepcopy(local) -# localFinalize['mode'] = "finalize" -# localFinalize['output'] = outputMerge -# localFinalize["validation"]["IOV"] = [] -# localFinalize["validation"]["mergeFile"] = subJob['output'] -# localFinalize["validation"]["lumiPerRun"] = [] -# localFinalize["validation"]["lumiPerIoV"] = subJob['lumiPerFile'] -# job = { -# "name": "MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_finalize"), -# "dir": workDirMerge, -# "exe": "mkLumiAveragedPlots.py", -# "run-mode": "Condor", -# "dependencies": subJob['name'], -# "config": localFinalize, -# } -# avpJobs.append(job) -# plotJob['inputData'].append(outputMerge) -# plotJob['dependencies'].append(job['name']) -# -# #Second create one averager job per all MC merge jobs -# if len(mergesMC) != 0: -# ##Adapt workdir per merge step -# workDirMerge = "{}/{}".format(workDir, "MC") -# outputMerge = "{}/{}".format(output, "MC") -# -# ##Create local config for MC average job -# local = {} -# local["type"] = "MTS" -# local["mode"] = "merge" -# local["isData"] = False -# local["isMC"] = True -# local["output"] = outputMerge -# -# ##Deep copy necessary things from global config -# local["validation"] = copy.deepcopy(config["validations"]["MTS"][mtsType][avpName]) -# local["validation"]["mergeFile"] = [] -# for mergeName in mergesMC: -# for alignment in config["alignments"]: -# local.setdefault("alignments", {}) -# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: -# if alignment in config["validations"]["MTS"]["single"][singleName]['alignments']: -# local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) -# local["validation"]["mergeFile"].append("{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], "merge", mergeName, "{}")) -# local["validation"]["lumiPerRun"] = lumiPerRun -# local["validation"]["lumiPerIoV"] = lumiPerIoV -# local["validation"]["lumiMC"] = lumiMC -# local["validation"]["IOV"] = [1] -# -# ##Write job info -# job = { -# "name": "MTS_{}_{}_{}".format(mtsType, avpName, mergeName+"_MC"), -# "dir": workDirMerge, -# "exe": "mkLumiAveragedPlots.py", -# "run-mode": "Condor", -# "dependencies": [], -# "config": local, -# } -# plotJob['inputMC'].append(outputMerge) -# plotJob['dependencies'].append(job['name']) -# -# ##Set average job dependencies from the list of all merge jobs -# for mergeJob in mergeJobs: -# alignment, mergeJobName, mergeIOV = mergeJob["name"].split("_")[1:] -# if mergeJobName in mergesMC: -# job["dependencies"].append(mergeJob["name"]) -# -# ##Add to queue -# avpJobs.append(job) -# -# ##Finally add job to plot averaged distributions -# if len(plotJob['inputData'])+len(plotJob['inputMC']) > 0: -# local = {} -# local["type"] = "MTS" -# local["mode"] = "plot" -# local["isData"] = True if len(plotJob['inputData']) > 0 else False -# local["isMC"] = True if len(plotJob['inputMC']) > 0 else False -# local["output"] = plotJob['output'] -# local["plot"] = { "inputData" : plotJob['inputData'], -# "inputMC" : plotJob['inputMC'], -# "alignments" : [], -# "objects" : [], -# "labels" : [], -# "colors" : [], -# "styles" : [], -# "useFit" : True, -# "useFitError" : False, -# "showMean" : True, -# "showMeanError" : False, -# "showRMS" : False, -# "showRMSError" : False} -# ##Copy alignment objects info from global config -# for mergeName in mergesDATA+mergesMC: -# for singleName in config["validations"]["MTS"]["merge"][mergeName]["singles"]: -# for alignment in config["validations"]["MTS"]["single"][singleName]['alignments']: -# if alignment in config['alignments'] and alignment not in local["plot"]["alignments"]: -# local["plot"]["alignments"].append(alignment) -# objectName = config["alignments"][alignment]["title"].replace(" ","_") -# if objectName not in local["plot"]["objects"]: #can happen for MC -# local["plot"]["objects"].append(objectName) -# local["plot"]["labels"].append(config["alignments"][alignment]["title"]) -# local["plot"]["colors"].append(config["alignments"][alignment]["color"]) -# local["plot"]["styles"].append(config["alignments"][alignment]["style"]) -# ##Overwrite if needed -# for extraKey in ["objects","labels","colors","styles","useFit","useFitError","showMean","showMeamError","showRMS","showRMSError"]: -# if extraKey in config["validations"]["MTS"][mtsType][avpName].keys(): -# local["plot"][extraKey] = config["validations"]["MTS"][mtsType][avpName][extraKey] -# ##Add global plotting options -# if "style" in config.keys(): -# if "MTS" in config['style'].keys(): -# if mtsType in config['style']['MTS'].keys(): -# local["plotGlobal"] = copy.deepcopy(config["style"]['MTS'][mtsType]) -# -# ##Write job info -# job = { -# "name": "MTS_{}_{}_{}".format(mtsType, avpName, "plot"), -# "dir": plotJob['workdir'], -# "exe": "mkLumiAveragedPlots.py", -# "run-mode": "Condor", -# "dependencies": plotJob['dependencies'], -# "config": local, -# } -# avpJobs.append(job) -# -# #Finally extend main job collection -# jobs.extend(avpJobs) -# -# FIXME%END + ##Do merge MTS if wished + if "merge" in config["validations"]["MTS"]: + ##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"]["MTS"][pvType]: + ##Loop over singles + for iname,singleName in enumerate(config["validations"]["MTS"][pvType][mergeName]['singles']): + for IOV in IOVs[singleName]: + + ##Work directory for each IOV + workDir = "{}/MTS/{}/{}/{}".format(validationDir, pvType, mergeName, IOV) #Different (DATA) single jobs must contain different set of IOVs + + ##Write job info + local = {} + + job = { + "name": "MTS_{}_{}_{}".format(pvType, mergeName, IOV), + "dir": workDir, + "exe": "MTSmerge", + "run-mode": "Condor", + "dependencies": [], + "config": local, + } + + ##Deep copy necessary things from global config + assure plot order + for alignment in config["alignments"]: + local.setdefault("alignments", {}) + if alignment in config["validations"]["MTS"]["single"][singleName]["alignments"]: #Cover all DATA validations + local["alignments"][alignment] = copy.deepcopy(config["alignments"][alignment]) + local["alignments"][alignment]['index'] = config["validations"]["MTS"]["single"][singleName]["alignments"].index(alignment) + local["alignments"][alignment]['isMC'] = False + local["validation"] = copy.deepcopy(config["validations"]["MTS"][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"] = "{}/{}/MTS/{}/{}/{}".format(config["LFS"], config["name"], pvType, mergeName, IOV) + + ##Add global plotting options + if "style" in config.keys(): + if "MTS" in config['style'].keys(): + if pvType in config['style']['MTS'].keys(): + local["style"] = copy.deepcopy(config["style"]["MTS"][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"]["MTS"][pvType][mergeName]["singles"]: + if (int(_singleIOV) == IOV): #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) + return jobs From 4feac7164841c65c98d3e115f11dd58c60cf8179 Mon Sep 17 00:00:00 2001 From: mmusich Date: Mon, 8 Jan 2024 17:45:52 +0100 Subject: [PATCH 3/6] implement MTS validation in all-in-one unit tests --- .../OfflineValidation/test/BuildFile.xml | 3 + .../test/testingScripts/test_unitMTS.sh | 23 ++++++++ .../OfflineValidation/test/unit_test.json | 59 ++++++++++++++++++- .../OfflineValidation/test/unit_test.yaml | 47 +++++++++++++++ 4 files changed, 131 insertions(+), 1 deletion(-) create mode 100755 Alignment/OfflineValidation/test/testingScripts/test_unitMTS.sh diff --git a/Alignment/OfflineValidation/test/BuildFile.xml b/Alignment/OfflineValidation/test/BuildFile.xml index a8bfe03534a9b..d6cc4c190ef4d 100644 --- a/Alignment/OfflineValidation/test/BuildFile.xml +++ b/Alignment/OfflineValidation/test/BuildFile.xml @@ -18,6 +18,9 @@ + + + diff --git a/Alignment/OfflineValidation/test/testingScripts/test_unitMTS.sh b/Alignment/OfflineValidation/test/testingScripts/test_unitMTS.sh new file mode 100755 index 0000000000000..71945e6a00b63 --- /dev/null +++ b/Alignment/OfflineValidation/test/testingScripts/test_unitMTS.sh @@ -0,0 +1,23 @@ +#! /bin/bash + +function die { echo $1: status $2 ; exit $2; } + +echo "TESTING Alignment/MTS single configuration with json..." +pushd test_yaml/MTS/single/testSingleMTS/PromptNewTemplate/1 +./cmsRun validation_cfg.py config=validation.json || die "Failure running MTS single configuration with json" $? + +echo "TESTING Alignment/MTS single configuration standalone..." +./cmsRun validation_cfg.py || die "Failure running MTS single configuration standalone" $? +popd + +pushd test_yaml/MTS/single/testSingleMTS/mp3619/1 +./cmsRun validation_cfg.py config=validation.json || die "Failure running MTS single configuration with json (part 2)" $? + +echo "TESTING Alignment/MTS single configuration standalone..." +./cmsRun validation_cfg.py || die "Failure running MTS single configuration standalone (part 2)" $? +popd + +echo "TESTING MTS merge step" +pushd test_yaml/MTS/merge/testSingleMTS/1 +./MTSmerge validation.json --verbose || die "Failure running MTS merge step" $? +popd diff --git a/Alignment/OfflineValidation/test/unit_test.json b/Alignment/OfflineValidation/test/unit_test.json index b5bba7315f84e..773866c51fec5 100644 --- a/Alignment/OfflineValidation/test/unit_test.json +++ b/Alignment/OfflineValidation/test/unit_test.json @@ -56,7 +56,45 @@ "globaltag": "auto:phase1_2018_realistic", "style": "2101", "title": "unit test" - } + }, + "PromptNewTemplate" : { + "name" : "PromptNewTemplate", + "color" : "1", + "globaltag" : "124X_dataRun3_Prompt_v10", + "style" : "2301", + "title" : "Alignment in prompt with 400V pixel templates", + "conditions" : { + "SiPixelTemplateDBObjectRcd" : { + "connect" : "frontier://FrontierProd/CMS_CONDITIONS", + "tag" : "SiPixelTemplateDBObject_phase1_38T_2022_v9" + }, + "SiPixel2DTemplateDBObjectRcd" : { + "connect" : "frontier://FrontierProd/CMS_CONDITIONS", + "tag" : "SiPixel2DTemplateDBObject_phase1_38T_2022_v9" + } + } + }, + "mp3619" : { + "name" : "mp3619", + "color" : "2", + "globaltag" : "124X_dataRun3_Prompt_v10", + "style" : "2001", + "title" : "mp3619", + "conditions" : { + "TrackerAlignmentRcd" : { + "connect" : "frontier://FrontierProd/CMS_CONDITIONS", + "tag" : "TrackerAlignment_collisions22_v13" + }, + "SiPixelTemplateDBObjectRcd" : { + "connect" : "frontier://FrontierProd/CMS_CONDITIONS", + "tag" : "SiPixelTemplateDBObject_phase1_38T_2022_v9" + }, + "SiPixel2DTemplateDBObjectRcd" : { + "connect" : "frontier://FrontierProd/CMS_CONDITIONS", + "tag" : "SiPixel2DTemplateDBObject_phase1_38T_2022_v9" + } + } + } }, "validations": { "DMR": { @@ -161,6 +199,25 @@ } } }, + "MTS" : { + "merge" : { + "testSingleMTS" : { + "singles" : ["testSingleMTS"] + } + }, + "single" : { + "testSingleMTS" : { + "IOV" : ["1"], + "alignments": ["PromptNewTemplate","mp3619"], + "maxevents" : 200000, + "trackcollection" : "ALCARECOTkAlCosmicsCTF0T", + "tthrbuilder" : "WithAngleAndTemplate", + "usePixelQualityFlag" : "True", + "cosmicsZeroTesla" : "False", + "magneticfield" : 3.8 + } + } + }, "GCP": { "GCPdetUnits": { "levels": "DetUnit", diff --git a/Alignment/OfflineValidation/test/unit_test.yaml b/Alignment/OfflineValidation/test/unit_test.yaml index 19c26174b914f..6274962d8076c 100644 --- a/Alignment/OfflineValidation/test/unit_test.yaml +++ b/Alignment/OfflineValidation/test/unit_test.yaml @@ -44,6 +44,35 @@ alignments: globaltag: auto:phase1_2022_realistic style: 2101 title: unit test + PromptNewTemplate: + name: PromptNewTemplate + color: 1 + globaltag: 124X_dataRun3_Prompt_v10 + style: 2301 + title: Alignment in prompt with 400V pixel templates + conditions: + SiPixelTemplateDBObjectRcd: + connect: frontier://FrontierProd/CMS_CONDITIONS + tag: SiPixelTemplateDBObject_phase1_38T_2022_v9 + SiPixel2DTemplateDBObjectRcd: + connect: frontier://FrontierProd/CMS_CONDITIONS + tag: SiPixel2DTemplateDBObject_phase1_38T_2022_v9 + mp3619: + name: mp3619 + color: 2 + globaltag: 124X_dataRun3_Prompt_v10 + style: 2001 + title: mp3619 + conditions: + TrackerAlignmentRcd: + connect: frontier://FrontierProd/CMS_CONDITIONS + tag: TrackerAlignment_collisions22_v13 + SiPixelTemplateDBObjectRcd: + connect: frontier://FrontierProd/CMS_CONDITIONS + tag: SiPixelTemplateDBObject_phase1_38T_2022_v9 + SiPixel2DTemplateDBObjectRcd: + connect: frontier://FrontierProd/CMS_CONDITIONS + tag: SiPixel2DTemplateDBObject_phase1_38T_2022_v9 validations: DMR: single: @@ -153,6 +182,24 @@ validations: - unitTestDiMuonVMC trackcollection: generalTracks maxevents: 10 + MTS: + merge: + testSingleMTS: + singles: + - testSingleMTS + single: + testSingleMTS: + IOV: + - 1 + alignments: + - PromptNewTemplate + - mp3619 + maxevents: 200000 + trackcollection: ALCARECOTkAlCosmicsCTF0T + tthrbuilder: WithAngleAndTemplate + usePixelQualityFlag: True + cosmicsZeroTesla: False + magneticfield: 3.8 GCP: GCPdetUnits: levels: DetUnit From 7557c510867078ba0c9650dbefa00f5fdc321da1 Mon Sep 17 00:00:00 2001 From: mmusich Date: Mon, 8 Jan 2024 17:46:26 +0100 Subject: [PATCH 4/6] fix typo in test_unitDiMuonV --- .../OfflineValidation/test/testingScripts/test_unitDiMuonV.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Alignment/OfflineValidation/test/testingScripts/test_unitDiMuonV.sh b/Alignment/OfflineValidation/test/testingScripts/test_unitDiMuonV.sh index 662561dfd0016..6d01a1d61385b 100755 --- a/Alignment/OfflineValidation/test/testingScripts/test_unitDiMuonV.sh +++ b/Alignment/OfflineValidation/test/testingScripts/test_unitDiMuonV.sh @@ -10,7 +10,7 @@ echo "TESTING Alignment/DiMuonV single configuration standalone..." ./cmsRun validation_cfg.py || die "Failure running DiMuonV single configuration standalone" $? popd -echo "TESTING PV merge step" +echo "TESTING DiMuonV merge step" pushd test_yaml/DiMuonV/merge/testUnits/1/ ./DiMuonVmerge validation.json --verbose || die "Failure running DiMuonV merge step" $? popd From b842705d6802144d2b108d9477de6c1a6bcdbe87 Mon Sep 17 00:00:00 2001 From: mmusich Date: Mon, 8 Jan 2024 18:04:45 +0100 Subject: [PATCH 5/6] update README for Muon Track Splitting --- Alignment/OfflineValidation/README.md | 3 +++ Alignment/OfflineValidation/README_MTS.md | 20 +++----------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Alignment/OfflineValidation/README.md b/Alignment/OfflineValidation/README.md index 02dd633ff9ca4..d7c4554d9812d 100644 --- a/Alignment/OfflineValidation/README.md +++ b/Alignment/OfflineValidation/README.md @@ -114,5 +114,8 @@ For details read [`README_PV.md`](https://github.com/cms-sw/cmssw/blob/master/Al ## JetHT validation For details read [`README_JetHT.md`](https://github.com/cms-sw/cmssw/blob/master/Alignment/OfflineValidation/README_JetHT.md) +## MTS validation +For details read [`README_MTS.md`](https://github.com/cms-sw/cmssw/blob/master/Alignment/OfflineValidation/README_MTS.md) + ## General info about IOV/run arguments For details read [`README_IOV.md`](https://github.com/cms-sw/cmssw/blob/master/Alignment/OfflineValidation/README_IOV.md) diff --git a/Alignment/OfflineValidation/README_MTS.md b/Alignment/OfflineValidation/README_MTS.md index e818168e24d78..e616e4d549147 100644 --- a/Alignment/OfflineValidation/README_MTS.md +++ b/Alignment/OfflineValidation/README_MTS.md @@ -1,4 +1,4 @@ -## PV validation +## MTS (Muon Track Splitting) validation ### General info @@ -15,9 +15,9 @@ MTS validation runs in 1 possible type of steps: Step name is arbitrary string which will be used as a reference for consequent steps. Merge and trend jobs are not yet implemented. -### Single PV jobs +### Single MTS jobs -Single jobs can be specified per run (IoV as well). In case of MC, IoV is specified to arbitrary 1. +Single jobs can be specified per run (IoV as well). **Parameters below to be updated** Variable | Default value | Explanation/Options @@ -27,21 +27,7 @@ Alignments | None | List of alignments. Will create separate directory for each. dataset | See defaultInputFiles_cff.py | Path to txt file containing list of datasets to be used. If file is missing at EOS or is corrupted - job will eventually fail (most common issue). goodlumi | cms.untracked.VLuminosityBlockRange() | Path to json file containing lumi information about selected IoV - must contain list of runs under particular IoV with lumiblock info. Format: `IOV_Vali_{}.json` maxevents | 1 | Maximum number of events before cmsRun terminates. -maxtracks | 1 | Maximum number of tracks per event before next event is processed. trackcollection | "generalTracks" | Track collection to be specified here, e.g. "ALCARECOTkAlMuonIsolated" or "ALCARECOTkAlMinBias" ... tthrbuilder | "WithAngleAndTemplate" | Specify TTRH Builder usePixelQualityFlag | True | Use pixel quality flag? cosmicsZeroTesla | False | Is this validation for cosmics with zero magnetic field? -vertexcollection | "offlinePrimaryVertices" | Specify vertex collection to be used. -isda | True | Use DA algorithm (True) or GAP algorithm (False) -ismc | True | Is validation for MC (True) or Data (False)? -runboundary | 1 | Specify starting run number (can be also list of starting numbers in multirun approach). -runControl | False | Enable run control -ptCut | 3. | Probe tracks with pT > 3GeV -etaCut | 2.5 | Probe tracks in abs(eta) < 2.5 region -minPt | 1. | Define minimal track pT -maxPt | 30. | Define maximum track pT -doBPix | True | Do not run validation for BPix if needed -doFPix | True | Do not run validation for FPix if needed -forceBeamSpot | False | Force beam spot -numberOfBins | 48 | Define histogram granularity From 9b5497d196cad52c79265eb7028f180eb2c679d4 Mon Sep 17 00:00:00 2001 From: mmusich Date: Fri, 12 Jan 2024 19:31:21 +0100 Subject: [PATCH 6/6] apply code-checks and code-format to trackSplitPlot.C --- .../OfflineValidation/macros/trackSplitPlot.C | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/Alignment/OfflineValidation/macros/trackSplitPlot.C b/Alignment/OfflineValidation/macros/trackSplitPlot.C index 9cdcf2b7e95cb..39e030fe10a91 100644 --- a/Alignment/OfflineValidation/macros/trackSplitPlot.C +++ b/Alignment/OfflineValidation/macros/trackSplitPlot.C @@ -37,7 +37,7 @@ TCanvas *trackSplitPlot(Int_t nFiles, stufftodelete->SetOwner(true); cout << xvar << " " << yvar << endl; if (xvar == "" && yvar == "") - return 0; + return nullptr; PlotType type; if (xvar == "") @@ -160,7 +160,7 @@ TCanvas *trackSplitPlot(Int_t nFiles, TFile *f = TFile::Open(files[i]); TTree *tree = (TTree *)f->Get("cosmicValidation/splitterTree"); - if (tree == 0) + if (tree == nullptr) tree = (TTree *)f->Get("splitterTree"); lengths[i] = tree->GetEntries(); @@ -438,16 +438,16 @@ TCanvas *trackSplitPlot(Int_t nFiles, } } - TH1 *firstp = 0; + TH1 *firstp = nullptr; for (int i = 0; i < n; i++) { if (used[i]) { firstp = p[i]; break; } } - if (firstp == 0) { + if (firstp == nullptr) { stufftodelete->Clear(); - return 0; + return nullptr; } TCanvas *c1 = TCanvas::MakeDefCanvas(); @@ -546,13 +546,13 @@ TCanvas *trackSplitPlot(Int_t nFiles, p[i]->Draw("same hist"); legend->AddEntry(p[i], names[i], "l"); } - legend->AddEntry((TObject *)0, meansrmss[i], ""); + legend->AddEntry((TObject *)nullptr, meansrmss[i], ""); } } - if (legend->GetListOfPrimitives()->At(0) == 0) { + if (legend->GetListOfPrimitives()->At(0) == nullptr) { stufftodelete->Clear(); deleteCanvas(c1); - return 0; + return nullptr; } c1->Update(); @@ -639,7 +639,7 @@ void saveplot(TCanvas *c1, TString saveas) { } void deleteCanvas(TObject *canvas) { - if (canvas == 0) + if (canvas == nullptr) return; if (!canvas->InheritsFrom("TCanvas")) { delete canvas; @@ -730,7 +730,7 @@ void misalignmentDependence(TCanvas *c1old, Bool_t resolution, Bool_t pull, TString saveas) { - if (c1old == 0) + if (c1old == nullptr) return; c1old = (TCanvas *)c1old->Clone("c1old"); if (misalignment == "" || yvar == "") @@ -761,9 +761,9 @@ void misalignmentDependence(TCanvas *c1old, s0 << "p" << i; TString pname = s0.str(); p[i] = (TH1 *)list->/*At(i+1+(xvar == ""))*/ FindObject(pname); - used[i] = (p[i] != 0); + used[i] = (p[i] != nullptr); if (used[i]) - p[i]->SetDirectory(0); + p[i]->SetDirectory(nullptr); if (xvar == "") continue; stringstream s; @@ -862,12 +862,12 @@ void misalignmentDependence(TCanvas *c1old, legend->SetFillStyle(0); legend->Draw(); } else { - if (values == 0) + if (values == nullptr) return; Bool_t phasesmatter = false; if (misalignment == "elliptical" || misalignment == "sagitta" || misalignment == "skew") { - if (phases == 0) { + if (phases == nullptr) { cout << "This misalignment has a phase, but you didn't supply the phases!" << endl << "Can't produce plots depending on the misalignment value." << endl; return; @@ -884,7 +884,7 @@ void misalignmentDependence(TCanvas *c1old, } if (!phasesmatter) { - TGraphErrors *g = new TGraphErrors(nFiles, values, result, (Double_t *)0, error); + TGraphErrors *g = new TGraphErrors(nFiles, values, result, (Double_t *)nullptr, error); g->SetName(""); stufftodelete->Add(g); @@ -918,7 +918,8 @@ void misalignmentDependence(TCanvas *c1old, xvalues[i] = values[i] * cos(phases[i]); yvalues[i] = values[i] * sin(phases[i]); } - TGraph2DErrors *g = new TGraph2DErrors(nFiles, xvalues, yvalues, result, (Double_t *)0, (Double_t *)0, error); + TGraph2DErrors *g = + new TGraph2DErrors(nFiles, xvalues, yvalues, result, (Double_t *)nullptr, (Double_t *)nullptr, error); g->SetName(""); stufftodelete->Add(g); delete[] xvalues; //A TGraph2DErrors has its own copy of xvalues and yvalues, so it's ok to delete these copies. @@ -1255,7 +1256,7 @@ Bool_t misalignmentDependence(TCanvas *c1old, Bool_t pull, TString saveas) { if (xvar == "") { - if (c1old == 0 || misalignment == "" || values == 0) + if (c1old == nullptr || misalignment == "" || values == nullptr) return false; misalignmentDependence(c1old, nFiles, @@ -1265,7 +1266,7 @@ Bool_t misalignmentDependence(TCanvas *c1old, phases, xvar, yvar, - (TF1 *)0, + (TF1 *)nullptr, 0, "", "", @@ -1275,7 +1276,7 @@ Bool_t misalignmentDependence(TCanvas *c1old, saveas); return true; } - TF1 *f = 0; + TF1 *f = nullptr; TString functionname = ""; //if only one parameter is of interest @@ -1284,8 +1285,8 @@ Bool_t misalignmentDependence(TCanvas *c1old, //if multiple parameters are of interest Int_t nParameters = -1; - TString *parameternames = 0; - Int_t *parameters = 0; + TString *parameternames = nullptr; + Int_t *parameters = nullptr; if (misalignment == "sagitta") { if (xvar == "phi" && yvar == "phi" && !resolution && !pull) { @@ -1556,12 +1557,12 @@ Bool_t misalignmentDependence(Int_t nFiles, } Bool_t hasFit(TString misalignment, TString xvar, TString yvar, Bool_t relative, Bool_t resolution, Bool_t pull) { - return misalignmentDependence((TCanvas *)0, + return misalignmentDependence((TCanvas *)nullptr, 0, - (TString *)0, + (TString *)nullptr, misalignment, - (Double_t *)0, - (Double_t *)0, + (Double_t *)nullptr, + (Double_t *)nullptr, xvar, yvar, false, @@ -1586,7 +1587,7 @@ void makePlots(Int_t nFiles, stufftodelete->SetOwner(true); for (Int_t i = 0, totaltime = 0; i < nFiles; i++) { - TFile *f = 0; + TFile *f = nullptr; bool exists = false; if (files[i] == "") exists = true; @@ -1594,7 +1595,7 @@ void makePlots(Int_t nFiles, for (int j = 1; j <= 60 * 24 && !exists; j++, totaltime++) //wait up to 1 day for the validation to be finished { f = TFile::Open(files[i]); - if (f != 0) + if (f != nullptr) exists = f->IsOpen(); delete f; if (exists) @@ -1859,7 +1860,7 @@ void makePlots(Int_t nFiles, } void makePlots(Int_t nFiles, TString *files, TString *names, TString directory, Bool_t matrix[xsize][ysize]) { - makePlots(nFiles, files, names, "", (Double_t *)0, (Double_t *)0, directory, matrix); + makePlots(nFiles, files, names, "", (Double_t *)nullptr, (Double_t *)nullptr, directory, matrix); } void makePlots(TString file, @@ -1903,7 +1904,7 @@ void makePlots(TString file, } void makePlots(TString file, TString directory, Bool_t matrix[xsize][ysize]) { - makePlots(file, "", (Double_t *)0, (Double_t *)0, directory, matrix); + makePlots(file, "", (Double_t *)nullptr, (Double_t *)nullptr, directory, matrix); } //*************************************************************************** @@ -1940,7 +1941,7 @@ void makePlots(Int_t nFiles, } void makePlots(Int_t nFiles, TString *files, TString *names, TString directory, TString xvar, TString yvar) { - makePlots(nFiles, files, names, "", (Double_t *)0, (Double_t *)0, directory, xvar, yvar); + makePlots(nFiles, files, names, "", (Double_t *)nullptr, (Double_t *)nullptr, directory, xvar, yvar); } void makePlots(TString file, @@ -1985,7 +1986,7 @@ void makePlots(TString file, } void makePlots(TString file, TString directory, TString xvar, TString yvar) { - makePlots(file, "", (Double_t *)0, (Double_t *)0, directory, xvar, yvar); + makePlots(file, "", (Double_t *)nullptr, (Double_t *)nullptr, directory, xvar, yvar); } //*************************** @@ -2003,7 +2004,7 @@ void makePlots(Int_t nFiles, } void makePlots(Int_t nFiles, TString *files, TString *names, TString directory) { - makePlots(nFiles, files, names, "", (Double_t *)0, (Double_t *)0, directory); + makePlots(nFiles, files, names, "", (Double_t *)nullptr, (Double_t *)nullptr, directory); } void makePlots(TString file, TString misalignment, Double_t *values, Double_t *phases, TString directory) { @@ -2041,7 +2042,9 @@ void makePlots(TString file, TString misalignment, Double_t *values, Double_t *p styles = tempstyles; } -void makePlots(TString file, TString directory) { makePlots(file, "", (Double_t *)0, (Double_t *)0, directory); } +void makePlots(TString file, TString directory) { + makePlots(file, "", (Double_t *)nullptr, (Double_t *)nullptr, directory); +} //============= //3. Axis Label @@ -2108,7 +2111,7 @@ TString latexunits(TString variable, char axis) { TString axislabel(TString variable, Char_t axis, Bool_t relative, Bool_t resolution, Bool_t pull) { if (axis == 'X' || axis == 'Y') { double min, max, bins; - axislimits(0, 0, variable, tolower(axis), relative, pull, min, max, bins); + axislimits(0, nullptr, variable, tolower(axis), relative, pull, min, max, bins); if (variable.BeginsWith("nHits")) return "fraction of tracks"; @@ -2284,7 +2287,7 @@ Double_t findStatistic( continue; TFile *f = TFile::Open(files[j]); TTree *tree = (TTree *)f->Get("cosmicValidation/splitterTree"); - if (tree == 0) + if (tree == nullptr) tree = (TTree *)f->Get("splitterTree"); Int_t length = tree->GetEntries(); @@ -2576,9 +2579,9 @@ Double_t placeLegend( Bool_t fitsHere(TLegend *l, Double_t x1, Double_t y1, Double_t x2, Double_t y2) { Bool_t fits = true; TList *list = l->GetListOfPrimitives(); - for (Int_t k = 0; list->At(k) != 0 && fits; k++) { + for (Int_t k = 0; list->At(k) != nullptr && fits; k++) { TObject *obj = ((TLegendEntry *)(list->At(k)))->GetObject(); - if (obj == 0) + if (obj == nullptr) continue; TClass *cl = obj->IsA();