From 613ef862befd93cb0ebcd8978b520272d6fa653a Mon Sep 17 00:00:00 2001 From: jesgum Date: Mon, 12 Oct 2026 15:46:15 +0200 Subject: [PATCH 1/3] Add inner and outermost hit information to alice 3 tracks --- ALICE3/Core/FastTracker.cxx | 16 +++++++++-- ALICE3/Core/FastTracker.h | 4 +++ ALICE3/DataModel/tracksAlice3.h | 6 ++++- ALICE3/Macros/Configuration/a3geometry_v3.ini | 27 ++++++++++++------- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 18 ++++++++++++- .../alice3TrackingTranslator.cxx | 4 ++- 6 files changed, 61 insertions(+), 14 deletions(-) diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index 20eb7087f16..5bf0bcd87e3 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -312,6 +312,8 @@ int FastTracker::fastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa nIntercepts = 0; nSiliconPoints = 0; nGasPoints = 0; + trackIU = -1.f; + trackOU = -1.f; std::array posIni{}; // provision for != PV inputTrack.getXYZGlo(posIni); const float initialRadius = std::hypot(posIni[0], posIni[1]); @@ -416,6 +418,9 @@ int FastTracker::fastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa firstLayerReached = il; } lastLayerReached = il; + if (layers[il].isTOF()) { + continue; // TOF layers are not used for tracking, but are kept in range for the innermost/outermost update + } nIntercepts++; } @@ -475,7 +480,7 @@ int FastTracker::fastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa continue; } - if (!layers[il].isInert()) { // only update covm for tracker hits + if (!layers[il].isInert() && !layers[il].isTOF()) { // only update covm for tracker hits const o2::track::TrackParametrization::dim2_t hitpoint = {xyz1[1], xyz1[2]}; const o2::track::TrackParametrization::dim3_t hitpointcov = {layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi(), 0.f, layers[il].getResolutionZ() * layers[il].getResolutionZ()}; @@ -510,7 +515,14 @@ int FastTracker::fastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } hits.push_back(thisHit); - if (!layers[il].isInert()) { // good hit probability calculation + if (!layers[il].isInert()) { + trackIU = std::hypot(spacePoint[0], spacePoint[1]); + if (trackOU < 0.f) { + trackOU = trackIU; + } + } + + if (!layers[il].isInert() && !layers[il].isTOF()) { // good hit probability calculation float sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); float sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); goodHitProbability[il] = probGoodChiSqHit(layers[il].getRadius() * 100, sigYCmb * 100, sigZCmb * 100); diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index d3d9a11d4ed..ed564095718 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -127,6 +127,8 @@ class FastTracker [[nodiscard]] int getNIntercepts() const { return nIntercepts; } [[nodiscard]] int getNSiliconPoints() const { return nSiliconPoints; } [[nodiscard]] int getNGasPoints() const { return nGasPoints; } + [[nodiscard]] float getTrackIU() const { return trackIU; } + [[nodiscard]] float getTrackOU() const { return trackOU; } [[nodiscard]] float getGoodHitProb(int layer) const { return (layer >= 0 && static_cast(layer) < goodHitProbability.size()) ? goodHitProbability[layer] : 0.0f; @@ -172,6 +174,8 @@ class FastTracker int nIntercepts = 0; /// found in first outward propagation int nSiliconPoints = 0; /// silicon-based space points added to track int nGasPoints = 0; /// tpc-based space points added to track + float trackIU = -1.f; /// innermost update: radius of the innermost active-layer hit added to track + float trackOU = -1.f; /// outermost update: radius of the outermost active-layer hit added to track std::vector goodHitProbability; ClassDef(FastTracker, 1); diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index 8e19feb0d0e..327d0587b64 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -32,9 +32,13 @@ DECLARE_SOA_COLUMN(NTPCHits, nTPCHits, int); //! number of tpc hi DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); //! PDG code of the linked truth MC particle DECLARE_SOA_COLUMN(TrackType, trackType, int); //! Type of the track DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); //! Has track contributed to the PV fit? +DECLARE_SOA_COLUMN(TrackIU, trackIU, float); //! Innermost update: radius (cm) of the innermost hit assigned to the track +DECLARE_SOA_COLUMN(TrackOU, trackOU, float); //! Outermost update: radius (cm) of the outermost hit assigned to the track } // namespace track_alice3 DECLARE_SOA_TABLE(TracksAlice3, "AOD", "TRACKSALICE3", - track_alice3::IsReconstructed); + track_alice3::IsReconstructed, + track_alice3::TrackIU, + track_alice3::TrackOU); using TrackAlice3 = TracksAlice3::iterator; DECLARE_SOA_TABLE(TracksAlice3Pdg, "AOD", "TRACKSALICE3PDG", diff --git a/ALICE3/Macros/Configuration/a3geometry_v3.ini b/ALICE3/Macros/Configuration/a3geometry_v3.ini index e4eb415c133..3381df08209 100644 --- a/ALICE3/Macros/Configuration/a3geometry_v3.ini +++ b/ALICE3/Macros/Configuration/a3geometry_v3.ini @@ -92,15 +92,6 @@ B05.resZ: 0.001 B05.eff: 1.00 B05.type: 1 -iTOF.r: 19 -iTOF.z: 250 -iTOF.x0: 0.01*3. -iTOF.xrho: 0.03 -iTOF.resRPhi: 0.001 -iTOF.resZ: 0.001 -iTOF.eff: 1.00 -iTOF.type: 0 - B06.r: 20. B06.z: 250 B06.x0: 0.01 @@ -110,6 +101,15 @@ B06.resZ: 0.001 B06.eff: 1.00 B06.type: 1 +iTOF.r: 21 +iTOF.z: 250 +iTOF.x0: 0.01*3. +iTOF.xrho: 0.03 +iTOF.resRPhi: 0.001 +iTOF.resZ: 0.001 +iTOF.eff: 1.00 +iTOF.type: 3 + B07.r: 30. B07.z: 250 B07.x0: 0.01 @@ -146,6 +146,15 @@ B10.resZ: 0.001 B10.eff: 1.00 B10.type: 1 +oTOF.r: 92 +oTOF.z: 250 +oTOF.x0: 0.01*3. +oTOF.xrho: 0.03 +oTOF.resRPhi: 0.001 +oTOF.resZ: 0.001 +oTOF.eff: 1.00 +oTOF.type: 3 + # Lookup tables global.lutEl: ccdb:/Users/j/jekarlss/LUTs/v3/b/el global.lutMu: ccdb:/Users/j/jekarlss/LUTs/v3/b/mu diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index ca0bc59230d..7e84ec9c223 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -299,6 +299,8 @@ struct OnTheFlyTracker { int nSiliconHits = 0; ///< number of silicon hits int nTPCHits = 0; ///< number of TPC hits TrackType trackType = TrackType::kNone; + float trackIU = -1.f; ///< radius of the innermost hit (-1 if not available) + float trackOU = -1.f; ///< radius of the outermost hit (-1 if not available) }; // Helper struct to pass cascade information @@ -1828,7 +1830,7 @@ struct OnTheFlyTracker { tableTrackSelection(static_cast(0), false, false, false, false, false, false); tableTrackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); } - tableTracksAlice3(true); + tableTracksAlice3(true, trackParCov.trackIU, trackParCov.trackOU); } } @@ -1949,12 +1951,14 @@ struct OnTheFlyTracker { bool reconstructed = true; int nTrkHits = 0; + std::array hitRadii = {-1.f, -1.f}; // {innermost, outermost} if (enablePrimarySmearing) { if (fastPrimaryTrackerSettings.fastTrackPrimaries && longLivedToBeHandled) { o2::track::TrackParCov perfectTrackParCov = o2::upgrade::convertMCParticleToO2Track(mcParticle, pdgDB); perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); computeBremsstrahlungLoss(mcParticle, perfectTrackParCov); nTrkHits = fastTracker[icfg]->fastTrack(perfectTrackParCov, trackParCov, dNdEta); + hitRadii = {fastTracker[icfg]->getTrackIU(), fastTracker[icfg]->getTrackOU()}; if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { reconstructed = false; } @@ -1965,6 +1969,7 @@ struct OnTheFlyTracker { const std::array decayVtx = decayer.generateDecayVertex(mcParticle, pdgDB); const float decayRadius2D = std::hypot(decayVtx[0], decayVtx[1]); nTrkHits = fastTracker[icfg]->fastTrack(perfectTrackParCov, trackParCov, dNdEta, decayRadius2D); + hitRadii = {fastTracker[icfg]->getTrackIU(), fastTracker[icfg]->getTrackOU()}; if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { reconstructed = false; } @@ -2033,8 +2038,12 @@ struct OnTheFlyTracker { bool isPVContributor = trackType == TrackType::kRecoPrimary; if (reconstructed) { recoPrimaries.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), trackTime, TimeResolutionUs, isDecayDaughter, isPVContributor, false, 0, nTrkHits, trackType}); + recoPrimaries.back().trackIU = hitRadii[0]; + recoPrimaries.back().trackOU = hitRadii[1]; } else { ghostPrimaries.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), trackTime, TimeResolutionUs, isDecayDaughter, isPVContributor, false, 0, nTrkHits, trackType}); + ghostPrimaries.back().trackIU = hitRadii[0]; + ghostPrimaries.back().trackOU = hitRadii[1]; } } @@ -2176,6 +2185,7 @@ struct OnTheFlyTracker { bool reconstructed = false; int nTrkHits = 0; + std::array hitRadii = {-1.f, -1.f}; // {innermost, outermost} const bool isSecondary = !otfParticle.isPrimary() && otfParticle.checkBit(o2::upgrade::DecayerBits::ProducedByDecayer) && otfParticle.isAlive(); if (enablePrimarySmearing && longLivedToBeHandled && otfParticle.isPrimary()) { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); @@ -2186,6 +2196,7 @@ struct OnTheFlyTracker { perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); computeBremsstrahlungLoss(mcParticle, perfectTrackParCov); nTrkHits = fastTracker[icfg]->fastTrack(perfectTrackParCov, trackParCov, dNdEta, mcParticle.decayRadius()); + hitRadii = {fastTracker[icfg]->getTrackIU(), fastTracker[icfg]->getTrackOU()}; getHist(histPath + "h2dGenShortLivedParticleRadius")->Fill(mcParticle.decayRadius(), perfectTrackParCov.getPt()); getHist(histPath + "h2dGenRadiusIniVsDecay")->Fill(std::hypot(perfectTrackParCov.getX(), perfectTrackParCov.getY()), mcParticle.decayRadius()); if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { @@ -2203,6 +2214,7 @@ struct OnTheFlyTracker { computeBremsstrahlungLoss(mcParticle, perfectTrackParCov); perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); nTrkHits = fastTracker[icfg]->fastTrack(perfectTrackParCov, trackParCov, dNdEta); + hitRadii = {fastTracker[icfg]->getTrackIU(), fastTracker[icfg]->getTrackOU()}; reconstructed = nTrkHits >= fastTrackerSettings.minSiliconHits; } @@ -2260,9 +2272,13 @@ struct OnTheFlyTracker { if (reconstructed) { tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, TimeResolutionUs, isSecondary, true, false, 0, nTrkHits, kRecoPrimary}); + tracksAlice3.back().trackIU = hitRadii[0]; + tracksAlice3.back().trackOU = hitRadii[1]; getHist(histPath + "hPtReconstructedPr")->Fill(trackParCov.getPt()); } else { ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, TimeResolutionUs, isSecondary, false, false, false, 0, nTrkHits, kGhostPrimary}); + ghostTracksAlice3.back().trackIU = hitRadii[0]; + ghostTracksAlice3.back().trackOU = hitRadii[1]; } } diff --git a/ALICE3/TableProducer/alice3TrackingTranslator.cxx b/ALICE3/TableProducer/alice3TrackingTranslator.cxx index 983092eb228..c45ddeb1f71 100644 --- a/ALICE3/TableProducer/alice3TrackingTranslator.cxx +++ b/ALICE3/TableProducer/alice3TrackingTranslator.cxx @@ -666,7 +666,9 @@ struct Alice3TrackingTranslator { tableTracksDCACov(0.0f, // sigmaDcaXY2 0.0f); // sigmaDcaZ2 // Fill ALICE3 specific tables - tableTracksAlice3(true); // isReconstructed + tableTracksAlice3(true, // isReconstructed + -1.f, // todo: track innermost update + -1.f); // todo: track outermost update if (mcParticleIdx > 0) tableTracksAlice3Pdg(GlobalIdxToPDGCode[mcParticleIdx]); // PdgCode to the linked MC truth particle else From e41229a600e41d3abea41bad3c2f0c73e56c1f9c Mon Sep 17 00:00:00 2001 From: jesgum Date: Mon, 12 Oct 2026 16:08:22 +0200 Subject: [PATCH 2/3] Make megalinter happy --- ALICE3/Core/DetLayer.h | 16 ++++++++-------- ALICE3/Core/FastTracker.h | 2 +- ALICE3/Core/GeometryContainer.cxx | 1 - ALICE3/Core/GeometryContainer.h | 6 +++--- .../TableProducer/alice3TrackingTranslator.cxx | 6 +++--- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/ALICE3/Core/DetLayer.h b/ALICE3/Core/DetLayer.h index b3ed3ed6b34..eb5b1cf0550 100644 --- a/ALICE3/Core/DetLayer.h +++ b/ALICE3/Core/DetLayer.h @@ -108,25 +108,25 @@ struct DetLayer { TString mName; // position variables - float mR; // radius in centimeters - float mZ; // mZ dimension in centimeters + float mR{}; // radius in centimeters + float mZ{}; // mZ dimension in centimeters // material variables - float mX0; // radiation length - float mXrho; // density + float mX0{}; // radiation length + float mXrho{}; // density // resolution variables for active layers - float mResRPhi; // RPhi resolution in centimeters - float mResZ; // Z resolution in centimeters + float mResRPhi{}; // RPhi resolution in centimeters + float mResZ{}; // Z resolution in centimeters // efficiency - float mEff; // detection efficiency + float mEff{1.f}; // detection efficiency // dead regions in phi (in radians) TGraph* mDeadPhiRegions = nullptr; // layer type - int mType; // 0: undefined/inert, 1: silicon, 2: gas/tpc + int mType{0}; // 0: undefined/inert, 1: silicon, 2: gas/tpc }; } // namespace o2::fastsim diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index ed564095718..1d272595bbb 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -58,7 +58,7 @@ class FastTracker /// \param phiEnd End angle of the dead region (in radians) void addDeadPhiRegionInLayer(const std::string& layerName, float phiStart, float phiEnd); [[nodiscard]] DetLayer getLayer(const int layer) const { return layers[layer]; } - [[nodiscard]] std::vector getLayers() const { return layers; } + [[nodiscard]] const std::vector& getLayers() const { return layers; } [[nodiscard]] int getLayerIndex(const std::string& name) const; [[nodiscard]] size_t getNLayers() const { return layers.size(); } [[nodiscard]] bool isLayerInert(const int layer) const { return layers[layer].isInert(); } diff --git a/ALICE3/Core/GeometryContainer.cxx b/ALICE3/Core/GeometryContainer.cxx index 7936e66b629..950a310443c 100644 --- a/ALICE3/Core/GeometryContainer.cxx +++ b/ALICE3/Core/GeometryContainer.cxx @@ -19,7 +19,6 @@ #include "Common/Core/TableHelper.h" -#include #include #include diff --git a/ALICE3/Core/GeometryContainer.h b/ALICE3/Core/GeometryContainer.h index c343ecedbb0..deb69663e3b 100644 --- a/ALICE3/Core/GeometryContainer.h +++ b/ALICE3/Core/GeometryContainer.h @@ -36,8 +36,8 @@ struct GeometryEntry { // Default constructor GeometryEntry() = default; explicit GeometryEntry(const std::string& filename, o2::ccdb::BasicCCDBManager* ccdb = nullptr) + : mFileName(ConfigurationParser::accessFile(filename, "./.ALICE3/Configuration/", ccdb)) { - mFileName = ConfigurationParser::accessFile(filename, "./.ALICE3/Configuration/", ccdb); mConfigurations = ConfigurationParser::parseTEnvConfiguration(mFileName, mLayerNames); LOG(info) << "Loaded geometry configuration from file: " << mFileName << " with " << mLayerNames.size() << " layers."; if (mLayerNames.empty()) { @@ -45,9 +45,9 @@ struct GeometryEntry { } } - std::map> getConfigurations() const { return mConfigurations; } + const std::map>& getConfigurations() const { return mConfigurations; } std::map getConfiguration(const std::string& layerName) const; - std::vector getLayerNames() const { return mLayerNames; } + const std::vector& getLayerNames() const { return mLayerNames; } bool hasValue(const std::string& layerName, const std::string& key) const; std::string getValue(const std::string& layerName, const std::string& key, bool require = true) const; void setValue(const std::string& layerName, const std::string& key, const std::string& value) { mConfigurations[layerName][key] = value; } diff --git a/ALICE3/TableProducer/alice3TrackingTranslator.cxx b/ALICE3/TableProducer/alice3TrackingTranslator.cxx index c45ddeb1f71..26f53cf9f5f 100644 --- a/ALICE3/TableProducer/alice3TrackingTranslator.cxx +++ b/ALICE3/TableProducer/alice3TrackingTranslator.cxx @@ -419,7 +419,7 @@ struct Alice3TrackingTranslator { // Convert tracks from ACTS to ALICE format const size_t nParticlesSim = fileParticlesSim.m_vx->size(); const size_t nTracks = fileTracksummary.m_ePX_fit->size(); - std::vector idMCparticles; + // std::vector idMCparticles; // fixme: unused // local index k within this event -> global AO2D index int firstIdxThisEvent = tableStoredMcParticles.lastIndex() + 1; @@ -438,7 +438,7 @@ struct Alice3TrackingTranslator { fileParticlesSim.m_particle->at(iPart), fileParticlesSim.m_generation->at(iPart), fileParticlesSim.m_sub_particle->at(iPart)); - barcodeToGlobalIdx[key] = firstIdxThisEvent + (int)iPart; + barcodeToGlobalIdx[key] = firstIdxThisEvent + static_cast(iPart); if (iPart == 0) { tableMcCollisions(0, // mccollision::BCId, @@ -486,7 +486,7 @@ struct Alice3TrackingTranslator { } } for (size_t iPart = 0; iPart < nParticlesSim; ++iPart) { - int globalIdx = firstIdxThisEvent + (int)iPart; + int globalIdx = firstIdxThisEvent + static_cast(iPart); int motherIdx = -1; if (GlobalIdxToMotherIdx.find(globalIdx) != GlobalIdxToMotherIdx.end()) { motherIdx = GlobalIdxToMotherIdx[globalIdx]; From 2e1e87e940a4cb7172c9492afa41072f9a8616e2 Mon Sep 17 00:00:00 2001 From: jesgum Date: Mon, 12 Oct 2026 16:16:20 +0200 Subject: [PATCH 3/3] megalinter round 2 --- ALICE3/Core/GeometryContainer.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ALICE3/Core/GeometryContainer.cxx b/ALICE3/Core/GeometryContainer.cxx index 950a310443c..130c3f9e1e9 100644 --- a/ALICE3/Core/GeometryContainer.cxx +++ b/ALICE3/Core/GeometryContainer.cxx @@ -40,15 +40,15 @@ void GeometryContainer::init(o2::framework::InitContext& initContext) } LOG(info) << "Size of detector configuration: " << detectorConfiguration.size(); - bool cleanLutWhenLoaded; - const bool foundCleanLutWhenLoaded = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "cleanLutWhenLoaded", cleanLutWhenLoaded, false); + bool cleanLut; + const bool foundCleanLutWhenLoaded = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "cleanLutWhenLoaded", cleanLut, false); if (!foundCleanLutWhenLoaded) { LOG(fatal) << "Could not retrieve foundCleanLutWhenLoaded option from OnTheFlyDetectorGeometryProvider task."; return; } - setLutCleanupSetting(cleanLutWhenLoaded); + setLutCleanupSetting(cleanLut); - for (std::string& configFile : detectorConfiguration) { + for (const std::string& configFile : detectorConfiguration) { LOG(info) << "Detector geometry configuration file used: " << configFile; addEntry(configFile); }