From 4d109aff27e6d1de8aee28082ea531ed564f805a Mon Sep 17 00:00:00 2001 From: gianniliveraro Date: Thu, 24 Jul 2025 21:20:15 -0300 Subject: [PATCH 1/3] New deduplication modes + V0DCAToPV in buildV0Candidate --- .../TableProducer/Strangeness/CMakeLists.txt | 2 +- .../Strangeness/strangenessbuilder.cxx | 366 ++++++++++++++---- PWGLF/Utils/strangenessBuilderHelper.h | 12 + 3 files changed, 314 insertions(+), 66 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index bc8ba1da673..1224f01df0f 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -108,7 +108,7 @@ o2physics_add_dpl_workflow(strangederivedbuilder o2physics_add_dpl_workflow(strangenessbuilder SOURCES strangenessbuilder.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(v0-selector diff --git a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx index 0cf07e8de4d..e7150e58556 100644 --- a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx @@ -48,9 +48,12 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "Common/Core/TPCVDriftManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" using namespace o2; using namespace o2::framework; +using namespace o2::ml; static constexpr int nParameters = 1; static const std::vector tableNames{ @@ -156,6 +159,9 @@ struct StrangenessBuilder { // helper object o2::pwglf::strangenessBuilderHelper straHelper; + // ML model + o2::ml::OnnxModel deduplication_bdt; + // table index : match order above enum tableIndex { kV0Indices = 0, kV0CoresBase, @@ -291,9 +297,34 @@ struct StrangenessBuilder { Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; } ccdbConfigurations; - // first order deduplication implementation - // more algorithms to be added as necessary - Configurable deduplicationAlgorithm{"deduplicationAlgorithm", 1, "0: disabled; 1: best pointing angle wins; 2: best DCA daughters wins; 3: best pointing and best DCA wins"}; + // ML options + std::map metadata; + + struct : ConfigurableGroup { + std::string prefix = "DeduplicationOpts"; + + Configurable deduplicationAlgorithm{"deduplicationAlgorithm", 1, + "0: disabled;" + "1: best pointing angle wins;" + "2: best DCA daughters wins;" + "3: best pointing and best DCA wins;" + "4: best BDT score wins;" + "5: selects on PA (not a winner takes it all approach!);" + "6: selects on BDT score (not a winner takes it all approach!)"}; + + // BDT settings + Configurable ccdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable BDTLocalPath{"BDTLocalPath", "Deduplication_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/g/gsetouel/MLModels2", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + + // Selection based duplicates removal + Configurable PAthreshold{"PAthreshold", 0.02, "PA cut to remove duplicates."}; + Configurable BDTthreshold{"BDTthreshold", 0.7, "BDT score cut to remove duplicates."}; + + } DeduplicationOpts; // V0 buffer for V0s used in cascades: master switch // exchanges CPU (generate V0s again) with memory (save pre-generated V0s) @@ -515,7 +546,18 @@ struct StrangenessBuilder { int mcParticleBachelor; }; mcCascinfo thisCascInfo; - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // Helper structure to save v0 duplicates auxiliary info + struct V0DuplicateExtra { + bool isBestPA; + bool isBestDCADau; + bool isBestMLScore; + bool isBuildOk; + float PA; + float V0DCAToPVz; + float V0z; + float MLScore; + }; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -594,6 +636,14 @@ struct StrangenessBuilder { hFindable->GetXaxis()->SetBinLabel(6, "Cascades with collId -1"); } + if (DeduplicationOpts.deduplicationAlgorithm.value > 0){ + histos.add("DeduplicationQA/hMLScore", "hMLScore", kTH1F, {{200, 0.0f, 1.0f}}); + histos.add("DeduplicationQA/hPA", "hPA", kTH1F, {{200, 0.0f, 0.4f}}); + histos.add("DeduplicationQA/hBestPA", "hBestPA", kTH1F, {{200, 0.0f, 0.4f}}); + histos.add("DeduplicationQA/hBestDCADau", "hBestDCADau", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("DeduplicationQA/hBestMLScore", "hBestMLScore", kTH1F, {{200, 0.0f, 1.0f}}); + } + auto hPrimaryV0s = histos.add("hPrimaryV0s", "hPrimaryV0s", kTH1D, {{2, -0.5f, 1.5f}}); hPrimaryV0s->GetXaxis()->SetBinLabel(1, "All V0s"); hPrimaryV0s->GetXaxis()->SetBinLabel(2, "Primary V0s"); @@ -714,6 +764,27 @@ struct StrangenessBuilder { straHelper.cascadeselections.dcacascdau = cascadeBuilderOpts.dcacascdau; straHelper.cascadeselections.lambdaMassWindow = cascadeBuilderOpts.lambdaMassWindow; straHelper.cascadeselections.maxDaughterEta = cascadeBuilderOpts.maxDaughterEta; + + // Loading BDT model + if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ + if (DeduplicationOpts.loadModelsFromCCDB) { + // Retrieve the model from CCDB + ccdbApi.init(DeduplicationOpts.ccdbUrl); + + /// Fetching model for specific timestamp + LOG(info) << "Fetching model for timestamp: " << DeduplicationOpts.timestampCCDB.value; + + bool retrieveSuccess = ccdbApi.retrieveBlob(DeduplicationOpts.BDTPathCCDB.value, ".", metadata, DeduplicationOpts.timestampCCDB.value, false, DeduplicationOpts.BDTLocalPath.value); + if (retrieveSuccess) { + deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + else{ + deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); + } + } } // for sorting @@ -730,6 +801,209 @@ struct StrangenessBuilder { return idx; } + // Simple function to rank vectors based on values + std::vector rankSort(const std::vector& v_temp, bool descending = false) { + std::vector> v_sort(v_temp.size()); + + // Pair each value with its original index + for (size_t i = 0U; i < v_temp.size(); ++i) { + v_sort[i] = std::make_pair(v_temp[i], i); + } + + // Sort by value - ascending: lowest gets rank 1, descending: highest gets rank 1 + + if (descending) { + std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { + return a.first > b.first; + }); + } else { + std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { + return a.first < b.first; + }); + } + + std::pair rank_tracker = std::make_pair(std::numeric_limits::quiet_NaN(), 0); + std::vector result(v_temp.size()); + + for (size_t i = 0U; i < v_sort.size(); ++i) { + // Only update rank if value is different from previous + if (v_sort[i].first != rank_tracker.first) { + rank_tracker = std::make_pair(v_sort[i].first, i + 1); // +1 for 1-based rank + } + result[v_sort[i].second] = rank_tracker.second; // assign rank to original index + } + + return result; + } + + //_______________________________________________________________________ + // Process duplicated photons + template + std::vector processDuplicates(TCollisions const& collisions, TTracks const& tracks, std::vector V0Grouped, size_t iV0) + { + auto pTrack = tracks.rawIteratorAt(V0Grouped[iV0].posTrackId); + auto nTrack = tracks.rawIteratorAt(V0Grouped[iV0].negTrackId); + + bool isPosTPCOnly = (pTrack.hasTPC() && !pTrack.hasITS() && !pTrack.hasTRD() && !pTrack.hasTOF()); + bool isNegTPCOnly = (nTrack.hasTPC() && !nTrack.hasITS() && !nTrack.hasTRD() && !nTrack.hasTOF()); + + // don't try to de-duplicate if no track is TPC only + if (!isPosTPCOnly && !isNegTPCOnly) { + return {}; + } + + // fitness criteria defined here + float bestPointingAngle = 10; // a nonsense angle, anything's better + size_t bestPointingAngleIndex = -1; + + float bestDCADaughters = 1e+3; // an excessively large DCA + size_t bestDCADaughtersIndex = -1; + + float bestMLScore = -1; // a nonsense ML score + size_t bestMLScoreIndex = -1; + + // Defining context variables + int NDuplicates = 0; + float AvgPA = 0.0f; + + // Containers for ranking + std::vector paVec(V0Grouped[iV0].collisionIds.size(), 999.f); + std::vector v0zVec(V0Grouped[iV0].collisionIds.size(), 999.f); + + // Auxiliary vector to store V0 duplicate info + std::vector V0DuplicateExtras; + + // Loop over duplicates + for (size_t ic = 0; ic < V0Grouped[iV0].collisionIds.size(); ic++) { + + // Helper structure to save duplicates info - initializing with dummy values + V0DuplicateExtra v0DuplicateInfo; + v0DuplicateInfo.isBestPA = false; + v0DuplicateInfo.isBestDCADau = false; + v0DuplicateInfo.isBestMLScore = false; + v0DuplicateInfo.isBuildOk = false; + v0DuplicateInfo.PA = 10; + v0DuplicateInfo.V0DCAToPVz = 999.f; + v0DuplicateInfo.V0z = 999.f; + v0DuplicateInfo.MLScore = -1; + + // We include V0DuplicateExtra info in the vector at this point to avoid indexing issues later + V0DuplicateExtras.push_back(v0DuplicateInfo); + + // get track parametrizations, collisions + auto posTrackPar = getTrackParCov(pTrack); + auto negTrackPar = getTrackParCov(nTrack); + auto const& collision = collisions.rawIteratorAt(V0Grouped[iV0].collisionIds[ic]); + + // handle TPC-only tracks properly (photon conversions) + if (v0BuilderOpts.moveTPCOnlyTracks) { + if (isPosTPCOnly) { + // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + if (!mVDriftMgr.moveTPCTrack(collision, pTrack, posTrackPar)) { + continue; + } + } + if (isNegTPCOnly) { + // Nota bene: negative is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + if (!mVDriftMgr.moveTPCTrack(collision, nTrack, negTrackPar)) { + continue; + } + } + } // end TPC drift treatment + + // process candidate with helper, generate properties for consulting + // : do not apply selections: do as much as possible to preserve + // candidate at this level and do not select with topo selections + if (straHelper.buildV0Candidate(V0Grouped[iV0].collisionIds[ic], collision.posX(), collision.posY(), collision.posZ(), pTrack, nTrack, posTrackPar, negTrackPar, true, false, true)) { + + // candidate built, check pointing angle + if (straHelper.v0.pointingAngle < bestPointingAngle) { + bestPointingAngle = straHelper.v0.pointingAngle; + bestPointingAngleIndex = ic; + } + if (straHelper.v0.daughterDCA < bestDCADaughters) { + bestDCADaughters = straHelper.v0.daughterDCA; + bestDCADaughtersIndex = ic; + } + + // Calculating features for ML Analysis + if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ + AvgPA += straHelper.v0.pointingAngle; + paVec[ic] = straHelper.v0.pointingAngle; + v0zVec[ic] = std::abs(straHelper.v0.position[2]); + NDuplicates++; + } + + // Updating values in the struct + V0DuplicateExtras[ic].isBuildOk = true; + V0DuplicateExtras[ic].PA = straHelper.v0.pointingAngle; + V0DuplicateExtras[ic].V0DCAToPVz = std::abs(straHelper.v0.v0DCAToPVz); + V0DuplicateExtras[ic].V0z = std::abs(straHelper.v0.position[2]); + } // end build V0 + } // end candidate loop + + + // Additional loop to perform ML Analysis if requested + if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ + + // Preparing features + if (NDuplicates > 0) + AvgPA /= NDuplicates; + + // Get vector of ranks + std::vector paRanks = rankSort(paVec, false); + std::vector v0zRanks = rankSort(v0zVec, false); + + // Fill the ML score for all candidates + for (size_t ic = 0; ic < V0Grouped[iV0].collisionIds.size(); ic++) { + + // Skip if v0 was not built + if (!V0DuplicateExtras[ic].isBuildOk) + continue; + + // Input vector for BDT + std::vector inputFeatures{V0DuplicateExtras[ic].V0DCAToPVz, // 1. V0DCAToPVz + V0DuplicateExtras[ic].PA, // 2. PointingAngle + V0DuplicateExtras[ic].V0z, // 3. V0z + static_cast(paRanks[ic]), // 4. V0PARank + static_cast(NDuplicates), // 5. V0NDuplicates + AvgPA, // 6. V0AvgPA + static_cast(v0zRanks[ic])}; // 7. V0ZRank + + + float* BDTProbability = deduplication_bdt.evalModel(inputFeatures); + + if (BDTProbability[1] > bestMLScore) { + bestMLScore = BDTProbability[1]; + bestMLScoreIndex = ic; + } + + // QA histo + histos.fill(HIST("DeduplicationQA/hMLScore"), BDTProbability[1]); + histos.fill(HIST("DeduplicationQA/hPA"), V0DuplicateExtras[ic].PA); + + // Updating BDT score info in the struct + V0DuplicateExtras[ic].MLScore = BDTProbability[1]; + } + } + + histos.fill(HIST("DeduplicationQA/hBestPA"), bestPointingAngle); + histos.fill(HIST("DeduplicationQA/hBestDCADau"), bestDCADaughters); + histos.fill(HIST("DeduplicationQA/hBestMLScore"), bestMLScore); + + // Final step: Defining the winners: + if (bestPointingAngleIndex != static_cast(-1)) V0DuplicateExtras[bestPointingAngleIndex].isBestPA = true; + if (bestDCADaughtersIndex != static_cast(-1)) V0DuplicateExtras[bestDCADaughtersIndex].isBestDCADau = true; + if (bestMLScoreIndex != static_cast(-1)) V0DuplicateExtras[bestMLScoreIndex].isBestMLScore = true; + + // return vector with duplicates info + return V0DuplicateExtras; + } + template bool initCCDB(aod::BCsWithTimestamps const& bcs, TCollisions const& collisions) { @@ -885,7 +1159,7 @@ struct StrangenessBuilder { // keep all unless de-duplication active ao2dV0toV0List.resize(v0s.size(), -1); // -1 means keep, -2 means do not keep - if (deduplicationAlgorithm > 0 && v0BuilderOpts.generatePhotonCandidates) { + if (DeduplicationOpts.deduplicationAlgorithm.value > 0 && v0BuilderOpts.generatePhotonCandidates) { // handle duplicates explicitly: group V0s according to (p,n) indices // will provide a list of collisionIds (in V0group), allowing for // easy de-duplication when passing to the v0List @@ -895,82 +1169,44 @@ struct StrangenessBuilder { // process grouped duplicates, remove 'bad' ones for (size_t iV0 = 0; iV0 < v0tableGrouped.size(); iV0++) { - auto pTrack = tracks.rawIteratorAt(v0tableGrouped[iV0].posTrackId); - auto nTrack = tracks.rawIteratorAt(v0tableGrouped[iV0].negTrackId); - - bool isPosTPCOnly = (pTrack.hasTPC() && !pTrack.hasITS() && !pTrack.hasTRD() && !pTrack.hasTOF()); - bool isNegTPCOnly = (nTrack.hasTPC() && !nTrack.hasITS() && !nTrack.hasTRD() && !nTrack.hasTOF()); // skip single copy V0s if (v0tableGrouped[iV0].collisionIds.size() == 1) { continue; } - // don't try to de-duplicate if no track is TPC only - if (!isPosTPCOnly && !isNegTPCOnly) { - continue; - } - - // fitness criteria defined here - float bestPointingAngle = 10; // a nonsense angle, anything's better - size_t bestPointingAngleIndex = -1; + // process duplicates + std::vector deduplicationOutput = processDuplicates(collisions, tracks, v0tableGrouped, iV0); - float bestDCADaughters = 1e+3; // an excessively large DCA - size_t bestDCADaughtersIndex = -1; - - for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { - // get track parametrizations, collisions - auto posTrackPar = getTrackParCov(pTrack); - auto negTrackPar = getTrackParCov(nTrack); - auto const& collision = collisions.rawIteratorAt(v0tableGrouped[iV0].collisionIds[ic]); - - // handle TPC-only tracks properly (photon conversions) - if (v0BuilderOpts.moveTPCOnlyTracks) { - if (isPosTPCOnly) { - // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate - posTrackPar.setPID(o2::track::PID::Electron); - negTrackPar.setPID(o2::track::PID::Electron); - if (!mVDriftMgr.moveTPCTrack(collision, pTrack, posTrackPar)) { - return; - } - } - if (isNegTPCOnly) { - // Nota bene: negative is TPC-only -> this entire V0 merits treatment as photon candidate - posTrackPar.setPID(o2::track::PID::Electron); - negTrackPar.setPID(o2::track::PID::Electron); - if (!mVDriftMgr.moveTPCTrack(collision, nTrack, negTrackPar)) { - return; - } - } - } // end TPC drift treatment - - // process candidate with helper, generate properties for consulting - // : do not apply selections: do as much as possible to preserve - // candidate at this level and do not select with topo selections - if (straHelper.buildV0Candidate(v0tableGrouped[iV0].collisionIds[ic], collision.posX(), collision.posY(), collision.posZ(), pTrack, nTrack, posTrackPar, negTrackPar, true, false, true)) { - // candidate built, check pointing angle - if (straHelper.v0.pointingAngle < bestPointingAngle) { - bestPointingAngle = straHelper.v0.pointingAngle; - bestPointingAngleIndex = ic; - } - if (straHelper.v0.daughterDCA < bestDCADaughters) { - bestDCADaughters = straHelper.v0.daughterDCA; - bestDCADaughtersIndex = ic; - } - } // end build V0 - } // end candidate loop + // skip if empty + if (deduplicationOutput.empty()) { + continue; + } // mark de-duplicated candidates for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -2; // algorithm 1: best pointing angle - if (bestPointingAngleIndex == ic && deduplicationAlgorithm.value == 1) { + if (deduplicationOutput[ic].isBestPA && DeduplicationOpts.deduplicationAlgorithm.value == 1) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + // algorithm 2: best DCA between daughters + if (deduplicationOutput[ic].isBestDCADau && DeduplicationOpts.deduplicationAlgorithm.value == 2) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + // algorithm 3: best PA AND DCA between daughters + if (deduplicationOutput[ic].isBestDCADau && deduplicationOutput[ic].isBestPA && DeduplicationOpts.deduplicationAlgorithm.value == 3) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + // algorithm 4: best ML Score + if (deduplicationOutput[ic].isBestMLScore && DeduplicationOpts.deduplicationAlgorithm.value == 4) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } - if (bestDCADaughtersIndex == ic && deduplicationAlgorithm.value == 2) { + // Selection-based duplicate removal + if (deduplicationOutput[ic].PA <= DeduplicationOpts.PAthreshold && DeduplicationOpts.deduplicationAlgorithm.value == 5) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } - if (bestDCADaughtersIndex == ic && bestPointingAngleIndex == ic && deduplicationAlgorithm.value == 3) { + if (deduplicationOutput[ic].MLScore >= DeduplicationOpts.BDTthreshold && DeduplicationOpts.deduplicationAlgorithm.value == 6) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } } diff --git a/PWGLF/Utils/strangenessBuilderHelper.h b/PWGLF/Utils/strangenessBuilderHelper.h index 85257418e0a..a3fd7a61ea4 100644 --- a/PWGLF/Utils/strangenessBuilderHelper.h +++ b/PWGLF/Utils/strangenessBuilderHelper.h @@ -160,6 +160,8 @@ struct v0candidate { float daughterDCA = 1000.0f; float pointingAngle = 1.0f; float dcaToPV = 0.0f; + float v0DCAToPVxy = 0.0f; + float v0DCAToPVz = 0.0f; // calculated masses for convenience float massGamma; @@ -346,6 +348,16 @@ class strangenessBuilderHelper } fitter.setCollinear(false); // proper cleaning: when exiting this loop, always reset to not collinear + // Calculate DCAToPV of the V0 + o2::track::TrackPar V0Temp = fitter.createParentTrackPar(); + V0Temp.setAbsCharge(0); // charge zero + std::array dcaV0Info; + + // propagate to collision vertex + o2::base::Propagator::Instance()->propagateToDCABxByBz({pvX, pvY, pvZ}, V0Temp, 2.f, fitter.getMatCorrType(), &dcaV0Info); + v0.v0DCAToPVxy = dcaV0Info[0]; + v0.v0DCAToPVz = dcaV0Info[1]; + v0.positiveTrackX = fitter.getTrack(0).getX(); v0.negativeTrackX = fitter.getTrack(1).getX(); positiveTrackParam = fitter.getTrack(0); From 3ceb3ecfcd7c315ec51917c358394147e1e87909 Mon Sep 17 00:00:00 2001 From: gianniliveraro Date: Fri, 25 Jul 2025 07:04:03 -0300 Subject: [PATCH 2/3] Minor improvements --- .../Strangeness/strangenessbuilder.cxx | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx index e7150e58556..04f0e536464 100644 --- a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx @@ -312,8 +312,7 @@ struct StrangenessBuilder { "5: selects on PA (not a winner takes it all approach!);" "6: selects on BDT score (not a winner takes it all approach!)"}; - // BDT settings - Configurable ccdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + // BDT settings Configurable BDTLocalPath{"BDTLocalPath", "Deduplication_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; Configurable BDTPathCCDB{"BDTPathCCDB", "Users/g/gsetouel/MLModels2", "Path on CCDB"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; @@ -555,7 +554,7 @@ struct StrangenessBuilder { bool isBuildOk; float PA; float V0DCAToPVz; - float V0z; + float V0zVtx; float MLScore; }; @@ -768,9 +767,7 @@ struct StrangenessBuilder { // Loading BDT model if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ if (DeduplicationOpts.loadModelsFromCCDB) { - // Retrieve the model from CCDB - ccdbApi.init(DeduplicationOpts.ccdbUrl); - + /// Fetching model for specific timestamp LOG(info) << "Fetching model for timestamp: " << DeduplicationOpts.timestampCCDB.value; @@ -884,7 +881,7 @@ struct StrangenessBuilder { v0DuplicateInfo.isBuildOk = false; v0DuplicateInfo.PA = 10; v0DuplicateInfo.V0DCAToPVz = 999.f; - v0DuplicateInfo.V0z = 999.f; + v0DuplicateInfo.V0zVtx = 999.f; v0DuplicateInfo.MLScore = -1; // We include V0DuplicateExtra info in the vector at this point to avoid indexing issues later @@ -942,7 +939,7 @@ struct StrangenessBuilder { V0DuplicateExtras[ic].isBuildOk = true; V0DuplicateExtras[ic].PA = straHelper.v0.pointingAngle; V0DuplicateExtras[ic].V0DCAToPVz = std::abs(straHelper.v0.v0DCAToPVz); - V0DuplicateExtras[ic].V0z = std::abs(straHelper.v0.position[2]); + V0DuplicateExtras[ic].V0zVtx = std::abs(straHelper.v0.position[2]); } // end build V0 } // end candidate loop @@ -967,12 +964,12 @@ struct StrangenessBuilder { // Input vector for BDT std::vector inputFeatures{V0DuplicateExtras[ic].V0DCAToPVz, // 1. V0DCAToPVz - V0DuplicateExtras[ic].PA, // 2. PointingAngle - V0DuplicateExtras[ic].V0z, // 3. V0z - static_cast(paRanks[ic]), // 4. V0PARank - static_cast(NDuplicates), // 5. V0NDuplicates - AvgPA, // 6. V0AvgPA - static_cast(v0zRanks[ic])}; // 7. V0ZRank + V0DuplicateExtras[ic].PA, // 2. Pointing Angle + V0DuplicateExtras[ic].V0zVtx, // 3. V0 Vtx z-position + static_cast(paRanks[ic]), // 4. Pointing Angle Rank + static_cast(NDuplicates), // 5. N. of Duplicates + AvgPA, // 6. Avg Pointing Angle + static_cast(v0zRanks[ic])}; // 7. V0 Vtx z Rank float* BDTProbability = deduplication_bdt.evalModel(inputFeatures); @@ -1187,26 +1184,26 @@ struct StrangenessBuilder { for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -2; // algorithm 1: best pointing angle - if (deduplicationOutput[ic].isBestPA && DeduplicationOpts.deduplicationAlgorithm.value == 1) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 1 && deduplicationOutput[ic].isBestPA) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } // algorithm 2: best DCA between daughters - if (deduplicationOutput[ic].isBestDCADau && DeduplicationOpts.deduplicationAlgorithm.value == 2) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 2 && deduplicationOutput[ic].isBestDCADau) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } // algorithm 3: best PA AND DCA between daughters - if (deduplicationOutput[ic].isBestDCADau && deduplicationOutput[ic].isBestPA && DeduplicationOpts.deduplicationAlgorithm.value == 3) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 3 && deduplicationOutput[ic].isBestDCADau && deduplicationOutput[ic].isBestPA) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } // algorithm 4: best ML Score - if (deduplicationOutput[ic].isBestMLScore && DeduplicationOpts.deduplicationAlgorithm.value == 4) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 && deduplicationOutput[ic].isBestMLScore) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } // Selection-based duplicate removal - if (deduplicationOutput[ic].PA <= DeduplicationOpts.PAthreshold && DeduplicationOpts.deduplicationAlgorithm.value == 5) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 5 && deduplicationOutput[ic].PA <= DeduplicationOpts.PAthreshold) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } - if (deduplicationOutput[ic].MLScore >= DeduplicationOpts.BDTthreshold && DeduplicationOpts.deduplicationAlgorithm.value == 6) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 6 && deduplicationOutput[ic].MLScore >= DeduplicationOpts.BDTthreshold) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } } From ca352c8c00838933e064d6c5bbd02907bfb5f18d Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 25 Jul 2025 10:13:39 +0000 Subject: [PATCH 3/3] Please consider the following formatting changes --- .../Strangeness/strangenessbuilder.cxx | 198 +++++++++--------- PWGLF/Utils/strangenessBuilderHelper.h | 2 +- 2 files changed, 102 insertions(+), 98 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx index 04f0e536464..c3f065876a6 100644 --- a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx @@ -32,25 +32,28 @@ // -- v0builderopts ......: V0-specific building options (topological, deduplication, etc) // -- cascadebuilderopts .: cascade-specific building options (topological, etc) -#include -#include - -#include "Framework/DataSpecUtils.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" #include "TableHelper.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/Utils/strangenessBuilderHelper.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" + #include "Common/Core/TPCVDriftManager.h" +#include "Common/DataModel/PIDResponse.h" #include "Tools/ML/MlResponse.h" #include "Tools/ML/model.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/runDataProcessing.h" + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::ml; @@ -159,8 +162,8 @@ struct StrangenessBuilder { // helper object o2::pwglf::strangenessBuilderHelper straHelper; - // ML model - o2::ml::OnnxModel deduplication_bdt; + // ML model + o2::ml::OnnxModel deduplication_bdt; // table index : match order above enum tableIndex { kV0Indices = 0, @@ -302,27 +305,27 @@ struct StrangenessBuilder { struct : ConfigurableGroup { std::string prefix = "DeduplicationOpts"; - + Configurable deduplicationAlgorithm{"deduplicationAlgorithm", 1, - "0: disabled;" - "1: best pointing angle wins;" - "2: best DCA daughters wins;" - "3: best pointing and best DCA wins;" - "4: best BDT score wins;" - "5: selects on PA (not a winner takes it all approach!);" - "6: selects on BDT score (not a winner takes it all approach!)"}; - - // BDT settings + "0: disabled;" + "1: best pointing angle wins;" + "2: best DCA daughters wins;" + "3: best pointing and best DCA wins;" + "4: best BDT score wins;" + "5: selects on PA (not a winner takes it all approach!);" + "6: selects on BDT score (not a winner takes it all approach!)"}; + + // BDT settings Configurable BDTLocalPath{"BDTLocalPath", "Deduplication_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; Configurable BDTPathCCDB{"BDTPathCCDB", "Users/g/gsetouel/MLModels2", "Path on CCDB"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; - + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + // Selection based duplicates removal Configurable PAthreshold{"PAthreshold", 0.02, "PA cut to remove duplicates."}; Configurable BDTthreshold{"BDTthreshold", 0.7, "BDT score cut to remove duplicates."}; - + } DeduplicationOpts; // V0 buffer for V0s used in cascades: master switch @@ -545,14 +548,14 @@ struct StrangenessBuilder { int mcParticleBachelor; }; mcCascinfo thisCascInfo; - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* // Helper structure to save v0 duplicates auxiliary info - struct V0DuplicateExtra { + struct V0DuplicateExtra { bool isBestPA; bool isBestDCADau; bool isBestMLScore; bool isBuildOk; - float PA; + float PA; float V0DCAToPVz; float V0zVtx; float MLScore; @@ -635,14 +638,14 @@ struct StrangenessBuilder { hFindable->GetXaxis()->SetBinLabel(6, "Cascades with collId -1"); } - if (DeduplicationOpts.deduplicationAlgorithm.value > 0){ + if (DeduplicationOpts.deduplicationAlgorithm.value > 0) { histos.add("DeduplicationQA/hMLScore", "hMLScore", kTH1F, {{200, 0.0f, 1.0f}}); histos.add("DeduplicationQA/hPA", "hPA", kTH1F, {{200, 0.0f, 0.4f}}); histos.add("DeduplicationQA/hBestPA", "hBestPA", kTH1F, {{200, 0.0f, 0.4f}}); histos.add("DeduplicationQA/hBestDCADau", "hBestDCADau", kTH1F, {{200, -10.0f, 10.0f}}); histos.add("DeduplicationQA/hBestMLScore", "hBestMLScore", kTH1F, {{200, 0.0f, 1.0f}}); } - + auto hPrimaryV0s = histos.add("hPrimaryV0s", "hPrimaryV0s", kTH1D, {{2, -0.5f, 1.5f}}); hPrimaryV0s->GetXaxis()->SetBinLabel(1, "All V0s"); hPrimaryV0s->GetXaxis()->SetBinLabel(2, "Primary V0s"); @@ -764,22 +767,21 @@ struct StrangenessBuilder { straHelper.cascadeselections.lambdaMassWindow = cascadeBuilderOpts.lambdaMassWindow; straHelper.cascadeselections.maxDaughterEta = cascadeBuilderOpts.maxDaughterEta; - // Loading BDT model - if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ - if (DeduplicationOpts.loadModelsFromCCDB) { - + // Loading BDT model + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 || DeduplicationOpts.deduplicationAlgorithm.value == 6) { + if (DeduplicationOpts.loadModelsFromCCDB) { + /// Fetching model for specific timestamp LOG(info) << "Fetching model for timestamp: " << DeduplicationOpts.timestampCCDB.value; - + bool retrieveSuccess = ccdbApi.retrieveBlob(DeduplicationOpts.BDTPathCCDB.value, ".", metadata, DeduplicationOpts.timestampCCDB.value, false, DeduplicationOpts.BDTLocalPath.value); if (retrieveSuccess) { deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); } else { LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; } - } - else{ - deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); + } else { + deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); } } } @@ -799,35 +801,36 @@ struct StrangenessBuilder { } // Simple function to rank vectors based on values - std::vector rankSort(const std::vector& v_temp, bool descending = false) { + std::vector rankSort(const std::vector& v_temp, bool descending = false) + { std::vector> v_sort(v_temp.size()); // Pair each value with its original index for (size_t i = 0U; i < v_temp.size(); ++i) { - v_sort[i] = std::make_pair(v_temp[i], i); + v_sort[i] = std::make_pair(v_temp[i], i); } // Sort by value - ascending: lowest gets rank 1, descending: highest gets rank 1 if (descending) { - std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { - return a.first > b.first; - }); + std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { + return a.first > b.first; + }); } else { - std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { - return a.first < b.first; - }); + std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { + return a.first < b.first; + }); } std::pair rank_tracker = std::make_pair(std::numeric_limits::quiet_NaN(), 0); std::vector result(v_temp.size()); for (size_t i = 0U; i < v_sort.size(); ++i) { - // Only update rank if value is different from previous - if (v_sort[i].first != rank_tracker.first) { - rank_tracker = std::make_pair(v_sort[i].first, i + 1); // +1 for 1-based rank - } - result[v_sort[i].second] = rank_tracker.second; // assign rank to original index + // Only update rank if value is different from previous + if (v_sort[i].first != rank_tracker.first) { + rank_tracker = std::make_pair(v_sort[i].first, i + 1); // +1 for 1-based rank + } + result[v_sort[i].second] = rank_tracker.second; // assign rank to original index } return result; @@ -861,27 +864,27 @@ struct StrangenessBuilder { // Defining context variables int NDuplicates = 0; - float AvgPA = 0.0f; + float AvgPA = 0.0f; // Containers for ranking std::vector paVec(V0Grouped[iV0].collisionIds.size(), 999.f); std::vector v0zVec(V0Grouped[iV0].collisionIds.size(), 999.f); // Auxiliary vector to store V0 duplicate info - std::vector V0DuplicateExtras; + std::vector V0DuplicateExtras; - // Loop over duplicates + // Loop over duplicates for (size_t ic = 0; ic < V0Grouped[iV0].collisionIds.size(); ic++) { // Helper structure to save duplicates info - initializing with dummy values - V0DuplicateExtra v0DuplicateInfo; + V0DuplicateExtra v0DuplicateInfo; v0DuplicateInfo.isBestPA = false; v0DuplicateInfo.isBestDCADau = false; v0DuplicateInfo.isBestMLScore = false; v0DuplicateInfo.isBuildOk = false; - v0DuplicateInfo.PA = 10; - v0DuplicateInfo.V0DCAToPVz = 999.f; - v0DuplicateInfo.V0zVtx = 999.f; + v0DuplicateInfo.PA = 10; + v0DuplicateInfo.V0DCAToPVz = 999.f; + v0DuplicateInfo.V0zVtx = 999.f; v0DuplicateInfo.MLScore = -1; // We include V0DuplicateExtra info in the vector at this point to avoid indexing issues later @@ -916,7 +919,7 @@ struct StrangenessBuilder { // : do not apply selections: do as much as possible to preserve // candidate at this level and do not select with topo selections if (straHelper.buildV0Candidate(V0Grouped[iV0].collisionIds[ic], collision.posX(), collision.posY(), collision.posZ(), pTrack, nTrack, posTrackPar, negTrackPar, true, false, true)) { - + // candidate built, check pointing angle if (straHelper.v0.pointingAngle < bestPointingAngle) { bestPointingAngle = straHelper.v0.pointingAngle; @@ -928,33 +931,32 @@ struct StrangenessBuilder { } // Calculating features for ML Analysis - if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ - AvgPA += straHelper.v0.pointingAngle; + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 || DeduplicationOpts.deduplicationAlgorithm.value == 6) { + AvgPA += straHelper.v0.pointingAngle; paVec[ic] = straHelper.v0.pointingAngle; - v0zVec[ic] = std::abs(straHelper.v0.position[2]); + v0zVec[ic] = std::abs(straHelper.v0.position[2]); NDuplicates++; } - + // Updating values in the struct - V0DuplicateExtras[ic].isBuildOk = true; - V0DuplicateExtras[ic].PA = straHelper.v0.pointingAngle; - V0DuplicateExtras[ic].V0DCAToPVz = std::abs(straHelper.v0.v0DCAToPVz); - V0DuplicateExtras[ic].V0zVtx = std::abs(straHelper.v0.position[2]); + V0DuplicateExtras[ic].isBuildOk = true; + V0DuplicateExtras[ic].PA = straHelper.v0.pointingAngle; + V0DuplicateExtras[ic].V0DCAToPVz = std::abs(straHelper.v0.v0DCAToPVz); + V0DuplicateExtras[ic].V0zVtx = std::abs(straHelper.v0.position[2]); } // end build V0 } // end candidate loop - // Additional loop to perform ML Analysis if requested - if (DeduplicationOpts.deduplicationAlgorithm.value==4 || DeduplicationOpts.deduplicationAlgorithm.value==6){ - - // Preparing features + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 || DeduplicationOpts.deduplicationAlgorithm.value == 6) { + + // Preparing features if (NDuplicates > 0) - AvgPA /= NDuplicates; - + AvgPA /= NDuplicates; + // Get vector of ranks std::vector paRanks = rankSort(paVec, false); std::vector v0zRanks = rankSort(v0zVec, false); - + // Fill the ML score for all candidates for (size_t ic = 0; ic < V0Grouped[iV0].collisionIds.size(); ic++) { @@ -963,28 +965,27 @@ struct StrangenessBuilder { continue; // Input vector for BDT - std::vector inputFeatures{V0DuplicateExtras[ic].V0DCAToPVz, // 1. V0DCAToPVz - V0DuplicateExtras[ic].PA, // 2. Pointing Angle - V0DuplicateExtras[ic].V0zVtx, // 3. V0 Vtx z-position - static_cast(paRanks[ic]), // 4. Pointing Angle Rank - static_cast(NDuplicates), // 5. N. of Duplicates - AvgPA, // 6. Avg Pointing Angle - static_cast(v0zRanks[ic])}; // 7. V0 Vtx z Rank + std::vector inputFeatures{V0DuplicateExtras[ic].V0DCAToPVz, // 1. V0DCAToPVz + V0DuplicateExtras[ic].PA, // 2. Pointing Angle + V0DuplicateExtras[ic].V0zVtx, // 3. V0 Vtx z-position + static_cast(paRanks[ic]), // 4. Pointing Angle Rank + static_cast(NDuplicates), // 5. N. of Duplicates + AvgPA, // 6. Avg Pointing Angle + static_cast(v0zRanks[ic])}; // 7. V0 Vtx z Rank + float* BDTProbability = deduplication_bdt.evalModel(inputFeatures); - float* BDTProbability = deduplication_bdt.evalModel(inputFeatures); - if (BDTProbability[1] > bestMLScore) { bestMLScore = BDTProbability[1]; bestMLScoreIndex = ic; - } - + } + // QA histo - histos.fill(HIST("DeduplicationQA/hMLScore"), BDTProbability[1]); + histos.fill(HIST("DeduplicationQA/hMLScore"), BDTProbability[1]); histos.fill(HIST("DeduplicationQA/hPA"), V0DuplicateExtras[ic].PA); - // Updating BDT score info in the struct - V0DuplicateExtras[ic].MLScore = BDTProbability[1]; + // Updating BDT score info in the struct + V0DuplicateExtras[ic].MLScore = BDTProbability[1]; } } @@ -993,12 +994,15 @@ struct StrangenessBuilder { histos.fill(HIST("DeduplicationQA/hBestMLScore"), bestMLScore); // Final step: Defining the winners: - if (bestPointingAngleIndex != static_cast(-1)) V0DuplicateExtras[bestPointingAngleIndex].isBestPA = true; - if (bestDCADaughtersIndex != static_cast(-1)) V0DuplicateExtras[bestDCADaughtersIndex].isBestDCADau = true; - if (bestMLScoreIndex != static_cast(-1)) V0DuplicateExtras[bestMLScoreIndex].isBestMLScore = true; - - // return vector with duplicates info - return V0DuplicateExtras; + if (bestPointingAngleIndex != static_cast(-1)) + V0DuplicateExtras[bestPointingAngleIndex].isBestPA = true; + if (bestDCADaughtersIndex != static_cast(-1)) + V0DuplicateExtras[bestDCADaughtersIndex].isBestDCADau = true; + if (bestMLScoreIndex != static_cast(-1)) + V0DuplicateExtras[bestMLScoreIndex].isBestMLScore = true; + + // return vector with duplicates info + return V0DuplicateExtras; } template @@ -1177,7 +1181,7 @@ struct StrangenessBuilder { // skip if empty if (deduplicationOutput.empty()) { - continue; + continue; } // mark de-duplicated candidates diff --git a/PWGLF/Utils/strangenessBuilderHelper.h b/PWGLF/Utils/strangenessBuilderHelper.h index a3fd7a61ea4..6eda3c07848 100644 --- a/PWGLF/Utils/strangenessBuilderHelper.h +++ b/PWGLF/Utils/strangenessBuilderHelper.h @@ -355,7 +355,7 @@ class strangenessBuilderHelper // propagate to collision vertex o2::base::Propagator::Instance()->propagateToDCABxByBz({pvX, pvY, pvZ}, V0Temp, 2.f, fitter.getMatCorrType(), &dcaV0Info); - v0.v0DCAToPVxy = dcaV0Info[0]; + v0.v0DCAToPVxy = dcaV0Info[0]; v0.v0DCAToPVz = dcaV0Info[1]; v0.positiveTrackX = fitter.getTrack(0).getX();