Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-04 08:39:33

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