File indexing completed on 2025-08-05 08:10:02
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Root/RootPlanarClusterWriter.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/Digitization/DigitizationCell.hpp"
0015 #include "Acts/Digitization/DigitizationModule.hpp"
0016 #include "Acts/Digitization/DigitizationSourceLink.hpp"
0017 #include "Acts/Digitization/PlanarModuleCluster.hpp"
0018 #include "Acts/Digitization/Segmentation.hpp"
0019 #include "Acts/EventData/SourceLink.hpp"
0020 #include "Acts/Geometry/GeometryIdentifier.hpp"
0021 #include "Acts/Geometry/TrackingGeometry.hpp"
0022 #include "Acts/Plugins/Identification/IdentifiedDetectorElement.hpp"
0023 #include "Acts/Surfaces/Surface.hpp"
0024 #include "Acts/Utilities/Result.hpp"
0025 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0026 #include "ActsExamples/Utilities/GroupBy.hpp"
0027 #include "ActsExamples/Utilities/Range.hpp"
0028 #include "ActsFatras/EventData/Barcode.hpp"
0029 #include "ActsFatras/EventData/Hit.hpp"
0030
0031 #include <cstdint>
0032 #include <ios>
0033 #include <ostream>
0034 #include <stdexcept>
0035 #include <utility>
0036
0037 #include <TFile.h>
0038 #include <TTree.h>
0039
0040 ActsExamples::RootPlanarClusterWriter::RootPlanarClusterWriter(
0041 const ActsExamples::RootPlanarClusterWriter::Config& config,
0042 Acts::Logging::Level level)
0043 : WriterT(config.inputClusters, "RootPlanarClusterWriter", level),
0044 m_cfg(config) {
0045
0046 if (m_cfg.inputSimHits.empty()) {
0047 throw std::invalid_argument("Missing simulated hits input collection");
0048 }
0049
0050 m_inputSimHits.initialize(m_cfg.inputSimHits);
0051
0052 if (m_cfg.treeName.empty()) {
0053 throw std::invalid_argument("Missing tree name");
0054 }
0055 if (!m_cfg.trackingGeometry) {
0056 throw std::invalid_argument("Missing tracking geometry");
0057 }
0058
0059 m_outputFile = TFile::Open(m_cfg.filePath.c_str(), m_cfg.fileMode.c_str());
0060 if (m_outputFile == nullptr) {
0061 throw std::ios_base::failure("Could not open '" + m_cfg.filePath + "'");
0062 }
0063 m_outputFile->cd();
0064 m_outputTree = new TTree(m_cfg.treeName.c_str(), m_cfg.treeName.c_str());
0065 if (m_outputTree == nullptr) {
0066 throw std::bad_alloc();
0067 }
0068
0069
0070 m_outputTree->Branch("event_nr", &m_eventNr);
0071 m_outputTree->Branch("volume_id", &m_volumeID);
0072 m_outputTree->Branch("layer_id", &m_layerID);
0073 m_outputTree->Branch("surface_id", &m_surfaceID);
0074 m_outputTree->Branch("g_x", &m_x);
0075 m_outputTree->Branch("g_y", &m_y);
0076 m_outputTree->Branch("g_z", &m_z);
0077 m_outputTree->Branch("g_t", &m_t);
0078 m_outputTree->Branch("l_x", &m_lx);
0079 m_outputTree->Branch("l_y", &m_ly);
0080 m_outputTree->Branch("cov_l_x", &m_cov_lx);
0081 m_outputTree->Branch("cov_l_y", &m_cov_ly);
0082 m_outputTree->Branch("cell_ID_x", &m_cell_IDx);
0083 m_outputTree->Branch("cell_ID_y", &m_cell_IDy);
0084 m_outputTree->Branch("cell_l_x", &m_cell_lx);
0085 m_outputTree->Branch("cell_l_y", &m_cell_ly);
0086 m_outputTree->Branch("cell_data", &m_cell_data);
0087 m_outputTree->Branch("truth_g_x", &m_t_gx);
0088 m_outputTree->Branch("truth_g_y", &m_t_gy);
0089 m_outputTree->Branch("truth_g_z", &m_t_gz);
0090 m_outputTree->Branch("truth_g_t", &m_t_gt);
0091 m_outputTree->Branch("truth_l_x", &m_t_lx);
0092 m_outputTree->Branch("truth_l_y", &m_t_ly);
0093 m_outputTree->Branch("truth_barcode", &m_t_barcode);
0094 }
0095
0096 ActsExamples::RootPlanarClusterWriter::~RootPlanarClusterWriter() {
0097 if (m_outputFile != nullptr) {
0098 m_outputFile->Close();
0099 }
0100 }
0101
0102 ActsExamples::ProcessCode ActsExamples::RootPlanarClusterWriter::finalize() {
0103
0104 m_outputFile->cd();
0105 m_outputTree->Write();
0106 m_outputFile->Close();
0107
0108 ACTS_INFO("Wrote clusters to tree '" << m_cfg.treeName << "' in '"
0109 << m_cfg.filePath << "'");
0110
0111 return ProcessCode::SUCCESS;
0112 }
0113
0114 ActsExamples::ProcessCode ActsExamples::RootPlanarClusterWriter::writeT(
0115 const AlgorithmContext& ctx,
0116 const ActsExamples::GeometryIdMultimap<Acts::PlanarModuleCluster>&
0117 clusters) {
0118
0119 const auto& simHits = m_inputSimHits(ctx);
0120
0121
0122 std::lock_guard<std::mutex> lock(m_writeMutex);
0123
0124 m_eventNr = ctx.eventNumber;
0125
0126
0127 for (auto [moduleGeoId, moduleClusters] : groupByModule(clusters)) {
0128 const Acts::Surface* surfacePtr =
0129 m_cfg.trackingGeometry->findSurface(moduleGeoId);
0130 if (surfacePtr == nullptr) {
0131 ACTS_ERROR("Could not find surface for " << moduleGeoId);
0132 return ProcessCode::ABORT;
0133 }
0134 const Acts::Surface& surface = *surfacePtr;
0135
0136
0137 m_volumeID = moduleGeoId.volume();
0138 m_layerID = moduleGeoId.layer();
0139 m_surfaceID = moduleGeoId.sensitive();
0140
0141 for (const auto& entry : moduleClusters) {
0142 const Acts::PlanarModuleCluster& cluster = entry.second;
0143
0144 auto parameters = cluster.parameters();
0145 Acts::Vector2 local(parameters[Acts::BoundIndices::eBoundLoc0],
0146 parameters[Acts::BoundIndices::eBoundLoc1]);
0147
0148
0149 Acts::Vector3 mom(1, 1, 1);
0150
0151 Acts::Vector3 pos = surface.localToGlobal(ctx.geoContext, local, mom);
0152 m_x = pos.x() / Acts::UnitConstants::mm;
0153 m_y = pos.y() / Acts::UnitConstants::mm;
0154 m_z = pos.z() / Acts::UnitConstants::mm;
0155 m_t = parameters[2] / Acts::UnitConstants::mm;
0156 m_lx = local.x();
0157 m_ly = local.y();
0158 m_cov_lx = 0.;
0159 m_cov_ly = 0.;
0160
0161 const auto& cells = cluster.digitizationCells();
0162 auto detectorElement =
0163 dynamic_cast<const Acts::IdentifiedDetectorElement*>(
0164 surface.associatedDetectorElement());
0165 for (auto& cell : cells) {
0166
0167 m_cell_IDx.push_back(cell.channel0);
0168 m_cell_IDy.push_back(cell.channel1);
0169 m_cell_data.push_back(cell.data);
0170
0171 if ((detectorElement != nullptr) &&
0172 detectorElement->digitizationModule()) {
0173 auto digitationModule = detectorElement->digitizationModule();
0174 const Acts::Segmentation& segmentation =
0175 digitationModule->segmentation();
0176
0177 auto cellLocalPosition = segmentation.cellPosition(cell);
0178 m_cell_lx.push_back(cellLocalPosition.x());
0179 m_cell_ly.push_back(cellLocalPosition.y());
0180 }
0181 }
0182
0183
0184 const auto& sl = cluster.sourceLink().get<Acts::DigitizationSourceLink>();
0185 for (auto idx : sl.indices()) {
0186 auto it = simHits.nth(idx);
0187 if (it == simHits.end()) {
0188 ACTS_FATAL("Simulation hit with index " << idx << " does not exist");
0189 return ProcessCode::ABORT;
0190 }
0191 const auto& simHit = *it;
0192
0193
0194 Acts::Vector2 lPosition{0., 0.};
0195 auto lpResult = surface.globalToLocal(ctx.geoContext, simHit.position(),
0196 simHit.direction());
0197 if (!lpResult.ok()) {
0198 ACTS_FATAL("Global to local transformation did not succeed.");
0199 return ProcessCode::ABORT;
0200 }
0201 lPosition = lpResult.value();
0202
0203 m_t_gx.push_back(simHit.position().x());
0204 m_t_gy.push_back(simHit.position().y());
0205 m_t_gz.push_back(simHit.position().z());
0206 m_t_gt.push_back(simHit.time());
0207 m_t_lx.push_back(lPosition.x());
0208 m_t_ly.push_back(lPosition.y());
0209 m_t_barcode.push_back(simHit.particleId().value());
0210 }
0211
0212 m_outputTree->Fill();
0213
0214 m_cell_IDx.clear();
0215 m_cell_IDy.clear();
0216 m_cell_lx.clear();
0217 m_cell_ly.clear();
0218 m_cell_data.clear();
0219 m_t_gx.clear();
0220 m_t_gy.clear();
0221 m_t_gz.clear();
0222 m_t_gt.clear();
0223 m_t_lx.clear();
0224 m_t_ly.clear();
0225 m_t_barcode.clear();
0226 }
0227 }
0228 return ActsExamples::ProcessCode::SUCCESS;
0229 }