File indexing completed on 2025-08-06 08:17:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "KFParticle_sPHENIX.h"
0023
0024 #include <globalvertex/MbdVertex.h>
0025 #include <globalvertex/MbdVertexMap.h>
0026 #include <globalvertex/SvtxVertexMap.h>
0027 #include <trackbase_historic/SvtxTrackMap.h>
0028
0029 #include <fun4all/Fun4AllReturnCodes.h>
0030
0031 #include <phool/getClass.h>
0032
0033 #include <TEntryList.h>
0034 #include <TFile.h>
0035 #include <TLeaf.h>
0036 #include <TSystem.h>
0037 #include <TTree.h> // for getting the TTree from the file
0038
0039 #include <KFPVertex.h>
0040 #include <KFParticle.h> // for KFParticle
0041 #include <fun4all/Fun4AllBase.h> // for Fun4AllBase::VERBOSITY...
0042 #include <fun4all/SubsysReco.h> // for SubsysReco
0043
0044 #include <ffamodules/CDBInterface.h> // for accessing the field map file from the CDB
0045 #include <cctype> // for toupper
0046 #include <cmath> // for sqrt
0047 #include <cstdlib> // for size_t, exit
0048 #include <filesystem>
0049 #include <iostream> // for operator<<, endl, basi...
0050 #include <map> // for map
0051 #include <tuple> // for tie, tuple
0052
0053 class PHCompositeNode;
0054
0055 namespace TMVA
0056 {
0057 class Reader;
0058 }
0059
0060
0061
0062
0063 KFParticle_sPHENIX::KFParticle_sPHENIX()
0064 : SubsysReco("KFPARTICLE")
0065 , m_has_intermediates_sPHENIX(false)
0066 , m_constrain_to_vertex_sPHENIX(false)
0067 , m_require_mva(false)
0068 , m_save_dst(false)
0069 , m_save_output(true)
0070 , m_outfile_name("outputData.root")
0071 , m_outfile(nullptr)
0072 {
0073 }
0074
0075 KFParticle_sPHENIX::KFParticle_sPHENIX(const std::string &name)
0076 : SubsysReco(name)
0077 , m_has_intermediates_sPHENIX(false)
0078 , m_constrain_to_vertex_sPHENIX(false)
0079 , m_require_mva(false)
0080 , m_save_dst(false)
0081 , m_save_output(true)
0082 , m_outfile_name("outputData.root")
0083 , m_outfile(nullptr)
0084 {
0085 }
0086
0087 int KFParticle_sPHENIX::Init(PHCompositeNode *topNode)
0088 {
0089
0090 if (m_save_output && Verbosity() >= VERBOSITY_SOME)
0091 {
0092 std::cout << "Output nTuple: " << m_outfile_name << std::endl;
0093 }
0094
0095 if (m_save_dst)
0096 {
0097 createParticleNode(topNode);
0098 }
0099
0100 if (m_require_mva)
0101 {
0102 TMVA::Reader *reader;
0103 std::vector<Float_t> MVA_parValues;
0104 tie(reader, MVA_parValues) = initMVA();
0105 }
0106
0107 int returnCode = 0;
0108 if (!m_decayDescriptor.empty())
0109 {
0110 returnCode = parseDecayDescriptor();
0111 }
0112
0113 if (m_get_trigger_info)
0114 {
0115 triggeranalyzer = new TriggerAnalyzer();
0116 }
0117
0118 if (m_use_PID)
0119 {
0120 init_dEdx_fits();
0121 }
0122
0123 return returnCode;
0124 }
0125
0126 int KFParticle_sPHENIX::InitRun(PHCompositeNode *topNode)
0127 {
0128 assert(topNode);
0129
0130 getField();
0131
0132 return 0;
0133 }
0134
0135 int KFParticle_sPHENIX::process_event(PHCompositeNode *topNode)
0136 {
0137
0138 std::vector<KFParticle> mother, vertex_kfparticle;
0139 std::vector<std::vector<KFParticle>> daughters, intermediates;
0140 int nPVs, multiplicity;
0141
0142 SvtxTrackMap *check_trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trk_map_node_name);
0143 multiplicity = check_trackmap->size();
0144
0145 if (check_trackmap->size() == 0)
0146 {
0147 if (Verbosity() >= VERBOSITY_SOME)
0148 {
0149 std::cout << "KFParticle: Event skipped as there are no tracks" << std::endl;
0150 }
0151 return Fun4AllReturnCodes::ABORTEVENT;
0152 }
0153
0154 if (!m_use_fake_pv)
0155 {
0156 if (m_use_mbd_vertex)
0157 {
0158 MbdVertexMap* check_vertexmap = findNode::getClass<MbdVertexMap>(topNode, "MbdVertexMap");
0159 if (check_vertexmap->size() == 0)
0160 {
0161 if (Verbosity() >= VERBOSITY_SOME)
0162 {
0163 std::cout << "KFParticle: Event skipped as there are no vertices" << std::endl;
0164 }
0165 return Fun4AllReturnCodes::ABORTEVENT;
0166 }
0167 }
0168 else
0169 {
0170 SvtxVertexMap* check_vertexmap = findNode::getClass<SvtxVertexMap>(topNode, m_vtx_map_node_name);
0171 if (check_vertexmap->size() == 0)
0172 {
0173 if (Verbosity() >= VERBOSITY_SOME)
0174 {
0175 std::cout << "KFParticle: Event skipped as there are no vertices" << std::endl;
0176 }
0177 return Fun4AllReturnCodes::ABORTEVENT;
0178 }
0179 }
0180
0181 }
0182
0183 createDecay(topNode, mother, vertex_kfparticle, daughters, intermediates, nPVs);
0184 if (!m_has_intermediates_sPHENIX)
0185 {
0186 intermediates = daughters;
0187 }
0188 if (!m_constrain_to_vertex_sPHENIX)
0189 {
0190 vertex_kfparticle = mother;
0191 }
0192
0193 if (mother.size() != 0)
0194 {
0195 for (unsigned int i = 0; i < mother.size(); ++i)
0196 {
0197
0198 if (m_save_output && getCandidateCounter() == 0)
0199 {
0200 m_outfile = new TFile(m_outfile_name.c_str(), "RECREATE");
0201 initializeBranches(topNode);
0202 }
0203
0204
0205 incrementCandidateCounter();
0206
0207 if (m_save_output)
0208 {
0209 fillBranch(topNode, mother[i], vertex_kfparticle[i], daughters[i], intermediates[i]);
0210 }
0211 if (m_save_dst)
0212 {
0213 fillParticleNode(topNode, mother[i], vertex_kfparticle[i], daughters[i], intermediates[i]);
0214 }
0215
0216 if (Verbosity() >= VERBOSITY_SOME)
0217 {
0218 printParticles(mother[i], vertex_kfparticle[i], daughters[i], intermediates[i], nPVs, multiplicity);
0219 }
0220 if (Verbosity() >= VERBOSITY_MORE)
0221 {
0222 if (m_save_dst)
0223 {
0224 printNode(topNode);
0225 }
0226 }
0227 }
0228 }
0229
0230 return Fun4AllReturnCodes::EVENT_OK;
0231 }
0232
0233 int KFParticle_sPHENIX::End(PHCompositeNode * )
0234 {
0235 std::cout << "KFParticle_sPHENIX object " << Name() << " finished. Number of candidates: " << getCandidateCounter() << std::endl;
0236
0237 if (m_save_output && getCandidateCounter() != 0)
0238 {
0239 m_outfile->Write();
0240 m_outfile->Close();
0241 delete m_outfile;
0242 }
0243
0244 return 0;
0245 }
0246
0247 void KFParticle_sPHENIX::printParticles(const KFParticle &motherParticle,
0248 const KFParticle &chosenVertex,
0249 const std::vector<KFParticle> &daughterParticles,
0250 const std::vector<KFParticle> &intermediateParticles,
0251 const int numPVs, const int numTracks)
0252 {
0253 std::cout << "\n---------------KFParticle candidate information---------------" << std::endl;
0254
0255 std::cout << "Mother information:" << std::endl;
0256 identify(motherParticle);
0257
0258 if (m_has_intermediates_sPHENIX)
0259 {
0260 std::cout << "Intermediate state information:" << std::endl;
0261 for (const auto &intermediateParticle : intermediateParticles)
0262 {
0263 identify(intermediateParticle);
0264 }
0265 }
0266
0267 std::cout << "Final track information:" << std::endl;
0268 for (const auto &daughterParticle : daughterParticles)
0269 {
0270 identify(daughterParticle);
0271 }
0272
0273 if (m_constrain_to_vertex_sPHENIX)
0274 {
0275 std::cout << "Primary vertex information:" << std::endl;
0276 std::cout << "(x,y,z) = (" << chosenVertex.GetX() << " +/- " << std::sqrt(chosenVertex.GetCovariance(0, 0)) << ", ";
0277 std::cout << chosenVertex.GetY() << " +/- " << std::sqrt(chosenVertex.GetCovariance(1, 1)) << ", ";
0278 std::cout << chosenVertex.GetZ() << " +/- " << std::sqrt(chosenVertex.GetCovariance(2, 2)) << ") cm\n"
0279 << std::endl;
0280 }
0281
0282 std::cout << "The number of primary vertices is: " << numPVs << std::endl;
0283 std::cout << "The number of tracks in the event is: " << numTracks << std::endl;
0284
0285 std::cout << "------------------------------------------------------------\n"
0286 << std::endl;
0287 }
0288
0289 int KFParticle_sPHENIX::parseDecayDescriptor()
0290 {
0291 bool ddCanBeParsed = true;
0292
0293 size_t daughterLocator;
0294
0295 std::string mother;
0296 std::string intermediate;
0297 std::string daughter;
0298
0299 std::vector<std::pair<std::string, int>> intermediate_list;
0300 std::vector<std::string> intermediates_name;
0301 std::vector<int> intermediates_charge;
0302
0303 std::vector<std::pair<std::string, int>> daughter_list;
0304 std::vector<std::string> daughters_name;
0305 std::vector<int> daughters_charge;
0306
0307 int nTracks = 0;
0308 std::vector<int> m_nTracksFromIntermediates;
0309
0310 std::string decayArrow = "->";
0311 std::string chargeIndicator = "^";
0312 std::string startIntermediate = "{";
0313 std::string endIntermediate = "}";
0314
0315
0316 std::string specialTracks[] = {"e", "mu", "pi", "K"};
0317
0318 std::string manipulateDecayDescriptor = m_decayDescriptor;
0319
0320
0321 size_t pos;
0322 while ((pos = manipulateDecayDescriptor.find(' ')) != std::string::npos)
0323 {
0324 manipulateDecayDescriptor.replace(pos, 1, "");
0325 }
0326
0327
0328 std::string checkForCC = manipulateDecayDescriptor.substr(0, 1) + manipulateDecayDescriptor.substr(manipulateDecayDescriptor.size() - 3, 3);
0329 std::for_each(checkForCC.begin(), checkForCC.end(), [](char &c)
0330 { c = ::toupper(c); });
0331
0332
0333 if (checkForCC == "[]CC")
0334 {
0335 manipulateDecayDescriptor = manipulateDecayDescriptor.substr(1, manipulateDecayDescriptor.size() - 4);
0336 getChargeConjugate();
0337 }
0338
0339
0340 size_t findMotherEndPoint = manipulateDecayDescriptor.find(decayArrow);
0341 mother = manipulateDecayDescriptor.substr(0, findMotherEndPoint);
0342 if (!findParticle(mother))
0343 {
0344 ddCanBeParsed = false;
0345 }
0346 manipulateDecayDescriptor.erase(0, findMotherEndPoint + decayArrow.length());
0347
0348
0349 while ((pos = manipulateDecayDescriptor.find(startIntermediate)) != std::string::npos)
0350 {
0351 size_t findIntermediateStartPoint = manipulateDecayDescriptor.find(startIntermediate, pos);
0352 size_t findIntermediateEndPoint = manipulateDecayDescriptor.find(endIntermediate, pos);
0353 std::string intermediateDecay = manipulateDecayDescriptor.substr(pos + 1, findIntermediateEndPoint - (pos + 1));
0354
0355 intermediate = intermediateDecay.substr(0, intermediateDecay.find(decayArrow));
0356 if (findParticle(intermediate))
0357 {
0358 intermediates_name.emplace_back(intermediate.c_str());
0359 }
0360 else
0361 {
0362 ddCanBeParsed = false;
0363 }
0364
0365
0366 int nDaughters = 0;
0367 intermediateDecay.erase(0, intermediateDecay.find(decayArrow) + decayArrow.length());
0368 while ((daughterLocator = intermediateDecay.find(chargeIndicator)) != std::string::npos)
0369 {
0370 daughter = intermediateDecay.substr(0, daughterLocator);
0371 std::string daughterChargeString = intermediateDecay.substr(daughterLocator + 1, 1);
0372 if (std::find(std::begin(specialTracks), std::end(specialTracks), daughter) != std::end(specialTracks))
0373 {
0374 daughter += daughterChargeString;
0375 }
0376 if (findParticle(daughter))
0377 {
0378 daughters_name.emplace_back(daughter.c_str());
0379
0380 if (daughterChargeString == "+")
0381 {
0382 daughters_charge.push_back(+1);
0383 }
0384 else if (daughterChargeString == "-")
0385 {
0386 daughters_charge.push_back(-1);
0387 }
0388 else if (daughterChargeString == "0")
0389 {
0390 daughters_charge.push_back(0);
0391 }
0392 else
0393 {
0394 if (Verbosity() >= VERBOSITY_MORE)
0395 {
0396 std::cout << "The charge of " << daughterChargeString << " was not known" << std::endl;
0397 }
0398 ddCanBeParsed = false;
0399 }
0400 }
0401 else
0402 {
0403 ddCanBeParsed = false;
0404 }
0405 intermediateDecay.erase(0, daughterLocator + 2);
0406 ++nDaughters;
0407 }
0408 manipulateDecayDescriptor.erase(findIntermediateStartPoint, findIntermediateEndPoint + 1 - findIntermediateStartPoint);
0409 m_nTracksFromIntermediates.push_back(nDaughters);
0410 nTracks += nDaughters;
0411 }
0412
0413
0414 while ((daughterLocator = manipulateDecayDescriptor.find(chargeIndicator)) != std::string::npos)
0415 {
0416 daughter = manipulateDecayDescriptor.substr(0, daughterLocator);
0417 std::string daughterChargeString = manipulateDecayDescriptor.substr(daughterLocator + 1, 1);
0418 if (std::find(std::begin(specialTracks), std::end(specialTracks), daughter) != std::end(specialTracks))
0419 {
0420 daughter += daughterChargeString;
0421 }
0422 if (findParticle(daughter))
0423 {
0424 daughters_name.emplace_back(daughter.c_str());
0425 if (daughterChargeString == "+")
0426 {
0427 daughters_charge.push_back(+1);
0428 }
0429 else if (daughterChargeString == "-")
0430 {
0431 daughters_charge.push_back(-1);
0432 }
0433 else if (daughterChargeString == "0")
0434 {
0435 daughters_charge.push_back(0);
0436 }
0437 else
0438 {
0439 if (Verbosity() >= VERBOSITY_MORE)
0440 {
0441 std::cout << "The charge of " << daughterChargeString << " was not known" << std::endl;
0442 }
0443 ddCanBeParsed = false;
0444 }
0445 }
0446 else
0447 {
0448 ddCanBeParsed = false;
0449 }
0450 manipulateDecayDescriptor.erase(0, daughterLocator + 2);
0451 nTracks += 1;
0452 }
0453
0454 int trackEnd = 0;
0455 for (unsigned int i = 0; i < intermediates_name.size(); ++i)
0456 {
0457 int trackStart = trackEnd;
0458 trackEnd = m_nTracksFromIntermediates[i] + trackStart;
0459
0460 int vtxCharge = 0;
0461
0462 for (int j = trackStart; j < trackEnd; ++j)
0463 {
0464 vtxCharge += daughters_charge[j];
0465 }
0466
0467 intermediates_charge.push_back(vtxCharge);
0468
0469 intermediate_list.emplace_back(intermediates_name[i], intermediates_charge[i]);
0470 }
0471
0472 daughter_list.reserve(nTracks);
0473 for (int i = 0; i < nTracks; ++i)
0474 {
0475 daughter_list.emplace_back(daughters_name[i], daughters_charge[i]);
0476 }
0477
0478 setMotherName(mother);
0479 setNumberOfTracks(nTracks);
0480 setDaughters(daughter_list);
0481
0482 if (intermediates_name.size() > 0)
0483 {
0484 hasIntermediateStates();
0485 setIntermediateStates(intermediate_list);
0486 setNumberOfIntermediateStates(intermediates_name.size());
0487 setNumberTracksFromIntermeditateState(m_nTracksFromIntermediates);
0488 }
0489
0490 if (ddCanBeParsed)
0491 {
0492 if (Verbosity() >= VERBOSITY_MORE)
0493 {
0494 std::cout << "Your decay descriptor can be parsed" << std::endl;
0495 }
0496 return 0;
0497 }
0498 else
0499 {
0500 if (Verbosity() >= VERBOSITY_SOME)
0501 {
0502 std::cout << "KFParticle: Your decay descriptor, " << Name() << " cannot be parsed"
0503 << "\nExiting!" << std::endl;
0504 }
0505 return Fun4AllReturnCodes::ABORTRUN;
0506 }
0507 }
0508
0509 void KFParticle_sPHENIX::getField()
0510 {
0511
0512 m_magField = std::filesystem::exists(m_magField) ? m_magField : CDBInterface::instance()->getUrl(m_magField);
0513
0514 if (Verbosity() > 0)
0515 {
0516 std::cout << PHWHERE << ": using fieldmap : " << m_magField << std::endl;
0517 }
0518
0519 TFile *fin = new TFile(m_magField.c_str());
0520 TTree *fieldmap = (TTree *) fin->Get("fieldmap");
0521
0522 float Bz = 0.;
0523 unsigned int r = 0.;
0524 float z = 0.;
0525
0526 double arc = M_PI/2;
0527 unsigned int n = 0;
0528
0529 while (Bz == 0)
0530 {
0531 if (n == 4)
0532 {
0533 ++r;
0534 }
0535
0536 if (r == 3)
0537 {
0538 ++z;
0539 }
0540
0541 n = n & 0x3U;
0542 r = r & 0x2U;
0543
0544 double x = r*std::cos(n*arc);
0545 double y = r*std::sin(n*arc);
0546
0547 std::string sweep = "x == " + std::to_string(x) + " && y == " + std::to_string(y) + " && z == " + std::to_string(z);
0548
0549 fieldmap->Draw(">>elist", sweep.c_str(), "entrylist");
0550 TEntryList *elist = (TEntryList*)gDirectory->Get("elist");
0551 if (elist->GetEntry(0))
0552 {
0553 TLeaf *fieldValue = fieldmap->GetLeaf("bz");
0554 fieldValue->GetBranch()->GetEntry(elist->GetEntry(0));
0555 Bz = fieldValue->GetValue();
0556 }
0557
0558 ++n;
0559
0560 if (r == 0)
0561 {
0562 ++r;
0563 n = 0;
0564 }
0565 }
0566
0567 Bz *= 10;
0568 KFParticle::SetField((double) Bz);
0569
0570 fieldmap->Delete();
0571 fin->Close();
0572 }