Skip to content

Commit d95c100

Browse files
committed
Backport modular resonance initializer
1 parent b34d08b commit d95c100

4 files changed

Lines changed: 1181 additions & 643 deletions

File tree

PWGLF/DataModel/LFResonanceTables.h

Lines changed: 208 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include <Framework/AnalysisDataModel.h>
3636

37+
#include <algorithm>
3738
#include <array>
3839
#include <cmath>
3940
#include <cstdint>
@@ -63,15 +64,15 @@ enum {
6364
kAllCutsINELg010,
6465
kECend,
6566
};
66-
DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, Collisions, "_Col"); //!
67-
DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality (Multiplicity) percentile (Default: FT0M)
68-
DECLARE_SOA_COLUMN(Spherocity, spherocity, float); //! Spherocity of the event
69-
DECLARE_SOA_COLUMN(EvtPl, evtPl, float); //! Second harmonic event plane
70-
DECLARE_SOA_COLUMN(EvtPlResAB, evtPlResAB, float); //! Second harmonic event plane resolution of A-B sub events
71-
DECLARE_SOA_COLUMN(EvtPlResAC, evtPlResAC, float); //! Second harmonic event plane resolution of A-C sub events
72-
DECLARE_SOA_COLUMN(EvtPlResBC, evtPlResBC, float); //! Second harmonic event plane resolution of B-C sub events
73-
DECLARE_SOA_COLUMN(BMagField, bMagField, float); //! Magnetic field
74-
DECLARE_SOA_COLUMN(IsRecINELgt0, isRecINELgt0, bool); //! Is reconstructed INEL>0 event
67+
DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! Original collision row ID stored as a scalar for standalone derived data
68+
DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality (Multiplicity) percentile (Default: FT0M)
69+
DECLARE_SOA_COLUMN(Spherocity, spherocity, float); //! Spherocity of the event
70+
DECLARE_SOA_COLUMN(EvtPl, evtPl, float); //! Second harmonic event plane
71+
DECLARE_SOA_COLUMN(EvtPlResAB, evtPlResAB, float); //! Second harmonic event plane resolution of A-B sub events
72+
DECLARE_SOA_COLUMN(EvtPlResAC, evtPlResAC, float); //! Second harmonic event plane resolution of A-C sub events
73+
DECLARE_SOA_COLUMN(EvtPlResBC, evtPlResBC, float); //! Second harmonic event plane resolution of B-C sub events
74+
DECLARE_SOA_COLUMN(BMagField, bMagField, float); //! Magnetic field
75+
DECLARE_SOA_COLUMN(IsRecINELgt0, isRecINELgt0, bool); //! Is reconstructed INEL>0 event
7576
// MC
7677
DECLARE_SOA_COLUMN(IsVtxIn10, isVtxIn10, bool); //! Vtx10
7778
DECLARE_SOA_COLUMN(IsINELgt0, isINELgt0, bool); //! INEL>0
@@ -179,9 +180,9 @@ struct ResoTrackFlags {
179180

180181
DECLARE_SOA_INDEX_COLUMN(ResoCollision, resoCollision);
181182
DECLARE_SOA_INDEX_COLUMN(ResoCollisionDF, resoCollisionDF);
182-
DECLARE_SOA_INDEX_COLUMN_FULL(Track, track, int, Tracks, "_Trk"); //!
183-
DECLARE_SOA_INDEX_COLUMN_FULL(V0, v0, int, V0s, "_V0"); //!
184-
DECLARE_SOA_INDEX_COLUMN_FULL(Cascade, cascade, int, Cascades, "_Cas"); //!
183+
DECLARE_SOA_COLUMN(TrackId, trackId, int); //! Original track row ID stored as a scalar for autocorrelation rejection
184+
DECLARE_SOA_COLUMN(V0Id, v0Id, int); //! Original V0 row ID stored as a scalar
185+
DECLARE_SOA_COLUMN(CascadeId, cascadeId, int); //! Original cascade row ID stored as a scalar
185186
DECLARE_SOA_COLUMN(Pt, pt, float); //! p_t (GeV/c)
186187
DECLARE_SOA_COLUMN(Px, px, float); //! p_x (GeV/c)
187188
DECLARE_SOA_COLUMN(Py, py, float); //! p_y (GeV/c)
@@ -507,6 +508,167 @@ struct ResoMicroTrackSelFlag {
507508
DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); });
508509
} // namespace resomicrodaughter
509510

