Skip to content

Commit 2989f90

Browse files
authored
[PWGLF,Trigger] Add V0 with He3, triton femto, and tracked 3 body triggers (#10834)
1 parent 56a24f1 commit 2989f90

File tree

2 files changed

+102
-27
lines changed

2 files changed

+102
-27
lines changed

EventFiltering/PWGLF/nucleiFilter.cxx

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <cmath>
1414
#include <string>
1515

16+
#include "Math/Vector4D.h"
17+
#include "Math/GenVector/Boost.h"
1618
#include "Common/DataModel/EventSelection.h"
1719
#include "Common/DataModel/PIDResponse.h"
1820
#include "Common/DataModel/TrackSelectionTables.h"
@@ -37,6 +39,7 @@
3739
#include "CCDB/BasicCCDBManager.h"
3840
#include "DCAFitter/DCAFitterN.h"
3941
#include "PWGLF/DataModel/pidTOFGeneric.h"
42+
#include "PWGLF/DataModel/LFStrangenessTables.h"
4043
#include "Common/Core/PID/PIDTOF.h"
4144

4245
using namespace o2;
@@ -47,8 +50,6 @@ namespace
4750
{
4851

4952
static constexpr int nNuclei{3};
50-
static constexpr int nHyperNuclei{1};
51-
static constexpr int nITStriggers{2};
5253
static constexpr int nCutsPID{5};
5354
static constexpr std::array<float, nNuclei> masses{
5455
constants::physics::MassDeuteron, constants::physics::MassTriton,
@@ -57,7 +58,7 @@ static constexpr std::array<int, nNuclei> charges{1, 1, 2};
5758
static const std::vector<std::string> matterOrNot{"Matter", "Antimatter"};
5859
static const std::vector<std::string> nucleiNames{"H2", "H3", "Helium"};
5960
static const std::vector<std::string> hypernucleiNames{"H3L"}; // 3-body decay case
60-
static const std::vector<std::string> columnsNames{o2::aod::filtering::H2::columnLabel(), "fH3", o2::aod::filtering::He::columnLabel(), o2::aod::filtering::H3L3Body::columnLabel(), o2::aod::filtering::ITSmildIonisation::columnLabel(), o2::aod::filtering::ITSextremeIonisation::columnLabel()};
61+
static const std::vector<std::string> columnsNames{o2::aod::filtering::H2::columnLabel(), o2::aod::filtering::He::columnLabel(), o2::aod::filtering::HeV0::columnLabel(), o2::aod::filtering::TritonFemto::columnLabel(), o2::aod::filtering::H3L3Body::columnLabel(), o2::aod::filtering::Tracked3Body::columnLabel(), o2::aod::filtering::ITSmildIonisation::columnLabel(), o2::aod::filtering::ITSextremeIonisation::columnLabel()};
6162
static const std::vector<std::string> cutsNames{
6263
"TPCnSigmaMin", "TPCnSigmaMax", "TOFnSigmaMin", "TOFnSigmaMax", "TOFpidStartPt"};
6364
constexpr double betheBlochDefault[nNuclei][6]{
@@ -100,13 +101,14 @@ struct nucleiFilter {
100101
Configurable<float> cfgCutNclusTPC{"cfgCutNclusTPC", 80, "Minimum number of TPC clusters"};
101102
Configurable<float> cfgCutDCAxy{"cfgCutDCAxy", 3, "Max DCAxy"};
102103
Configurable<float> cfgCutDCAz{"cfgCutDCAz", 10, "Max DCAz"};
104+
Configurable<float> cfgCutKstar{"cfgCutKstar", 1.f, "Kstar cut for triton femto trigger"};
103105

104106
Configurable<LabeledArray<double>> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], nNuclei, 6, nucleiNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"};
105107
Configurable<LabeledArray<double>> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {bbMomScalingDefault[0], nNuclei, 2, nucleiNames, matterOrNot}, "TPC Bethe-Bloch momentum scaling for light nuclei"};
106108
Configurable<LabeledArray<double>> cfgMinTPCmom{"cfgMinTPCmom", {minTPCmom[0], nNuclei, 2, nucleiNames, matterOrNot}, "Minimum TPC p/Z for nuclei PID"};
107109

108110
Configurable<LabeledArray<float>> cfgCutsPID{"nucleiCutsPID", {cutsPID[0], nNuclei, nCutsPID, nucleiNames, cutsNames}, "Nuclei PID selections"};
109-
Configurable<bool> fixTPCinnerParam{"fixTPCinnerParam", false, "Fix TPC inner param"};
111+
Configurable<bool> cfgFixTPCinnerParam{"cfgFixTPCinnerParam", false, "Fix TPC inner param"};
110112

111113
// variable/tool for hypertriton 3body decay
112114
int mRunNumber;
@@ -160,9 +162,9 @@ struct nucleiFilter {
160162
} trgH3L3Body;
161163

162164
HistogramRegistry qaHists{"qaHists", {}, OutputObjHandlingPolicy::AnalysisObject, true, true};
163-
OutputObj<TH1D> hProcessedEvents{TH1D("hProcessedEvents", ";;Number of filtered events", nNuclei + nHyperNuclei + nITStriggers + 1, -0.5, nNuclei + nHyperNuclei + nITStriggers + 0.5)};
165+
OutputObj<TH1D> hProcessedEvents{TH1D("hProcessedEvents", ";;Number of filtered events", kNtriggers + 1, -0.5, static_cast<double>(kNtriggers) + 0.5)};
164166

165-
void init(o2::framework::InitContext&)
167+
void init(InitContext&)
166168
{
167169
std::vector<double> ptBinning = {0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5.};
168170

@@ -313,27 +315,50 @@ struct nucleiFilter {
313315
bachelorTOFPID.SetParams(mRespParamsV2);
314316
}
315317

318+
enum {
319+
kH2 = 0,
320+
kHe,
321+
kHeV0,
322+
kTritonFemto,
323+
kH3L3Body,
324+
kTracked3Body,
325+
kITSmildIonisation,
326+
kITSextremeIonisation,
327+
kNtriggers
328+
} TriggerType;
316329
// void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, TrackCandidates const& tracks)
317330
using ColWithEvTime = soa::Join<aod::Collisions, aod::EvSels, aod::EvTimeTOFFT0>;
318-
void process(ColWithEvTime::iterator const& collision, aod::Decay3Bodys const& decay3bodys, TrackCandidates const& tracks, aod::BCsWithTimestamps const&)
331+
void process(ColWithEvTime::iterator const& collision, aod::Decay3Bodys const& decay3bodys, TrackCandidates const& tracks, aod::AssignedTracked3Bodys const& tracked3Bodys, aod::V0s const& v0s, aod::BCsWithTimestamps const&)
319332
{
320333
// collision process loop
321-
bool keepEvent[nNuclei + nHyperNuclei + nITStriggers]{false};
334+
std::array<bool, kNtriggers> keepEvent{false};
322335
//
323336
qaHists.fill(HIST("fCollZpos"), collision.posZ());
324337
hProcessedEvents->Fill(0);
325338
//
326339
if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) {
327-
tags(keepEvent[0], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5]);
340+
tags(keepEvent[kH2], keepEvent[kHe], keepEvent[kHeV0], keepEvent[kTritonFemto], keepEvent[kH3L3Body], keepEvent[kTracked3Body], keepEvent[kITSmildIonisation], keepEvent[kITSextremeIonisation]);
328341
return;
329342
}
343+
330344
//
331345
const double bgScalings[nNuclei][2]{
332346
{charges[0] * cfgMomentumScalingBetheBloch->get(0u, 0u) / masses[0], charges[0] * cfgMomentumScalingBetheBloch->get(0u, 1u) / masses[0]},
333347
{charges[1] * cfgMomentumScalingBetheBloch->get(1u, 0u) / masses[1], charges[1] * cfgMomentumScalingBetheBloch->get(1u, 1u) / masses[1]},
334348
{charges[2] * cfgMomentumScalingBetheBloch->get(2u, 0u) / masses[2], charges[2] * cfgMomentumScalingBetheBloch->get(2u, 1u) / masses[2]}};
335349

336-
for (auto& track : tracks) { // start loop over tracks
350+
constexpr int nucleusIndex[nNuclei]{kH2, -1, kHe}; /// remap for nuclei triggers
351+
std::vector<int> h3indices;
352+
std::vector<ROOT::Math::PtEtaPhiMVector> h3vectors;
353+
354+
auto getNsigma = [&](const auto& track, int iN, int iC) {
355+
float fixTPCrigidity{(cfgFixTPCinnerParam && (track.pidForTracking() == track::PID::Helium3 || track.pidForTracking() == track::PID::Alpha)) ? 0.5f : 1.f};
356+
double expBethe{tpc::BetheBlochAleph(static_cast<double>(track.tpcInnerParam() * fixTPCrigidity * bgScalings[iN][iC]), cfgBetheBlochParams->get(iN, 0u), cfgBetheBlochParams->get(iN, 1u), cfgBetheBlochParams->get(iN, 2u), cfgBetheBlochParams->get(iN, 3u), cfgBetheBlochParams->get(iN, 4u))};
357+
double expSigma{expBethe * cfgBetheBlochParams->get(iN, 5u)};
358+
return static_cast<float>((track.tpcSignal() - expBethe) / expSigma);
359+
};
360+
361+
for (const auto& track : tracks) { // start loop over tracks
337362
if (track.itsNCls() >= cfgCutNclusExtremeIonisationITS) {
338363
double avgClsSize{0.};
339364
double cosL{std::sqrt(1. / (1. + track.tgl() * track.tgl()))};
@@ -342,8 +367,8 @@ struct nucleiFilter {
342367
}
343368
avgClsSize = avgClsSize * cosL / track.itsNCls();
344369
qaHists.fill(HIST("fExtremeIonisationITS"), track.itsNCls(), avgClsSize, track.p());
345-
keepEvent[4] = track.p() > cfgMomentumCutExtremeIonisation && avgClsSize > cfgCutClsSizeMildIonisation;
346-
keepEvent[5] = track.p() > cfgMomentumCutExtremeIonisation && avgClsSize > cfgCutClsSizeExtremeIonisation;
370+
keepEvent[kITSmildIonisation] = track.p() > cfgMomentumCutExtremeIonisation && avgClsSize > cfgCutClsSizeMildIonisation;
371+
keepEvent[kITSextremeIonisation] = track.p() > cfgMomentumCutExtremeIonisation && avgClsSize > cfgCutClsSizeExtremeIonisation;
347372
}
348373
if (track.itsNCls() < cfgCutNclusITS ||
349374
track.tpcNClsFound() < cfgCutNclusTPC) {
@@ -354,18 +379,16 @@ struct nucleiFilter {
354379
qaHists.fill(HIST("fDeuTOFNsigma"), track.p() * track.sign(), track.tofNSigmaDe());
355380
}
356381

357-
if (track.sign() > 0 && (std::abs(track.dcaXY()) > cfgCutDCAxy ||
358-
std::abs(track.dcaZ()) > cfgCutDCAz)) {
359-
continue;
360-
}
382+
bool passesDCAselection{(track.sign() < 0 || (std::abs(track.dcaXY()) < cfgCutDCAxy &&
383+
std::abs(track.dcaZ()) < cfgCutDCAz))};
361384

362385
float nSigmaTPC[nNuclei]{
363386
track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe()};
364387
const float nSigmaTOF[nNuclei]{
365388
track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe()};
366389
const int iC{track.sign() < 0};
367390

368-
float fixTPCrigidity{(fixTPCinnerParam && (track.pidForTracking() == track::PID::Helium3 || track.pidForTracking() == track::PID::Alpha)) ? 0.5f : 1.f};
391+
float fixTPCrigidity{(cfgFixTPCinnerParam && (track.pidForTracking() == track::PID::Helium3 || track.pidForTracking() == track::PID::Alpha)) ? 0.5f : 1.f};
369392

370393
// fill QA hist: dEdx for all charged tracks
371394
qaHists.fill(HIST("fTPCsignalAll"), track.sign() * track.tpcInnerParam() * fixTPCrigidity, track.tpcSignal());
@@ -377,9 +400,7 @@ struct nucleiFilter {
377400
}
378401

379402
if (cfgBetheBlochParams->get(iN, 5u) > 0.f) {
380-
double expBethe{tpc::BetheBlochAleph(static_cast<double>(track.tpcInnerParam() * fixTPCrigidity * bgScalings[iN][iC]), cfgBetheBlochParams->get(iN, 0u), cfgBetheBlochParams->get(iN, 1u), cfgBetheBlochParams->get(iN, 2u), cfgBetheBlochParams->get(iN, 3u), cfgBetheBlochParams->get(iN, 4u))};
381-
double expSigma{expBethe * cfgBetheBlochParams->get(iN, 5u)};
382-
nSigmaTPC[iN] = static_cast<float>((track.tpcSignal() - expBethe) / expSigma);
403+
nSigmaTPC[iN] = getNsigma(track, iN, iC);
383404
}
384405
h2TPCnSigma[iN]->Fill(track.sign() * track.tpcInnerParam() * fixTPCrigidity, nSigmaTPC[iN]);
385406
if (nSigmaTPC[iN] < cfgCutsPID->get(iN, 0u) || nSigmaTPC[iN] > cfgCutsPID->get(iN, 1u)) {
@@ -388,12 +409,61 @@ struct nucleiFilter {
388409
if (track.p() > cfgCutsPID->get(iN, 4u) && (nSigmaTOF[iN] < cfgCutsPID->get(iN, 2u) || nSigmaTOF[iN] > cfgCutsPID->get(iN, 3u))) {
389410
continue;
390411
}
391-
keepEvent[iN] = true;
392-
if (keepEvent[iN]) {
412+
if (iN == 1 && passesDCAselection) {
413+
h3indices.push_back(track.globalIndex());
414+
h3vectors.emplace_back(track.pt(), track.eta(), track.phi(), masses[iN]);
415+
}
416+
if (nucleusIndex[iN] < 0) {
417+
continue;
418+
}
419+
keepEvent[nucleusIndex[iN]] = passesDCAselection;
420+
if (keepEvent[nucleusIndex[iN]]) {
393421
h2TPCsignal[iN]->Fill(track.sign() * track.tpcInnerParam() * fixTPCrigidity, track.tpcSignal());
394422
}
395423
}
396424

425+
for (const auto& track : tracks) {
426+
if (track.itsNCls() < cfgCutNclusITS ||
427+
track.tpcNClsFound() < cfgCutNclusTPC ||
428+
std::abs(track.dcaXY()) > cfgCutDCAxy ||
429+
std::abs(track.dcaZ()) > cfgCutDCAz ||
430+
std::abs(track.eta()) > cfgCutEta) {
431+
continue;
432+
}
433+
const ROOT::Math::PtEtaPhiMVector trackVector(track.pt(), track.eta(), track.phi(), constants::physics::MassPiMinus);
434+
for (size_t iH3{0}; iH3 < h3vectors.size(); ++iH3) {
435+
if (h3indices[iH3] == track.globalIndex()) {
436+
continue;
437+
}
438+
const auto& h3vector = h3vectors[iH3];
439+
auto pivector = trackVector;
440+
auto cm = h3vector + trackVector;
441+
const ROOT::Math::Boost boost(cm.BoostToCM());
442+
boost(pivector);
443+
if (pivector.P() < cfgCutKstar) {
444+
keepEvent[kTritonFemto] = true;
445+
break;
446+
}
447+
}
448+
}
449+
450+
for (const auto& v0 : v0s) {
451+
const auto& posTrack = tracks.rawIteratorAt(v0.posTrackId());
452+
const auto& negTrack = tracks.rawIteratorAt(v0.negTrackId());
453+
if ((posTrack.itsNCls() < cfgCutNclusITS || posTrack.tpcNClsFound() < cfgCutNclusTPC) &&
454+
(negTrack.itsNCls() < cfgCutNclusITS || negTrack.tpcNClsFound() < cfgCutNclusTPC)) {
455+
continue;
456+
}
457+
float nSigmas[2]{
458+
cfgBetheBlochParams->get(2, 5u) > 0.f ? getNsigma(posTrack, 2, 0) : posTrack.tpcNSigmaHe(),
459+
cfgBetheBlochParams->get(2, 5u) > 0.f ? getNsigma(negTrack, 2, 1) : negTrack.tpcNSigmaHe()};
460+
if ((nSigmas[0] > cfgCutsPID->get(2, 0u) && nSigmas[0] < cfgCutsPID->get(2, 1u)) ||
461+
(nSigmas[1] > cfgCutsPID->get(2, 0u) && nSigmas[1] < cfgCutsPID->get(2, 1u))) {
462+
keepEvent[kHeV0] = true;
463+
break;
464+
}
465+
}
466+
397467
//
398468
// fill QA histograms
399469
//
@@ -531,7 +601,7 @@ struct nucleiFilter {
531601
qaHists.fill(HIST("fBachDeuTOFNsigma"), track2.p() * track2.sign(), tofNSigmaDeuteron);
532602
qaHists.fill(HIST("fH3LDcaVsPt"), pt3B, dcaDaughters);
533603
qaHists.fill(HIST("fH3LCosPAVsPt"), pt3B, vtxCosPA);
534-
keepEvent[3] = true;
604+
keepEvent[kH3L3Body] = true;
535605
}
536606
}
537607
if (invmassAntiH3L >= trgH3L3Body.h3LMassLowerlimit && invmassAntiH3L <= trgH3L3Body.h3LMassUpperlimit) {
@@ -541,17 +611,20 @@ struct nucleiFilter {
541611
qaHists.fill(HIST("fBachDeuTOFNsigma"), track2.p() * track2.sign(), tofNSigmaDeuteron);
542612
qaHists.fill(HIST("fH3LDcaVsPt"), pt3B, dcaDaughters);
543613
qaHists.fill(HIST("fH3LCosPAVsPt"), pt3B, vtxCosPA);
544-
keepEvent[3] = true;
614+
keepEvent[kH3L3Body] = true;
545615
}
546616
}
547617
}
548618

549-
for (int iDecision{0}; iDecision < nNuclei + nHyperNuclei + nITStriggers; ++iDecision) {
619+
keepEvent[kTracked3Body] = tracked3Bodys.size() > 0;
620+
621+
for (int iDecision{0}; iDecision < kNtriggers; ++iDecision) {
550622
if (keepEvent[iDecision]) {
551623
hProcessedEvents->Fill(iDecision + 1);
552624
}
553625
}
554-
tags(keepEvent[0], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5]);
626+
627+
tags(keepEvent[kH2], keepEvent[kHe], keepEvent[kHeV0], keepEvent[kTritonFemto], keepEvent[kH3L3Body], keepEvent[kTracked3Body], keepEvent[kITSmildIonisation], keepEvent[kITSextremeIonisation]);
555628
}
556629
};
557630

EventFiltering/filterTables.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ namespace filtering
4848
{
4949
DECLARE_SOA_COLUMN(H2, hasH2, bool); //! deuteron trigger for the helium normalisation (to be downscaled)
5050
DECLARE_SOA_COLUMN(He, hasHe, bool); //! helium
51+
DECLARE_SOA_COLUMN(HeV0, hasHeV0, bool); //! V0 containing a V0
52+
DECLARE_SOA_COLUMN(TritonFemto, hasTritonFemto, bool); //! Triton hadron femtoscopy
5153
DECLARE_SOA_COLUMN(H3L3Body, hasH3L3Body, bool); //! hypertriton 3body
5254
DECLARE_SOA_COLUMN(ITSextremeIonisation, hasITSextremeIonisation, bool); //! ITS extreme ionisation
5355
DECLARE_SOA_COLUMN(ITSmildIonisation, hasITSmildIonisation, bool); //! ITS mild ionisation (normalisation of the extreme ionisation), to be downscaled
@@ -215,7 +217,7 @@ DECLARE_SOA_COLUMN(BCend, hasBCend, uint64_t); //! CEFP bcrange
215217

216218
// nuclei
217219
DECLARE_SOA_TABLE(NucleiFilters, "AOD", "NucleiFilters", //!
218-
filtering::H2, filtering::He, filtering::H3L3Body, filtering::ITSmildIonisation,
220+
filtering::H2, filtering::He, filtering::HeV0, filtering::TritonFemto, filtering::H3L3Body, filtering::Tracked3Body, filtering::ITSmildIonisation,
219221
filtering::ITSextremeIonisation);
220222
using NucleiFilter = NucleiFilters::iterator;
221223

0 commit comments

Comments
 (0)