Backporting MC jet flavour definition from CMSSW 9 to CMSSW 8

Intro

This backports the new jet flavour definition in CMSSW 9 into CMSSW 8. It runs over MiniAOD, updating the partonFlavor() attribute of a pat::Jet collection.

In this new definition, you recluster each jet's constituents along with all genpartons as “ghosts”, then pick the highest pT genparton that gets clustered, irrespective of status.
This way it can work for both Pythia and Herwig (in the former it often corresponds to status==23 particle anyway for MG+Pythia8).

Reference PRs:

https://github.com/cms-sw/cmssw/pull/19048/
https://github.com/cms-sw/cmssw/pull/20281/
https://github.com/cms-sw/cmssw/pull/20840/

https://indico.cern.ch/event/649196/contributions/2641282/attachments/1483715/2302215/JetFlavour.pdf

In terms of modules, this is how the partonFlavour gets calculated normally:

  • A HadronAndPartonSelector EDProducer produces collections of partons (both algortimicPartons and physicsPartons), leptons, bHadrons, and cHadrons from some input collection (often genParticles) according to some selection criteria. This is the critical part that determines which gen particles can be used for the flavour definition.
  • A JetFlavourClustering EDProducer takes in these collections, along with some jet collection, and does the ghost reclustering. The jet:flavour info is stored as a JetFlavourInfoMatchingCollection, which is really a edm::AssociationVector<edm::RefToBaseProd<reco::Jet>,std::vector<reco::JetFlavourInfo> > (i.e. a map between a reference to a Jet, and a JetFlavourInfo object)
This is normally done on reco::Jet when making the MiniAOD, and gets stored when the pat::Jets are made.

However, if you just want to run over MiniAOD you will need another module to update the pat::Jets (which I have written).

JERC presentation: https://indico.cern.ch/event/684468/contributions/2806100/attachments/1567041/2470474/jec_29_11_17.pdf

Old flavour definitions

In the Summer16 MiniAOD, the partonFlavour is from the algorithmicPartons. These are selected on a per-generator basis. For Pythia8, this includes all partons (not status 1 or 2) with no daughters, i.e. at end of parton showering sequence. So expect the new and old partonFlavour() to differ.

There is also the pat::Jet::genParton() attribute. This uses another method of determining flavour: it looks for status 3 or 23 genPartons, and then matches by ∆R to each jet. The closest one is the assigned genParton. Since these are often pre-showering, they are generally hardest and thus will often give the same result as the new partonFlavour. However, this method only works for MG+Pythia8 samples.

Any comments, questions: robin DOT aggleton AT cern DOT ch

Instructions

The full PRs update both how the definition is calculated, as well as configs for making MiniAOD. We don't need that, so I have only picked the necessary algorithmic parts. I have also added a small pat::Jet updater module.

This was done on top of CMSSW 8_0_28, but should work across 80X releases.

To merge the changes, simply do:

git cms-merge-topic raggleton:Backport_JetFlavour

For reference, incase you want to manually apply the diffs:

Algorithmic changes: https://github.com/raggleton/cmssw/commit/8a04d7bdd690b815f9f65b74ef45cf30c0e5a9f4

pat::Jet updater: https://github.com/raggleton/cmssw/commit/f0d5542b24478f9f6196440131766cbc7a0793e0

Usage

To update your pat::Jets you will need such a snippet in your config:

# Select the genpartons to be used for flavour info 
process.selectedHadronsAndPartons = cms.EDProducer('HadronAndPartonSelector',
 src = cms.InputTag("generator"),
 particles = cms.InputTag("prunedGenParticles"),
 partonMode = cms.string("Auto"),
 fullChainPhysPartons = cms.bool(True)
)
# Create the jet:flavour mapping using your jets and selected genpartons 
process.ak4CHSJetFlavourInfos = cms.EDProducer("JetFlavourClustering",
 jets = cms.InputTag("slimmedJets"),
 bHadrons = cms.InputTag("selectedHadronsAndPartons","bHadrons"),
 cHadrons = cms.InputTag("selectedHadronsAndPartons","cHadrons"),
 partons = cms.InputTag("selectedHadronsAndPartons","physicsPartons"),
 leptons = cms.InputTag("selectedHadronsAndPartons","leptons"),
 jetAlgorithm = cms.string("AntiKt"),
 rParam = cms.double(0.4), # Must match the parameter of the input jets
 ghostRescaling = cms.double(1e-18),
 relPtTolerance = cms.double(5), # large as we are dealing with calibrated jets
 hadronFlavourHasPriority = cms.bool(False)
)
# This updates our slimmedJets - must use same collection you gave to the JetFlavourClustering module! 
process.updateFlavAK4CHSJets = cms.EDProducer("UpdatePatJetFlavourInfo",
 jetSrc = cms.InputTag("slimmedJets"),
 jetFlavourInfos = cms.InputTag("ak4CHSJetFlavourInfos")
)
 

You can then use the output of updateFlavAK4CHSJets. The only updated attribute is partonFlavour() (in particular, you can therefore compare with pat::Jet::genParton()).

Note that because our input collection is calibrated, when performing the reclustering the resultant jet energy will be different. We therefor set relPtTolerance rather large.

But you should really un-apply JEC, do flavour stuff, reapply JEC.

Alternatively, you can produce a jet collection that removes the JEC, then apply the JEC after the flavour updating.

IMPORTANT: this method doesn't work properly for slimmed PUPPI jets as the puppi weight is not taken into account

-- RobinAggleton - 2017-12-08

Edit | Attach | Watch | Print version | History: r6 < r5 < r4 < r3 < r2 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r6 - 2018-02-09 - RobinAggleton
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback