Skip to content

Commit 15c799b

Browse files
minjungkim12claude
andcommitted
Add UPC detector amplitudes and optimize taskD0/taskDplus
- Add FV0A, FDDA, FDDC, ZNA, ZNC axes to THnSparse histograms - Optimize detector binning: unified FT0/FDD/ZN for A/C sides - Optimize utilsUpcHf.h: add constexpr/noexcept to utility functions - Optimize ZDC access: eliminate duplicate calls to bcForUPC.zdc() - Remove EventFilteringUtils dependency from CMakeLists.txt - Add const qualifiers for improved code clarity Binning configuration: - FT0: {1001, -1.5, 999.5} - FV0A: {2001, -1.5, 1999.5} - FDD: {200, 0., 4000.} - ZN: {510, -1.5, 49.5} 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent aca23b5 commit 15c799b

File tree

4 files changed

+121
-50
lines changed

4 files changed

+121
-50
lines changed

PWGHF/D2H/Tasks/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ o2physics_add_dpl_workflow(task-charm-reso-to-d-trk-reduced
7171

7272
o2physics_add_dpl_workflow(task-d0
7373
SOURCES taskD0.cxx
74-
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::SGCutParHolder O2Physics::EventFilteringUtils
74+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::SGCutParHolder
7575
COMPONENT_NAME Analysis)
7676

7777
o2physics_add_dpl_workflow(task-directed-flow-charm-hadrons
@@ -81,7 +81,7 @@ o2physics_add_dpl_workflow(task-directed-flow-charm-hadrons
8181

8282
o2physics_add_dpl_workflow(task-dplus
8383
SOURCES taskDplus.cxx
84-
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::SGCutParHolder O2Physics::EventFilteringUtils
84+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::SGCutParHolder
8585
COMPONENT_NAME Analysis)
8686

8787
o2physics_add_dpl_workflow(task-ds

PWGHF/D2H/Tasks/taskD0.cxx

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ struct HfTaskD0 {
103103
Configurable<float> upcZDCThreshold{"upcZDCThreshold", 1.0f, "ZDC energy threshold for UPC gap determination (a.u.)"};
104104

105105
HfEventSelection hfEvSel; // event selection and monitoring
106-
SGSelector sgSelector; // UPC gap selector
107-
108106
ctpRateFetcher mRateFetcher;
109107

110108
SliceCache cache;
@@ -161,8 +159,10 @@ struct HfTaskD0 {
161159
ConfigurableAxis thnConfigAxisMinTpcNCrossedRows{"thnConfigAxisMinTpcNCrossedRows", {10, 70, 180}, "axis for minimum TPC NCls crossed rows of candidate prongs"};
162160
ConfigurableAxis thnConfigAxisIR{"thnConfigAxisIR", {5000, 0, 500}, "Interaction rate (kHz)"};
163161
ConfigurableAxis thnConfigAxisGapType{"thnConfigAxisGapType", {7, -1.5, 5.5}, "axis for UPC gap type (-1=NoGap, 0=SingleGapA, 1=SingleGapC, 2=DoubleGap, 3=NoUpc, 4=TrkOutOfRange, 5=BadDoubleGap)"};
164-
ConfigurableAxis thnConfigAxisFT0A{"thnConfigAxisFT0A", {1001, -1.5, 999.5}, "axis for FT0-A amplitude (a.u.)"};
165-
ConfigurableAxis thnConfigAxisFT0C{"thnConfigAxisFT0C", {1001, -1.5, 999.5}, "axis for FT0-C amplitude (a.u.)"};
162+
ConfigurableAxis thnConfigAxisFT0{"thnConfigAxisFT0", {1001, -1.5, 999.5}, "axis for FT0 amplitude (a.u.)"};
163+
ConfigurableAxis thnConfigAxisFV0A{"thnConfigAxisFV0A", {2001, -1.5, 1999.5}, "axis for FV0-A amplitude (a.u.)"};
164+
ConfigurableAxis thnConfigAxisFDD{"thnConfigAxisFDD", {200, 0., 4000.}, "axis for FDD amplitude (a.u.)"};
165+
ConfigurableAxis thnConfigAxisZN{"thnConfigAxisZN", {510, -1.5, 49.5}, "axis for ZN energy (a.u.)"};
166166

167167
HistogramRegistry registry{
168168
"registry",
@@ -306,8 +306,13 @@ struct HfTaskD0 {
306306
const AxisSpec thnAxisMinTpcNCrossedRows{thnConfigAxisMinTpcNCrossedRows, "Minimum TPC crossed rows"};
307307
const AxisSpec thnAxisIR{thnConfigAxisIR, "Interaction rate"};
308308
const AxisSpec thnAxisGapType{thnConfigAxisGapType, "Gap type"};
309-
const AxisSpec thnAxisFT0A{thnConfigAxisFT0A, "FT0-A amplitude"};
310-
const AxisSpec thnAxisFT0C{thnConfigAxisFT0C, "FT0-C amplitude"};
309+
const AxisSpec thnAxisFT0A{thnConfigAxisFT0, "FT0-A amplitude"};
310+
const AxisSpec thnAxisFT0C{thnConfigAxisFT0, "FT0-C amplitude"};
311+
const AxisSpec thnAxisFV0A{thnConfigAxisFV0A, "FV0-A amplitude"};
312+
const AxisSpec thnAxisFDDA{thnConfigAxisFDD, "FDD-A amplitude"};
313+
const AxisSpec thnAxisFDDC{thnConfigAxisFDD, "FDD-C amplitude"};
314+
const AxisSpec thnAxisZNA{thnConfigAxisZN, "ZNA energy"};
315+
const AxisSpec thnAxisZNC{thnConfigAxisZN, "ZNC energy"};
311316

312317
if (doprocessMcWithDCAFitterN || doprocessMcWithDCAFitterNCent || doprocessMcWithKFParticle || doprocessMcWithDCAFitterNMl || doprocessMcWithDCAFitterNMlCent || doprocessMcWithKFParticleMl) {
313318
std::vector<AxisSpec> axesAcc = {thnAxisGenPtD, thnAxisGenPtB, thnAxisY, thnAxisOrigin, thnAxisNumPvContr};
@@ -361,6 +366,11 @@ struct HfTaskD0 {
361366
axes.push_back(thnAxisGapType);
362367
axes.push_back(thnAxisFT0A);
363368
axes.push_back(thnAxisFT0C);
369+
axes.push_back(thnAxisFV0A);
370+
axes.push_back(thnAxisFDDA);
371+
axes.push_back(thnAxisFDDC);
372+
axes.push_back(thnAxisZNA);
373+
axes.push_back(thnAxisZNC);
364374
}
365375

366376
if (applyMl) {
@@ -576,23 +586,42 @@ struct HfTaskD0 {
576586
if (rejectionMask != 0) {
577587
continue;
578588
}
579-
const auto& bc = collision.template bc_as<BCsType>();
580-
upchelpers::FITInfo fitInfo{};
581-
udhelpers::getFITinfo(fitInfo, bc, bcs, ft0s, fv0as, fdds);
589+
auto bc = collision.template bc_as<BCsType>();
582590

583591
// Determine gap type using SGSelector with BC range checking
584-
int gap = hf_upc::determineGapType(collision, bcs, sgSelector,
585-
upcFV0AThreshold, upcFT0AThreshold, upcFT0CThreshold);
592+
const auto gapResult = hf_upc::determineGapType(collision, bcs,
593+
upcFV0AThreshold, upcFT0AThreshold, upcFT0CThreshold);
594+
const int gap = gapResult.value;
595+
596+
// Use the BC with FIT activity if available from SGSelector
597+
auto bcForUPC = bc;
598+
if (gapResult.bc) {
599+
bcForUPC = *(gapResult.bc);
600+
}
601+
602+
// Get FIT information from the UPC BC
603+
upchelpers::FITInfo fitInfo{};
604+
udhelpers::getFITinfo(fitInfo, bcForUPC, bcs, ft0s, fv0as, fdds);
605+
606+
// Get ZDC energies if available (extract once and reuse)
607+
const bool hasZdc = bcForUPC.has_zdc();
608+
float zdcEnergyZNA = -1.f;
609+
float zdcEnergyZNC = -1.f;
610+
if (hasZdc) {
611+
const auto& zdc = bcForUPC.zdc();
612+
zdcEnergyZNA = zdc.energyCommonZNA();
613+
zdcEnergyZNC = zdc.energyCommonZNC();
614+
}
586615

587-
if (bc.has_zdc()) {
588-
const auto& zdc = bc.zdc();
616+
// Fill QA histograms using the UPC BC for both FIT and ZDC
617+
if (hasZdc) {
589618
registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C);
590-
registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdc.energyCommonZNA(), zdc.energyCommonZNC());
619+
registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC);
591620
registry.fill(HIST("Data/hUpcGapAfterSelection"), hf_upc::gapTypeToInt(gap));
592621
}
593622

594623
if (hf_upc::isSingleSidedGap(gap)) {
595-
int const gapTypeInt = hf_upc::gapTypeToInt(gap);
624+
const int gapTypeInt = hf_upc::gapTypeToInt(gap);
596625
const auto thisCollId = collision.globalIndex();
597626
const auto& groupedD0Candidates = candidates.sliceBy(candD0PerCollision, thisCollId);
598627

@@ -624,10 +653,10 @@ struct HfTaskD0 {
624653
registry.fill(HIST("hMassVsPhi"), massD0bar, ptCandidate, candidate.phi());
625654
}
626655

627-
// Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C]
656+
// Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC]
628657
auto fillTHnData = [&](float mass, int d0Type) {
629658
// Pre-calculate vector size to avoid reallocations
630-
constexpr int NAxesBase = 7; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C
659+
constexpr int NAxesBase = 12; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC
631660
constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl
632661
int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality
633662
int const nAxesOccIR = storeOccupancyAndIR ? 2 : 0; // occupancy and IR if storeOccupancyAndIR
@@ -656,6 +685,11 @@ struct HfTaskD0 {
656685
valuesToFill.push_back(static_cast<double>(gapTypeInt));
657686
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0A));
658687
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0C));
688+
valuesToFill.push_back(static_cast<double>(fitInfo.ampFV0A));
689+
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDA));
690+
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDC));
691+
valuesToFill.push_back(static_cast<double>(zdcEnergyZNA));
692+
valuesToFill.push_back(static_cast<double>(zdcEnergyZNC));
659693

660694
if constexpr (FillMl) {
661695
registry.get<THnSparse>(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data());

PWGHF/D2H/Tasks/taskDplus.cxx

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ struct HfTaskDplus {
9393
Configurable<float> upcZDCThreshold{"upcZDCThreshold", 1.0f, "ZDC energy threshold for UPC gap determination (a.u.)"};
9494

9595
HfEventSelection hfEvSel; // event selection and monitoring
96-
SGSelector sgSelector; // UPC gap selector
9796
ctpRateFetcher mRateFetcher; // interaction rate fetcher
9897

9998
Service<o2::ccdb::BasicCCDBManager> ccdb;
@@ -136,8 +135,10 @@ struct HfTaskDplus {
136135
ConfigurableAxis thnConfigAxisMlScore1{"thnConfigAxisMlScore1", {100, 0., 1.}, "axis for ML output score 1"};
137136
ConfigurableAxis thnConfigAxisMlScore2{"thnConfigAxisMlScore2", {100, 0., 1.}, "axis for ML output score 2"};
138137
ConfigurableAxis thnConfigAxisGapType{"thnConfigAxisGapType", {7, -1.5, 5.5}, "axis for UPC gap type (-1=NoGap, 0=SingleGapA, 1=SingleGapC, 2=DoubleGap, 3=NoUpc, 4=TrkOutOfRange, 5=BadDoubleGap)"};
139-
ConfigurableAxis thnConfigAxisFT0A{"thnConfigAxisFT0A", {1001, -1.5, 999.5}, "axis for FT0-A amplitude (a.u.)"};
140-
ConfigurableAxis thnConfigAxisFT0C{"thnConfigAxisFT0C", {1001, -1.5, 999.5}, "axis for FT0-C amplitude (a.u.)"};
138+
ConfigurableAxis thnConfigAxisFT0{"thnConfigAxisFT0", {1001, -1.5, 999.5}, "axis for FT0 amplitude (a.u.)"};
139+
ConfigurableAxis thnConfigAxisFV0A{"thnConfigAxisFV0A", {2001, -1.5, 1999.5}, "axis for FV0-A amplitude (a.u.)"};
140+
ConfigurableAxis thnConfigAxisFDD{"thnConfigAxisFDD", {200, 0., 4000.}, "axis for FDD amplitude (a.u.)"};
141+
ConfigurableAxis thnConfigAxisZN{"thnConfigAxisZN", {510, -1.5, 49.5}, "axis for ZN energy (a.u.)"};
141142

142143
HistogramRegistry registry{
143144
"registry",
@@ -171,8 +172,13 @@ struct HfTaskDplus {
171172
AxisSpec const thnAxisIR{thnConfigAxisIR, "Interaction rate (kHz)"};
172173
AxisSpec const thnAxisPvContributors{thnConfigAxisPvContributors, "PV contributors"};
173174
AxisSpec const thnAxisGapType{thnConfigAxisGapType, "Gap type"};
174-
AxisSpec const thnAxisFT0A{thnConfigAxisFT0A, "FT0-A amplitude"};
175-
AxisSpec const thnAxisFT0C{thnConfigAxisFT0C, "FT0-C amplitude"};
175+
AxisSpec const thnAxisFT0A{thnConfigAxisFT0, "FT0-A amplitude"};
176+
AxisSpec const thnAxisFT0C{thnConfigAxisFT0, "FT0-C amplitude"};
177+
AxisSpec const thnAxisFV0A{thnConfigAxisFV0A, "FV0-A amplitude"};
178+
AxisSpec const thnAxisFDDA{thnConfigAxisFDD, "FDD-A amplitude"};
179+
AxisSpec const thnAxisFDDC{thnConfigAxisFDD, "FDD-C amplitude"};
180+
AxisSpec const thnAxisZNA{thnConfigAxisZN, "ZNA energy"};
181+
AxisSpec const thnAxisZNC{thnConfigAxisZN, "ZNC energy"};
176182

177183
registry.add("hMass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{350, 1.7, 2.05}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}});
178184
registry.add("hEta", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}});
@@ -233,6 +239,11 @@ struct HfTaskDplus {
233239
axes.push_back(thnAxisGapType);
234240
axes.push_back(thnAxisFT0A);
235241
axes.push_back(thnAxisFT0C);
242+
axes.push_back(thnAxisFV0A);
243+
axes.push_back(thnAxisFDDA);
244+
axes.push_back(thnAxisFDDC);
245+
axes.push_back(thnAxisZNA);
246+
axes.push_back(thnAxisZNC);
236247
}
237248

238249
registry.add("hSparseMass", "THn for Dplus", HistType::kTHnSparseF, axes);
@@ -712,24 +723,45 @@ struct HfTaskDplus {
712723
/// at least one event selection not satisfied --> reject the candidate
713724
continue;
714725
}
715-
const auto& bc = collision.template bc_as<BCsType>();
716-
upchelpers::FITInfo fitInfo{};
717-
udhelpers::getFITinfo(fitInfo, bc, bcs, ft0s, fv0as, fdds);
726+
auto bc = collision.template bc_as<BCsType>();
718727

719728
// Determine gap type using SGSelector with BC range checking
720-
int gap = hf_upc::determineGapType(collision, bcs, sgSelector,
721-
upcFV0AThreshold, upcFT0AThreshold, upcFT0CThreshold);
729+
const auto gapResult = hf_upc::determineGapType(collision, bcs,
730+
upcFV0AThreshold, upcFT0AThreshold, upcFT0CThreshold);
731+
const int gap = gapResult.value;
732+
733+
// Use the BC with FIT activity if available from SGSelector
734+
auto bcForUPC = bc;
735+
if (gapResult.bc) {
736+
bcForUPC = *(gapResult.bc);
737+
}
722738

723-
if (bc.has_zdc()) {
724-
const auto& zdc = bc.zdc();
739+
// Get FIT information from the UPC BC
740+
upchelpers::FITInfo fitInfo{};
741+
udhelpers::getFITinfo(fitInfo, bcForUPC, bcs, ft0s, fv0as, fdds);
742+
743+
// Get ZDC energies if available (extract once and reuse)
744+
const bool hasZdc = bcForUPC.has_zdc();
745+
float zdcEnergyZNA = -1.f;
746+
float zdcEnergyZNC = -1.f;
747+
if (hasZdc) {
748+
const auto& zdc = bcForUPC.zdc();
749+
zdcEnergyZNA = zdc.energyCommonZNA();
750+
zdcEnergyZNC = zdc.energyCommonZNC();
751+
}
752+
753+
// Fill QA histograms using the UPC BC for both FIT and ZDC
754+
if (hasZdc) {
725755
registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C);
726-
registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdc.energyCommonZNA(), zdc.energyCommonZNC());
756+
registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC);
727757
registry.fill(HIST("Data/hUpcGapAfterSelection"), hf_upc::gapTypeToInt(gap));
728758
}
759+
729760
if (hf_upc::isSingleSidedGap(gap)) {
730-
// Use the candidates from this collision
761+
const int gapTypeInt = hf_upc::gapTypeToInt(gap);
731762
const auto thisCollId = collision.globalIndex();
732763
const auto& groupedDplusCandidates = candidates.sliceBy(candDplusPerCollision, thisCollId);
764+
733765
float cent{-1.f};
734766
float occ{-1.f};
735767
float ir{-1.f};
@@ -739,13 +771,11 @@ struct HfTaskDplus {
739771
if (storeIR) {
740772
ir = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource, true) * 1.e-3; // kHz
741773
}
742-
float numPvContr{-1.f};
743-
int const gapTypeInt = hf_upc::gapTypeToInt(gap);
744774

745775
// Lambda function to fill THn - handles both ML and non-ML cases
746776
auto fillTHnData = [&](const auto& candidate) {
747777
// Pre-calculate vector size to avoid reallocations
748-
constexpr int NAxesBase = 5; // mass, pt, gapType, FT0A, FT0C
778+
constexpr int NAxesBase = 10; // mass, pt, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC
749779
constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl
750780
int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality
751781
int const nAxesOcc = storeOccupancy ? 1 : 0; // occupancy if storeOccupancy
@@ -779,6 +809,11 @@ struct HfTaskDplus {
779809
valuesToFill.push_back(static_cast<double>(gapTypeInt));
780810
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0A));
781811
valuesToFill.push_back(static_cast<double>(fitInfo.ampFT0C));
812+
valuesToFill.push_back(static_cast<double>(fitInfo.ampFV0A));
813+
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDA));
814+
valuesToFill.push_back(static_cast<double>(fitInfo.ampFDDC));
815+
valuesToFill.push_back(static_cast<double>(zdcEnergyZNA));
816+
valuesToFill.push_back(static_cast<double>(zdcEnergyZNC));
782817
registry.get<THnSparse>(HIST("hSparseMass"))->Fill(valuesToFill.data());
783818
};
784819

PWGHF/Utils/utilsUpcHf.h

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,19 @@ constexpr int MaxNTracks = 100; ///< Maximum number of tracks
4545
/// \tparam TBCs BC table type
4646
/// \param collision Collision object
4747
/// \param bcs BC table
48-
/// \param sgSelector SGSelector instance
4948
/// \param amplitudeThresholdFV0A Threshold for FV0-A (default: 100.0)
5049
/// \param amplitudeThresholdFT0A Threshold for FT0-A (default: 100.0)
5150
/// \param amplitudeThresholdFT0C Threshold for FT0-C (default: 50.0)
52-
/// \return TrueGap enum value (-1=NoGap, 0=SingleGapA, 1=SingleGapC, 2=DoubleGap, 3=NoUpc, 4=TrkOutOfRange, 5=BadDoubleGap)
51+
/// \return SelectionResult with gap type value and BC pointer
5352
template <typename TCollision, typename TBCs>
54-
inline int determineGapType(TCollision const& collision,
55-
TBCs const& bcs,
56-
SGSelector& sgSelector,
57-
float amplitudeThresholdFV0A = defaults::AmplitudeThresholdFV0A,
58-
float amplitudeThresholdFT0A = defaults::AmplitudeThresholdFT0A,
59-
float amplitudeThresholdFT0C = defaults::AmplitudeThresholdFT0C)
53+
inline auto determineGapType(TCollision const& collision,
54+
TBCs const& bcs,
55+
float amplitudeThresholdFV0A = defaults::AmplitudeThresholdFV0A,
56+
float amplitudeThresholdFT0A = defaults::AmplitudeThresholdFT0A,
57+
float amplitudeThresholdFT0C = defaults::AmplitudeThresholdFT0C)
6058
{
59+
using BCType = std::decay_t<decltype(collision.template foundBC_as<TBCs>())>;
60+
6161
// Configure SGSelector thresholds
6262
SGCutParHolder sgCuts;
6363
sgCuts.SetNDtcoll(defaults::NDtColl);
@@ -68,30 +68,31 @@ inline int determineGapType(TCollision const& collision,
6868

6969
// Get BC and BC range
7070
if (!collision.has_foundBC()) {
71-
return TrueGap::NoGap;
71+
return SelectionResult<BCType>{TrueGap::NoGap, nullptr};
7272
}
7373

7474
const auto bc = collision.template foundBC_as<TBCs>();
7575
const auto bcRange = udhelpers::compatibleBCs(collision, sgCuts.NDtcoll(), bcs, sgCuts.minNBCs());
7676

77-
// Use SGSelector to determine gap type with BC range checking
77+
// Create SGSelector instance and determine gap type with BC range checking
78+
SGSelector sgSelector;
7879
const auto sgResult = sgSelector.IsSelected(sgCuts, collision, bcRange, bc);
7980

80-
return sgResult.value;
81+
return sgResult;
8182
}
8283

8384
/// \brief Check if the gap type is a single-sided gap (SingleGapA or SingleGapC)
8485
/// \param gap TrueGap enum value
8586
/// \return true if single-sided gap, false otherwise
86-
inline bool isSingleSidedGap(int gap)
87+
constexpr bool isSingleSidedGap(int gap) noexcept
8788
{
8889
return (gap == TrueGap::SingleGapA || gap == TrueGap::SingleGapC);
8990
}
9091

9192
/// \brief Get gap type name as string
9293
/// \param gap TrueGap enum value
9394
/// \return String representation of gap type
94-
inline const char* getGapTypeName(int gap)
95+
constexpr const char* getGapTypeName(int gap) noexcept
9596
{
9697
switch (gap) {
9798
case TrueGap::NoGap:
@@ -116,7 +117,8 @@ inline const char* getGapTypeName(int gap)
116117
/// \brief Convert gap type to integer for histogram filling
117118
/// \param gap TrueGap enum value
118119
/// \return Integer representation (-1, 0, 1, 2, 3, 4, 5)
119-
inline int gapTypeToInt(int gap)
120+
/// \note This is a pass-through function for consistency with other utility functions
121+
constexpr int gapTypeToInt(int gap) noexcept
120122
{
121123
return gap;
122124
}

0 commit comments

Comments
 (0)