Skip to content

Commit fb51a3c

Browse files
committed
[PWGCF] Event shape capabilities Added
1 parent 0291c81 commit fb51a3c

File tree

3 files changed

+199
-2
lines changed

3 files changed

+199
-2
lines changed

PWGCF/DataModel/CorrelationsDerived.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ using CFCollLabel = CFCollLabels::iterator;
6262
using CFCollisionsWithLabel = soa::Join<CFCollisions, CFCollLabels>;
6363
using CFCollisionWithLabel = CFCollisionsWithLabel::iterator;
6464

65+
namespace cfeventshape
66+
{
67+
DECLARE_SOA_INDEX_COLUMN(CFCollision, cfCollision); //! Index to collision
68+
DECLARE_SOA_COLUMN(Spherocity, spherocity, float); //! Spherocity
69+
} // namespace cfeventshape
70+
DECLARE_SOA_TABLE(CFEventShapes, "AOD", "CFEVENTSHAPE", //! Event shape table
71+
o2::soa::Index<>,
72+
cfeventshape::Spherocity);
73+
using CFEventShape = CFEventShapes::iterator;
74+
6575
namespace cftrack
6676
{
6777
DECLARE_SOA_INDEX_COLUMN(CFCollision, cfCollision); //! Index to collision

PWGCF/TableProducer/filterCorrelations.cxx

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,177 @@ struct MultiplicitySelector {
574574
PROCESS_SWITCH(MultiplicitySelector, processMCGen, "Select MC particle count as multiplicity", false);
575575
};
576576

577+
struct EventShapeProducer {
578+
Produces<aod::CFEventShapes> OutputEventShape;
579+
580+
O2_DEFINE_CONFIGURABLE(minTracks, int, 10, "Minimum number of tracks per collision required to estimate spherocity");
581+
O2_DEFINE_CONFIGURABLE(minPtTrack, float, 0.2, "Minimum pT of tracks required to estimate spherocity");
582+
O2_DEFINE_CONFIGURABLE(AbsEtaTrack, float, 0.8, "Maximum |eta| of tracks required to estimate spherocity");
583+
O2_DEFINE_CONFIGURABLE(usePtWeighted, bool, false, "Use pt-weighted spherocity");
584+
O2_DEFINE_CONFIGURABLE(outputQAHistos, bool, false, "Whether to output QA histograms for spherocity");
585+
586+
HistogramRegistry QAhistos{"QAhistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true};
587+
HistogramRegistry QAhistosCent{"QAhistosCent", {}, OutputObjHandlingPolicy::AnalysisObject, false, true};
588+
HistogramRegistry QAhistosSpherocity{"QAhistosSpherocity", {}, OutputObjHandlingPolicy::AnalysisObject, false, true};
589+
590+
std::vector<float> nx, ny, px, py;
591+
592+
void init(InitContext const&)
593+
{
594+
AxisSpec axisPt = {100, 0.0, 50.0};
595+
AxisSpec axisEta = {100, -1.2, 1.2};
596+
AxisSpec axisPhi = {100, 0.0, 2.0 * M_PI};
597+
AxisSpec axisNtracks = {100, 0.0, 200.0};
598+
AxisSpec axisMult = {100, 0.0, 100.0};
599+
AxisSpec axisSpherocity = {1000, 0.0, 1.0};
600+
601+
QAhistos.add("multS0", "",{HistType::kTH2F,{axisMult, axisSpherocity}});
602+
QAhistos.add("spherocity", "", {HistType::kTH1F, {axisSpherocity}});
603+
604+
if(!outputQAHistos) return;
605+
QAhistos.add("pt", "", {HistType::kTH1F, {axisPt}});
606+
QAhistos.add("eta", "", {HistType::kTH1F, {axisEta}});
607+
QAhistos.add("phi", "", {HistType::kTH1F, {axisPhi}});
608+
QAhistos.add("ntracks", "", {HistType::kTH1F, {axisNtracks}});
609+
QAhistos.add("mult", "", {HistType::kTH1F, {axisMult}});
610+
QAhistos.add("etaphi", "", {HistType::kTH2F, {axisPhi, axisEta}});
611+
612+
QAhistosCent.add("ntracks_0_20", "", {HistType::kTH1F, {axisNtracks}});
613+
QAhistosCent.add("ntracks_20_40", "", {HistType::kTH1F, {axisNtracks}});
614+
QAhistosCent.add("ntracks_40_60", "", {HistType::kTH1F, {axisNtracks}});
615+
QAhistosCent.add("ntracks_60_100", "", {HistType::kTH1F, {axisNtracks}});
616+
617+
QAhistosSpherocity.add("spherocity_0_20", "", {HistType::kTH1F, {axisSpherocity}});
618+
QAhistosSpherocity.add("spherocity_20_40", "", {HistType::kTH1F, {axisSpherocity}});
619+
QAhistosSpherocity.add("spherocity_40_60", "", {HistType::kTH1F, {axisSpherocity}});
620+
QAhistosSpherocity.add("spherocity_60_100", "", {HistType::kTH1F, {axisSpherocity}});
621+
}
622+
623+
// Spherocity calculation based on the central barrel tracks
624+
template<typename TTracks>
625+
float CalculateSpherocity(TTracks const& tracks, bool usePtWeighted, bool outputQAHistos)
626+
{
627+
const size_t nTracks = tracks.size();
628+
if (nTracks < static_cast<size_t>(minTracks)) return -2.0f;
629+
630+
if (nx.size() < nTracks) {
631+
nx.resize(nTracks);
632+
ny.resize(nTracks);
633+
px.resize(nTracks);
634+
py.resize(nTracks);
635+
}
636+
637+
float sumPt = 0.0f;
638+
float retval = 999.0f;
639+
640+
size_t idx = 0;
641+
for (auto& track : tracks) {
642+
const float cosPhi = std::cos(track.phi());
643+
const float sinPhi = std::sin(track.phi());
644+
645+
nx[idx] = cosPhi;
646+
ny[idx] = sinPhi;
647+
648+
if (usePtWeighted) {
649+
const float pt = track.pt();
650+
px[idx] = pt * cosPhi;
651+
py[idx] = pt * sinPhi;
652+
sumPt += pt;
653+
} else {
654+
px[idx] = cosPhi;
655+
py[idx] = sinPhi;
656+
sumPt += 1.0f;
657+
}
658+
if (outputQAHistos) {
659+
QAhistos.fill(HIST("pt"), track.pt());
660+
QAhistos.fill(HIST("eta"), track.eta());
661+
QAhistos.fill(HIST("phi"), track.phi());
662+
QAhistos.fill(HIST("etaphi"), track.phi(), track.eta());
663+
}
664+
idx++;
665+
}
666+
667+
if (sumPt == 0.0f) return -1.5f; // no tracks -- avoid division by zero
668+
669+
// Validation check for non-weighted case
670+
if (!usePtWeighted && std::abs(static_cast<float>(nTracks) - sumPt) > 0.01f) {
671+
LOGF(info, "Spherocity calculation: number of tracks (%zu) does not match sum of pT (%f)", nTracks, sumPt);
672+
return -1.0f;
673+
}
674+
675+
for (size_t i = 0; i < nTracks; i++) {
676+
float numerator = 0.0f;
677+
const float nyi = ny[i];
678+
const float nxi = nx[i];
679+
680+
for (size_t j = 0; j < nTracks; j++) {
681+
numerator += std::abs(nyi * px[j] - nxi * py[j]);
682+
}
683+
684+
const float sFull = std::pow(numerator / sumPt, 2);
685+
if (sFull < retval) retval = sFull;
686+
}
687+
688+
retval = retval * M_PI * M_PI / 4.0f; // normalization factor
689+
690+
if (retval < 0.0f || retval > 1.0f) {
691+
LOGF(info, "Spherocity value is out of range: %f", retval);
692+
return -0.5f;
693+
}
694+
695+
return retval;
696+
}//spherocity calculation ends
697+
698+
Filter cftrackFilter = (aod::cftrack::pt > minPtTrack) && (nabs(aod::cftrack::eta) < AbsEtaTrack);
699+
700+
using myCollisions = aod::CFCollisions;
701+
using myTracks = soa::Filtered<aod::CFTracks>;
702+
703+
inline int getCentralityBin(float multiplicity) {
704+
if (multiplicity < 20.0f) return 0;
705+
else if (multiplicity < 40.0f) return 1;
706+
else if (multiplicity < 60.0f) return 2;
707+
else if (multiplicity < 100.0f) return 3;
708+
return -1; // outside range
709+
}
710+
711+
void processSpherocityData(myCollisions::iterator const& coll, myTracks const& tracks)
712+
{
713+
float spherocity = CalculateSpherocity(tracks, usePtWeighted, outputQAHistos);
714+
OutputEventShape(spherocity);
715+
const float multiplicity = coll.multiplicity();
716+
QAhistos.fill(HIST("multS0"), multiplicity, spherocity);
717+
QAhistos.fill(HIST("spherocity"), spherocity);
718+
719+
if (!outputQAHistos) return;
720+
721+
const size_t nTracks = tracks.size();
722+
const int centralityBin = getCentralityBin(multiplicity);
723+
724+
QAhistos.fill(HIST("ntracks"), nTracks);
725+
QAhistos.fill(HIST("mult"), multiplicity);
726+
727+
if (centralityBin == 0) {
728+
QAhistosCent.fill(HIST("ntracks_0_20"), nTracks);
729+
QAhistosSpherocity.fill(HIST("spherocity_0_20"), spherocity);
730+
} else if (centralityBin == 1) {
731+
QAhistosCent.fill(HIST("ntracks_20_40"), nTracks);
732+
QAhistosSpherocity.fill(HIST("spherocity_20_40"), spherocity);
733+
} else if (centralityBin == 2) {
734+
QAhistosCent.fill(HIST("ntracks_40_60"), nTracks);
735+
QAhistosSpherocity.fill(HIST("spherocity_40_60"), spherocity);
736+
} else if (centralityBin == 3) {
737+
QAhistosCent.fill(HIST("ntracks_60_100"), nTracks);
738+
QAhistosSpherocity.fill(HIST("spherocity_60_100"), spherocity);
739+
}
740+
}
741+
PROCESS_SWITCH(EventShapeProducer, processSpherocityData, "Spherocity analysis for Data", false);
742+
};
743+
577744
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
578745
{
579746
return WorkflowSpec{
580747
adaptAnalysisTask<FilterCF>(cfgc),
581-
adaptAnalysisTask<MultiplicitySelector>(cfgc)};
748+
adaptAnalysisTask<MultiplicitySelector>(cfgc),
749+
adaptAnalysisTask<EventShapeProducer>(cfgc)};
582750
}

PWGCF/Tasks/correlations.cxx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ struct CorrelationTask {
109109
O2_DEFINE_CONFIGURABLE(cfgPtDepMLbkg, std::vector<float>, {}, "pT interval for ML training")
110110
O2_DEFINE_CONFIGURABLE(cfgPtCentDepMLbkgSel, std::vector<float>, {}, "Bkg ML selection")
111111

112+
O2_DEFINE_CONFIGURABLE(cfgS0CutLow, float, 0.0, "Lower cut for spherocity");
113+
O2_DEFINE_CONFIGURABLE(cfgS0CutUp, float, 1.0, "Upper cut for spherocity");
114+
112115
ConfigurableAxis axisVertex{"axisVertex", {7, -7, 7}, "vertex axis for histograms"};
113116
ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"};
114117
ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"};
@@ -126,7 +129,9 @@ struct CorrelationTask {
126129
Filter collisionZVtxFilter = nabs(aod::collision::posZ) < cfgCutVertex;
127130
// This filter is only applied to AOD
128131
Filter collisionVertexTypeFilter = (aod::collision::flags & static_cast<uint16_t>(aod::collision::CollisionFlagsRun2::Run2VertexerTracks)) == static_cast<uint16_t>(aod::collision::CollisionFlagsRun2::Run2VertexerTracks);
129-
132+
133+
Filter collisionSpherocityFilter = (aod::cfeventshape::spherocity > cfgS0CutLow) && (aod::cfeventshape::spherocity < cfgS0CutUp);
134+
130135
// Track filters
131136
Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true));
132137
Filter cfTrackFilter = (nabs(aod::cftrack::eta) < cfgCutEta) && (aod::cftrack::pt > cfgCutPt) && ((aod::track::trackType & (uint8_t)cfgTrackBitMask) == (uint8_t)cfgTrackBitMask);
@@ -167,6 +172,8 @@ struct CorrelationTask {
167172
using DerivedCollisions = soa::Filtered<aod::CFCollisions>;
168173
using DerivedTracks = soa::Filtered<aod::CFTracks>;
169174

175+
using DerivedCollisionsWithSpherocity = soa::Filtered<soa::Join<aod::CFCollisions, aod::CFEventShapes>>;
176+
170177
void init(o2::framework::InitContext&)
171178
{
172179
if ((doprocessSame2ProngDerivedML || doprocessSame2Prong2ProngML || doprocessMixed2ProngDerivedML || doprocessMixed2Prong2ProngML) && (cfgPtDepMLbkg->empty() || cfgPtCentDepMLbkgSel->empty()))
@@ -859,6 +866,12 @@ struct CorrelationTask {
859866
}
860867
PROCESS_SWITCH(CorrelationTask, processSameDerivedMultSet, "Process same event on derived data with multiplicity sets", false);
861868

869+
void processSameDerivedWithSpherocity(DerivedCollisionsWithSpherocity::iterator const& collision, soa::Filtered<aod::CFTracks> const& tracks)
870+
{
871+
processSameDerivedT(collision, tracks, tracks);
872+
}
873+
PROCESS_SWITCH(CorrelationTask, processSameDerivedWithSpherocity, "Process same event on derived data with spherocity", false);
874+
862875
void processSame2ProngDerived(DerivedCollisions::iterator const& collision, soa::Filtered<aod::CFTracks> const& tracks, soa::Filtered<aod::CF2ProngTracks> const& p2tracks)
863876
{
864877
processSameDerivedT(collision, p2tracks, tracks);
@@ -995,6 +1008,12 @@ struct CorrelationTask {
9951008
}
9961009
PROCESS_SWITCH(CorrelationTask, processMixedDerivedMultSet, "Process mixed events on derived data with multiplicity sets", false);
9971010

1011+
void processMixedDerivedWithSpherocity(DerivedCollisionsWithSpherocity const& collisions, DerivedTracks const& tracks)
1012+
{
1013+
processMixedDerivedT(collisions, tracks);
1014+
}
1015+
PROCESS_SWITCH(CorrelationTask, processMixedDerivedWithSpherocity, "Process mixed events on derived data with spherocity", false);
1016+
9981017
void processMixed2ProngDerived(DerivedCollisions const& collisions, DerivedTracks const& tracks, soa::Filtered<aod::CF2ProngTracks> const& p2tracks)
9991018
{
10001019
processMixedDerivedT(collisions, p2tracks, tracks);

0 commit comments

Comments
 (0)