From e43685d61c66101442540003ee35c87335acbdf0 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 14 Sep 2026 22:36:19 +0200 Subject: [PATCH 01/10] lowerCamelCase --- Common/Tools/PID/pidTPCModule.h | 94 ++++++++++++++++----------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 9e8d93c9e43..54d3a06fdfa 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -446,9 +446,9 @@ class pidTPCModule std::vector createNetworkPrediction(TCCDB& ccdb, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) { - std::vector network_prediction; + std::vector networkPrediction; - auto start_network_total = std::chrono::high_resolution_clock::now(); + auto startNetworkTotal = std::chrono::high_resolution_clock::now(); if (pidTPCopts.autofetchNetworks) { const auto& bc = bcs.begin(); // Initialise correct TPC response object before NN setup (for NCl normalisation) @@ -500,18 +500,18 @@ class pidTPCModule } // Defining some network parameters - int input_dimensions = network.getNumInputNodes(); - int output_dimensions = network.getNumOutputNodes(); - const uint64_t track_prop_size = input_dimensions * size; - const uint64_t prediction_size = output_dimensions * size; + int inputDimensions = network.getNumInputNodes(); + int outputDimensions = network.getNumOutputNodes(); + const uint64_t track_prop_size = inputDimensions * size; + const uint64_t prediction_size = outputDimensions * size; - network_prediction = std::vector(prediction_size * 9); // For each mass hypotheses + networkPrediction = std::vector(prediction_size * 9); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); - float duration_network = 0; + float durationNetwork = 0; - std::vector track_properties(track_prop_size); - uint64_t counter_track_props = 0; - int loop_counter = 0; + std::vector trackProperties(track_prop_size); + uint64_t counterTrackProps = 0; + int loopCounter = 0; // To load the Hadronic rate once for each collision float hadronicRateBegin = 0.; @@ -552,74 +552,74 @@ class pidTPCModule continue; } } - track_properties[counter_track_props] = trk.tpcInnerParam(); - track_properties[counter_track_props + 1] = trk.tgl(); - track_properties[counter_track_props + 2] = trk.signed1Pt(); - track_properties[counter_track_props + 3] = o2::track::pid_constants::sMasses[j]; - track_properties[counter_track_props + 4] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / 11000. : 1.; - track_properties[counter_track_props + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); - if (input_dimensions == ExpectedInputDimensionsNNV2 && networkVersion == NetworkVersionV2) { - track_properties[counter_track_props + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + trackProperties[counterTrackProps] = trk.tpcInnerParam(); + trackProperties[counterTrackProps + 1] = trk.tgl(); + trackProperties[counterTrackProps + 2] = trk.signed1Pt(); + trackProperties[counterTrackProps + 3] = o2::track::pid_constants::sMasses[j]; + trackProperties[counterTrackProps + 4] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / 11000. : 1.; + trackProperties[counterTrackProps + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); + if (inputDimensions == ExpectedInputDimensionsNNV2 && networkVersion == NetworkVersionV2) { + trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; } - if (input_dimensions == ExpectedInputDimensionsNNV3 && networkVersion == NetworkVersionV3) { - track_properties[counter_track_props + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + if (inputDimensions == ExpectedInputDimensionsNNV3 && networkVersion == NetworkVersionV3) { + trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; if (trk.has_collision() && mults.size() > 0) { if (collsys == CollisionSystemType::kCollSyspp) { - track_properties[counter_track_props + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; } else { - track_properties[counter_track_props + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; } } else { // asign Hadronic Rate at beginning of run if track does not belong to a collision if (collsys == CollisionSystemType::kCollSyspp) { - track_properties[counter_track_props + 7] = hadronicRateBegin / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / 1500.; } else { - track_properties[counter_track_props + 7] = hadronicRateBegin / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / 50.; } } } - if (input_dimensions == ExpectedInputDimensionsNNV4 && networkVersion == NetworkVersionV4) { - track_properties[counter_track_props + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + if (inputDimensions == ExpectedInputDimensionsNNV4 && networkVersion == NetworkVersionV4) { + trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; if (trk.has_collision() && mults.size() > 0) { if (collsys == CollisionSystemType::kCollSyspp) { - track_properties[counter_track_props + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; } else { - track_properties[counter_track_props + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; } } else { // asign Hadronic Rate at beginning of run if track does not belong to a collision if (collsys == CollisionSystemType::kCollSyspp) { - track_properties[counter_track_props + 7] = hadronicRateBegin / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / 1500.; } else { - track_properties[counter_track_props + 7] = hadronicRateBegin / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / 50.; } } - track_properties[counter_track_props + 8] = std::fmod(std::fmod(trk.phi(), 2 * M_PI) + 2 * M_PI, M_PI / 9.0); + trackProperties[counterTrackProps + 8] = std::fmod(std::fmod(trk.phi(), 2 * M_PI) + 2 * M_PI, M_PI / 9.0); } - counter_track_props += input_dimensions; + counterTrackProps += inputDimensions; } - auto start_network_eval = std::chrono::high_resolution_clock::now(); - float* output_network = network.evalModel(track_properties); - auto stop_network_eval = std::chrono::high_resolution_clock::now(); - duration_network += std::chrono::duration>(stop_network_eval - start_network_eval).count(); - for (uint64_t k = 0; k < prediction_size; k += output_dimensions) { - for (int l = 0; l < output_dimensions; l++) { - network_prediction[k + l + prediction_size * loop_counter] = output_network[k + l]; + auto startNetworkEval = std::chrono::high_resolution_clock::now(); + float* outputNetwork = network.evalModel(trackProperties); + auto stopNetworkEval = std::chrono::high_resolution_clock::now(); + durationNetwork += std::chrono::duration>(stopNetworkEval - startNetworkEval).count(); + for (uint64_t k = 0; k < prediction_size; k += outputDimensions) { + for (int l = 0; l < outputDimensions; l++) { + networkPrediction[k + l + prediction_size * loopCounter] = outputNetwork[k + l]; } } - counter_track_props = 0; - loop_counter += 1; + counterTrackProps = 0; + loopCounter += 1; } - track_properties.clear(); + trackProperties.clear(); - auto stop_network_total = std::chrono::high_resolution_clock::now(); - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << duration_network / (size * 9) << "ns ; Total time (eval ONNX): " << duration_network / 1000000000 << " s"; - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / (size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / 1000000000 << " s"; + auto stopNetworkTotal = std::chrono::high_resolution_clock::now(); + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << durationNetwork / (size * 9) << "ns ; Total time (eval ONNX): " << durationNetwork / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / (size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / 1000000000 << " s"; - return network_prediction; + return networkPrediction; } //__________________________________________________ From 3cc0c26229bc1d8f238d6d18eff9a099bfc9fd25 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 14 Sep 2026 22:47:48 +0200 Subject: [PATCH 02/10] add consts + lowerCamelCase --- Common/Tools/PID/pidTPCModule.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 54d3a06fdfa..a0fc66fe0a3 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -448,7 +448,7 @@ class pidTPCModule std::vector networkPrediction; - auto startNetworkTotal = std::chrono::high_resolution_clock::now(); + const auto startNetworkTotal = std::chrono::high_resolution_clock::now(); if (pidTPCopts.autofetchNetworks) { const auto& bc = bcs.begin(); // Initialise correct TPC response object before NN setup (for NCl normalisation) @@ -486,7 +486,7 @@ class pidTPCModule if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); - bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, bc.timestamp(), false, pidTPCopts.networkPathLocally.value, "", "", &headers); + const bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, bc.timestamp(), false, pidTPCopts.networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(pidTPCopts.networkPathLocally.value, pidTPCopts.enableNetworkOptimizations.value, pidTPCopts.networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); @@ -500,16 +500,16 @@ class pidTPCModule } // Defining some network parameters - int inputDimensions = network.getNumInputNodes(); - int outputDimensions = network.getNumOutputNodes(); - const uint64_t track_prop_size = inputDimensions * size; - const uint64_t prediction_size = outputDimensions * size; + const int inputDimensions = network.getNumInputNodes(); + const int outputDimensions = network.getNumOutputNodes(); + const uint64_t trackPropSize = inputDimensions * size; + const uint64_t predictionSize = outputDimensions * size; - networkPrediction = std::vector(prediction_size * 9); // For each mass hypotheses + networkPrediction = std::vector(predictionSize * 9); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); float durationNetwork = 0; - std::vector trackProperties(track_prop_size); + std::vector trackProperties(trackPropSize); uint64_t counterTrackProps = 0; int loopCounter = 0; @@ -600,13 +600,13 @@ class pidTPCModule counterTrackProps += inputDimensions; } - auto startNetworkEval = std::chrono::high_resolution_clock::now(); - float* outputNetwork = network.evalModel(trackProperties); - auto stopNetworkEval = std::chrono::high_resolution_clock::now(); + const auto startNetworkEval = std::chrono::high_resolution_clock::now(); + const float* const outputNetwork = network.evalModel(trackProperties); + const auto stopNetworkEval = std::chrono::high_resolution_clock::now(); durationNetwork += std::chrono::duration>(stopNetworkEval - startNetworkEval).count(); - for (uint64_t k = 0; k < prediction_size; k += outputDimensions) { + for (uint64_t k = 0; k < predictionSize; k += outputDimensions) { for (int l = 0; l < outputDimensions; l++) { - networkPrediction[k + l + prediction_size * loopCounter] = outputNetwork[k + l]; + networkPrediction[k + l + predictionSize * loopCounter] = outputNetwork[k + l]; } } @@ -615,7 +615,7 @@ class pidTPCModule } trackProperties.clear(); - auto stopNetworkTotal = std::chrono::high_resolution_clock::now(); + const auto stopNetworkTotal = std::chrono::high_resolution_clock::now(); LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << durationNetwork / (size * 9) << "ns ; Total time (eval ONNX): " << durationNetwork / 1000000000 << " s"; LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / (size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / 1000000000 << " s"; From f668a223166ffd5f82009f9edfa6b417f046a9b7 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 14 Sep 2026 23:11:17 +0200 Subject: [PATCH 03/10] give names to magic numbers --- Common/Tools/PID/pidTPCModule.h | 46 +++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index a0fc66fe0a3..8fbc1bc9653 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -30,6 +30,7 @@ #include "Common/TableProducer/PID/pidTPCBase.h" // IWYU pragma: keep #include "Tools/ML/model.h" +#include #include #include #include @@ -445,6 +446,13 @@ class pidTPCModule template std::vector createNetworkPrediction(TCCDB& ccdb, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) { + constexpr int NParticleTypes = 9; + constexpr double OneToKilo = 1.e-3; + constexpr double MultiplicityNorm = 11000.; + constexpr double HadronicRateNormPp = 1500.; + constexpr double HadronicRateNormAa = 50.; + constexpr double Ft0cOccupancyNorm = 60000.; + constexpr int NumberOfTpcSectors = 18; std::vector networkPrediction; @@ -505,7 +513,7 @@ class pidTPCModule const uint64_t trackPropSize = inputDimensions * size; const uint64_t predictionSize = outputDimensions * size; - networkPrediction = std::vector(predictionSize * 9); // For each mass hypotheses + networkPrediction = std::vector(predictionSize * NParticleTypes); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); float durationNetwork = 0; @@ -520,7 +528,7 @@ class pidTPCModule for (const auto& collision : collisions) { const auto& bc = collision.template bc_as(); if (irSource.compare("") != 0) { - hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; + hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * OneToKilo; } else { hadronicRateForCollision[i] = 0.0f; } @@ -528,14 +536,14 @@ class pidTPCModule } auto bc = bcs.begin(); if (irSource.compare("") != 0) { - hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; // kHz + hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * OneToKilo; } else { hadronicRateBegin = 0.0f; } // Filling a std::vector to be evaluated by the network // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector - static constexpr int NParticleTypes = 9; + constexpr int ExpectedInputDimensionsNNV2 = 7; constexpr int ExpectedInputDimensionsNNV3 = 8; constexpr int ExpectedInputDimensionsNNV4 = 9; @@ -556,46 +564,46 @@ class pidTPCModule trackProperties[counterTrackProps + 1] = trk.tgl(); trackProperties[counterTrackProps + 2] = trk.signed1Pt(); trackProperties[counterTrackProps + 3] = o2::track::pid_constants::sMasses[j]; - trackProperties[counterTrackProps + 4] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / 11000. : 1.; + trackProperties[counterTrackProps + 4] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / MultiplicityNorm : 1.; trackProperties[counterTrackProps + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); if (inputDimensions == ExpectedInputDimensionsNNV2 && networkVersion == NetworkVersionV2) { - trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; } if (inputDimensions == ExpectedInputDimensionsNNV3 && networkVersion == NetworkVersionV3) { - trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; if (trk.has_collision() && mults.size() > 0) { if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; } } else { // asign Hadronic Rate at beginning of run if track does not belong to a collision if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormAa; } } } if (inputDimensions == ExpectedInputDimensionsNNV4 && networkVersion == NetworkVersionV4) { - trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; if (trk.has_collision() && mults.size() > 0) { if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; } } else { // asign Hadronic Rate at beginning of run if track does not belong to a collision if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / 1500.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / 50.; + trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormAa; } } - trackProperties[counterTrackProps + 8] = std::fmod(std::fmod(trk.phi(), 2 * M_PI) + 2 * M_PI, M_PI / 9.0); + trackProperties[counterTrackProps + 8] = std::fmod(std::fmod(trk.phi(), o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); } counterTrackProps += inputDimensions; } @@ -616,8 +624,8 @@ class pidTPCModule trackProperties.clear(); const auto stopNetworkTotal = std::chrono::high_resolution_clock::now(); - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << durationNetwork / (size * 9) << "ns ; Total time (eval ONNX): " << durationNetwork / 1000000000 << " s"; - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / (size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << durationNetwork / (size * NParticleTypes) << "ns ; Total time (eval ONNX): " << durationNetwork / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / (size * NParticleTypes) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / 1000000000 << " s"; return networkPrediction; } From 9eab47d413c0512b189b6b2f79685198778beb3f Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 14 Sep 2026 23:40:44 +0200 Subject: [PATCH 04/10] introduce nnVersionsDictionary --- Common/Tools/PID/pidTPCModule.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 8fbc1bc9653..5bf039b9417 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include #include #include @@ -454,6 +456,19 @@ class pidTPCModule constexpr double Ft0cOccupancyNorm = 60000.; constexpr int NumberOfTpcSectors = 18; + struct NNVersionEntry { + std::string_view versionName{}; + int numberOfFeatures{}; + int versionNumber{}; + }; + + constexpr std::array nnVersionsDictionary{ + {{"", 6, 1}, + {"1", 6, 1}, + {"2", 7, 2}, + {"3", 8, 3}, + {"4", 9, 4}}}; + std::vector networkPrediction; const auto startNetworkTotal = std::chrono::high_resolution_clock::now(); @@ -513,6 +528,17 @@ class pidTPCModule const uint64_t trackPropSize = inputDimensions * size; const uint64_t predictionSize = outputDimensions * size; + int nnVersion{0}; + for (const auto& nnVersionEntry : nnVersionsDictionary) { + if (networkVersion == nnVersionEntry.versionName && inputDimensions == nnVersionEntry.numberOfFeatures) { + nnVersion = nnVersionEntry.versionNumber; + break; + } + } + if (nnVersion == 0) { + LOG(fatal) << "createNetworkPrediction(): networkVersion '" << networkVersion << "' and number of features " << inputDimensions << " are not compatible according to nnVersionsDictionary"; + } + networkPrediction = std::vector(predictionSize * NParticleTypes); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); float durationNetwork = 0; From 909aab35f585352641200daa7f94ad9943af49a1 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 14 Sep 2026 23:51:06 +0200 Subject: [PATCH 05/10] introduce enum IndexNnFeature --- Common/Tools/PID/pidTPCModule.h | 48 ++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 5bf039b9417..940e2befcfd 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -469,6 +469,18 @@ class pidTPCModule {"3", 8, 3}, {"4", 9, 4}}}; + enum IndexNnFeature : int { + IdxTpcInnerParam = 0, + IdxTgl, + IdxSigned1Pt, + IdxMass, + IdxMultiplicity, + IdxNClusters, + IdxFt0cOcc, + IdxHadronicRate, + IdxModPhi + }; + std::vector networkPrediction; const auto startNetworkTotal = std::chrono::high_resolution_clock::now(); @@ -586,50 +598,50 @@ class pidTPCModule continue; } } - trackProperties[counterTrackProps] = trk.tpcInnerParam(); - trackProperties[counterTrackProps + 1] = trk.tgl(); - trackProperties[counterTrackProps + 2] = trk.signed1Pt(); - trackProperties[counterTrackProps + 3] = o2::track::pid_constants::sMasses[j]; - trackProperties[counterTrackProps + 4] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / MultiplicityNorm : 1.; - trackProperties[counterTrackProps + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); + trackProperties[counterTrackProps + IdxTpcInnerParam] = trk.tpcInnerParam(); + trackProperties[counterTrackProps + IdxTgl] = trk.tgl(); + trackProperties[counterTrackProps + IdxSigned1Pt] = trk.signed1Pt(); + trackProperties[counterTrackProps + IdxMass] = o2::track::pid_constants::sMasses[j]; + trackProperties[counterTrackProps + IdxMultiplicity] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / MultiplicityNorm : 1.; + trackProperties[counterTrackProps + IdxNClusters] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); if (inputDimensions == ExpectedInputDimensionsNNV2 && networkVersion == NetworkVersionV2) { - trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; + trackProperties[counterTrackProps + IdxFt0cOcc] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; } if (inputDimensions == ExpectedInputDimensionsNNV3 && networkVersion == NetworkVersionV3) { - trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; + trackProperties[counterTrackProps + IdxFt0cOcc] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; if (trk.has_collision() && mults.size() > 0) { if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; } } else { // asign Hadronic Rate at beginning of run if track does not belong to a collision if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormPp; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormAa; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormAa; } } } if (inputDimensions == ExpectedInputDimensionsNNV4 && networkVersion == NetworkVersionV4) { - trackProperties[counterTrackProps + 6] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; + trackProperties[counterTrackProps + IdxFt0cOcc] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; if (trk.has_collision() && mults.size() > 0) { if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; } } else { // asign Hadronic Rate at beginning of run if track does not belong to a collision if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormPp; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormPp; } else { - trackProperties[counterTrackProps + 7] = hadronicRateBegin / HadronicRateNormAa; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormAa; } } - trackProperties[counterTrackProps + 8] = std::fmod(std::fmod(trk.phi(), o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); + trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(trk.phi(), o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); } counterTrackProps += inputDimensions; } From b1935ad333d6569243fcc2e1d2c6e6958606ab4b Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 15 Sep 2026 00:09:27 +0200 Subject: [PATCH 06/10] DRY fill trackProperties --- Common/Tools/PID/pidTPCModule.h | 57 ++++++++------------------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 940e2befcfd..9f363587d7d 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -481,6 +481,10 @@ class pidTPCModule IdxModPhi }; + constexpr int OldestNNVersionWithFt0c{2}; + constexpr int OldestNNVersionWithHadronicRate{3}; + constexpr int OldestNNVersionWithModPhi{4}; + std::vector networkPrediction; const auto startNetworkTotal = std::chrono::high_resolution_clock::now(); @@ -551,6 +555,8 @@ class pidTPCModule LOG(fatal) << "createNetworkPrediction(): networkVersion '" << networkVersion << "' and number of features " << inputDimensions << " are not compatible according to nnVersionsDictionary"; } + const int hadronicRateNorm = collsys == CollisionSystemType::kCollSyspp ? HadronicRateNormPp : HadronicRateNormAa; + networkPrediction = std::vector(predictionSize * NParticleTypes); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); float durationNetwork = 0; @@ -581,13 +587,6 @@ class pidTPCModule // Filling a std::vector to be evaluated by the network // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector - - constexpr int ExpectedInputDimensionsNNV2 = 7; - constexpr int ExpectedInputDimensionsNNV3 = 8; - constexpr int ExpectedInputDimensionsNNV4 = 9; - constexpr auto NetworkVersionV2 = "2"; - constexpr auto NetworkVersionV3 = "3"; - constexpr auto NetworkVersionV4 = "4"; for (int j = 0; j < NParticleTypes; j++) { // Loop over particle number for which network correction is used for (auto const& trk : tracks) { if (!trk.hasTPC()) { @@ -598,49 +597,21 @@ class pidTPCModule continue; } } + const bool isGoodTrack = trk.has_collision() && mults.size() > 0; trackProperties[counterTrackProps + IdxTpcInnerParam] = trk.tpcInnerParam(); trackProperties[counterTrackProps + IdxTgl] = trk.tgl(); trackProperties[counterTrackProps + IdxSigned1Pt] = trk.signed1Pt(); trackProperties[counterTrackProps + IdxMass] = o2::track::pid_constants::sMasses[j]; - trackProperties[counterTrackProps + IdxMultiplicity] = (trk.has_collision() && mults.size() > 0) ? mults[trk.collisionId()] / MultiplicityNorm : 1.; + trackProperties[counterTrackProps + IdxMultiplicity] = isGoodTrack ? mults[trk.collisionId()] / MultiplicityNorm : 1.; trackProperties[counterTrackProps + IdxNClusters] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); - if (inputDimensions == ExpectedInputDimensionsNNV2 && networkVersion == NetworkVersionV2) { - trackProperties[counterTrackProps + IdxFt0cOcc] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; + if (nnVersion >= OldestNNVersionWithFt0c) { + trackProperties[counterTrackProps + IdxFt0cOcc] = isGoodTrack ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; } - if (inputDimensions == ExpectedInputDimensionsNNV3 && networkVersion == NetworkVersionV3) { - trackProperties[counterTrackProps + IdxFt0cOcc] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; - if (trk.has_collision() && mults.size() > 0) { - if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; - } else { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; - } - } else { - // asign Hadronic Rate at beginning of run if track does not belong to a collision - if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormPp; - } else { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormAa; - } - } + if (nnVersion >= OldestNNVersionWithHadronicRate) { + const float hadronicRate = isGoodTrack ? hadronicRateForCollision[trk.collisionId()] : hadronicRateBegin; + trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRate / hadronicRateNorm; } - - if (inputDimensions == ExpectedInputDimensionsNNV4 && networkVersion == NetworkVersionV4) { - trackProperties[counterTrackProps + IdxFt0cOcc] = (trk.has_collision() && mults.size() > 0) ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / Ft0cOccupancyNorm : 1.; - if (trk.has_collision() && mults.size() > 0) { - if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormPp; - } else { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateForCollision[trk.collisionId()] / HadronicRateNormAa; - } - } else { - // asign Hadronic Rate at beginning of run if track does not belong to a collision - if (collsys == CollisionSystemType::kCollSyspp) { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormPp; - } else { - trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRateBegin / HadronicRateNormAa; - } - } + if (nnVersion >= OldestNNVersionWithModPhi) { trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(trk.phi(), o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); } counterTrackProps += inputDimensions; From 9720ad07a47d10dcdc9d66ff59e274b4215b5610 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 15 Sep 2026 00:30:35 +0200 Subject: [PATCH 07/10] DRY handronicRate, unfold cryptic variables --- Common/Tools/PID/pidTPCModule.h | 34 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 9f363587d7d..822c236bfed 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -450,6 +450,7 @@ class pidTPCModule { constexpr int NParticleTypes = 9; constexpr double OneToKilo = 1.e-3; + constexpr int NanoToOne = 1000000000; constexpr double MultiplicityNorm = 11000.; constexpr double HadronicRateNormPp = 1500.; constexpr double HadronicRateNormAa = 50.; @@ -566,28 +567,21 @@ class pidTPCModule int loopCounter = 0; // To load the Hadronic rate once for each collision - float hadronicRateBegin = 0.; std::vector hadronicRateForCollision(collisions.size(), 0.0f); - size_t i = 0; + size_t iCollision = 0; for (const auto& collision : collisions) { const auto& bc = collision.template bc_as(); if (irSource.compare("") != 0) { - hadronicRateForCollision[i] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * OneToKilo; - } else { - hadronicRateForCollision[i] = 0.0f; + hadronicRateForCollision[iCollision] = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * OneToKilo; } - i++; - } - auto bc = bcs.begin(); - if (irSource.compare("") != 0) { - hadronicRateBegin = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * OneToKilo; - } else { - hadronicRateBegin = 0.0f; + ++iCollision; } + const auto bc = bcs.begin(); + const float hadronicRateBegin = irSource.compare("") != 0 ? mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * OneToKilo : 0.f; // Filling a std::vector to be evaluated by the network // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector - for (int j = 0; j < NParticleTypes; j++) { // Loop over particle number for which network correction is used + for (int jParticleType = 0; jParticleType < NParticleTypes; ++jParticleType) { // Loop over particle number for which network correction is used for (auto const& trk : tracks) { if (!trk.hasTPC()) { continue; @@ -601,7 +595,7 @@ class pidTPCModule trackProperties[counterTrackProps + IdxTpcInnerParam] = trk.tpcInnerParam(); trackProperties[counterTrackProps + IdxTgl] = trk.tgl(); trackProperties[counterTrackProps + IdxSigned1Pt] = trk.signed1Pt(); - trackProperties[counterTrackProps + IdxMass] = o2::track::pid_constants::sMasses[j]; + trackProperties[counterTrackProps + IdxMass] = o2::track::pid_constants::sMasses[jParticleType]; trackProperties[counterTrackProps + IdxMultiplicity] = isGoodTrack ? mults[trk.collisionId()] / MultiplicityNorm : 1.; trackProperties[counterTrackProps + IdxNClusters] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); if (nnVersion >= OldestNNVersionWithFt0c) { @@ -620,10 +614,10 @@ class pidTPCModule const auto startNetworkEval = std::chrono::high_resolution_clock::now(); const float* const outputNetwork = network.evalModel(trackProperties); const auto stopNetworkEval = std::chrono::high_resolution_clock::now(); - durationNetwork += std::chrono::duration>(stopNetworkEval - startNetworkEval).count(); - for (uint64_t k = 0; k < predictionSize; k += outputDimensions) { - for (int l = 0; l < outputDimensions; l++) { - networkPrediction[k + l + predictionSize * loopCounter] = outputNetwork[k + l]; + durationNetwork += std::chrono::duration>(stopNetworkEval - startNetworkEval).count(); + for (uint64_t kPrediction = 0; kPrediction < predictionSize; kPrediction += outputDimensions) { + for (int lOutputDim = 0; lOutputDim < outputDimensions; ++lOutputDim) { + networkPrediction[kPrediction + lOutputDim + predictionSize * loopCounter] = outputNetwork[kPrediction + lOutputDim]; } } @@ -633,8 +627,8 @@ class pidTPCModule trackProperties.clear(); const auto stopNetworkTotal = std::chrono::high_resolution_clock::now(); - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << durationNetwork / (size * NParticleTypes) << "ns ; Total time (eval ONNX): " << durationNetwork / 1000000000 << " s"; - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / (size * NParticleTypes) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << durationNetwork / (size * NParticleTypes) << "ns ; Total time (eval ONNX): " << durationNetwork / NanoToOne << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / (size * NParticleTypes) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stopNetworkTotal - startNetworkTotal).count() / NanoToOne << " s"; return networkPrediction; } From 3cbdc4ce07dc8d1802bbe1c57e59711f94c1dccc Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 15 Sep 2026 01:15:39 +0200 Subject: [PATCH 08/10] introduce NN version 5 --- Common/Tools/PID/pidTPCModule.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 822c236bfed..17e41e57acb 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -31,6 +31,7 @@ #include "Tools/ML/model.h" #include +#include #include #include #include @@ -142,6 +143,9 @@ struct pidTPCConfigurables : o2::framework::ConfigurableGroup { o2::framework::Configurable useNetworkAl{"useNetworkAl", 1, {"Switch for applying neural network on the alpha mass hypothesis (if network enabled) (set to 0 to disable)"}}; o2::framework::Configurable networkBetaGammaCutoff{"networkBetaGammaCutoff", 0.45, {"Lower value of beta-gamma to override the NN application"}}; o2::framework::Configurable cfgPathGrpLhcIf{"ccdb-path-grplhcif", "GLO/Config/GRPLHCIF", "Path on the CCDB for the GRPLHCIF object"}; + + o2::framework::Configurable phiEntranceCoeff1{"phiEntranceCoeff1", 1.026f, "phiEntrance = phi + phiEntranceCoeff1 * LightSpeedDm2PS * 0.5 * phiEntranceCoeff2 * 1/pT[GeV/c]"}; + o2::framework::Configurable phiEntranceCoeff2{"phiEntranceCoeff2", 85.f, "phiEntrance = phi + phiEntranceCoeff1 * LightSpeedDm2PS * 0.5 * phiEntranceCoeff2 * 1/pT[GeV/c]"}; }; // helper getter - FIXME should be separate @@ -456,6 +460,7 @@ class pidTPCModule constexpr double HadronicRateNormAa = 50.; constexpr double Ft0cOccupancyNorm = 60000.; constexpr int NumberOfTpcSectors = 18; + constexpr float LightSpeedDm2PS = o2::constants::physics::LightSpeedCm2PS / 10.f; struct NNVersionEntry { std::string_view versionName{}; @@ -463,12 +468,13 @@ class pidTPCModule int versionNumber{}; }; - constexpr std::array nnVersionsDictionary{ + constexpr std::array nnVersionsDictionary{ {{"", 6, 1}, {"1", 6, 1}, {"2", 7, 2}, {"3", 8, 3}, - {"4", 9, 4}}}; + {"4", 9, 4}, + {"5", 9, 5}}}; enum IndexNnFeature : int { IdxTpcInnerParam = 0, @@ -485,6 +491,7 @@ class pidTPCModule constexpr int OldestNNVersionWithFt0c{2}; constexpr int OldestNNVersionWithHadronicRate{3}; constexpr int OldestNNVersionWithModPhi{4}; + constexpr int NNVersionWithModPhiEntrance{5}; std::vector networkPrediction; @@ -606,7 +613,11 @@ class pidTPCModule trackProperties[counterTrackProps + IdxHadronicRate] = hadronicRate / hadronicRateNorm; } if (nnVersion >= OldestNNVersionWithModPhi) { - trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(trk.phi(), o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); + float phi = trk.phi(); + if (nnVersion == NNVersionWithModPhiEntrance) { + phi += pidTPCopts.phiEntranceCoeff1 * LightSpeedDm2PS * 0.5 * pidTPCopts.phiEntranceCoeff2 * trk.signed1Pt(); + } + trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(phi, o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); } counterTrackProps += inputDimensions; } From 40d784f28864cbd7f59aee3bcf2945d877fcad10 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 15 Sep 2026 01:20:46 +0200 Subject: [PATCH 09/10] minor cleaning --- Common/Tools/PID/pidTPCModule.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 17e41e57acb..a57a53f05fb 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -459,7 +459,6 @@ class pidTPCModule constexpr double HadronicRateNormPp = 1500.; constexpr double HadronicRateNormAa = 50.; constexpr double Ft0cOccupancyNorm = 60000.; - constexpr int NumberOfTpcSectors = 18; constexpr float LightSpeedDm2PS = o2::constants::physics::LightSpeedCm2PS / 10.f; struct NNVersionEntry { @@ -617,7 +616,7 @@ class pidTPCModule if (nnVersion == NNVersionWithModPhiEntrance) { phi += pidTPCopts.phiEntranceCoeff1 * LightSpeedDm2PS * 0.5 * pidTPCopts.phiEntranceCoeff2 * trk.signed1Pt(); } - trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(phi, o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / NumberOfTpcSectors); + trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(phi, o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / o2::constants::math::NSectors); } counterTrackProps += inputDimensions; } @@ -633,7 +632,7 @@ class pidTPCModule } counterTrackProps = 0; - loopCounter += 1; + ++loopCounter; } trackProperties.clear(); From 3a4cbd3af61ce48bfe0dafea667d302d4520cffc Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 15 Sep 2026 01:45:20 +0200 Subject: [PATCH 10/10] replace std::fmod() with RecoDecay::constrainAngle() --- Common/Tools/PID/pidTPCModule.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index a57a53f05fb..78402587660 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -24,6 +24,7 @@ #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/CollisionTypeHelper.h" #include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TableHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTPC.h" @@ -616,7 +617,7 @@ class pidTPCModule if (nnVersion == NNVersionWithModPhiEntrance) { phi += pidTPCopts.phiEntranceCoeff1 * LightSpeedDm2PS * 0.5 * pidTPCopts.phiEntranceCoeff2 * trk.signed1Pt(); } - trackProperties[counterTrackProps + IdxModPhi] = std::fmod(std::fmod(phi, o2::constants::math::TwoPI) + o2::constants::math::TwoPI, o2::constants::math::TwoPI / o2::constants::math::NSectors); + trackProperties[counterTrackProps + IdxModPhi] = RecoDecay::constrainAngle(phi, 0.f, o2::constants::math::NSectors); } counterTrackProps += inputDimensions; }