65 std::vector<int> &hadIndex,
66 std::vector<reco::GenParticle> &hadMothersGenPart,
68 std::vector<int> &hadLeptonIndex,
69 std::vector<int> &hadLeptonHadIndex,
70 std::vector<int> &hadLeptonViaTau,
71 std::vector<int> &hadFlavour,
72 std::vector<int> &hadFromTopWeakDecay,
73 std::vector<int> &hadBHadronId)
const;
76 int &topBarDaughterQId,
77 std::vector<const reco::Candidate *> &hadMothers,
79 std::set<const reco::Candidate *> *analyzedParticles,
80 const int prevPartIndex)
const;
91 std::vector<int> &mothChains,
92 const std::vector<std::vector<int>> &hadMothersIndices,
93 const std::vector<reco::GenParticle> &hadMothers,
106 const std::vector<int> &hadIndices,
107 const std::vector<reco::GenParticle> &hadMothers,
108 const std::vector<std::vector<int>> &hadMothersIndices,
109 const std::vector<int> &isFromTopWeakDecay,
111 const std::vector<std::vector<int>> &LastQuarkMotherIds,
112 std::vector<int> &lastQuarkIndices,
114 std::set<int> &checkedHadronIds,
115 const int lastQuarkIndex)
const;
163 edm::LogError(
"GenHFHadronMatcher") <<
"Flavour option must be 4 (c-jet) or 5 (b-jet), but is: " <<
flavour
164 <<
". Correct this!";
171 jetFlavourInfosToken_(
172 consumes<
reco::JetFlavourInfoMatchingCollection>(
cfg.getParameter<
edm::
InputTag>(
"jetFlavourInfos"))),
173 flavour_{
std::abs(
cfg.getParameter<
int>(
"flavour"))},
174 noBBbarResonances_{
cfg.getParameter<
bool>(
"noBBbarResonances")},
175 onlyJetClusteredHadrons_{
cfg.getParameter<
bool>(
"onlyJetClusteredHadrons")},
176 flavourStr_{flavourName(flavour_)},
177 plusMothersToken_{produces<std::vector<reco::GenParticle>>(
178 "gen" + flavourStr_ +
180 plusMothersIndicesToken_{produces<std::vector<std::vector<int>>>(
181 "gen" + flavourStr_ +
"HadPlusMothersIndices")},
183 produces<std::vector<int>>(
"gen" + flavourStr_ +
"HadIndex")},
184 flavourToken_{produces<std::vector<int>>(
185 "gen" + flavourStr_ +
187 jetIndexToken_{produces<std::vector<int>>(
188 "gen" + flavourStr_ +
"HadJetIndex")},
189 leptonIndexToken_{produces<std::vector<int>>(
190 "gen" + flavourStr_ +
192 leptonHadronIndexToken_{produces<std::vector<int>>(
193 "gen" + flavourStr_ +
"HadLeptonHadronIndex")},
194 leptonViaTauToken_{produces<std::vector<int>>(
195 "gen" + flavourStr_ +
"HadLeptonViaTau")},
196 fromTopWeakDecayToken_{produces<std::vector<int>>(
197 "gen" + flavourStr_ +
198 "HadFromTopWeakDecay")},
199 bHadronIdToken_{produces<std::vector<int>>(
"gen" + flavourStr_ +
"HadBHadronId")}
215 ->setComment(
"Collection of GenParticle objects which contains all particles produced in the event");
218 "Output from the JetFlavour tool. Contains information about partons/hadrons/leptons associated to jets");
219 desc.add<
bool>(
"noBBbarResonances",
true)->setComment(
"Whether resonances should not be treated as hadrons");
220 desc.add<
bool>(
"onlyJetClusteredHadrons",
false)
221 ->setComment(
"Whether only hadrons that are matched to jets should be analysed. Runs x1000 faster in Sherpa");
222 desc.add<
int>(
"flavour", 5)->setComment(
"Flavour of weakly decaying hadron that should be analysed (4-c, 5-b)");
223 descriptions.
add(
"matchGenHFHadron",
desc);
241 std::vector<reco::GenParticle> hadMothers;
242 std::vector<std::vector<int>> hadMothersIndices;
243 std::vector<int> hadIndex;
244 std::vector<int> hadFlavour;
245 std::vector<int> hadJetIndex;
246 std::vector<int> hadLeptonIndex;
247 std::vector<int> hadLeptonHadIndex;
248 std::vector<int> hadLeptonViaTau;
249 std::vector<int> hadFromTopWeakDecay;
250 std::vector<int> hadBHadronId;
301 std::vector<int> &hadIndex,
302 std::vector<reco::GenParticle> &hadMothers,
304 std::vector<int> &hadLeptonIndex,
305 std::vector<int> &hadLeptonHadIndex,
306 std::vector<int> &hadLeptonViaTau,
307 std::vector<int> &hadFlavour,
308 std::vector<int> &hadFromTopWeakDecay,
309 std::vector<int> &hadBHadronId)
const {
310 std::vector<int> hadJetIndex;
311 std::vector<const reco::Candidate *> hadMothersCand;
313 int topDaughterQId = -1;
314 int topBarDaughterQId = -1;
342 hadIndex.push_back(hadronIndex);
343 hadJetIndex.push_back(jetIndex);
349 for (reco::GenParticleCollection::const_iterator i_particle =
genParticles->begin();
356 if (
std::find(hadMothersCand.begin(), hadMothersCand.end(), thisParticle) != hadMothersCand.end())
361 thisParticle, topDaughterQId, topBarDaughterQId, hadMothersCand, hadMothersIndices,
nullptr, -1);
363 hadIndex.push_back(hadronIndex);
364 hadJetIndex.push_back(-1);
369 for (
int i = 0;
i < (
int)hadMothersCand.size();
i++) {
370 const reco::GenParticle *particle = dynamic_cast<const reco::GenParticle *>(hadMothersCand.at(
i));
371 hadMothers.push_back(*particle);
375 for (reco::GenParticleCollection::const_iterator i_particle =
genParticles->begin();
379 const int pdg_abs = lepton.
pdgId();
381 if (pdg_abs != 11 && pdg_abs != 13)
383 bool leptonViaTau =
false;
390 leptonMother = leptonMother->
mother();
396 size_t leptonHadronParticleIndex =
397 std::find(hadMothersCand.begin(), hadMothersCand.end(), leptonMother) - hadMothersCand.begin();
398 if (leptonHadronParticleIndex >= hadMothersCand.size())
401 size_t leptonHadronIndex =
402 std::find(hadIndex.begin(), hadIndex.end(), leptonHadronParticleIndex) - hadIndex.begin();
403 if (leptonHadronIndex >= hadIndex.size())
406 hadMothers.push_back(lepton);
407 const int leptonIndex = hadMothersCand.size() - 1;
408 hadLeptonIndex.push_back(leptonIndex);
409 hadLeptonViaTau.push_back(leptonViaTau);
410 hadLeptonHadIndex.push_back(leptonHadronIndex);
414 unsigned int nHad = hadIndex.size();
416 std::vector<std::vector<int>> LastQuarkMotherIds;
417 std::vector<std::vector<int>> LastQuarkIds;
418 std::vector<int> lastQuarkIndices(nHad, -1);
421 for (
unsigned int hadNum = 0; hadNum < nHad; hadNum++) {
422 unsigned int hadIdx = hadIndex.at(hadNum);
424 std::vector<int> FirstQuarkId;
425 std::vector<int> LastQuarkId;
426 std::vector<int> LastQuarkMotherId;
428 const int hadronFlavourSign =
flavourSign(hadMothers.at(hadIdx).pdgId());
431 if (hadronFlavourSign != 0) {
433 hadIdx, FirstQuarkId, hadMothersIndices, hadMothers, 0, hadronFlavourSign *
flavour_,
false, -1, 1,
false);
437 findInMothers(hadIdx, FirstQuarkId, hadMothersIndices, hadMothers, 0,
flavour_,
false, -1, 1,
false);
438 findInMothers(hadIdx, FirstQuarkId, hadMothersIndices, hadMothers, 0, -1 *
flavour_,
false, -1, 1,
false);
442 for (
unsigned int qId = 0; qId < FirstQuarkId.size(); qId++) {
444 const int quarkFlavourSign =
flavourSign(hadMothers.at(FirstQuarkId.at(qId)).
pdgId());
462 std::vector<std::pair<double, int>> lastQuark_dR_id_pairs;
465 for (
unsigned int qId = 0; qId < LastQuarkId.size(); qId++) {
466 int qIdx = LastQuarkId.at(qId);
468 float dR =
deltaR(hadMothers.at(hadIdx).eta(),
469 hadMothers.at(hadIdx).phi(),
470 hadMothers.at(qIdx).eta(),
471 hadMothers.at(qIdx).phi());
473 std::pair<double, int> dR_hadId_pair(
dR, qIdx);
474 lastQuark_dR_id_pairs.push_back(dR_hadId_pair);
477 std::sort(lastQuark_dR_id_pairs.begin(), lastQuark_dR_id_pairs.end());
479 if (lastQuark_dR_id_pairs.size() > 1) {
481 (lastQuark_dR_id_pairs.at(1).first - lastQuark_dR_id_pairs.at(0).first) / lastQuark_dR_id_pairs.at(1).first;
482 int qIdx_closest = lastQuark_dR_id_pairs.at(0).second;
485 LastQuarkId.push_back(qIdx_closest);
487 for (std::pair<double, int> qIdDrPair : lastQuark_dR_id_pairs)
488 LastQuarkId.push_back(qIdDrPair.second);
490 for (
int qIdx : LastQuarkId) {
491 int qmIdx = hadMothersIndices.at(qIdx).at(0);
492 LastQuarkMotherId.push_back(qmIdx);
495 if ((
int)LastQuarkId.size() > 0)
496 lastQuarkIndices.at(hadNum) = 0;
498 LastQuarkIds.push_back(LastQuarkId);
500 LastQuarkMotherIds.push_back(LastQuarkMotherId);
502 if (LastQuarkMotherId.empty()) {
505 int qIdx = LastQuarkId.at(lastQuarkIndices.at(hadNum));
506 int qFlav =
flavourSign(hadMothers.at(qIdx).pdgId());
507 hadronFlavour = qFlav *
std::abs(hadMothers.at(LastQuarkMotherId.at(lastQuarkIndices.at(hadNum))).pdgId());
512 int isFromTopWeakDecay = 1;
513 std::vector<int> checkedParticles;
514 if (hadFlavour.at(hadNum) != 0) {
515 int lastQIndex = LastQuarkId.at(lastQuarkIndices.at(hadNum));
516 bool fromTB = topDaughterQId >= 0 ?
findInMothers(lastQIndex,
527 checkedParticles.clear();
528 bool fromTbarB = topBarDaughterQId >= 0 ?
findInMothers(lastQIndex,
539 checkedParticles.clear();
540 if (!fromTB && !fromTbarB) {
541 isFromTopWeakDecay = 0;
544 isFromTopWeakDecay = 2;
545 hadFromTopWeakDecay.push_back(isFromTopWeakDecay);
546 int bHadronMotherId =
547 findInMothers(hadIdx, checkedParticles, hadMothersIndices, hadMothers, 0, 555555,
true, -1, 1,
false);
548 hadBHadronId.push_back(bHadronMotherId);
550 if (!LastQuarkMotherId.empty()) {
551 std::set<int> checkedHadronIds;
580 const unsigned int position =
std::find(particleList.begin(), particleList.end(), particle) - particleList.begin();
581 if (
position >= particleList.size())
632 if (flavour_abs != 5 && flavour_abs != 4)
636 if (pdgId_abs / 100 % 10 != flavour_abs)
639 if (pdgId_abs / 1000 == flavour_abs)
658 if (flavour_abs != 5 && flavour_abs != 4)
662 if (pdgId_abs / 1000 != flavour_abs)
681 if (
pdgId % 1000 / 10 / 11 > 0)
697 bool hasDaughter =
false;
728 int &topBarDaughterQId,
729 std::vector<const reco::Candidate *> &hadMothers,
731 std::set<const reco::Candidate *> *analyzedParticles,
732 const int prevPartIndex)
const {
734 int hadronIndex = -1;
737 hadMothers.push_back(thisParticle);
738 hadronIndex = hadMothers.size() - 1;
744 partIndex =
idInList(hadMothers, thisParticle);
748 if (!analyzedParticles) {
749 analyzedParticles =
new std::set<const reco::Candidate *>;
751 for (
unsigned int i = 0;
i < analyzedParticles->size();
i++) {
752 if (analyzedParticles->count(thisParticle) <= 0) {
761 if (prevPartIndex >= 0) {
766 analyzedParticles->insert(thisParticle);
769 for (
size_t iMother = 0; iMother < thisParticle->
numberOfMothers(); ++iMother) {
771 int mothIndex =
idInList(hadMothers, mother);
772 if (mothIndex == partIndex && partIndex >= 0) {
778 hadMothers.push_back(mother);
779 mothIndex = hadMothers.size() - 1;
782 if (mothIndex != partIndex && partIndex >= 0) {
786 mother, topDaughterQId, topBarDaughterQId, hadMothers, hadMothersIndices, analyzedParticles, partIndex);
789 int &bId = mother->
pdgId() < 0 ? topBarDaughterQId : topDaughterQId;
795 int bIdFlav =
std::abs(hadMothers.at(bId)->pdgId());
796 if (bIdFlav != 5 && thisFlav == 5)
798 else if (thisFlav == 5 && thisParticle->
pt() > hadMothers.at(bId)->pt())
804 analyzedParticles->erase(thisParticle);
829 int mothIndex)
const {
836 while ((
int)hadMothersIndices.size() <= partIndex) {
837 std::vector<int> mothersIndices;
838 hadMothersIndices.push_back(mothersIndices);
841 std::vector<int> *hadMotherIndices = &hadMothersIndices.at(partIndex);
843 if (mothIndex == -1) {
844 hadMotherIndices->clear();
847 for (
int k = 0;
k < (
int)hadMotherIndices->size();
k++) {
848 if (hadMotherIndices->at(
k) != mothIndex && hadMotherIndices->at(
k) != -1) {
857 hadMotherIndices->push_back(mothIndex);
881 std::vector<int> &mothChains,
882 const std::vector<std::vector<int>> &hadMothersIndices,
883 const std::vector<reco::GenParticle> &hadMothers,
890 int foundStopId = -1;
891 int pdg_1 = hadMothers.at(
idx).pdgId();
893 if ((
int)hadMothersIndices.size() <=
idx) {
895 printf(
" Stopping checking particle %d. No mothers are stored.\n",
idx);
901 printf(
"Lepton: %d\n", hadMothers.at(
idx).pdgId());
903 std::vector<int> mothers = hadMothersIndices.at(
idx);
904 unsigned int nMothers = mothers.size();
905 bool isCorrect =
false;
907 if (
std::abs(hadMothers.at(
idx).pdgId()) == 2212) {
908 printf(
"Chk: %d\tpdg: %d\tstatus: %d",
idx, hadMothers.at(
idx).pdgId(), hadMothers.at(
idx).status());
910 printf(
" Chk: %d(%d mothers)\tpdg: %d\tstatus: %d\tPt: %.3f\tEta: %.3f",
913 hadMothers.at(
idx).pdgId(),
914 hadMothers.at(
idx).status(),
915 hadMothers.at(
idx).pt(),
916 hadMothers.at(
idx).eta());
919 bool hasCorrectMothers =
true;
921 hasCorrectMothers =
false;
922 else if (mothers.at(0) < 0)
923 hasCorrectMothers =
false;
924 if (!hasCorrectMothers) {
926 printf(
" NO CORRECT MOTHER\n");
930 if (stopId >= 0 &&
idx == stopId)
941 if (((hadMothers.at(
idx).pdgId() ==
pdgId && pdgAbs ==
false) ||
943 (hadMothers.at(
idx).status() ==
status ||
status == 0) && hasCorrectMothers) {
946 const bool inList =
std::find(mothChains.begin(), mothChains.end(),
idx) != mothChains.end();
947 if (!inList && mothers.at(0) >= 0 && (hadMothers.at(
idx).pdgId() *
pdgId > 0 || !pdgAbs)) {
948 if (firstLast == 0 || firstLast == 1) {
949 mothChains.push_back(
idx);
963 if (isCorrect && firstLast == 1) {
968 unsigned int nDifferingMothers = 0;
969 for (
unsigned int i = 0;
i < nMothers;
i++) {
970 int idx2 = mothers.at(
i);
973 printf(
"^^^ Has no mother\n");
978 printf(
"^^^ Stored as its own mother\n");
981 int pdg_2 = hadMothers[idx2].pdgId();
986 printf(
"######### Inverting flavour of the hadron\n");
995 printf(
"Checking mother %d out of %d mothers (%d -> %d), looking for pdgId: %d\n",
i, nMothers,
idx, idx2,
pdgId);
997 if (firstLast == 2 && pdg_1 != pdg_2)
1000 idx2, mothChains, hadMothersIndices, hadMothers,
status,
pdgId, pdgAbs, stopId, firstLast,
verbose);
1003 if (firstLast == 2 && isCorrect && nDifferingMothers >= nMothers) {
1005 printf(
"Checking particle %d once more to store it as the last quark\n",
idx);
1022 const int neutralPdgs_array[] = {9, 21, 22, 23, 25};
1023 const std::vector<int> neutralPdgs(neutralPdgs_array, neutralPdgs_array +
sizeof(neutralPdgs_array) /
sizeof(
int));
1045 const std::vector<int> &hadIndices,
1046 const std::vector<reco::GenParticle> &hadMothers,
1047 const std::vector<std::vector<int>> &hadMothersIndices,
1048 const std::vector<int> &isFromTopWeakDecay,
1049 const std::vector<std::vector<int>> &LastQuarkIds,
1050 const std::vector<std::vector<int>> &LastQuarkMotherIds,
1051 std::vector<int> &lastQuarkIndices,
1053 std::set<int> &checkedHadronIds,
1054 const int lastQuarkIndex)
const {
1055 if (checkedHadronIds.count(hadId) != 0)
1057 checkedHadronIds.insert(hadId);
1059 if (lastQuarkIndex < 0)
1061 if ((
int)LastQuarkIds.at(hadId).size() < lastQuarkIndex + 1)
1063 int LastQuarkId = LastQuarkIds.at(hadId).at(lastQuarkIndex);
1064 int LastQuarkMotherId = LastQuarkMotherIds.at(hadId).at(lastQuarkIndex);
1065 int qmFlav = hadMothers.at(LastQuarkId).pdgId() < 0 ? -1 : 1;
1066 int hadFlavour = qmFlav *
std::abs(hadMothers.at(LastQuarkMotherId).pdgId());
1067 bool ambiguityResolved =
true;
1069 if ((hadMothers.at(LastQuarkId).pdgId() * hadMothers.at(LastQuarkMotherId).pdgId() < 0 &&
1070 !
isNeutralPdg(hadMothers.at(LastQuarkMotherId).pdgId())) ||
1073 if ((
int)LastQuarkIds.at(hadId).size() > lastQuarkIndex + 1)
1084 lastQuarkIndex + 1);
1090 int nSameFlavourHadrons = 0;
1092 for (
unsigned int iHad = 0; iHad <
hadronFlavour.size(); iHad++) {
1095 int theLastQuarkIndex = lastQuarkIndices.at(iHad);
1096 if (theLastQuarkIndex < 0)
1098 if ((
int)LastQuarkMotherIds.at(iHad).size() <= theLastQuarkIndex)
1100 int theLastQuarkMotherId = LastQuarkMotherIds.at(iHad).at(theLastQuarkIndex);
1103 if (theHadFlavour == 0 ||
std::abs(theHadFlavour) == 21)
1105 if (theHadFlavour != hadFlavour || theLastQuarkMotherId != LastQuarkMotherId)
1107 ambiguityResolved =
false;
1108 nSameFlavourHadrons++;
1111 if ((
int)LastQuarkIds.at(hadId).size() > lastQuarkIndex + 1) {
1122 lastQuarkIndex + 1)) {
1123 ambiguityResolved =
true;
1128 if ((
int)LastQuarkIds.at(iHad).size() > theLastQuarkIndex + 1) {
1139 theLastQuarkIndex + 1)) {
1140 ambiguityResolved =
true;
1147 checkedHadronIds.erase(hadId);
1148 if (nSameFlavourHadrons > 0 && !ambiguityResolved) {
1152 lastQuarkIndices.at(hadId) = lastQuarkIndex;