File indexing completed on 2025-01-18 09:11:57
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Root/RootParticleWriter.hpp"
0010
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Utilities/Helpers.hpp"
0013 #include "Acts/Utilities/VectorHelpers.hpp"
0014 #include "ActsExamples/EventData/SimParticle.hpp"
0015 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0016
0017 #include <cstdint>
0018 #include <ios>
0019 #include <ostream>
0020 #include <stdexcept>
0021
0022 #include <TFile.h>
0023 #include <TTree.h>
0024
0025 ActsExamples::RootParticleWriter::RootParticleWriter(
0026 const ActsExamples::RootParticleWriter::Config& cfg,
0027 Acts::Logging::Level lvl)
0028 : WriterT(cfg.inputParticles, "RootParticleWriter", lvl), m_cfg(cfg) {
0029
0030 if (m_cfg.filePath.empty()) {
0031 throw std::invalid_argument("Missing file path");
0032 }
0033 if (m_cfg.treeName.empty()) {
0034 throw std::invalid_argument("Missing tree name");
0035 }
0036
0037
0038 m_outputFile = TFile::Open(m_cfg.filePath.c_str(), m_cfg.fileMode.c_str());
0039 if (m_outputFile == nullptr) {
0040 throw std::ios_base::failure("Could not open '" + m_cfg.filePath + "'");
0041 }
0042 m_outputFile->cd();
0043 m_outputTree = new TTree(m_cfg.treeName.c_str(), m_cfg.treeName.c_str());
0044 if (m_outputTree == nullptr) {
0045 throw std::bad_alloc();
0046 }
0047
0048
0049 m_outputTree->Branch("event_id", &m_eventId);
0050 m_outputTree->Branch("particle_id", &m_particleId);
0051 m_outputTree->Branch("particle_type", &m_particleType);
0052 m_outputTree->Branch("process", &m_process);
0053 m_outputTree->Branch("vx", &m_vx);
0054 m_outputTree->Branch("vy", &m_vy);
0055 m_outputTree->Branch("vz", &m_vz);
0056 m_outputTree->Branch("vt", &m_vt);
0057 m_outputTree->Branch("px", &m_px);
0058 m_outputTree->Branch("py", &m_py);
0059 m_outputTree->Branch("pz", &m_pz);
0060 m_outputTree->Branch("m", &m_m);
0061 m_outputTree->Branch("q", &m_q);
0062 m_outputTree->Branch("eta", &m_eta);
0063 m_outputTree->Branch("phi", &m_phi);
0064 m_outputTree->Branch("pt", &m_pt);
0065 m_outputTree->Branch("p", &m_p);
0066 m_outputTree->Branch("vertex_primary", &m_vertexPrimary);
0067 m_outputTree->Branch("vertex_secondary", &m_vertexSecondary);
0068 m_outputTree->Branch("particle", &m_particle);
0069 m_outputTree->Branch("generation", &m_generation);
0070 m_outputTree->Branch("sub_particle", &m_subParticle);
0071
0072 m_outputTree->Branch("e_loss", &m_eLoss);
0073 m_outputTree->Branch("total_x0", &m_pathInX0);
0074 m_outputTree->Branch("total_l0", &m_pathInL0);
0075 m_outputTree->Branch("number_of_hits", &m_numberOfHits);
0076 m_outputTree->Branch("outcome", &m_outcome);
0077 }
0078
0079 ActsExamples::RootParticleWriter::~RootParticleWriter() {
0080 if (m_outputFile != nullptr) {
0081 m_outputFile->Close();
0082 }
0083 }
0084
0085 ActsExamples::ProcessCode ActsExamples::RootParticleWriter::finalize() {
0086 m_outputFile->cd();
0087 m_outputTree->Write();
0088 m_outputFile->Close();
0089
0090 ACTS_INFO("Wrote particles to tree '" << m_cfg.treeName << "' in '"
0091 << m_cfg.filePath << "'");
0092
0093 return ProcessCode::SUCCESS;
0094 }
0095
0096 ActsExamples::ProcessCode ActsExamples::RootParticleWriter::writeT(
0097 const AlgorithmContext& ctx, const SimParticleContainer& particles) {
0098
0099 std::lock_guard<std::mutex> lock(m_writeMutex);
0100
0101 m_eventId = ctx.eventNumber;
0102 for (const auto& particle : particles) {
0103 m_particleId.push_back(particle.particleId().value());
0104 m_particleType.push_back(particle.pdg());
0105 m_process.push_back(static_cast<std::uint32_t>(particle.process()));
0106
0107 m_vx.push_back(Acts::clampValue<float>(particle.fourPosition().x() /
0108 Acts::UnitConstants::mm));
0109 m_vy.push_back(Acts::clampValue<float>(particle.fourPosition().y() /
0110 Acts::UnitConstants::mm));
0111 m_vz.push_back(Acts::clampValue<float>(particle.fourPosition().z() /
0112 Acts::UnitConstants::mm));
0113 m_vt.push_back(Acts::clampValue<float>(particle.fourPosition().w() /
0114 Acts::UnitConstants::mm));
0115
0116 const auto p = particle.absoluteMomentum() / Acts::UnitConstants::GeV;
0117 m_p.push_back(Acts::clampValue<float>(p));
0118 m_px.push_back(Acts::clampValue<float>(p * particle.direction().x()));
0119 m_py.push_back(Acts::clampValue<float>(p * particle.direction().y()));
0120 m_pz.push_back(Acts::clampValue<float>(p * particle.direction().z()));
0121
0122 m_m.push_back(
0123 Acts::clampValue<float>(particle.mass() / Acts::UnitConstants::GeV));
0124 m_q.push_back(
0125 Acts::clampValue<float>(particle.charge() / Acts::UnitConstants::e));
0126
0127 m_eta.push_back(Acts::clampValue<float>(
0128 Acts::VectorHelpers::eta(particle.direction())));
0129 m_phi.push_back(Acts::clampValue<float>(
0130 Acts::VectorHelpers::phi(particle.direction())));
0131 m_pt.push_back(Acts::clampValue<float>(
0132 p * Acts::VectorHelpers::perp(particle.direction())));
0133
0134 m_vertexPrimary.push_back(particle.particleId().vertexPrimary());
0135 m_vertexSecondary.push_back(particle.particleId().vertexSecondary());
0136 m_particle.push_back(particle.particleId().particle());
0137 m_generation.push_back(particle.particleId().generation());
0138 m_subParticle.push_back(particle.particleId().subParticle());
0139
0140 m_eLoss.push_back(Acts::clampValue<float>(particle.energyLoss() /
0141 Acts::UnitConstants::GeV));
0142 m_pathInX0.push_back(
0143 Acts::clampValue<float>(particle.pathInX0() / Acts::UnitConstants::mm));
0144 m_pathInL0.push_back(
0145 Acts::clampValue<float>(particle.pathInL0() / Acts::UnitConstants::mm));
0146 m_numberOfHits.push_back(particle.numberOfHits());
0147 m_outcome.push_back(static_cast<std::uint32_t>(particle.outcome()));
0148 }
0149
0150 m_outputTree->Fill();
0151
0152 m_particleId.clear();
0153 m_particleType.clear();
0154 m_process.clear();
0155 m_vx.clear();
0156 m_vy.clear();
0157 m_vz.clear();
0158 m_vt.clear();
0159 m_p.clear();
0160 m_px.clear();
0161 m_py.clear();
0162 m_pz.clear();
0163 m_m.clear();
0164 m_q.clear();
0165 m_eta.clear();
0166 m_phi.clear();
0167 m_pt.clear();
0168 m_vertexPrimary.clear();
0169 m_vertexSecondary.clear();
0170 m_particle.clear();
0171 m_generation.clear();
0172 m_subParticle.clear();
0173 m_eLoss.clear();
0174 m_numberOfHits.clear();
0175 m_outcome.clear();
0176 m_pathInX0.clear();
0177 m_pathInL0.clear();
0178
0179 return ProcessCode::SUCCESS;
0180 }