Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:48

0001 /*
0002  * This file is part of KFParticle package
0003  * Copyright ( C ) 2007-2019 FIAS Frankfurt Institute for Advanced Studies
0004  *               2007-2019 Goethe University of Frankfurt
0005  *               2007-2019 Ivan Kisel <I.Kisel@compeng.uni-frankfurt.de>
0006  *               2007-2019 Maksym Zyzak
0007  *
0008  * KFParticle is free software: you can redistribute it and/or modify
0009  * it under the terms of the GNU General Public License as published by
0010  * the Free Software Foundation, either version 3 of the License, or
0011  * ( at your option ) any later version.
0012  *
0013  * KFParticle is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016  * GNU General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU General Public License
0019  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
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 //int candidateCounter = 0;
0061 
0062 /// KFParticle constructor
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       //candidateCounter += 1;
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 * /*topNode*/)
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   // These tracks require a + or - after their name for TDatabasePDG
0316   std::string specialTracks[] = {"e", "mu", "pi", "K"};
0317 
0318   std::string manipulateDecayDescriptor = m_decayDescriptor;
0319 
0320   // Remove all white space before we begin
0321   size_t pos;
0322   while ((pos = manipulateDecayDescriptor.find(' ')) != std::string::npos)
0323   {
0324     manipulateDecayDescriptor.replace(pos, 1, "");
0325   }
0326 
0327   // Check for charge conjugate requirement
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   // Remove the CC check if needed
0333   if (checkForCC == "[]CC")
0334   {
0335     manipulateDecayDescriptor = manipulateDecayDescriptor.substr(1, manipulateDecayDescriptor.size() - 4);
0336     getChargeConjugate();
0337   }
0338 
0339   // Find the initial particle
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   // Try and find the intermediates
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     // Now find the daughters associated to this intermediate
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   // Now find any remaining reconstructable tracks from the mother
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   //This sweeps the sPHENIX magnetic field map from some point radially then grabs the first event that passes the selection
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) //Dont go too far out radially
0537     {
0538       ++z;
0539     }
0540 
0541     n = n & 0x3U; //Constrains n from 0 to 3
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) // No point in rescanning (0,0)
0561     {
0562       ++r;
0563       n = 0;
0564     }
0565   }
0566   // The actual unit of KFParticle is in kilo Gauss (kG), which is equivalent to 0.1 T, instead of Tesla (T). The positive value indicates the B field is in the +z direction
0567   Bz *= 10;  // Factor of 10 to convert the B field unit from kG to T
0568   KFParticle::SetField((double) Bz);
0569 
0570   fieldmap->Delete();
0571   fin->Close();
0572 }