Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-14 08:18:13

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/EventData/AnyTrackProxy.hpp"
0014 #include "Acts/EventData/ParticleHypothesis.hpp"
0015 #include "Acts/EventData/TrackContainer.hpp"
0016 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0017 #include "Acts/EventData/VectorTrackContainer.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Geometry/Polyhedron.hpp"
0020 #include "Acts/Surfaces/Surface.hpp"
0021 #include "Acts/Visualization/GeometryView3D.hpp"
0022 #include "Acts/Visualization/IVisualization3D.hpp"
0023 #include "Acts/Visualization/ViewConfig.hpp"
0024 
0025 #include <array>
0026 #include <cmath>
0027 #include <cstddef>
0028 #include <numbers>
0029 #include <vector>
0030 
0031 namespace Acts {
0032 class IVisualization3D;
0033 
0034 /// View configuration for track parameters
0035 static ViewConfig s_viewParameter = {.color = {0, 0, 255}};
0036 /// View configuration for measurements
0037 static ViewConfig s_viewMeasurement = {.color = {255, 102, 0}};
0038 /// View configuration for predicted states
0039 static ViewConfig s_viewPredicted = {.color = {51, 204, 51}};
0040 /// View configuration for filtered states
0041 static ViewConfig s_viewFiltered = {.color = {255, 255, 0}};
0042 /// View configuration for smoothed states
0043 static ViewConfig s_viewSmoothed = {.color = {0, 102, 25}};
0044 
0045 /// Utilities to visualize event data in 3D.
0046 struct EventDataView3D {
0047   /// Helper to find the eigen values and corr angle
0048   ///
0049   /// @param covariance The covariance matrix
0050   /// @return Array containing [eigenvalue0, eigenvalue1, theta]
0051   static inline std::array<double, 3> decomposeCovariance(
0052       const SquareMatrix<2>& covariance) {
0053     double c00 = covariance(eBoundLoc0, eBoundLoc0);
0054     double c01 = covariance(eBoundLoc0, eBoundLoc1);
0055     double c11 = covariance(eBoundLoc1, eBoundLoc1);
0056 
0057     double cdsq = std::pow((c00 - c11), 2) / 4.;
0058     double cosq = c01 * c01;
0059 
0060     // Calculate the eigen values w.r.t reference frame
0061     double lambda0 = (c00 + c11) / 2. + std::sqrt(cdsq + cosq);
0062     double lambda1 = (c00 + c11) / 2. - std::sqrt(cdsq + cosq);
0063     double theta = std::atan2(lambda0 - c00, c01);
0064 
0065     return {lambda0, lambda1, theta};
0066   }
0067 
0068   /// Helper method to draw the ellipse points
0069   ///
0070   /// @param lambda0 The Eigenvalue in 0
0071   /// @param lambda1 The Eigenvalue in 1
0072   /// @param theta The angle between the x/y frame and EV frame
0073   /// @param lseg The number of segments
0074   /// @param offset The out of plane offset for visibility
0075   /// @param lposition The local anker point of the ellipse
0076   /// @param transform The transform to global
0077   /// @return Vector of 3D points representing the ellipse
0078   static inline std::vector<Vector3> createEllipse(
0079       double lambda0, double lambda1, double theta, std::size_t lseg,
0080       double offset, const Vector2& lposition = Vector2(0., 0.),
0081       const Transform3& transform = Transform3::Identity()) {
0082     double ctheta = std::cos(theta);
0083     double stheta = std::sin(theta);
0084 
0085     double l1sq = std::sqrt(lambda0);
0086     double l2sq = std::sqrt(lambda1);
0087 
0088     // Now generate the ellipse points
0089     std::vector<Vector3> ellipse;
0090     ellipse.reserve(lseg);
0091     double thetaStep = 2 * std::numbers::pi / lseg;
0092     for (std::size_t it = 0; it < lseg; ++it) {
0093       double phi = -std::numbers::pi + it * thetaStep;
0094       double cphi = std::cos(phi);
0095       double sphi = std::sin(phi);
0096       double x = lposition.x() + (l1sq * ctheta * cphi - l2sq * stheta * sphi);
0097       double y = lposition.y() + (l1sq * stheta * cphi + l2sq * ctheta * sphi);
0098       ellipse.push_back(transform * Vector3(x, y, offset));
0099     }
0100     return ellipse;
0101   }
0102 
0103   /// Helper method to draw error ellipse
0104   ///
0105   /// @param helper [in, out] The visualization helper
0106   /// @param lposition The local position
0107   /// @param covariance The covariance matrix
0108   /// @param transform The reference Frame transform
0109   /// @param locErrorScale The local Error scale
0110   /// @param viewConfig The visualization parameters
0111   static void drawCovarianceCartesian(
0112       IVisualization3D& helper, const Vector2& lposition,
0113       const SquareMatrix2& covariance, const Transform3& transform,
0114       double locErrorScale = 1, const ViewConfig& viewConfig = s_viewParameter);
0115 
0116   /// Helper method to draw error cone of a direction
0117   ///
0118   /// @param helper [in, out] The visualization helper
0119   /// @param position Where the cone originates from
0120   /// @param direction The direction parameters
0121   /// @param covariance The 2x2 covariance matrix for phi/theta
0122   /// @param directionScale The direction arrow length
0123   /// @param angularErrorScale The local Error scale
0124   /// @param viewConfig The visualization parameters
0125   static void drawCovarianceAngular(
0126       IVisualization3D& helper, const Vector3& position,
0127       const Vector3& direction, const SquareMatrix<2>& covariance,
0128       double directionScale = 1, double angularErrorScale = 1,
0129       const ViewConfig& viewConfig = s_viewParameter);
0130 
0131   /// Helper method to draw bound parameters object
0132   ///
0133   /// @param helper [in, out] The visualization helper
0134   /// @param parameters The bound parameters to be drawn
0135   /// @param gctx The geometry context for which it is drawn
0136   /// @param momentumScale The scale of the momentum
0137   /// @param locErrorScale  The scale of the local error
0138   /// @param angularErrorScale The scale of the angular error
0139   /// @param parConfig The visualization options for the parameter
0140   /// @param covConfig The visualization option for the covariance
0141   /// @param surfConfig The visualization option for the surface
0142   template <typename parameters_t>
0143   static inline void drawBoundTrackParameters(
0144       IVisualization3D& helper, const parameters_t& parameters,
0145       const GeometryContext& gctx =
0146           GeometryContext::dangerouslyDefaultConstruct(),
0147       double momentumScale = 1., double locErrorScale = 1.,
0148       double angularErrorScale = 1.,
0149       const ViewConfig& parConfig = s_viewParameter,
0150       const ViewConfig& covConfig = s_viewParameter,
0151       const ViewConfig& surfConfig = s_viewSensitive) {
0152     if (surfConfig.visible) {
0153       GeometryView3D::drawSurface(helper, parameters.referenceSurface(), gctx,
0154                                   Transform3::Identity(), surfConfig);
0155     }
0156 
0157     // Draw the parameter shaft and cone
0158     auto position = parameters.position(gctx);
0159     auto direction = parameters.direction();
0160     double p = parameters.absoluteMomentum();
0161 
0162     ViewConfig lparConfig = parConfig;
0163     lparConfig.lineThickness = 0.05;
0164     Vector3 parLength = p * momentumScale * direction;
0165 
0166     GeometryView3D::drawArrowBackward(
0167         helper, position, position + 0.5 * parLength, 100., 1.0, lparConfig);
0168 
0169     GeometryView3D::drawArrowForward(helper, position + 0.5 * parLength,
0170                                      position + parLength, 4., 2.5, lparConfig);
0171 
0172     if (parameters.covariance().has_value()) {
0173       auto paramVec = parameters.parameters();
0174       auto lposition = paramVec.template block<2, 1>(0, 0);
0175 
0176       // Draw the local covariance
0177       const auto& covariance = *parameters.covariance();
0178       drawCovarianceCartesian(
0179           helper, lposition, covariance.template block<2, 2>(0, 0),
0180           parameters.referenceSurface().localToGlobalTransform(gctx),
0181           locErrorScale, covConfig);
0182 
0183       drawCovarianceAngular(
0184           helper, position, direction, covariance.template block<2, 2>(2, 2),
0185           0.9 * p * momentumScale, angularErrorScale, covConfig);
0186     }
0187   }
0188 
0189   /// Helper method to draw a single measurement
0190   ///
0191   /// @param helper [in, out] The visualization helper
0192   /// @param lposition calibrated measurement
0193   /// @param covariance calibrated covariance
0194   /// @param transform reference surface transformed with the geometry context
0195   /// @param locErrorScale  The scale of the local error
0196   /// @param measurementConfig The visualization options for the measurement
0197   ///
0198   /// TODO: Expand to 1D measurements
0199   static void drawMeasurement(
0200       IVisualization3D& helper, const Vector2& lposition,
0201       const SquareMatrix2& covariance, const Transform3& transform,
0202       const double locErrorScale = 1.,
0203       const ViewConfig& measurementConfig = s_viewMeasurement) {
0204     if (locErrorScale <= 0) {
0205       throw std::invalid_argument("locErrorScale must be > 0");
0206     }
0207     if (measurementConfig.visible) {
0208       drawCovarianceCartesian(helper, lposition, covariance, transform,
0209                               locErrorScale, measurementConfig);
0210     }
0211   }
0212 
0213   /// Helper method to draw one trajectory stored in a MultiTrajectory object
0214   ///
0215   /// @param helper [in, out] The visualization helper
0216   /// @param multiTraj The MultiTrajectory storing the trajectory to be drawn
0217   /// @param entryIndex The trajectory entry index
0218   /// @param gctx The geometry context for which it is drawn
0219   /// @param momentumScale The scale of the momentum
0220   /// @param locErrorScale  The scale of the local error
0221   /// @param angularErrorScale The scale of the angular error
0222   /// @param surfaceConfig The visualization options for the surface
0223   /// @param measurementConfig The visualization options for the measurement
0224   /// @param predictedConfig The visualization options for the predicted
0225   /// measurement
0226   /// @param filteredConfig The visualization options for the filtered
0227   /// parameters
0228   /// @param smoothedConfig The visualization options for the smoothed
0229   /// parameters
0230   template <typename traj_t>
0231   static void drawMultiTrajectory(
0232       IVisualization3D& helper, const traj_t& multiTraj,
0233       const std::size_t& entryIndex,
0234       const GeometryContext& gctx =
0235           GeometryContext::dangerouslyDefaultConstruct(),
0236       double momentumScale = 1., double locErrorScale = 1.,
0237       double angularErrorScale = 1.,
0238       const ViewConfig& surfaceConfig = s_viewSensitive,
0239       const ViewConfig& measurementConfig = s_viewMeasurement,
0240       const ViewConfig& predictedConfig = s_viewPredicted,
0241       const ViewConfig& filteredConfig = s_viewFiltered,
0242       const ViewConfig& smoothedConfig = s_viewSmoothed) {
0243     // @TODO: Refactor based on Track class
0244 
0245     // TODO get particle hypothesis from track
0246     ParticleHypothesis particleHypothesis = ParticleHypothesis::pion();
0247 
0248     // Visit the track states on the trajectory
0249     multiTraj.visitBackwards(entryIndex, [&](const auto& state) {
0250       // Only draw the measurement states
0251       if (!state.typeFlags().hasMeasurement()) {
0252         return true;
0253       }
0254 
0255       // Use smaller scaling factors for the first state
0256       // @Todo: add parameter for the first state error scaling
0257       if (state.index() == 0) {
0258         locErrorScale = locErrorScale * 0.1;
0259         angularErrorScale = angularErrorScale * 0.1;
0260       }
0261 
0262       // First, if necessary, draw the surface
0263       if (surfaceConfig.visible) {
0264         GeometryView3D::drawSurface(helper, state.referenceSurface(), gctx,
0265                                     Transform3::Identity(), surfaceConfig);
0266       }
0267 
0268       // Second, if necessary and present, draw the calibrated measurement (only
0269       // draw 2D measurement here)
0270       // @Todo: how to draw 1D measurement?
0271       if (state.hasCalibrated() && state.calibratedSize() == 2) {
0272         const Vector2& lposition = state.template calibrated<2>();
0273         const SquareMatrix2 covariance =
0274             state.template calibratedCovariance<2>();
0275         drawMeasurement(helper, lposition, covariance,
0276                         state.referenceSurface().localToGlobalTransform(gctx),
0277                         locErrorScale, measurementConfig);
0278       }
0279 
0280       // Last, if necessary and present, draw the track parameters
0281       // (a) predicted track parameters
0282       if (predictedConfig.visible && state.hasPredicted()) {
0283         drawBoundTrackParameters(
0284             helper,
0285             BoundTrackParameters(state.referenceSurface().getSharedPtr(),
0286                                  state.predicted(), state.predictedCovariance(),
0287                                  particleHypothesis),
0288             gctx, momentumScale, locErrorScale, angularErrorScale,
0289             predictedConfig, predictedConfig, {.visible = false});
0290       }
0291       // (b) filtered track parameters
0292       if (filteredConfig.visible && state.hasFiltered()) {
0293         drawBoundTrackParameters(
0294             helper,
0295             BoundTrackParameters(state.referenceSurface().getSharedPtr(),
0296                                  state.filtered(), state.filteredCovariance(),
0297                                  particleHypothesis),
0298             gctx, momentumScale, locErrorScale, angularErrorScale,
0299             filteredConfig, filteredConfig, {.visible = false});
0300       }
0301       // (c) smoothed track parameters
0302       if (smoothedConfig.visible && state.hasSmoothed()) {
0303         drawBoundTrackParameters(
0304             helper,
0305             BoundTrackParameters(state.referenceSurface().getSharedPtr(),
0306                                  state.smoothed(), state.smoothedCovariance(),
0307                                  particleHypothesis),
0308             gctx, momentumScale, locErrorScale, angularErrorScale,
0309             smoothedConfig, smoothedConfig, {.visible = false});
0310       }
0311       return true;
0312     });
0313   }
0314 
0315   /// Helper method to draw a track from AnyTrackProxy
0316   ///
0317   /// @param helper [in, out] The visualization helper
0318   /// @param track The track to be drawn
0319   /// @param gctx The geometry context for which it is drawn
0320   static void drawTrack(IVisualization3D& helper,
0321                         const AnyConstTrackProxy& track,
0322                         const GeometryContext& gctx);
0323 };
0324 
0325 }  // namespace Acts