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;
341 hadIndex.push_back(hadronIndex);
342 hadJetIndex.push_back(jetIndex);
348 for (reco::GenParticleCollection::const_iterator i_particle =
genParticles->begin();
355 if (
std::find(hadMothersCand.begin(), hadMothersCand.end(), thisParticle) != hadMothersCand.end())
360 thisParticle, topDaughterQId, topBarDaughterQId, hadMothersCand, hadMothersIndices,
nullptr, -1);
362 hadIndex.push_back(hadronIndex);
363 hadJetIndex.push_back(-1);
368 for (
int i = 0;
i < (
int)hadMothersCand.size();
i++) {
369 const reco::GenParticle *particle = dynamic_cast<const reco::GenParticle *>(hadMothersCand.at(
i));
370 hadMothers.push_back(*particle);
374 for (reco::GenParticleCollection::const_iterator i_particle =
genParticles->begin();
378 const int pdg_abs = lepton.
pdgId();
380 if (pdg_abs != 11 && pdg_abs != 13)
382 bool leptonViaTau =
false;
389 leptonMother = leptonMother->
mother();
395 size_t leptonHadronParticleIndex =
396 std::find(hadMothersCand.begin(), hadMothersCand.end(), leptonMother) - hadMothersCand.begin();
397 if (leptonHadronParticleIndex >= hadMothersCand.size())
400 size_t leptonHadronIndex =
401 std::find(hadIndex.begin(), hadIndex.end(), leptonHadronParticleIndex) - hadIndex.begin();
402 if (leptonHadronIndex >= hadIndex.size())
405 hadMothers.push_back(lepton);
406 const int leptonIndex = hadMothersCand.size() - 1;
407 hadLeptonIndex.push_back(leptonIndex);
408 hadLeptonViaTau.push_back(leptonViaTau);
409 hadLeptonHadIndex.push_back(leptonHadronIndex);
413 unsigned int nHad = hadIndex.size();
415 std::vector<std::vector<int>> LastQuarkMotherIds;
416 std::vector<std::vector<int>> LastQuarkIds;
417 std::vector<int> lastQuarkIndices(nHad, -1);
420 for (
unsigned int hadNum = 0; hadNum < nHad; hadNum++) {
421 unsigned int hadIdx = hadIndex.at(hadNum);
423 std::vector<int> FirstQuarkId;
424 std::vector<int> LastQuarkId;
425 std::vector<int> LastQuarkMotherId;
427 const int hadronFlavourSign =
flavourSign(hadMothers.at(hadIdx).pdgId());
430 if (hadronFlavourSign != 0) {
432 hadIdx, FirstQuarkId, hadMothersIndices, hadMothers, 0, hadronFlavourSign *
flavour_,
false, -1, 1,
false);
436 findInMothers(hadIdx, FirstQuarkId, hadMothersIndices, hadMothers, 0,
flavour_,
false, -1, 1,
false);
437 findInMothers(hadIdx, FirstQuarkId, hadMothersIndices, hadMothers, 0, -1 *
flavour_,
false, -1, 1,
false);
441 for (
unsigned int qId = 0; qId < FirstQuarkId.size(); qId++) {
443 const int quarkFlavourSign =
flavourSign(hadMothers.at(FirstQuarkId.at(qId)).
pdgId());
461 std::vector<std::pair<double, int>> lastQuark_dR_id_pairs;
464 for (
unsigned int qId = 0; qId < LastQuarkId.size(); qId++) {
465 int qIdx = LastQuarkId.at(qId);
467 float dR =
deltaR(hadMothers.at(hadIdx).eta(),
468 hadMothers.at(hadIdx).phi(),
469 hadMothers.at(qIdx).eta(),
470 hadMothers.at(qIdx).phi());
472 std::pair<double, int> dR_hadId_pair(
dR, qIdx);
473 lastQuark_dR_id_pairs.push_back(dR_hadId_pair);
476 std::sort(lastQuark_dR_id_pairs.begin(), lastQuark_dR_id_pairs.end());
478 if (lastQuark_dR_id_pairs.size() > 1) {
480 (lastQuark_dR_id_pairs.at(1).first - lastQuark_dR_id_pairs.at(0).first) / lastQuark_dR_id_pairs.at(1).first;
481 int qIdx_closest = lastQuark_dR_id_pairs.at(0).second;
484 LastQuarkId.push_back(qIdx_closest);
486 for (std::pair<double, int> qIdDrPair : lastQuark_dR_id_pairs)
487 LastQuarkId.push_back(qIdDrPair.second);
489 for (
int qIdx : LastQuarkId) {
490 int qmIdx = hadMothersIndices.at(qIdx).at(0);
491 LastQuarkMotherId.push_back(qmIdx);
494 if ((
int)LastQuarkId.size() > 0)
495 lastQuarkIndices.at(hadNum) = 0;
497 LastQuarkIds.push_back(LastQuarkId);
499 LastQuarkMotherIds.push_back(LastQuarkMotherId);
501 if (LastQuarkMotherId.empty()) {
504 int qIdx = LastQuarkId.at(lastQuarkIndices.at(hadNum));
505 int qFlav =
flavourSign(hadMothers.at(qIdx).pdgId());
506 hadronFlavour = qFlav *
std::abs(hadMothers.at(LastQuarkMotherId.at(lastQuarkIndices.at(hadNum))).pdgId());
511 int isFromTopWeakDecay = 1;
512 std::vector<int> checkedParticles;
513 if (hadFlavour.at(hadNum) != 0) {
514 int lastQIndex = LastQuarkId.at(lastQuarkIndices.at(hadNum));
515 bool fromTB = topDaughterQId >= 0 ?
findInMothers(lastQIndex,
526 checkedParticles.clear();
527 bool fromTbarB = topBarDaughterQId >= 0 ?
findInMothers(lastQIndex,
538 checkedParticles.clear();
539 if (!fromTB && !fromTbarB) {
540 isFromTopWeakDecay = 0;
543 isFromTopWeakDecay = 2;
544 hadFromTopWeakDecay.push_back(isFromTopWeakDecay);
545 int bHadronMotherId =
546 findInMothers(hadIdx, checkedParticles, hadMothersIndices, hadMothers, 0, 555555,
true, -1, 1,
false);
547 hadBHadronId.push_back(bHadronMotherId);
549 if (!LastQuarkMotherId.empty()) {
550 std::set<int> checkedHadronIds;
579 const unsigned int position =
std::find(particleList.begin(), particleList.end(), particle) - particleList.begin();
580 if (
position >= particleList.size())
631 if (flavour_abs != 5 && flavour_abs != 4)
635 if (pdgId_abs / 100 % 10 != flavour_abs)
638 if (pdgId_abs / 1000 == flavour_abs)
657 if (flavour_abs != 5 && flavour_abs != 4)
661 if (pdgId_abs / 1000 != flavour_abs)
680 if (
pdgId % 1000 / 10 / 11 > 0)
696 bool hasDaughter =
false;
727 int &topBarDaughterQId,
728 std::vector<const reco::Candidate *> &hadMothers,
730 std::set<const reco::Candidate *> *analyzedParticles,
731 const int prevPartIndex)
const {
733 int hadronIndex = -1;
736 hadMothers.push_back(thisParticle);
737 hadronIndex = hadMothers.size() - 1;
743 partIndex =
idInList(hadMothers, thisParticle);
747 if (!analyzedParticles) {
748 analyzedParticles =
new std::set<const reco::Candidate *>;
750 for (
unsigned int i = 0;
i < analyzedParticles->size();
i++) {
751 if (analyzedParticles->count(thisParticle) <= 0) {
760 if (prevPartIndex >= 0) {
765 analyzedParticles->insert(thisParticle);
768 for (
size_t iMother = 0; iMother < thisParticle->
numberOfMothers(); ++iMother) {
770 int mothIndex =
idInList(hadMothers, mother);
771 if (mothIndex == partIndex && partIndex >= 0) {
777 hadMothers.push_back(mother);
778 mothIndex = hadMothers.size() - 1;
781 if (mothIndex != partIndex && partIndex >= 0) {
785 mother, topDaughterQId, topBarDaughterQId, hadMothers, hadMothersIndices, analyzedParticles, partIndex);
788 int &bId = mother->
pdgId() < 0 ? topBarDaughterQId : topDaughterQId;
794 int bIdFlav =
std::abs(hadMothers.at(bId)->pdgId());
795 if (bIdFlav != 5 && thisFlav == 5)
797 else if (thisFlav == 5 && thisParticle->
pt() > hadMothers.at(bId)->pt())
803 analyzedParticles->erase(thisParticle);
828 int mothIndex)
const {
835 while ((
int)hadMothersIndices.size() <= partIndex) {
836 std::vector<int> mothersIndices;
837 hadMothersIndices.push_back(mothersIndices);
840 std::vector<int> *hadMotherIndices = &hadMothersIndices.at(partIndex);
842 if (mothIndex == -1) {
843 hadMotherIndices->clear();
846 for (
int k = 0;
k < (
int)hadMotherIndices->size();
k++) {
847 if (hadMotherIndices->at(
k) != mothIndex && hadMotherIndices->at(
k) != -1) {
856 hadMotherIndices->push_back(mothIndex);
880 std::vector<int> &mothChains,
881 const std::vector<std::vector<int>> &hadMothersIndices,
882 const std::vector<reco::GenParticle> &hadMothers,
889 int foundStopId = -1;
890 int pdg_1 = hadMothers.at(
idx).pdgId();
892 if ((
int)hadMothersIndices.size() <=
idx) {
894 printf(
" Stopping checking particle %d. No mothers are stored.\n",
idx);
900 printf(
"Lepton: %d\n", hadMothers.at(
idx).pdgId());
902 std::vector<int> mothers = hadMothersIndices.at(
idx);
903 unsigned int nMothers = mothers.size();
904 bool isCorrect =
false;
906 if (
std::abs(hadMothers.at(
idx).pdgId()) == 2212) {
907 printf(
"Chk: %d\tpdg: %d\tstatus: %d",
idx, hadMothers.at(
idx).pdgId(), hadMothers.at(
idx).status());
909 printf(
" Chk: %d(%d mothers)\tpdg: %d\tstatus: %d\tPt: %.3f\tEta: %.3f",
912 hadMothers.at(
idx).pdgId(),
913 hadMothers.at(
idx).status(),
914 hadMothers.at(
idx).pt(),
915 hadMothers.at(
idx).eta());
918 bool hasCorrectMothers =
true;
920 hasCorrectMothers =
false;
921 else if (mothers.at(0) < 0)
922 hasCorrectMothers =
false;
923 if (!hasCorrectMothers) {
925 printf(
" NO CORRECT MOTHER\n");
929 if (stopId >= 0 &&
idx == stopId)
940 if (((hadMothers.at(
idx).pdgId() ==
pdgId && pdgAbs ==
false) ||
942 (hadMothers.at(
idx).status() ==
status ||
status == 0) && hasCorrectMothers) {
945 const bool inList =
std::find(mothChains.begin(), mothChains.end(),
idx) != mothChains.end();
946 if (!inList && mothers.at(0) >= 0 && (hadMothers.at(
idx).pdgId() *
pdgId > 0 || !pdgAbs)) {
947 if (firstLast == 0 || firstLast == 1) {
948 mothChains.push_back(
idx);
962 if (isCorrect && firstLast == 1) {
967 unsigned int nDifferingMothers = 0;
968 for (
unsigned int i = 0;
i < nMothers;
i++) {
969 int idx2 = mothers.at(
i);
972 printf(
"^^^ Has no mother\n");
977 printf(
"^^^ Stored as its own mother\n");
980 int pdg_2 = hadMothers[idx2].pdgId();
985 printf(
"######### Inverting flavour of the hadron\n");
994 printf(
"Checking mother %d out of %d mothers (%d -> %d), looking for pdgId: %d\n",
i, nMothers,
idx, idx2,
pdgId);
996 if (firstLast == 2 && pdg_1 != pdg_2)
999 idx2, mothChains, hadMothersIndices, hadMothers,
status,
pdgId, pdgAbs, stopId, firstLast,
verbose);
1002 if (firstLast == 2 && isCorrect && nDifferingMothers >= nMothers) {
1004 printf(
"Checking particle %d once more to store it as the last quark\n",
idx);
1021 const int neutralPdgs_array[] = {9, 21, 22, 23, 25};
1022 const std::vector<int> neutralPdgs(neutralPdgs_array, neutralPdgs_array +
sizeof(neutralPdgs_array) /
sizeof(
int));
1044 const std::vector<int> &hadIndices,
1045 const std::vector<reco::GenParticle> &hadMothers,
1046 const std::vector<std::vector<int>> &hadMothersIndices,
1047 const std::vector<int> &isFromTopWeakDecay,
1048 const std::vector<std::vector<int>> &LastQuarkIds,
1049 const std::vector<std::vector<int>> &LastQuarkMotherIds,
1050 std::vector<int> &lastQuarkIndices,
1052 std::set<int> &checkedHadronIds,
1053 const int lastQuarkIndex)
const {
1054 if (checkedHadronIds.count(hadId) != 0)
1056 checkedHadronIds.insert(hadId);
1058 if (lastQuarkIndex < 0)
1060 if ((
int)LastQuarkIds.at(hadId).size() < lastQuarkIndex + 1)
1062 int LastQuarkId = LastQuarkIds.at(hadId).at(lastQuarkIndex);
1063 int LastQuarkMotherId = LastQuarkMotherIds.at(hadId).at(lastQuarkIndex);
1064 int qmFlav = hadMothers.at(LastQuarkId).pdgId() < 0 ? -1 : 1;
1065 int hadFlavour = qmFlav *
std::abs(hadMothers.at(LastQuarkMotherId).pdgId());
1066 bool ambiguityResolved =
true;
1068 if ((hadMothers.at(LastQuarkId).pdgId() * hadMothers.at(LastQuarkMotherId).pdgId() < 0 &&
1069 !
isNeutralPdg(hadMothers.at(LastQuarkMotherId).pdgId())) ||
1072 if ((
int)LastQuarkIds.at(hadId).size() > lastQuarkIndex + 1)
1083 lastQuarkIndex + 1);
1089 int nSameFlavourHadrons = 0;
1091 for (
unsigned int iHad = 0; iHad <
hadronFlavour.size(); iHad++) {
1094 int theLastQuarkIndex = lastQuarkIndices.at(iHad);
1095 if (theLastQuarkIndex < 0)
1097 if ((
int)LastQuarkMotherIds.at(iHad).size() <= theLastQuarkIndex)
1099 int theLastQuarkMotherId = LastQuarkMotherIds.at(iHad).at(theLastQuarkIndex);
1102 if (theHadFlavour == 0 ||
std::abs(theHadFlavour) == 21)
1104 if (theHadFlavour != hadFlavour || theLastQuarkMotherId != LastQuarkMotherId)
1106 ambiguityResolved =
false;
1107 nSameFlavourHadrons++;
1110 if ((
int)LastQuarkIds.at(hadId).size() > lastQuarkIndex + 1) {
1121 lastQuarkIndex + 1)) {
1122 ambiguityResolved =
true;
1127 if ((
int)LastQuarkIds.at(iHad).size() > theLastQuarkIndex + 1) {
1138 theLastQuarkIndex + 1)) {
1139 ambiguityResolved =
true;
1146 checkedHadronIds.erase(hadId);
1147 if (nSameFlavourHadrons > 0 && !ambiguityResolved) {
1151 lastQuarkIndices.at(hadId) = lastQuarkIndex;