File indexing completed on 2025-12-16 09:24:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Root/RootTrackStatesWriter.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/EventData/MultiTrajectory.hpp"
0015 #include "Acts/EventData/TransformationHelpers.hpp"
0016 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/Utilities/Helpers.hpp"
0020 #include "Acts/Utilities/TrackHelpers.hpp"
0021 #include "Acts/Utilities/detail/periodic.hpp"
0022 #include "ActsExamples/EventData/AverageSimHits.hpp"
0023 #include "ActsExamples/EventData/IndexSourceLink.hpp"
0024 #include "ActsExamples/EventData/Track.hpp"
0025 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0026 #include "ActsExamples/Utilities/Range.hpp"
0027 #include "ActsFatras/EventData/Barcode.hpp"
0028
0029 #include <cmath>
0030 #include <ios>
0031 #include <limits>
0032 #include <numbers>
0033 #include <optional>
0034 #include <ostream>
0035 #include <stdexcept>
0036 #include <utility>
0037
0038 #include <TFile.h>
0039 #include <TTree.h>
0040
0041 namespace ActsExamples {
0042
0043 using Acts::VectorHelpers::eta;
0044 using Acts::VectorHelpers::perp;
0045 using Acts::VectorHelpers::phi;
0046 using Acts::VectorHelpers::theta;
0047
0048 RootTrackStatesWriter::RootTrackStatesWriter(
0049 const RootTrackStatesWriter::Config& config, Acts::Logging::Level level)
0050 : WriterT(config.inputTracks, "RootTrackStatesWriter", level),
0051 m_cfg(config) {
0052
0053 if (m_cfg.inputParticles.empty()) {
0054 throw std::invalid_argument("Missing particles input collection");
0055 }
0056 if (m_cfg.inputTrackParticleMatching.empty()) {
0057 throw std::invalid_argument("Missing input track particles matching");
0058 }
0059 if (m_cfg.inputSimHits.empty()) {
0060 throw std::invalid_argument("Missing simulated hits input collection");
0061 }
0062 if (m_cfg.inputMeasurementSimHitsMap.empty()) {
0063 throw std::invalid_argument(
0064 "Missing hit-simulated-hits map input collection");
0065 }
0066 if (m_cfg.filePath.empty()) {
0067 throw std::invalid_argument("Missing output filename");
0068 }
0069 if (m_cfg.treeName.empty()) {
0070 throw std::invalid_argument("Missing tree name");
0071 }
0072
0073 m_inputParticles.initialize(m_cfg.inputParticles);
0074 m_inputTrackParticleMatching.initialize(m_cfg.inputTrackParticleMatching);
0075 m_inputSimHits.initialize(m_cfg.inputSimHits);
0076 m_inputMeasurementSimHitsMap.initialize(m_cfg.inputMeasurementSimHitsMap);
0077
0078
0079 auto path = m_cfg.filePath;
0080 m_outputFile = TFile::Open(path.c_str(), m_cfg.fileMode.c_str());
0081 if (m_outputFile == nullptr) {
0082 throw std::ios_base::failure("Could not open '" + path + "'");
0083 }
0084 m_outputFile->cd();
0085 m_outputTree = new TTree(m_cfg.treeName.c_str(), m_cfg.treeName.c_str());
0086 if (m_outputTree == nullptr) {
0087 throw std::bad_alloc();
0088 }
0089
0090
0091 m_outputTree->Branch("event_nr", &m_eventNr);
0092 m_outputTree->Branch("track_nr", &m_trackNr);
0093
0094 m_outputTree->Branch("nStates", &m_nStates);
0095 m_outputTree->Branch("nMeasurements", &m_nMeasurements);
0096
0097 m_outputTree->Branch("volume_id", &m_volumeID);
0098 m_outputTree->Branch("layer_id", &m_layerID);
0099 m_outputTree->Branch("module_id", &m_moduleID);
0100
0101 m_outputTree->Branch("stateType", &m_stateType);
0102
0103 m_outputTree->Branch("chi2", &m_chi2);
0104
0105 m_outputTree->Branch("pathLength", &m_pathLength);
0106
0107 m_outputTree->Branch("t_x", &m_t_x);
0108 m_outputTree->Branch("t_y", &m_t_y);
0109 m_outputTree->Branch("t_z", &m_t_z);
0110 m_outputTree->Branch("t_r", &m_t_r);
0111 m_outputTree->Branch("t_dx", &m_t_dx);
0112 m_outputTree->Branch("t_dy", &m_t_dy);
0113 m_outputTree->Branch("t_dz", &m_t_dz);
0114 m_outputTree->Branch("t_eLOC0", &m_t_eLOC0);
0115 m_outputTree->Branch("t_eLOC1", &m_t_eLOC1);
0116 m_outputTree->Branch("t_ePHI", &m_t_ePHI);
0117 m_outputTree->Branch("t_eTHETA", &m_t_eTHETA);
0118 m_outputTree->Branch("t_eQOP", &m_t_eQOP);
0119 m_outputTree->Branch("t_eT", &m_t_eT);
0120 m_outputTree->Branch("particle_ids_vertex_primary", &m_particleVertexPrimary);
0121 m_outputTree->Branch("particle_ids_vertex_secondary",
0122 &m_particleVertexSecondary);
0123 m_outputTree->Branch("particle_ids_particle", &m_particleParticle);
0124 m_outputTree->Branch("particle_ids_generation", &m_particleGeneration);
0125 m_outputTree->Branch("particle_ids_sub_particle", &m_particleSubParticle);
0126
0127 m_outputTree->Branch("dim_hit", &m_dim_hit);
0128 m_outputTree->Branch("l_x_hit", &m_lx_hit);
0129 m_outputTree->Branch("l_y_hit", &m_ly_hit);
0130 m_outputTree->Branch("g_x_hit", &m_x_hit);
0131 m_outputTree->Branch("g_y_hit", &m_y_hit);
0132 m_outputTree->Branch("g_z_hit", &m_z_hit);
0133 m_outputTree->Branch("res_x_hit", &m_res_x_hit);
0134 m_outputTree->Branch("res_y_hit", &m_res_y_hit);
0135 m_outputTree->Branch("err_x_hit", &m_err_x_hit);
0136 m_outputTree->Branch("err_y_hit", &m_err_y_hit);
0137 m_outputTree->Branch("pull_x_hit", &m_pull_x_hit);
0138 m_outputTree->Branch("pull_y_hit", &m_pull_y_hit);
0139
0140 m_outputTree->Branch("nPredicted", &m_nParams[ePredicted]);
0141 m_outputTree->Branch("predicted", &m_hasParams[ePredicted]);
0142 m_outputTree->Branch("eLOC0_prt", &m_eLOC0[ePredicted]);
0143 m_outputTree->Branch("eLOC1_prt", &m_eLOC1[ePredicted]);
0144 m_outputTree->Branch("ePHI_prt", &m_ePHI[ePredicted]);
0145 m_outputTree->Branch("eTHETA_prt", &m_eTHETA[ePredicted]);
0146 m_outputTree->Branch("eQOP_prt", &m_eQOP[ePredicted]);
0147 m_outputTree->Branch("eT_prt", &m_eT[ePredicted]);
0148 m_outputTree->Branch("res_eLOC0_prt", &m_res_eLOC0[ePredicted]);
0149 m_outputTree->Branch("res_eLOC1_prt", &m_res_eLOC1[ePredicted]);
0150 m_outputTree->Branch("res_ePHI_prt", &m_res_ePHI[ePredicted]);
0151 m_outputTree->Branch("res_eTHETA_prt", &m_res_eTHETA[ePredicted]);
0152 m_outputTree->Branch("res_eQOP_prt", &m_res_eQOP[ePredicted]);
0153 m_outputTree->Branch("res_eT_prt", &m_res_eT[ePredicted]);
0154 m_outputTree->Branch("err_eLOC0_prt", &m_err_eLOC0[ePredicted]);
0155 m_outputTree->Branch("err_eLOC1_prt", &m_err_eLOC1[ePredicted]);
0156 m_outputTree->Branch("err_ePHI_prt", &m_err_ePHI[ePredicted]);
0157 m_outputTree->Branch("err_eTHETA_prt", &m_err_eTHETA[ePredicted]);
0158 m_outputTree->Branch("err_eQOP_prt", &m_err_eQOP[ePredicted]);
0159 m_outputTree->Branch("err_eT_prt", &m_err_eT[ePredicted]);
0160 m_outputTree->Branch("pull_eLOC0_prt", &m_pull_eLOC0[ePredicted]);
0161 m_outputTree->Branch("pull_eLOC1_prt", &m_pull_eLOC1[ePredicted]);
0162 m_outputTree->Branch("pull_ePHI_prt", &m_pull_ePHI[ePredicted]);
0163 m_outputTree->Branch("pull_eTHETA_prt", &m_pull_eTHETA[ePredicted]);
0164 m_outputTree->Branch("pull_eQOP_prt", &m_pull_eQOP[ePredicted]);
0165 m_outputTree->Branch("pull_eT_prt", &m_pull_eT[ePredicted]);
0166 m_outputTree->Branch("g_x_prt", &m_x[ePredicted]);
0167 m_outputTree->Branch("g_y_prt", &m_y[ePredicted]);
0168 m_outputTree->Branch("g_z_prt", &m_z[ePredicted]);
0169 m_outputTree->Branch("px_prt", &m_px[ePredicted]);
0170 m_outputTree->Branch("py_prt", &m_py[ePredicted]);
0171 m_outputTree->Branch("pz_prt", &m_pz[ePredicted]);
0172 m_outputTree->Branch("eta_prt", &m_eta[ePredicted]);
0173 m_outputTree->Branch("pT_prt", &m_pT[ePredicted]);
0174
0175 m_outputTree->Branch("nFiltered", &m_nParams[eFiltered]);
0176 m_outputTree->Branch("filtered", &m_hasParams[eFiltered]);
0177 m_outputTree->Branch("eLOC0_flt", &m_eLOC0[eFiltered]);
0178 m_outputTree->Branch("eLOC1_flt", &m_eLOC1[eFiltered]);
0179 m_outputTree->Branch("ePHI_flt", &m_ePHI[eFiltered]);
0180 m_outputTree->Branch("eTHETA_flt", &m_eTHETA[eFiltered]);
0181 m_outputTree->Branch("eQOP_flt", &m_eQOP[eFiltered]);
0182 m_outputTree->Branch("eT_flt", &m_eT[eFiltered]);
0183 m_outputTree->Branch("res_eLOC0_flt", &m_res_eLOC0[eFiltered]);
0184 m_outputTree->Branch("res_eLOC1_flt", &m_res_eLOC1[eFiltered]);
0185 m_outputTree->Branch("res_ePHI_flt", &m_res_ePHI[eFiltered]);
0186 m_outputTree->Branch("res_eTHETA_flt", &m_res_eTHETA[eFiltered]);
0187 m_outputTree->Branch("res_eQOP_flt", &m_res_eQOP[eFiltered]);
0188 m_outputTree->Branch("res_eT_flt", &m_res_eT[eFiltered]);
0189 m_outputTree->Branch("err_eLOC0_flt", &m_err_eLOC0[eFiltered]);
0190 m_outputTree->Branch("err_eLOC1_flt", &m_err_eLOC1[eFiltered]);
0191 m_outputTree->Branch("err_ePHI_flt", &m_err_ePHI[eFiltered]);
0192 m_outputTree->Branch("err_eTHETA_flt", &m_err_eTHETA[eFiltered]);
0193 m_outputTree->Branch("err_eQOP_flt", &m_err_eQOP[eFiltered]);
0194 m_outputTree->Branch("err_eT_flt", &m_err_eT[eFiltered]);
0195 m_outputTree->Branch("pull_eLOC0_flt", &m_pull_eLOC0[eFiltered]);
0196 m_outputTree->Branch("pull_eLOC1_flt", &m_pull_eLOC1[eFiltered]);
0197 m_outputTree->Branch("pull_ePHI_flt", &m_pull_ePHI[eFiltered]);
0198 m_outputTree->Branch("pull_eTHETA_flt", &m_pull_eTHETA[eFiltered]);
0199 m_outputTree->Branch("pull_eQOP_flt", &m_pull_eQOP[eFiltered]);
0200 m_outputTree->Branch("pull_eT_flt", &m_pull_eT[eFiltered]);
0201 m_outputTree->Branch("g_x_flt", &m_x[eFiltered]);
0202 m_outputTree->Branch("g_y_flt", &m_y[eFiltered]);
0203 m_outputTree->Branch("g_z_flt", &m_z[eFiltered]);
0204 m_outputTree->Branch("px_flt", &m_px[eFiltered]);
0205 m_outputTree->Branch("py_flt", &m_py[eFiltered]);
0206 m_outputTree->Branch("pz_flt", &m_pz[eFiltered]);
0207 m_outputTree->Branch("eta_flt", &m_eta[eFiltered]);
0208 m_outputTree->Branch("pT_flt", &m_pT[eFiltered]);
0209
0210 m_outputTree->Branch("nSmoothed", &m_nParams[eSmoothed]);
0211 m_outputTree->Branch("smoothed", &m_hasParams[eSmoothed]);
0212 m_outputTree->Branch("eLOC0_smt", &m_eLOC0[eSmoothed]);
0213 m_outputTree->Branch("eLOC1_smt", &m_eLOC1[eSmoothed]);
0214 m_outputTree->Branch("ePHI_smt", &m_ePHI[eSmoothed]);
0215 m_outputTree->Branch("eTHETA_smt", &m_eTHETA[eSmoothed]);
0216 m_outputTree->Branch("eQOP_smt", &m_eQOP[eSmoothed]);
0217 m_outputTree->Branch("eT_smt", &m_eT[eSmoothed]);
0218 m_outputTree->Branch("res_eLOC0_smt", &m_res_eLOC0[eSmoothed]);
0219 m_outputTree->Branch("res_eLOC1_smt", &m_res_eLOC1[eSmoothed]);
0220 m_outputTree->Branch("res_ePHI_smt", &m_res_ePHI[eSmoothed]);
0221 m_outputTree->Branch("res_eTHETA_smt", &m_res_eTHETA[eSmoothed]);
0222 m_outputTree->Branch("res_eQOP_smt", &m_res_eQOP[eSmoothed]);
0223 m_outputTree->Branch("res_eT_smt", &m_res_eT[eSmoothed]);
0224 m_outputTree->Branch("err_eLOC0_smt", &m_err_eLOC0[eSmoothed]);
0225 m_outputTree->Branch("err_eLOC1_smt", &m_err_eLOC1[eSmoothed]);
0226 m_outputTree->Branch("err_ePHI_smt", &m_err_ePHI[eSmoothed]);
0227 m_outputTree->Branch("err_eTHETA_smt", &m_err_eTHETA[eSmoothed]);
0228 m_outputTree->Branch("err_eQOP_smt", &m_err_eQOP[eSmoothed]);
0229 m_outputTree->Branch("err_eT_smt", &m_err_eT[eSmoothed]);
0230 m_outputTree->Branch("pull_eLOC0_smt", &m_pull_eLOC0[eSmoothed]);
0231 m_outputTree->Branch("pull_eLOC1_smt", &m_pull_eLOC1[eSmoothed]);
0232 m_outputTree->Branch("pull_ePHI_smt", &m_pull_ePHI[eSmoothed]);
0233 m_outputTree->Branch("pull_eTHETA_smt", &m_pull_eTHETA[eSmoothed]);
0234 m_outputTree->Branch("pull_eQOP_smt", &m_pull_eQOP[eSmoothed]);
0235 m_outputTree->Branch("pull_eT_smt", &m_pull_eT[eSmoothed]);
0236 m_outputTree->Branch("g_x_smt", &m_x[eSmoothed]);
0237 m_outputTree->Branch("g_y_smt", &m_y[eSmoothed]);
0238 m_outputTree->Branch("g_z_smt", &m_z[eSmoothed]);
0239 m_outputTree->Branch("px_smt", &m_px[eSmoothed]);
0240 m_outputTree->Branch("py_smt", &m_py[eSmoothed]);
0241 m_outputTree->Branch("pz_smt", &m_pz[eSmoothed]);
0242 m_outputTree->Branch("eta_smt", &m_eta[eSmoothed]);
0243 m_outputTree->Branch("pT_smt", &m_pT[eSmoothed]);
0244
0245 m_outputTree->Branch("nUnbiased", &m_nParams[eUnbiased]);
0246 m_outputTree->Branch("unbiased", &m_hasParams[eUnbiased]);
0247 m_outputTree->Branch("eLOC0_ubs", &m_eLOC0[eUnbiased]);
0248 m_outputTree->Branch("eLOC1_ubs", &m_eLOC1[eUnbiased]);
0249 m_outputTree->Branch("ePHI_ubs", &m_ePHI[eUnbiased]);
0250 m_outputTree->Branch("eTHETA_ubs", &m_eTHETA[eUnbiased]);
0251 m_outputTree->Branch("eQOP_ubs", &m_eQOP[eUnbiased]);
0252 m_outputTree->Branch("eT_ubs", &m_eT[eUnbiased]);
0253 m_outputTree->Branch("res_eLOC0_ubs", &m_res_eLOC0[eUnbiased]);
0254 m_outputTree->Branch("res_eLOC1_ubs", &m_res_eLOC1[eUnbiased]);
0255 m_outputTree->Branch("res_ePHI_ubs", &m_res_ePHI[eUnbiased]);
0256 m_outputTree->Branch("res_eTHETA_ubs", &m_res_eTHETA[eUnbiased]);
0257 m_outputTree->Branch("res_eQOP_ubs", &m_res_eQOP[eUnbiased]);
0258 m_outputTree->Branch("res_eT_ubs", &m_res_eT[eUnbiased]);
0259 m_outputTree->Branch("err_eLOC0_ubs", &m_err_eLOC0[eUnbiased]);
0260 m_outputTree->Branch("err_eLOC1_ubs", &m_err_eLOC1[eUnbiased]);
0261 m_outputTree->Branch("err_ePHI_ubs", &m_err_ePHI[eUnbiased]);
0262 m_outputTree->Branch("err_eTHETA_ubs", &m_err_eTHETA[eUnbiased]);
0263 m_outputTree->Branch("err_eQOP_ubs", &m_err_eQOP[eUnbiased]);
0264 m_outputTree->Branch("err_eT_ubs", &m_err_eT[eUnbiased]);
0265 m_outputTree->Branch("pull_eLOC0_ubs", &m_pull_eLOC0[eUnbiased]);
0266 m_outputTree->Branch("pull_eLOC1_ubs", &m_pull_eLOC1[eUnbiased]);
0267 m_outputTree->Branch("pull_ePHI_ubs", &m_pull_ePHI[eUnbiased]);
0268 m_outputTree->Branch("pull_eTHETA_ubs", &m_pull_eTHETA[eUnbiased]);
0269 m_outputTree->Branch("pull_eQOP_ubs", &m_pull_eQOP[eUnbiased]);
0270 m_outputTree->Branch("pull_eT_ubs", &m_pull_eT[eUnbiased]);
0271 m_outputTree->Branch("g_x_ubs", &m_x[eUnbiased]);
0272 m_outputTree->Branch("g_y_ubs", &m_y[eUnbiased]);
0273 m_outputTree->Branch("g_z_ubs", &m_z[eUnbiased]);
0274 m_outputTree->Branch("px_ubs", &m_px[eUnbiased]);
0275 m_outputTree->Branch("py_ubs", &m_py[eUnbiased]);
0276 m_outputTree->Branch("pz_ubs", &m_pz[eUnbiased]);
0277 m_outputTree->Branch("eta_ubs", &m_eta[eUnbiased]);
0278 m_outputTree->Branch("pT_ubs", &m_pT[eUnbiased]);
0279 }
0280
0281 RootTrackStatesWriter::~RootTrackStatesWriter() {
0282 m_outputFile->Close();
0283 }
0284
0285 ProcessCode RootTrackStatesWriter::finalize() {
0286 m_outputFile->cd();
0287 m_outputTree->Write();
0288 m_outputFile->Close();
0289 return ProcessCode::SUCCESS;
0290 }
0291
0292 RootTrackStatesWriter::StateType RootTrackStatesWriter::getStateType(
0293 ConstTrackStateProxy state) {
0294 if (state.typeFlags().test(Acts::OutlierFlag)) {
0295 return StateType::eOutlier;
0296 }
0297 if (state.typeFlags().test(Acts::MeasurementFlag)) {
0298 return StateType::eMeasurement;
0299 }
0300 if (state.typeFlags().test(Acts::HoleFlag)) {
0301 return StateType::eHole;
0302 }
0303 if (state.typeFlags().test(Acts::MaterialFlag)) {
0304 return StateType::eMaterial;
0305 }
0306 return StateType::eUnknown;
0307 }
0308
0309 ProcessCode RootTrackStatesWriter::writeT(const AlgorithmContext& ctx,
0310 const ConstTrackContainer& tracks) {
0311 constexpr float nan = std::numeric_limits<float>::quiet_NaN();
0312
0313 const Acts::GeometryContext& gctx = ctx.geoContext;
0314
0315 const auto& particles = m_inputParticles(ctx);
0316 const auto& trackParticleMatching = m_inputTrackParticleMatching(ctx);
0317 const auto& simHits = m_inputSimHits(ctx);
0318 const auto& hitSimHitsMap = m_inputMeasurementSimHitsMap(ctx);
0319
0320
0321 std::lock_guard<std::mutex> lock(m_writeMutex);
0322
0323
0324 m_eventNr = ctx.eventNumber;
0325
0326 for (const auto& track : tracks) {
0327 m_trackNr = track.index();
0328
0329
0330 m_nMeasurements = track.nMeasurements();
0331 m_nStates = track.nTrackStates();
0332
0333
0334 int truthQ = 1;
0335 auto match = trackParticleMatching.find(track.index());
0336 if (match != trackParticleMatching.end() &&
0337 match->second.particle.has_value()) {
0338
0339 auto barcode = match->second.particle.value();
0340
0341 auto ip = particles.find(barcode);
0342 if (ip != particles.end()) {
0343 const auto& particle = *ip;
0344 ACTS_VERBOSE("Find the truth particle with barcode " << barcode << "="
0345 << barcode.hash());
0346
0347 truthQ = static_cast<int>(particle.charge());
0348 } else {
0349 ACTS_DEBUG("Truth particle with barcode "
0350 << barcode << "=" << barcode.hash() << " not found!");
0351 }
0352 }
0353
0354
0355 m_nParams = {0, 0, 0, 0};
0356
0357 std::vector<std::uint32_t> particleVertexPrimary;
0358 std::vector<std::uint32_t> particleVertexSecondary;
0359 std::vector<std::uint32_t> particleParticle;
0360 std::vector<std::uint32_t> particleGeneration;
0361 std::vector<std::uint32_t> particleSubParticle;
0362
0363 for (const auto& state : track.trackStatesReversed()) {
0364 const Acts::Surface& surface = state.referenceSurface();
0365
0366
0367 const Acts::GeometryIdentifier geoID = surface.geometryId();
0368 m_volumeID.push_back(geoID.volume());
0369 m_layerID.push_back(geoID.layer());
0370 m_moduleID.push_back(geoID.sensitive());
0371
0372 m_stateType.push_back(Acts::toUnderlying(getStateType(state)));
0373
0374
0375 m_pathLength.push_back(state.pathLength());
0376
0377
0378 m_chi2.push_back(state.chi2());
0379
0380
0381 Acts::BoundVector truthParams;
0382
0383 particleVertexPrimary.clear();
0384 particleVertexSecondary.clear();
0385 particleParticle.clear();
0386 particleGeneration.clear();
0387 particleSubParticle.clear();
0388
0389 if (!state.hasUncalibratedSourceLink()) {
0390 m_t_x.push_back(nan);
0391 m_t_y.push_back(nan);
0392 m_t_z.push_back(nan);
0393 m_t_r.push_back(nan);
0394 m_t_dx.push_back(nan);
0395 m_t_dy.push_back(nan);
0396 m_t_dz.push_back(nan);
0397 m_t_eLOC0.push_back(nan);
0398 m_t_eLOC1.push_back(nan);
0399 m_t_ePHI.push_back(nan);
0400 m_t_eTHETA.push_back(nan);
0401 m_t_eQOP.push_back(nan);
0402 m_t_eT.push_back(nan);
0403
0404 m_lx_hit.push_back(nan);
0405 m_ly_hit.push_back(nan);
0406 m_x_hit.push_back(nan);
0407 m_y_hit.push_back(nan);
0408 m_z_hit.push_back(nan);
0409 } else {
0410
0411
0412 const auto sl =
0413 state.getUncalibratedSourceLink().template get<IndexSourceLink>();
0414
0415 const auto hitIdx = sl.index();
0416 const auto indices = makeRange(hitSimHitsMap.equal_range(hitIdx));
0417 const auto [truthLocal, truthPos4, truthUnitDir] =
0418 averageSimHits(ctx.geoContext, surface, simHits, indices, logger());
0419
0420
0421
0422 if (!indices.empty()) {
0423
0424
0425 const auto simHitIdx0 = indices.begin()->second;
0426 const auto& simHit0 = *simHits.nth(simHitIdx0);
0427 const double p =
0428 simHit0.momentum4Before().template segment<3>(Acts::eMom0).norm();
0429 truthParams[Acts::eBoundQOverP] = truthQ / p;
0430
0431
0432 for (auto const& [key, simHitIdx] : indices) {
0433 const auto& simHit = *simHits.nth(simHitIdx);
0434 const auto barcode = simHit.particleId();
0435 particleVertexPrimary.push_back(barcode.vertexPrimary());
0436 particleVertexSecondary.push_back(barcode.vertexSecondary());
0437 particleParticle.push_back(barcode.particle());
0438 particleGeneration.push_back(barcode.generation());
0439 particleSubParticle.push_back(barcode.subParticle());
0440 }
0441 }
0442
0443
0444 m_t_x.push_back(Acts::clampValue<float>(truthPos4[Acts::ePos0]));
0445 m_t_y.push_back(Acts::clampValue<float>(truthPos4[Acts::ePos1]));
0446 m_t_z.push_back(Acts::clampValue<float>(truthPos4[Acts::ePos2]));
0447 m_t_r.push_back(Acts::clampValue<float>(
0448 perp(truthPos4.template segment<3>(Acts::ePos0))));
0449 m_t_dx.push_back(Acts::clampValue<float>(truthUnitDir[Acts::eMom0]));
0450 m_t_dy.push_back(Acts::clampValue<float>(truthUnitDir[Acts::eMom1]));
0451 m_t_dz.push_back(Acts::clampValue<float>(truthUnitDir[Acts::eMom2]));
0452
0453
0454 truthParams[Acts::eBoundLoc0] = truthLocal[Acts::ePos0];
0455 truthParams[Acts::eBoundLoc1] = truthLocal[Acts::ePos1];
0456 truthParams[Acts::eBoundPhi] = phi(truthUnitDir);
0457 truthParams[Acts::eBoundTheta] = theta(truthUnitDir);
0458 truthParams[Acts::eBoundTime] = truthPos4[Acts::eTime];
0459
0460
0461 m_t_eLOC0.push_back(
0462 Acts::clampValue<float>(truthParams[Acts::eBoundLoc0]));
0463 m_t_eLOC1.push_back(
0464 Acts::clampValue<float>(truthParams[Acts::eBoundLoc1]));
0465 m_t_ePHI.push_back(
0466 Acts::clampValue<float>(truthParams[Acts::eBoundPhi]));
0467 m_t_eTHETA.push_back(
0468 Acts::clampValue<float>(truthParams[Acts::eBoundTheta]));
0469 m_t_eQOP.push_back(
0470 Acts::clampValue<float>(truthParams[Acts::eBoundQOverP]));
0471 m_t_eT.push_back(
0472 Acts::clampValue<float>(truthParams[Acts::eBoundTime]));
0473
0474
0475 const Acts::BoundVector meas =
0476 state.projectorSubspaceHelper().expandVector(
0477 state.effectiveCalibrated());
0478
0479 const Acts::Vector2 local(meas[Acts::eBoundLoc0],
0480 meas[Acts::eBoundLoc1]);
0481 const Acts::Vector3 global =
0482 surface.localToGlobal(ctx.geoContext, local, truthUnitDir);
0483
0484
0485 m_lx_hit.push_back(Acts::clampValue<float>(local[Acts::ePos0]));
0486 m_ly_hit.push_back(Acts::clampValue<float>(local[Acts::ePos1]));
0487 m_x_hit.push_back(Acts::clampValue<float>(global[Acts::ePos0]));
0488 m_y_hit.push_back(Acts::clampValue<float>(global[Acts::ePos1]));
0489 m_z_hit.push_back(Acts::clampValue<float>(global[Acts::ePos2]));
0490 }
0491
0492
0493 auto getTrackParams = [&](unsigned int ipar)
0494 -> std::optional<std::pair<Acts::BoundVector, Acts::BoundMatrix>> {
0495 if (ipar == ePredicted && state.hasPredicted()) {
0496 return std::pair(state.predicted(), state.predictedCovariance());
0497 }
0498 if (ipar == eFiltered && state.hasFiltered()) {
0499 return std::pair(state.filtered(), state.filteredCovariance());
0500 }
0501 if (ipar == eSmoothed && state.hasSmoothed()) {
0502 return std::pair(state.smoothed(), state.smoothedCovariance());
0503 }
0504 if (ipar == eUnbiased && state.hasSmoothed() && state.hasProjector() &&
0505 state.hasCalibrated()) {
0506 return Acts::calculateUnbiasedParametersCovariance(state);
0507 }
0508 return std::nullopt;
0509 };
0510
0511
0512 for (unsigned int ipar = 0; ipar < eSize; ++ipar) {
0513
0514 const auto trackParamsOpt = getTrackParams(ipar);
0515
0516 m_hasParams[ipar].push_back(trackParamsOpt.has_value());
0517
0518 if (!trackParamsOpt.has_value()) {
0519 if (ipar == ePredicted) {
0520
0521 m_res_x_hit.push_back(nan);
0522 m_res_y_hit.push_back(nan);
0523 m_err_x_hit.push_back(nan);
0524 m_err_y_hit.push_back(nan);
0525 m_pull_x_hit.push_back(nan);
0526 m_pull_y_hit.push_back(nan);
0527 m_dim_hit.push_back(0);
0528 }
0529
0530
0531 m_eLOC0[ipar].push_back(nan);
0532 m_eLOC1[ipar].push_back(nan);
0533 m_ePHI[ipar].push_back(nan);
0534 m_eTHETA[ipar].push_back(nan);
0535 m_eQOP[ipar].push_back(nan);
0536 m_eT[ipar].push_back(nan);
0537 m_res_eLOC0[ipar].push_back(nan);
0538 m_res_eLOC1[ipar].push_back(nan);
0539 m_res_ePHI[ipar].push_back(nan);
0540 m_res_eTHETA[ipar].push_back(nan);
0541 m_res_eQOP[ipar].push_back(nan);
0542 m_res_eT[ipar].push_back(nan);
0543 m_err_eLOC0[ipar].push_back(nan);
0544 m_err_eLOC1[ipar].push_back(nan);
0545 m_err_ePHI[ipar].push_back(nan);
0546 m_err_eTHETA[ipar].push_back(nan);
0547 m_err_eQOP[ipar].push_back(nan);
0548 m_err_eT[ipar].push_back(nan);
0549 m_pull_eLOC0[ipar].push_back(nan);
0550 m_pull_eLOC1[ipar].push_back(nan);
0551 m_pull_ePHI[ipar].push_back(nan);
0552 m_pull_eTHETA[ipar].push_back(nan);
0553 m_pull_eQOP[ipar].push_back(nan);
0554 m_pull_eT[ipar].push_back(nan);
0555 m_x[ipar].push_back(nan);
0556 m_y[ipar].push_back(nan);
0557 m_z[ipar].push_back(nan);
0558 m_px[ipar].push_back(nan);
0559 m_py[ipar].push_back(nan);
0560 m_pz[ipar].push_back(nan);
0561 m_pT[ipar].push_back(nan);
0562 m_eta[ipar].push_back(nan);
0563
0564 continue;
0565 }
0566
0567 ++m_nParams[ipar];
0568 const auto& [parameters, covariance] = *trackParamsOpt;
0569
0570
0571 m_eLOC0[ipar].push_back(
0572 Acts::clampValue<float>(parameters[Acts::eBoundLoc0]));
0573 m_eLOC1[ipar].push_back(
0574 Acts::clampValue<float>(parameters[Acts::eBoundLoc1]));
0575 m_ePHI[ipar].push_back(
0576 Acts::clampValue<float>(parameters[Acts::eBoundPhi]));
0577 m_eTHETA[ipar].push_back(
0578 Acts::clampValue<float>(parameters[Acts::eBoundTheta]));
0579 m_eQOP[ipar].push_back(
0580 Acts::clampValue<float>(parameters[Acts::eBoundQOverP]));
0581 m_eT[ipar].push_back(
0582 Acts::clampValue<float>(parameters[Acts::eBoundTime]));
0583
0584
0585 Acts::BoundVector errors;
0586 for (Eigen::Index i = 0; i < parameters.size(); ++i) {
0587 const double variance = covariance(i, i);
0588 errors[i] = variance >= 0 ? std::sqrt(variance) : nan;
0589 }
0590 m_err_eLOC0[ipar].push_back(
0591 Acts::clampValue<float>(errors[Acts::eBoundLoc0]));
0592 m_err_eLOC1[ipar].push_back(
0593 Acts::clampValue<float>(errors[Acts::eBoundLoc1]));
0594 m_err_ePHI[ipar].push_back(
0595 Acts::clampValue<float>(errors[Acts::eBoundPhi]));
0596 m_err_eTHETA[ipar].push_back(
0597 Acts::clampValue<float>(errors[Acts::eBoundTheta]));
0598 m_err_eQOP[ipar].push_back(
0599 Acts::clampValue<float>(errors[Acts::eBoundQOverP]));
0600 m_err_eT[ipar].push_back(
0601 Acts::clampValue<float>(errors[Acts::eBoundTime]));
0602
0603
0604 const Acts::FreeVector freeParams =
0605 Acts::transformBoundToFreeParameters(surface, gctx, parameters);
0606 m_x[ipar].push_back(
0607 Acts::clampValue<float>(freeParams[Acts::eFreePos0]));
0608 m_y[ipar].push_back(
0609 Acts::clampValue<float>(freeParams[Acts::eFreePos1]));
0610 m_z[ipar].push_back(
0611 Acts::clampValue<float>(freeParams[Acts::eFreePos2]));
0612
0613 const double p = std::abs(1 / freeParams[Acts::eFreeQOverP]);
0614 m_px[ipar].push_back(
0615 Acts::clampValue<float>(p * freeParams[Acts::eFreeDir0]));
0616 m_py[ipar].push_back(
0617 Acts::clampValue<float>(p * freeParams[Acts::eFreeDir1]));
0618 m_pz[ipar].push_back(
0619 Acts::clampValue<float>(p * freeParams[Acts::eFreeDir2]));
0620 m_pT[ipar].push_back(Acts::clampValue<float>(
0621 p * std::hypot(freeParams[Acts::eFreeDir0],
0622 freeParams[Acts::eFreeDir1])));
0623 m_eta[ipar].push_back(Acts::clampValue<float>(
0624 Acts::VectorHelpers::eta(freeParams.segment<3>(Acts::eFreeDir0))));
0625
0626 if (!state.hasUncalibratedSourceLink()) {
0627 continue;
0628 }
0629
0630
0631 Acts::BoundVector residuals = parameters - truthParams;
0632 residuals[Acts::eBoundPhi] = Acts::detail::difference_periodic(
0633 parameters[Acts::eBoundPhi], truthParams[Acts::eBoundPhi],
0634 2 * std::numbers::pi);
0635 m_res_eLOC0[ipar].push_back(
0636 Acts::clampValue<float>(residuals[Acts::eBoundLoc0]));
0637 m_res_eLOC1[ipar].push_back(
0638 Acts::clampValue<float>(residuals[Acts::eBoundLoc1]));
0639 m_res_ePHI[ipar].push_back(
0640 Acts::clampValue<float>(residuals[Acts::eBoundPhi]));
0641 m_res_eTHETA[ipar].push_back(
0642 Acts::clampValue<float>(residuals[Acts::eBoundTheta]));
0643 m_res_eQOP[ipar].push_back(
0644 Acts::clampValue<float>(residuals[Acts::eBoundQOverP]));
0645 m_res_eT[ipar].push_back(
0646 Acts::clampValue<float>(residuals[Acts::eBoundTime]));
0647
0648
0649 Acts::BoundVector pulls = Acts::BoundVector::Constant(nan);
0650 for (Eigen::Index i = 0; i < parameters.size(); ++i) {
0651 pulls[i] = (!std::isnan(errors[i]) && errors[i] > 0)
0652 ? residuals[i] / errors[i]
0653 : nan;
0654 }
0655 m_pull_eLOC0[ipar].push_back(
0656 Acts::clampValue<float>(pulls[Acts::eBoundLoc0]));
0657 m_pull_eLOC1[ipar].push_back(
0658 Acts::clampValue<float>(pulls[Acts::eBoundLoc1]));
0659 m_pull_ePHI[ipar].push_back(
0660 Acts::clampValue<float>(pulls[Acts::eBoundPhi]));
0661 m_pull_eTHETA[ipar].push_back(
0662 Acts::clampValue<float>(pulls[Acts::eBoundTheta]));
0663 m_pull_eQOP[ipar].push_back(
0664 Acts::clampValue<float>(pulls[Acts::eBoundQOverP]));
0665 m_pull_eT[ipar].push_back(
0666 Acts::clampValue<float>(pulls[Acts::eBoundTime]));
0667
0668 if (ipar == ePredicted) {
0669
0670 const Acts::ActsDynamicMatrix H =
0671 state.projectorSubspaceHelper().fullProjector().topLeftCorner(
0672 state.calibratedSize(), Acts::eBoundSize);
0673 const Acts::ActsDynamicMatrix V =
0674 state.effectiveCalibratedCovariance();
0675 const Acts::ActsDynamicMatrix resCov =
0676 V + H * covariance * H.transpose();
0677 const Acts::ActsDynamicVector res =
0678 state.effectiveCalibrated() - H * parameters;
0679
0680 const double resX = res[Acts::eBoundLoc0];
0681 const double errX =
0682 V(Acts::eBoundLoc0, Acts::eBoundLoc0) >= 0
0683 ? std::sqrt(V(Acts::eBoundLoc0, Acts::eBoundLoc0))
0684 : nan;
0685 const double pullX =
0686 resCov(Acts::eBoundLoc0, Acts::eBoundLoc0) > 0
0687 ? resX / std::sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))
0688 : nan;
0689
0690 m_res_x_hit.push_back(Acts::clampValue<float>(resX));
0691 m_err_x_hit.push_back(Acts::clampValue<float>(errX));
0692 m_pull_x_hit.push_back(Acts::clampValue<float>(pullX));
0693
0694 if (state.calibratedSize() >= 2) {
0695 const double resY = res[Acts::eBoundLoc1];
0696 const double errY =
0697 V(Acts::eBoundLoc1, Acts::eBoundLoc1) >= 0
0698 ? std::sqrt(V(Acts::eBoundLoc1, Acts::eBoundLoc1))
0699 : nan;
0700 const double pullY =
0701 resCov(Acts::eBoundLoc1, Acts::eBoundLoc1) > 0
0702 ? resY /
0703 std::sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))
0704 : nan;
0705
0706 m_res_y_hit.push_back(Acts::clampValue<float>(resY));
0707 m_err_y_hit.push_back(Acts::clampValue<float>(errY));
0708 m_pull_y_hit.push_back(Acts::clampValue<float>(pullY));
0709 } else {
0710 m_res_y_hit.push_back(nan);
0711 m_err_y_hit.push_back(nan);
0712 m_pull_y_hit.push_back(nan);
0713 }
0714
0715 m_dim_hit.push_back(state.calibratedSize());
0716 }
0717 }
0718 m_particleVertexPrimary.push_back(std::move(particleVertexPrimary));
0719 m_particleVertexSecondary.push_back(std::move(particleVertexSecondary));
0720 m_particleParticle.push_back(std::move(particleParticle));
0721 m_particleGeneration.push_back(std::move(particleGeneration));
0722 m_particleSubParticle.push_back(std::move(particleSubParticle));
0723 }
0724
0725
0726 m_outputTree->Fill();
0727
0728
0729 m_volumeID.clear();
0730 m_layerID.clear();
0731 m_moduleID.clear();
0732
0733 m_stateType.clear();
0734
0735 m_chi2.clear();
0736
0737 m_pathLength.clear();
0738
0739 m_t_x.clear();
0740 m_t_y.clear();
0741 m_t_z.clear();
0742 m_t_r.clear();
0743 m_t_dx.clear();
0744 m_t_dy.clear();
0745 m_t_dz.clear();
0746 m_t_eLOC0.clear();
0747 m_t_eLOC1.clear();
0748 m_t_ePHI.clear();
0749 m_t_eTHETA.clear();
0750 m_t_eQOP.clear();
0751 m_t_eT.clear();
0752 m_particleVertexPrimary.clear();
0753 m_particleVertexSecondary.clear();
0754 m_particleParticle.clear();
0755 m_particleGeneration.clear();
0756 m_particleSubParticle.clear();
0757
0758 m_dim_hit.clear();
0759 m_lx_hit.clear();
0760 m_ly_hit.clear();
0761 m_x_hit.clear();
0762 m_y_hit.clear();
0763 m_z_hit.clear();
0764 m_res_x_hit.clear();
0765 m_res_y_hit.clear();
0766 m_err_x_hit.clear();
0767 m_err_y_hit.clear();
0768 m_pull_x_hit.clear();
0769 m_pull_y_hit.clear();
0770
0771 for (unsigned int ipar = 0; ipar < eSize; ++ipar) {
0772 m_hasParams[ipar].clear();
0773 m_eLOC0[ipar].clear();
0774 m_eLOC1[ipar].clear();
0775 m_ePHI[ipar].clear();
0776 m_eTHETA[ipar].clear();
0777 m_eQOP[ipar].clear();
0778 m_eT[ipar].clear();
0779 m_res_eLOC0[ipar].clear();
0780 m_res_eLOC1[ipar].clear();
0781 m_res_ePHI[ipar].clear();
0782 m_res_eTHETA[ipar].clear();
0783 m_res_eQOP[ipar].clear();
0784 m_res_eT[ipar].clear();
0785 m_err_eLOC0[ipar].clear();
0786 m_err_eLOC1[ipar].clear();
0787 m_err_ePHI[ipar].clear();
0788 m_err_eTHETA[ipar].clear();
0789 m_err_eQOP[ipar].clear();
0790 m_err_eT[ipar].clear();
0791 m_pull_eLOC0[ipar].clear();
0792 m_pull_eLOC1[ipar].clear();
0793 m_pull_ePHI[ipar].clear();
0794 m_pull_eTHETA[ipar].clear();
0795 m_pull_eQOP[ipar].clear();
0796 m_pull_eT[ipar].clear();
0797 m_x[ipar].clear();
0798 m_y[ipar].clear();
0799 m_z[ipar].clear();
0800 m_px[ipar].clear();
0801 m_py[ipar].clear();
0802 m_pz[ipar].clear();
0803 m_eta[ipar].clear();
0804 m_pT[ipar].clear();
0805 }
0806
0807 m_chi2.clear();
0808 }
0809
0810 return ProcessCode::SUCCESS;
0811 }
0812
0813 }