From 64e54840197e47c941f22e1a2c59f7460019675d Mon Sep 17 00:00:00 2001 From: miranov Date: Fri, 23 Oct 2026 19:51:37 +0200 Subject: [PATCH 1/4] TrackTools: introduce full-state TrackGeometry C++ utilities and portable tests Introduce TrackGeometry as the first component of the shared TrackTools package for O2 reconstruction, O2Physics and calibration workflows. The goal is to provide consistent geometry-derived track observables for detector acceptance, tracking-quality and dE/dx PID studies. C++ implementation: - Accept complete O2 TrackPar states, including displaced tracks. - Provide analytic helix (H) and O2 transport (K0) queries at requested cylindrical radii, relevant to TPC, TRD and TOF. - Provide TPC row-geometry evaluation with H, per-stack linear (L) and O2 propagator (K) methods. - Calculate crossed, dead, guard-excluded and available TPC rows, geometrical lengths and 152-row classification masks. - Support configurable sector-edge guards and acceptance limits. - Provide reduced-primary compatibility adapters. - Use H/K as references for validating the accuracy of fast L. Portable tests: - conftest.py: ROOT/PyROOT setup for standalone O2 testing. - test_full_state_radius.py: full-track state-at-radius checks. - test_sector_rows_primary_baseline.py: TPC row baseline checks. - README_TESTS.md: portable test execution instructions. The implementation enables configurable geometrical selections to study shortened tracks and their impact on tracking and PID. This commit does not include the main README, physics figure, O2 CMake registration or the extended full-state TPC test suite. Those are handled separately. Numerical performance and remaining physics-validation issues are tracked in the project CRR. --- Common/TrackTools/include/TrackGeometry.h | 1433 +++++++++++++++++ Common/TrackTools/test/README_TESTS.md | 27 + Common/TrackTools/test/python/conftest.py | 26 + .../test/python/test_full_state_radius.py | 74 + .../test_sector_rows_primary_baseline.py | 79 + 5 files changed, 1639 insertions(+) create mode 100644 Common/TrackTools/include/TrackGeometry.h create mode 100644 Common/TrackTools/test/README_TESTS.md create mode 100644 Common/TrackTools/test/python/conftest.py create mode 100644 Common/TrackTools/test/python/test_full_state_radius.py create mode 100644 Common/TrackTools/test/python/test_sector_rows_primary_baseline.py diff --git a/Common/TrackTools/include/TrackGeometry.h b/Common/TrackTools/include/TrackGeometry.h new file mode 100644 index 0000000000000..cff11da476a14 --- /dev/null +++ b/Common/TrackTools/include/TrackGeometry.h @@ -0,0 +1,1433 @@ +#pragma once + +/** + * @file TrackGeometry.h + * @brief Lightweight O2 track-geometry helpers for propagation to cylindrical radii and TPC row/sector-edge accounting. + * + * The header provides two related layers: + * + * 1. `o2::recohelpers` + * - propagation of an `o2::track::TrackPar` to a cylindrical radius; + * - H: fast analytic helix transport in a uniform Bz field; + * - K0: O2 `TrackPar` parameter propagation in Bz, without material correction; + * - derived global position/momentum, position azimuth, momentum azimuth, tan(lambda), and fractional sector position; + * - scalar and batch interfaces for primary-like and local O2 track parameters. + * + * 2. `o2::tpc::recohelpers` + * - TPC row sampling geometry from `o2::tpc::Mapper` (F6 centre correction pending); + * - H: analytic-helix row traversal; + * - L: stack-local linear approximation derived from helix endpoints; + * - K: O2 `Propagator` row traversal with `MatCorrType::USEMatCorrNONE`; + * - row counts, approximate track lengths, and 152-row masks for Crossed, Dead, Excluded, and Available rows; + * - configurable longitudinal, local-inclination, and active-pad-edge guard acceptance. + * + * The TPC classification currently samples the Mapper's inner-row reference radius (F6: pad-centre correction pending). + * `Dead` is defined by the physical Mapper active-pad boundary, while + * `Excluded` is the additional configurable guard measured inward from that active-pad edge. The nominal 20-degree + * sector boundary is not the guard reference. + * + * This header is intentionally self-contained and header-only so the same definitions can be used from compiled O2 + * code and from PyROOT/commissioning wrappers. + * + * @par Propagation hierarchy and implementation status + * + * The frozen TrackGeometry design distinguishes the following transport levels: + * + * - **H** — analytic helix, constant signed Bz, no material. + * Implemented for the generic state-at-radius API and for TPC row traversal. + * - **L** — stack-local linear approximation. + * Implemented for the TPC row/length approximation path only. + * - **K0** — O2 `TrackPar` / TrackParametrization, constant signed Bz, no material. + * Implemented for the generic state-at-radius API. + * - **K1** — O2 `Propagator`, initialized O2 magnetic-field machinery, material OFF. + * The current TPC row evaluator named **K** already uses `Propagator` with + * `MatCorrType::USEMatCorrNONE` and therefore exercises the K1 transport ingredients for this bounded TPC-row use + * case. The common generic K0/K1/K2 state-at-radius dispatch and final public K1 naming are **not yet implemented**. + * - **K2** — O2 `Propagator`, initialized O2 magnetic-field machinery, material ON. + * **Not yet implemented.** The production material mode and material-map initialization must be explicitly verified + * during K2 commissioning before this mode is exposed. + * + * The intended diagnostic decomposition is: + * `H-K0` = implementation/convention closure, + * `K1-K0` = realistic-field/Propagator effect, + * `K2-K1` = material effect. + * + * Planned functionality is documented here deliberately so that the public contract is visible before implementation; + * planned modes must not be presented by wrappers as available until the corresponding C++ path and validation exist. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CommonConstants/MathConstants.h" +#include "MathUtils/Utils.h" +#include "ReconstructionDataFormats/Track.h" +#include "TPCBase/Mapper.h" +#include "DetectorsBase/Propagator.h" + + +namespace o2::recohelpers +{ + +/** @brief Status returned by the cylindrical-radius track-parameter evaluators. */ +enum class TrackParametersStatus : int32_t { + OK = 0, + InvalidInput = 1, + UnreachableRadius = 2, + WrongDirection = 3, + PropagationFailed = 4, + MomentumInvalid = 5 +}; + +/** @brief Global track state evaluated at a requested cylindrical radius. + * + * Invalid components remain NaN. `valid()` is true only for `TrackParametersStatus::OK`. + */ +struct TrackParametersAtRadius { + float gx = std::numeric_limits::quiet_NaN(); + float gy = std::numeric_limits::quiet_NaN(); + float gz = std::numeric_limits::quiet_NaN(); + float px = std::numeric_limits::quiet_NaN(); + float py = std::numeric_limits::quiet_NaN(); + float pz = std::numeric_limits::quiet_NaN(); + TrackParametersStatus status = TrackParametersStatus::InvalidInput; + + bool valid() const { return status == TrackParametersStatus::OK; } +}; + +/** @brief Global azimuth of the propagated position, atan2(y,x), or NaN for an invalid state. */ +inline float statePhiPos(const TrackParametersAtRadius& state) +{ + return state.valid() ? std::atan2(state.gy, state.gx) : std::numeric_limits::quiet_NaN(); +} + +/** @brief Global azimuth of the propagated momentum, atan2(py,px), or NaN for an invalid state. */ +inline float statePhiMom(const TrackParametersAtRadius& state) +{ + return state.valid() ? std::atan2(state.py, state.px) : std::numeric_limits::quiet_NaN(); +} + +/** @brief tan(lambda)=pz/pT of the propagated state, or NaN for an invalid state. */ +inline float stateTgl(const TrackParametersAtRadius& state) +{ + if (!state.valid()) { + return std::numeric_limits::quiet_NaN(); + } + const float pt = std::hypot(state.px, state.py); + return pt > 0.f ? state.pz / pt : std::numeric_limits::quiet_NaN(); +} + +/** @brief Fractional azimuthal position inside a periodic sector pattern. + * + * @param phi Global azimuth [rad]. + * @param nSectors Number of equal azimuthal sectors. + * @param sectorPhaseRad Azimuth corresponding to fractional sector coordinate 0. + * @return Fractional sector coordinate in [0,1), or NaN for invalid input. + * + * This is a periodic coordinate, not a metric distance to the physical active-pad edge. + */ +inline float dSector(float phi, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + if (!std::isfinite(phi) || !std::isfinite(sectorPhaseRad) || nSectors <= 0) { + return std::numeric_limits::quiet_NaN(); + } + const float x = 0.5f * nSectors * (phi - sectorPhaseRad) / o2::constants::math::PI; + const float phase = x - std::floor(x); + return phase < 1.f ? phase : 0.f; +} + +/** @brief `dSector()` evaluated from the propagated global position azimuth. */ +inline float stateDSector(const TrackParametersAtRadius& state, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + return dSector(statePhiPos(state), nSectors, sectorPhaseRad); +} + +/** @brief Build an O2 `TrackPar` from a reduced primary-like state. + * + * @param phi Momentum azimuth at the supplied vertex [rad]. + * @param tgl tan(lambda). + * @param qpt Signed q/pT [(GeV/c)^-1]. + * @param vx,vy,vz Vertex coordinates [cm]. + * + * The transverse momentum magnitude is reconstructed as 1/|qpt| and the charge sign from qpt. + */ +inline o2::track::TrackPar makeTrackParFromPrimaryApproximation(float phi, float tgl, float qpt, + float vx = 0.f, float vy = 0.f, float vz = 0.f) +{ + const float pt = 1.f / std::abs(qpt); + const int charge = qpt >= 0.f ? 1 : -1; + o2::track::TrackPar::dim3_t xyz{{vx, vy, vz}}; + o2::track::TrackPar::dim3_t pxyz{{pt * std::cos(phi), pt * std::sin(phi), pt * tgl}}; + return o2::track::TrackPar(xyz, pxyz, charge, false); +} + +/// Backward-compatible reduced-primary constructor used by existing commissioning code. +inline o2::track::TrackPar makePrimaryTrackPar(float phi, float tgl, float qpt, float vz = 0.f) +{ + return makeTrackParFromPrimaryApproximation(phi, tgl, qpt, 0.f, 0.f, vz); +} + +/** @brief Extract finite global position and momentum from an O2 `TrackPar`. */ +inline bool extractGlobalState(const o2::track::TrackPar& track, + o2::track::TrackPar::dim3_t& xyz, + o2::track::TrackPar::dim3_t& pxyz) +{ + track.getXYZGlo(xyz); + if (!track.getPxPyPzGlo(pxyz)) { + return false; + } + for (int i = 0; i < 3; ++i) { + if (!std::isfinite(xyz[i]) || !std::isfinite(pxyz[i])) { + return false; + } + } + return true; +} + +/** @brief Check whether the radial derivative is compatible with the requested propagation direction. */ +inline bool directionMatches(o2::track::DirType dir, float drds) +{ + constexpr float eps = 1.e-6f; + if (dir == o2::track::DirType::DirOutward) { + return drds >= -eps; + } + if (dir == o2::track::DirType::DirInward) { + return drds <= eps; + } + return true; +} + +/** @brief H transport: analytic helix intersection with a cylindrical radius in uniform Bz. + * + * The implementation solves the transverse circle/circle intersection analytically, selects the first solution + * compatible with the requested direction, and transports z with the constant input tan(lambda). Double precision is + * used internally for the geometric construction, while the public state remains float. + * + * @param track Input O2 track parameters. + * @param radius Target cylindrical radius [cm]. + * @param bzKG Uniform Bz field in O2 kG convention. + * @param dir Required radial propagation direction. + * @return Global state and status at the requested radius. + */ +inline TrackParametersAtRadius getParametersAtRadiusH(const o2::track::TrackPar& track, float radius, float bzKG, + o2::track::DirType dir = o2::track::DirType::DirOutward) +{ + TrackParametersAtRadius out; + if (!(radius > 0.f) || !std::isfinite(radius) || !std::isfinite(bzKG) || !track.isValid()) { + out.status = TrackParametersStatus::InvalidInput; + return out; + } + + o2::track::TrackPar::dim3_t xyz{}, pxyz{}; + if (!extractGlobalState(track, xyz, pxyz)) { + out.status = TrackParametersStatus::MomentumInvalid; + return out; + } + + // Use double precision for the analytic construction even though TrackPar and + // the public result are float-based. For high-pT tracks the circle centre is + // O(1/curvature) away while the requested detector radius is O(10^2 cm). + // Performing the circle/circle intersection in float loses several microrad + // through cancellation. K0 is therefore the numerical oracle for the final + // float state, while H keeps the fast analytic transport. + const double x0 = static_cast(xyz[0]); + const double y0 = static_cast(xyz[1]); + const double z0 = static_cast(xyz[2]); + const double px0 = static_cast(pxyz[0]); + const double py0 = static_cast(pxyz[1]); + const double pz0 = static_cast(pxyz[2]); + const double targetR = static_cast(radius); + const double pt = std::hypot(px0, py0); + if (!(pt > 0.) || !std::isfinite(pt)) { + out.status = TrackParametersStatus::MomentumInvalid; + return out; + } + + const double phi0 = std::atan2(py0, px0); + const double tgl = pz0 / pt; + const double curv = static_cast(track.getQ2Pt()) * + static_cast(bzKG) * + static_cast(o2::constants::math::B2C); + constexpr double eps = 1.e-10; + constexpr double curvEps = 1.e-12; + const double twoPi = 2.0 * static_cast(o2::constants::math::PI); + + bool foundAny = false; + bool foundDirection = false; + double bestSxy = std::numeric_limits::infinity(); + double bestX = 0., bestY = 0., bestPhiMom = 0.; + + auto directionMatchesD = [&](double drds) { + constexpr double dirEps = 1.e-10; + if (dir == o2::track::DirType::DirOutward) { + return drds >= -dirEps; + } + if (dir == o2::track::DirType::DirInward) { + return drds <= dirEps; + } + return true; + }; + + auto consider = [&](double x, double y, double phiMom, double sxy) { + if (!std::isfinite(sxy) || sxy < -eps) { + return; + } + foundAny = true; + sxy = std::max(0.0, sxy); + const double drds = (x * std::cos(phiMom) + y * std::sin(phiMom)) / targetR; + if (!directionMatchesD(drds)) { + return; + } + foundDirection = true; + if (sxy < bestSxy) { + bestSxy = sxy; + bestX = x; + bestY = y; + bestPhiMom = phiMom; + } + }; + + if (std::abs(curv) < curvEps) { + const double ux = px0 / pt, uy = py0 / pt; + const double b = x0 * ux + y0 * uy; + const double c = x0 * x0 + y0 * y0 - targetR * targetR; + double disc = b * b - c; + if (disc < -eps) { + out.status = TrackParametersStatus::UnreachableRadius; + return out; + } + disc = std::max(0.0, disc); + const double root = std::sqrt(disc); + for (const double sxy : {-b - root, -b + root}) { + consider(x0 + sxy * ux, y0 + sxy * uy, phi0, sxy); + } + } else { + const double xc = x0 - std::sin(phi0) / curv; + const double yc = y0 + std::cos(phi0) / curv; + const double rho = 1.0 / std::abs(curv); + const double d = std::hypot(xc, yc); + if (!(d > eps) || d > targetR + rho + eps || d < std::abs(targetR - rho) - eps) { + out.status = TrackParametersStatus::UnreachableRadius; + return out; + } + + const double a = (targetR * targetR - rho * rho + d * d) / (2.0 * d); + double h2 = targetR * targetR - a * a; + if (h2 < -eps) { + out.status = TrackParametersStatus::UnreachableRadius; + return out; + } + h2 = std::max(0.0, h2); + const double h = std::sqrt(h2); + const double bx = a * xc / d, by = a * yc / d; + const double ox = -yc * h / d, oy = xc * h / d; + + const std::array, 2> intersections{{ + {{bx + ox, by + oy}}, + {{bx - ox, by - oy}} + }}; + for (const auto& xy : intersections) { + const double x = xy[0], y = xy[1]; + double sinPhi = curv * (x - xc); + double cosPhi = -curv * (y - yc); + const double norm = std::hypot(sinPhi, cosPhi); + if (!(norm > 0.) || !std::isfinite(norm)) { + continue; + } + sinPhi /= norm; + cosPhi /= norm; + const double phiMom = std::atan2(sinPhi, cosPhi); + double delta = phiMom - phi0; + if (curv > 0.) { + while (delta < -eps) { + delta += twoPi; + } + } else { + while (delta > eps) { + delta -= twoPi; + } + } + consider(x, y, phiMom, delta / curv); + } + } + + if (!foundDirection || !std::isfinite(bestSxy)) { + out.status = foundAny ? TrackParametersStatus::WrongDirection : TrackParametersStatus::UnreachableRadius; + return out; + } + + out.gx = static_cast(bestX); + out.gy = static_cast(bestY); + out.gz = static_cast(z0 + bestSxy * tgl); + out.px = static_cast(pt * std::cos(bestPhiMom)); + out.py = static_cast(pt * std::sin(bestPhiMom)); + out.pz = static_cast(pz0); + out.status = TrackParametersStatus::OK; + return out; +} + +/** @brief K0 transport: O2 `TrackPar` propagation to a cylindrical radius in Bz, without material correction. + * + * `getXatLabR()` locates the local-x target corresponding to the requested laboratory radius and + * `propagateParamTo()` performs the O2 parameter transport. A state is reported as OK only when its final global + * radius agrees with the requested cylinder within 2e-3 cm; an off-radius one-step result is PropagationFailed. + * This path is used as an independent O2 transport reference for the fast analytic H implementation. + * + * @param track Input O2 track parameters. + * @param radius Target cylindrical radius [cm]. + * @param bzKG Bz field in O2 kG convention. + * @param dir Required radial propagation direction. + * @return Global state and status at the requested radius. + */ +inline TrackParametersAtRadius getParametersAtRadiusK0(const o2::track::TrackPar& track, float radius, float bzKG, + o2::track::DirType dir = o2::track::DirType::DirOutward) +{ + TrackParametersAtRadius out; + if (!(radius > 0.f) || !std::isfinite(radius) || !std::isfinite(bzKG) || !track.isValid()) { + out.status = TrackParametersStatus::InvalidInput; + return out; + } + + float xAtR = 0.f; + if (!track.getXatLabR(radius, xAtR, bzKG, dir)) { + out.status = TrackParametersStatus::UnreachableRadius; + return out; + } + + auto propagated = track; + if (!propagated.propagateParamTo(xAtR, bzKG)) { + out.status = TrackParametersStatus::PropagationFailed; + return out; + } + + o2::track::TrackPar::dim3_t xyz{}, pxyz{}; + if (!extractGlobalState(propagated, xyz, pxyz)) { + out.status = TrackParametersStatus::MomentumInvalid; + return out; + } + + // A successful internal TrackPar update is not sufficient: the returned + // global state must actually lie on the requested cylinder (Architect A5). + constexpr float radiusToleranceCm = 2.e-3f; + const float resultRadius = std::hypot(xyz[0], xyz[1]); + if (!std::isfinite(resultRadius) || std::abs(resultRadius - radius) > radiusToleranceCm) { + out.status = TrackParametersStatus::PropagationFailed; + return out; + } + + out.gx = xyz[0]; + out.gy = xyz[1]; + out.gz = xyz[2]; + out.px = pxyz[0]; + out.py = pxyz[1]; + out.pz = pxyz[2]; + out.status = TrackParametersStatus::OK; + return out; +} + +/** @brief Backward-compatible scalar wrapper returning only the propagated position azimuth using K0. */ +inline float phiAtRadius(const o2::track::TrackPar& track, float radius, float bzKG, + o2::track::DirType dir = o2::track::DirType::DirOutward) +{ + return statePhiPos(getParametersAtRadiusK0(track, radius, bzKG, dir)); +} + +/** @brief Backward-compatible scalar wrapper returning only the propagated fractional sector coordinate using K0. */ +inline float dSectorAtRadius(const o2::track::TrackPar& track, float radius, float bzKG, int nSectors = 18, + o2::track::DirType dir = o2::track::DirType::DirOutward, float sectorPhaseRad = 0.f) +{ + return stateDSector(getParametersAtRadiusK0(track, radius, bzKG, dir), nSectors, sectorPhaseRad); +} + +/** @brief Position azimuth at radius for the reduced primary-like parameterization, evaluated with K0. */ +inline float primaryPhiAtRadius(float phi, float tgl, float qpt, float radius, float bzKG, float vz = 0.f) +{ + if (!std::isfinite(phi) || !std::isfinite(tgl) || !std::isfinite(qpt) || std::abs(qpt) < 1.e-12f) { + return std::numeric_limits::quiet_NaN(); + } + return phiAtRadius(makePrimaryTrackPar(phi, tgl, qpt, vz), radius, bzKG, o2::track::DirType::DirOutward); +} + +/** @brief Fractional sector coordinate at radius for the reduced primary-like parameterization, evaluated with K0. */ +inline float primaryDSectorAtRadius(float phi, float tgl, float qpt, float radius, float bzKG, + int nSectors = 18, float vz = 0.f, float sectorPhaseRad = 0.f) +{ + const float phiR = primaryPhiAtRadius(phi, tgl, qpt, radius, bzKG, vz); + return dSector(phiR, nSectors, sectorPhaseRad); +} + +/** @brief Structure-of-arrays result for batch cylindrical-radius propagation. + * + * Besides the global position/momentum, the batch result stores commonly used derived observables and one status value + * per input track. + */ +struct TrackParametersAtRadiusBatchResult { + std::vector gx, gy, gz, px, py, pz; + std::vector phiPos, phiMom, tgl, dSector; + std::vector status; + + void resize(std::size_t n) + { + gx.resize(n); gy.resize(n); gz.resize(n); + px.resize(n); py.resize(n); pz.resize(n); + phiPos.resize(n); phiMom.resize(n); tgl.resize(n); dSector.resize(n); + status.resize(n); + } + + void set(std::size_t i, const TrackParametersAtRadius& state, int nSectors, float sectorPhaseRad) + { + gx[i] = state.gx; gy[i] = state.gy; gz[i] = state.gz; + px[i] = state.px; py[i] = state.py; pz[i] = state.pz; + phiPos[i] = statePhiPos(state); + phiMom[i] = statePhiMom(state); + tgl[i] = stateTgl(state); + dSector[i] = stateDSector(state, nSectors, sectorPhaseRad); + status[i] = static_cast(state.status); + } +}; + +template +inline TrackParametersAtRadiusBatchResult primaryTrackParametersAtRadiusBatch( + const float* phi, const float* tgl, const float* qpt, + const float* vx, const float* vy, const float* vz, + std::size_t n, float radius, float bzKG, int nSectors, float sectorPhaseRad, Evaluator&& evaluate) +{ + TrackParametersAtRadiusBatchResult out; + out.resize(n); + for (std::size_t i = 0; i < n; ++i) { + if (!phi || !tgl || !qpt || !std::isfinite(qpt[i]) || std::abs(qpt[i]) < 1.e-12f) { + TrackParametersAtRadius invalid; + invalid.status = TrackParametersStatus::InvalidInput; + out.set(i, invalid, nSectors, sectorPhaseRad); + continue; + } + const auto track = makeTrackParFromPrimaryApproximation(phi[i], tgl[i], qpt[i], + vx ? vx[i] : 0.f, + vy ? vy[i] : 0.f, + vz ? vz[i] : 0.f); + out.set(i, evaluate(track, radius, bzKG), nSectors, sectorPhaseRad); + } + return out; +} + +/** @brief Batch H transport for reduced primary-like inputs. */ +inline TrackParametersAtRadiusBatchResult primaryTrackParametersAtRadiusHBatch( + const float* phi, const float* tgl, const float* qpt, + const float* vx, const float* vy, const float* vz, + std::size_t n, float radius, float bzKG, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + return primaryTrackParametersAtRadiusBatch( + phi, tgl, qpt, vx, vy, vz, n, radius, bzKG, nSectors, sectorPhaseRad, + [](const o2::track::TrackPar& track, float r, float bz) { + return getParametersAtRadiusH(track, r, bz, o2::track::DirType::DirOutward); + }); +} + +/** @brief Batch K0 transport for reduced primary-like inputs. */ +inline TrackParametersAtRadiusBatchResult primaryTrackParametersAtRadiusK0Batch( + const float* phi, const float* tgl, const float* qpt, + const float* vx, const float* vy, const float* vz, + std::size_t n, float radius, float bzKG, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + return primaryTrackParametersAtRadiusBatch( + phi, tgl, qpt, vx, vy, vz, n, radius, bzKG, nSectors, sectorPhaseRad, + [](const o2::track::TrackPar& track, float r, float bz) { + return getParametersAtRadiusK0(track, r, bz, o2::track::DirType::DirOutward); + }); +} + +/** @brief Build an O2 `TrackPar` from the standard local O2 track parameterization. */ +inline o2::track::TrackPar makeTrackParFromLocalParameters(float x, float alpha, float y, float z, + float snp, float tgl, float qpt, int absCharge = 1) +{ + o2::track::TrackPar::params_t par{{y, z, snp, tgl, qpt}}; + return o2::track::TrackPar(x, alpha, par, std::max(1, std::abs(absCharge))); +} + +template +inline TrackParametersAtRadiusBatchResult localTrackParametersAtRadiusBatch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float radius, float bzKG, int nSectors, float sectorPhaseRad, Evaluator&& evaluate) +{ + TrackParametersAtRadiusBatchResult out; + out.resize(n); + for (std::size_t i = 0; i < n; ++i) { + if (!x || !alpha || !y || !z || !snp || !tgl || !qpt) { + TrackParametersAtRadius invalid; + invalid.status = TrackParametersStatus::InvalidInput; + out.set(i, invalid, nSectors, sectorPhaseRad); + continue; + } + const auto track = makeTrackParFromLocalParameters(x[i], alpha[i], y[i], z[i], snp[i], tgl[i], qpt[i]); + out.set(i, evaluate(track, radius, bzKG), nSectors, sectorPhaseRad); + } + return out; +} + +/** @brief Batch H transport for tracks supplied in local O2 parameterization. */ +inline TrackParametersAtRadiusBatchResult localTrackParametersAtRadiusHBatch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float radius, float bzKG, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + return localTrackParametersAtRadiusBatch( + x, alpha, y, z, snp, tgl, qpt, n, radius, bzKG, nSectors, sectorPhaseRad, + [](const o2::track::TrackPar& track, float r, float bz) { + return getParametersAtRadiusH(track, r, bz, o2::track::DirType::DirOutward); + }); +} + +/** @brief Batch K0 transport for tracks supplied in local O2 parameterization. */ +inline TrackParametersAtRadiusBatchResult localTrackParametersAtRadiusK0Batch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float radius, float bzKG, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + return localTrackParametersAtRadiusBatch( + x, alpha, y, z, snp, tgl, qpt, n, radius, bzKG, nSectors, sectorPhaseRad, + [](const o2::track::TrackPar& track, float r, float bz) { + return getParametersAtRadiusK0(track, r, bz, o2::track::DirType::DirOutward); + }); +} + +/// Backward-compatible batch wrappers retained for existing commissioning notebooks/tests. +inline std::vector primaryPhiAtRadiusBatch(const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float radius, float bzKG) +{ + auto batch = primaryTrackParametersAtRadiusK0Batch(phi, tgl, qpt, nullptr, nullptr, vz, n, radius, bzKG); + return std::move(batch.phiPos); +} + +inline std::vector primaryDSectorAtRadiusBatch(const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float radius, float bzKG, int nSectors = 18, + float sectorPhaseRad = 0.f) +{ + auto batch = primaryTrackParametersAtRadiusK0Batch(phi, tgl, qpt, nullptr, nullptr, vz, n, radius, bzKG, + nSectors, sectorPhaseRad); + return std::move(batch.dSector); +} + +/** @brief Legacy compact batch result containing only position azimuth and fractional sector coordinate. */ +struct PrimaryTrackGeometryBatchResult { + std::vector phi; + std::vector dSector; +}; + +inline PrimaryTrackGeometryBatchResult primaryTrackGeometryAtRadiusBatch( + const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float radius, float bzKG, int nSectors = 18, float sectorPhaseRad = 0.f) +{ + auto batch = primaryTrackParametersAtRadiusK0Batch(phi, tgl, qpt, nullptr, nullptr, vz, n, radius, bzKG, + nSectors, sectorPhaseRad); + return {std::move(batch.phiPos), std::move(batch.dSector)}; +} + +} // namespace o2::recohelpers + +namespace o2::tpc::recohelpers +{ + +/** + * @name TPC row and sector-edge accounting + * + * These helpers evaluate the first outward TPC trajectory branch at sampled Mapper row radii and classify every accepted + * crossed row using the physical active-pad edge plus an optional inward guard. + */ +///@{ + +/** @brief Status returned by the TPC row/sector-edge evaluators. */ +enum class SectorEdgeStatus : int32_t { + OK = 0, + InvalidInput = 1, + NoRowsCrossed = 2, + PropagationFailed = 3, + FieldNotInitialized = 4 +}; + +/** @brief Reduced primary-track seed used by the TPC row evaluators. + * + * The seed assumes x=y=0 at the primary vertex. Bz follows the O2 kG convention. + */ +struct TPCPrimaryTrackSeed { + float phi = 0.f; // momentum azimuth at the primary vertex [rad] + float tgl = 0.f; // tan(lambda) + float qpt = 0.f; // signed q/pT [(GeV/c)^-1] + float vz = 0.f; // primary vertex z [cm] + float bzKG = std::numeric_limits::quiet_NaN(); // signed O2 field convention [kG]; must be supplied +}; + +/** @brief Configuration for TPC row acceptance and sector-edge classification. + * + * A row is `Crossed` only when its row-centre cylindrical surface is reached on the first outward trajectory branch and + * the propagated state satisfies: + * - |z| <= `zMaxCm`; + * - |snp| < `maxSnp`. + * + * The row-reachability limit uses radial-frame `snp = sin(phiMom-phiPos)` from global position/momentum + * azimuths. This is invariant under O2 tracking-frame rotation; the Mapper sector frame remains in use only + * for local-y active-pad-edge classification. + * Rows outside this acceptance are not Crossed and therefore are not Dead, Excluded, or Available. + * + * Every Crossed row belongs to exactly one of three mutually exclusive classes: + * - `Dead`: row-centre position lies outside the Mapper active-pad boundary; independent of guard width. + * - `Excluded`: position is inside the active-pad boundary but closer than the configured guard to that boundary. + * - `Available`: neither Dead nor Excluded. + * + * Therefore, independently for row counts, masks, and approximate lengths: + * `Crossed = Dead + Excluded + Available`. + * + * `guardLowerCm` and `guardUpperCm` are measured inward from the physical active-pad edge on the negative and positive + * local-y sides respectively. They are not measured from the nominal 20-degree sector boundary. + */ +struct TPCSectorEdgeConfig { + float guardLowerCm = 0.f; // active-side exclusion adjacent to negative local-y edge + float guardUpperCm = 0.f; // active-side exclusion adjacent to positive local-y edge + float zMaxCm = 250.f; // symmetric TPC longitudinal acceptance |z| <= zMaxCm + float maxSnp = 0.9f; // radial-frame |sin(phiMom-phiPos)| < maxSnp; not O2 TrackPar::getSnp() +}; + +/** @brief Result of one TPC row/sector-edge evaluation. + * + * `nRows*` count accepted row-centre intersections. `length*Cm` accumulates the corresponding approximate track length + * as radial row thickness multiplied by ds/dr. The four 152-row masks deliberately retain redundant information so the + * partition identity can be checked directly. + * + * `maxRadiusCm` is the radius of the last accepted sampled row; NaN if none. It is not the continuous + * mathematical turning radius of a helix and is not a propagation-failure sentinel. + * `firstDeadRow` and `lastDeadRow` delimit the first/last crossed rows classified outside the active-pad boundary; + * they remain -1 when no Dead row is found. + */ +struct TPCSectorEdgeResult { + float lengthCrossedCm = 0.f; + float lengthDeadCm = 0.f; + float lengthExcludedCm = 0.f; + float lengthAvailableCm = 0.f; + float maxRadiusCm = std::numeric_limits::quiet_NaN(); // last accepted row radius [cm], not turning radius + + uint16_t nRowsCrossed = 0; + uint16_t nRowsDead = 0; + uint16_t nRowsExcluded = 0; + uint16_t nRowsAvailable = 0; + + std::array crossedMask{}; + std::array deadMask{}; + std::array excludedMask{}; + std::array availableMask{}; + + int16_t firstDeadRow = -1; + int16_t lastDeadRow = -1; + SectorEdgeStatus status = SectorEdgeStatus::OK; +}; + + +/** @brief Structure-of-arrays batch result for the TPC row/sector-edge evaluators. + * + * The batch API exposes counts, approximate lengths, and status. Per-row masks remain available from the scalar API. + */ +struct TPCSectorEdgeBatchResult { + std::vector lengthCrossedCm; + std::vector lengthDeadCm; + std::vector lengthExcludedCm; + std::vector lengthAvailableCm; + std::vector maxRadiusCm; + + std::vector nRowsCrossed; + std::vector nRowsDead; + std::vector nRowsExcluded; + std::vector nRowsAvailable; + + std::vector status; + + void resize(std::size_t n) + { + lengthCrossedCm.resize(n); + lengthDeadCm.resize(n); + lengthExcludedCm.resize(n); + lengthAvailableCm.resize(n); + maxRadiusCm.resize(n); + nRowsCrossed.resize(n); + nRowsDead.resize(n); + nRowsExcluded.resize(n); + nRowsAvailable.resize(n); + status.resize(n); + } + + void set(std::size_t i, const TPCSectorEdgeResult& r) + { + lengthCrossedCm[i] = r.lengthCrossedCm; + lengthDeadCm[i] = r.lengthDeadCm; + lengthExcludedCm[i] = r.lengthExcludedCm; + lengthAvailableCm[i] = r.lengthAvailableCm; + maxRadiusCm[i] = r.maxRadiusCm; + nRowsCrossed[i] = static_cast(r.nRowsCrossed); + nRowsDead[i] = static_cast(r.nRowsDead); + nRowsExcluded[i] = static_cast(r.nRowsExcluded); + nRowsAvailable[i] = static_cast(r.nRowsAvailable); + status[i] = static_cast(r.status); + } +}; + +/** @brief Internal global trajectory sample at one TPC row-centre radius. */ +struct TrajectoryPoint { + float x = 0.f; + float y = 0.f; + float z = 0.f; + float phiPos = 0.f; + float phiMom = 0.f; + float dsDr = 0.f; + bool valid = false; +}; + +/** @brief Debug-only row state; trajectory[row] is the state at that sampled TPC row. + * Append even the first state rejected by maxSnp. With tracing disabled no momentum conversion is performed. + */ +inline void appendTrajectoryState(std::vector& trajectory, + const TrajectoryPoint& p, float qpt, float tgl) +{ + const float pt = 1.f / std::abs(qpt); + trajectory.push_back({p.x, p.y, p.z, pt * std::cos(p.phiMom), pt * std::sin(p.phiMom), + pt * tgl, o2::recohelpers::TrackParametersStatus::OK}); +} + +/** @brief Set one of the 152 TPC row bits in the five-word row mask. */ +inline void setMaskBit(std::array& mask, int row) +{ + mask[row >> 5] |= uint32_t(1) << (row & 31); +} + +/** @brief Return the Mapper pad-region index containing a global TPC row, or -1 if none. */ +inline int regionForRow(const o2::tpc::Mapper& mapper, int row) +{ + for (int i = 0; i < mapper.getNumberOfPadRegions(); ++i) { + const auto& r = mapper.getPadRegionInfo(i); + const int first = r.getGlobalRowOffset(), last = first + r.getNumberOfPadRows(); + if (row >= first && row < last) { + return i; + } + } + return -1; +} + +/** @brief Current sampled TPC row radius [cm]; F6 physical pad-centre correction remains pending. */ +inline float rowRadius(const o2::tpc::Mapper& mapper, int row) +{ + const int ireg = regionForRow(mapper, row); + if (ireg < 0) { + return std::numeric_limits::quiet_NaN(); + } + const auto& r = mapper.getPadRegionInfo(ireg); + return r.getRadiusFirstRow() + (row - r.getGlobalRowOffset()) * r.getPadHeight(); +} + +/** @brief Radial row thickness, taken from the Mapper pad height [cm]. */ +inline float rowLengthRadial(const o2::tpc::Mapper& mapper, int row) +{ + const int ireg = regionForRow(mapper, row); + return ireg < 0 ? 0.f : mapper.getPadRegionInfo(ireg).getPadHeight(); +} + +/** @brief Active half-width of one TPC row in local-y from Mapper pad count and pad width [cm]. */ +inline float rowActiveHalfWidth(const o2::tpc::Mapper& mapper, int row) +{ + const int ireg = regionForRow(mapper, row); + if (ireg < 0) { + return 0.f; + } + const auto& r = mapper.getPadRegionInfo(ireg); + return 0.5f * mapper.getNumberOfPadsInRowSector(row) * r.getPadWidth(); +} + +/** @brief Radial-frame sin(phiMom-phiPos); independent of the O2 TrackPar alpha rotation. + * + * This is the row-stopping convention ratified for PHASE_0_3. The Mapper sector-local + * inclination (phiMom-alphaSector) is distinct and does not control row reachability. + */ +inline float trajectoryRadialSnp(const TrajectoryPoint& p) +{ + if (!p.valid || !std::isfinite(p.x) || !std::isfinite(p.y) || !std::isfinite(p.phiMom)) { + return std::numeric_limits::quiet_NaN(); + } + return std::sin(p.phiMom - std::atan2(p.y, p.x)); +} + +/** @brief Backward-compatible internal spelling; use trajectoryRadialSnp for new code. */ +inline float trajectoryLocalSnp(const TrajectoryPoint& p) { return trajectoryRadialSnp(p); } + +/** @brief True when a valid row-centre trajectory point satisfies the configured z and snp acceptance. */ +inline bool rowWithinAcceptance(const TrajectoryPoint& p, const TPCSectorEdgeConfig& cfg) +{ + const float snp = trajectoryRadialSnp(p); + return p.valid && std::isfinite(p.z) && std::abs(p.z) <= cfg.zMaxCm && + std::isfinite(snp) && std::abs(snp) < cfg.maxSnp; +} + +/** @brief True when the radial-frame inclination reaches the configured stopping boundary. */ +inline bool reachedMaxSnp(const TrajectoryPoint& p, const TPCSectorEdgeConfig& cfg) +{ + const float snp = trajectoryRadialSnp(p); + return std::isfinite(snp) && std::abs(snp) >= cfg.maxSnp; +} + +/** @brief Validate the complete input state and report its global reference radius. + * An outward-only row query does not back-propagate to rows inside this radius. + */ +inline bool trackOutwardReference(const o2::track::TrackPar& track, float& radius) +{ + o2::track::TrackPar::dim3_t xyz{}, pxyz{}; + if (!track.isValid() || !o2::recohelpers::extractGlobalState(track, xyz, pxyz)) { + return false; + } + radius = std::hypot(xyz[0], xyz[1]); + if (!std::isfinite(radius) || !std::isfinite(track.getQ2Pt()) || + std::abs(track.getQ2Pt()) < 1.e-12f) { + return false; + } + // Negative radial motion at the supplied reference is not the first outward branch. + return radius < 1.e-5f || xyz[0] * pxyz[0] + xyz[1] * pxyz[1] >= 0.f; +} + +/** @brief One TPC row trajectory sample from a complete O2 local five-parameter track. */ +inline TrajectoryPoint helixAtRadius(const o2::track::TrackPar& track, float radius, float bzKG) +{ + TrajectoryPoint p; + if (!track.isValid() || !std::isfinite(bzKG) || !(radius > 0.f)) { + return p; + } + const auto state = o2::recohelpers::getParametersAtRadiusH( + track, radius, bzKG, o2::track::DirType::DirOutward); + if (!state.valid()) { + return p; + } + p.x = state.gx; + p.y = state.gy; + p.z = state.gz; + p.phiPos = o2::recohelpers::statePhiPos(state); + p.phiMom = o2::recohelpers::statePhiMom(state); + const float c = std::abs(std::cos(p.phiMom - p.phiPos)); + const float tgl = o2::recohelpers::stateTgl(state); + p.dsDr = std::sqrt(1.f + tgl * tgl) / std::max(c, 1.e-6f); + p.valid = std::isfinite(p.dsDr); + return p; +} + +/** @brief Legacy reduced-primary adapter to the same complete-track H implementation. */ +inline TrajectoryPoint primaryHelixAtRadius(const TPCPrimaryTrackSeed& seed, float radius) +{ + if (!std::isfinite(seed.phi) || !std::isfinite(seed.tgl) || !std::isfinite(seed.qpt) || + !std::isfinite(seed.bzKG) || std::abs(seed.qpt) < 1.e-12f) { + return {}; + } + return helixAtRadius(o2::recohelpers::makeTrackParFromPrimaryApproximation( + seed.phi, seed.tgl, seed.qpt, 0.f, 0.f, seed.vz), radius, seed.bzKG); +} + +/** @brief Apply acceptance and classify one crossed row as Dead, Excluded, or Available. + * + * The physical active-pad edge is `N_pads(row) * padWidth / 2` in sector-local y. A point outside that edge is Dead. + * Otherwise the side-dependent guard is measured inward from that edge; points inside the guard are Excluded and the + * remaining crossed rows are Available. + * + * This function updates row counts, approximate lengths, row masks, and first/last Dead row consistently. + */ +inline void accumulateRow(const o2::tpc::Mapper& mapper, int row, const TrajectoryPoint& p, float rowLength, + const TPCSectorEdgeConfig& cfg, TPCSectorEdgeResult& out) +{ + if (!rowWithinAcceptance(p, cfg) || !std::isfinite(rowLength) || rowLength <= 0.f) { + return; + } + + const float phi = std::atan2(p.y, p.x); + const int sector = o2::math_utils::angle2Sector(phi); + const float alpha = o2::math_utils::sector2Angle(sector); + const float localY = -p.x * std::sin(alpha) + p.y * std::cos(alpha); + const float halfWidth = rowActiveHalfWidth(mapper, row); + const float edgeDistance = halfWidth - std::abs(localY); + const float guard = localY < 0.f ? cfg.guardLowerCm : cfg.guardUpperCm; + + ++out.nRowsCrossed; + out.maxRadiusCm = rowRadius(mapper, row); + out.lengthCrossedCm += rowLength; + setMaskBit(out.crossedMask, row); + + if (edgeDistance < 0.f) { + ++out.nRowsDead; + out.lengthDeadCm += rowLength; + setMaskBit(out.deadMask, row); + if (out.firstDeadRow < 0) { + out.firstDeadRow = row; + } + out.lastDeadRow = row; + } else if (edgeDistance < guard) { + ++out.nRowsExcluded; + out.lengthExcludedCm += rowLength; + setMaskBit(out.excludedMask, row); + } else { + ++out.nRowsAvailable; + out.lengthAvailableCm += rowLength; + setMaskBit(out.availableMask, row); + } +} + +/** @brief H row evaluator: analytic helix sampled at the current Mapper row radii. + * + * Rows are processed from inner to outer radius. Evaluation stops when radial |snp| reaches `cfg.maxSnp`. + * The result uses the common Crossed/Dead/Excluded/Available classification in `accumulateRow()`. + */ +inline TPCSectorEdgeResult sectorEdgeHelixRows(const o2::track::TrackPar& track, float bzKG, const TPCSectorEdgeConfig& cfg = {}, + std::vector* trajectory = nullptr) +{ + TPCSectorEdgeResult out; + if (trajectory) { + trajectory->clear(); + } + float startRadius = 0.f; + if (!std::isfinite(bzKG) || !trackOutwardReference(track, startRadius)) { + out.status = SectorEdgeStatus::InvalidInput; + return out; + } + const auto& mapper = o2::tpc::Mapper::instance(); + + for (int row = 0; row < mapper.getNumberOfRows(); ++row) { + const float r = rowRadius(mapper, row); + if (r + 1.e-4f < startRadius) { + if (trajectory) { + trajectory->emplace_back(); // Preserve trajectory[row] indexing for skipped rows. + } + continue; // A full track can start inside the TPC; do not count earlier rows. + } + const auto p = helixAtRadius(track, r, bzKG); + if (!p.valid) { + break; // a larger radius cannot re-enter the first outward primary-helix branch + } + if (trajectory) { + appendTrajectoryState(*trajectory, p, track.getQ2Pt(), track.getTgl()); + } + if (reachedMaxSnp(p, cfg)) { + break; + } + accumulateRow(mapper, row, p, rowLengthRadial(mapper, row) * p.dsDr, cfg, out); + } + + if (!out.nRowsCrossed) { + out.status = SectorEdgeStatus::NoRowsCrossed; + } + return out; +} + +/** @brief Reduced-primary compatibility adapter: construct TrackPar and call the full H evaluator. */ +inline TPCSectorEdgeResult sectorEdgeHelixRows(const TPCPrimaryTrackSeed& seed, const TPCSectorEdgeConfig& cfg = {}, + std::vector* trajectory = nullptr) +{ + if (!std::isfinite(seed.phi) || !std::isfinite(seed.tgl) || !std::isfinite(seed.qpt) || + !std::isfinite(seed.bzKG) || std::abs(seed.qpt) < 1.e-12f) { + TPCSectorEdgeResult r; + r.status = SectorEdgeStatus::InvalidInput; + return r; + } + return sectorEdgeHelixRows(o2::recohelpers::makeTrackParFromPrimaryApproximation( + seed.phi, seed.tgl, seed.qpt, 0.f, 0.f, seed.vz), seed.bzKG, cfg, trajectory); +} + +/** @brief Conservative path-continuity guard against a later outward orbit. + * + * This is a gross-branch-rejection criterion, NOT an H/K numerical-agreement tolerance. + * The generous factor 10 avoids flagging near-boundary valid segments; a long detour + * around a curl cannot be accepted merely because its final radial direction is outward. + */ +inline bool plausibleFirstOutwardStep(float dr, float ds, float tgl, float maxSnp) +{ + if (!(dr > 0.f) || !(ds > 0.f) || !std::isfinite(ds) || !std::isfinite(tgl) || + !(maxSnp > 0.f && maxSnp < 1.f)) { + return false; + } + const float minRadialCos = std::sqrt(1.f - maxSnp * maxSnp); + return ds <= 10.f * dr * std::sqrt(1.f + tgl * tgl) / minRadialCos; +} + +/** @brief K row evaluator: O2 `Propagator` traversal of TPC row radii without material correction. + * + * The first eligible row is initialized from analytic H propagation of the supplied complete TrackPar, + * after which the O2 Propagator advances the track + * row by row with `MatCorrType::USEMatCorrNONE`. The radial-frame maxSnp stop and common row classification + * are applied independently of the Propagator's rotating internal tracking frame. + * Numerical propagation failures return `PropagationFailed`; a physical snp stop returns `OK` with the last + * accepted row reported in `maxRadiusCm`. + * + * The O2 magnetic field must already be initialized; otherwise `FieldNotInitialized` is returned. + */ +inline TPCSectorEdgeResult sectorEdgeO2PropagatorRows(const o2::track::TrackPar& inputTrack, float bzKG, + const TPCSectorEdgeConfig& cfg = {}, + std::vector* trajectory = nullptr) +{ + TPCSectorEdgeResult out; + if (trajectory) { + trajectory->clear(); + } + const auto& mapper = o2::tpc::Mapper::instance(); + auto* prop = o2::base::Propagator::Instance(); + if (!prop->hasMagFieldSet()) { + out.status = SectorEdgeStatus::FieldNotInitialized; + return out; + } + float startRadius = 0.f; + if (!std::isfinite(bzKG) || !trackOutwardReference(inputTrack, startRadius) || + !std::isfinite(cfg.maxSnp) || !(cfg.maxSnp > 0.f && cfg.maxSnp < 1.f)) { + out.status = SectorEdgeStatus::InvalidInput; + return out; + } + + int firstRow = 0; + while (firstRow < mapper.getNumberOfRows() && + rowRadius(mapper, firstRow) + 1.e-4f < startRadius) { + ++firstRow; + } + if (firstRow == mapper.getNumberOfRows()) { + out.status = SectorEdgeStatus::NoRowsCrossed; + return out; + } + const float r0 = rowRadius(mapper, firstRow); + if (trajectory) { + trajectory->resize(firstRow); // Keep diagnostic trace indexed by global TPC row. + } + // Preserve the reviewed K first-row seeding convention, but use the complete + // original track rather than reconstructing a primary vertex. K field-map + // transport from the original reference remains a separate physics-validation item. + const auto p0 = helixAtRadius(inputTrack, r0, bzKG); + if (!p0.valid) { + out.status = SectorEdgeStatus::NoRowsCrossed; + return out; + } + + const float qpt = inputTrack.getQ2Pt(); + const float pt = 1.f / std::abs(qpt); + const int charge = qpt >= 0.f ? 1 : -1; + o2::track::TrackPar::dim3_t xyz{{p0.x, p0.y, p0.z}}; + o2::track::TrackPar::dim3_t pxyz{{pt * std::cos(p0.phiMom), pt * std::sin(p0.phiMom), pt * inputTrack.getTgl()}}; + o2::track::TrackPar track(xyz, pxyz, charge, true); + o2::track::TrackLTIntegral path; + path.clear(); + path.setTimeNotNeeded(); + float previousPathCm = 0.f; + float previousRadiusCm = r0; + + for (int row = firstRow; row < mapper.getNumberOfRows(); ++row) { + const float radius = rowRadius(mapper, row); + if (row > firstRow) { + // Record accumulated transported path length. A later outward *orbit* can have positive dr/ds + // and lie on the requested cylinder; radialCos > 0 alone would accept that wrong branch. + // With radial |snp| < maxSnp, a first-branch step should be short relative to its radial + // increment. This deliberately generous guard only rejects gross discontinuities; numerical + // H/K row-mask agreement is checked separately by the physics oracle. + if (!prop->propagateToR(track, radius, false, o2::base::Propagator::MAX_SIN_PHI, + o2::base::Propagator::MAX_STEP, + o2::base::Propagator::MatCorrType::USEMatCorrNONE, &path)) { + out.status = SectorEdgeStatus::PropagationFailed; + return out; + } + const float deltaPathCm = path.getL() - previousPathCm; + const float deltaRadiusCm = radius - previousRadiusCm; + if (!plausibleFirstOutwardStep(deltaRadiusCm, deltaPathCm, track.getTgl(), cfg.maxSnp)) { + out.status = SectorEdgeStatus::PropagationFailed; + return out; + } + previousPathCm = path.getL(); + previousRadiusCm = radius; + } + + const auto xyzg = track.getXYZGlo(); + TrajectoryPoint p; + p.x = xyzg.X(); + p.y = xyzg.Y(); + p.z = xyzg.Z(); + p.phiPos = track.getPhiPos(); + p.phiMom = track.getPhi(); + const float dphi = p.phiMom - p.phiPos; + const float radialCos = std::cos(dphi); + // propagateToR() may return a state on a different branch or slightly off the target cylinder. + // Neither may contribute a crossed row. The radial-frame snp limit is checked independently below. + constexpr float radiusToleranceCm = 2.e-3f; + const float actualRadius = std::hypot(p.x, p.y); + if (!std::isfinite(actualRadius) || std::abs(actualRadius - radius) > radiusToleranceCm || + !std::isfinite(radialCos)) { + out.status = SectorEdgeStatus::PropagationFailed; + return out; + } + if (radialCos <= 0.f) { + break; // reached the transverse turning point or a returning arc + } + p.dsDr = std::sqrt(1.f + track.getTgl() * track.getTgl()) / radialCos; + p.valid = true; + if (trajectory) { + appendTrajectoryState(*trajectory, p, track.getQ2Pt(), track.getTgl()); + } + if (reachedMaxSnp(p, cfg)) { + break; + } + accumulateRow(mapper, row, p, rowLengthRadial(mapper, row) * p.dsDr, cfg, out); + } + + if (!out.nRowsCrossed && out.status == SectorEdgeStatus::OK) { + out.status = SectorEdgeStatus::NoRowsCrossed; + } + return out; +} + +/** @brief Reduced-primary compatibility adapter to complete-state K row evaluation. */ +inline TPCSectorEdgeResult sectorEdgeO2PropagatorRows(const TPCPrimaryTrackSeed& seed, + const TPCSectorEdgeConfig& cfg = {}, + std::vector* trajectory = nullptr) +{ + if (!std::isfinite(seed.phi) || !std::isfinite(seed.tgl) || !std::isfinite(seed.qpt) || + !std::isfinite(seed.bzKG) || std::abs(seed.qpt) < 1.e-12f) { + TPCSectorEdgeResult r; + r.status = SectorEdgeStatus::InvalidInput; + return r; + } + return sectorEdgeO2PropagatorRows(o2::recohelpers::makeTrackParFromPrimaryApproximation( + seed.phi, seed.tgl, seed.qpt, 0.f, 0.f, seed.vz), seed.bzKG, cfg, trajectory); +} + +/** @brief L row evaluator: stack-local linear approximation to the analytic helix. + * + * Rows with equal Mapper pad height are treated as one stack. Analytic H endpoints define linear interpolation in phi + * and z versus radius. If the nominal outer endpoint is unreachable or reaches maxSnp first, the last reachable row + * below maxSnp becomes the endpoint of a retained partial stack and the outward traversal stops after that stack. + * Row position, momentum direction, and ds/dr are then evaluated from the local approximation before classification. + */ +inline TPCSectorEdgeResult sectorEdgeStackLinear(const o2::track::TrackPar& track, float bzKG, const TPCSectorEdgeConfig& cfg = {}, + std::vector* trajectory = nullptr) +{ + TPCSectorEdgeResult out; + if (trajectory) { + trajectory->clear(); + } + float startRadius = 0.f; + if (!std::isfinite(bzKG) || !trackOutwardReference(track, startRadius)) { + out.status = SectorEdgeStatus::InvalidInput; + return out; + } + const auto& mapper = o2::tpc::Mapper::instance(); + + int first = 0; + while (first < mapper.getNumberOfRows()) { + const float h = rowLengthRadial(mapper, first); + int last = first; + while (last + 1 < mapper.getNumberOfRows() && std::abs(rowLengthRadial(mapper, last + 1) - h) < 1.e-6f) { + ++last; + } + + if (rowRadius(mapper, first) + 1.e-4f < startRadius) { + if (trajectory) { + trajectory->emplace_back(); // Preserve global row indexing. + } + ++first; // Ignore rows inside the complete track's reference radius. + continue; + } + const float r0 = rowRadius(mapper, first); + const auto p0 = helixAtRadius(track, r0, bzKG); + if (!p0.valid || reachedMaxSnp(p0, cfg)) { + break; + } + + // The frozen Linear contract keeps a reachable partial stack. If the nominal + // outer endpoint is unreachable or already beyond maxSnp, walk inward to the + // last reachable row below maxSnp and use that row as the interpolation endpoint. + int endpoint = last; + auto p1 = helixAtRadius(track, rowRadius(mapper, endpoint), bzKG); + bool stopAfterStack = false; + while (endpoint > first && (!p1.valid || reachedMaxSnp(p1, cfg))) { + --endpoint; + p1 = helixAtRadius(track, rowRadius(mapper, endpoint), bzKG); + stopAfterStack = true; + } + if (!p1.valid || reachedMaxSnp(p1, cfg)) { + break; + } + stopAfterStack = stopAfterStack || endpoint < last; + + const float r1 = rowRadius(mapper, endpoint); + float dphi = p1.phiPos - p0.phiPos; + o2::math_utils::detail::bringToPMPi(dphi); + const float dr = std::max(r1 - r0, 1.e-6f); + const float dphiDr = dphi / dr, dzDr = (p1.z - p0.z) / dr; + + for (int row = first; row <= endpoint; ++row) { + const float r = rowRadius(mapper, row), f = (r - r0) / dr; + const float phi = p0.phiPos + f * dphi; + TrajectoryPoint p; + p.x = r * std::cos(phi); + p.y = r * std::sin(phi); + p.z = p0.z + f * (p1.z - p0.z); + p.phiPos = phi; + p.phiMom = phi + std::atan(r * dphiDr); + p.dsDr = std::sqrt(1.f + (r * dphiDr) * (r * dphiDr) + dzDr * dzDr); + // When the limit leaves a single reachable row, finite-difference derivatives are undefined. + // Reuse the actual helix tangent and path length at that row rather than setting the slopes to zero. + if (endpoint == first) { + p.phiMom = p0.phiMom; + p.dsDr = p0.dsDr; + } + p.valid = true; + if (trajectory) { + appendTrajectoryState(*trajectory, p, track.getQ2Pt(), track.getTgl()); + } + if (reachedMaxSnp(p, cfg)) { + stopAfterStack = true; + break; + } + accumulateRow(mapper, row, p, rowLengthRadial(mapper, row) * p.dsDr, cfg, out); + } + + if (stopAfterStack) { + break; + } + first = last + 1; + } + + if (!out.nRowsCrossed) { + out.status = SectorEdgeStatus::NoRowsCrossed; + } + return out; +} + +/** @brief Reduced-primary compatibility adapter to complete-state L row evaluation. */ +inline TPCSectorEdgeResult sectorEdgeStackLinear(const TPCPrimaryTrackSeed& seed, const TPCSectorEdgeConfig& cfg = {}, + std::vector* trajectory = nullptr) +{ + if (!std::isfinite(seed.phi) || !std::isfinite(seed.tgl) || !std::isfinite(seed.qpt) || + !std::isfinite(seed.bzKG) || std::abs(seed.qpt) < 1.e-12f) { + TPCSectorEdgeResult r; + r.status = SectorEdgeStatus::InvalidInput; + return r; + } + return sectorEdgeStackLinear(o2::recohelpers::makeTrackParFromPrimaryApproximation( + seed.phi, seed.tgl, seed.qpt, 0.f, 0.f, seed.vz), seed.bzKG, cfg, trajectory); +} + +template +inline TPCSectorEdgeBatchResult sectorEdgeBatch(const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg, Evaluator&& evaluate) +{ + TPCSectorEdgeBatchResult out; + out.resize(n); + + if (!phi || !tgl || !qpt) { + for (std::size_t i = 0; i < n; ++i) { + TPCSectorEdgeResult r; + r.status = SectorEdgeStatus::InvalidInput; + out.set(i, r); + } + return out; + } + + for (std::size_t i = 0; i < n; ++i) { + TPCPrimaryTrackSeed seed; + seed.phi = phi[i]; + seed.tgl = tgl[i]; + seed.qpt = qpt[i]; + seed.vz = vz ? vz[i] : 0.f; + seed.bzKG = bzKG; + out.set(i, evaluate(seed, cfg)); + } + return out; +} + +/** @brief Batch wrapper for the analytic H TPC row evaluator. */ +inline TPCSectorEdgeBatchResult sectorEdgeHelixRowsBatch(const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg = {}) +{ + return sectorEdgeBatch(phi, tgl, qpt, vz, n, bzKG, cfg, + [](const TPCPrimaryTrackSeed& seed, const TPCSectorEdgeConfig& c) { return sectorEdgeHelixRows(seed, c); }); +} + +/** @brief Batch wrapper for the stack-linear L TPC row evaluator. */ +inline TPCSectorEdgeBatchResult sectorEdgeStackLinearBatch(const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg = {}) +{ + return sectorEdgeBatch(phi, tgl, qpt, vz, n, bzKG, cfg, + [](const TPCPrimaryTrackSeed& seed, const TPCSectorEdgeConfig& c) { return sectorEdgeStackLinear(seed, c); }); +} + +/** @brief Batch wrapper for the O2 Propagator K TPC row evaluator, without material correction. */ +inline TPCSectorEdgeBatchResult sectorEdgeO2PropagatorRowsBatch(const float* phi, const float* tgl, const float* qpt, const float* vz, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg = {}) +{ + return sectorEdgeBatch(phi, tgl, qpt, vz, n, bzKG, cfg, + [](const TPCPrimaryTrackSeed& seed, const TPCSectorEdgeConfig& c) { + return sectorEdgeO2PropagatorRows(seed, c); + }); +} + +/** @brief Evaluate row acceptance for a batch of complete O2 local 5D track states. + * Input arrays are x, alpha, y, z, snp, tgl, q/pT; all are mandatory. + * `absCharge=1` is currently used by the convenience constructor, as in the generic + * state-at-radius batch interface. For multi-charge tracks use the scalar TrackPar API. + */ +template +inline TPCSectorEdgeBatchResult localSectorEdgeBatch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg, Evaluator&& evaluate) +{ + TPCSectorEdgeBatchResult out; + out.resize(n); + for (std::size_t i = 0; i < n; ++i) { + if (!x || !alpha || !y || !z || !snp || !tgl || !qpt || + !std::isfinite(x[i]) || !std::isfinite(alpha[i]) || !std::isfinite(y[i]) || + !std::isfinite(z[i]) || !std::isfinite(snp[i]) || !std::isfinite(tgl[i]) || + !std::isfinite(qpt[i]) || std::abs(qpt[i]) < 1.e-12f || std::abs(snp[i]) >= 1.f) { + TPCSectorEdgeResult r; + r.status = SectorEdgeStatus::InvalidInput; + out.set(i, r); + continue; + } + const auto track = o2::recohelpers::makeTrackParFromLocalParameters( + x[i], alpha[i], y[i], z[i], snp[i], tgl[i], qpt[i]); + out.set(i, evaluate(track, bzKG, cfg)); + } + return out; +} + +inline TPCSectorEdgeBatchResult localSectorEdgeHelixRowsBatch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg = {}) +{ + return localSectorEdgeBatch(x, alpha, y, z, snp, tgl, qpt, n, bzKG, cfg, + [](const o2::track::TrackPar& t, float bz, const TPCSectorEdgeConfig& c) { + return sectorEdgeHelixRows(t, bz, c); + }); +} + +inline TPCSectorEdgeBatchResult localSectorEdgeStackLinearBatch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg = {}) +{ + return localSectorEdgeBatch(x, alpha, y, z, snp, tgl, qpt, n, bzKG, cfg, + [](const o2::track::TrackPar& t, float bz, const TPCSectorEdgeConfig& c) { + return sectorEdgeStackLinear(t, bz, c); + }); +} + +inline TPCSectorEdgeBatchResult localSectorEdgeO2PropagatorRowsBatch( + const float* x, const float* alpha, const float* y, const float* z, + const float* snp, const float* tgl, const float* qpt, + std::size_t n, float bzKG, const TPCSectorEdgeConfig& cfg = {}) +{ + return localSectorEdgeBatch(x, alpha, y, z, snp, tgl, qpt, n, bzKG, cfg, + [](const o2::track::TrackPar& t, float bz, const TPCSectorEdgeConfig& c) { + return sectorEdgeO2PropagatorRows(t, bz, c); + }); +} + +///@} + +} // namespace o2::tpc::recohelpers diff --git a/Common/TrackTools/test/README_TESTS.md b/Common/TrackTools/test/README_TESTS.md new file mode 100644 index 0000000000000..677f9addfbbf6 --- /dev/null +++ b/Common/TrackTools/test/README_TESTS.md @@ -0,0 +1,27 @@ +# O2 TrackTools — Step 0 portable PyROOT tests + +These tests execute the **existing** C++ `TrackGeometry.h` in a ROOT/O2 environment. They deliberately do not import `AliasDataFrame`, `dfdraw`, `gbregression`, or the development-repository `o2reco` package. Python dependencies: `pytest` and `ROOT` (PyROOT supplied by the matching O2/ROOT environment). + +Run from `O2/Common/TrackTools` after configuring the O2 environment: + +```sh +python -m pytest -q -ra test/python +``` + +If the source header is elsewhere, set `TRACKTOOLS_INCLUDE` to the directory containing the actual O2 header. The test fixture **fails** if ROOT or the header cannot be loaded; no environment failure is counted as PASS. + +Current cases: + +- Full 5D `TrackPar` scalar H/K0 reaches the requested radius and yields a defined `dSector`. +- **Nonprimary/displaced 5D H** at `Bz=0` is independently checked against an analytic straight-line/cylinder intersection at three radii, including an outer-TPC secondary. Detects silent resetting to a primary vertex. +- Signed field/charge, explicit field argument, invalid-radius status. +- Current **reduced-primary-only** TPC H/L row classification: 152-bit partition identities, guard monotonicity and basic Mapper cardinality. +- F6 physical row centre is an **expected failure (XFAIL)** pending the Mapper oracle and code fix; it is not treated as a successful geometry test. + +## Outstanding—not certified by Step 0 + +- Full 5D **TPC H/L/K** row/sector-edge API for displaced secondary tracks (not implemented in the reviewed source). This requires scalar, batch and Python/ADF tests in Step 1. +- K field-map / high-curvature regressions (six previous red cases); do not widen tolerances or convert them to PASS. +- Full 152-row Mapper pad-centre oracle, native C++ unit test, O2 CMake/CTest registration, real-data parity. + +**Never claim that these tests alone validate production secondary-track TPC geometry or all K propagation.** Record the current header SHA256, O2 commit, ROOT/O2 environment and full pytest transcript for the PR. diff --git a/Common/TrackTools/test/python/conftest.py b/Common/TrackTools/test/python/conftest.py new file mode 100644 index 0000000000000..461fd0fc3ce01 --- /dev/null +++ b/Common/TrackTools/test/python/conftest.py @@ -0,0 +1,26 @@ +"""Standalone O2 TrackTools PyROOT test setup; no dEdxAI/ADF imports.""" + +import os +from pathlib import Path + +import pytest + + +@pytest.fixture(scope="session") +def cpp(): + try: + import ROOT + except ImportError: + pytest.fail("PyROOT is required: run within an O2/ROOT environment", pytrace=False) + + include = Path(os.environ.get("TRACKTOOLS_INCLUDE", Path(__file__).resolve().parents[2] / "include")) + if not (include / "TrackGeometry.h").is_file(): + pytest.fail(f"Missing TrackGeometry.h under {include}", pytrace=False) + ROOT.gInterpreter.AddIncludePath(str(include)) + try: + ok = ROOT.gInterpreter.Declare('#include "TrackGeometry.h"') + except Exception as exc: + pytest.fail(f"Cannot compile TrackGeometry.h with current O2 environment: {exc}", pytrace=False) + if not ok: + pytest.fail("Cling rejected TrackGeometry.h; verify O2 include paths and dependencies", pytrace=False) + return ROOT.o2 diff --git a/Common/TrackTools/test/python/test_full_state_radius.py b/Common/TrackTools/test/python/test_full_state_radius.py new file mode 100644 index 0000000000000..8c34afb9b6d3b --- /dev/null +++ b/Common/TrackTools/test/python/test_full_state_radius.py @@ -0,0 +1,74 @@ +"""Full O2 TrackPar (x, alpha, y, z, snp, tgl, qpt) state-at-radius tests. + +Source API exists in the 2026-10-22 TrackGeometry.h snapshot. These are +regression checks, not certification of the TPC full-state row API. +""" + +import math + +import pytest + + +@pytest.mark.parametrize("method", ("H", "K0")) +def test_full_5d_reaches_radius(cpp, method): + reco = cpp.recohelpers + track = reco.makeTrackParFromLocalParameters(85., 0.10, 2.0, 17., 0.04, 0.10, 0.50) + state = getattr(reco, f"getParametersAtRadius{method}")(track, 100., 5.) + assert state.valid(), f"{method} status={int(state.status)}" + assert math.hypot(float(state.gx), float(state.gy)) == pytest.approx(100., abs=0.02) + d_sector = float(reco.stateDSector(state)) + assert 0 <= d_sector < 1 + + +@pytest.mark.parametrize("x,alpha,y,z,snp,tgl,qpt,radius", [ + (80., 0.20, 4., 17., 0.12, 0.23, 0.40, 100.), + (140., -0.40, 12., 68., -0.15, 0.40, -0.60, 180.), + (205., 0.35, -8., 190., 0.08, -0.20, 0.25, 230.), +]) +def test_displaced_secondary_full_state_zero_field_analytic_oracle( + cpp, x, alpha, y, z, snp, tgl, qpt, radius): + """A non-vertex track keeps y,z,alpha and has the correct straight-line intersection. + + At zero Bz the analytic H transport has an independent geometry oracle. + The test will fail if the implementation silently resets to a primary seed. + """ + reco = cpp.recohelpers + track = reco.makeTrackParFromLocalParameters(x, alpha, y, z, snp, tgl, qpt) + state = reco.getParametersAtRadiusH(track, radius, 0.) + assert state.valid(), f"secondary H status={int(state.status)}" + + # Global position from the local O2 reference plane and momentum direction. + x0 = x * math.cos(alpha) - y * math.sin(alpha) + y0 = x * math.sin(alpha) + y * math.cos(alpha) + theta = alpha + math.asin(snp) + ux, uy = math.cos(theta), math.sin(theta) + projection = x0 * ux + y0 * uy + sxy = -projection + math.sqrt(projection**2 + radius**2 - x0**2 - y0**2) + expected = (x0 + sxy * ux, y0 + sxy * uy, z + tgl * sxy) + for actual, target in zip((state.gx, state.gy, state.gz), expected): + assert float(actual) == pytest.approx(target, abs=2e-3) + assert 0 <= float(reco.stateDSector(state)) < 1 + + # Explicitly demonstrate that resetting this secondary to a primary changes the state. + primary = reco.makePrimaryTrackPar(theta, tgl, qpt, 0.) + primary_state = reco.getParametersAtRadiusH(primary, radius, 0.) + assert primary_state.valid() + delta = math.sqrt(sum((float(a) - float(b))**2 for a, b in zip( + (state.gx, state.gy, state.gz), + (primary_state.gx, primary_state.gy, primary_state.gz)))) + assert delta > 1.0 # cm, intentionally separated reference states + + +@pytest.mark.parametrize("qpt,bz", ((0.40, 5.), (-0.40, -5.))) +def test_signed_field_and_charge_explicit(cpp, qpt, bz): + reco = cpp.recohelpers + trk = reco.makeTrackParFromLocalParameters(85., 0.12, 1.2, 7., 0.05, 0.15, qpt) + out = reco.getParametersAtRadiusH(trk, 100., bz) + assert out.valid(), f"signed-field H status={int(out.status)}" + assert math.hypot(float(out.gx), float(out.gy)) == pytest.approx(100., abs=0.02) + + +def test_invalid_radius_status(cpp): + reco = cpp.recohelpers + track = reco.makeTrackParFromLocalParameters(85., 0., 0., 0., 0.02, 0.1, 0.5) + assert not reco.getParametersAtRadiusH(track, -1., 5.).valid() diff --git a/Common/TrackTools/test/python/test_sector_rows_primary_baseline.py b/Common/TrackTools/test/python/test_sector_rows_primary_baseline.py new file mode 100644 index 0000000000000..e38744ce755cc --- /dev/null +++ b/Common/TrackTools/test/python/test_sector_rows_primary_baseline.py @@ -0,0 +1,79 @@ +"""Current TPC H/L row-accounting baseline, explicitly REDUCED PRIMARY ONLY. + +No ADF, dfdraw, local dEdxAI Python package or NumPy required. This test does +NOT exercise the missing full-5D secondary-track TPC row evaluator. +""" + +import math + +import pytest + + +@pytest.fixture +def tpc(cpp): + return cpp.tpc.recohelpers + + +def _seed(ns, phi=2.15374, tgl=-0.814225, qpt=0.896099, bz=5.): + s = ns.TPCPrimaryTrackSeed() + s.phi, s.tgl, s.qpt, s.vz, s.bzKG = phi, tgl, qpt, 0., bz + return s + + +def _assert_partition(result): + crossed = int(result.nRowsCrossed) + assert crossed == int(result.nRowsDead) + int(result.nRowsExcluded) + int(result.nRowsAvailable) + assert 0 <= crossed <= 152 + # These are bitsets over exactly the 152 global TPC rows. + counts = [] + for mask in (result.crossedMask, result.deadMask, result.excludedMask, result.availableMask): + rows = [i for i in range(152) if (int(mask[i >> 5]) >> (i & 31)) & 1] + counts.append(set(rows)) + crossed_set, dead_set, excluded_set, available_set = counts + assert len(crossed_set) == crossed + assert (dead_set | excluded_set | available_set) == crossed_set + assert not (dead_set & excluded_set or dead_set & available_set or excluded_set & available_set) + assert [len(x) for x in counts] == [int(result.nRowsCrossed), int(result.nRowsDead), + int(result.nRowsExcluded), int(result.nRowsAvailable)] + length_sum = float(result.lengthDeadCm + result.lengthExcludedCm + result.lengthAvailableCm) + assert float(result.lengthCrossedCm) == pytest.approx(length_sum, abs=2e-4) + + +def test_mapper_has_152_rows(cpp): + assert int(cpp.tpc.Mapper.instance().getNumberOfRows()) == 152 + + +@pytest.mark.parametrize("method", ("sectorEdgeHelixRows", "sectorEdgeStackLinear")) +def test_primary_h_l_partition(tpc, method): + cfg = tpc.TPCSectorEdgeConfig() + cfg.guardLowerCm, cfg.guardUpperCm = 1., 1. + result = getattr(tpc, method)(_seed(tpc), cfg) + assert int(result.status) == 0, f"{method} status={int(result.status)}" + assert int(result.nRowsCrossed) > 0 + _assert_partition(result) + + +def test_primary_guard_monotonicity(tpc): + results = [] + for guard in (0., 0.5, 1.): + cfg = tpc.TPCSectorEdgeConfig() + cfg.guardLowerCm = cfg.guardUpperCm = guard + result = tpc.sectorEdgeHelixRows(_seed(tpc), cfg) + assert int(result.status) == 0 + _assert_partition(result) + results.append(result) + assert len({int(r.nRowsCrossed) for r in results}) == 1 + assert len({int(r.nRowsDead) for r in results}) == 1 + assert [int(r.nRowsExcluded) for r in results] == sorted(int(r.nRowsExcluded) for r in results) + assert [int(r.nRowsAvailable) for r in results] == sorted( + (int(r.nRowsAvailable) for r in results), reverse=True) + + +@pytest.mark.xfail(strict=True, reason="F6: reviewed rowRadius uses inner edge; pad-centre oracle not yet certified") +def test_f6_row_centre_expected_but_not_yet_implemented(cpp): + """Known geometry blocker; expected failure until physical pad centres are verified.""" + tpc = cpp.tpc.recohelpers + mapper = cpp.tpc.Mapper.instance() + r0 = mapper.getPadRegionInfo(0) + expected = float(r0.getRadiusFirstRow()) + 0.5 * float(r0.getPadHeight()) + assert float(tpc.rowRadius(mapper, 0)) == pytest.approx(expected, abs=1e-5) From a300256ea93908676ef658a9d29a75c4e804488b Mon Sep 17 00:00:00 2001 From: miranov Date: Fri, 23 Oct 2026 20:01:52 +0200 Subject: [PATCH 2/4] TrackTools: document TrackGeometry physics motivation and C++ usage Document TrackGeometry as the first component of the shared TrackTools package. Explain the impact of geometrically shortened TPC tracks on tracking efficiency, fake associations, dE/dx PID resolution, biases and comparisons between data, MC and reconstruction passes. Document the purpose of the three geometry methods: - L: candidate fast per-stack linear approximation. - H: analytic helix reference for precision studies. - K: O2 propagation reference. Provide practical user examples: - C++ analysis with two configurable sector-edge guard widths. - Verified interactive ROOT session using a complete 5D track. - Independent available-row selections and H/L comparisons. - Python/AliasDataFrame visualization with synthetic primary and secondary trajectories. Document the committed portable tests, execution instructions, geometry conventions and the distinction between predicted available rows and measured clusters. Include the synthetic geometry figure as supplementary QA. Detailed physics-validation findings remain in the project CRR. --- Common/TrackTools/README.md | 306 ++++++++++++++++++ ...ckgeometry_synthetic_5d_available_rows.png | Bin 0 -> 1415405 bytes 2 files changed, 306 insertions(+) create mode 100644 Common/TrackTools/README.md create mode 100644 Common/TrackTools/docs/figures/trackgeometry_synthetic_5d_available_rows.png diff --git a/Common/TrackTools/README.md b/Common/TrackTools/README.md new file mode 100644 index 0000000000000..5661d1f30b391 --- /dev/null +++ b/Common/TrackTools/README.md @@ -0,0 +1,306 @@ +# TrackTools + +**TrackTools** is a home for reusable C++ track utilities in ALICE O2. Its purpose is to make common, physics-motivated track calculations available consistently to reconstruction, O2Physics analyses and calibration. More utilities can be added without changing the role of the package. + +**TrackGeometry** is the first component. It evaluates reconstructed tracks at requested detector radii and, for the TPC, estimates geometrically crossed, dead, edge-excluded and available pad rows and corresponding track lengths. This README documents **TrackGeometry**, not the scope of all future TrackTools components. + +## TrackGeometry: physics motivation + +**Shorter usable tracks generally mean worse tracking and PID performance:** less dE/dx information and poorer PID resolution, reduced reconstruction efficiency, potentially greater fit/PID biases and fake associations, and larger differences between data, simulation and reconstruction passes. We need to **quantify these effects track by track**, not merely describe them. TrackGeometry supplies common geometry-derived observables that analysts can use to study and select the *usable* portion of a track while separating geometric acceptance from reconstruction and calibration effects. + +A concrete Run 3 example is the **TPC sector-edge pad treatment**. In some early reconstruction passes, two pads at a sector boundary were treated as edge pads rather than one as in the earlier treatment. Edge-pad positions and amplitudes are intrinsically less reliable. Inflated cluster-position uncertainties reduce their contribution to the track fit, and excluding these pads from dE/dx shortens the segment available for PID. Charging-up and steep space-charge distortion gradients can amplify such effects. Later reconstruction changes appear to have alleviated part of the problem, but the exact treatment **must be checked for each production pass**; the library does not presume a correction date. + +The practical analysis question is therefore: *how many TPC pad rows, or how much track length, remain available if we exclude inactive regions and an adjustable guard near the **physical active-pad edge**?* A two-pad versus one-pad scenario can be studied by choosing guard widths appropriate to the detector geometry and reconstruction settings; **pad count is not itself a universal width in centimetres**. TrackGeometry provides the quantities for both selections, so one can correlate their effects with efficiency, fake rate, dE/dx resolution, PID biases and data/MC or pass-to-pass differences. + +A related, complementary measurement is the TPC cluster bitmask in TrackQA: eight bits summarize the 152 pad rows in eight groups of 19; in the current definition a bit is set when **more than five associated clusters** occur in that group. It can support studies of segment PID and potentially overlapping/split tracks, but it does **not** supply exact per-row reconstructed-cluster occupancy. TrackGeometry predicts geometric row availability; the bitmask describes coarse reconstructed-cluster information. Their comparison is useful precisely because the two are different observables. + +The same shared C++ component can return a track state and sector coordinate at an arbitrary **reachable** cylindrical radius, relevant to TPC, TRD and TOF studies. TPC-specific Mapper-based row/length acceptance is the first detector specialization; TRD/TOF detector-specific gap or strip acceptance is not implied by the generic query. + +The goal is to compute these observables **quickly and with controlled accuracy**, from the standard O2 track representation rather than reproducing tracking formulae in every analysis. In particular: + +- **L — stack-local linear approximation:** the candidate **fast** evaluator for repeated TPC row/length selections. +- **H — analytic helix:** constant-field reference against which the L approximation can be quantified. +- **K — O2 Propagator:** an independent transport reference for the TPC row calculation, requiring properly initialized O2 field conditions. Generic **K0** supplies constant-field O2 transport to a chosen radius. + +The practical objective is to establish the phase space where **L is both accurate enough and faster end-to-end**; H-derived endpoint construction must be included in its timing. The implementation supplies the comparison methods; this README does not claim an unmeasured speedup or universal accuracy threshold. + +A query at a TRD/TOF radius does **not** automatically calculate TRD chamber acceptance, TOF strip acceptance or arrival time; detector sector counts and phase conventions must be configured explicitly. + +## Input and functionality + +The preferred input is an existing full `o2::track::TrackPar`: local fitted parameters `(y, z, snp, tgl, q/pT)` at its reference plane `(x, alpha)`. It represents both primary and displaced/secondary tracks; do not replace a secondary's complete state with a primary-vertex approximation. The header also provides a reduced-primary adapter for older applications. All constant-field calls take an **explicit signed `Bz` in kG**, supplied from the data-taking conditions (GRP/CCDB) by the caller. + +Include the single component header in a configured O2 environment: + +```cpp +#include "TrackGeometry.h" +``` + +| Capability | Current C++ interface | +|---|---| +| Full track at a reachable cylindrical radius, H | `o2::recohelpers::getParametersAtRadiusH(track, radiusCm, signedBzKG)` | +| Same, constant-field O2 reference K0 | `o2::recohelpers::getParametersAtRadiusK0(track, radiusCm, signedBzKG)` | +| Position/momentum azimuth, inclination, fractional sector coordinate | `statePhiPos(state)`, `statePhiMom(state)`, `stateTgl(state)`, `stateDSector(state, nSectors, sectorPhaseRad)` | +| TPC available rows/length: linear L | `o2::tpc::recohelpers::sectorEdgeStackLinear(track, signedBzKG, cfg)` | +| Same: helix reference H | `o2::tpc::recohelpers::sectorEdgeHelixRows(track, signedBzKG, cfg)` | +| Same: initialized O2 Propagator K | `o2::tpc::recohelpers::sectorEdgeO2PropagatorRows(track, signedBzKG, cfg)` | +| Multiple full local states | `localTrackParametersAtRadiusHBatch`, `localTrackParametersAtRadiusK0Batch`, and `localSectorEdge{HelixRows,StackLinear,O2PropagatorRows}Batch` | + +The current candidate exposes the full-`TrackPar` H/L/K TPC row functions. It also retains primary-compatible overloads; the latter are **input adapters**, not separate geometry models. L is a TPC stack approximation, **not** a generic TRD/TOF straight-line propagator. + +For a TPC evaluation, `TPCSectorEdgeResult` provides four matching sets of quantities: + +| Classification | Predicted pad rows | Approximate trajectory length | Per-row mask | +|---|---|---|---| +| Crossed | `nRowsCrossed` | `lengthCrossedCm` | `crossedMask` | +| Dead: outside Mapper's physical active-pad boundary | `nRowsDead` | `lengthDeadCm` | `deadMask` | +| Excluded: *inside* that boundary, within the configured edge guard | `nRowsExcluded` | `lengthExcludedCm` | `excludedMask` | +| Available: inside the boundary and beyond the guard | `nRowsAvailable` | `lengthAvailableCm` | `availableMask` | + +The partition is `Crossed = Dead + Excluded + Available` for row membership and counts; lengths satisfy the corresponding sum up to floating-point roundoff. The masks encode 152 global pad-row indices, subdivided into **IROC (0–62), OROC1 (63–96), OROC2 (97–126), OROC3 (127–151)**, so per-stack counts can be calculated from the appropriate bits. Length estimates are geometric row-thickness contributions, not material-integrated paths. + +`TPCSectorEdgeConfig` specifies `guardLowerCm` and `guardUpperCm` (inward distances from the **active-pad edge**, not the nominal sector boundary), `zMaxCm` and `maxSnp` (the *radial-frame* inclination limit, distinct from the local `TrackPar::getSnp()`). The input track's reference radius and the first outward trajectory branch govern which rows are reachable. `stateDSector` returns a **fractional periodic sector coordinate**, not the physical distance to an active pad; supply the actual detector sector count and phase for non-TPC use. + +**Check results before using them:** `TrackParametersAtRadius::valid()` for radius queries and `result.status == o2::tpc::recohelpers::SectorEdgeStatus::OK` for row/length queries. The geometry-predicted row opportunities must not be confused with measured associated clusters or the subset of clusters used for PID. + +## C++ example 1 — compare two edge exclusions and make independent selections + +This is a typical use inside an O2 or O2Physics track loop. `track` is the actual fitted `o2::track::TrackPar`; `signedBzKG`, both guard widths and the cut threshold come from the **run/analysis configuration**. The two output counters are kept separately. Using **two configurations** on the same track makes it possible to compare selections across reconstruction passes or systematic variations. + +```cpp +#include "TrackGeometry.h" + +// Call this in an O2/O2Physics track loop. The run configuration supplies +// signedBzKG, both guard widths and minAvailableRows. +void countEdgeSelections(const o2::track::TrackPar& track, + float signedBzKG, + float guard0Cm, float guard1Cm, + int minAvailableRows, + unsigned& nRejected0, unsigned& nRejected1) +{ + namespace tg = o2::tpc::recohelpers; + tg::TPCSectorEdgeConfig cfg0; + cfg0.guardLowerCm = cfg0.guardUpperCm = guard0Cm; + cfg0.zMaxCm = 250.f; // set from desired longitudinal acceptance + cfg0.maxSnp = 0.9f; // radial-frame trajectory stopping criterion + + auto cfg1 = cfg0; + cfg1.guardLowerCm = cfg1.guardUpperCm = guard1Cm; + + // Two independent predictions for the same complete TrackPar. + // Use L for selections after verifying its accuracy in your phase space. + const auto result0 = tg::sectorEdgeStackLinear(track, signedBzKG, cfg0); + const auto result1 = tg::sectorEdgeStackLinear(track, signedBzKG, cfg1); + if (result0.status != tg::SectorEdgeStatus::OK || + result1.status != tg::SectorEdgeStatus::OK) { + return; // Handle non-OK tracks separately in your analysis. + } + + const int nRowsCut0 = result0.nRowsAvailable; + const int nRowsCut1 = result1.nRowsAvailable; + const float lengthCut0Cm = result0.lengthAvailableCm; + const float lengthCut1Cm = result1.lengthAvailableCm; + + if (nRowsCut0 < minAvailableRows) { + ++nRejected0; // Edge treatment 0: independent selection. + } + if (nRowsCut1 < minAvailableRows) { + ++nRejected1; // Edge treatment 1: independent selection. + } + // The same two results allow length-based cuts on lengthCut{0,1}Cm. + (void)lengthCut0Cm; + (void)lengthCut1Cm; +} +``` + +Changing the guard changes **Excluded/Available**, not the physical Mapper **Dead** classification. For a systematic comparison, keep both decisions rather than overwriting the first. If L accuracy for your sample has not yet been established, call `sectorEdgeHelixRows` on the same full track and compare available rows, available length, row masks and selection decisions. + +## C++ example 2 — interactive ROOT, one question at a time + +This is a **real, user-executed ROOT/Cling session** using the full-5D candidate header, not pseudocode or a compiled macro. It shows the workflow that can then be moved almost unchanged into an O2Physics track loop: start with one track, inspect `dSector`, vary the active-pad-edge guard, read out the available rows and lengths, apply two cuts, and compare L with H. + +Start a **fresh ROOT session** in the O2 environment, pointing to the header that implements the full-`TrackPar` overloads. Do not use the old `#include "include/TrackGeometry.h"` from an unsynchronized O2 checkout; that earlier file exposed only the reduced-primary TPC-row signatures. + +```bash +ROOT_INCLUDE_PATH="$dEdxAI_CODE/o2reco/cpp${ROOT_INCLUDE_PATH:+:$ROOT_INCLUDE_PATH}" root -l +``` + +For an installed O2 component, use the corresponding configured O2 header include directory instead. The following expressions are entered **one line at a time** at the ROOT prompt; no multiline `std::cout` statement is required. + +### 1. Construct a complete local O2 track and query the 85 cm surface + +```cpp +#include "TrackGeometry.h" +#include +namespace geo = o2::recohelpers; +namespace tpc = o2::tpc::recohelpers; + +const float bzKG = 5.f; +auto track = geo::makeTrackParFromLocalParameters(80.f, 0.12f, -9.5f, 17.f, 0.06f, 0.25f, 0.30f); +auto at85 = geo::getParametersAtRadiusH(track, 85.f, bzKG); +at85.valid() +geo::stateDSector(at85, 18, 0.f) +at85.gz +geo::statePhiMom(at85) +``` + +Actual ROOT results: + +```text +(bool) true +(float) 0.0319329f // fractional sector coordinate at R=85 cm +(float) 18.1262f // global z at R=85 cm [cm] +(float) 0.178010f // global momentum azimuth [rad] +``` + +`bzKG=+5` is a **synthetic demo setting**, not a production field default. In production obtain the signed field and conditions from the actual run. The initial state is local `(x, alpha, y, z, snp, tgl, q/pT)` and may represent a displaced track; it is not silently reset to the primary vertex. For other detectors use the actual sector count and phase, not necessarily the TPC's `18, 0` convention. + +### 2. Define two edge-guard configurations + +```cpp +tpc::TPCSectorEdgeConfig cfg0; +cfg0.guardLowerCm = 0.5f; +cfg0.guardUpperCm = 0.5f; +cfg0.zMaxCm = 250.f; +cfg0.maxSnp = 0.9f; +auto cfg1 = cfg0; +cfg1.guardLowerCm = 1.5f; +cfg1.guardUpperCm = 1.5f; +``` + +Guard distances are **centimetres inward from the Mapper active-pad boundary**, not distances from the nominal 20° sector boundary. The numbers demonstrate a guard scan, not certified conversions of one versus two physical pad widths. + +### 3. Calculate available rows and useful length under each guard + +```cpp +auto l0 = tpc::sectorEdgeStackLinear(track, bzKG, cfg0); +auto l1 = tpc::sectorEdgeStackLinear(track, bzKG, cfg1); +int(l0.status) +int(l1.status) +l0.nRowsAvailable +l1.nRowsAvailable +l0.lengthAvailableCm +l1.lengthAvailableCm +``` + +Actual ROOT results: + +```text +(int) 0 +(int) 0 +(unsigned short) 143 +(unsigned short) 134 +(float) 153.057f +(float) 146.054f +``` + +For the same reconstructed track, increasing the guard decreases the predicted available rows from **143 to 134**, and the available length from **153.057 to 146.054 cm**. A real analysis should retain non-OK statuses separately rather than treating failed geometry evaluations as accepted rows. + +### 4. Make independent analysis selections + +```cpp +const int minRows = 140; +bool reject0 = int(l0.status) != 0 || l0.nRowsAvailable < minRows; +bool reject1 = int(l1.status) != 0 || l1.nRowsAvailable < minRows; +reject0 +reject1 +``` + +Actual ROOT results: + +```text +(bool) false // 0.5-cm guard: ACCEPT, 143 >= 140 +(bool) true // 1.5-cm guard: REJECT, 134 < 140 +``` + +This is the direct use case for an O2Physics task: compute `nRowsCut0` and `nRowsCut1` from two configurations of the **same fitted `TrackPar`**, then keep both acceptance decisions. `minRows=140` is an **illustrative** threshold to make the difference visible, not a recommended universal analysis cut. Available-length cuts work analogously using `lengthAvailableCm`. + +### 5. Quantify how much the fast L method differs from H + +```cpp +auto h1 = tpc::sectorEdgeHelixRows(track, bzKG, cfg1); +int(h1.status) +int(h1.nRowsAvailable) - int(l1.nRowsAvailable) +h1.lengthAvailableCm - l1.lengthAvailableCm +``` + +Actual ROOT results: + +```text +(int) 0 +(int) 6 +(float) 4.58417f +``` + +For this **near-edge, deliberately demanding example**, H and L differ by **6 available rows and 4.58417 cm**. Thus agreement of H and L must be checked in the analysis phase space before substituting the faster approximation for a cut. No blanket speedup or precision claim follows from a single-track demonstration. + +For a generic detector-surface query, the same full-state API also evaluated a state at an illustrative radius of 300 cm in the compiled demonstration: + +```cpp +auto at300 = geo::getParametersAtRadiusH(track, 300.f, bzKG); +at300.valid() +``` + +The 300-cm point is an example cylinder, **not** a claim that TRD/TOF-specific acceptance is implemented. A user can next vary `y`, signed `q/pT`, `tgl`, `guardLowerCm`, `guardUpperCm`, or the requested radius interactively and inspect the resulting quantities. Because these are ordinary C++ calls, they transfer to compiled O2 or O2Physics code without a second geometry implementation. + +## Tests included with TrackGeometry + +The portable O2/PyROOT tests call the same C++ header. They are intended to be runnable without AliasDataFrame or dfdraw. In the O2 checkout, after loading the matching O2/ROOT environment: + +```sh +cd O2/Common/TrackTools # replace with your actual checkout path +python -m pytest -q -ra test/python +``` + +The portable test sources supplied with TrackTools include: + +- `test/python/conftest.py`: load the same ROOT environment and `TrackGeometry.h` used by C++. +- `test/python/test_full_state_radius.py`: full 5D H/K0 radius evaluation, independent straight-line truth for displaced tracks, field/charge-sign and invalid-input checks. +- `test/python/test_sector_rows_primary_baseline.py`: TPC Mapper's 152-row accounting, mask partitions, guard monotonicity and the recorded row-centre expected failure. +- `test/python/test_full_state_tpc_rows.py` **in the extended full-5D test set**: full-state H/L, reduced-primary adapter equivalence, displaced tracks, first-outward start radius, scalar/batch parity and field-initialized K smoke checks. Run this file in O2 only once its exact committed version is present in that checkout. + +The historical focused full-state portable run was reported as **26 passed, 1 expected failure** in dEdxAI; this is not a statement that the entire O2 test suite or O2 CTest has passed. Test counts belong to the exact source revision and should be updated from the PR's attached log. The row-centre finding is an expected failure, not a passing geometry oracle. + +For developers in the canonical **dEdxAI** source tree, the focused tests (including the extended full-state tests) run from the repository root: + +```sh +O2RECO_GRP="$dEdxAI_CODE/o2sim_grp.root" \ +TRACKTOOLS_INCLUDE="$dEdxAI_CODE/o2reco/cpp" \ +python -m pytest -v -ra tests/o2reco/portable_o2/ +``` + +Run the project's canonical `run_tests.sh` and attach its actual output, O2 build status and source revision to the PR/CRR when available. An expected failure for the Mapper row-centre condition is **not** a passing physical validation. The detailed K and row-centre investigations belong in technical review evidence; use method K only with initialized O2 field conditions and appropriate validation. + +## Python and AliasDataFrame example + +The **optional dEdxAI Python demonstration** calls the C++ TrackGeometry implementation through PyROOT and plots useful TPC geometry observables with AliasDataFrame/dfdraw. These development packages are **not** dependencies of the C++ header or the portable O2 tests. + +```python +import importlib +import examples.tracktools_synthetic_5d_demo as demo +importlib.reload(demo) + +adfSynthetic = demo.make_synthetic_track_geometry_adf(n_tracks=1000) +adfCounts = demo.make_synthetic_row_counts_adf(adfSynthetic) + +sel = ('(input_mode=="5D_full")&(method=="H")&' + '(state_status==0)&(rows_status==0)&' + '(observable=="Available")&(stack!="TPC")') + +adfCounts.draw( + "count:dSector85", selection=sel, + type="scatter", color="qpt", marker="o", + facet_by=["isPrimary", "stack"], ncols=4, + auto_title=True, share_y="none" +) +``` + +![Geometrically available TPC rows versus dSector85, split by TPC stack and primary/secondary truth](docs/figures/trackgeometry_synthetic_5d_available_rows.png) + +*Figure — Synthetic TrackGeometry illustration.* The vertical axis `count` is the **number of geometrically Available pad rows**, not observed clusters; the horizontal axis `dSector85` is the **fractional sector coordinate at R = 85 cm** (not an edge distance); colour encodes signed `q/pT` [(GeV/c)⁻¹]. Each column is one TPC stack and the facets separate true origin-produced primaries (`isPrimary=1`) and displaced secondaries (`isPrimary=0`). The example uses H, full 5D input, a synthetic **+5 kG** field, and **1.5 cm guards** on both active-pad edges. It is a **constructed 50/50 mixture** of 500 primaries transported from `(0,0,0)` to reference radii 78–82 cm, and 500 displaced secondaries sampled around reference `x` positions 79, 80, 81, 105, 145 and 195 cm with ±1.5 cm smearing, broad local `y,z` and random signed curvature. Conditioning on a successful *outward* R=85 cm state removes most secondaries starting at larger radii; it is not a realistic detector-production spectrum. The figure illustrates geometry dependence, **not H–L precision, L timing or measured Ncl**. + +To investigate those comparisons in Python, keep the same `adfSynthetic` sample and inspect H versus L available-row and length differences in the data; an H-only scatter plot is not a substitute for the L validation benchmark. + +--- + +**Component status.** `TrackGeometry.h` is the implemented component covered above. Some field/curvature and physical pad-row-centre validation remains under technical review, as does the O2 build/install integration. For the exact current revision, test logs and identified follow-up work, consult the associated PR/CRR rather than treating this user manual as a debugging report. diff --git a/Common/TrackTools/docs/figures/trackgeometry_synthetic_5d_available_rows.png b/Common/TrackTools/docs/figures/trackgeometry_synthetic_5d_available_rows.png new file mode 100644 index 0000000000000000000000000000000000000000..633dd2eb4da68137f2d497c1eca4a07446638a32 GIT binary patch literal 1415405 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 z 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ë`$yXUHrUS?jbzQLFMEX0h{5I$dCF z0}h=lkd5#oAbXW>`=xI5Btm=61I$~cjw0BJOECG!g{ zM@+Qmh!|ZK)jc_~{*E!5j(L$psL_lugx)A6SI+Puzh*r@V^&p4(Fhmj-TEaHyQ`C>NOqMYUGf`4FjeZ?V_ zHbVq?pO;L*&Y`gN^Bg&}7I{3j3F98qIn5?RCkWpO!xn*0@Z8r}4_=aX1tPT83A+u`>6>xu!n# ztj3#0tVw(IZSVYxx$iMQ1X_E+%0eWi4G;j}%bX!(8`Nsz1HQ;@WFZ9&vcLLB-F&OX zv#cKFhCT+yh$;cT+%VRpi#W9>pa_#?$J8&`f}KaS@4v9bIOTi1BuS19wG~%L5x98Vaq8wSml_b}<>zi24KD=6O1{Fda5%v0BfVs3cHs zf}fOJhjh&r0XeSQWFM3k(%smSxAvlQHtFO`E6UEvXiCY22})BPrC|q7lQ|%(NK>QI z@Uyj&@H%*hVR$ayRgmUe2UC2QT(If_A37^n!}v54WRLZ;+7Vh3h001tiSvoJNXYh@lUdb5gPr&)%UNuy`c$0f-ipy$f*pPsZ`@*ZwbI zz@mfn!#mieBPUdH;6LPNb^|6$0v7LqD~0?_;ohlrOeM`ods~o0hR99qhq@g=Aj6&# zmFdBKm38Z6_1}m7|Gez?H$WF8?Vkw!9~3k;x3N>z*iD)u`?701rfV1hq1&|g)F1CF zD?L#q*PP?ov@}4S?EWaD=2TxtV7lftU&yXOcDx}oLjxt7w=1@^Wkoqf znl+2pSUN?zXjZ?z0v)~@u9URMu?vRl{69Q5=B;gnu*=^4FTa}Aox`$@ZtwwD){a4W zyfOJ~Zuz$u*!~xpG%bQC_y+E+v!2J=W|iG}m(?-SPKg9A|BE1?;o}GH{Qu=qh_KVv z?TAdW1nd|9$>ed&GJL6%7(lC<;fuj;jyJ74& zSWS4YAO>OvQ0L`kGewYp6aJjUJGFTn`=;>-3C3NUrg>PWo2kCOG@3E;(wLUmf9!?y zNzD0*?l+^7!lwA>`SU>-hb)t40vzgfX9FhXbNW;v zlF_&Gs$an?^0{yKy*DQ8Dtv z-ibwb1a##mS@*P))A&5j9;2wu9#*)}+S(eU$RO2?6z$+^y7SYzeqMw^=m+BSbVCD!mDT)c#0i z_U($V3y7;@Y3Y-Oz4!AcjW-N7O_K1xOIS9CV_!Ay&L9P&ud#~Eov6hsh5lw)cQ9KO zy{LG2^PzqanuNisZx-Hl5IHsPcIiiYlw`X1g)E;x^Cc-5Ah-EFTgT^Rwjr3@q+KL7 zDEauw;K36)=@j4X(mH@a=7WINE<1Ej18V|2D71E_1ei6n%-@zl<#HS@BDvoh-!*M7 z6WjG>rqk~^wKCrdSi%H+f=+5tDIMs}Yk%C%DM0x!h&g~X_0B`@`?gpFdf3+C*OY8< z6)O(ydu$c0?J44S?`)`k#td5DLAE3VLy0TRI`G(uao&^EdoQNca^68@yDqoX$O(jc4LZz?m&Mz$~VU;->(r^DvZ-qmG6bS z2-4l6#Kk0|!peA88_!A%0DYHO&J3%*3HbmJ{1Y#La(`5C2 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