511+
// Ultra-micro track representation. The momentum components are quantised
512+
// to 1 MeV/c and only one (pion/kaon/proton) PID flag is retained.
513+
namespace resoultramicrodaughter
514+
{
515+
/// @brief Compact absolute TPC/TOF n-sigma values for one configured species.
516+
/// Code 0 represents |n-sigma| < 1.5. Codes 1..14 represent lower-inclusive
517+
/// 0.25-sigma-wide bins [1.5, 1.75), ..., [4.75, 5.0) and decode to their
518+
/// lower edges. Code 15 represents |n-sigma| >= 5. Missing TOF information
519+
/// is carried independently by resodaughter::TrackFlags::kHasTOF.
520+
struct PidNSigma {
521+
static constexpr float MinFineNSigma = 1.5f;
522+
static constexpr float Step = 0.25f;
523+
static constexpr float MaxNSigma = 5.f;
524+
static constexpr uint8_t MaxRegularCode = 14;
525+
static constexpr uint8_t AboveRangeCode = 15;
526+
527+
uint8_t flag;
528+
529+
PidNSigma(float tpcNSigma, float tofNSigma, bool hasTOF)
530+
{
531+
const uint8_t tpcEncoded = encodeNSigma(tpcNSigma);
532+
const uint8_t tofEncoded = hasTOF && std::isfinite(tofNSigma) ? encodeNSigma(tofNSigma) : AboveRangeCode;
533+
flag = (tpcEncoded << 4) | tofEncoded;
534+
}
535+
536+
static uint8_t encodeNSigma(float nSigma)
537+
{
538+
const float value = std::abs(nSigma);
539+
if (!std::isfinite(value)) {
540+
return AboveRangeCode;
541+
}
542+
if (value < MinFineNSigma) {
543+
return 0;
544+
}
545+
if (value >= MaxNSigma) {
546+
return AboveRangeCode;
547+
}
548+
const int encoded = 1 + static_cast<int>(std::floor((value - MinFineNSigma) / Step));
549+
return static_cast<uint8_t>(std::clamp(encoded, 1, static_cast<int>(MaxRegularCode)));
550+
}
551+
552+
static float decodeNSigma(uint8_t encoded)
553+
{
554+
const uint8_t code = encoded & 0x0F;
555+
if (code == 0) {
556+
return 0.f;
557+
}
558+
return code == AboveRangeCode ? MaxNSigma : MinFineNSigma + static_cast<float>(code - 1) * Step;
559+
}
560+
561+
static float getTPCNSigma(uint8_t encoded)
562+
{
563+
return decodeNSigma((encoded >> 4) & 0x0F);
564+
}
565+
566+
static float getTOFNSigma(uint8_t encoded, bool hasTOF)
567+
{
568+
return hasTOF ? decodeNSigma(encoded & 0x0F) : NAN;
569+
}
570+
571+
operator uint8_t() const { return flag; }
572+
};
573+
574+
/// @brief Compact absolute DCAxy/DCAz values into two four-bit fields.
575+
/// Codes 0..14 represent lower-inclusive 0.01 cm-wide bins [0.00, 0.01),
576+
/// ..., [0.14, 0.15) cm and decode to their lower edges. Code 15 directly
577+
/// represents |DCA| >= 0.15 cm and decodes to the 0.15 cm marker; no additional
578+
/// tight-DCA or overflow flag is stored.
579+
struct DCAEncoding {
580+
static constexpr float MaxDCA = 0.15f;
581+
static constexpr float Step = 0.01f;
582+
static constexpr uint8_t MaxRegularCode = 14;
583+
static constexpr uint8_t AboveRangeCode = 15;
584+
585+
uint8_t flag = 0;
586+
587+
DCAEncoding() = default;
588+
DCAEncoding(float dcaXY, float dcaZ)
589+
: flag(static_cast<uint8_t>((encodeDCA(dcaXY) << 4) | encodeDCA(dcaZ)))
590+
{
591+
}
592+
593+
static bool isValid(float dca)
594+
{
595+
return std::isfinite(dca);
596+
}
597+
598+
static uint8_t encodeDCA(float dca)
599+
{
600+
const float value = std::abs(dca);
601+
if (!std::isfinite(value)) {
602+
return AboveRangeCode;
603+
}
604+
if (value >= MaxDCA) {
605+
return AboveRangeCode;
606+
}
607+
const int encoded = static_cast<int>(std::floor(value / Step));
608+
return static_cast<uint8_t>(std::clamp(encoded, 0, static_cast<int>(MaxRegularCode)));
609+
}
610+
611+
static float decodeDCA(uint8_t encoded)
612+
{
613+
const uint8_t code = encoded & 0x0F;
614+
return code == AboveRangeCode ? MaxDCA : static_cast<float>(code) * Step;
615+
}
616+
617+
static float decodeDCAxy(uint8_t encoded)
618+
{
619+
return decodeDCA((encoded >> 4) & 0x0F);
620+
}
621+
622+
static float decodeDCAz(uint8_t encoded)
623+
{
624+
return decodeDCA(encoded & 0x0F);
625+
}
626+
627+
operator uint8_t() const { return flag; }
628+
};
629+
630+
DECLARE_SOA_COLUMN(PidNSigmaFlag, pidNSigmaFlag, uint8_t); //! TPC/TOF PID flag for the configured species
631+
DECLARE_SOA_COLUMN(TrackSelectionFlags, trackSelectionFlags, uint8_t); //! Packed absolute DCAxy/DCAz values
632+
DECLARE_SOA_COLUMN(Px1000, px1000, int16_t); //! p_x x 1000 (GeV/c)
633+
DECLARE_SOA_COLUMN(Py1000, py1000, int16_t); //! p_y x 1000 (GeV/c)
634+
DECLARE_SOA_COLUMN(Pz1000, pz1000, int16_t); //! p_z x 1000 (GeV/c)
635+
636+
DECLARE_SOA_DYNAMIC_COLUMN(Px, px,
637+
[](int16_t px1000) { return static_cast<float>(px1000) / 1000.f; });
638+
DECLARE_SOA_DYNAMIC_COLUMN(Py, py,
639+
[](int16_t py1000) { return static_cast<float>(py1000) / 1000.f; });
640+
DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz,
641+
[](int16_t pz1000) { return static_cast<float>(pz1000) / 1000.f; });
642+
DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt,
643+
[](int16_t px1000, int16_t py1000) {
644+
const float px = static_cast<float>(px1000) / 1000.f;
645+
const float py = static_cast<float>(py1000) / 1000.f;
646+
return RecoDecay::sqrtSumOfSquares(px, py);
647+
});
648+
DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta,
649+
[](int16_t px1000, int16_t py1000, int16_t pz1000) {
650+
return RecoDecay::eta(std::array{static_cast<float>(px1000) / 1000.f,
651+
static_cast<float>(py1000) / 1000.f,
652+
static_cast<float>(pz1000) / 1000.f});
653+
});
654+
DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi,
655+
[](int16_t px1000, int16_t py1000) {
656+
return RecoDecay::phi(static_cast<float>(px1000) / 1000.f,
657+
static_cast<float>(py1000) / 1000.f);
658+
});
659+
DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigma, tpcNSigma,
660+
[](uint8_t pidNSigmaFlag) { return PidNSigma::getTPCNSigma(pidNSigmaFlag); });
661+
DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigma, tofNSigma,
662+
[](uint8_t pidNSigmaFlag, uint8_t trackFlags) -> float {
663+
const bool hasTOF = resodaughter::ResoTrackFlags::checkFlag(trackFlags, resodaughter::ResoTrackFlags::kHasTOF);
664+
return PidNSigma::getTOFNSigma(pidNSigmaFlag, hasTOF);
665+
});
666+
DECLARE_SOA_DYNAMIC_COLUMN(DcaXY, dcaXY,
667+
[](uint8_t trackSelectionFlags) { return DCAEncoding::decodeDCAxy(trackSelectionFlags); });
668+
DECLARE_SOA_DYNAMIC_COLUMN(DcaZ, dcaZ,
669+
[](uint8_t trackSelectionFlags) { return DCAEncoding::decodeDCAz(trackSelectionFlags); });
670+
} // namespace resoultramicrodaughter
671+
510672
DECLARE_SOA_TABLE(ResoTracks, "AOD", "RESOTRACK",
511673
o2::soa::Index<>,
512674
resodaughter::ResoCollisionId,
@@ -582,6 +744,40 @@ DECLARE_SOA_TABLE(ResoMicroTrackTracks, "AOD", "RESOMICROTRACKTRACK",
582744
resodaughter::TrackId);
583745
using ResoMicroTrackTrack = ResoMicroTrackTracks::iterator;
584746

747+
DECLARE_SOA_TABLE(ResoUltraMicroTracks, "AOD", "RESOULTRAMTRK",
748+
o2::soa::Index<>,
749+
resodaughter::ResoCollisionId,
750+
resoultramicrodaughter::Px1000,
751+
resoultramicrodaughter::Py1000,
752+
resoultramicrodaughter::Pz1000,
753+
resoultramicrodaughter::PidNSigmaFlag,
754+
resoultramicrodaughter::TrackSelectionFlags,
755+
resodaughter::TrackFlags,
756+
// Dynamic columns
757+
resoultramicrodaughter::Px<resoultramicrodaughter::Px1000>,
758+
resoultramicrodaughter::Py<resoultramicrodaughter::Py1000>,
759+
resoultramicrodaughter::Pz<resoultramicrodaughter::Pz1000>,
760+
resoultramicrodaughter::Pt<resoultramicrodaughter::Px1000, resoultramicrodaughter::Py1000>,
761+
resoultramicrodaughter::Eta<resoultramicrodaughter::Px1000, resoultramicrodaughter::Py1000, resoultramicrodaughter::Pz1000>,
762+
resoultramicrodaughter::Phi<resoultramicrodaughter::Px1000, resoultramicrodaughter::Py1000>,
763+
resoultramicrodaughter::TPCNSigma<resoultramicrodaughter::PidNSigmaFlag>,
764+
resoultramicrodaughter::TOFNSigma<resoultramicrodaughter::PidNSigmaFlag, resodaughter::TrackFlags>,
765+
resoultramicrodaughter::DcaXY<resoultramicrodaughter::TrackSelectionFlags>,
766+
resoultramicrodaughter::DcaZ<resoultramicrodaughter::TrackSelectionFlags>,
767+
resodaughter::PassedITSRefit<resodaughter::TrackFlags>,
768+
resodaughter::PassedTPCRefit<resodaughter::TrackFlags>,
769+
resodaughter::IsGlobalTrackWoDCA<resodaughter::TrackFlags>,
770+
resodaughter::IsGlobalTrack<resodaughter::TrackFlags>,
771+
resodaughter::IsPrimaryTrack<resodaughter::TrackFlags>,
772+
resodaughter::IsPVContributor<resodaughter::TrackFlags>,
773+
resodaughter::HasTOF<resodaughter::TrackFlags>,
774+
resodaughter::Sign<resodaughter::TrackFlags>);
775+
using ResoUltraMicroTrack = ResoUltraMicroTracks::iterator;
776+
777+
DECLARE_SOA_TABLE(ResoUltraMicroTrackTracks, "AOD", "RESOULTRAMTRKID",
778+
resodaughter::TrackId);
779+
using ResoUltraMicroTrackTrack = ResoUltraMicroTrackTracks::iterator;
780+
585781
// For DF mixing study
586782
DECLARE_SOA_TABLE(ResoTrackDFs, "AOD", "RESOTRACKDF",
587783
o2::soa::Index<>,

0 commit comments

Comments
 (0)