Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:18:07

0001 /*!
0002  * \file Fun4AllDstPileupInputMerger.h
0003  * \author Hugo Pereira Da Costa <hugo.pereira-da-costa@cea.fr>
0004  */
0005 
0006 #include "Fun4AllDstPileupMerger.h"
0007 
0008 #include "PHG4Hit.h"  // for PHG4Hit
0009 #include "PHG4HitContainer.h"
0010 #include "PHG4Hitv1.h"
0011 #include "PHG4Particle.h"  // for PHG4Particle
0012 #include "PHG4Particlev3.h"
0013 #include "PHG4TruthInfoContainer.h"
0014 #include "PHG4VtxPoint.h"  // for PHG4VtxPoint
0015 #include "PHG4VtxPointv1.h"
0016 
0017 #include <phhepmc/PHHepMCGenEvent.h>  // for PHHepMCGenEvent
0018 #include <phhepmc/PHHepMCGenEventMap.h>
0019 
0020 #include <phool/PHCompositeNode.h>
0021 #include <phool/PHIODataNode.h>    // for PHIODataNode
0022 #include <phool/PHNode.h>          // for PHNode
0023 #include <phool/PHNodeIterator.h>  // for PHNodeIterator
0024 #include <phool/PHNodeOperation.h>
0025 #include <phool/PHObject.h>  // for PHObject
0026 #include <phool/getClass.h>
0027 
0028 #include <TObject.h>
0029 
0030 #pragma GCC diagnostic push
0031 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0032 #include <HepMC/GenEvent.h>
0033 #pragma GCC diagnostic pop
0034 
0035 #include <iostream>
0036 #include <iterator>
0037 #include <limits>
0038 #include <utility>
0039 
0040 // convenient aliases for deep copying nodes
0041 namespace
0042 {
0043   using PHG4Particle_t = PHG4Particlev3;
0044   using PHG4VtxPoint_t = PHG4VtxPointv1;
0045   using PHG4Hit_t = PHG4Hitv1;
0046 
0047   //! utility class to find all PHG4Hit container nodes from the DST node
0048   class FindG4HitContainer : public PHNodeOperation
0049   {
0050    public:
0051     //! container map alias
0052     using ContainerMap = std::map<std::string, PHG4HitContainer *>;
0053 
0054     //! get container map
0055     const ContainerMap &containers() const
0056     {
0057       return m_containers;
0058     }
0059 
0060    protected:
0061     //! iterator action
0062     void perform(PHNode *node) override
0063     {
0064       // check type name. Only load PHIODataNode
0065       if (node->getType() != "PHIODataNode")
0066       {
0067         return;
0068       }
0069 
0070       // cast to IODataNode and check data
0071       auto ionode = static_cast<PHIODataNode<TObject> *>(node);
0072       auto data = dynamic_cast<PHG4HitContainer *>(ionode->getData());
0073       if (data)
0074       {
0075         m_containers.insert(std::make_pair(node->getName(), data));
0076       }
0077     }
0078 
0079    private:
0080     //! container map
0081     ContainerMap m_containers;
0082   };
0083 
0084 }  // namespace
0085 
0086 //_____________________________________________________________________________
0087 void Fun4AllDstPileupMerger::load_nodes(PHCompositeNode *dstNode)
0088 {
0089   // hep mc
0090   m_geneventmap = findNode::getClass<PHHepMCGenEventMap>(dstNode, "PHHepMCGenEventMap");
0091   if (!m_geneventmap)
0092   {
0093     std::cout << "Fun4AllDstPileupMerger::load_nodes - creating PHHepMCGenEventMap" << std::endl;
0094     m_geneventmap = new PHHepMCGenEventMap();
0095     dstNode->addNode(new PHIODataNode<PHObject>(m_geneventmap, "PHHepMCGenEventMap", "PHObject"));
0096   }
0097 
0098   // find all G4Hit containers under dstNode
0099   FindG4HitContainer nodeFinder;
0100   PHNodeIterator(dstNode).forEach(nodeFinder);
0101   m_g4hitscontainers = nodeFinder.containers();
0102 
0103   // g4 truth info
0104   m_g4truthinfo = findNode::getClass<PHG4TruthInfoContainer>(dstNode, "G4TruthInfo");
0105   if (!m_g4truthinfo)
0106   {
0107     std::cout << "Fun4AllDstPileupMerger::load_nodes - creating node G4TruthInfo" << std::endl;
0108     m_g4truthinfo = new PHG4TruthInfoContainer();
0109     dstNode->addNode(new PHIODataNode<PHObject>(m_g4truthinfo, "G4TruthInfo", "PHObject"));
0110   }
0111 }
0112 
0113 //_____________________________________________________________________________
0114 void Fun4AllDstPileupMerger::copy_background_event(PHCompositeNode *dstNode, double delta_t) const
0115 {
0116   // copy PHHepMCGenEventMap
0117   const auto map = findNode::getClass<PHHepMCGenEventMap>(dstNode, "PHHepMCGenEventMap");
0118 
0119   // keep track of new embed id, after insertion as background event
0120   int new_embed_id = -1;
0121 
0122   if (map && m_geneventmap)
0123   {
0124     if (map->size() != 1)
0125     {
0126       std::cout << "Fun4AllDstPileupMerger::copy_background_event - cannot merge events that contain more than one PHHepMCGenEventMap" << std::endl;
0127       return;
0128     }
0129 
0130     // get event and insert in new map
0131     auto genevent = map->get_map().begin()->second;
0132     auto newevent = m_geneventmap->insert_background_event(genevent);
0133 
0134     /*
0135      * this hack prevents a crash when writting out
0136      * it boils down to root trying to write deleted items from the HepMC::GenEvent copy if the source has been deleted
0137      * it does not happen if the source gets written while the copy is deleted
0138      */
0139     newevent->getEvent()->swap(*genevent->getEvent());
0140 
0141     // shift vertex time and store new embed id
0142     newevent->moveVertex(0, 0, 0, delta_t);
0143     new_embed_id = newevent->get_embedding_id();
0144   }
0145 
0146   // copy truth container
0147   // keep track of the correspondance between source index and destination index for vertices, tracks and showers
0148   using ConversionMap = std::map<int, int>;
0149   ConversionMap vtxid_map;
0150   ConversionMap trkid_map;
0151 
0152   const auto container_truth = findNode::getClass<PHG4TruthInfoContainer>(dstNode, "G4TruthInfo");
0153   if (container_truth && m_g4truthinfo)
0154   {
0155     {
0156       // primary vertices
0157       auto key = m_g4truthinfo->maxvtxindex();
0158       const auto range = container_truth->GetPrimaryVtxRange();
0159       for (auto iter = range.first; iter != range.second; ++iter)
0160       {
0161         // clone vertex, insert in map, and add index conversion
0162         const auto &sourceVertex = iter->second;
0163         auto newVertex = new PHG4VtxPoint_t(sourceVertex);
0164         newVertex->set_t(sourceVertex->get_t() + delta_t);
0165         m_g4truthinfo->AddVertex(++key, newVertex);
0166         vtxid_map.insert(std::make_pair(sourceVertex->get_id(), key));
0167       }
0168     }
0169 
0170     {
0171       // secondary vertices
0172       auto key = m_g4truthinfo->minvtxindex();
0173       const auto range = container_truth->GetSecondaryVtxRange();
0174 
0175       // loop from last to first to preserve order with respect to the original event
0176       for (
0177           auto iter = std::reverse_iterator<PHG4TruthInfoContainer::ConstVtxIterator>(range.second);
0178           iter != std::reverse_iterator<PHG4TruthInfoContainer::ConstVtxIterator>(range.first);
0179           ++iter)
0180       {
0181         // clone vertex, shift time, insert in map, and add index conversion
0182         const auto &sourceVertex = iter->second;
0183         auto newVertex = new PHG4VtxPoint_t(sourceVertex);
0184         newVertex->set_t(sourceVertex->get_t() + delta_t);
0185         m_g4truthinfo->AddVertex(--key, newVertex);
0186         vtxid_map.insert(std::make_pair(sourceVertex->get_id(), key));
0187       }
0188     }
0189 
0190     {
0191       // primary particles
0192       auto key = m_g4truthinfo->maxtrkindex();
0193       const auto range = container_truth->GetPrimaryParticleRange();
0194       for (auto iter = range.first; iter != range.second; ++iter)
0195       {
0196         const auto &source = iter->second;
0197         auto dest = new PHG4Particle_t(source);
0198         m_g4truthinfo->AddParticle(++key, dest);
0199         dest->set_track_id(key);
0200 
0201         // set parent to zero
0202         dest->set_parent_id(0);
0203 
0204         // set primary to itself
0205         dest->set_primary_id(dest->get_track_id());
0206 
0207         // update vertex
0208         const auto keyiter = vtxid_map.find(source->get_vtx_id());
0209         if (keyiter != vtxid_map.end())
0210         {
0211           dest->set_vtx_id(keyiter->second);
0212         }
0213         else
0214         {
0215           std::cout << "Fun4AllDstPileupMerger::copy_background_event - vertex id " << source->get_vtx_id() << " not found in map" << std::endl;
0216         }
0217 
0218         // insert in map
0219         trkid_map.insert(std::make_pair(source->get_track_id(), dest->get_track_id()));
0220       }
0221     }
0222 
0223     {
0224       // secondary particles
0225       auto key = m_g4truthinfo->mintrkindex();
0226       const auto range = container_truth->GetSecondaryParticleRange();
0227 
0228       /*
0229        * loop from last to first to preserve order with respect to the original event
0230        * also this ensures that for a given particle its parent has already been converted and thus found in the map
0231        */
0232       for (
0233           auto iter = std::reverse_iterator<PHG4TruthInfoContainer::ConstIterator>(range.second);
0234           iter != std::reverse_iterator<PHG4TruthInfoContainer::ConstIterator>(range.first);
0235           ++iter)
0236       {
0237         const auto &source = iter->second;
0238         auto dest = new PHG4Particle_t(source);
0239         m_g4truthinfo->AddParticle(--key, dest);
0240         dest->set_track_id(key);
0241 
0242         // update parent id
0243         auto keyiter = trkid_map.find(source->get_parent_id());
0244         if (keyiter != trkid_map.end())
0245         {
0246           dest->set_parent_id(keyiter->second);
0247         }
0248         else
0249         {
0250           std::cout << "Fun4AllDstPileupMerger::copy_background_event - track id " << source->get_parent_id() << " not found in map" << std::endl;
0251         }
0252 
0253         // update primary id
0254         keyiter = trkid_map.find(source->get_primary_id());
0255         if (keyiter != trkid_map.end())
0256         {
0257           dest->set_primary_id(keyiter->second);
0258         }
0259         else
0260         {
0261           std::cout << "Fun4AllDstPileupMerger::copy_background_event - track id " << source->get_primary_id() << " not found in map" << std::endl;
0262         }
0263 
0264         // update vertex
0265         keyiter = vtxid_map.find(source->get_vtx_id());
0266         if (keyiter != vtxid_map.end())
0267         {
0268           dest->set_vtx_id(keyiter->second);
0269         }
0270         else
0271         {
0272           std::cout << "Fun4AllDstPileupMerger::copy_background_event - vertex id " << source->get_vtx_id() << " not found in map" << std::endl;
0273         }
0274 
0275         // insert in map
0276         trkid_map.insert(std::make_pair(source->get_track_id(), dest->get_track_id()));
0277       }
0278     }
0279 
0280     // vertex embed flags
0281     /* embed flag is stored only for primary vertices, consistently with PHG4TruthEventAction */
0282     for (const auto &pair : vtxid_map)
0283     {
0284       if (pair.first > 0)
0285       {
0286         m_g4truthinfo->AddEmbededVtxId(pair.second, new_embed_id);
0287       }
0288     }
0289 
0290     // track embed flags
0291     /* embed flag is stored only for primary tracks, consistently with PHG4TruthEventAction */
0292     for (const auto &pair : trkid_map)
0293     {
0294       if (pair.first > 0)
0295       {
0296         m_g4truthinfo->AddEmbededTrkId(pair.second, new_embed_id);
0297       }
0298     }
0299   }
0300 
0301   // copy g4hits
0302   // loop over registered maps
0303   for (const auto &pair : m_g4hitscontainers)
0304   {
0305     // check destination node
0306     if (!pair.second)
0307     {
0308       std::cout << "Fun4AllDstPileupMerger::copy_background_event - invalid destination container " << pair.first << std::endl;
0309       continue;
0310     }
0311 
0312     // find source node
0313     auto container_hit = findNode::getClass<PHG4HitContainer>(dstNode, pair.first);
0314     if (!container_hit)
0315     {
0316       std::cout << "Fun4AllDstPileupMerger::copy_background_event - invalid source container " << pair.first << std::endl;
0317       continue;
0318     }
0319     auto detiter = m_DetectorTiming.find(pair.first);
0320     // apply special  cuts for selected detectors
0321     if (detiter != m_DetectorTiming.end())
0322     {
0323       if (delta_t < detiter->second.first || delta_t > detiter->second.second)
0324       {
0325         continue;
0326       }
0327     }
0328     {
0329       // hits
0330       const auto range = container_hit->getHits();
0331       for (auto iter = range.first; iter != range.second; ++iter)
0332       {
0333         // clone hit
0334         const auto &sourceHit = iter->second;
0335         auto newHit = new PHG4Hit_t(sourceHit);
0336 
0337         // shift time
0338         newHit->set_t(0, sourceHit->get_t(0) + delta_t);
0339         newHit->set_t(1, sourceHit->get_t(1) + delta_t);
0340 
0341         // update track id
0342         const auto keyiter = trkid_map.find(sourceHit->get_trkid());
0343         if (keyiter != trkid_map.end())
0344         {
0345           newHit->set_trkid(keyiter->second);
0346         }
0347         else
0348         {
0349           std::cout << "Fun4AllDstPileupMerger::copy_background_event - track id " << sourceHit->get_trkid() << " not found in map" << std::endl;
0350         }
0351 
0352         /*
0353          * reset shower ids
0354          * it was decided that showers from the background events will not be copied to the merged event
0355          * as such we just reset the hits shower id
0356          */
0357         newHit->set_shower_id(std::numeric_limits<int>::min());
0358 
0359         /*
0360          * this will generate a new key for the hit and assign it to the hit
0361          * this ensures that there is no conflict with the hits from the 'main' event
0362          */
0363         pair.second->AddHit(newHit->get_detid(), newHit);
0364       }
0365     }
0366 
0367     {
0368       // layers
0369       const auto range = container_hit->getLayers();
0370       for (auto iter = range.first; iter != range.second; ++iter)
0371       {
0372         pair.second->AddLayer(*iter);
0373       }
0374     }
0375   }
0376 }