From 41f17cb56dc9836f91af9cff43fd7ef94259b3d3 Mon Sep 17 00:00:00 2001 From: Ram Krishna Sharma Date: Wed, 13 Nov 2024 22:55:32 +0100 Subject: [PATCH 1/3] changes to adapt EL9 --- .gitignore | 3 + ExampleInputFileList.txt | 5 - H4LCppModule.py | 154 +++++++--- Helper.py | 26 +- Input_2022.yml | 7 +- README.md | 33 +- external/JHUGen_py2to3.patch | 55 ++++ external/nanoAODTools_py2to3.patch | 129 ++++++++ external/yaml-cpp | 1 - external/yamlcpp_pkg_py2to3.patch | 465 +++++++++++++++++++++++++++++ post_proc.py | 2 +- 11 files changed, 807 insertions(+), 73 deletions(-) create mode 100644 external/JHUGen_py2to3.patch create mode 100644 external/nanoAODTools_py2to3.patch delete mode 160000 external/yaml-cpp create mode 100644 external/yamlcpp_pkg_py2to3.patch diff --git a/.gitignore b/.gitignore index f8b45c1..f175a71 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,6 @@ br.sm2 *maincc *linkdef.h JHUGenMELA/ +yaml-cpp/ +nanoAOD_skim.wiki/ +*.xml diff --git a/ExampleInputFileList.txt b/ExampleInputFileList.txt index 427f69a..7aaad41 100644 --- a/ExampleInputFileList.txt +++ b/ExampleInputFileList.txt @@ -1,6 +1 @@ /store/mc/Run3Summer22NanoAODv12/GluGluHtoZZto4L_M-125_TuneCP5_13p6TeV_powheg2-JHUGenV752-pythia8/NANOAODSIM/130X_mcRun3_2022_realistic_v5-v2/2520000/dcae7632-2ea5-4832-80f0-de7d45837a7f.root -/store/mc/Run3Summer22NanoAODv12/GluGluHtoZZto4L_M-125_TuneCP5_13p6TeV_powheg2-JHUGenV752-pythia8/NANOAODSIM/130X_mcRun3_2022_realistic_v5-v2/2530000/25212339-d2db-48c4-936d-fc47e9de45e9.root -/store/mc/Run3Summer22NanoAODv12/GluGluHtoZZto4L_M-125_TuneCP5_13p6TeV_powheg2-JHUGenV752-pythia8/NANOAODSIM/130X_mcRun3_2022_realistic_v5-v2/2530000/7a86daa3-36d3-42a4-8962-dc831b8608e0.root -/store/mc/Run3Summer22NanoAODv12/GluGluHtoZZto4L_M-125_TuneCP5_13p6TeV_powheg2-JHUGenV752-pythia8/NANOAODSIM/130X_mcRun3_2022_realistic_v5-v2/2530000/c7c62ee7-13a9-4de1-962d-64503a6fef05.root -/store/mc/Run3Summer22NanoAODv12/GluGluHtoZZto4L_M-125_TuneCP5_13p6TeV_powheg2-JHUGenV752-pythia8/NANOAODSIM/130X_mcRun3_2022_realistic_v5-v2/2540000/a2a64a49-3404-49db-bf42-cb0ceb5218e2.root -/store/mc/Run3Summer22NanoAODv12/GluGluHtoZZto4L_M-125_TuneCP5_13p6TeV_powheg2-JHUGenV752-pythia8/NANOAODSIM/130X_mcRun3_2022_realistic_v5-v2/2540000/b46903af-5d85-479e-b776-0803db6c3e2c.root diff --git a/H4LCppModule.py b/H4LCppModule.py index 4360ac1..7ffad6d 100644 --- a/H4LCppModule.py +++ b/H4LCppModule.py @@ -1,5 +1,5 @@ from PhysicsTools.NanoAODTools.postprocessing.framework.eventloop import Module -from PhysicsTools.NanoAODTools.postprocessing.framework.datamodel import Collection +from PhysicsTools.NanoAODTools.postprocessing.framework.datamodel import Collection, Object import ROOT import yaml import os @@ -9,48 +9,109 @@ class HZZAnalysisCppProducer(Module): def __init__(self,year,cfgFile,isMC,isFSR,isFiducialAna, DEBUG=False): - base = "$CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim" - ROOT.gSystem.Load("%s/JHUGenMELA/MELA/data/slc7_amd64_gcc700/libJHUGenMELAMELA.so" % base) - ROOT.gSystem.Load("%s/JHUGenMELA/MELA/data/slc7_amd64_gcc700/libjhugenmela.so" % base) - ROOT.gSystem.Load("%s/JHUGenMELA/MELA/data/slc7_amd64_gcc700/libmcfm_707.so" % base) - ROOT.gSystem.Load("%s/JHUGenMELA/MELA/data/slc7_amd64_gcc700/libcollier.so" % base) - yaml_cpp_path = os.path.join(base, "external/yaml-cpp") + self.loadLibraries() + self.year = year + self.isMC = isMC + self.DEBUG = DEBUG + self.cfgFile = cfgFile + self.cfg = self._load_config(cfgFile) + self.CutFlowTable = ROOT.TH1F('cutFlow','cutFlow',20, 0, 20) + self.CutFlowTable.GetXaxis().SetBinLabel(1, "Events") + self.CutFlowTable.GetXaxis().SetBinLabel(2, "Trigger") + self.CutFlowTable.GetXaxis().SetBinLabel(3, "4Lepton") + self.CutFlowTable.GetXaxis().SetBinLabel(4, "4LeptonOSSF") + self.CutFlowTable.GetXaxis().SetBinLabel(5, "getTightZ") + self.CutFlowTable.GetXaxis().SetBinLabel(6, "getTightZ1") + self.CutFlowTable.GetXaxis().SetBinLabel(7, "lep_pTcut") + self.CutFlowTable.GetXaxis().SetBinLabel(8, "lepdRcut") + self.CutFlowTable.GetXaxis().SetBinLabel(9, "QCDcut") + self.CutFlowTable.GetXaxis().SetBinLabel(10, "Smartcut") + self.CutFlowTable.GetXaxis().SetBinLabel(11, "MZ1MZ2cut") + self.CutFlowTable.GetXaxis().SetBinLabel(12, "M4Lcut") + self.CutFlowTable.GetXaxis().SetBinLabel(13, "SR") + self.CutFlowTable.GetXaxis().SetBinLabel(14, "CR") + self.CutFlowTable.GetXaxis().SetBinLabel(15, "3Lepton") + self.CutFlowTable.GetXaxis().SetBinLabel(16, "properID_3lep") + self.CutFlowTable.GetXaxis().SetBinLabel(17, "3LepDRcut") + self.CutFlowTable.GetXaxis().SetBinLabel(18, "3LepPtcut") + self.CutFlowTable.GetXaxis().SetBinLabel(19, "3LepQCDcut") + self.CutFlowTable.GetXaxis().SetBinLabel(20, "3LepTightZ1cut") + + self.worker = ROOT.H4LTools(self.year, self.isMC) + self._initialize_worker(self.cfg) + self.worker.isFSR = isFSR + self._initialize_counters() + self.worker.isFiducialAna = isFiducialAna + pass + + def loadLibraries(self): + base_path = os.getenv('CMSSW_BASE') + '/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim' + yaml_cpp_path = os.path.join(base_path, "external/yaml-cpp") + + # Adding yaml-cpp headers to the include path ROOT.gSystem.AddIncludePath("-I%s/include" % yaml_cpp_path) + libraries = [ + 'libmcfm_710.so', + 'libJHUGenMELAMELA.so', + 'libjhugenmela.so', + 'libcollier.so', + ] + for lib in libraries: + fullPath = os.path.join(base_path, 'JHUGenMELA/MELA/data/el9_amd64_gcc12', lib) + ROOT.gSystem.Load(fullPath) + + # Load the yaml-cpp library yaml_cpp_lib_path = os.path.join(yaml_cpp_path, "build") ROOT.gSystem.Load(os.path.join(yaml_cpp_lib_path, "libyaml-cpp.so")) + + # Load the C++ module if "/H4LTools_cc.so" not in ROOT.gSystem.GetLibraries(): print("Load H4LTools C++ module") - base = "$CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim" - if base: + if base_path: ROOT.gROOT.ProcessLine( - ".L %s/src/H4LTools.cc+O" % base) + ".L %s/src/H4LTools.cc+O" % base_path) else: - base = "$CMSSW_BASE//src/PhysicsTools/NanoAODTools" + base_path = "$CMSSW_BASE//src/PhysicsTools/NanoAODTools" ROOT.gSystem.Load("libPhysicsToolsNanoAODTools.so") ROOT.gROOT.ProcessLine( - ".L %s/interface/H4LTools.h" % base) - self.year = year - self.isMC = isMC - self.DEBUG = DEBUG - self.CutFlowTable = ROOT.TH1F('cutFlow','cutFlow',18, -0.5, 17.5) + ".L %s/interface/H4LTools.h" % base_path) + + def _load_config(self, cfgFile): with open(cfgFile, 'r') as ymlfile: - cfg = yaml.load(ymlfile) - self.worker = ROOT.H4LTools(self.year,self.isMC) - self.worker.InitializeElecut(cfg['Electron']['pTcut'],cfg['Electron']['Etacut'],cfg['Electron']['Sip3dcut'],cfg['Electron']['Loosedxycut'],cfg['Electron']['Loosedzcut'], - cfg['Electron']['Isocut'],cfg['Electron']['BDTWP']['LowEta']['LowPT'],cfg['Electron']['BDTWP']['MedEta']['LowPT'],cfg['Electron']['BDTWP']['HighEta']['LowPT'], - cfg['Electron']['BDTWP']['LowEta']['HighPT'],cfg['Electron']['BDTWP']['MedEta']['HighPT'],cfg['Electron']['BDTWP']['HighEta']['HighPT']) - self.worker.InitializeMucut(cfg['Muon']['pTcut'],cfg['Muon']['Etacut'],cfg['Muon']['Sip3dcut'],cfg['Muon']['Loosedxycut'],cfg['Muon']['Loosedzcut'],cfg['Muon']['Isocut'], - cfg['Muon']['Tightdxycut'],cfg['Muon']['Tightdzcut'],cfg['Muon']['TightTrackerLayercut'],cfg['Muon']['TightpTErrorcut'],cfg['Muon']['HighPtBound']) - self.worker.InitializeFsrPhotonCut(cfg['FsrPhoton']['pTcut'],cfg['FsrPhoton']['Etacut'],cfg['FsrPhoton']['Isocut'],cfg['FsrPhoton']['dRlcut'],cfg['FsrPhoton']['dRlOverPtcut']) - self.worker.InitializeJetcut(cfg['Jet']['pTcut'],cfg['Jet']['Etacut']) - self.worker.InitializeEvtCut(cfg['MZ1cut'],cfg['MZZcut'],cfg['Higgscut']['down'],cfg['Higgscut']['up'],cfg['Zmass'],cfg['MZcut']['down'],cfg['MZcut']['up']) + return yaml.safe_load(ymlfile) + + def _initialize_worker(self, cfg): + self.worker.InitializeElecut(cfg['Electron']['pTcut'],cfg['Electron']['Etacut'],cfg['Electron']['Sip3dcut'],cfg['Electron']['Loosedxycut'],cfg['Electron']['Loosedzcut'], + cfg['Electron']['Isocut'],cfg['Electron']['BDTWP']['LowEta']['LowPT'],cfg['Electron']['BDTWP']['MedEta']['LowPT'],cfg['Electron']['BDTWP']['HighEta']['LowPT'], + cfg['Electron']['BDTWP']['LowEta']['HighPT'],cfg['Electron']['BDTWP']['MedEta']['HighPT'],cfg['Electron']['BDTWP']['HighEta']['HighPT']) + self.worker.InitializeMucut(cfg['Muon']['pTcut'],cfg['Muon']['Etacut'],cfg['Muon']['Sip3dcut'],cfg['Muon']['Loosedxycut'],cfg['Muon']['Loosedzcut'],cfg['Muon']['Isocut'], + cfg['Muon']['Tightdxycut'],cfg['Muon']['Tightdzcut'],cfg['Muon']['TightTrackerLayercut'],cfg['Muon']['TightpTErrorcut'],cfg['Muon']['HighPtBound']) + self.worker.InitializeFsrPhotonCut(cfg['FsrPhoton']['pTcut'],cfg['FsrPhoton']['Etacut'],cfg['FsrPhoton']['Isocut'],cfg['FsrPhoton']['dRlcut'],cfg['FsrPhoton']['dRlOverPtcut']) + self.worker.InitializeJetcut(cfg['Jet']['pTcut'],cfg['Jet']['Etacut']) + self.worker.InitializeEvtCut(cfg['MZ1cut'],cfg['MZZcut'],cfg['Higgscut']['down'],cfg['Higgscut']['up'],cfg['Zmass'],cfg['MZcut']['down'],cfg['MZcut']['up']) + + def _get_nested_values(self, dictionary, keys): + values = [] + for key in keys: + if isinstance(key, list): + sub_dict = dictionary + for sub_key in key: + sub_dict = sub_dict.get(sub_key, {}) + values.append(sub_dict if sub_dict else 'N/A') + else: + values.append(dictionary.get(key, 'N/A')) + return values + def _initialize_counters(self): + self.passAllEvts = 0 self.passtrigEvts = 0 + self.passMETFilters = 0 + self.passZZ4lEvts = 0 + self.passZZ2l2qEvts = 0 + self.passZZ2l2nuEvts = 0 + self.passZZ2l2nu_emuCR_Evts = 0 self.passZZEvts = 0 - self.cfgFile = cfgFile - self.worker.isFSR = isFSR - self.worker.isFiducialAna = isFiducialAna - pass + def beginJob(self): pass @@ -81,6 +142,9 @@ def endJob(self): def beginFile(self, inputFile, outputFile, inputTree, wrappedOutputTree): self.initReaders(inputTree) # initReaders must be called in beginFile self.out = wrappedOutputTree + # Boolean branches for Trigger channels + for TriggerChannel in self.cfg['TriggerChannels']: + self.out.branch(TriggerChannel, "O") self.out.branch("mass4l", "F") self.out.branch("mass4e", "F") self.out.branch("mass4mu", "F") @@ -235,12 +299,21 @@ def analyze(self, event): phi4l = -99 mass4l = 0 rapidity4l = -99 - passedTrig = PassTrig(event, self.cfgFile) - if (passedTrig==True): - self.passtrigEvts += 1 - #keepIt = True - else: + + TriggerMap = {} + passedTrig = False + for TriggerChannel in self.cfg['TriggerChannels']: + TriggerMap[TriggerChannel] = PassTrig(event, self.cfg, TriggerChannel) + + # If any of the trigger channel from TriggerMap passes, then the event is kept else return keepIt + for value in TriggerMap.values(): + if value: + passedTrig = True + break + if not passedTrig: return keepIt + self.passtrigEvts += 1 + electrons = Collection(event, "Electron") muons = Collection(event, "Muon") fsrPhotons = Collection(event, "FsrPhoton") @@ -356,7 +429,7 @@ def analyze(self, event): lep_matchedR03_MomId.append(lep_matchedR03_MomId_vec[i]) lep_matchedR03_MomMomId.append(lep_matchedR03_MomMomId_vec[i]) lep_RelIsoNoFSR.append(lep_RelIsoNoFSR_vec[i]) - + if (foundZZCandidate): self.passZZEvts += 1 pTZ1 = self.worker.Z1.Pt() @@ -459,7 +532,10 @@ def analyze(self, event): mass4l = self.worker.mass4l rapidity4l = self.worker.ZZsystemnofsr.Rapidity() - + + # Fill the branches with the Trigger information for each channel + for TriggerChannel in self.cfg['TriggerChannels']: + self.out.fillBranch(TriggerChannel, TriggerMap[TriggerChannel]) self.out.fillBranch("mass4l",mass4l) self.out.fillBranch("mass4e",mass4e) self.out.fillBranch("mass2e2mu",mass2e2mu) @@ -544,8 +620,8 @@ def analyze(self, event): self.out.fillBranch("lep_matchedR03_MomId", lep_matchedR03_MomId) self.out.fillBranch("lep_matchedR03_PdgId", lep_matchedR03_PdgId) self.out.fillBranch("lep_matchedR03_MomMomId", lep_matchedR03_MomMomId) - - + + # self.out.fillBranch("nElectron_Fsr", len(electrons)) # self.out.fillBranch("nMuon_Fsr", len(muons)) diff --git a/Helper.py b/Helper.py index d5ee4c2..a644c67 100644 --- a/Helper.py +++ b/Helper.py @@ -2,16 +2,12 @@ import yaml PI=3.14159 -def PassTrig(event,cfgFile): - - +def PassTrig(event, cfg, TriggerCh): PassTrig = False - with open(cfgFile, 'r') as ymlfile: - cfg = yaml.load(ymlfile) - TriggerList = [] - for TriggerName in cfg['Triggers']: - TriggerList.append(eval(TriggerName)) - + TriggerList = [] + for TriggerName in cfg[TriggerCh]: + TriggerList.append(eval(TriggerName)) + for i in range(len(TriggerList)): PassTrig = PassTrig | TriggerList[i] @@ -88,7 +84,7 @@ def passTight_BDT_Id(electrons,year = '2018'): Tight_Id = [] cutVal = 1000 mvaVal = -1 - + for x in electrons: if (year == '2018'): if (x.pt<=10): @@ -101,7 +97,7 @@ def passTight_BDT_Id(electrons,year = '2018'): if (abs(x.eta) >= 1.479): cutVal = -0.5169136775 mvaVal = x.mvaFall17V2Iso_WP90 - + if (year == '2017'): if (x.pt<=10): if (abs(x.eta) < 0.8): cutVal = 0.9128577458 @@ -111,7 +107,7 @@ def passTight_BDT_Id(electrons,year = '2018'): if (abs(x.eta) < 0.8): cutVal = 0.1559788054 if ((abs(x.eta) >= 0.8)&(abs(x.eta) <1.479)): cutVal = 0.0273863727 if (abs(x.eta) >= 1.479): cutVal = -0.5532483665 - + mvaVal = x.mvaFall17V2Iso_WP90 if (year == '2016'): if (x.pt<=10): @@ -122,14 +118,14 @@ def passTight_BDT_Id(electrons,year = '2018'): if (abs(x.eta) < 0.8): cutVal = 0.3272075608 if ((abs(x.eta) >= 0.8)&(abs(x.eta) <1.479)): cutVal = 0.2468345995 if (abs(x.eta) >= 1.479): cutVal = -0.5955762814 - + mvaVal = x.mvaFall17V2Iso_WP90 if mvaVal > cutVal: Tight_Id.append(True) else: Tight_Id.append(False) - + return Tight_Id def passTight_Id(muons): @@ -140,4 +136,4 @@ def passTight_Id(muons): else: Tight_Id.append(((x.ptErr/x.pt)<0.3)&(abs(x.dxy)<0.2)&(abs(x.dz)<0.5)&(x.nTrackerLayers>5)|x.isPFcand) - return Tight_Id \ No newline at end of file + return Tight_Id diff --git a/Input_2022.yml b/Input_2022.yml index d6921f3..04a082e 100644 --- a/Input_2022.yml +++ b/Input_2022.yml @@ -1,4 +1,7 @@ -Triggers: +TriggerChannels: + - Triggers_HZZ4l + +Triggers_HZZ4l: - event.HLT_Ele23_Ele12_CaloIdL_TrackIdL_IsoVL - event.HLT_DoubleEle25_CaloIdL_MW - event.HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ_Mass3p8 @@ -44,7 +47,7 @@ Electron: LowEta: LowPT: 0.926614978724 - HighPT: + HighPT: 0.352678981617 MedEta: LowPT: diff --git a/README.md b/README.md index 03f2ca4..1db9347 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. 1. Step: 1: Get CMSSW release ```bash - cmsrel CMSSW_10_6_30 - cd CMSSW_10_6_30/src + cmsrel CMSSW_14_0_2 + cd CMSSW_14_0_2/src cmsenv ``` @@ -16,7 +16,7 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. ```bash git clone git@github.com:cms-nanoAOD/nanoAOD-tools.git PhysicsTools/NanoAODTools cd PhysicsTools/NanoAODTools - git checkout 65359982275c476834ad4b37363d658166881f12 # Updated to commit on 16 June 2023 in official nanoAOD-tools + git checkout d163c18096fe2c5963ff5a9764bb420b46632178 # Updated to commit on 6 Dec 2023 in official nanoAOD-tools ``` 3. Step: 3: Get our analysis repository @@ -26,9 +26,17 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. git clone git@github.com:ram1123/nanoAOD_skim.git PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim cd PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim git checkout ZXCR - cd - - cmsenv - # patch PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim/nanoAOD_tools.patch + cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools + git apply python/postprocessing/analysis/nanoAOD_skim/external/nanoAODTools_py2to3.patch + cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim + git clone git@github.com:jbeder/yaml-cpp.git external/yaml-cpp + cd external/yaml-cpp/ + git apply ../yamlcpp_pkg_py2to3.patch + mkdir build + cd build + cmake3 .. -DBUILD_SHARED_LIBS=ON + cmake3 --build . + cd $CMSSW_BASE/src cp PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim/data/btag/*.csv PhysicsTools/NanoAODTools/data/btagSF/. scram b voms-proxy-init --voms cms --valid 168:00 @@ -44,17 +52,22 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. ```bash cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim - git clone -b v2.3.5 https://github.com/JHUGen/JHUGenMELA + git clone -b v2.4.2 https://github.com/JHUGen/JHUGenMELA + cd JHUGenMELA + git apply ../external/JHUGen_py2to3.patch + cd .. sh JHUGenMELA/MELA/setup.sh -j 8 - cd JHUGenMELA/MELA - make + cd JHUGenMELA/MELA/data/el9_amd64_gcc12/ + chmod +x *.so ``` 4. Step: 4: interactive running ```bash cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim - python post_proc.py + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/afs/cern.ch/work/r/rasharma/h2l2nu/checkNewSetup_15July2024/CMSSW_14_0_2/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim/JHUGenMELA/MELA/data/el9_amd64_gcc12 + # NOTE: The above export command is needed to run just before running the post_proc.py script. Otherwise, it will give error. + python3 post_proc.py ``` 5. batch job submission. diff --git a/external/JHUGen_py2to3.patch b/external/JHUGen_py2to3.patch new file mode 100644 index 0000000..cc56900 --- /dev/null +++ b/external/JHUGen_py2to3.patch @@ -0,0 +1,55 @@ +diff --git a/MELA/makefile b/MELA/makefile +index a7d3b07..c1490c2 100644 +--- a/MELA/makefile ++++ b/MELA/makefile +@@ -19,7 +19,8 @@ MELADIR = $(shell pwd) + MELASRCDIR = $(MELADIR)/src + MELAOBJDIR = $(MELADIR)/obj + # Modify MELALIBDIR for the gcc version as needed +-MELALIBDIR = ${MELA_LIB_PATH} ++# MELALIBDIR = ${MELA_LIB_PATH} ++MELALIBDIR = "./data/el9_amd64_gcc12/" + # _melapkgpath_ should refer to the root compilation path just like MELADIR with an extra '/'. + # If environment variables need to be inserted without expansion for portability, + # you can use '.oODOLLAROo..oOOPEN_BRACKETOo.[YOUR_ENV_VARIABLE].oOCLOSE_BRACKETOo.', +diff --git a/MELA/test/batch.py b/MELA/test/batch.py +index e19b07b..f9c4e15 100755 +--- a/MELA/test/batch.py ++++ b/MELA/test/batch.py +@@ -2,12 +2,12 @@ + + import os + import sys +-import commands ++import subprocess + + from ROOT import TFile + + def processDirectory ( args, dirname, filenames ): +- print "processing " + dirname ++ print("processing " + dirname) + for filename in filenames: + fullname = dirname + "/" + filename + +@@ -55,18 +55,18 @@ def processDirectory ( args, dirname, filenames ): + + + +- print " " * 4 + filename + " with flavor " + str(flavor) + " and sqrts = " + str(sqrts) ++ print(" " * 4 + filename + " with flavor " + str(flavor) + " and sqrts = " + str(sqrts)) + + + + if flavor!=10: # looks like a valid file, prepare string + command = "root -q -b addProbtoTree.C\\(\\\"" + fullname[:-5] + "\\\","+str(flavor)+",-1,"+str(sqrts)+"\\)\n" + #create batch script +- commands.getstatusoutput("cp batchscript.csh batchscript_tmp.csh") ++ subprocess.getstatusoutput("cp batchscript.csh batchscript_tmp.csh") + file = open('batchscript_tmp.csh', 'a') + file.write(command) + file.close() +- commands.getstatusoutput("bsub -q 8nh < batchscript_tmp.csh" ) ++ subprocess.getstatusoutput("bsub -q 8nh < batchscript_tmp.csh" ) + #exit(0) + + diff --git a/external/nanoAODTools_py2to3.patch b/external/nanoAODTools_py2to3.patch new file mode 100644 index 0000000..e7885d9 --- /dev/null +++ b/external/nanoAODTools_py2to3.patch @@ -0,0 +1,129 @@ +diff --git a/python/postprocessing/examples/exampleAnalysis.py b/python/postprocessing/examples/exampleAnalysis.py +index 28cb45f..1824684 100644 +--- a/python/postprocessing/examples/exampleAnalysis.py ++++ b/python/postprocessing/examples/exampleAnalysis.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + from PhysicsTools.NanoAODTools.postprocessing.framework.eventloop import Module + from PhysicsTools.NanoAODTools.postprocessing.framework.datamodel import Collection + from PhysicsTools.NanoAODTools.postprocessing.framework.postprocessor import PostProcessor +diff --git a/python/postprocessing/examples/example_postproc.py b/python/postprocessing/examples/example_postproc.py +index 1ace02c..3e7a495 100644 +--- a/python/postprocessing/examples/example_postproc.py ++++ b/python/postprocessing/examples/example_postproc.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + from exampleModule import * + from PhysicsTools.NanoAODTools.postprocessing.modules.jme.jetmetHelperRun2 import * + from PhysicsTools.NanoAODTools.postprocessing.modules.jme.jetmetUncertainties import * +diff --git a/python/postprocessing/framework/crabhelper.py b/python/postprocessing/framework/crabhelper.py +index 405b055..53613a7 100644 +--- a/python/postprocessing/framework/crabhelper.py ++++ b/python/postprocessing/framework/crabhelper.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + import os + from PhysicsTools.NanoAODTools.postprocessing.framework.postprocessor import * + import sys +diff --git a/python/postprocessing/framework/postprocessor.py b/python/postprocessing/framework/postprocessor.py +index c7cc3ca..ea54b4a 100755 +--- a/python/postprocessing/framework/postprocessor.py ++++ b/python/postprocessing/framework/postprocessor.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + from PhysicsTools.NanoAODTools.postprocessing.framework.jobreport import JobReport + from PhysicsTools.NanoAODTools.postprocessing.framework.preskimming import preSkim + from PhysicsTools.NanoAODTools.postprocessing.framework.output import FriendOutput, FullOutput +@@ -261,8 +261,18 @@ class PostProcessor: + if self.haddFileName: + haddnano = "./haddnano.py" if os.path.isfile( + "./haddnano.py") else "haddnano.py" ++ print("Merging output files into %s" % self.haddFileName) ++ print("") ++ os.system('date') ++ startTime = time.time() ++ print("%s %s %s" % ++ (haddnano, self.outputDir + "/" + self.haddFileName, " ".join(outFileNames))) + os.system("%s %s %s" % +- (haddnano, self.haddFileName, " ".join(outFileNames))) ++ (haddnano, self.outputDir + "/" + self.haddFileName, " ".join(outFileNames))) ++ os.system('date') ++ print("Total time to merge %i files: %.1f sec" % ++ (len(outFileNames), time.time() - startTime)) ++ print("Done") + if self.jobReport: +- self.jobReport.addOutputFile(self.haddFileName) ++ self.jobReport.addOutputFile( self.outputDir + "/" + self.haddFileName) + self.jobReport.save() +diff --git a/python/postprocessing/modules/common/puWeightProducer.py b/python/postprocessing/modules/common/puWeightProducer.py +index b9062b4..7c5a1da 100644 +--- a/python/postprocessing/modules/common/puWeightProducer.py ++++ b/python/postprocessing/modules/common/puWeightProducer.py +@@ -59,8 +59,13 @@ class puWeightProducer(Module): + + def loadHisto(self, filename, hname): + tf = ROOT.TFile.Open(filename) ++ if not tf or tf.IsZombie(): ++ raise IOError(f"Cannot open file: {filename}") + hist = tf.Get(hname) +- hist.SetDirectory(None) ++ if not hist: ++ raise IOError(f"Cannot find histogram {hname} in file: {filename}") ++ ++ hist.SetDirectory(0) # With Python3/EL9 "None" is not working. So, replaced "None" with "0" + tf.Close() + return hist + +diff --git a/python/postprocessing/modules/jme/jetmetHelperRun2.py b/python/postprocessing/modules/jme/jetmetHelperRun2.py +index d38c623..9d07645 100644 +--- a/python/postprocessing/modules/jme/jetmetHelperRun2.py ++++ b/python/postprocessing/modules/jme/jetmetHelperRun2.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + import os + import sys + import subprocess +@@ -107,7 +107,7 @@ jmsValues = { + 'UL2016': [1.000, 1.000, 1.000], # placeholder + 'UL2017': [1.000, 1.000, 1.000], # placeholder + 'UL2018': [1.000, 1.000, 1.000], # placeholder +-} ++} + + + def createJMECorrector(isMC=True, +diff --git a/scripts/haddnano.py b/scripts/haddnano.py +index 96d7d11..82ac1dc 100755 +--- a/scripts/haddnano.py ++++ b/scripts/haddnano.py +@@ -1,4 +1,4 @@ +-#!/bin/env python ++#!/usr/bin/env python3 + import ROOT + import numpy + import sys +diff --git a/scripts/nano_postproc.py b/scripts/nano_postproc.py +index acd5c80..e788c10 100755 +--- a/scripts/nano_postproc.py ++++ b/scripts/nano_postproc.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + from PhysicsTools.NanoAODTools.postprocessing.framework.postprocessor import PostProcessor + from importlib import import_module + import os +diff --git a/scripts/nano_report.py b/scripts/nano_report.py +index e54b55b..e162a9a 100644 +--- a/scripts/nano_report.py ++++ b/scripts/nano_report.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + # imported from https://github.com/CERN-PH-CMG/cmg-cmssw/blob/0c11a5a0a15c4c3e1a648c9707b06b08b747b0c0/PhysicsTools/Heppy/scripts/heppy_report.py + from optparse import OptionParser + import json diff --git a/external/yaml-cpp b/external/yaml-cpp deleted file mode 160000 index b95aa14..0000000 --- a/external/yaml-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b95aa146ec3226f31b7b75bef1b5f750af25fb8a diff --git a/external/yamlcpp_pkg_py2to3.patch b/external/yamlcpp_pkg_py2to3.patch new file mode 100644 index 0000000..f19fa3d --- /dev/null +++ b/external/yamlcpp_pkg_py2to3.patch @@ -0,0 +1,465 @@ +diff --git a/test/gtest-1.11.0/googletest/scripts/gen_gtest_pred_impl.py b/test/gtest-1.11.0/googletest/scripts/gen_gtest_pred_impl.py +index e09a6e0..95c8574 100755 +--- a/test/gtest-1.11.0/googletest/scripts/gen_gtest_pred_impl.py ++++ b/test/gtest-1.11.0/googletest/scripts/gen_gtest_pred_impl.py +@@ -184,7 +184,7 @@ def Title(word): + def OneTo(n): + """Returns the list [1, 2, 3, ..., n].""" + +- return range(1, n + 1) ++ return list(range(1, n + 1)) + + + def Iter(n, format, sep=''): +@@ -308,12 +308,12 @@ def GenerateFile(path, content): + """Given a file path and a content string + overwrites it with the given content. + """ +- print 'Updating file %s . . .' % path ++ print('Updating file %s . . .' % path) + f = file(path, 'w+') +- print >>f, content, ++ print(content, end=' ', file=f) + f.close() + +- print 'File %s has been updated.' % path ++ print('File %s has been updated.' % path) + + + def GenerateHeader(n): +@@ -720,8 +720,8 @@ def _Main(): + unit test.""" + + if len(sys.argv) != 2: +- print __doc__ +- print 'Author: ' + __author__ ++ print(__doc__) ++ print('Author: ' + __author__) + sys.exit(1) + + n = int(sys.argv[1]) +diff --git a/test/gtest-1.11.0/googletest/scripts/release_docs.py b/test/gtest-1.11.0/googletest/scripts/release_docs.py +index 8d24f28..05b15fd 100755 +--- a/test/gtest-1.11.0/googletest/scripts/release_docs.py ++++ b/test/gtest-1.11.0/googletest/scripts/release_docs.py +@@ -127,11 +127,11 @@ class WikiBrancher(object): + def BranchFiles(self): + """Branches the .wiki files needed to be branched.""" + +- print 'Branching %d .wiki files:' % (len(self.files_to_branch),) ++ print('Branching %d .wiki files:' % (len(self.files_to_branch),)) + os.chdir(self.wiki_dir) + for f in self.files_to_branch: + command = 'svn cp %s %s%s' % (f, self.version_prefix, f) +- print command ++ print(command) + os.system(command) + + def UpdateLinksInBranchedFiles(self): +@@ -139,7 +139,7 @@ class WikiBrancher(object): + for f in self.files_to_branch: + source_file = os.path.join(self.wiki_dir, f) + versioned_file = os.path.join(self.wiki_dir, self.version_prefix + f) +- print 'Updating links in %s.' % (versioned_file,) ++ print('Updating links in %s.' % (versioned_file,)) + text = file(source_file, 'r').read() + new_text = self.search_for_re.sub(self.replace_with, text) + file(versioned_file, 'w').write(new_text) +diff --git a/test/gtest-1.11.0/googletest/scripts/upload.py b/test/gtest-1.11.0/googletest/scripts/upload.py +index eba5711..786c281 100755 +--- a/test/gtest-1.11.0/googletest/scripts/upload.py ++++ b/test/gtest-1.11.0/googletest/scripts/upload.py +@@ -46,7 +46,7 @@ against by using the '--rev' option. + # This code is derived from appcfg.py in the App Engine SDK (open source), + # and from ASPN recipe #146306. + +-import cookielib ++import http.cookiejar + import getpass + import logging + import md5 +@@ -57,9 +57,9 @@ import re + import socket + import subprocess + import sys +-import urllib +-import urllib2 +-import urlparse ++import urllib.request, urllib.parse, urllib.error ++import urllib.request, urllib.error, urllib.parse ++import urllib.parse + + try: + import readline +@@ -94,15 +94,15 @@ def GetEmail(prompt): + last_email = last_email_file.readline().strip("\n") + last_email_file.close() + prompt += " [%s]" % last_email +- except IOError, e: ++ except IOError as e: + pass +- email = raw_input(prompt + ": ").strip() ++ email = input(prompt + ": ").strip() + if email: + try: + last_email_file = open(last_email_file_name, "w") + last_email_file.write(email) + last_email_file.close() +- except IOError, e: ++ except IOError as e: + pass + else: + email = last_email +@@ -118,20 +118,20 @@ def StatusUpdate(msg): + msg: The string to print. + """ + if verbosity > 0: +- print msg ++ print(msg) + + + def ErrorExit(msg): + """Print an error message to stderr and exit.""" +- print >>sys.stderr, msg ++ print(msg, file=sys.stderr) + sys.exit(1) + + +-class ClientLoginError(urllib2.HTTPError): ++class ClientLoginError(urllib.error.HTTPError): + """Raised to indicate there was an error authenticating with ClientLogin.""" + + def __init__(self, url, code, msg, headers, args): +- urllib2.HTTPError.__init__(self, url, code, msg, headers, None) ++ urllib.error.HTTPError.__init__(self, url, code, msg, headers, None) + self.args = args + self.reason = args["Error"] + +@@ -177,10 +177,10 @@ class AbstractRpcServer(object): + def _CreateRequest(self, url, data=None): + """Creates a new urllib request.""" + logging.debug("Creating request for: '%s' with payload:\n%s", url, data) +- req = urllib2.Request(url, data=data) ++ req = urllib.request.Request(url, data=data) + if self.host_override: + req.add_header("Host", self.host_override) +- for key, value in self.extra_headers.iteritems(): ++ for key, value in self.extra_headers.items(): + req.add_header(key, value) + return req + +@@ -204,7 +204,7 @@ class AbstractRpcServer(object): + account_type = "HOSTED" + req = self._CreateRequest( + url="https://www.google.com/accounts/ClientLogin", +- data=urllib.urlencode({ ++ data=urllib.parse.urlencode({ + "Email": email, + "Passwd": password, + "service": "ah", +@@ -218,7 +218,7 @@ class AbstractRpcServer(object): + response_dict = dict(x.split("=") + for x in response_body.split("\n") if x) + return response_dict["Auth"] +- except urllib2.HTTPError, e: ++ except urllib.error.HTTPError as e: + if e.code == 403: + body = e.read() + response_dict = dict(x.split("=", 1) for x in body.split("\n") if x) +@@ -240,14 +240,14 @@ class AbstractRpcServer(object): + continue_location = "http://localhost/" + args = {"continue": continue_location, "auth": auth_token} + req = self._CreateRequest("http://%s/_ah/login?%s" % +- (self.host, urllib.urlencode(args))) ++ (self.host, urllib.parse.urlencode(args))) + try: + response = self.opener.open(req) +- except urllib2.HTTPError, e: ++ except urllib.error.HTTPError as e: + response = e + if (response.code != 302 or + response.info()["location"] != continue_location): +- raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg, ++ raise urllib.error.HTTPError(req.get_full_url(), response.code, response.msg, + response.headers, response.fp) + self.authenticated = True + +@@ -270,34 +270,34 @@ class AbstractRpcServer(object): + credentials = self.auth_function() + try: + auth_token = self._GetAuthToken(credentials[0], credentials[1]) +- except ClientLoginError, e: ++ except ClientLoginError as e: + if e.reason == "BadAuthentication": +- print >>sys.stderr, "Invalid username or password." ++ print("Invalid username or password.", file=sys.stderr) + continue + if e.reason == "CaptchaRequired": +- print >>sys.stderr, ( ++ print(( + "Please go to\n" + "https://www.google.com/accounts/DisplayUnlockCaptcha\n" +- "and verify you are a human. Then try again.") ++ "and verify you are a human. Then try again."), file=sys.stderr) + break + if e.reason == "NotVerified": +- print >>sys.stderr, "Account not verified." ++ print("Account not verified.", file=sys.stderr) + break + if e.reason == "TermsNotAgreed": +- print >>sys.stderr, "User has not agreed to TOS." ++ print("User has not agreed to TOS.", file=sys.stderr) + break + if e.reason == "AccountDeleted": +- print >>sys.stderr, "The user account has been deleted." ++ print("The user account has been deleted.", file=sys.stderr) + break + if e.reason == "AccountDisabled": +- print >>sys.stderr, "The user account has been disabled." ++ print("The user account has been disabled.", file=sys.stderr) + break + if e.reason == "ServiceDisabled": +- print >>sys.stderr, ("The user's access to the service has been " +- "disabled.") ++ print(("The user's access to the service has been " ++ "disabled."), file=sys.stderr) + break + if e.reason == "ServiceUnavailable": +- print >>sys.stderr, "The service is not available; try again later." ++ print("The service is not available; try again later.", file=sys.stderr) + break + raise + self._GetAuthCookie(auth_token) +@@ -334,7 +334,7 @@ class AbstractRpcServer(object): + args = dict(kwargs) + url = "http://%s%s" % (self.host, request_path) + if args: +- url += "?" + urllib.urlencode(args) ++ url += "?" + urllib.parse.urlencode(args) + req = self._CreateRequest(url=url, data=payload) + req.add_header("Content-Type", content_type) + try: +@@ -342,7 +342,7 @@ class AbstractRpcServer(object): + response = f.read() + f.close() + return response +- except urllib2.HTTPError, e: ++ except urllib.error.HTTPError as e: + if tries > 3: + raise + elif e.code == 401: +@@ -372,35 +372,35 @@ class HttpRpcServer(AbstractRpcServer): + Returns: + A urllib2.OpenerDirector object. + """ +- opener = urllib2.OpenerDirector() +- opener.add_handler(urllib2.ProxyHandler()) +- opener.add_handler(urllib2.UnknownHandler()) +- opener.add_handler(urllib2.HTTPHandler()) +- opener.add_handler(urllib2.HTTPDefaultErrorHandler()) +- opener.add_handler(urllib2.HTTPSHandler()) ++ opener = urllib.request.OpenerDirector() ++ opener.add_handler(urllib.request.ProxyHandler()) ++ opener.add_handler(urllib.request.UnknownHandler()) ++ opener.add_handler(urllib.request.HTTPHandler()) ++ opener.add_handler(urllib.request.HTTPDefaultErrorHandler()) ++ opener.add_handler(urllib.request.HTTPSHandler()) + opener.add_handler(urllib2.HTTPErrorProcessor()) + if self.save_cookies: + self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies") +- self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file) ++ self.cookie_jar = http.cookiejar.MozillaCookieJar(self.cookie_file) + if os.path.exists(self.cookie_file): + try: + self.cookie_jar.load() + self.authenticated = True + StatusUpdate("Loaded authentication cookies from %s" % + self.cookie_file) +- except (cookielib.LoadError, IOError): ++ except (http.cookiejar.LoadError, IOError): + # Failed to load cookies - just ignore them. + pass + else: + # Create an empty cookie file with mode 600 +- fd = os.open(self.cookie_file, os.O_CREAT, 0600) ++ fd = os.open(self.cookie_file, os.O_CREAT, 0o600) + os.close(fd) + # Always chmod the cookie file +- os.chmod(self.cookie_file, 0600) ++ os.chmod(self.cookie_file, 0o600) + else: + # Don't save cookies across runs of update.py. +- self.cookie_jar = cookielib.CookieJar() +- opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) ++ self.cookie_jar = http.cookiejar.CookieJar() ++ opener.add_handler(urllib.request.HTTPCookieProcessor(self.cookie_jar)) + return opener + + +@@ -575,7 +575,7 @@ def RunShellWithReturnCode(command, print_output=False, + line = p.stdout.readline() + if not line: + break +- print line.strip("\n") ++ print(line.strip("\n")) + output_array.append(line) + output = "".join(output_array) + else: +@@ -583,7 +583,7 @@ def RunShellWithReturnCode(command, print_output=False, + p.wait() + errout = p.stderr.read() + if print_output and errout: +- print >>sys.stderr, errout ++ print(errout, file=sys.stderr) + p.stdout.close() + p.stderr.close() + return output, p.returncode +@@ -629,11 +629,11 @@ class VersionControlSystem(object): + """Show an "are you sure?" prompt if there are unknown files.""" + unknown_files = self.GetUnknownFiles() + if unknown_files: +- print "The following files are not added to version control:" ++ print("The following files are not added to version control:") + for line in unknown_files: +- print line ++ print(line) + prompt = "Are you sure to continue?(y/N) " +- answer = raw_input(prompt).strip() ++ answer = input(prompt).strip() + if answer != "y": + ErrorExit("User aborted") + +@@ -685,13 +685,13 @@ class VersionControlSystem(object): + else: + type = "current" + if len(content) > MAX_UPLOAD_SIZE: +- print ("Not uploading the %s file for %s because it's too large." % +- (type, filename)) ++ print(("Not uploading the %s file for %s because it's too large." % ++ (type, filename))) + file_too_large = True + content = "" + checksum = md5.new(content).hexdigest() + if options.verbose > 0 and not file_too_large: +- print "Uploading %s file for %s" % (type, filename) ++ print("Uploading %s file for %s" % (type, filename)) + url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id) + form_fields = [("filename", filename), + ("status", status), +@@ -713,7 +713,7 @@ class VersionControlSystem(object): + + patches = dict() + [patches.setdefault(v, k) for k, v in patch_list] +- for filename in patches.keys(): ++ for filename in list(patches.keys()): + base_content, new_content, is_binary, status = files[filename] + file_id_str = patches.get(filename) + if file_id_str.find("nobase") != -1: +@@ -770,8 +770,8 @@ class SubversionVCS(VersionControlSystem): + words = line.split() + if len(words) == 2 and words[0] == "URL:": + url = words[1] +- scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) +- username, netloc = urllib.splituser(netloc) ++ scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) ++ username, netloc = urllib.parse.splituser(netloc) + if username: + logging.info("Removed username from base URL") + if netloc.endswith("svn.python.org"): +@@ -789,12 +789,12 @@ class SubversionVCS(VersionControlSystem): + logging.info("Guessed CollabNet base = %s", base) + elif netloc.endswith(".googlecode.com"): + path = path + "/" +- base = urlparse.urlunparse(("http", netloc, path, params, ++ base = urllib.parse.urlunparse(("http", netloc, path, params, + query, fragment)) + logging.info("Guessed Google Code base = %s", base) + else: + path = path + "/" +- base = urlparse.urlunparse((scheme, netloc, path, params, ++ base = urllib.parse.urlunparse((scheme, netloc, path, params, + query, fragment)) + logging.info("Guessed base = %s", base) + return base +@@ -1202,8 +1202,8 @@ def UploadSeparatePatches(issue, rpc_server, patchset, data, options): + rv = [] + for patch in patches: + if len(patch[1]) > MAX_UPLOAD_SIZE: +- print ("Not uploading the patch for " + patch[0] + +- " because the file is too large.") ++ print(("Not uploading the patch for " + patch[0] + ++ " because the file is too large.")) + continue + form_fields = [("filename", patch[0])] + if not options.download_base: +@@ -1211,7 +1211,7 @@ def UploadSeparatePatches(issue, rpc_server, patchset, data, options): + files = [("data", "data.diff", patch[1])] + ctype, body = EncodeMultipartFormData(form_fields, files) + url = "/%d/upload_patch/%d" % (int(issue), int(patchset)) +- print "Uploading patch for " + patch[0] ++ print("Uploading patch for " + patch[0]) + response_body = rpc_server.Send(url, body, content_type=ctype) + lines = response_body.splitlines() + if not lines or lines[0] != "OK": +@@ -1238,7 +1238,8 @@ def GuessVCS(options): + out, returncode = RunShellWithReturnCode(["hg", "root"]) + if returncode == 0: + return MercurialVCS(options, out.strip()) +- except OSError, (errno, message): ++ except OSError as xxx_todo_changeme: ++ (errno, message) = xxx_todo_changeme.args + if errno != 2: # ENOENT -- they don't have hg installed. + raise + +@@ -1254,7 +1255,8 @@ def GuessVCS(options): + "--is-inside-work-tree"]) + if returncode == 0: + return GitVCS(options) +- except OSError, (errno, message): ++ except OSError as xxx_todo_changeme1: ++ (errno, message) = xxx_todo_changeme1.args + if errno != 2: # ENOENT -- they don't have git installed. + raise + +@@ -1301,12 +1303,12 @@ def RealMain(argv, data=None): + data = vcs.GenerateDiff(args) + files = vcs.GetBaseFiles(data) + if verbosity >= 1: +- print "Upload server:", options.server, "(change with -s/--server)" ++ print("Upload server:", options.server, "(change with -s/--server)") + if options.issue: + prompt = "Message describing this patch set: " + else: + prompt = "New issue subject: " +- message = options.message or raw_input(prompt).strip() ++ message = options.message or input(prompt).strip() + if not message: + ErrorExit("A non-empty message is required") + rpc_server = GetRpcServer(options) +@@ -1339,7 +1341,7 @@ def RealMain(argv, data=None): + # Send a hash of all the base file so the server can determine if a copy + # already exists in an earlier patchset. + base_hashes = "" +- for file, info in files.iteritems(): ++ for file, info in files.items(): + if not info[0] is None: + checksum = md5.new(info[0]).hexdigest() + if base_hashes: +@@ -1353,7 +1355,7 @@ def RealMain(argv, data=None): + if not options.download_base: + form_fields.append(("content_upload", "1")) + if len(data) > MAX_UPLOAD_SIZE: +- print "Patch is large, so uploading file patches separately." ++ print("Patch is large, so uploading file patches separately.") + uploaded_diff_file = [] + form_fields.append(("separate_patches", "1")) + else: +@@ -1393,7 +1395,7 @@ def main(): + try: + RealMain(sys.argv) + except KeyboardInterrupt: +- print ++ print() + StatusUpdate("Interrupted.") + sys.exit(1) + diff --git a/post_proc.py b/post_proc.py index 3e0c9b1..97278cc 100755 --- a/post_proc.py +++ b/post_proc.py @@ -19,7 +19,7 @@ def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument("-i", "--inputFile", default="", type=str, help="Input file name") parser.add_argument('-o', '--outputFile', default="skimmed_nano.root", type=str, help="Output file name") - parser.add_argument("-n", "--entriesToRun", default=0, type=int, help="Set to 0 if need to run over all entries else put number of entries to run") + parser.add_argument("-n", "--entriesToRun", default=1000, type=int, help="Set to 0 if need to run over all entries else put number of entries to run") parser.add_argument("-d", "--DownloadFileToLocalThenRun", default=True, type=bool, help="Download file to local then run") parser.add_argument("--NOsyst", default=False, action="store_true", help="Do not run systematics") parser.add_argument("--DEBUG", default=False, action="store_true", help="Print debug information") From 167ed959de45d2185cae98fdce9bd103094673bd Mon Sep 17 00:00:00 2001 From: Ram Krishna Sharma Date: Thu, 14 Nov 2024 15:47:04 +0100 Subject: [PATCH 2/3] - Added muon rochester correction - Fixed the bug in M2e2mu and 4l kinematics --- H4LCppModule.py | 31 +++++++++++++------ README.md | 17 ++++------- crab/crab_script.py | 2 +- crab/crab_scriptMC.py | 2 +- post_proc.py | 2 +- scripts/check_condor_stuck_or_not.py | 22 +++++++------- scripts/check_das_sample.py | 24 +++++++-------- scripts/compareHist.py | 45 ++++++++++++++++++++++++++++ 8 files changed, 98 insertions(+), 47 deletions(-) create mode 100644 scripts/compareHist.py diff --git a/H4LCppModule.py b/H4LCppModule.py index 7ffad6d..f01032d 100644 --- a/H4LCppModule.py +++ b/H4LCppModule.py @@ -81,14 +81,26 @@ def _load_config(self, cfgFile): return yaml.safe_load(ymlfile) def _initialize_worker(self, cfg): - self.worker.InitializeElecut(cfg['Electron']['pTcut'],cfg['Electron']['Etacut'],cfg['Electron']['Sip3dcut'],cfg['Electron']['Loosedxycut'],cfg['Electron']['Loosedzcut'], - cfg['Electron']['Isocut'],cfg['Electron']['BDTWP']['LowEta']['LowPT'],cfg['Electron']['BDTWP']['MedEta']['LowPT'],cfg['Electron']['BDTWP']['HighEta']['LowPT'], - cfg['Electron']['BDTWP']['LowEta']['HighPT'],cfg['Electron']['BDTWP']['MedEta']['HighPT'],cfg['Electron']['BDTWP']['HighEta']['HighPT']) - self.worker.InitializeMucut(cfg['Muon']['pTcut'],cfg['Muon']['Etacut'],cfg['Muon']['Sip3dcut'],cfg['Muon']['Loosedxycut'],cfg['Muon']['Loosedzcut'],cfg['Muon']['Isocut'], - cfg['Muon']['Tightdxycut'],cfg['Muon']['Tightdzcut'],cfg['Muon']['TightTrackerLayercut'],cfg['Muon']['TightpTErrorcut'],cfg['Muon']['HighPtBound']) - self.worker.InitializeFsrPhotonCut(cfg['FsrPhoton']['pTcut'],cfg['FsrPhoton']['Etacut'],cfg['FsrPhoton']['Isocut'],cfg['FsrPhoton']['dRlcut'],cfg['FsrPhoton']['dRlOverPtcut']) - self.worker.InitializeJetcut(cfg['Jet']['pTcut'],cfg['Jet']['Etacut']) - self.worker.InitializeEvtCut(cfg['MZ1cut'],cfg['MZZcut'],cfg['Higgscut']['down'],cfg['Higgscut']['up'],cfg['Zmass'],cfg['MZcut']['down'],cfg['MZcut']['up']) + self.worker.InitializeElecut(*self._get_nested_values(cfg['Electron'], [ + 'pTcut', 'Etacut', 'Sip3dcut', 'Loosedxycut', 'Loosedzcut', + 'Isocut', ['BDTWP', 'LowEta', 'LowPT'], ['BDTWP', 'MedEta', 'LowPT'], + ['BDTWP', 'HighEta', 'LowPT'], ['BDTWP', 'LowEta', 'HighPT'], + ['BDTWP', 'MedEta', 'HighPT'], ['BDTWP', 'HighEta', 'HighPT'] + ])) + self.worker.InitializeMucut(*self._get_nested_values(cfg['Muon'], [ + 'pTcut', 'Etacut', 'Sip3dcut', 'Loosedxycut', 'Loosedzcut', 'Isocut', + 'Tightdxycut', 'Tightdzcut', 'TightTrackerLayercut', 'TightpTErrorcut', + 'HighPtBound' + ])) + self.worker.InitializeFsrPhotonCut(*self._get_nested_values(cfg['FsrPhoton'], [ + 'pTcut', 'Etacut', 'Isocut', 'dRlcut', 'dRlOverPtcut' + ])) + self.worker.InitializeJetcut(*self._get_nested_values(cfg['Jet'], ['pTcut', 'Etacut'])) + self.worker.InitializeEvtCut(*self._get_nested_values(cfg, ['MZ1cut', 'MZZcut', + ['Higgscut', 'down'], ['Higgscut', 'up'], + 'Zmass', ['MZcut', 'down'], ['MZcut', 'up'], + ])) + def _get_nested_values(self, dictionary, keys): values = [] @@ -345,6 +357,7 @@ def analyze(self, event): self.worker.findZ1LCandidate() if ((self.worker.nTightEle<2)|(self.worker.nTightMu<2)): pass + self.worker.ZZSelection() Electron_Fsr_pt_vec = self.worker.ElectronFsrPt() Electron_Fsr_eta_vec = self.worker.ElectronFsrEta() @@ -522,7 +535,7 @@ def analyze(self, event): if self.worker.flag4e: mass4e = mass4l if self.worker.flag2e2mu: - mass4e = mass4l + mass2e2mu = mass4l if self.worker.flag4mu: mass4mu = mass4l if (self.worker.isFSR==False & (passedFullSelection | passedZXCRSelection)): diff --git a/README.md b/README.md index 1db9347..0b229e8 100644 --- a/README.md +++ b/README.md @@ -14,21 +14,21 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. 2. Step: 2: Get official nanoAODTools ```bash - git clone git@github.com:cms-nanoAOD/nanoAOD-tools.git PhysicsTools/NanoAODTools + git clone git@github.com:ram1123/nanoAOD-tools.git PhysicsTools/NanoAODTools cd PhysicsTools/NanoAODTools - git checkout d163c18096fe2c5963ff5a9764bb420b46632178 # Updated to commit on 6 Dec 2023 in official nanoAOD-tools + git checkout h4l_dev ``` 3. Step: 3: Get our analysis repository ```bash + # Main analysis repository cd $CMSSW_BASE/src git clone git@github.com:ram1123/nanoAOD_skim.git PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim cd PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim git checkout ZXCR - cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools - git apply python/postprocessing/analysis/nanoAOD_skim/external/nanoAODTools_py2to3.patch - cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim + + # External package: yaml-cpp git clone git@github.com:jbeder/yaml-cpp.git external/yaml-cpp cd external/yaml-cpp/ git apply ../yamlcpp_pkg_py2to3.patch @@ -37,17 +37,10 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. cmake3 .. -DBUILD_SHARED_LIBS=ON cmake3 --build . cd $CMSSW_BASE/src - cp PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim/data/btag/*.csv PhysicsTools/NanoAODTools/data/btagSF/. scram b voms-proxy-init --voms cms --valid 168:00 ``` - (Optional: Fix git repo) - - ```bash - find PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim/.git/ -name "*.py*" -delete - ``` - 4. Step: 4: Get the MELA package ```bash diff --git a/crab/crab_script.py b/crab/crab_script.py index 6136e5e..cf2c9c1 100644 --- a/crab/crab_script.py +++ b/crab/crab_script.py @@ -16,4 +16,4 @@ p.run() -print "DONE" +print("DONE") diff --git a/crab/crab_scriptMC.py b/crab/crab_scriptMC.py index 4cb7b72..e0ca1b4 100644 --- a/crab/crab_scriptMC.py +++ b/crab/crab_scriptMC.py @@ -17,4 +17,4 @@ p.run() -print "DONE" +print ("DONE") diff --git a/post_proc.py b/post_proc.py index 97278cc..e9324a0 100755 --- a/post_proc.py +++ b/post_proc.py @@ -76,7 +76,7 @@ def main(): cfgFile = "Input_2022.yml" jsonFileName = "golden_Json/Cert_Collisions2022_355100_362760_Golden.json" sfFileName = "DeepCSV_102XSF_V2.csv" # FIXME: Update for year 2022 - modulesToRun.extend([muonScaleRes2018()]) # FIXME: Update for year 2022 + modulesToRun.extend([muonScaleRes2022()]) # FIXME: Update for year 2022 if "UL18" in first_file or "UL2018" in first_file: """UL2018 for identification of 2018 UL data and UL18 for identification of 2018 UL MC """ diff --git a/scripts/check_condor_stuck_or_not.py b/scripts/check_condor_stuck_or_not.py index 7dcb482..6c13692 100644 --- a/scripts/check_condor_stuck_or_not.py +++ b/scripts/check_condor_stuck_or_not.py @@ -12,9 +12,9 @@ #Oprint output.split("\t") lpcschedd = "" -print type(output) +print(type(output)) for outputs in output.split('\n'): - print outputs + print(outputs) if outputs.find('Submitter') != -1: lpcschedd = outputs.split()[2].split('.')[0] if outputs.find('rasharma') != -1 and outputs.split()[5] == 'R': @@ -23,21 +23,21 @@ """ condor_tail = "condor_tail "+outputs.split()[0]+" -name "+lpcschedd - print "\n","-"*51,"\n\n" - print(style.GREEN + outputs+style.RESET+"\n\n") - print "COMMAND: ",condor_tail - print "\n" + print("\n","-"*51,"\n\n") + print((style.GREEN + outputs+style.RESET+"\n\n")) + print("COMMAND: ",condor_tail) + print("\n") # os.system(condor_tail) output = os.popen(condor_tail).read() foundOrNot = any(match in output for match in error_check_string) if foundOrNot: - print(style.RED + "ERROR: Going to kill this job" + style.RESET) + print((style.RED + "ERROR: Going to kill this job" + style.RESET)) killCommand = "condor_rm "+outputs.split()[0]+" -name "+lpcschedd - print(style.RED + "Running Command: " + killCommand + style.RESET) + print((style.RED + "Running Command: " + killCommand + style.RESET)) os.system(killCommand) - print(style.RED + "Successfully killed." + style.RESET) + print((style.RED + "Successfully killed." + style.RESET)) else: - print output -print "\n\n" + print(output) +print("\n\n") diff --git a/scripts/check_das_sample.py b/scripts/check_das_sample.py index b983409..38ad725 100644 --- a/scripts/check_das_sample.py +++ b/scripts/check_das_sample.py @@ -17,11 +17,11 @@ defaultOldCampaign = "v6" defaultNewCampaign = "v7" -print "="*51 +print("="*51) CommandToRun = 'cp input_data_Files/sample_list_'+campaign_to_run.replace(defaultNewCampaign,defaultOldCampaign)+'.dat samples.dat' -print CommandToRun +print(CommandToRun) os.system(CommandToRun) -print "="*51 +print("="*51) with open('samples.dat') as in_file: count = 0 outjdl_file = open("sample_list_"+campaign_to_run+".dat","w") @@ -32,25 +32,25 @@ continue #if count > 27: break count = count +1 - print "="*51,"\n" - print "==> Sample : ",count - print "==> line : ",lines + print("="*51,"\n") + print("==> Sample : ",count) + print("==> line : ",lines) sample_name = lines.split('/')[1] campaign = lines.split('/')[2] tier = lines.split('/')[3] #campaign = lines.split('/')[2].split('-')[0] - print "==> DAS = ",lines - print "==> sample_name = ",sample_name - print "==> campaign = ",campaign - print "==> campaign = ",tier + print("==> DAS = ",lines) + print("==> sample_name = ",sample_name) + print("==> campaign = ",campaign) + print("==> campaign = ",tier) if sample_name.find("SingleMuon") != -1 or sample_name.find("EGamma") != -1 or sample_name.find("SingleElectron") !=-1 or sample_name.find("DoubleEG") != -1 or sample_name.find("DoubleMuon") != -1 or sample_name.find("MuonEG") != -1: v6_ntuples = "/"+sample_name+"/"+year_campaign_dict[campaign_to_run][1]+"/"+tier else: v6_ntuples = "/"+sample_name+"/"+year_campaign_dict[campaign_to_run][0]+"/"+tier #output = os.popen('dasgoclient --query="dataset='+lines.strip()+'"').read() - print 'dasgoclient --query="dataset='+v6_ntuples.strip()+'"' + print('dasgoclient --query="dataset='+v6_ntuples.strip()+'"') output = os.popen('dasgoclient --query="dataset='+v6_ntuples.strip()+'"').read() - print "output : ",output,"\n",type(output)," : ",len(output) + print("output : ",output,"\n",type(output)," : ",len(output)) if len(output.strip()) == 0: outjdl_file.write("# NOT FOUND: "+v6_ntuples.strip()+"\n") else: diff --git a/scripts/compareHist.py b/scripts/compareHist.py new file mode 100644 index 0000000..1abfbe3 --- /dev/null +++ b/scripts/compareHist.py @@ -0,0 +1,45 @@ +import uproot +import matplotlib.pyplot as plt +import numpy as np + +# Open the ROOT file and access the TTree +file = uproot.open("skimmed_nano.root") +tree = file["Events"] + +# Define the histogram bins +pt_bins = np.linspace(0, 150, 51) # 50 bins from 0 to 150 + +# Load nMuon and Muon_pt branches +nMuon = tree["nMuon"].array(library="np") +muon_pt = tree["Muon_pt"].array(library="np") +muon_uncorrected_pt = tree["Muon_uncorrected_pt"].array(library="np") + +# Apply the cut nMuon > 0 and select only Muon_pt[0] for events with at least one muon +muon_pt = muon_pt[nMuon > 0] +muon_uncorrected_pt = muon_uncorrected_pt[nMuon > 0] + +# Extract the first muon pt (Muon_pt[0]) for each event +first_muon_pt = np.array([event[0] for event in muon_pt if len(event) > 0]) +first_muon_uncorrected_pt = np.array([event[0] for event in muon_uncorrected_pt if len(event) > 0]) + +# Create histograms +counts1, bin_edges1 = np.histogram(first_muon_pt, bins=pt_bins) +counts2, bin_edges2 = np.histogram(first_muon_uncorrected_pt, bins=pt_bins) + +# Plotting without displaying +fig, ax = plt.subplots() + +# Plot histogram1 in blue +ax.step(bin_edges1[:-1], counts1, where="mid", label="Muon_pt[0]", color="blue") + +# Plot histogram2 in red on the same canvas +ax.step(bin_edges2[:-1], counts2, where="mid", label="Muon_uncorrected_pt[0]", color="red") + +# Customize the plot +ax.legend(title="First Muon Transverse Momentum") +ax.set_xlabel("Transverse Momentum (GeV)") +ax.set_ylabel("Counts") + +# Save the plot to a PNG file +fig.savefig("histogram_comparison.png") +plt.close(fig) From 3ca0315279ede4685fa6f4fab25d4678d5e8f874 Mon Sep 17 00:00:00 2001 From: Ram Krishna Sharma Date: Thu, 14 Nov 2024 16:19:19 +0100 Subject: [PATCH 3/3] Updated README --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0b229e8..280a21c 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,7 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. 2. Step: 2: Get official nanoAODTools ```bash - git clone git@github.com:ram1123/nanoAOD-tools.git PhysicsTools/NanoAODTools - cd PhysicsTools/NanoAODTools - git checkout h4l_dev + git clone -b h4l_dev git@github.com:ram1123/nanoAOD-tools.git PhysicsTools/NanoAODTools ``` 3. Step: 3: Get our analysis repository @@ -26,7 +24,7 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. cd $CMSSW_BASE/src git clone git@github.com:ram1123/nanoAOD_skim.git PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim cd PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim - git checkout ZXCR + git checkout ZXCR_EL9 # External package: yaml-cpp git clone git@github.com:jbeder/yaml-cpp.git external/yaml-cpp @@ -37,8 +35,7 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. cmake3 .. -DBUILD_SHARED_LIBS=ON cmake3 --build . cd $CMSSW_BASE/src - scram b - voms-proxy-init --voms cms --valid 168:00 + scram b -j 8 ``` 4. Step: 4: Get the MELA package @@ -60,6 +57,7 @@ nanoAOD skiming code for H->ZZ->2l2Q studies. cd $CMSSW_BASE/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/afs/cern.ch/work/r/rasharma/h2l2nu/checkNewSetup_15July2024/CMSSW_14_0_2/src/PhysicsTools/NanoAODTools/python/postprocessing/analysis/nanoAOD_skim/JHUGenMELA/MELA/data/el9_amd64_gcc12 # NOTE: The above export command is needed to run just before running the post_proc.py script. Otherwise, it will give error. + voms-proxy-init --voms cms --valid 168:00 python3 post_proc.py ```