File indexing completed on 2024-06-01 07:06:48
0001
0002
0003
0004
0005 #include "TrackParamTruthInit.h"
0006
0007 #include <Acts/Definitions/Algebra.hpp>
0008 #include <Acts/Surfaces/PerigeeSurface.hpp>
0009 #include <Acts/Surfaces/Surface.hpp>
0010 #include <Acts/Utilities/Result.hpp>
0011
0012 #include <Evaluator/DD4hepUnits.h>
0013 #include <TParticlePDG.h>
0014 #include <edm4hep/Vector3d.h>
0015 #include <edm4hep/Vector3f.h>
0016 #include <edm4eic/Cov6f.h>
0017 #include <fmt/core.h>
0018 #include <spdlog/common.h>
0019 #include <Eigen/Core>
0020 #include <cmath>
0021 #include <limits>
0022 #include <memory>
0023 #include <utility>
0024
0025 #include "extensions/spdlog/SpdlogFormatters.h" // IWYU pragma: keep
0026
0027
0028 void eicrecon::TrackParamTruthInit::init(std::shared_ptr<const ActsGeometryProvider> geo_svc, const std::shared_ptr<spdlog::logger> logger) {
0029 m_log = logger;
0030 m_geoSvc = geo_svc;
0031
0032
0033 m_pdg_db = std::make_shared<TDatabasePDG>();
0034 }
0035
0036 std::unique_ptr<edm4eic::TrackParametersCollection>
0037 eicrecon::TrackParamTruthInit::produce(const edm4hep::MCParticleCollection* mcparticles) {
0038
0039
0040
0041
0042 auto track_parameters = std::make_unique<edm4eic::TrackParametersCollection>();
0043
0044
0045 for (const auto& mcparticle: *mcparticles) {
0046
0047
0048 if (mcparticle.getGeneratorStatus() != 1 ) {
0049 m_log->trace("ignoring particle with generatorStatus = {}", mcparticle.getGeneratorStatus());
0050 continue;
0051 }
0052
0053
0054 auto v = mcparticle.getVertex();
0055 if (abs(v.x) * dd4hep::mm > m_cfg.maxVertexX ||
0056 abs(v.y) * dd4hep::mm > m_cfg.maxVertexY ||
0057 abs(v.z) * dd4hep::mm > m_cfg.maxVertexZ) {
0058 m_log->trace("ignoring particle with vs = {} [mm]", v);
0059 continue;
0060 }
0061
0062
0063 const auto& p = mcparticle.getMomentum();
0064 const auto pmag = std::hypot(p.x, p.y, p.z);
0065 if (pmag * dd4hep::GeV < m_cfg.minMomentum) {
0066 m_log->trace("ignoring particle with p = {} GeV ", pmag);
0067 continue;
0068 }
0069
0070
0071 const auto phi = std::atan2(p.y, p.x);
0072 const auto theta = std::atan2(std::hypot(p.x, p.y), p.z);
0073 const auto eta = -std::log(std::tan(theta/2));
0074 if (eta > m_cfg.maxEtaForward || eta < -std::abs(m_cfg.maxEtaBackward)) {
0075 m_log->trace("ignoring particle with Eta = {}", eta);
0076 continue;
0077 }
0078
0079
0080
0081
0082
0083 const auto pdg = mcparticle.getPDG();
0084 const auto* particle = m_pdg_db->GetParticle(pdg);
0085 if (particle == nullptr) {
0086 m_log->debug("particle with PDG {} not in TDatabasePDG", pdg);
0087 continue;
0088 }
0089 double charge = std::copysign(1.0,particle->Charge());
0090 if (abs(charge) < std::numeric_limits<double>::epsilon()) {
0091 m_log->trace("ignoring neutral particle");
0092 continue;
0093 }
0094
0095
0096 const auto pinit = pmag * (1.0 + m_cfg.momentumSmear * m_normDist(generator));
0097
0098
0099 auto perigee = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(0,0,0));
0100
0101
0102
0103 auto linesurface_parameter = -(v.x*p.x + v.y*p.y)/(p.x*p.x + p.y*p.y);
0104
0105 auto xpca = v.x + linesurface_parameter*p.x;
0106 auto ypca = v.y + linesurface_parameter*p.y;
0107 auto zpca = v.z + linesurface_parameter*p.z;
0108
0109 Acts::Vector3 global(xpca, ypca, zpca);
0110 Acts::Vector3 direction(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta));
0111
0112
0113 auto local = perigee->globalToLocal(m_geoSvc->getActsGeometryContext(), global, direction);
0114
0115 if(!local.ok())
0116 {
0117 m_log->error("skipping the track because globaltoLocal function failed");
0118 continue;
0119 }
0120
0121 Acts::Vector2 localpos = local.value();
0122
0123
0124 auto track_parameter = track_parameters->create();
0125 track_parameter.setType(-1);
0126 track_parameter.setLoc({static_cast<float>(localpos(0)), static_cast<float>(localpos(1))});
0127 track_parameter.setPhi(phi);
0128 track_parameter.setTheta(theta);
0129 track_parameter.setQOverP(charge / (pinit / dd4hep::GeV));
0130 track_parameter.setTime(mcparticle.getTime());
0131 edm4eic::Cov6f cov;
0132 cov(0,0) = 1.0;
0133 cov(1,1) = 1.0;
0134 cov(2,2) = 0.05;
0135 cov(3,3) = 0.01;
0136 cov(4,4) = 0.1;
0137 cov(5,5) = 10e9;
0138 track_parameter.setCovariance(cov);
0139
0140
0141 if (m_log->level() <= spdlog::level::debug) {
0142 m_log->debug("Invoke track finding seeded by truth particle with:");
0143 m_log->debug(" p = {} GeV (smeared to {} GeV)", pmag / dd4hep::GeV, pinit / dd4hep::GeV);
0144 m_log->debug(" q = {}", charge);
0145 m_log->debug(" q/p = {} e/GeV (smeared to {} e/GeV)", charge / (pmag / dd4hep::GeV), charge / (pinit / dd4hep::GeV));
0146 m_log->debug(" theta = {}", theta);
0147 m_log->debug(" phi = {}", phi);
0148 }
0149 }
0150
0151 return std::move(track_parameters);
0152
0153 }