From e978bee26eaa509620a7b0e0f369fab2e167a34c Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Thu, 18 Jun 2026 17:48:36 +0200 Subject: [PATCH] Add possibility to reapply trigger selections --- .../candidateCreatorXicToXiPiPi.cxx | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx index a618360598f..5ec7bbced6b 100644 --- a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -111,12 +111,21 @@ struct HfCandidateCreatorXicToXiPiPi { Configurable constrainXicPlusToPv{"constrainXicPlusToPv", false, "Constrain XicPlus to PV"}; Configurable kfConstructMethod{"kfConstructMethod", 2, "Construct method of XicPlus: 0 fast mathematics without constraint of fixed daughter particle masses, 2 daughter particle masses stay fixed in construction process"}; Configurable rejDiffCollTrack{"rejDiffCollTrack", true, "Reject tracks coming from different collisions (effective only for KFParticle w/o derived data)"}; + // configurables for software trigger selections + struct : ConfigurableGroup { + std::string prefix = "softtrig"; + Configurable applySoftwareTrigSelections{"applySoftwareTrigSelections", false, "Enable application of software trigger selections"}; + Configurable minDecayLength{"minDecayLength", 0.015, "Minimum decay length (computed with DCAFitter)"}; + Configurable minCosPA{"minCosPA", 0.9, "Minimum coine of pointing angle (computed with DCAFitter)"}; + Configurable maxChi2Pca{"maxChi2Pca", 3., "Maximum chi2 PCA (computed with DCAFitter)"}; + } softTrigCuts; Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; o2::vertexing::DCAFitterN<3> df; + o2::vertexing::DCAFitterN<2> df2Prong; HfEventSelection hfEvSel; @@ -196,6 +205,66 @@ struct HfCandidateCreatorXicToXiPiPi { df.setMinRelChi2Change(minRelChi2Change); df.setUseAbsDCA(useAbsDCA); df.setWeightedFinalPCA(useWeightedFinalPCA); + + if (softTrigCuts.applySoftwareTrigSelections) { + float maxRadSoftTrig = 200.; + float maxDZIniSoftTrig = 1.e9; + float maxDXYIniSoftTrig = 4.; + float minParamChangeSoftTrig = 1.e-3; + float maxChi2SoftTrig = 0.9; + float minRelChi2ChangeSoftTrig = 0.9; + df2Prong.setPropagateToPCA(true); + df2Prong.setMaxR(maxRadSoftTrig); + df2Prong.setMaxDZIni(maxDZIniSoftTrig); + df2Prong.setMaxDXYIni(maxDXYIniSoftTrig); + df2Prong.setMinParamChange(minParamChangeSoftTrig); + df2Prong.setMinRelChi2Change(minRelChi2ChangeSoftTrig); + df2Prong.setMaxChi2(maxChi2SoftTrig); + df2Prong.setUseAbsDCA(false); + df2Prong.setWeightedFinalPCA(false); + } + } + + /// Method that reapplies the selections applied in the software trigger + /// \param pVecCascade is the cascade momentum vector + /// \param trackParBachelor is the array with two bachelor track parametrisations + /// \param collision is the collision containing the candidate + template + bool isSelectedXicSoftwareTriggers(std::array const& pVecCascade, std::array const& trackParBachelor, Coll const& collision) + { + int nCand{0}; + try { + nCand = df2Prong.process(trackParBachelor[0], trackParBachelor[1]); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call for bachelor + bachelor in software trigger selection function!"; + return false; + } + if (nCand == 0) { + return false; + } + + const auto& vtx = df2Prong.getPCACandidate(); + if (df2Prong.getChi2AtPCACandidate() > softTrigCuts.maxChi2Pca) { + return false; + } + + std::array pVecBachFirst{}, pVecBachSecond{}; + const auto& trackBachFirstProp = df2Prong.getTrack(0); + const auto& trackBachSecondProp = df2Prong.getTrack(1); + trackBachFirstProp.getPxPyPzGlo(pVecBachFirst); + trackBachSecondProp.getPxPyPzGlo(pVecBachSecond); + auto momXiBachBach = RecoDecay::pVec(pVecCascade, pVecBachFirst, pVecBachSecond); + + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; + if (RecoDecay::cpa(primVtx, std::array{vtx[0], vtx[1], vtx[2]}, momXiBachBach) < softTrigCuts.minCosPA) { + return false; + } + + if (RecoDecay::distance(primVtx, vtx) < softTrigCuts.minDecayLength) { + return false; + } + + return true; } template @@ -282,6 +351,13 @@ struct HfCandidateCreatorXicToXiPiPi { auto trackParCovCharmBachelor0 = getTrackParCov(trackCharmBachelor0); auto trackParCovCharmBachelor1 = getTrackParCov(trackCharmBachelor1); + // if enabled, apply selections of software trigger + if (softTrigCuts.applySoftwareTrigSelections) { + if (!isSelectedXicSoftwareTriggers(pVecCasc, std::array{trackParCovCharmBachelor0, trackParCovCharmBachelor1}, collision)) { + continue; + } + } + // reconstruct the 3-prong secondary vertex try { if (df.process(trackCasc, trackParCovCharmBachelor0, trackParCovCharmBachelor1) == 0) { @@ -459,9 +535,20 @@ struct HfCandidateCreatorXicToXiPiPi { continue; } auto casc = cascAodElement.kfCascData_as(); + auto trackCharmBachelor0 = rowTrackIndexXicPlus.prong0_as(); auto trackCharmBachelor1 = rowTrackIndexXicPlus.prong1_as(); + // if enabled, apply selections of software trigger + if (softTrigCuts.applySoftwareTrigSelections) { + auto trackParCovCharmBachelor0 = getTrackParCov(trackCharmBachelor0); + auto trackParCovCharmBachelor1 = getTrackParCov(trackCharmBachelor1); + std::array const pVecCasc = {casc.px(), casc.py(), casc.pz()}; + if (!isSelectedXicSoftwareTriggers(pVecCasc, std::array{trackParCovCharmBachelor0, trackParCovCharmBachelor1}, collision)) { + continue; + } + } + //-------------------preselect cascade candidates-------------------------------------- if (doCascadePreselection) { if (std::abs(casc.dcaXYCascToPV()) > dcaXYToPVCascadeMax) {