From 28018139246afdc2cb95a8e33597d342359cb7f7 Mon Sep 17 00:00:00 2001 From: Lauren Hay Date: Thu, 1 Oct 2020 23:02:48 +0200 Subject: [PATCH 1/5] Adding PF candidates and additional BTV information to JME workflow. --- .../python/relval_pileup.py | 2 + .../python/relval_steps.py | 4 + .../python/upgradeWorkflowComponents.py | 30 +++ PhysicsTools/NanoAOD/python/addBTV.py | 251 ++++++++++++++++++ PhysicsTools/NanoAOD/python/addPFCands_cff.py | 130 +++++++++ PhysicsTools/NanoAOD/python/custom_jme_cff.py | 26 ++ 6 files changed, 443 insertions(+) create mode 100644 PhysicsTools/NanoAOD/python/addBTV.py create mode 100644 PhysicsTools/NanoAOD/python/addPFCands_cff.py diff --git a/Configuration/PyReleaseValidation/python/relval_pileup.py b/Configuration/PyReleaseValidation/python/relval_pileup.py index be7d1e352a108..1b2ce2e5bd18a 100644 --- a/Configuration/PyReleaseValidation/python/relval_pileup.py +++ b/Configuration/PyReleaseValidation/python/relval_pileup.py @@ -40,6 +40,8 @@ workflows[25202.1]=['',['TTbar_13','DIGIUP15APVSimu_PU25','RECOUP15_PU25','HARVESTUP15_PU25']] workflows[25202.2]=['',['TTbar_13','DIGIUP15APVSimu_PU25','RECOUP15_PU25_HIPM','HARVESTUP15_PU25']] workflows[25202.15]=['',['TTbar_13','DIGIUP15_PU25','RECOUP15_PU25','HARVESTUP15_PU25','NANOUP15MC_PU25_JME']] +workflows[25202.16]=['',['TTbar_13','DIGIUP15_PU25','RECOUP15_PU25','HARVESTUP15_PU25','NANOUP15MC_PU25_JMEAK8PF']] +workflows[25202.17]=['',['TTbar_13','DIGIUP15_PU25','RECOUP15_PU25','HARVESTUP15_PU25','NANOUP15MC_PU25_JMEPF']] workflows[25203]=['',['H125GGgluonfusion_13','DIGIUP15_PU25','RECOUP15_PU25','HARVESTUP15_PU25','NANOUP15_PU25']] workflows[25204]=['',['QQH1352T_13','DIGIUP15_PU25','RECOUP15_PU25','HARVESTUP15_PU25']] workflows[25205]=['',['ZTT_13','DIGIUP15_PU25','RECOUP15_PU25','HARVESTUP15_PU25','NANOUP15_PU25']] diff --git a/Configuration/PyReleaseValidation/python/relval_steps.py b/Configuration/PyReleaseValidation/python/relval_steps.py index 48f983da0ea1b..f3efa69f26e51 100644 --- a/Configuration/PyReleaseValidation/python/relval_steps.py +++ b/Configuration/PyReleaseValidation/python/relval_steps.py @@ -3135,6 +3135,10 @@ def gen2021HiMix(fragment,howMuch): steps['NANOUP15Had']=merge([{'--filein':'file:step4_inMINIAODSIM.root'},steps['NANOUP15']]) steps['NANOUP15MC_PU25_JME']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomNanoAOD_MC'},steps['NANOUP15']]) steps['NANOUP15Data_PU25_JME']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomNanoAOD_Data','--data':''},steps['NANOUP15']]) +steps['NANOUP15MC_PU25_JMEAK8PF']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomAK8PFNanoAOD_MC'},steps['NANOUP15']]) +steps['NANOUP15Data_PU25_JMEAK8PF']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomAK8PFNanoAOD_Data','--data':''},steps['NANOUP15']]) +steps['NANOUP15MC_PU25_JMEPF']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomPFNanoAOD_MC'},steps['NANOUP15']]) +steps['NANOUP15Data_PU25_JMEPF']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomPFNanoAOD_Data','--data':''},steps['NANOUP15']]) steps['NANOUP17Had']=merge([{'--filein':'file:step4_inMINIAODSIM.root'},steps['NANOUP17']]) steps['NANOUP18'] = merge([{'--conditions': 'auto:phase1_2018_realistic', '--era': 'Run2_2018','-n':'10', '--filein':'file:step3_inMINIAODSIM.root', '--nThreads':'2'}, stepNanoEDMMCProd ]) steps['NANOUP18Had']=merge([{'--filein':'file:step4_inMINIAODSIM.root'},steps['NANOUP18']]) diff --git a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py index 416152297f093..d9886ea6e76d2 100644 --- a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py +++ b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py @@ -646,6 +646,36 @@ def condition(self, fragment, stepList, key, hasHarvest): offset = 0.15, ) +class UpgradeWorkflow_JMEAK8PFNano(UpgradeWorkflow): + def setup_(self, step, stepName, stepDict, k, properties): + if 'Nano' in step: + stepDict[stepName][k] = merge([{'--customise': 'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomAK8PFNanoAOD_MC'}, stepDict[step][k]]) + def condition(self, fragment, stepList, key, hasHarvest): + return fragment=="TTbar_13" and ('2017' in key or '2018' in key) +upgradeWFs['JMEAK8PFNano'] = UpgradeWorkflow_JMEAK8PFNano( + steps = [ + 'Nano', + ], + PU = [], + suffix = '_JMEAK8PFNano', + offset = 0.16, +) + +class UpgradeWorkflow_JMEPFNano(UpgradeWorkflow): + def setup_(self, step, stepName, stepDict, k, properties): + if 'Nano' in step: + stepDict[stepName][k] = merge([{'--customise': 'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomPFNanoAOD_MC'}, stepDict[step][k]]) + def condition(self, fragment, stepList, key, hasHarvest): + return fragment=="TTbar_13" and ('2017' in key or '2018' in key) +upgradeWFs['JMEPFNano'] = UpgradeWorkflow_JMEPFNano( + steps = [ + 'Nano', + ], + PU = [], + suffix = '_JMEPFNano', + offset = 0.17, +) + # common operations for aging workflows class UpgradeWorkflowAging(UpgradeWorkflow): diff --git a/PhysicsTools/NanoAOD/python/addBTV.py b/PhysicsTools/NanoAOD/python/addBTV.py new file mode 100644 index 0000000000000..1ec192ebf9e44 --- /dev/null +++ b/PhysicsTools/NanoAOD/python/addBTV.py @@ -0,0 +1,251 @@ +import FWCore.ParameterSet.Config as cms +# from PhysicsTools.NanoAOD.common_cff import * +from PhysicsTools.NanoAOD.common_cff import Var +from PhysicsTools.NanoAOD.jets_cff import jetTable, fatJetTable, subJetTable +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection + + +def update_jets_AK4(process): + # Based on ``nanoAOD_addDeepInfo`` + # in https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/python/nano_cff.py + _btagDiscriminators = [ + 'pfJetProbabilityBJetTags', + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probudsg', + ] + updateJetCollection( + process, + jetSource=cms.InputTag('slimmedJets'), + jetCorrections=('AK4PFchs', + cms.vstring( + ['L1FastJet', 'L2Relative', 'L3Absolute', + 'L2L3Residual']), 'None'), + btagDiscriminators=_btagDiscriminators, + postfix='WithDeepInfo', + ) + process.load("Configuration.StandardSequences.MagneticField_cff") + process.jetCorrFactorsNano.src = "selectedUpdatedPatJetsWithDeepInfo" + process.updatedJets.jetSource = "selectedUpdatedPatJetsWithDeepInfo" + return process + + +def update_jets_AK8(process): + # Based on ``nanoAOD_addDeepInfoAK8`` + # in https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/python/nano_cff.py + _btagDiscriminators = [ + 'pfJetProbabilityBJetTags', + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probudsg', + 'pfMassIndependentDeepDoubleBvLV2JetTags:probHbb', + 'pfMassIndependentDeepDoubleCvLV2JetTags:probHcc', + 'pfMassIndependentDeepDoubleCvBV2JetTags:probHcc', + ] + updateJetCollection( + process, + jetSource=cms.InputTag('slimmedJetsAK8'), + pvSource=cms.InputTag('offlineSlimmedPrimaryVertices'), + svSource=cms.InputTag('slimmedSecondaryVertices'), + rParam=0.8, + jetCorrections=('AK8PFPuppi', + cms.vstring([ + 'L1FastJet', 'L2Relative', 'L3Absolute', + 'L2L3Residual' + ]), 'None'), + btagDiscriminators=_btagDiscriminators, + postfix='AK8WithDeepInfo', + # this should work but doesn't seem to enable the tag info with addTagInfos + # btagInfos=['pfDeepDoubleXTagInfos'], + printWarning=False) + process.jetCorrFactorsAK8.src = "selectedUpdatedPatJetsAK8WithDeepInfo" + process.updatedJetsAK8.jetSource = "selectedUpdatedPatJetsAK8WithDeepInfo" + # add DeepDoubleX taginfos + process.updatedPatJetsTransientCorrectedAK8WithDeepInfo.tagInfoSources.append(cms.InputTag("pfDeepDoubleXTagInfosAK8WithDeepInfo")) + process.updatedPatJetsTransientCorrectedAK8WithDeepInfo.addTagInfos = cms.bool(True) + return process + + +def update_jets_AK8_subjet(process): + # Based on ``nanoAOD_addDeepInfoAK8`` + # in https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/python/nano_cff.py + # and https://github.com/alefisico/RecoBTag-PerformanceMeasurements/blob/10_2_X_boostedCommissioning/test/runBTagAnalyzer_cfg.py + _btagDiscriminators = [ + 'pfJetProbabilityBJetTags', + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probudsg', + ] + updateJetCollection( + process, + labelName='SoftDropSubjetsPF', + jetSource=cms.InputTag("slimmedJetsAK8PFPuppiSoftDropPacked", "SubJets"), + jetCorrections=('AK4PFPuppi', + ['L2Relative', 'L3Absolute'], 'None'), + btagDiscriminators=list(_btagDiscriminators), + explicitJTA=True, # needed for subjet b tagging + svClustering=False, # needed for subjet b tagging (IMPORTANT: Needs to be set to False to disable ghost-association which does not work with slimmed jets) + fatJets=cms.InputTag('slimmedJetsAK8'), # needed for subjet b tagging + rParam=0.8, # needed for subjet b tagging + postfix='AK8SubjetsWithDeepInfo') + + process.subJetTable.src = 'updatedPatJetsTransientCorrectedSoftDropSubjetsPFAK8SubjetsWithDeepInfo' ### VERY LONG NAME!!! :P + return process + + +def get_DDX_vars(): + # retreive 27 jet-level features used in double-b and deep double-x taggers + # defiend in arXiv:1712.07158 + + DDXVars = cms.PSet( + DDX_jetNTracks = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.jetNTracks", int, doc="number of tracks associated with the jet"), + DDX_jetNSecondaryVertices = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.jetNSecondaryVertices", int, doc="number of SVs associated with the jet"), + DDX_tau1_trackEtaRel_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackEtaRel_0", float, doc="1st smallest track pseudorapidity, relative to the jet axis, associated to the 1st N-subjettiness axis", precision=10), + DDX_tau1_trackEtaRel_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackEtaRel_1", float, doc="2nd smallest track pseudorapidity, relative to the jet axis, associated to the 1st N-subjettiness axis", precision=10), + DDX_tau1_trackEtaRel_2 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackEtaRel_2", float, doc="3rd smallest track pseudorapidity, relative to the jet axis, associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_trackEtaRel_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackEtaRel_0", float, doc="1st smallest track pseudorapidity, relative to the jet axis, associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau2_trackEtaRel_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackEtaRel_1", float, doc="2nd smallest track pseudorapidity, relative to the jet axis, associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau2_trackEtaRel_3 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackEtaRel_2", float, doc="3rd smallest track pseudorapidity, relative to the jet axis, associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau1_flightDistance2dSig = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_flightDistance2dSig", float, doc="transverse distance significance between primary and secondary vertex associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_flightDistance2dSig = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_flightDistance2dSig", float, doc="transverse distance significance between primary and secondary vertex associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau1_vertexDeltaR = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_vertexDeltaR", float, doc="deltaR between the 1st N-subjettiness axis and secondary vertex direction", precision=10), + DDX_tau1_vertexEnergyRatio = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_vertexEnergyRatio", float, doc="ratio of energy at secondary vertex over total energy associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_vertexEnergyRatio = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_vertexEnergyRatio", float, doc="ratio of energy at secondary vertex over total energy associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau1_vertexMass = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_vertexMass", float, doc="mass of track sum at secondary vertex associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_vertexMass = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_vertexMass", float, doc="mass of track sum at secondary vertex associated to the 2nd N-subjettiness axis", precision=10), + DDX_trackSip2dSigAboveBottom_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip2dSigAboveBottom_0", float, doc="track 2D signed impact parameter significance of 1st track lifting mass above bottom", precision=10), + DDX_trackSip2dSigAboveBottom_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip2dSigAboveBottom_1", float, doc="track 2D signed impact parameter significance of 2nd track lifting mass above bottom", precision=10), + DDX_trackSip2dSigAboveCharm = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip2dSigAboveCharm", float, doc="track 2D signed impact parameter significance of 1st track lifting mass above charm", precision=10), + DDX_trackSip3dSig_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_0", float, doc="1st largest track 3D signed impact parameter significance", precision=10), + DDX_tau1_trackSip3dSig_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackSip3dSig_0", float, doc="1st largest track 3D signed impact parameter significance associated to the 1st N-subjettiness axis", precision=10), + DDX_tau1_trackSip3dSig_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackSip3dSig_1", float, doc="2nd largest track 3D signed impact parameter significance associated to the 1st N-subjettiness axis", precision=10), + DDX_trackSip3dSig_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_1", float, doc="2nd largest track 3D signed impact parameter significance", precision=10), + DDX_tau2_trackSip3dSig_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackSip3dSig_0", float, doc="1st largest track 3D signed impact parameter significance associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau2_trackSip3dSig_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackSip3dSig_1", float, doc="2nd largest track 3D signed impact parameter significance associated to the 2nd N-subjettiness axis", precision=10), + DDX_trackSip3dSig_2 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_2", float, doc="3rd largest track 3D signed impact parameter significance", precision=10), + DDX_trackSip3dSig_3 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_3", float, doc="4th largest track 3D signed impact parameter significance", precision=10), + DDX_z_ratio = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.z_ratio", float, doc="z = deltaR(SV0,SV1)*pT(SV1)/m(SV0,SV1), defined in Eq. 7 of arXiv:1712.07158", precision=10) + ) + + return DDXVars + + +def add_BTV(process, runOnMC=False, onlyAK4=False, onlyAK8=False): + addAK4 = not onlyAK8 + addAK8 = not onlyAK4 + + if addAK4: + process = update_jets_AK4(process) + if addAK8: + process = update_jets_AK8(process) + process = update_jets_AK8_subjet(process) + + process.customizeJetTask = cms.Task() + process.schedule.associate(process.customizeJetTask) + + CommonVars = cms.PSet( + Proba=Var("bDiscriminator('pfJetProbabilityBJetTags')", + float, + doc="Jet Probability (Usage:BTV)", + precision=10), + nBHadrons=Var("jetFlavourInfo().getbHadrons().size()", + int, + doc="number of b-hadrons"), + nCHadrons=Var("jetFlavourInfo().getcHadrons().size()", + int, + doc="number of c-hadrons"), + btagDeepB_b=Var("bDiscriminator('pfDeepCSVJetTags:probb')", + float, + doc="DeepCSV b tag discriminator", + precision=10), + btagDeepB_bb=Var("bDiscriminator('pfDeepCSVJetTags:probbb')", + float, + doc="DeepCSV bb tag discriminator", + precision=10), + btagDeepL=Var("bDiscriminator('pfDeepCSVJetTags:probudsg')", + float, + doc="DeepCSV light btag discriminator", + precision=10), + ) + + # AK4 + process.customJetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=jetTable.src, + cut=jetTable.cut, + name=jetTable.name, + doc=jetTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for Jets + variables=cms.PSet( + CommonVars, + )) + + # AK8 + process.customFatJetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=fatJetTable.src, + cut=fatJetTable.cut, + name=fatJetTable.name, + doc=fatJetTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for FatJets + variables=cms.PSet( + CommonVars, + cms.PSet( + btagDDBvLV2 = Var("bDiscriminator('pfMassIndependentDeepDoubleBvLV2JetTags:probHbb')",float,doc="DeepDoubleX V2 discriminator for H(Z)->bb vs QCD",precision=10), + btagDDCvLV2 = Var("bDiscriminator('pfMassIndependentDeepDoubleCvLV2JetTags:probHcc')",float,doc="DeepDoubleX V2 discriminator for H(Z)->cc vs QCD",precision=10), + btagDDCvBV2 = Var("bDiscriminator('pfMassIndependentDeepDoubleCvBV2JetTags:probHcc')",float,doc="DeepDoubleX V2 discriminator for H(Z)->cc vs H(Z)->bb",precision=10), + ), + get_DDX_vars(), + )) + + # Subjets + process.customSubJetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=subJetTable.src, + cut=subJetTable.cut, + name=subJetTable.name, + doc=subJetTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for FatJets + variables=cms.PSet( + CommonVars, + # Proba=Var("bDiscriminator('pfJetProbabilityBJetTags')", + # float, + # doc="Jet Probability (Usage:BTV)", + # precision=10), + btagDeepC = Var("bDiscriminator('pfDeepCSVJetTags:probc')", + float, + doc="DeepCSV charm btag discriminator", + precision=10), + + )) + + process.customSubJetMCExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src = subJetTable.src, + cut = subJetTable.cut, + name = subJetTable.name, + doc=subJetTable.doc, + singleton = cms.bool(False), + extension = cms.bool(True), + variables = cms.PSet( + subGenJetAK8Idx = Var("?genJetFwdRef().backRef().isNonnull()?genJetFwdRef().backRef().key():-1", + int, + doc="index of matched gen Sub jet"), + ) + ) + + if addAK4: + process.customizeJetTask.add(process.customJetExtTable) + if addAK8: + process.customizeJetTask.add(process.customFatJetExtTable) + process.customizeJetTask.add(process.customSubJetExtTable) + if runOnMC and addAK8: + process.customizeJetTask.add(process.customSubJetMCExtTable) + + return process diff --git a/PhysicsTools/NanoAOD/python/addPFCands_cff.py b/PhysicsTools/NanoAOD/python/addPFCands_cff.py new file mode 100644 index 0000000000000..ab8e7ff0473c5 --- /dev/null +++ b/PhysicsTools/NanoAOD/python/addPFCands_cff.py @@ -0,0 +1,130 @@ +import FWCore.ParameterSet.Config as cms +from PhysicsTools.NanoAOD.common_cff import * + +def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=False): + process.customizedPFCandsTask = cms.Task( ) + process.schedule.associate(process.customizedPFCandsTask) + + process.finalJetsAK8Constituents = cms.EDProducer("PatJetConstituentPtrSelector", + src = cms.InputTag("finalJetsAK8"), + cut = cms.string("") + ) + process.finalJetsAK4Constituents = cms.EDProducer("PatJetConstituentPtrSelector", + src = cms.InputTag("finalJets"), + cut = cms.string("") + ) + if allPF: + candInput = cms.InputTag("packedPFCandidates") + elif onlyAK4: + candList = cms.VInputTag(cms.InputTag("finalJetsAK4Constituents", "constituents")) + process.customizedPFCandsTask.add(process.finalJetsAK4Constituents) + process.finalJetsConstituents = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + candInput = cms.InputTag("finalJetsConstituents") + elif onlyAK8: + candList = cms.VInputTag(cms.InputTag("finalJetsAK8Constituents", "constituents")) + process.customizedPFCandsTask.add(process.finalJetsAK8Constituents) + process.finalJetsConstituents = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + candInput = cms.InputTag("finalJetsConstituents") + else: + candList = cms.VInputTag(cms.InputTag("finalJetsAK4Constituents", "constituents"), cms.InputTag("finalJetsAK8Constituents", "constituents")) + process.customizedPFCandsTask.add(process.finalJetsAK4Constituents) + process.customizedPFCandsTask.add(process.finalJetsAK8Constituents) + process.finalJetsConstituents = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + candInput = cms.InputTag("finalJetsConstituents") + process.customConstituentsExtTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = candInput, + cut = cms.string(""), #we should not filter after pruning + name = cms.string("JetPFCands"), + doc = cms.string("interesting particles from AK4 and AK8 jets"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the extension table for the AK8 constituents + variables = cms.PSet(CandVars, + puppiWeight = Var("puppiWeight()", float, doc="Puppi weight",precision=10), + puppiWeightNoLep = Var("puppiWeightNoLep()", float, doc="Puppi weight removing leptons",precision=10), + vtxChi2 = Var("?hasTrackDetails()?vertexChi2():-1", float, doc="vertex chi2",precision=10), + trkChi2 = Var("?hasTrackDetails()?pseudoTrack().normalizedChi2():-1", float, doc="normalized trk chi2", precision=10), + dz = Var("?hasTrackDetails()?dz():-1", float, doc="pf dz", precision=10), + dzErr = Var("?hasTrackDetails()?dzError():-1", float, doc="pf dz err", precision=10), + d0 = Var("?hasTrackDetails()?dxy():-1", float, doc="pf d0", precision=10), + d0Err = Var("?hasTrackDetails()?dxyError():-1", float, doc="pf d0 err", precision=10), + pvAssocQuality = Var("pvAssociationQuality()", int, doc="primary vertex association quality"), + lostInnerHits = Var("lostInnerHits()", int, doc="lost inner hits"), + trkQuality = Var("?hasTrackDetails()?pseudoTrack().qualityMask():0", int, doc="track quality mask"), + ) + ) + process.customAK8ConstituentsTable = cms.EDProducer("PatJetConstituentTableProducer", + candidates = candInput, + jets = cms.InputTag("finalJetsAK8"), + jet_radius = cms.double(0.8), + name = cms.string("JetPFCandsAK8"), + nameSV = cms.string("JetSVsAK8")) + process.customAK4ConstituentsTable = cms.EDProducer("PatJetConstituentTableProducer", + #candidates = cms.InputTag("packedPFCandidates"), + candidates = candInput, + jets = cms.InputTag("finalJets"), + jet_radius = cms.double(0.4), + name = cms.string("JetPFCandsAK4"), + nameSV = cms.string("JetSVsAK4")) + if not allPF: + process.customizedPFCandsTask.add(process.finalJetsConstituents) + process.customizedPFCandsTask.add(process.customConstituentsExtTable) + process.customizedPFCandsTask.add(process.customAK8ConstituentsTable) + process.customizedPFCandsTask.add(process.customAK4ConstituentsTable) + + if runOnMC: + + process.genJetsAK8Constituents = cms.EDProducer("GenJetPackedConstituentPtrSelector", + src = cms.InputTag("slimmedGenJetsAK8"), + cut = cms.string("pt > 80") + ) + + + process.genJetsAK4Constituents = process.genJetsAK8Constituents.clone( + src = cms.InputTag("slimmedGenJets"), + cut = cms.string("pt > 20") + ) + if allPF: + genCandInput = cms.InputTag("packedGenParticles") + elif onlyAK4: + genCandList = cms.VInputTag(cms.InputTag("genJetsAK4Constituents", "constituents")) + genCandInput = cms.InputTag("genJetsConstituents") + process.genJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = genCandList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + elif onlyAK8: + genCandList = cms.VInputTag(cms.InputTag("genJetsAK8Constituents", "constituents")) + genCandInput = cms.InputTag("genJetsConstituents") + process.genJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = genCandList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + else: + genCandList = cms.VInputTag(cms.InputTag("genJetsAK4Constituents", "constituents"), cms.InputTag("genJetsAK8Constituents", "constituents")) + genCandInput = cms.InputTag("genJetsConstituents") + process.genJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = genCandList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + process.genJetsParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = genCandInput, + cut = cms.string(""), #we should not filter after pruning + name= cms.string("GenJetCands"), + doc = cms.string("interesting gen particles from AK4 and AK8 jets"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the main table for the AK8 constituents + variables = cms.PSet(CandVars + ) + ) + process.genAK8ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", + candidates = genCandInput, + jets = cms.InputTag("genJetsAK8Constituents"), # Note: The name has "Constituents" in it, but these are the jets + name = cms.string("GenJetCandsAK8"), + nameSV = cms.string("GenJetSVsAK8"), + readBtag = cms.bool(False)) + process.genAK4ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", + candidates = genCandInput, + jets = cms.InputTag("genJetsAK4Constituents"), # Note: The name has "Constituents" in it, but these are the jets + name = cms.string("GenJetCandsAK4"), + nameSV = cms.string("GenJetSVsAK4"), + readBtag = cms.bool(False)) + process.customizedPFCandsTask.add(process.genJetsAK4Constituents) #Note: For gen need to add jets to the process to keep pt cuts. + process.customizedPFCandsTask.add(process.genJetsAK8Constituents) + if not allPF: + process.customizedPFCandsTask.add(process.genJetsConstituents) + process.customizedPFCandsTask.add(process.genJetsParticleTable) + process.customizedPFCandsTask.add(process.genAK8ConstituentsTable) + process.customizedPFCandsTask.add(process.genAK4ConstituentsTable) + + return process diff --git a/PhysicsTools/NanoAOD/python/custom_jme_cff.py b/PhysicsTools/NanoAOD/python/custom_jme_cff.py index f00cfc3fd275c..fb0b988427144 100644 --- a/PhysicsTools/NanoAOD/python/custom_jme_cff.py +++ b/PhysicsTools/NanoAOD/python/custom_jme_cff.py @@ -887,3 +887,29 @@ def PrepJMECustomNanoAOD_MC(process): def PrepJMECustomNanoAOD_Data(process): PrepJMECustomNanoAOD(process,runOnMC=False) return process + +#### Add AK8 PFCands and BTV info +def PrepJMECustomAK8PFNanoAOD_MC(process): + PrepJMECustomNanoAOD(process, runOnMC=True) + addPFCands(process, runOnMC = True, onlyAK8 = True) + add_BTV(process, runOnMC = True, onlyAK8 = True) + return process + +def PrepJMECustomAK8PFNanoAOD_Data(process): + PrepJMECustomNanoAOD(process, runOnMC=False) + addPFCands(process, runOnMC = False, onlyAK8 = True) + add_BTV(process, runOnMC = False, onlyAK8 = True) + return process + +#### All PFCands and BTV info +def PrepJMECustomPFNanoAOD_MC(process): + PrepJMECustomNanoAOD(process, runOnMC=True) + addPFCands(process, runOnMC = True, allPF = True) + add_BTV(process, runOnMC = True) + return process + +def PrepJMECustomPFNanoAOD_Data(process): + PrepJMECustomNanoAOD(process, runOnMC=False) + addPFCands(process, runOnMC = False, allPF = True) + add_BTV(process, runOnMC = False) + return process From d736f4246e3e3902f7c9b987354fe2fa4ea694e8 Mon Sep 17 00:00:00 2001 From: Lauren Hay Date: Fri, 2 Oct 2020 20:31:31 +0200 Subject: [PATCH 2/5] Updating to 11_2_X syntax. --- .../python/upgradeWorkflowComponents.py | 1 + PhysicsTools/NanoAOD/plugins/BuildFile.xml | 2 + .../plugins/JetConstituentTableProducer.cc | 253 ++++++++++++++++++ .../python/{addBTV.py => addBTV_cff.py} | 2 +- PhysicsTools/NanoAOD/python/custom_jme_cff.py | 11 +- 5 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc rename PhysicsTools/NanoAOD/python/{addBTV.py => addBTV_cff.py} (99%) diff --git a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py index d9886ea6e76d2..7747f954b9794 100644 --- a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py +++ b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py @@ -1,3 +1,4 @@ + from copy import deepcopy from collections import OrderedDict import six diff --git a/PhysicsTools/NanoAOD/plugins/BuildFile.xml b/PhysicsTools/NanoAOD/plugins/BuildFile.xml index 8d4e3269834b9..7706af7b2c9d5 100644 --- a/PhysicsTools/NanoAOD/plugins/BuildFile.xml +++ b/PhysicsTools/NanoAOD/plugins/BuildFile.xml @@ -8,6 +8,8 @@ + + diff --git a/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc b/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc new file mode 100644 index 0000000000000..192c5d0b79f50 --- /dev/null +++ b/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc @@ -0,0 +1,253 @@ +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" + +#include "DataFormats/VertexReco/interface/VertexFwd.h" + +#include "DataFormats/PatCandidates/interface/Jet.h" +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" + +#include "DataFormats/Candidate/interface/CandidateFwd.h" + +#include "RecoBTag/FeatureTools/interface/TrackInfoBuilder.h" +#include "TrackingTools/Records/interface/TransientTrackRecord.h" + +#include "DataFormats/BTauReco/interface/TrackIPTagInfo.h" +#include "DataFormats/BTauReco/interface/SecondaryVertexTagInfo.h" +#include "RecoBTag/FeatureTools/interface/deep_helpers.h" +#include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h" +using namespace btagbtvdeep; + +#include "CommonTools/Utils/interface/StringCutObjectSelector.h" +#include "DataFormats/NanoAOD/interface/FlatTable.h" +#include "DataFormats/NanoAOD/interface/MergeableCounterTable.h" + +template +class JetConstituentTableProducer : public edm::stream::EDProducer<> { +public: + explicit JetConstituentTableProducer(const edm::ParameterSet &); + ~JetConstituentTableProducer() override; + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); + +private: + void produce(edm::Event &, const edm::EventSetup &) override; + + typedef reco::VertexCollection VertexCollection; + //===== + typedef reco::VertexCompositePtrCandidateCollection SVCollection; + + //const std::string name_; + const std::string name_; + const std::string nameSV_; + const bool readBtag_; + const double jet_radius_; + + edm::EDGetTokenT> jet_token_; + edm::EDGetTokenT vtx_token_; + edm::EDGetTokenT cand_token_; + edm::EDGetTokenT sv_token_; + + edm::Handle vtxs_; + edm::Handle cands_; + edm::Handle svs_; + edm::ESHandle track_builder_; + + const reco::Vertex *pv_ = nullptr; + +}; + +// +// constructors and destructor +// +template< typename T> +JetConstituentTableProducer::JetConstituentTableProducer(const edm::ParameterSet &iConfig) + : //name_(iConfig.getParameter("name")), + name_(iConfig.getParameter("name")), + nameSV_(iConfig.getParameter("nameSV")), + readBtag_(iConfig.getParameter("readBtag")), + jet_radius_(iConfig.getParameter("jet_radius")), + jet_token_(consumes>(iConfig.getParameter("jets"))), + vtx_token_(consumes(iConfig.getParameter("vertices"))), + cand_token_(consumes(iConfig.getParameter("candidates"))), + sv_token_(consumes(iConfig.getParameter("secondary_vertices"))){ + //produces(name_); + produces(name_); + produces(nameSV_); + produces>(); +} + +template< typename T> +JetConstituentTableProducer::~JetConstituentTableProducer() {} + +template< typename T> +void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { + // elements in all these collections must have the same order! + auto outCands = std::make_unique>(); + auto outSVs = std::make_unique> (); + std::vector jetIdx_pf, jetIdx_sv, candIdx; + //std::vector jetIdx, candIdx; + // PF Cands + std::vector btagEtaRel, btagPtRatio, btagPParRatio, btagSip3dVal, btagSip3dSig, btagJetDistVal; + // Secondary vertices + std::vector sv_mass, sv_pt, sv_ntracks, sv_chi2, sv_normchi2, sv_dxy, sv_dxysig, sv_d3d, sv_d3dsig, sv_costhetasvpv; + std::vector sv_ptrel, sv_phirel, sv_deltaR, sv_enratio; + + auto jets = iEvent.getHandle(jet_token_); + iEvent.getByToken(vtx_token_, vtxs_); + iEvent.getByToken(cand_token_, cands_); + iEvent.getByToken(sv_token_, svs_); + + if(readBtag_){ + iSetup.get().get("TransientTrackBuilder", track_builder_); + } + + for (unsigned i_jet = 0; i_jet < jets->size(); ++i_jet) { + const auto &jet = jets->at(i_jet); + math::XYZVector jet_dir = jet.momentum().Unit(); + GlobalVector jet_ref_track_dir(jet.px(), jet.py(), jet.pz()); + + pv_ = &vtxs_->at(0); + ////////////////////// + // Secondary Vertices + std::vector jetSVs; + for (const auto &sv : *svs_) { + if (reco::deltaR2(sv, jet) < jet_radius_ * jet_radius_) { + jetSVs.push_back(&sv); + } + } + // sort by dxy significance + std::sort(jetSVs.begin(), + jetSVs.end(), + [&](const reco::VertexCompositePtrCandidate *sva, const reco::VertexCompositePtrCandidate *svb) { + return sv_vertex_comparator(*sva, *svb, *pv_); + }); + + for (const auto &sv : jetSVs) { + outSVs->push_back(sv); + jetIdx_sv.push_back(i_jet); + if (readBtag_ && !vtxs_->empty()) { + // Jet independent + sv_mass.push_back(sv->mass()); + sv_pt.push_back(sv->pt()); + + sv_ntracks.push_back(sv->numberOfDaughters()); + sv_chi2.push_back(sv->vertexChi2()); + sv_normchi2.push_back(catch_infs_and_bound(sv->vertexChi2() / sv->vertexNdof(), 1000, -1000, 1000)); + const auto& dxy_meas = vertexDxy(*sv, *pv_); + sv_dxy.push_back(dxy_meas.value()); + sv_dxysig.push_back(catch_infs_and_bound(dxy_meas.value() / dxy_meas.error(), 0, -1, 800)); + const auto& d3d_meas = vertexD3d(*sv, *pv_); + sv_d3d.push_back(d3d_meas.value()); + sv_d3dsig.push_back(catch_infs_and_bound(d3d_meas.value() / d3d_meas.error(), 0, -1, 800)); + sv_costhetasvpv.push_back(vertexDdotP(*sv, *pv_)); + // Jet related + sv_ptrel.push_back(sv->pt() / jet.pt()); + sv_phirel.push_back(reco::deltaPhi(*sv, jet)); + sv_deltaR.push_back(catch_infs_and_bound(std::fabs(reco::deltaR(*sv, jet_dir)) - 0.5, 0, -2, 0)); + sv_enratio.push_back(sv->energy() / jet.energy()); + } + } + + // PF Cands + std::vector const & daughters = jet.daughterPtrVector(); + + for (const auto &cand : daughters) { + auto candPtrs = cands_->ptrs(); + auto candInNewList = std::find( candPtrs.begin(), candPtrs.end(), cand ); + if ( candInNewList == candPtrs.end() ) { + //std::cout << "Cannot find candidate : " << cand.id() << ", " << cand.key() << ", pt = " << cand->pt() << std::endl; + continue; + } + outCands->push_back(cand); + jetIdx_pf.push_back(i_jet); + candIdx.push_back( candInNewList - candPtrs.begin() ); + if (readBtag_ && !vtxs_->empty()) { + if ( cand.isNull() ) continue; + auto const *packedCand = dynamic_cast (cand.get()); + if ( packedCand == nullptr ) continue; + if ( packedCand && packedCand->hasTrackDetails()){ + btagbtvdeep::TrackInfoBuilder trkinfo(track_builder_); + trkinfo.buildTrackInfo(&(*packedCand), jet_dir, jet_ref_track_dir, vtxs_->at(0)); + btagEtaRel.push_back(trkinfo.getTrackEtaRel()); + btagPtRatio.push_back(trkinfo.getTrackPtRatio()); + btagPParRatio.push_back(trkinfo.getTrackPParRatio()); + btagSip3dVal.push_back(trkinfo.getTrackSip3dVal()); + btagSip3dSig.push_back(trkinfo.getTrackSip3dSig()); + btagJetDistVal.push_back(trkinfo.getTrackJetDistVal()); + } else { + btagEtaRel.push_back(0); + btagPtRatio.push_back(0); + btagPParRatio.push_back(0); + btagSip3dVal.push_back(0); + btagSip3dSig.push_back(0); + btagJetDistVal.push_back(0); + } + } + } // end jet loop + } + + auto candTable = std::make_unique(outCands->size(), name_, false); + // We fill from here only stuff that cannot be created with the SimpleFlatTableProducer + candTable->addColumn("candIdx", candIdx, "Index in the candidate list"); + candTable->addColumn("jetIdx", jetIdx_pf, "Index of the parent jet"); + if (readBtag_) { + candTable->addColumn("btagEtaRel", btagEtaRel, "btagEtaRel", 10); + candTable->addColumn("btagPtRatio", btagPtRatio, "btagPtRatio", 10); + candTable->addColumn("btagPParRatio", btagPParRatio, "btagPParRatio", 10); + candTable->addColumn("btagSip3dVal", btagSip3dVal, "btagSip3dVal", 10); + candTable->addColumn("btagSip3dSig", btagSip3dSig, "btagSip3dSig", 10); + candTable->addColumn("btagJetDistVal", btagJetDistVal, "btagJetDistVal", 10); + } + iEvent.put(std::move(candTable), name_); + + // SV table + auto svTable = std::make_unique(outSVs->size(), nameSV_, false); + // We fill from here only stuff that cannot be created with the SimpleFlatTnameableProducer + svTable->addColumn("jetIdx", jetIdx_sv, "Index of the parent jet"); + if (readBtag_) { + svTable->addColumn("mass", sv_mass, "SV mass", 10); + svTable->addColumn("pt", sv_pt, "SV pt", 10); + svTable->addColumn("ntracks", sv_ntracks, "Number of trakcs associated to SV", 10); + svTable->addColumn("chi2", sv_chi2, "chi2", 10); + svTable->addColumn("normchi2", sv_normchi2, "chi2/ndof", 10); + svTable->addColumn("dxy", sv_dxy, "", 10); + svTable->addColumn("dxysig", sv_dxysig, "", 10); + svTable->addColumn("d3d", sv_d3d, "", 10); + svTable->addColumn("d3dsig", sv_d3dsig, "", 10); + svTable->addColumn("costhetasvpv", sv_costhetasvpv, "", 10); + // Jet related + svTable->addColumn("phirel", sv_phirel, "DeltaPhi(sv, jet)", 10); + svTable->addColumn("ptrel", sv_ptrel, "pT relative to parent jet", 10); + svTable->addColumn("deltaR", sv_deltaR, "dR from parent jet", 10); + svTable->addColumn("enration", sv_enratio, "energy relative to parent jet", 10); + } + iEvent.put(std::move(svTable), nameSV_); + + iEvent.put(std::move(outCands)); +} + +template< typename T> +void JetConstituentTableProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc; + desc.add("name", "JetPFCands"); + desc.add("nameSV", "JetSV"); + desc.add("jet_radius", true); + desc.add("readBtag", true); + desc.add("jets", edm::InputTag("slimmedJetsAK8")); + desc.add("vertices", edm::InputTag("offlineSlimmedPrimaryVertices")); + desc.add("candidates", edm::InputTag("packedPFCandidates")); + desc.add("secondary_vertices", edm::InputTag("slimmedSecondaryVertices")); + descriptions.addWithDefaultLabel(desc); +} + +typedef JetConstituentTableProducer PatJetConstituentTableProducer; +typedef JetConstituentTableProducer GenJetConstituentTableProducer; + +DEFINE_FWK_MODULE(PatJetConstituentTableProducer); +DEFINE_FWK_MODULE(GenJetConstituentTableProducer); diff --git a/PhysicsTools/NanoAOD/python/addBTV.py b/PhysicsTools/NanoAOD/python/addBTV_cff.py similarity index 99% rename from PhysicsTools/NanoAOD/python/addBTV.py rename to PhysicsTools/NanoAOD/python/addBTV_cff.py index 1ec192ebf9e44..fdd823d1a4797 100644 --- a/PhysicsTools/NanoAOD/python/addBTV.py +++ b/PhysicsTools/NanoAOD/python/addBTV_cff.py @@ -133,7 +133,7 @@ def get_DDX_vars(): return DDXVars -def add_BTV(process, runOnMC=False, onlyAK4=False, onlyAK8=False): +def addBTV(process, runOnMC=False, onlyAK4=False, onlyAK8=False): addAK4 = not onlyAK8 addAK8 = not onlyAK4 diff --git a/PhysicsTools/NanoAOD/python/custom_jme_cff.py b/PhysicsTools/NanoAOD/python/custom_jme_cff.py index fb0b988427144..963468398a09c 100644 --- a/PhysicsTools/NanoAOD/python/custom_jme_cff.py +++ b/PhysicsTools/NanoAOD/python/custom_jme_cff.py @@ -16,6 +16,9 @@ from PhysicsTools.PatAlgos.tools.jetTools import supportedJetAlgos from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection +from PhysicsTools.NanoAOD.addPFCands_cff import addPFCands +from PhysicsTools.NanoAOD.addBTV_cff import addBTV + import copy bTagCSVV2 = ['pfDeepCSVJetTags:probb','pfDeepCSVJetTags:probbb','pfDeepCSVJetTags:probc'] @@ -892,24 +895,24 @@ def PrepJMECustomNanoAOD_Data(process): def PrepJMECustomAK8PFNanoAOD_MC(process): PrepJMECustomNanoAOD(process, runOnMC=True) addPFCands(process, runOnMC = True, onlyAK8 = True) - add_BTV(process, runOnMC = True, onlyAK8 = True) + addBTV(process, runOnMC = True, onlyAK8 = True) return process def PrepJMECustomAK8PFNanoAOD_Data(process): PrepJMECustomNanoAOD(process, runOnMC=False) addPFCands(process, runOnMC = False, onlyAK8 = True) - add_BTV(process, runOnMC = False, onlyAK8 = True) + addBTV(process, runOnMC = False, onlyAK8 = True) return process #### All PFCands and BTV info def PrepJMECustomPFNanoAOD_MC(process): PrepJMECustomNanoAOD(process, runOnMC=True) addPFCands(process, runOnMC = True, allPF = True) - add_BTV(process, runOnMC = True) + addBTV(process, runOnMC = True) return process def PrepJMECustomPFNanoAOD_Data(process): PrepJMECustomNanoAOD(process, runOnMC=False) addPFCands(process, runOnMC = False, allPF = True) - add_BTV(process, runOnMC = False) + addBTV(process, runOnMC = False) return process From 0495536eacd772eca2f4e557f5315ddd5e5b2903 Mon Sep 17 00:00:00 2001 From: Lauren Hay Date: Tue, 6 Oct 2020 21:08:52 +0200 Subject: [PATCH 3/5] Changing names of candidate collections for clarity. --- PhysicsTools/NanoAOD/python/addPFCands_cff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PhysicsTools/NanoAOD/python/addPFCands_cff.py b/PhysicsTools/NanoAOD/python/addPFCands_cff.py index ab8e7ff0473c5..972d3012d2672 100644 --- a/PhysicsTools/NanoAOD/python/addPFCands_cff.py +++ b/PhysicsTools/NanoAOD/python/addPFCands_cff.py @@ -34,7 +34,7 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal process.customConstituentsExtTable = cms.EDProducer("SimpleCandidateFlatTableProducer", src = candInput, cut = cms.string(""), #we should not filter after pruning - name = cms.string("JetPFCands"), + name = cms.string("PFCands"), doc = cms.string("interesting particles from AK4 and AK8 jets"), singleton = cms.bool(False), # the number of entries is variable extension = cms.bool(False), # this is the extension table for the AK8 constituents @@ -100,7 +100,7 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal process.genJetsParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", src = genCandInput, cut = cms.string(""), #we should not filter after pruning - name= cms.string("GenJetCands"), + name= cms.string("GenParticles"), doc = cms.string("interesting gen particles from AK4 and AK8 jets"), singleton = cms.bool(False), # the number of entries is variable extension = cms.bool(False), # this is the main table for the AK8 constituents From 1b813fb6bd18c7fb53b4c31426a31f897ff66890 Mon Sep 17 00:00:00 2001 From: Lauren Hay Date: Tue, 6 Oct 2020 22:37:32 +0200 Subject: [PATCH 4/5] Changing description of candidate tables for clarity. --- PhysicsTools/NanoAOD/python/addPFCands_cff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PhysicsTools/NanoAOD/python/addPFCands_cff.py b/PhysicsTools/NanoAOD/python/addPFCands_cff.py index 972d3012d2672..b48e35abd026a 100644 --- a/PhysicsTools/NanoAOD/python/addPFCands_cff.py +++ b/PhysicsTools/NanoAOD/python/addPFCands_cff.py @@ -35,7 +35,7 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal src = candInput, cut = cms.string(""), #we should not filter after pruning name = cms.string("PFCands"), - doc = cms.string("interesting particles from AK4 and AK8 jets"), + doc = cms.string("interesting particles from selected candidate collection"), singleton = cms.bool(False), # the number of entries is variable extension = cms.bool(False), # this is the extension table for the AK8 constituents variables = cms.PSet(CandVars, @@ -101,7 +101,7 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal src = genCandInput, cut = cms.string(""), #we should not filter after pruning name= cms.string("GenParticles"), - doc = cms.string("interesting gen particles from AK4 and AK8 jets"), + doc = cms.string("interesting gen particles from selected candidate collection"), singleton = cms.bool(False), # the number of entries is variable extension = cms.bool(False), # this is the main table for the AK8 constituents variables = cms.PSet(CandVars From f7e6b07c6d00749656ccfd4a1d5d8cc2b2b168e1 Mon Sep 17 00:00:00 2001 From: Lauren Hay Date: Wed, 14 Oct 2020 17:01:11 +0200 Subject: [PATCH 5/5] Cand mapping names, descriptions updated. Code checks. --- .../plugins/JetConstituentTableProducer.cc | 60 ++++++++++--------- PhysicsTools/NanoAOD/python/addPFCands_cff.py | 33 ++++++---- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc b/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc index 192c5d0b79f50..0a618bb15774b 100644 --- a/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc @@ -27,7 +27,7 @@ using namespace btagbtvdeep; #include "DataFormats/NanoAOD/interface/FlatTable.h" #include "DataFormats/NanoAOD/interface/MergeableCounterTable.h" -template +template class JetConstituentTableProducer : public edm::stream::EDProducer<> { public: explicit JetConstituentTableProducer(const edm::ParameterSet &); @@ -59,15 +59,14 @@ class JetConstituentTableProducer : public edm::stream::EDProducer<> { edm::ESHandle track_builder_; const reco::Vertex *pv_ = nullptr; - }; // // constructors and destructor // -template< typename T> +template JetConstituentTableProducer::JetConstituentTableProducer(const edm::ParameterSet &iConfig) - : //name_(iConfig.getParameter("name")), + : //name_(iConfig.getParameter("name")), name_(iConfig.getParameter("name")), nameSV_(iConfig.getParameter("nameSV")), readBtag_(iConfig.getParameter("readBtag")), @@ -75,27 +74,28 @@ JetConstituentTableProducer::JetConstituentTableProducer(const edm::Parameter jet_token_(consumes>(iConfig.getParameter("jets"))), vtx_token_(consumes(iConfig.getParameter("vertices"))), cand_token_(consumes(iConfig.getParameter("candidates"))), - sv_token_(consumes(iConfig.getParameter("secondary_vertices"))){ + sv_token_(consumes(iConfig.getParameter("secondary_vertices"))) { //produces(name_); produces(name_); produces(nameSV_); produces>(); } -template< typename T> +template JetConstituentTableProducer::~JetConstituentTableProducer() {} -template< typename T> +template void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { // elements in all these collections must have the same order! auto outCands = std::make_unique>(); - auto outSVs = std::make_unique> (); + auto outSVs = std::make_unique>(); std::vector jetIdx_pf, jetIdx_sv, candIdx; //std::vector jetIdx, candIdx; // PF Cands std::vector btagEtaRel, btagPtRatio, btagPParRatio, btagSip3dVal, btagSip3dSig, btagJetDistVal; // Secondary vertices - std::vector sv_mass, sv_pt, sv_ntracks, sv_chi2, sv_normchi2, sv_dxy, sv_dxysig, sv_d3d, sv_d3dsig, sv_costhetasvpv; + std::vector sv_mass, sv_pt, sv_ntracks, sv_chi2, sv_normchi2, sv_dxy, sv_dxysig, sv_d3d, sv_d3dsig, + sv_costhetasvpv; std::vector sv_ptrel, sv_phirel, sv_deltaR, sv_enratio; auto jets = iEvent.getHandle(jet_token_); @@ -103,7 +103,7 @@ void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::Even iEvent.getByToken(cand_token_, cands_); iEvent.getByToken(sv_token_, svs_); - if(readBtag_){ + if (readBtag_) { iSetup.get().get("TransientTrackBuilder", track_builder_); } @@ -139,10 +139,10 @@ void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::Even sv_ntracks.push_back(sv->numberOfDaughters()); sv_chi2.push_back(sv->vertexChi2()); sv_normchi2.push_back(catch_infs_and_bound(sv->vertexChi2() / sv->vertexNdof(), 1000, -1000, 1000)); - const auto& dxy_meas = vertexDxy(*sv, *pv_); + const auto &dxy_meas = vertexDxy(*sv, *pv_); sv_dxy.push_back(dxy_meas.value()); sv_dxysig.push_back(catch_infs_and_bound(dxy_meas.value() / dxy_meas.error(), 0, -1, 800)); - const auto& d3d_meas = vertexD3d(*sv, *pv_); + const auto &d3d_meas = vertexD3d(*sv, *pv_); sv_d3d.push_back(d3d_meas.value()); sv_d3dsig.push_back(catch_infs_and_bound(d3d_meas.value() / d3d_meas.error(), 0, -1, 800)); sv_costhetasvpv.push_back(vertexDdotP(*sv, *pv_)); @@ -154,24 +154,26 @@ void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::Even } } - // PF Cands - std::vector const & daughters = jet.daughterPtrVector(); + // PF Cands + std::vector const &daughters = jet.daughterPtrVector(); for (const auto &cand : daughters) { auto candPtrs = cands_->ptrs(); - auto candInNewList = std::find( candPtrs.begin(), candPtrs.end(), cand ); - if ( candInNewList == candPtrs.end() ) { + auto candInNewList = std::find(candPtrs.begin(), candPtrs.end(), cand); + if (candInNewList == candPtrs.end()) { //std::cout << "Cannot find candidate : " << cand.id() << ", " << cand.key() << ", pt = " << cand->pt() << std::endl; continue; } outCands->push_back(cand); jetIdx_pf.push_back(i_jet); - candIdx.push_back( candInNewList - candPtrs.begin() ); + candIdx.push_back(candInNewList - candPtrs.begin()); if (readBtag_ && !vtxs_->empty()) { - if ( cand.isNull() ) continue; - auto const *packedCand = dynamic_cast (cand.get()); - if ( packedCand == nullptr ) continue; - if ( packedCand && packedCand->hasTrackDetails()){ + if (cand.isNull()) + continue; + auto const *packedCand = dynamic_cast(cand.get()); + if (packedCand == nullptr) + continue; + if (packedCand && packedCand->hasTrackDetails()) { btagbtvdeep::TrackInfoBuilder trkinfo(track_builder_); trkinfo.buildTrackInfo(&(*packedCand), jet_dir, jet_ref_track_dir, vtxs_->at(0)); btagEtaRel.push_back(trkinfo.getTrackEtaRel()); @@ -181,12 +183,12 @@ void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::Even btagSip3dSig.push_back(trkinfo.getTrackSip3dSig()); btagJetDistVal.push_back(trkinfo.getTrackJetDistVal()); } else { - btagEtaRel.push_back(0); - btagPtRatio.push_back(0); - btagPParRatio.push_back(0); - btagSip3dVal.push_back(0); - btagSip3dSig.push_back(0); - btagJetDistVal.push_back(0); + btagEtaRel.push_back(0); + btagPtRatio.push_back(0); + btagPParRatio.push_back(0); + btagSip3dVal.push_back(0); + btagSip3dSig.push_back(0); + btagJetDistVal.push_back(0); } } } // end jet loop @@ -206,7 +208,7 @@ void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::Even } iEvent.put(std::move(candTable), name_); - // SV table + // SV table auto svTable = std::make_unique(outSVs->size(), nameSV_, false); // We fill from here only stuff that cannot be created with the SimpleFlatTnameableProducer svTable->addColumn("jetIdx", jetIdx_sv, "Index of the parent jet"); @@ -232,7 +234,7 @@ void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::Even iEvent.put(std::move(outCands)); } -template< typename T> +template void JetConstituentTableProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { edm::ParameterSetDescription desc; desc.add("name", "JetPFCands"); diff --git a/PhysicsTools/NanoAOD/python/addPFCands_cff.py b/PhysicsTools/NanoAOD/python/addPFCands_cff.py index b48e35abd026a..2370f31cb0f48 100644 --- a/PhysicsTools/NanoAOD/python/addPFCands_cff.py +++ b/PhysicsTools/NanoAOD/python/addPFCands_cff.py @@ -31,13 +31,14 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal process.customizedPFCandsTask.add(process.finalJetsAK8Constituents) process.finalJetsConstituents = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) candInput = cms.InputTag("finalJetsConstituents") + process.customConstituentsExtTable = cms.EDProducer("SimpleCandidateFlatTableProducer", - src = candInput, + src = candInput, #stores PFcands based on chosen inputs (all PF candidates, only those belonging to the FatJet collection, etc...) cut = cms.string(""), #we should not filter after pruning name = cms.string("PFCands"), - doc = cms.string("interesting particles from selected candidate collection"), + doc = cms.string("Interesting particles from chosen candidate collection."), singleton = cms.bool(False), # the number of entries is variable - extension = cms.bool(False), # this is the extension table for the AK8 constituents + extension = cms.bool(False), variables = cms.PSet(CandVars, puppiWeight = Var("puppiWeight()", float, doc="Puppi weight",precision=10), puppiWeightNoLep = Var("puppiWeightNoLep()", float, doc="Puppi weight removing leptons",precision=10), @@ -52,19 +53,21 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal trkQuality = Var("?hasTrackDetails()?pseudoTrack().qualityMask():0", int, doc="track quality mask"), ) ) + + # AK8 PF PUPPI Jet table (FetJet in NanoAOD) process.customAK8ConstituentsTable = cms.EDProducer("PatJetConstituentTableProducer", candidates = candInput, jets = cms.InputTag("finalJetsAK8"), jet_radius = cms.double(0.8), - name = cms.string("JetPFCandsAK8"), - nameSV = cms.string("JetSVsAK8")) + name = cms.string("FatJetPFCands"), + nameSV = cms.string("FatJetSVs")) + # AK4 PF CHS Jet table (Jet in NanoAOD) process.customAK4ConstituentsTable = cms.EDProducer("PatJetConstituentTableProducer", - #candidates = cms.InputTag("packedPFCandidates"), candidates = candInput, jets = cms.InputTag("finalJets"), jet_radius = cms.double(0.4), - name = cms.string("JetPFCandsAK4"), - nameSV = cms.string("JetSVsAK4")) + name = cms.string("JetPFCands"), + nameSV = cms.string("JetSVs")) if not allPF: process.customizedPFCandsTask.add(process.finalJetsConstituents) process.customizedPFCandsTask.add(process.customConstituentsExtTable) @@ -97,27 +100,31 @@ def addPFCands(process, runOnMC=False, allPF = False, onlyAK4=False, onlyAK8=Fal genCandList = cms.VInputTag(cms.InputTag("genJetsAK4Constituents", "constituents"), cms.InputTag("genJetsAK8Constituents", "constituents")) genCandInput = cms.InputTag("genJetsConstituents") process.genJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = genCandList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + process.genJetsParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", src = genCandInput, cut = cms.string(""), #we should not filter after pruning name= cms.string("GenParticles"), - doc = cms.string("interesting gen particles from selected candidate collection"), + doc = cms.string("Interesting gen particles from entire candidate collection."), singleton = cms.bool(False), # the number of entries is variable extension = cms.bool(False), # this is the main table for the AK8 constituents variables = cms.PSet(CandVars ) ) + + # AK4 Gen Jet table (GenJet in NanoAOD) process.genAK8ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", candidates = genCandInput, jets = cms.InputTag("genJetsAK8Constituents"), # Note: The name has "Constituents" in it, but these are the jets - name = cms.string("GenJetCandsAK8"), - nameSV = cms.string("GenJetSVsAK8"), + name = cms.string("GenJetAK8Particles"), + nameSV = cms.string("GenJetAK8SVs"), readBtag = cms.bool(False)) + # AK8 Gen Jet table (GenJetAK8 in NanoAOD) process.genAK4ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", candidates = genCandInput, jets = cms.InputTag("genJetsAK4Constituents"), # Note: The name has "Constituents" in it, but these are the jets - name = cms.string("GenJetCandsAK4"), - nameSV = cms.string("GenJetSVsAK4"), + name = cms.string("GenJetParticles"), + nameSV = cms.string("GenJetSVs"), readBtag = cms.bool(False)) process.customizedPFCandsTask.add(process.genJetsAK4Constituents) #Note: For gen need to add jets to the process to keep pt cuts. process.customizedPFCandsTask.add(process.genJetsAK8Constituents)