File indexing completed on 2025-07-09 08:52:16
0001
0002
0003
0004 #include <algorithm>
0005
0006
0007 #include "Gaudi/Algorithm.h"
0008 #include "GaudiKernel/ToolHandle.h"
0009 #include "GaudiKernel/RndmGenerators.h"
0010 #include "Gaudi/Property.h"
0011
0012 #include "DDRec/CellIDPositionConverter.h"
0013 #include "DDRec/SurfaceManager.h"
0014 #include "DDRec/Surface.h"
0015
0016 #include <k4FWCore/DataHandle.h>
0017 #include <k4Interface/IGeoSvc.h>
0018
0019 #include "Acts/EventData/MultiTrajectory.hpp"
0020 #include "Acts/EventData/MultiTrajectoryHelpers.hpp"
0021
0022
0023 #include "edm4eic/EDM4eicVersion.h"
0024 #include "edm4eic/ReconstructedParticleCollection.h"
0025 #include "edm4eic/TrackerHitCollection.h"
0026 #include "edm4eic/TrackParametersCollection.h"
0027 #include "ActsExamples/EventData/IndexSourceLink.hpp"
0028 #include "ActsExamples/EventData/Track.hpp"
0029 #include "ActsExamples/EventData/Trajectories.hpp"
0030
0031 #include "Acts/Utilities/Helpers.hpp"
0032
0033 #include "edm4hep/utils/vector_utils.h"
0034
0035 #include <cmath>
0036
0037 namespace Jug::Reco {
0038
0039 #if EDM4EIC_VERSION_MAJOR >= 5
0040
0041
0042
0043
0044
0045
0046 static constexpr std::array<std::pair<Acts::BoundIndices, double>, 6> edm4eic_indexed_units{{
0047 {Acts::eBoundLoc0, Acts::UnitConstants::mm},
0048 {Acts::eBoundLoc1, Acts::UnitConstants::mm},
0049 {Acts::eBoundTheta, 1.},
0050 {Acts::eBoundPhi, 1.},
0051 {Acts::eBoundQOverP, 1. / Acts::UnitConstants::GeV},
0052 {Acts::eBoundTime, Acts::UnitConstants::ns}
0053 }};
0054 #endif
0055
0056
0057
0058
0059
0060 class ParticlesFromTrackFit : public Gaudi::Algorithm {
0061 private:
0062 mutable DataHandle<ActsExamples::TrajectoriesContainer> m_inputTrajectories{"inputTrajectories", Gaudi::DataHandle::Reader, this};
0063 mutable DataHandle<edm4eic::ReconstructedParticleCollection> m_outputParticles{"outputParticles", Gaudi::DataHandle::Writer, this};
0064 mutable DataHandle<edm4eic::TrackParametersCollection> m_outputTrackParameters{"outputTrackParameters", Gaudi::DataHandle::Writer, this};
0065
0066 public:
0067
0068 ParticlesFromTrackFit(const std::string& name, ISvcLocator* svcLoc)
0069 : Gaudi::Algorithm(name, svcLoc) {
0070 declareProperty("inputTrajectories", m_inputTrajectories,"");
0071 declareProperty("outputParticles", m_outputParticles, "");
0072 declareProperty("outputTrackParameters", m_outputTrackParameters, "Acts Track Parameters");
0073 }
0074
0075 StatusCode initialize() override {
0076 if (Gaudi::Algorithm::initialize().isFailure()) {
0077 return StatusCode::FAILURE;
0078 }
0079 return StatusCode::SUCCESS;
0080 }
0081
0082 StatusCode execute(const EventContext&) const override {
0083
0084 const auto* const trajectories = m_inputTrajectories.get();
0085
0086 auto* rec_parts = m_outputParticles.createAndPut();
0087 auto* track_pars = m_outputTrackParameters.createAndPut();
0088
0089 if (msgLevel(MSG::DEBUG)) {
0090 debug() << std::size(*trajectories) << " trajectories " << endmsg;
0091 }
0092
0093
0094 for (const auto& traj : *trajectories) {
0095
0096
0097
0098 const auto& mj = traj.multiTrajectory();
0099 const auto& trackTips = traj.tips();
0100 if (trackTips.empty()) {
0101 if (msgLevel(MSG::DEBUG)) {
0102 debug() << "Empty multiTrajectory." << endmsg;
0103 }
0104 continue;
0105 }
0106
0107 const auto& trackTip = trackTips.front();
0108
0109
0110 auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip);
0111
0112
0113
0114
0115
0116 if (traj.hasTrackParameters(trackTip)) {
0117 const auto& boundParam = traj.trackParameters(trackTip);
0118 const auto& parameter = boundParam.parameters();
0119 const auto& covariance = *boundParam.covariance();
0120 if (msgLevel(MSG::DEBUG)) {
0121 debug() << "loc 0 = " << parameter[Acts::eBoundLoc0] << endmsg;
0122 debug() << "loc 1 = " << parameter[Acts::eBoundLoc1] << endmsg;
0123 debug() << "phi = " << parameter[Acts::eBoundPhi] << endmsg;
0124 debug() << "theta = " << parameter[Acts::eBoundTheta] << endmsg;
0125 debug() << "q/p = " << parameter[Acts::eBoundQOverP] << endmsg;
0126 debug() << "p = " << 1.0 / parameter[Acts::eBoundQOverP] << endmsg;
0127
0128 debug() << "err phi = " << sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi)) << endmsg;
0129 debug() << "err th = " << sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta)) << endmsg;
0130 debug() << "err q/p = " << sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)) << endmsg;
0131
0132 debug() << " chi2 = " << trajState.chi2Sum << endmsg;
0133 }
0134
0135 auto pars = track_pars->create();
0136 pars.setType(0);
0137 pars.setLoc({
0138 static_cast<float>(parameter[Acts::eBoundLoc0]),
0139 static_cast<float>(parameter[Acts::eBoundLoc1])
0140 });
0141 pars.setTheta(static_cast<float>(parameter[Acts::eBoundTheta]));
0142 pars.setPhi(static_cast<float>(parameter[Acts::eBoundPhi]));
0143 pars.setQOverP(static_cast<float>(parameter[Acts::eBoundQOverP]));
0144 pars.setTime(static_cast<float>(parameter[Acts::eBoundTime]));
0145 #if EDM4EIC_VERSION_MAJOR >= 5
0146 edm4eic::Cov6f cov;
0147 for (size_t i = 0; const auto& [a, x] : edm4eic_indexed_units) {
0148 for (size_t j = 0; const auto& [b, y] : edm4eic_indexed_units) {
0149
0150 cov(i,j) = covariance(a,b) / x / y;
0151 }
0152 }
0153 pars.setCovariance(cov);
0154 #else
0155 pars.setCharge(static_cast<float>(boundParam.charge()));
0156 pars.setLocError({
0157 static_cast<float>(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)),
0158 static_cast<float>(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)),
0159 static_cast<float>(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1))
0160 });
0161 pars.setMomentumError({
0162 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundTheta)),
0163 static_cast<float>(covariance(Acts::eBoundPhi, Acts::eBoundPhi)),
0164 static_cast<float>(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)),
0165 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundPhi)),
0166 static_cast<float>(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)),
0167 static_cast<float>(covariance(Acts::eBoundPhi, Acts::eBoundQOverP))
0168 });
0169 pars.setTimeError(sqrt(static_cast<float>(covariance(Acts::eBoundTime, Acts::eBoundTime))));
0170 #endif
0171 }
0172
0173 auto tsize = trackTips.size();
0174 if (msgLevel(MSG::DEBUG)) {
0175 debug() << "# fitted parameters : " << tsize << endmsg;
0176 }
0177 if (tsize == 0) {
0178 continue;
0179 }
0180
0181 mj.visitBackwards(tsize - 1, [&](auto&& trackstate) {
0182
0183
0184 auto params = trackstate.predicted();
0185
0186 double p0 = (1.0 / params[Acts::eBoundQOverP]) / Acts::UnitConstants::GeV;
0187 if (msgLevel(MSG::DEBUG)) {
0188 debug() << "track predicted p = " << p0 << " GeV" << endmsg;
0189 }
0190 if (std::abs(p0) > 500) {
0191 if (msgLevel(MSG::DEBUG)) {
0192 debug() << "skipping" << endmsg;
0193 }
0194 return;
0195 }
0196
0197 auto rec_part = rec_parts->create();
0198 rec_part.setMomentum(
0199 edm4hep::utils::sphericalToVector(
0200 1.0 / std::abs(params[Acts::eBoundQOverP]),
0201 params[Acts::eBoundTheta],
0202 params[Acts::eBoundPhi])
0203 );
0204 rec_part.setCharge(static_cast<int16_t>(std::copysign(1., params[Acts::eBoundQOverP])));
0205 });
0206 }
0207
0208 return StatusCode::SUCCESS;
0209 }
0210
0211 };
0212
0213 DECLARE_COMPONENT(ParticlesFromTrackFit)
0214
0215 }