Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:24:00

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsExamples/Io/Root/RootParticleReader.hpp"
0010 
0011 #include "Acts/Definitions/PdgParticle.hpp"
0012 #include "Acts/Utilities/Logger.hpp"
0013 #include "ActsExamples/EventData/SimParticle.hpp"
0014 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0015 #include "ActsExamples/Io/Root/RootUtility.hpp"
0016 #include "ActsFatras/EventData/ParticleOutcome.hpp"
0017 #include "ActsFatras/EventData/ProcessType.hpp"
0018 
0019 #include <iostream>
0020 #include <stdexcept>
0021 
0022 #include <TChain.h>
0023 
0024 namespace ActsExamples {
0025 
0026 RootParticleReader::RootParticleReader(const RootParticleReader::Config& config,
0027                                        Acts::Logging::Level level)
0028     : IReader(),
0029       m_cfg(config),
0030       m_logger(Acts::getDefaultLogger(name(), level)) {
0031   m_inputChain = std::make_unique<TChain>(m_cfg.treeName.c_str());
0032 
0033   if (m_cfg.filePath.empty()) {
0034     throw std::invalid_argument("Missing input filename");
0035   }
0036   if (m_cfg.treeName.empty()) {
0037     throw std::invalid_argument("Missing tree name");
0038   }
0039 
0040   m_outputParticles.initialize(m_cfg.outputParticles);
0041 
0042   // Set the branches
0043   m_inputChain->SetBranchAddress("event_id", &m_eventId);
0044   m_inputChain->SetBranchAddress("particle_hash", &m_particleHash.get());
0045   m_inputChain->SetBranchAddress("particle_type", &m_particleType.get());
0046   m_inputChain->SetBranchAddress("process", &m_process.get());
0047   m_inputChain->SetBranchAddress("vx", &m_vx.get());
0048   m_inputChain->SetBranchAddress("vy", &m_vy.get());
0049   m_inputChain->SetBranchAddress("vz", &m_vz.get());
0050   m_inputChain->SetBranchAddress("vt", &m_vt.get());
0051   m_inputChain->SetBranchAddress("p", &m_p.get());
0052   m_inputChain->SetBranchAddress("px", &m_px.get());
0053   m_inputChain->SetBranchAddress("py", &m_py.get());
0054   m_inputChain->SetBranchAddress("pz", &m_pz.get());
0055   m_inputChain->SetBranchAddress("m", &m_m.get());
0056   m_inputChain->SetBranchAddress("q", &m_q.get());
0057   m_inputChain->SetBranchAddress("eta", &m_eta.get());
0058   m_inputChain->SetBranchAddress("phi", &m_phi.get());
0059   m_inputChain->SetBranchAddress("pt", &m_pt.get());
0060   m_inputChain->SetBranchAddress("vertex_primary", &m_vertexPrimary.get());
0061   m_inputChain->SetBranchAddress("vertex_secondary", &m_vertexSecondary.get());
0062   m_inputChain->SetBranchAddress("particle", &m_particle.get());
0063   m_inputChain->SetBranchAddress("generation", &m_generation.get());
0064   m_inputChain->SetBranchAddress("sub_particle", &m_subParticle.get());
0065 
0066   m_inputChain->SetBranchAddress("e_loss", &m_eLoss.get());
0067   m_inputChain->SetBranchAddress("total_x0", &m_pathInX0.get());
0068   m_inputChain->SetBranchAddress("total_l0", &m_pathInL0.get());
0069   m_inputChain->SetBranchAddress("number_of_hits", &m_numberOfHits.get());
0070   m_inputChain->SetBranchAddress("outcome", &m_outcome.get());
0071 
0072   auto path = m_cfg.filePath;
0073 
0074   // add file to the input chain
0075   m_inputChain->Add(path.c_str());
0076   ACTS_DEBUG("Adding File " << path << " to tree '" << m_cfg.treeName << "'.");
0077 
0078   m_events = m_inputChain->GetEntries();
0079   ACTS_DEBUG("The full chain has " << m_events << " entries.");
0080 
0081   // Sort the entry numbers of the events
0082   {
0083     // necessary to guarantee that m_inputChain->GetV1() is valid for the
0084     // entire range
0085     m_inputChain->SetEstimate(m_events + 1);
0086 
0087     m_entryNumbers.resize(m_events);
0088     m_inputChain->Draw("event_id", "", "goff");
0089     RootUtility::stableSort(m_inputChain->GetEntries(), m_inputChain->GetV1(),
0090                             m_entryNumbers.data(), false);
0091   }
0092 }
0093 
0094 std::pair<std::size_t, std::size_t> RootParticleReader::availableEvents()
0095     const {
0096   return {0u, m_events};
0097 }
0098 
0099 ProcessCode RootParticleReader::read(const AlgorithmContext& context) {
0100   ACTS_DEBUG("Trying to read recorded particles.");
0101 
0102   if (m_inputChain == nullptr || context.eventNumber >= m_events) {
0103     return ProcessCode::SUCCESS;
0104   }
0105 
0106   // lock the mutex
0107   std::lock_guard<std::mutex> lock(m_read_mutex);
0108   // now read
0109 
0110   // The particle collection to be filled
0111   SimParticleContainer particles;
0112 
0113   // Read the correct entry
0114   auto entry = m_entryNumbers.at(context.eventNumber);
0115   m_inputChain->GetEntry(entry);
0116   ACTS_DEBUG("Reading event: " << context.eventNumber
0117                                << " stored as entry: " << entry);
0118 
0119   unsigned int nParticles = m_particleType->size();
0120 
0121   for (unsigned int i = 0; i < nParticles; i++) {
0122     SimParticle p;
0123 
0124     p.setProcess(static_cast<ActsFatras::ProcessType>((*m_process).at(i)));
0125     p.setPdg(static_cast<Acts::PdgParticle>((*m_particleType).at(i)));
0126     p.setCharge((*m_q).at(i) * Acts::UnitConstants::e);
0127     p.setMass((*m_m).at(i) * Acts::UnitConstants::GeV);
0128     p.setParticleId(SimBarcode()
0129                         .withVertexPrimary((*m_vertexPrimary).at(i))
0130                         .withVertexSecondary((*m_vertexSecondary).at(i))
0131                         .withParticle((*m_particle).at(i))
0132                         .withGeneration((*m_generation).at(i))
0133                         .withSubParticle((*m_subParticle).at(i)));
0134 
0135     SimParticleState& initialState = p.initialState();
0136 
0137     initialState.setPosition4((*m_vx).at(i) * Acts::UnitConstants::mm,
0138                               (*m_vy).at(i) * Acts::UnitConstants::mm,
0139                               (*m_vz).at(i) * Acts::UnitConstants::mm,
0140                               (*m_vt).at(i) * Acts::UnitConstants::mm);
0141     // NOTE: direction is normalized inside `setDirection`
0142     initialState.setDirection((*m_px).at(i), (*m_py).at(i), (*m_pz).at(i));
0143     initialState.setAbsoluteMomentum((*m_p).at(i) * Acts::UnitConstants::GeV);
0144 
0145     SimParticleState& finalState = p.finalState();
0146 
0147     // TODO eloss cannot be read since we need the final momentum
0148     finalState.setMaterialPassed((*m_pathInX0).at(i) * Acts::UnitConstants::mm,
0149                                  (*m_pathInL0).at(i) * Acts::UnitConstants::mm);
0150     finalState.setNumberOfHits((*m_numberOfHits).at(i));
0151     finalState.setOutcome(
0152         static_cast<ActsFatras::ParticleOutcome>((*m_outcome).at(i)));
0153 
0154     particles.insert(p);
0155   }
0156 
0157   ACTS_DEBUG("Read " << particles.size() << " particles for event "
0158                      << context.eventNumber);
0159 
0160   // Write the collections to the EventStore
0161   m_outputParticles(context, std::move(particles));
0162 
0163   // Return success flag
0164   return ProcessCode::SUCCESS;
0165 }
0166 
0167 }  // namespace ActsExamples