File indexing completed on 2024-04-06 12:25:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include "InputGenJetsParticleSelector.h"
0041 #include "FWCore/Framework/interface/MakerMacros.h"
0042 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0043
0044 #include <memory>
0045 #include "CommonTools/CandUtils/interface/pdgIdUtils.h"
0046
0047 using namespace std;
0048
0049 InputGenJetsParticleSelector::InputGenJetsParticleSelector(const edm::ParameterSet ¶ms)
0050 : inTag(params.getParameter<edm::InputTag>("src")),
0051 prunedInTag(params.exists("prunedGenParticles") ? params.getParameter<edm::InputTag>("prunedGenParticles")
0052 : edm::InputTag("prunedGenParticles")),
0053 partonicFinalState(params.getParameter<bool>("partonicFinalState")),
0054 excludeResonances(params.getParameter<bool>("excludeResonances")),
0055 tausAsJets(params.getParameter<bool>("tausAsJets")),
0056 ptMin(0.0) {
0057 if (params.exists("ignoreParticleIDs"))
0058 setIgnoredParticles(params.getParameter<std::vector<unsigned int> >("ignoreParticleIDs"));
0059 setExcludeFromResonancePids(params.getParameter<std::vector<unsigned int> >("excludeFromResonancePids"));
0060 isMiniAOD =
0061 (params.exists("isMiniAOD") ? params.getParameter<bool>("isMiniAOD") : (inTag.label() == "packedGenParticles"));
0062
0063 if (isMiniAOD && partonicFinalState) {
0064 edm::LogError("PartonicFinalStateFromMiniAOD")
0065 << "Partonic final state not supported for MiniAOD. Falling back to the stable particle selection.";
0066 partonicFinalState = false;
0067 }
0068
0069 produces<reco::CandidatePtrVector>();
0070
0071 input_genpartcoll_token_ = consumes<reco::CandidateView>(inTag);
0072 if (isMiniAOD)
0073 input_prunedgenpartcoll_token_ = consumes<reco::CandidateView>(prunedInTag);
0074 }
0075
0076 InputGenJetsParticleSelector::~InputGenJetsParticleSelector() {}
0077
0078 void InputGenJetsParticleSelector::setIgnoredParticles(const std::vector<unsigned int> &particleIDs) {
0079 ignoreParticleIDs = particleIDs;
0080 std::sort(ignoreParticleIDs.begin(), ignoreParticleIDs.end());
0081 }
0082
0083 void InputGenJetsParticleSelector::setExcludeFromResonancePids(const std::vector<unsigned int> &particleIDs) {
0084 excludeFromResonancePids = particleIDs;
0085 std::sort(excludeFromResonancePids.begin(), excludeFromResonancePids.end());
0086 }
0087
0088 bool InputGenJetsParticleSelector::isParton(int pdgId) const {
0089 pdgId = (pdgId > 0 ? pdgId : -pdgId) % 10000;
0090 return (pdgId > 0 && pdgId < 6) || pdgId == 9 || (tausAsJets && pdgId == 15) || pdgId == 21;
0091
0092
0093 }
0094
0095 bool InputGenJetsParticleSelector::isHadron(int pdgId) {
0096 pdgId = (pdgId > 0 ? pdgId : -pdgId) % 10000;
0097 return (pdgId > 100 && pdgId < 900) || (pdgId > 1000 && pdgId < 9000);
0098 }
0099
0100 bool InputGenJetsParticleSelector::isResonance(int pdgId) {
0101
0102 pdgId = (pdgId > 0 ? pdgId : -pdgId) % 10000;
0103 return (pdgId > 21 && pdgId <= 42) || pdgId == 6 || pdgId == 7 || pdgId == 8;
0104 }
0105
0106 bool InputGenJetsParticleSelector::isIgnored(int pdgId) const {
0107 pdgId = pdgId > 0 ? pdgId : -pdgId;
0108 std::vector<unsigned int>::const_iterator pos =
0109 std::lower_bound(ignoreParticleIDs.begin(), ignoreParticleIDs.end(), (unsigned int)pdgId);
0110 return pos != ignoreParticleIDs.end() && *pos == (unsigned int)pdgId;
0111 }
0112
0113 bool InputGenJetsParticleSelector::isExcludedFromResonance(int pdgId) const {
0114 pdgId = pdgId > 0 ? pdgId : -pdgId;
0115 std::vector<unsigned int>::const_iterator pos =
0116 std::lower_bound(excludeFromResonancePids.begin(), excludeFromResonancePids.end(), (unsigned int)pdgId);
0117 return pos != excludeFromResonancePids.end() && *pos == (unsigned int)pdgId;
0118 }
0119
0120 static unsigned int partIdx(const InputGenJetsParticleSelector::ParticleVector &p, const reco::Candidate *particle) {
0121 InputGenJetsParticleSelector::ParticleVector::const_iterator pos = std::lower_bound(p.begin(), p.end(), particle);
0122 if (pos == p.end() || *pos != particle)
0123 throw cms::Exception("CorruptedData") << "reco::GenEvent corrupted: Unlisted particles"
0124 " in decay tree."
0125 << std::endl;
0126
0127 return pos - p.begin();
0128 }
0129
0130 static void invalidateTree(InputGenJetsParticleSelector::ParticleBitmap &invalid,
0131 const InputGenJetsParticleSelector::ParticleVector &p,
0132 const reco::Candidate *particle) {
0133 unsigned int npart = particle->numberOfDaughters();
0134 if (!npart)
0135 return;
0136
0137 for (unsigned int i = 0; i < npart; ++i) {
0138 unsigned int idx = partIdx(p, particle->daughter(i));
0139 if (invalid[idx])
0140 continue;
0141 invalid[idx] = true;
0142
0143 invalidateTree(invalid, p, particle->daughter(i));
0144 }
0145 }
0146
0147 int InputGenJetsParticleSelector::testPartonChildren(InputGenJetsParticleSelector::ParticleBitmap &invalid,
0148 const InputGenJetsParticleSelector::ParticleVector &p,
0149 const reco::Candidate *particle) const {
0150 unsigned int npart = particle->numberOfDaughters();
0151 if (!npart) {
0152 return 0;
0153 }
0154
0155 for (unsigned int i = 0; i < npart; ++i) {
0156 unsigned int idx = partIdx(p, particle->daughter(i));
0157 if (invalid[idx])
0158 continue;
0159 if (isParton((particle->daughter(i)->pdgId()))) {
0160 return 1;
0161 }
0162 if (isHadron((particle->daughter(i)->pdgId()))) {
0163 return -1;
0164 }
0165 int result = testPartonChildren(invalid, p, particle->daughter(i));
0166 if (result)
0167 return result;
0168 }
0169 return 0;
0170 }
0171
0172 InputGenJetsParticleSelector::ResonanceState InputGenJetsParticleSelector::fromResonance(
0173 ParticleBitmap &invalid, const ParticleVector &p, const reco::Candidate *particle) const {
0174 unsigned int idx = partIdx(p, particle);
0175 int id = particle->pdgId();
0176
0177 if (invalid[idx])
0178 return kIndirect;
0179
0180 if (isResonance(id) && (particle->status() == 3 || particle->status() == 22)) {
0181 return kDirect;
0182 }
0183
0184 if (!isIgnored(id) && (isParton(id)))
0185 return kNo;
0186
0187 unsigned int nMo = particle->numberOfMothers();
0188 if (!nMo)
0189 return kNo;
0190
0191 for (unsigned int i = 0; i < nMo; ++i) {
0192 ResonanceState result = fromResonance(invalid, p, particle->mother(i));
0193 switch (result) {
0194 case kNo:
0195 break;
0196 case kDirect:
0197 if (particle->mother(i)->pdgId() == id || isResonance(id))
0198 return kDirect;
0199 if (!isExcludedFromResonance(id))
0200 break;
0201 [[fallthrough]];
0202 case kIndirect:
0203 return kIndirect;
0204 }
0205 }
0206 return kNo;
0207 }
0208
0209 bool InputGenJetsParticleSelector::hasPartonChildren(ParticleBitmap &invalid,
0210 const ParticleVector &p,
0211 const reco::Candidate *particle) const {
0212 return testPartonChildren(invalid, p, particle) > 0;
0213 }
0214
0215
0216
0217 void InputGenJetsParticleSelector::produce(edm::StreamID, edm::Event &evt, const edm::EventSetup &evtSetup) const {
0218 auto selected_ = std::make_unique<reco::CandidatePtrVector>();
0219
0220 ParticleVector particles;
0221
0222 edm::Handle<reco::CandidateView> prunedGenParticles;
0223 if (isMiniAOD) {
0224 evt.getByToken(input_prunedgenpartcoll_token_, prunedGenParticles);
0225
0226 for (edm::View<reco::Candidate>::const_iterator iter = prunedGenParticles->begin();
0227 iter != prunedGenParticles->end();
0228 ++iter) {
0229 if (iter->status() !=
0230 1)
0231 particles.push_back(&*iter);
0232 }
0233 }
0234
0235 edm::Handle<reco::CandidateView> genParticles;
0236 evt.getByToken(input_genpartcoll_token_, genParticles);
0237
0238 std::map<const reco::Candidate *, size_t> particlePtrIdxMap;
0239
0240 for (edm::View<reco::Candidate>::const_iterator iter = genParticles->begin(); iter != genParticles->end(); ++iter) {
0241 particles.push_back(&*iter);
0242 particlePtrIdxMap[&*iter] = (iter - genParticles->begin());
0243 }
0244
0245 std::sort(particles.begin(), particles.end());
0246 unsigned int size = particles.size();
0247
0248 ParticleBitmap selected(size, false);
0249 ParticleBitmap invalid(size, false);
0250
0251 for (unsigned int i = 0; i < size; i++) {
0252 const reco::Candidate *particle = particles[i];
0253 if (invalid[i])
0254 continue;
0255 if (particle->status() == 1)
0256 selected[i] = true;
0257 if (partonicFinalState && isParton(particle->pdgId())) {
0258 if (particle->numberOfDaughters() == 0 && particle->status() != 1) {
0259
0260 invalid[i] = true;
0261 } else if (!hasPartonChildren(invalid, particles, particle)) {
0262 selected[i] = true;
0263 invalidateTree(invalid, particles, particle);
0264 }
0265 }
0266 }
0267
0268 for (size_t idx = 0; idx < size; ++idx) {
0269 const reco::Candidate *particle = particles[idx];
0270 if (!selected[idx] || invalid[idx]) {
0271 continue;
0272 }
0273
0274 if (excludeResonances && fromResonance(invalid, particles, particle)) {
0275 invalid[idx] = true;
0276
0277 continue;
0278 }
0279
0280 if (isIgnored(particle->pdgId())) {
0281 continue;
0282 }
0283
0284 if (particle->pt() >= ptMin) {
0285 selected_->push_back(genParticles->ptrAt(particlePtrIdxMap[particle]));
0286
0287 }
0288 }
0289 evt.put(std::move(selected_));
0290 }
0291
0292
0293 DEFINE_FWK_MODULE(InputGenJetsParticleSelector);