File indexing completed on 2024-04-06 12:31:13
0001 #include "DataFormats/Math/interface/deltaR.h"
0002 #include "CommonTools/Utils/interface/PtComparator.h"
0003
0004 #include "RecoJets/JetProducers/interface/JetSpecific.h"
0005 #include "fastjet/ClusterSequence.hh"
0006
0007 #include "FWCore/Framework/interface/Frameworkfwd.h"
0008 #include "FWCore/Framework/interface/stream/EDProducer.h"
0009 #include "FWCore/Framework/interface/Event.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011
0012 #include "DataFormats/Candidate/interface/Candidate.h"
0013 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0014
0015 #include "fastjet/JetDefinition.hh"
0016 #include <set>
0017
0018 class PseudoTopProducer : public edm::stream::EDProducer<> {
0019 public:
0020 PseudoTopProducer(const edm::ParameterSet& pset);
0021 void produce(edm::Event& event, const edm::EventSetup& eventSetup) override;
0022
0023 private:
0024 bool isFromHadron(const reco::Candidate* p) const;
0025 bool isBHadron(const reco::Candidate* p) const;
0026 bool isBHadron(const unsigned int pdgId) const;
0027
0028 typedef reco::Particle::LorentzVector LorentzVector;
0029
0030 private:
0031 const edm::EDGetTokenT<edm::View<reco::Candidate> > finalStateToken_;
0032 const edm::EDGetTokenT<edm::View<reco::Candidate> > genParticleToken_;
0033 const double minLeptonPt_, maxLeptonEta_, minJetPt_, maxJetEta_;
0034 const double wMass_, tMass_;
0035 const double minLeptonPtDilepton_, maxLeptonEtaDilepton_;
0036 const double minDileptonMassDilepton_;
0037 const double minLeptonPtSemilepton_, maxLeptonEtaSemilepton_;
0038 const double minVetoLeptonPtSemilepton_, maxVetoLeptonEtaSemilepton_;
0039 const double minMETSemiLepton_, minMtWSemiLepton_;
0040
0041 typedef fastjet::JetDefinition JetDef;
0042 std::shared_ptr<JetDef> fjLepDef_, fjJetDef_;
0043 reco::Particle::Point genVertex_;
0044 };
0045
0046 using namespace std;
0047 using namespace edm;
0048 using namespace reco;
0049
0050 PseudoTopProducer::PseudoTopProducer(const edm::ParameterSet& pset)
0051 : finalStateToken_(consumes<edm::View<reco::Candidate> >(pset.getParameter<edm::InputTag>("finalStates"))),
0052 genParticleToken_(consumes<edm::View<reco::Candidate> >(pset.getParameter<edm::InputTag>("genParticles"))),
0053 minLeptonPt_(pset.getParameter<double>("minLeptonPt")),
0054 maxLeptonEta_(pset.getParameter<double>("maxLeptonEta")),
0055 minJetPt_(pset.getParameter<double>("minJetPt")),
0056 maxJetEta_(pset.getParameter<double>("maxJetEta")),
0057 wMass_(pset.getParameter<double>("wMass")),
0058 tMass_(pset.getParameter<double>("tMass")),
0059 minLeptonPtDilepton_(pset.getParameter<double>("minLeptonPtDilepton")),
0060 maxLeptonEtaDilepton_(pset.getParameter<double>("maxLeptonEtaDilepton")),
0061 minDileptonMassDilepton_(pset.getParameter<double>("minDileptonMassDilepton")),
0062 minLeptonPtSemilepton_(pset.getParameter<double>("minLeptonPtSemilepton")),
0063 maxLeptonEtaSemilepton_(pset.getParameter<double>("maxLeptonEtaSemilepton")),
0064 minVetoLeptonPtSemilepton_(pset.getParameter<double>("minVetoLeptonPtSemilepton")),
0065 maxVetoLeptonEtaSemilepton_(pset.getParameter<double>("maxVetoLeptonEtaSemilepton")),
0066 minMETSemiLepton_(pset.getParameter<double>("minMETSemiLepton")),
0067 minMtWSemiLepton_(pset.getParameter<double>("minMtWSemiLepton")) {
0068 const double leptonConeSize = pset.getParameter<double>("leptonConeSize");
0069 const double jetConeSize = pset.getParameter<double>("jetConeSize");
0070 fjLepDef_ = std::make_shared<JetDef>(fastjet::antikt_algorithm, leptonConeSize);
0071 fjJetDef_ = std::make_shared<JetDef>(fastjet::antikt_algorithm, jetConeSize);
0072
0073 genVertex_ = reco::Particle::Point(0, 0, 0);
0074
0075 produces<reco::GenParticleCollection>("neutrinos");
0076 produces<reco::GenJetCollection>("leptons");
0077 produces<reco::GenJetCollection>("jets");
0078
0079 produces<reco::GenParticleCollection>();
0080 }
0081
0082 void PseudoTopProducer::produce(edm::Event& event, const edm::EventSetup& eventSetup) {
0083 edm::Handle<edm::View<reco::Candidate> > finalStateHandle;
0084 event.getByToken(finalStateToken_, finalStateHandle);
0085
0086 edm::Handle<edm::View<reco::Candidate> > genParticleHandle;
0087 event.getByToken(genParticleToken_, genParticleHandle);
0088
0089 std::unique_ptr<reco::GenParticleCollection> neutrinos(new reco::GenParticleCollection);
0090 std::unique_ptr<reco::GenJetCollection> leptons(new reco::GenJetCollection);
0091 std::unique_ptr<reco::GenJetCollection> jets(new reco::GenJetCollection);
0092 auto neutrinosRefHandle = event.getRefBeforePut<reco::GenParticleCollection>("neutrinos");
0093 auto leptonsRefHandle = event.getRefBeforePut<reco::GenJetCollection>("leptons");
0094 auto jetsRefHandle = event.getRefBeforePut<reco::GenJetCollection>("jets");
0095
0096 std::unique_ptr<reco::GenParticleCollection> pseudoTop(new reco::GenParticleCollection);
0097 auto pseudoTopRefHandle = event.getRefBeforePut<reco::GenParticleCollection>();
0098
0099
0100 std::set<int> bHadronIdxs;
0101 for (size_t i = 0, n = genParticleHandle->size(); i < n; ++i) {
0102 const reco::Candidate& p = genParticleHandle->at(i);
0103 const int status = p.status();
0104 if (status == 1)
0105 continue;
0106
0107
0108 if (isBHadron(&p))
0109 bHadronIdxs.insert(-i - 1);
0110 }
0111
0112
0113 size_t nStables = 0;
0114 std::vector<size_t> leptonIdxs;
0115 for (size_t i = 0, n = finalStateHandle->size(); i < n; ++i) {
0116 const reco::Candidate& p = finalStateHandle->at(i);
0117 const int absPdgId = abs(p.pdgId());
0118 if (p.status() != 1)
0119 continue;
0120
0121 ++nStables;
0122 if (p.numberOfMothers() == 0)
0123 continue;
0124 if (p.mother()->status() == 4)
0125 continue;
0126 if (isFromHadron(&p))
0127 continue;
0128 switch (absPdgId) {
0129 case 11:
0130 case 13:
0131 case 22:
0132 leptonIdxs.push_back(i);
0133 break;
0134 case 12:
0135 case 14:
0136 case 16:
0137 neutrinos->push_back(reco::GenParticle(p.charge(), p.p4(), p.vertex(), p.pdgId(), p.status(), true));
0138 break;
0139 }
0140 }
0141
0142
0143 std::sort(neutrinos->begin(), neutrinos->end(), GreaterByPt<reco::Candidate>());
0144
0145
0146
0147 std::vector<fastjet::PseudoJet> fjLepInputs;
0148 fjLepInputs.reserve(leptonIdxs.size());
0149 for (auto index : leptonIdxs) {
0150 const reco::Candidate& p = finalStateHandle->at(index);
0151 if (std::isnan(p.pt()) or p.pt() <= 0)
0152 continue;
0153
0154 fjLepInputs.push_back(fastjet::PseudoJet(p.px(), p.py(), p.pz(), p.energy()));
0155 fjLepInputs.back().set_user_index(index);
0156 }
0157
0158
0159 fastjet::ClusterSequence fjLepClusterSeq(fjLepInputs, *fjLepDef_);
0160 std::vector<fastjet::PseudoJet> fjLepJets = fastjet::sorted_by_pt(fjLepClusterSeq.inclusive_jets(minLeptonPt_));
0161
0162
0163 leptons->reserve(fjLepJets.size());
0164 std::set<size_t> lepDauIdxs;
0165 for (auto& fjJet : fjLepJets) {
0166 if (abs(fjJet.eta()) > maxLeptonEta_)
0167 continue;
0168
0169
0170 const std::vector<fastjet::PseudoJet> fjConstituents = fastjet::sorted_by_pt(fjJet.constituents());
0171
0172 std::vector<reco::CandidatePtr> constituents;
0173 reco::CandidatePtr lepCand;
0174 for (auto& fjConstituent : fjConstituents) {
0175 const size_t index = fjConstituent.user_index();
0176 reco::CandidatePtr cand = finalStateHandle->ptrAt(index);
0177 const int absPdgId = abs(cand->pdgId());
0178 if (absPdgId == 11 or absPdgId == 13) {
0179 if (lepCand.isNonnull() and lepCand->pt() > cand->pt())
0180 continue;
0181 lepCand = cand;
0182 }
0183 constituents.push_back(cand);
0184 }
0185 if (lepCand.isNull())
0186 continue;
0187
0188 const LorentzVector jetP4(fjJet.px(), fjJet.py(), fjJet.pz(), fjJet.E());
0189 reco::GenJet lepJet;
0190 reco::writeSpecific(lepJet, jetP4, genVertex_, constituents);
0191
0192 lepJet.setPdgId(lepCand->pdgId());
0193 lepJet.setCharge(lepCand->charge());
0194
0195 const double jetArea = fjJet.has_area() ? fjJet.area() : 0;
0196 lepJet.setJetArea(jetArea);
0197
0198 leptons->push_back(lepJet);
0199
0200
0201 for (auto& fjConstituent : fjConstituents) {
0202 lepDauIdxs.insert(fjConstituent.user_index());
0203 }
0204 }
0205
0206
0207
0208
0209 std::vector<fastjet::PseudoJet> fjJetInputs;
0210 fjJetInputs.reserve(nStables);
0211 for (size_t i = 0, n = finalStateHandle->size(); i < n; ++i) {
0212 const reco::Candidate& p = finalStateHandle->at(i);
0213 if (p.status() != 1)
0214 continue;
0215 if (std::isnan(p.pt()) or p.pt() <= 0)
0216 continue;
0217
0218 const int absId = std::abs(p.pdgId());
0219 if (absId == 12 or absId == 14 or absId == 16)
0220 continue;
0221 if (lepDauIdxs.find(i) != lepDauIdxs.end())
0222 continue;
0223
0224 fjJetInputs.push_back(fastjet::PseudoJet(p.px(), p.py(), p.pz(), p.energy()));
0225 fjJetInputs.back().set_user_index(i);
0226 }
0227
0228 for (auto index : bHadronIdxs) {
0229 const reco::Candidate& p = genParticleHandle->at(abs(index + 1));
0230 if (std::isnan(p.pt()) or p.pt() <= 0)
0231 continue;
0232
0233 const double scale = 1e-20 / p.p();
0234 fjJetInputs.push_back(fastjet::PseudoJet(p.px() * scale, p.py() * scale, p.pz() * scale, p.energy() * scale));
0235 fjJetInputs.back().set_user_index(index);
0236 }
0237
0238
0239 fastjet::ClusterSequence fjJetClusterSeq(fjJetInputs, *fjJetDef_);
0240 std::vector<fastjet::PseudoJet> fjJets = fastjet::sorted_by_pt(fjJetClusterSeq.inclusive_jets(minJetPt_));
0241
0242
0243 jets->reserve(fjJets.size());
0244 std::vector<size_t> bjetIdxs, ljetIdxs;
0245 for (auto& fjJet : fjJets) {
0246 if (abs(fjJet.eta()) > maxJetEta_)
0247 continue;
0248
0249
0250 const std::vector<fastjet::PseudoJet> fjConstituents = fastjet::sorted_by_pt(fjJet.constituents());
0251
0252 std::vector<reco::CandidatePtr> constituents;
0253 bool hasBHadron = false;
0254 for (size_t j = 0, m = fjConstituents.size(); j < m; ++j) {
0255 const int index = fjConstituents[j].user_index();
0256 if (bHadronIdxs.find(index) != bHadronIdxs.end()) {
0257 hasBHadron = true;
0258 continue;
0259 }
0260 reco::CandidatePtr cand = finalStateHandle->ptrAt(index);
0261 constituents.push_back(cand);
0262 }
0263
0264 const LorentzVector jetP4(fjJet.px(), fjJet.py(), fjJet.pz(), fjJet.E());
0265 reco::GenJet genJet;
0266 reco::writeSpecific(genJet, jetP4, genVertex_, constituents);
0267
0268 const double jetArea = fjJet.has_area() ? fjJet.area() : 0;
0269 genJet.setJetArea(jetArea);
0270 if (hasBHadron) {
0271 genJet.setPdgId(5);
0272 bjetIdxs.push_back(jets->size());
0273 } else {
0274 ljetIdxs.push_back(jets->size());
0275 }
0276
0277 jets->push_back(genJet);
0278 }
0279
0280
0281
0282 do {
0283 if (bjetIdxs.size() < 2)
0284 break;
0285
0286
0287 if (leptons->size() == 2 and neutrinos->size() >= 2) {
0288
0289 const int q1 = leptons->at(0).charge();
0290 const int q2 = leptons->at(1).charge();
0291 if (q1 * q2 > 0)
0292 break;
0293
0294 const auto& lepton1 = q1 > 0 ? leptons->at(0) : leptons->at(1);
0295 const auto& lepton2 = q1 > 0 ? leptons->at(1) : leptons->at(0);
0296
0297 if (lepton1.pt() < minLeptonPtDilepton_ or std::abs(lepton1.eta()) > maxLeptonEtaDilepton_)
0298 break;
0299 if (lepton2.pt() < minLeptonPtDilepton_ or std::abs(lepton2.eta()) > maxLeptonEtaDilepton_)
0300 break;
0301 if ((lepton1.p4() + lepton2.p4()).mass() < minDileptonMassDilepton_)
0302 break;
0303
0304 double dm = 1e9;
0305 int selNu1 = -1, selNu2 = -1;
0306 for (int i = 0; i < 2; ++i) {
0307 const double dm1 = std::abs((lepton1.p4() + neutrinos->at(i).p4()).mass() - wMass_);
0308 for (int j = 0; j < 2; ++j) {
0309 if (i == j)
0310 continue;
0311 const double dm2 = std::abs((lepton2.p4() + neutrinos->at(j).p4()).mass() - wMass_);
0312 const double newDm = dm1 + dm2;
0313
0314 if (newDm < dm) {
0315 dm = newDm;
0316 selNu1 = i;
0317 selNu2 = j;
0318 }
0319 }
0320 }
0321 if (dm >= 1e9)
0322 break;
0323
0324 const auto& nu1 = neutrinos->at(selNu1);
0325 const auto& nu2 = neutrinos->at(selNu2);
0326 const auto w1LVec = lepton1.p4() + nu1.p4();
0327 const auto w2LVec = lepton2.p4() + nu2.p4();
0328
0329
0330 dm = 1e9;
0331 int selB1 = -1, selB2 = -1;
0332 for (auto i : bjetIdxs) {
0333 const double dm1 = std::abs((w1LVec + jets->at(i).p4()).mass() - tMass_);
0334 for (auto j : bjetIdxs) {
0335 if (i == j)
0336 continue;
0337 const double dm2 = std::abs((w2LVec + jets->at(j).p4()).mass() - tMass_);
0338 const double newDm = dm1 + dm2;
0339
0340 if (newDm < dm) {
0341 dm = newDm;
0342 selB1 = i;
0343 selB2 = j;
0344 }
0345 }
0346 }
0347 if (dm >= 1e9)
0348 break;
0349
0350 const auto& bJet1 = jets->at(selB1);
0351 const auto& bJet2 = jets->at(selB2);
0352 const auto t1LVec = w1LVec + bJet1.p4();
0353 const auto t2LVec = w2LVec + bJet2.p4();
0354
0355
0356 const int lepQ1 = lepton1.charge();
0357 const int lepQ2 = lepton2.charge();
0358
0359
0360 reco::GenParticle t1(lepQ1 * 2 / 3., t1LVec, genVertex_, lepQ1 * 6, 3, false);
0361 reco::GenParticle w1(lepQ1, w1LVec, genVertex_, lepQ1 * 24, 3, true);
0362 reco::GenParticle b1(-lepQ1 / 3., bJet1.p4(), genVertex_, lepQ1 * 5, 1, true);
0363 reco::GenParticle l1(lepQ1, lepton1.p4(), genVertex_, lepton1.pdgId(), 1, true);
0364 reco::GenParticle n1(0, nu1.p4(), genVertex_, nu1.pdgId(), 1, true);
0365
0366 reco::GenParticle t2(lepQ2 * 2 / 3., t2LVec, genVertex_, lepQ2 * 6, 3, false);
0367 reco::GenParticle w2(lepQ2, w2LVec, genVertex_, lepQ2 * 24, 3, true);
0368 reco::GenParticle b2(-lepQ2 / 3., bJet2.p4(), genVertex_, lepQ2 * 5, 1, true);
0369 reco::GenParticle l2(lepQ2, lepton2.p4(), genVertex_, lepton2.pdgId(), 1, true);
0370 reco::GenParticle n2(0, nu2.p4(), genVertex_, nu2.pdgId(), 1, true);
0371
0372 pseudoTop->push_back(t1);
0373 pseudoTop->push_back(t2);
0374
0375 pseudoTop->push_back(w1);
0376 pseudoTop->push_back(b1);
0377 pseudoTop->push_back(l1);
0378 pseudoTop->push_back(n1);
0379
0380 pseudoTop->push_back(w2);
0381 pseudoTop->push_back(b2);
0382 pseudoTop->push_back(l2);
0383 pseudoTop->push_back(n2);
0384 } else if (!leptons->empty() and !neutrinos->empty() and ljetIdxs.size() >= 2) {
0385
0386 const auto& lepton = leptons->at(0);
0387 if (lepton.pt() < minLeptonPtSemilepton_ or std::abs(lepton.eta()) > maxLeptonEtaSemilepton_)
0388 break;
0389
0390
0391 bool hasVetoLepton = false;
0392 for (auto vetoLeptonItr = next(leptons->begin()); vetoLeptonItr != leptons->end(); ++vetoLeptonItr) {
0393 if (vetoLeptonItr->pt() > minVetoLeptonPtSemilepton_ and
0394 std::abs(vetoLeptonItr->eta()) < maxVetoLeptonEtaSemilepton_) {
0395 hasVetoLepton = true;
0396 }
0397 }
0398 if (hasVetoLepton)
0399 break;
0400
0401
0402 double metX = 0, metY = 0;
0403 for (const auto& neutrino : *neutrinos) {
0404 metX += neutrino.px();
0405 metY += neutrino.py();
0406 }
0407 const double metPt = std::hypot(metX, metY);
0408 if (metPt < minMETSemiLepton_)
0409 break;
0410
0411 const double mtW = std::sqrt(2 * lepton.pt() * metPt * cos(lepton.phi() - atan2(metX, metY)));
0412 if (mtW < minMtWSemiLepton_)
0413 break;
0414
0415
0416
0417
0418
0419
0420
0421 const double lpz = lepton.pz(), le = lepton.energy(), lpt = lepton.pt();
0422 const double cf = (wMass_ * wMass_) / 2 + lepton.px() * metX + lepton.py() * metY;
0423 const double det = cf * cf * lpz * lpz - lpt * lpt * (le * le * metPt * metPt - cf * cf);
0424 const double pz = (cf * lpz + (cf < 0 ? -sqrt(det) : sqrt(det))) / lpt / lpt;
0425 const reco::Candidate::LorentzVector nu1P4(metX, metY, pz, std::hypot(metPt, pz));
0426 const auto w1LVec = lepton.p4() + nu1P4;
0427
0428
0429 double minDR = 1e9;
0430 int selB1 = -1;
0431 for (auto b1Itr = bjetIdxs.begin(); b1Itr != bjetIdxs.end(); ++b1Itr) {
0432 const double dR = deltaR(jets->at(*b1Itr).p4(), w1LVec);
0433 if (dR < minDR) {
0434 selB1 = *b1Itr;
0435 minDR = dR;
0436 }
0437 }
0438 if (selB1 == -1)
0439 break;
0440 const auto& bJet1 = jets->at(selB1);
0441 const auto t1LVec = w1LVec + bJet1.p4();
0442
0443
0444 const auto& wJet1 = jets->at(ljetIdxs[0]);
0445 const auto& wJet2 = jets->at(ljetIdxs[1]);
0446 const auto w2LVec = wJet1.p4() + wJet2.p4();
0447
0448
0449 double dm = 1e9;
0450 int selB2 = -1;
0451 for (auto i : bjetIdxs) {
0452 if (int(i) == selB1)
0453 continue;
0454 const double newDm = std::abs((w2LVec + jets->at(i).p4()).mass() - tMass_);
0455 if (newDm < dm) {
0456 dm = newDm;
0457 selB2 = i;
0458 }
0459 }
0460 if (dm >= 1e9)
0461 break;
0462
0463 const auto& bJet2 = jets->at(selB2);
0464 const auto t2LVec = w2LVec + bJet2.p4();
0465
0466 const int q = lepton.charge();
0467
0468 reco::GenParticle t1(q * 2 / 3., t1LVec, genVertex_, q * 6, 3, false);
0469 reco::GenParticle w1(q, w1LVec, genVertex_, q * 24, 3, true);
0470 reco::GenParticle b1(-q / 3., bJet1.p4(), genVertex_, q * 5, 1, true);
0471 reco::GenParticle l1(q, lepton.p4(), genVertex_, lepton.pdgId(), 1, true);
0472 reco::GenParticle n1(0, nu1P4, genVertex_, q * (std::abs(lepton.pdgId()) + 1), 1, true);
0473
0474 reco::GenParticle t2(-q * 2 / 3., t2LVec, genVertex_, -q * 6, 3, false);
0475 reco::GenParticle w2(-q, w2LVec, genVertex_, -q * 24, 3, true);
0476 reco::GenParticle b2(0, bJet2.p4(), genVertex_, -q * 5, 1, true);
0477 reco::GenParticle u2(0, wJet1.p4(), genVertex_, -2 * q, 1, true);
0478 reco::GenParticle d2(0, wJet2.p4(), genVertex_, q, 1, true);
0479
0480 pseudoTop->push_back(t1);
0481 pseudoTop->push_back(t2);
0482
0483 pseudoTop->push_back(w1);
0484 pseudoTop->push_back(b1);
0485 pseudoTop->push_back(l1);
0486 pseudoTop->push_back(n1);
0487
0488 pseudoTop->push_back(w2);
0489 pseudoTop->push_back(b2);
0490 pseudoTop->push_back(u2);
0491 pseudoTop->push_back(d2);
0492 }
0493 } while (false);
0494
0495 if (pseudoTop->size() == 10)
0496 {
0497
0498 pseudoTop->at(0).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 2));
0499 pseudoTop->at(0).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 3));
0500 pseudoTop->at(2).addMother(reco::GenParticleRef(pseudoTopRefHandle, 0));
0501 pseudoTop->at(3).addMother(reco::GenParticleRef(pseudoTopRefHandle, 0));
0502
0503
0504 pseudoTop->at(2).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 4));
0505 pseudoTop->at(2).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 5));
0506 pseudoTop->at(4).addMother(reco::GenParticleRef(pseudoTopRefHandle, 2));
0507 pseudoTop->at(5).addMother(reco::GenParticleRef(pseudoTopRefHandle, 2));
0508
0509
0510 pseudoTop->at(1).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 6));
0511 pseudoTop->at(1).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 7));
0512 pseudoTop->at(6).addMother(reco::GenParticleRef(pseudoTopRefHandle, 1));
0513 pseudoTop->at(7).addMother(reco::GenParticleRef(pseudoTopRefHandle, 1));
0514
0515
0516 pseudoTop->at(6).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 8));
0517 pseudoTop->at(6).addDaughter(reco::GenParticleRef(pseudoTopRefHandle, 9));
0518 pseudoTop->at(8).addMother(reco::GenParticleRef(pseudoTopRefHandle, 6));
0519 pseudoTop->at(9).addMother(reco::GenParticleRef(pseudoTopRefHandle, 6));
0520 }
0521
0522 event.put(std::move(neutrinos), "neutrinos");
0523 event.put(std::move(leptons), "leptons");
0524 event.put(std::move(jets), "jets");
0525
0526 event.put(std::move(pseudoTop));
0527 }
0528
0529 bool PseudoTopProducer::isFromHadron(const reco::Candidate* p) const {
0530 for (size_t i = 0, n = p->numberOfMothers(); i < n; ++i) {
0531 const reco::Candidate* mother = p->mother(i);
0532 if (!mother)
0533 continue;
0534 if (mother->status() == 4 or mother->numberOfMothers() == 0)
0535 continue;
0536 const int pdgId = abs(mother->pdgId());
0537
0538 if (pdgId > 100)
0539 return true;
0540 else if (isFromHadron(mother))
0541 return true;
0542 }
0543 return false;
0544 }
0545
0546 bool PseudoTopProducer::isBHadron(const reco::Candidate* p) const {
0547 const unsigned int absPdgId = abs(p->pdgId());
0548 if (!isBHadron(absPdgId))
0549 return false;
0550
0551
0552
0553 for (int i = 0, n = p->numberOfDaughters(); i < n; ++i) {
0554 const reco::Candidate* dau = p->daughter(i);
0555 if (isBHadron(abs(dau->pdgId())))
0556 return false;
0557 }
0558
0559 return true;
0560 }
0561
0562 bool PseudoTopProducer::isBHadron(const unsigned int absPdgId) const {
0563 if (absPdgId <= 100)
0564 return false;
0565 if (absPdgId >= 1000000000)
0566 return false;
0567
0568
0569
0570
0571 const int nq3 = (absPdgId / 10) % 10;
0572 const int nq2 = (absPdgId / 100) % 10;
0573 const int nq1 = (absPdgId / 1000) % 10;
0574
0575 if (nq3 == 0)
0576 return false;
0577 if (nq1 == 0 and nq2 == 5)
0578 return true;
0579 if (nq1 == 5)
0580 return true;
0581
0582 return false;
0583 }
0584
0585 #include "FWCore/Framework/interface/MakerMacros.h"
0586 DEFINE_FWK_MODULE(PseudoTopProducer);