File indexing completed on 2025-12-16 09:19:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "DecayFinder.h"
0012
0013 #include "DecayFinderContainerBase.h" // for DecayFinderContainerBase::Iter
0014 #include "DecayFinderContainer_v1.h" // for DecayFinderContainer_v1
0015
0016 #include <g4main/PHG4TruthInfoContainer.h>
0017
0018 #include <phhepmc/PHHepMCGenEvent.h>
0019 #include <phhepmc/PHHepMCGenEventMap.h>
0020
0021 #include <fun4all/Fun4AllReturnCodes.h>
0022
0023 #include <phool/PHCompositeNode.h>
0024 #include <phool/PHIODataNode.h> // for PHIODataNode
0025 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0026 #include <phool/getClass.h>
0027
0028 #pragma GCC diagnostic push
0029 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0030 #include <HepMC/GenEvent.h>
0031 #include <HepMC/GenVertex.h> // for GenVertex::particle_iterator
0032 #pragma GCC diagnostic pop
0033
0034 #include <HepMC/GenParticle.h>
0035 #include <HepMC/IteratorRange.h>
0036 #include <HepMC/SimpleVector.h>
0037
0038 #include <TDatabasePDG.h>
0039
0040 #include <algorithm> // for find, for_each, sort, transform
0041 #include <cctype> // for toupper
0042 #include <cstdlib> // for abs, size_t
0043 #include <iostream> // for operator<<, endl, basic_ostream
0044 #include <iterator> // for end, begin
0045 #include <map> // for map, map<>::mapped_type, _Rb...
0046 #include <memory> // for allocator_traits<>::value_type
0047
0048 int listOfResonantPIDs[] = {111, 113, 213, 333, 310, 311, 313, 323, 413, 423, 513, 523, 441, 443, 100443, 9000111, 9000211, 100111, 100211, 10111,
0049 10211, 9010111, 9010211, 10113, 10213, 20113, 20213, 9000113, 9000213, 100113, 100213, 9010113, 9010213, 9020113, 9020213,
0050 30113, 30213, 9030113, 9030213, 9040113, 9040213, 115, 215, 10115, 10215, 9000115, 9000215, 9010115, 9010215, 117, 217,
0051 9000117, 9000217, 9010117, 9010217, 119, 219, 221, 331, 9000221, 9010221, 100221, 10221, 9020221, 100331, 9030221, 10331,
0052 9040221, 9050221, 9060221, 9070221, 9080221, 223, 10223, 20223, 10333, 20333, 1000223, 9000223, 9010223, 30223, 100333, 225,
0053 9000225, 335, 9010225, 9020225, 10225, 9030225, 10335, 9040225, 9050225, 9060225, 9070225, 9080225, 9090225, 227, 337, 229,
0054 9000229, 9010229, 9000311, 9000321, 10311, 10321, 100311, 100321, 9010311, 9010321, 9020311, 9020321, 10313, 10323, 20313,
0055 20323, 100313, 100323, 9000313, 9000323, 30313, 30323, 315, 325, 9000315, 9000325, 10315, 10325, 20315, 20325, 9010315,
0056 9010325, 9020315, 9020325, 317, 327, 9010317, 9010327, 319, 329, 9000319, 9000329, 10411, 10421, 10413, 10423, 20413, 20423,
0057 415, 425, 431, 10431, 433, 10433, 20433, 435, 10511, 10521, 10513, 10523, 20513, 20523, 515, 525, 10531, 533, 10533, 20533, 535,
0058 10541, 543, 10543, 20543, 545, 10441, 100441, 10443, 20443, 30443, 9000443, 9010443, 9020443, 445, 100445, 551, 10551, 100551,
0059 110551, 200551, 210551, 10553, 20553, 30553, 110553, 120553, 130553, 210553, 220553, 9000553, 9010553, 555, 10555, 20555, 100555,
0060 110555, 120555, 200555, 557, 100557, 2224, 2214, 2114, 1114, 3212, 3224, 3214, 3114, 3324, 3314, 4222, 4212, 4112, 4224, 4214,
0061 4114, 4232, 4132, 4322, 4312, 4324, 4314, 4332, 4334, 4412, 4422, 4414, 4424, 4432, 4434, 4444};
0062
0063 DecayFinder::DecayFinder()
0064 : SubsysReco("DECAYFINDER")
0065 , m_save_dst(false)
0066 {
0067 }
0068
0069 DecayFinder::DecayFinder(const std::string& name)
0070 : SubsysReco(name)
0071 , m_save_dst(false)
0072 {
0073 }
0074
0075 int DecayFinder::Init(PHCompositeNode* topNode)
0076 {
0077 if (Verbosity() >= VERBOSITY_SOME)
0078 {
0079 std::cout << "DecayFinder name: " << Name() << std::endl;
0080 std::cout << "Decay descriptor: " << m_decayDescriptor << std::endl;
0081 }
0082
0083 int canSearchDecay = parseDecayDescriptor();
0084
0085 if (m_save_dst)
0086 {
0087 createDecayNode(topNode);
0088 }
0089
0090 return canSearchDecay;
0091 }
0092
0093 int DecayFinder::process_event(PHCompositeNode* topNode)
0094 {
0095 bool decayFound = findDecay(topNode);
0096
0097 if (decayFound && m_save_dst && Verbosity() >= VERBOSITY_MORE)
0098 {
0099 printNode(topNode);
0100 }
0101
0102 if (m_triggerOnDecay && !decayFound)
0103 {
0104 if (Verbosity() >= VERBOSITY_MORE)
0105 {
0106 std::cout << "The decay, " << m_decayDescriptor << " was not found or reconstructable in this event, skipping" << std::endl;
0107 }
0108 return Fun4AllReturnCodes::ABORTEVENT;
0109 }
0110 else
0111 {
0112 return Fun4AllReturnCodes::EVENT_OK;
0113 }
0114 }
0115
0116 int DecayFinder::End(PHCompositeNode* )
0117 {
0118 if (Verbosity() >= VERBOSITY_SOME)
0119 {
0120 printInfo();
0121 }
0122
0123 return 0;
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133 int DecayFinder::parseDecayDescriptor()
0134 {
0135 bool ddCanBeParsed = true;
0136
0137 size_t daughterLocator;
0138
0139 std::string mother;
0140 std::string intermediate;
0141 std::string daughter;
0142
0143 int mother_charge = 0;
0144 std::vector<int> intermediates_charge;
0145 std::vector<int> daughters_charge;
0146
0147 std::string decayArrow = "->";
0148 std::string chargeIndicator = "^";
0149 std::string startIntermediate = "{";
0150 std::string endIntermediate = "}";
0151
0152
0153 std::string specialTracks[] = {"e", "mu", "pi", "K"};
0154
0155 std::string manipulateDecayDescriptor = m_decayDescriptor;
0156
0157
0158 size_t pos;
0159 while ((pos = manipulateDecayDescriptor.find(' ')) != std::string::npos)
0160 {
0161 manipulateDecayDescriptor.replace(pos, 1, "");
0162 }
0163
0164
0165 std::string checkForCC = manipulateDecayDescriptor.substr(0, 1) + manipulateDecayDescriptor.substr(manipulateDecayDescriptor.size() - 3, 3);
0166 std::for_each(checkForCC.begin(), checkForCC.end(), [](char& c)
0167 { c = ::toupper(c); });
0168
0169
0170 if (checkForCC == "[]CC")
0171 {
0172 manipulateDecayDescriptor = manipulateDecayDescriptor.substr(1, manipulateDecayDescriptor.size() - 4);
0173 m_getChargeConjugate = true;
0174 }
0175
0176
0177 size_t findMotherEndPoint = manipulateDecayDescriptor.find(decayArrow);
0178 mother = manipulateDecayDescriptor.substr(0, findMotherEndPoint);
0179 if (findParticle(mother))
0180 {
0181 m_mother_ID = abs(get_pdgcode(mother));
0182 }
0183 else
0184 {
0185 ddCanBeParsed = false;
0186 }
0187 manipulateDecayDescriptor.erase(0, findMotherEndPoint + decayArrow.length());
0188
0189
0190 while ((pos = manipulateDecayDescriptor.find(startIntermediate)) != std::string::npos)
0191 {
0192 size_t findIntermediateStartPoint = manipulateDecayDescriptor.find(startIntermediate, pos);
0193 size_t findIntermediateEndPoint = manipulateDecayDescriptor.find(endIntermediate, pos);
0194 std::string intermediateDecay = manipulateDecayDescriptor.substr(pos + 1, findIntermediateEndPoint - (pos + 1));
0195
0196 intermediate = intermediateDecay.substr(0, intermediateDecay.find(decayArrow));
0197 if (findParticle(intermediate))
0198 {
0199 m_intermediates_ID.push_back(abs(get_pdgcode(intermediate)));
0200 }
0201 else
0202 {
0203 ddCanBeParsed = false;
0204 }
0205
0206
0207 int nDaughters = 0;
0208 intermediateDecay.erase(0, intermediateDecay.find(decayArrow) + decayArrow.length());
0209 while ((daughterLocator = intermediateDecay.find(chargeIndicator)) != std::string::npos)
0210 {
0211 daughter = intermediateDecay.substr(0, daughterLocator);
0212 std::string daughterChargeString = intermediateDecay.substr(daughterLocator + 1, 1);
0213 if (std::find(std::begin(specialTracks), std::end(specialTracks), daughter) != std::end(specialTracks))
0214 {
0215 daughter += daughterChargeString;
0216 }
0217 if (findParticle(daughter))
0218 {
0219 int daughter_ID = abs(get_pdgcode(daughter));
0220 m_daughters_ID.push_back(daughter_ID);
0221 daughters_charge.push_back(get_charge(daughter));
0222
0223 if (daughter_ID == 22)
0224 {
0225 m_hasPhotonDaughter = m_allowPhotons = true;
0226 }
0227 }
0228 else
0229 {
0230 ddCanBeParsed = false;
0231 }
0232 intermediateDecay.erase(0, daughterLocator + 2);
0233 ++nDaughters;
0234 }
0235 manipulateDecayDescriptor.erase(findIntermediateStartPoint, findIntermediateEndPoint + 1 - findIntermediateStartPoint);
0236 m_nTracksFromIntermediates.push_back(nDaughters);
0237 m_nTracksFromMother += 1;
0238 }
0239
0240
0241 while ((daughterLocator = manipulateDecayDescriptor.find(chargeIndicator)) != std::string::npos)
0242 {
0243 daughter = manipulateDecayDescriptor.substr(0, daughterLocator);
0244 std::string daughterChargeString = manipulateDecayDescriptor.substr(daughterLocator + 1, 1);
0245 if (std::find(std::begin(specialTracks), std::end(specialTracks), daughter) != std::end(specialTracks))
0246 {
0247 daughter += daughterChargeString;
0248 }
0249 if (findParticle(daughter))
0250 {
0251 m_daughters_ID.push_back(abs(get_pdgcode(daughter)));
0252 daughters_charge.push_back(get_charge(daughter));
0253 }
0254 else
0255 {
0256 ddCanBeParsed = false;
0257 }
0258 manipulateDecayDescriptor.erase(0, daughterLocator + 2);
0259 m_nTracksFromMother += 1;
0260 }
0261
0262 unsigned int trackStart = 0;
0263 unsigned int trackEnd = 0;
0264 for (unsigned int i = 0; i < m_intermediates_ID.size(); ++i)
0265 {
0266 trackStart = trackEnd;
0267 trackEnd = m_nTracksFromIntermediates[i] + trackStart;
0268
0269 int vtxCharge = 0;
0270
0271 for (unsigned int j = trackStart; j < trackEnd; ++j)
0272 {
0273 vtxCharge += daughters_charge[j];
0274 }
0275
0276 intermediates_charge.push_back(vtxCharge);
0277 }
0278
0279 for (unsigned int i = 0; i < m_daughters_ID.size(); ++i)
0280 {
0281 mother_charge += daughters_charge[i];
0282 }
0283
0284 m_mother_ID = mother_charge == 0 ? m_mother_ID : mother_charge * m_mother_ID;
0285 for (unsigned int i = 0; i < m_intermediates_ID.size(); ++i)
0286 {
0287 m_intermediates_ID[i] = intermediates_charge[i] == 0 ? m_intermediates_ID[i] : intermediates_charge[i] * m_intermediates_ID[i];
0288 m_motherDecayProducts.push_back(m_intermediates_ID[i]);
0289 }
0290 for (unsigned int i = 0; i < m_daughters_ID.size(); ++i)
0291 {
0292 m_daughters_ID[i] = daughters_charge[i] == 0 ? m_daughters_ID[i] : daughters_charge[i] * m_daughters_ID[i];
0293 if (i >= trackEnd)
0294 {
0295 m_motherDecayProducts.push_back(m_daughters_ID[i]);
0296 }
0297 }
0298
0299 if (ddCanBeParsed)
0300 {
0301 if (Verbosity() >= VERBOSITY_MORE)
0302 {
0303 std::cout << "Your decay descriptor can be parsed" << std::endl;
0304 }
0305 return 0;
0306 }
0307 else
0308 {
0309 if (Verbosity() >= VERBOSITY_SOME)
0310 {
0311 std::cout << "Your decay descriptor cannot be parsed, " << Name() << " will not be registered" << std::endl;
0312 }
0313 return Fun4AllReturnCodes::DONOTREGISTERSUBSYSTEM;
0314 }
0315 }
0316
0317
0318
0319
0320
0321
0322
0323 bool DecayFinder::findDecay(PHCompositeNode* topNode)
0324 {
0325 bool decayWasFound = false;
0326 bool reconstructableDecayWasFound = false;
0327 bool aTrackFailedPT = false;
0328 bool aTrackFailedETA = false;
0329 bool aMotherHasPhoton = false;
0330 bool aMotherHasPi0 = false;
0331 std::vector<int> correctMotherProducts;
0332 std::vector<int> positive_motherDecayProducts;
0333
0334 int n = sizeof(listOfResonantPIDs) / sizeof(listOfResonantPIDs[0]);
0335 for (int i : m_intermediates_ID)
0336 {
0337 n = deleteElement(listOfResonantPIDs, n, i);
0338 }
0339
0340 n = deleteElement(listOfResonantPIDs, n, m_mother_ID);
0341
0342 for (int m_motherDecayProduct : m_motherDecayProducts)
0343 {
0344 positive_motherDecayProducts.push_back(std::abs(m_motherDecayProduct));
0345 }
0346
0347 m_truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
0348 if (!m_truthinfo)
0349 {
0350 std::cout << "DecayFinder: Missing node G4TruthInfo" << std::endl;
0351 }
0352
0353 m_geneventmap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
0354 if (!m_geneventmap)
0355 {
0356 std::cout << "DecayFinder: Missing node PHHepMCGenEventMap" << std::endl;
0357 }
0358
0359 if (!m_truthinfo && !m_geneventmap)
0360 {
0361 std::cout << "You have neither the PHHepMCGenEventMap or G4TruthInfo nodes" << std::endl;
0362 std::cout << "DecayFinder will crash, exiting now!" << std::endl;
0363 exit(1);
0364 }
0365
0366 if (m_truthinfo && !m_geneventmap)
0367 {
0368 if (Verbosity() >= VERBOSITY_SOME)
0369 {
0370 std::cout << "You have a valid G4TruthInfo but no PHHepMCGenEventMap container" << std::endl;
0371 std::cout << "You are probably using a particle gun" << std::endl;
0372 }
0373
0374 PHG4TruthInfoContainer::ConstRange range = m_truthinfo->GetParticleRange();
0375 for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter)
0376 {
0377 PHG4Particle* g4particle = iter->second;
0378 int this_pid = m_getChargeConjugate ? abs(g4particle->get_pid()) : g4particle->get_pid();
0379 if (this_pid == m_mother_ID)
0380 {
0381 if (Verbosity() >= VERBOSITY_MAX)
0382 {
0383 std::cout << "parent->pdg_id(): " << g4particle->get_pid() << std::endl;
0384 }
0385
0386 bool breakOut = false;
0387 correctMotherProducts.clear();
0388 decayChain.clear();
0389 decayChain.push_back(std::make_pair(std::make_pair(g4particle->get_primary_id(), g4particle->get_barcode()), g4particle->get_pid()));
0390
0391 searchGeant4Record(g4particle->get_barcode(), g4particle->get_pid(), positive_motherDecayProducts, breakOut, aMotherHasPhoton, aMotherHasPi0, aTrackFailedPT, aTrackFailedETA, correctMotherProducts);
0392
0393 if (breakOut)
0394 {
0395 continue;
0396 }
0397
0398 decayWasFound = compareDecays(m_motherDecayProducts, correctMotherProducts);
0399
0400 if (decayWasFound)
0401 {
0402 m_counter += 1;
0403 if (aTrackFailedPT && !aTrackFailedETA)
0404 {
0405 m_nCandFail_pT += 1;
0406 }
0407 else if (!aTrackFailedPT && aTrackFailedETA)
0408 {
0409 m_nCandFail_eta += 1;
0410 }
0411 else if (aTrackFailedPT && aTrackFailedETA)
0412 {
0413 m_nCandFail_pT_and_eta += 1;
0414 }
0415 else
0416 {
0417 m_nCandReconstructable += 1;
0418 reconstructableDecayWasFound = true;
0419 if (m_save_dst)
0420 {
0421 fillDecayNode(topNode, decayChain);
0422 }
0423 if (aMotherHasPhoton && !aMotherHasPi0)
0424 {
0425 m_nCandHas_Photon += 1;
0426 }
0427 else if (!aMotherHasPhoton && aMotherHasPi0)
0428 {
0429 m_nCandHas_Pi0 += 1;
0430 }
0431 else if (aMotherHasPhoton && aMotherHasPi0)
0432 {
0433 m_nCandHas_Photon_and_Pi0 += 1;
0434 }
0435 else
0436 {
0437 m_nCandHas_noPhoton_and_noPi0 += 1;
0438 }
0439 }
0440 }
0441 }
0442 }
0443 return reconstructableDecayWasFound;
0444 }
0445
0446 for (PHHepMCGenEventMap::ConstReverseIter riter = m_geneventmap->rbegin();
0447 riter != m_geneventmap->rend(); ++riter)
0448 {
0449 m_genevt = riter->second;
0450 if (!m_genevt)
0451 {
0452 std::cout << "DecayFinder: Missing node PHHepMCGenEvent" << std::endl;
0453 return false;
0454 }
0455
0456 HepMC::GenEvent* theEvent = m_genevt->getEvent();
0457
0458 for (HepMC::GenEvent::particle_const_iterator p = theEvent->particles_begin(); p != theEvent->particles_end(); ++p)
0459 {
0460 int this_pid = m_getChargeConjugate ? abs((*p)->pdg_id()) : (*p)->pdg_id();
0461 if (this_pid == m_mother_ID)
0462 {
0463 if (Verbosity() >= VERBOSITY_MAX)
0464 {
0465 std::cout << "parent->pdg_id(): " << (*p)->pdg_id() << std::endl;
0466 }
0467
0468 bool breakOut = false;
0469 correctMotherProducts.clear();
0470 decayChain.clear();
0471 decayChain.push_back(std::make_pair(std::make_pair(m_genevt->get_embedding_id(), (*p)->barcode()), (*p)->pdg_id()));
0472
0473
0474 if (!(*p)->end_vertex())
0475 {
0476 searchGeant4Record((*p)->barcode(), (*p)->pdg_id(), positive_motherDecayProducts, breakOut, aMotherHasPhoton, aMotherHasPi0, aTrackFailedPT, aTrackFailedETA, correctMotherProducts);
0477 }
0478 else
0479 {
0480 searchHepMCRecord((*p), positive_motherDecayProducts, breakOut, aMotherHasPhoton, aMotherHasPi0, aTrackFailedPT, aTrackFailedETA, correctMotherProducts);
0481 }
0482
0483 if (breakOut)
0484 {
0485 continue;
0486 }
0487
0488 decayWasFound = compareDecays(m_motherDecayProducts, correctMotherProducts);
0489
0490 if (decayWasFound)
0491 {
0492 m_counter += 1;
0493 if (aTrackFailedPT && !aTrackFailedETA)
0494 {
0495 m_nCandFail_pT += 1;
0496 }
0497 else if (!aTrackFailedPT && aTrackFailedETA)
0498 {
0499 m_nCandFail_eta += 1;
0500 }
0501 else if (aTrackFailedPT && aTrackFailedETA)
0502 {
0503 m_nCandFail_pT_and_eta += 1;
0504 }
0505 else
0506 {
0507 m_nCandReconstructable += 1;
0508 reconstructableDecayWasFound = true;
0509 if (m_save_dst)
0510 {
0511 fillDecayNode(topNode, decayChain);
0512 }
0513 if (aMotherHasPhoton && !aMotherHasPi0)
0514 {
0515 m_nCandHas_Photon += 1;
0516 }
0517 else if (!aMotherHasPhoton && aMotherHasPi0)
0518 {
0519 m_nCandHas_Pi0 += 1;
0520 }
0521 else if (aMotherHasPhoton && aMotherHasPi0)
0522 {
0523 m_nCandHas_Photon_and_Pi0 += 1;
0524 }
0525 else
0526 {
0527 m_nCandHas_noPhoton_and_noPi0 += 1;
0528 }
0529 }
0530 }
0531 }
0532 }
0533 }
0534
0535 return reconstructableDecayWasFound;
0536 }
0537
0538
0539
0540
0541
0542 void DecayFinder::searchHepMCRecord(HepMC::GenParticle* particle, std::vector<int> decayProducts,
0543 bool& breakLoop, bool& hasPhoton, bool& hasPi0, bool& failedPT, bool& failedETA,
0544 std::vector<int>& actualDecayProducts)
0545 {
0546 for (HepMC::GenVertex::particle_iterator children = particle->end_vertex()->particles_begin(HepMC::children);
0547 children != particle->end_vertex()->particles_end(HepMC::children); ++children)
0548 {
0549 if (Verbosity() >= VERBOSITY_MAX)
0550 {
0551 std::cout << "--children->pdg_id(): " << (*children)->pdg_id() << std::endl;
0552 }
0553
0554 if ((*children)->pdg_id() == 22)
0555 {
0556 hasPhoton = true;
0557 }
0558 if ((*children)->pdg_id() == 111)
0559 {
0560 hasPi0 = true;
0561 }
0562 if ((!m_allowPhotons && (*children)->pdg_id() == 22) || (!m_allowPi0 && (*children)->pdg_id() == 111))
0563 {
0564 breakLoop = true;
0565 break;
0566 }
0567
0568
0569 if (std::find(decayProducts.begin(), decayProducts.end(),
0570 std::abs((*children)->pdg_id())) != decayProducts.end())
0571 {
0572 if (Verbosity() >= VERBOSITY_MAX)
0573 {
0574 std::cout << "This is a child you were looking for" << std::endl;
0575 }
0576
0577 std::vector<int> positive_intermediates_ID;
0578 for (int i : m_intermediates_ID)
0579 {
0580 positive_intermediates_ID.push_back(abs(i));
0581 }
0582
0583 if (!(*children)->end_vertex() && std::find(positive_intermediates_ID.begin(), positive_intermediates_ID.end(),
0584 abs((*children)->pdg_id())) != positive_intermediates_ID.end())
0585 {
0586 std::vector<int> requiredIntermediateDecayProducts;
0587 std::vector<int> positive_requiredIntermediateDecayProducts;
0588 std::vector<int> actualIntermediateDecayProducts;
0589
0590 auto it = std::find(positive_intermediates_ID.begin(), positive_intermediates_ID.end(), abs((*children)->pdg_id()));
0591 int index = std::distance(positive_intermediates_ID.begin(), it);
0592
0593 unsigned int trackStart = 0, trackStop = 0;
0594 if (index == 0)
0595 {
0596 trackStop = m_nTracksFromIntermediates[0];
0597 }
0598 else
0599 {
0600 for (int i = 0; i < index; ++i)
0601 {
0602 trackStart += m_nTracksFromIntermediates[i];
0603 }
0604 trackStop = trackStart + m_nTracksFromIntermediates[index];
0605 }
0606 for (unsigned int i = trackStart; i < trackStop; ++i)
0607 {
0608 requiredIntermediateDecayProducts.push_back(m_daughters_ID[i]);
0609 positive_requiredIntermediateDecayProducts.push_back(abs(m_daughters_ID[i]));
0610 }
0611
0612 searchGeant4Record((*children)->barcode(), (*children)->pdg_id(), positive_requiredIntermediateDecayProducts,
0613 breakLoop, hasPhoton, hasPi0, failedPT, failedETA, actualIntermediateDecayProducts);
0614
0615 bool needThisParticle = compareDecays(requiredIntermediateDecayProducts, actualIntermediateDecayProducts);
0616 if (needThisParticle)
0617 {
0618 actualDecayProducts.push_back((*children)->pdg_id());
0619 decayChain.push_back(std::make_pair(std::make_pair(m_genevt->get_embedding_id(), (*children)->barcode()), (*children)->pdg_id()));
0620 }
0621 else
0622 {
0623 decayChain.erase(decayChain.end() - (m_intermediate_product_counter + 1), decayChain.end());
0624 decayChain.pop_back();
0625 }
0626
0627 m_intermediate_product_counter = 0;
0628 }
0629 else
0630 {
0631 bool needThisParticle = checkIfCorrectHepMCParticle((*children), failedPT, failedETA);
0632 if (needThisParticle)
0633 {
0634 actualDecayProducts.push_back((*children)->pdg_id());
0635 decayChain.push_back(std::make_pair(std::make_pair(m_genevt->get_embedding_id(), (*children)->barcode()), (*children)->pdg_id()));
0636 }
0637 }
0638 }
0639 else if (std::find(std::begin(listOfResonantPIDs), std::end(listOfResonantPIDs),
0640 std::abs((*children)->pdg_id())) != std::end(listOfResonantPIDs))
0641 {
0642 if (Verbosity() >= VERBOSITY_MAX)
0643 {
0644 std::cout << "This is a resonance to investigate further" << std::endl;
0645 }
0646 if (!(*children)->end_vertex())
0647 {
0648 searchGeant4Record((*children)->barcode(), (*children)->pdg_id(), decayProducts,
0649 breakLoop, hasPhoton, hasPi0, failedPT, failedETA, actualDecayProducts);
0650 }
0651 else
0652 {
0653 for (HepMC::GenVertex::particle_iterator grandchildren = (*children)->end_vertex()->particles_begin(HepMC::children);
0654 grandchildren != (*children)->end_vertex()->particles_end(HepMC::children); ++grandchildren)
0655 {
0656 bool needThisParticle = checkIfCorrectHepMCParticle((*grandchildren), failedPT, failedETA);
0657 if (needThisParticle)
0658 {
0659 actualDecayProducts.push_back((*grandchildren)->pdg_id());
0660 decayChain.push_back(std::make_pair(std::make_pair(m_genevt->get_embedding_id(), (*grandchildren)->barcode()), (*grandchildren)->pdg_id()));
0661 }
0662 }
0663 }
0664 }
0665 else
0666 {
0667 breakLoop = true;
0668 break;
0669 }
0670 }
0671 }
0672
0673
0674
0675
0676
0677 void DecayFinder::searchGeant4Record(int barcode, int pid, std::vector<int> decayProducts, bool& breakLoop, bool& hasPhoton, bool& hasPi0, bool& failedPT, bool& failedETA, std::vector<int>& actualDecayProducts)
0678 {
0679 PHG4TruthInfoContainer::ConstRange range = m_truthinfo->GetParticleRange();
0680 for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter)
0681 {
0682 if (decayChain.size() == 100)
0683 {
0684 breakLoop = true;
0685 break;
0686 }
0687
0688 PHG4Particle* g4particle = iter->second;
0689 PHG4Particle* mother = nullptr;
0690 if (g4particle->get_parent_id() != 0)
0691 {
0692 mother = m_truthinfo->GetParticle(g4particle->get_parent_id());
0693 }
0694 else
0695 {
0696 continue;
0697 }
0698 if (mother->get_barcode() == barcode && abs(mother->get_pid()) == abs(pid))
0699 {
0700 int particleID = g4particle->get_pid();
0701 if (Verbosity() >= VERBOSITY_MAX)
0702 {
0703 std::cout << "--children->pdg_id(): " << particleID << std::endl;
0704 }
0705 if (particleID == 22)
0706 {
0707 hasPhoton = true;
0708 }
0709 if (particleID == 111)
0710 {
0711 hasPi0 = true;
0712 }
0713
0714 if ((!m_allowPhotons && particleID == 22) || (!m_hasPhotonDaughter && particleID == 22) || (!m_allowPi0 && particleID == 111))
0715 {
0716 breakLoop = true;
0717 break;
0718 }
0719
0720 if (std::find(decayProducts.begin(), decayProducts.end(),
0721 std::abs(particleID)) != decayProducts.end())
0722 {
0723 bool needThisParticle = checkIfCorrectGeant4Particle(g4particle, hasPhoton, hasPi0, failedPT, failedETA);
0724 if (needThisParticle)
0725 {
0726 if (Verbosity() >= VERBOSITY_MAX)
0727 {
0728 std::cout << "This is a child you were looking for" << std::endl;
0729 }
0730 actualDecayProducts.push_back(particleID);
0731 int embedding_id = m_geneventmap ? m_genevt->get_embedding_id() : g4particle->get_primary_id();
0732 decayChain.push_back(std::make_pair(std::make_pair(embedding_id, g4particle->get_barcode()), particleID));
0733 }
0734 }
0735 else if ((m_allowPhotons && !m_hasPhotonDaughter && particleID == 22) || (m_allowPi0 && particleID == 111))
0736 {
0737 continue;
0738 }
0739 else if (std::find(std::begin(listOfResonantPIDs), std::end(listOfResonantPIDs),
0740 std::abs(particleID)) != std::end(listOfResonantPIDs))
0741 {
0742 if (Verbosity() >= VERBOSITY_MAX)
0743 {
0744 std::cout << "This is a resonance to investigate further" << std::endl;
0745 }
0746 searchGeant4Record(g4particle->get_barcode(), g4particle->get_pid(), decayProducts,
0747 breakLoop, hasPhoton, hasPi0, failedPT, failedETA, actualDecayProducts);
0748 }
0749 else
0750 {
0751 breakLoop = true;
0752 break;
0753 }
0754 }
0755 }
0756 }
0757
0758
0759
0760
0761 bool DecayFinder::checkIfCorrectHepMCParticle(HepMC::GenParticle* particle, bool& trackFailedPT, bool& trackFailedETA)
0762 {
0763 bool acceptParticle = false;
0764
0765 std::vector<int> positive_intermediates_ID;
0766 for (int i : m_intermediates_ID)
0767 {
0768 positive_intermediates_ID.push_back(abs(i));
0769 }
0770
0771
0772 if (std::find(positive_intermediates_ID.begin(), positive_intermediates_ID.end(),
0773 abs(particle->pdg_id())) != positive_intermediates_ID.end())
0774 {
0775 std::vector<int> requiredIntermediateDecayProducts;
0776 std::vector<int> actualIntermediateDecayProducts;
0777
0778 auto it = std::find(positive_intermediates_ID.begin(), positive_intermediates_ID.end(), abs(particle->pdg_id()));
0779 int index = std::distance(positive_intermediates_ID.begin(), it);
0780
0781 unsigned int trackStart = 0, trackStop = 0;
0782 if (index == 0)
0783 {
0784 trackStop = m_nTracksFromIntermediates[0];
0785 }
0786 else
0787 {
0788 for (int i = 0; i < index; ++i)
0789 {
0790 trackStart += m_nTracksFromIntermediates[i];
0791 }
0792 trackStop = trackStart + m_nTracksFromIntermediates[index];
0793 }
0794
0795 for (unsigned int i = trackStart; i < trackStop; ++i)
0796 {
0797 requiredIntermediateDecayProducts.push_back(m_daughters_ID[i]);
0798 }
0799
0800 for (HepMC::GenVertex::particle_iterator grandchildren = particle->end_vertex()->particles_begin(HepMC::children);
0801 grandchildren != particle->end_vertex()->particles_end(HepMC::children); ++grandchildren)
0802 {
0803 if (Verbosity() >= VERBOSITY_MAX)
0804 {
0805 std::cout << "----grandchildren->pdg_id(): " << (*grandchildren)->pdg_id() << std::endl;
0806 }
0807
0808 if (std::find(std::begin(listOfResonantPIDs), std::end(listOfResonantPIDs),
0809 std::abs((*grandchildren)->pdg_id())) != std::end(listOfResonantPIDs))
0810 {
0811 for (HepMC::GenVertex::particle_iterator greatgrandchildren = (*grandchildren)->end_vertex()->particles_begin(HepMC::children);
0812 greatgrandchildren != (*grandchildren)->end_vertex()->particles_end(HepMC::children); ++greatgrandchildren)
0813 {
0814 if (Verbosity() >= VERBOSITY_MAX)
0815 {
0816 std::cout << "--------greatgrandchildren->pdg_id(): " << (*greatgrandchildren)->pdg_id() << std::endl;
0817 }
0818
0819 if ((m_allowPhotons && !m_hasPhotonDaughter && (*greatgrandchildren)->pdg_id() == 22) || (m_allowPi0 && (*greatgrandchildren)->pdg_id() == 111))
0820 {
0821 continue;
0822 }
0823 else if ((!m_hasPhotonDaughter && (*greatgrandchildren)->pdg_id() == 22) || (!m_allowPhotons && (*greatgrandchildren)->pdg_id() == 22) || (!m_allowPi0 && (*greatgrandchildren)->pdg_id() == 111))
0824 {
0825 break;
0826 }
0827 else
0828 {
0829 actualIntermediateDecayProducts.push_back((*greatgrandchildren)->pdg_id());
0830 decayChain.push_back(std::make_pair(std::make_pair(m_genevt->get_embedding_id(), (*greatgrandchildren)->barcode()), (*greatgrandchildren)->pdg_id()));
0831 ++m_intermediate_product_counter;
0832
0833 HepMC::FourVector myFourVector = (*greatgrandchildren)->momentum();
0834
0835 HepMC::GenVertex* thisVtx = (*greatgrandchildren)->production_vertex();
0836 double vtxPos[3] = {thisVtx->point3d().x(), thisVtx->point3d().y(), thisVtx->point3d().z()};
0837 if (m_recalcualteEtaRange)
0838 {
0839 recalculateEta(myFourVector.py(), vtxPos);
0840 }
0841
0842 if (myFourVector.perp() < m_pt_req)
0843 {
0844 trackFailedPT = true;
0845 }
0846 if (!isInRange(m_eta_low_req, myFourVector.eta(), m_eta_high_req))
0847 {
0848 trackFailedETA = true;
0849 }
0850
0851 if (Verbosity() >= VERBOSITY_MAX)
0852 {
0853 std::cout << "pT = " << myFourVector.perp() << ", eta = " << myFourVector.eta() << std::endl;
0854 std::cout << "The track " << passOrFail(myFourVector.perp() >= m_pt_req) << " the pT requirement, ";
0855 std::cout << "the track " << passOrFail(isInRange(m_eta_low_req, myFourVector.eta(), m_eta_high_req)) << " the eta requirement." << std::endl;
0856 }
0857 }
0858 }
0859 }
0860 else if ((m_allowPhotons && !m_hasPhotonDaughter && (*grandchildren)->pdg_id() == 22) || (m_allowPi0 && (*grandchildren)->pdg_id() == 111))
0861 {
0862 continue;
0863 }
0864 else if ((!m_hasPhotonDaughter && (*grandchildren)->pdg_id() == 22) || (!m_allowPhotons && (*grandchildren)->pdg_id() == 22) || (!m_allowPi0 && (*grandchildren)->pdg_id() == 111))
0865 {
0866 break;
0867 }
0868 else
0869 {
0870 actualIntermediateDecayProducts.push_back((*grandchildren)->pdg_id());
0871 decayChain.push_back(std::make_pair(std::make_pair(m_genevt->get_embedding_id(), (*grandchildren)->barcode()), (*grandchildren)->pdg_id()));
0872 ++m_intermediate_product_counter;
0873
0874 HepMC::FourVector myFourVector = (*grandchildren)->momentum();
0875
0876 HepMC::GenVertex* thisVtx = (*grandchildren)->production_vertex();
0877 double vtxPos[3] = {thisVtx->point3d().x(), thisVtx->point3d().y(), thisVtx->point3d().z()};
0878 if (m_recalcualteEtaRange)
0879 {
0880 recalculateEta(myFourVector.py(), vtxPos);
0881 }
0882
0883 if (myFourVector.perp() < m_pt_req)
0884 {
0885 trackFailedPT = true;
0886 }
0887 if (!isInRange(m_eta_low_req, myFourVector.eta(), m_eta_high_req))
0888 {
0889 trackFailedETA = true;
0890 }
0891
0892 if (Verbosity() >= VERBOSITY_MAX)
0893 {
0894 std::cout << "pT = " << myFourVector.perp() << ", eta = " << myFourVector.eta() << std::endl;
0895 std::cout << "The track " << passOrFail(myFourVector.perp() >= m_pt_req) << " the pT requirement, ";
0896 std::cout << "the track " << passOrFail(isInRange(m_eta_low_req, myFourVector.eta(), m_eta_high_req)) << " the eta requirement." << std::endl;
0897 }
0898 }
0899 }
0900
0901 acceptParticle = compareDecays(requiredIntermediateDecayProducts, actualIntermediateDecayProducts);
0902 }
0903
0904
0905
0906
0907 else
0908 {
0909 if (Verbosity() >= VERBOSITY_MAX)
0910 {
0911 std::cout << "This is a final state track" << std::endl;
0912 }
0913 const HepMC::FourVector& myFourVector = particle->momentum();
0914
0915 HepMC::GenVertex* thisVtx = particle->production_vertex();
0916 double vtxPos[3] = {thisVtx->point3d().x(), thisVtx->point3d().y(), thisVtx->point3d().z()};
0917 if (m_recalcualteEtaRange)
0918 {
0919 recalculateEta(myFourVector.py(), vtxPos);
0920 }
0921
0922 if (myFourVector.perp() < m_pt_req)
0923 {
0924 trackFailedPT = true;
0925 }
0926 if (!isInRange(m_eta_low_req, myFourVector.eta(), m_eta_high_req))
0927 {
0928 trackFailedETA = true;
0929 }
0930
0931 if (Verbosity() >= VERBOSITY_MAX)
0932 {
0933 std::cout << "pT = " << myFourVector.perp() << ", eta = " << myFourVector.eta() << std::endl;
0934 std::cout << "The track " << passOrFail(myFourVector.perp() >= m_pt_req) << " the pT requirement, ";
0935 std::cout << "the track " << passOrFail(isInRange(m_eta_low_req, myFourVector.eta(), m_eta_high_req)) << " the eta requirement." << std::endl;
0936 }
0937 acceptParticle = true;
0938 }
0939
0940 return acceptParticle;
0941 }
0942
0943
0944
0945
0946 bool DecayFinder::checkIfCorrectGeant4Particle(PHG4Particle* particle, bool& hasPhoton, bool& hasPi0, bool& trackFailedPT, bool& trackFailedETA)
0947 {
0948 bool acceptParticle = false;
0949
0950 std::vector<int> positive_intermediates_ID;
0951 for (int i : m_intermediates_ID)
0952 {
0953 positive_intermediates_ID.push_back(abs(i));
0954 }
0955
0956 if (std::find(positive_intermediates_ID.begin(), positive_intermediates_ID.end(),
0957 abs(particle->get_pid())) != positive_intermediates_ID.end())
0958 {
0959 std::vector<int> requiredIntermediateDecayProducts;
0960 std::vector<int> actualIntermediateDecayProducts;
0961
0962 auto it = std::find(positive_intermediates_ID.begin(), positive_intermediates_ID.end(), abs(particle->get_pid()));
0963 int index = std::distance(positive_intermediates_ID.begin(), it);
0964
0965 unsigned int trackStart = 0, trackStop = 0;
0966 if (index == 0)
0967 {
0968 trackStop = m_nTracksFromIntermediates[0];
0969 }
0970 else
0971 {
0972 for (int i = 0; i < index; ++i)
0973 {
0974 trackStart += m_nTracksFromIntermediates[i];
0975 }
0976 trackStop = trackStart + m_nTracksFromIntermediates[index];
0977 }
0978
0979 std::vector<int> positive_intermediateDecayProducts;
0980 for (unsigned int i = trackStart; i < trackStop; ++i)
0981 {
0982 positive_intermediateDecayProducts.push_back(abs(m_daughters_ID[i]));
0983 requiredIntermediateDecayProducts.push_back(m_daughters_ID[i]);
0984 }
0985
0986 bool fakeBreak = false;
0987 searchGeant4Record(particle->get_barcode(), particle->get_pid(), positive_intermediateDecayProducts, fakeBreak,
0988 hasPhoton, hasPi0, trackFailedPT, trackFailedETA, actualIntermediateDecayProducts);
0989
0990 acceptParticle = compareDecays(requiredIntermediateDecayProducts, actualIntermediateDecayProducts);
0991 }
0992
0993
0994
0995
0996 else
0997 {
0998 if (Verbosity() >= VERBOSITY_MAX)
0999 {
1000 std::cout << "This is a final state track" << std::endl;
1001 }
1002 double px = particle->get_px();
1003 double py = particle->get_py();
1004 double pz = particle->get_pz();
1005
1006 double pt = std::sqrt(std::pow(px, 2) + std::pow(py, 2));
1007 double p = std::sqrt(std::pow(px, 2) + std::pow(py, 2) + std::pow(pz, 2));
1008 double eta = 0.5 * std::log((p + pz) / (p - pz));
1009
1010 PHG4VtxPoint* thisVtx = m_truthinfo->GetVtx(particle->get_vtx_id());
1011 double vtxPos[3] = {thisVtx->get_x(), thisVtx->get_y(), thisVtx->get_z()};
1012 if (m_recalcualteEtaRange)
1013 {
1014 recalculateEta(py, vtxPos);
1015 }
1016
1017 if (pt < m_pt_req)
1018 {
1019 trackFailedPT = true;
1020 }
1021 if (!isInRange(m_eta_low_req, eta, m_eta_high_req))
1022 {
1023 trackFailedETA = true;
1024 }
1025
1026 if (Verbosity() >= VERBOSITY_MAX)
1027 {
1028 std::cout << "pT = " << pt << ", eta = " << eta << std::endl;
1029 std::cout << "The track " << passOrFail(pt >= m_pt_req) << " the pT requirement, ";
1030 std::cout << "the track " << passOrFail(isInRange(m_eta_low_req, eta, m_eta_high_req)) << " the eta requirement." << std::endl;
1031 }
1032
1033 acceptParticle = true;
1034 }
1035
1036 return acceptParticle;
1037 }
1038
1039
1040
1041
1042 bool DecayFinder::compareDecays(std::vector<int> required, std::vector<int> actual)
1043 {
1044 bool accept = false;
1045 multiplyVectorByScalarAndSort(required, +1);
1046 multiplyVectorByScalarAndSort(actual, +1);
1047
1048 if (Verbosity() >= VERBOSITY_MAX)
1049 {
1050 std::cout << "Printing required decay products: ";
1051 for (int i : required)
1052 {
1053 std::cout << i << ", ";
1054 }
1055 std::cout << std::endl;
1056 std::cout << "Printing actual decay products: ";
1057 for (int i : actual)
1058 {
1059 std::cout << i << ", ";
1060 }
1061 std::cout << std::endl;
1062 if (required == actual)
1063 {
1064 std::cout << "*\n* These vectors match\n*\n"
1065 << std::endl;
1066 }
1067 else
1068 {
1069 std::cout << "*\n* These vectors DONT match\n*\n"
1070 << std::endl;
1071 }
1072 }
1073
1074 if (required == actual)
1075 {
1076 accept = true;
1077 }
1078
1079 if (m_getChargeConjugate && !accept)
1080 {
1081 multiplyVectorByScalarAndSort(required, -1);
1082 if (required == actual)
1083 {
1084 accept = true;
1085 }
1086
1087 if (Verbosity() >= VERBOSITY_MAX)
1088 {
1089 std::cout << "Checking CC state" << std::endl;
1090 if (required == actual)
1091 {
1092 std::cout << "*\n* These vectors match\n*\n"
1093 << std::endl;
1094 }
1095 else
1096 {
1097 std::cout << "*\n* These vectors DONT match\n*\n"
1098 << std::endl;
1099 }
1100 }
1101 }
1102 return accept;
1103 }
1104
1105
1106
1107
1108 int DecayFinder::deleteElement(int arr[], int n, int x)
1109 {
1110
1111
1112 int i;
1113 for (i = 0; i < n; i++)
1114 {
1115 if (arr[i] == x)
1116 {
1117 break;
1118 }
1119 }
1120
1121
1122 if (i < n)
1123 {
1124
1125
1126 n = n - 1;
1127 for (int j = i; j < n; j++)
1128 {
1129 arr[j] = arr[j + 1];
1130 }
1131 }
1132
1133 return n;
1134 }
1135
1136 bool DecayFinder::findParticle(const std::string& particle)
1137 {
1138 bool particleFound = true;
1139 if (!TDatabasePDG::Instance()->GetParticle(particle.c_str()))
1140 {
1141 if (Verbosity() >= VERBOSITY_SOME)
1142 {
1143 std::cout << "The particle, " << particle << " is not in the TDatabasePDG particle list" << std::endl;
1144 }
1145 particleFound = false;
1146 }
1147
1148 return particleFound;
1149 }
1150
1151 void DecayFinder::multiplyVectorByScalarAndSort(std::vector<int>& v, int k)
1152 {
1153
1154 std::transform(v.begin(), v.end(), v.begin(), [k](const int& c)
1155 {
1156 int particlesWithNoCC[] = {111, 113, 115, 130, 220, 221, 223, 225, 310, 330, 331, 333, 335, 440, 441, 443,
1157 445, 551, 553, 555, 10111, 10113, 10221, 10223, 10331, 10333, 10441, 10443,
1158 10551, 10553, 20113, 20223, 20333, 20443, 20553, 100443, 100553};
1159 if (std::find(std::begin(particlesWithNoCC), std::end(particlesWithNoCC), c) != std::end(particlesWithNoCC))
1160 {
1161 return c;
1162 }
1163 else
1164 {
1165 return c * k;
1166 }
1167 });
1168 std::sort(v.begin(), v.end());
1169 }
1170
1171 int DecayFinder::get_pdgcode(const std::string& name)
1172 {
1173 if (findParticle(name))
1174 {
1175 return TDatabasePDG::Instance()->GetParticle(name.c_str())->PdgCode();
1176 }
1177 else
1178 {
1179 return 0;
1180 }
1181 }
1182
1183 int DecayFinder::get_charge(const std::string& name)
1184 {
1185 if (findParticle(name))
1186 {
1187 return TDatabasePDG::Instance()->GetParticle(name.c_str())->Charge() / 3;
1188 }
1189 else
1190 {
1191 return -99;
1192 }
1193 }
1194
1195 bool DecayFinder::isInRange(float min, float value, float max)
1196 {
1197 return min <= value && value <= max;
1198 }
1199
1200 void DecayFinder::calculateEffectiveTPCradius(double vertex[3], double& effective_top_r, double& effective_bottom_r)
1201 {
1202 double r_sq = std::pow(m_tpc_r, 2);
1203 double x_sq = std::pow(vertex[0], 2);
1204
1205 effective_top_r = std::sqrt(r_sq - x_sq) - vertex[1];
1206 effective_bottom_r = std::sqrt(r_sq - x_sq) + vertex[1];
1207 }
1208
1209 void DecayFinder::recalculateEta(double py, double vertex[3])
1210 {
1211 calculateEffectiveTPCradius(vertex, m_effective_top_tpc_r, m_effective_bottom_tpc_r);
1212
1213 double z_north = m_tpc_z - vertex[2];
1214 double z_south = m_tpc_z + vertex[2];
1215
1216 double top_north_theta = atan(m_effective_top_tpc_r / z_north);
1217 double bottom_north_theta = atan(m_effective_bottom_tpc_r / z_north);
1218 double top_south_theta = atan(m_effective_top_tpc_r / z_south);
1219 double bottom_south_theta = atan(m_effective_bottom_tpc_r / z_south);
1220
1221 double top_north_eta = -1 * std::log(tan(top_north_theta / 2));
1222 double bottom_north_eta = -1 * std::log(tan(bottom_north_theta / 2));
1223 double top_south_eta = std::log(tan(top_south_theta / 2));
1224 double bottom_south_eta = std::log(tan(bottom_south_theta / 2));
1225
1226 m_eta_high_req = py < 0 ? bottom_north_eta : top_north_eta;
1227 m_eta_low_req = py < 0 ? bottom_south_eta : top_south_eta;
1228 }
1229
1230 int DecayFinder::createDecayNode(PHCompositeNode* topNode)
1231 {
1232 PHNodeIterator iter(topNode);
1233
1234 PHCompositeNode* lowerNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
1235 if (!lowerNode)
1236 {
1237 lowerNode = new PHCompositeNode("DST");
1238 topNode->addNode(lowerNode);
1239 std::cout << "DST node added" << std::endl;
1240 }
1241
1242 std::string baseName;
1243
1244 if (m_container_name.empty())
1245 {
1246
1247 baseName = Name();
1248 }
1249 else
1250 {
1251 baseName = m_container_name;
1252 }
1253
1254
1255 size_t pos;
1256 std::string undrscr = "_";
1257 std::string nothing = "";
1258 std::map<std::string, std::string> forbiddenStrings;
1259 forbiddenStrings["/"] = undrscr;
1260 forbiddenStrings["("] = undrscr;
1261 forbiddenStrings[")"] = nothing;
1262 forbiddenStrings["+"] = "plus";
1263 forbiddenStrings["-"] = "minus";
1264 forbiddenStrings["*"] = "star";
1265 forbiddenStrings[" "] = nothing;
1266 for (auto const& [badString, goodString] : forbiddenStrings)
1267 {
1268 while ((pos = baseName.find(badString)) != std::string::npos)
1269 {
1270 baseName.replace(pos, 1, goodString);
1271 }
1272 }
1273
1274 m_nodeName = baseName + "_DecayMap";
1275
1276 m_decayMap = new DecayFinderContainer_v1();
1277 PHIODataNode<PHObject>* decayNode = new PHIODataNode<PHObject>(m_decayMap, m_nodeName.c_str(), "PHObject");
1278 lowerNode->addNode(decayNode);
1279 std::cout << m_nodeName << " node added" << std::endl;
1280
1281 return Fun4AllReturnCodes::EVENT_OK;
1282 }
1283
1284 void DecayFinder::fillDecayNode(PHCompositeNode* topNode, Decay& decay)
1285 {
1286 m_decayMap = findNode::getClass<DecayFinderContainer_v1>(topNode, m_nodeName.c_str());
1287 m_decayMap->insert(decay);
1288 }
1289
1290 void DecayFinder::printInfo()
1291 {
1292 std::cout << "\n---------------DecayFinder information---------------" << std::endl;
1293 std::cout << "Module name: " << Name() << std::endl;
1294 std::cout << "Decay descriptor: " << m_decayDescriptor << std::endl;
1295 std::cout << "Number of generated decays: " << m_counter << std::endl;
1296 std::cout << " Number of decays that failed pT requirement: " << m_nCandFail_pT << std::endl;
1297 std::cout << " Number of decays that failed eta requirement: " << m_nCandFail_eta << std::endl;
1298 std::cout << " Number of decays that failed pT and eta requirements: " << m_nCandFail_pT_and_eta << std::endl;
1299 std::cout << "Number of decays that could be reconstructed: " << m_nCandReconstructable << std::endl;
1300 std::cout << " Number of reconstructable mothers with associated photon: " << m_nCandHas_Photon << std::endl;
1301 std::cout << " Number of reconstructable mothers with associated Pi0: " << m_nCandHas_Pi0 << std::endl;
1302 std::cout << " Number of reconstructable mothers with associated photon and Pi0: " << m_nCandHas_Photon_and_Pi0 << std::endl;
1303 std::cout << " Number of reconstructable mothers with no associated photons or Pi0s: " << m_nCandHas_noPhoton_and_noPi0 << std::endl;
1304 std::cout << "-----------------------------------------------------\n";
1305 std::cout << std::endl;
1306 }
1307
1308 void DecayFinder::printNode(PHCompositeNode* topNode)
1309 {
1310 std::cout << "----------------";
1311 std::cout << " DecayFinderNode: " << m_nodeName << " information ";
1312 std::cout << "----------------" << std::endl;
1313 DecayFinderContainer_v1* map = findNode::getClass<DecayFinderContainer_v1>(topNode, m_nodeName.c_str());
1314 for (auto& iter : *map)
1315 {
1316 Decay decay = iter.second;
1317 for (auto& i : decay)
1318 {
1319 std::cout << "Particle embedding ID: " << i.first.first << ", particle barcode: " << i.first.second << ", particle PDG ID: " << i.second << std::endl;
1320 }
1321 }
1322 std::cout << "--------------------------------------------------------------------------------------------------" << std::endl;
1323 }
1324
1325 std::string DecayFinder::passOrFail(bool condition)
1326 {
1327 return condition ? "passed" : "failed";
1328 }