@@ -26,31 +26,44 @@ using namespace o2;
2626using namespace o2 ::framework;
2727using namespace o2 ::framework::expressions;
2828
29- using TracksFull = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::pidTPCPi>;
29+ using TracksFull = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU,
30+ aod::pidTPCFullPi, aod::pidTPCFullPr, aod::pidTPCFullKa,
31+ aod::pidTOFFullPi, aod::pidTOFFullPr, aod::pidTOFFullKa>;
3032using CollisionsFull = soa::Join<aod::Collisions, aod::EvSel>;
3133using CollisionsFullMC = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSel>;
3234
3335struct sigmaminustask {
36+
37+ // Output Tables
38+ Produces<aod::SlimKinkCands> outputDataTable;
39+ Produces<aod::SlimKinkCandsMC> outputDataTableMC;
40+
3441 // Histograms are defined with HistogramRegistry
3542 HistogramRegistry rEventSelection{" eventSelection" , {}, OutputObjHandlingPolicy::AnalysisObject, true , true };
3643 HistogramRegistry rSigmaMinus{" sigmaminus" , {}, OutputObjHandlingPolicy::AnalysisObject, true , true };
3744
3845 // Configurable for event selection
3946 Configurable<float > cutzvertex{" cutzvertex" , 10 .0f , " Accepted z-vertex range (cm)" };
4047 Configurable<float > cutNSigmaPi{" cutNSigmaPi" , 4 , " NSigmaTPCPion" };
48+ Configurable<float > cutEtaMotherMC{" cutEtaMotherMC" , 1 .0f , " Eta cut for mother Sigma in MC" };
49+
50+ Configurable<bool > fillOutputTree{" fillOutputTree" , true , " If true, fill the output tree with Kink candidates" };
4151
4252 Preslice<aod::KinkCands> mPerCol = aod::track::collisionId;
4353
4454 void init (InitContext const &)
4555 {
4656 // Axes
47- const AxisSpec ptAxis{50 , -10 , 10 , " #it{p}_{T} (GeV/#it{c})" };
57+ const AxisSpec ptAxis{100 , -10 , 10 , " #it{p}_{T} (GeV/#it{c})" };
4858 const AxisSpec nSigmaPiAxis{100 , -5 , 5 , " n#sigma_{#pi}" };
4959 const AxisSpec sigmaMassAxis{100 , 1.1 , 1.4 , " m (GeV/#it{c}^{2})" };
5060 const AxisSpec xiMassAxis{100 , 1.2 , 1.6 , " m_{#Xi} (GeV/#it{c}^{2})" };
5161 const AxisSpec pdgAxis{10001 , -5000 , 5000 , " PDG code" };
5262 const AxisSpec vertexZAxis{100 , -15 ., 15 ., " vrtx_{Z} [cm]" };
5363
64+ const AxisSpec ptResolutionAxis{100 , -0.5 , 0.5 , " #it{p}_{T}^{rec} - #it{p}_{T}^{gen} (GeV/#it{c})" };
65+ const AxisSpec massResolutionAxis{100 , -0.1 , 0.1 , " m_{rec} - m_{gen} (GeV/#it{c}^{2})" };
66+
5467 // Event selection
5568 rEventSelection.add (" hVertexZRec" , " hVertexZRec" , {HistType::kTH1F , {vertexZAxis}});
5669 // Sigma-minus reconstruction
@@ -62,6 +75,11 @@ struct sigmaminustask {
6275 // Add MC histograms if needed
6376 rSigmaMinus.add (" h2MassPtMCRec" , " h2MassPtMCRec" , {HistType::kTH2F , {ptAxis, sigmaMassAxis}});
6477 rSigmaMinus.add (" h2MassPtMCGen" , " h2MassPtMCGen" , {HistType::kTH2F , {ptAxis, sigmaMassAxis}});
78+
79+ rSigmaMinus.add (" h2MassResolution_minus" , " h2MassResolution_minus" , {HistType::kTH2F , {sigmaMassAxis, massResolutionAxis}});
80+ rSigmaMinus.add (" h2PtResolution_minus" , " h2PtResolution_minus" , {HistType::kTH2F , {ptAxis, ptResolutionAxis}});
81+ rSigmaMinus.add (" h2MassResolution_plus" , " h2MassResolution_plus" , {HistType::kTH2F , {sigmaMassAxis, massResolutionAxis}});
82+ rSigmaMinus.add (" h2PtResolution_plus" , " h2PtResolution_plus" , {HistType::kTH2F , {ptAxis, ptResolutionAxis}});
6583 }
6684 }
6785
@@ -71,14 +89,27 @@ struct sigmaminustask {
7189 return ;
7290 }
7391 rEventSelection.fill (HIST (" hVertexZRec" ), collision.posZ ());
92+
7493 for (const auto & kinkCand : KinkCands) {
7594 auto dauTrack = kinkCand.trackDaug_as <TracksFull>();
76- if (abs (dauTrack.tpcNSigmaPi ()) > cutNSigmaPi) {
95+
96+ if (std::abs (dauTrack.tpcNSigmaPi ()) > cutNSigmaPi) {
7797 continue ;
7898 }
99+
79100 rSigmaMinus.fill (HIST (" h2MassSigmaMinusPt" ), kinkCand.mothSign () * kinkCand.ptMoth (), kinkCand.mSigmaMinus ());
80101 rSigmaMinus.fill (HIST (" h2SigmaMassVsXiMass" ), kinkCand.mXiMinus (), kinkCand.mSigmaMinus ());
81102 rSigmaMinus.fill (HIST (" h2NSigmaPiPt" ), kinkCand.mothSign () * kinkCand.ptMoth (), dauTrack.tpcNSigmaPi ());
103+
104+ if (fillOutputTree) {
105+ outputDataTable (kinkCand.xDecVtx (), kinkCand.yDecVtx (), kinkCand.zDecVtx (),
106+ kinkCand.pxMoth (), kinkCand.pyMoth (), kinkCand.pzMoth (),
107+ kinkCand.pxDaug (), kinkCand.pyDaug (), kinkCand.pzDaug (),
108+ kinkCand.dcaMothPv (), kinkCand.dcaDaugPv (), kinkCand.dcaKinkTopo (),
109+ kinkCand.mothSign (),
110+ dauTrack.tpcNSigmaPi (), dauTrack.tpcNSigmaPr (), dauTrack.tpcNSigmaKa (),
111+ dauTrack.tofNSigmaPi (), dauTrack.tofNSigmaPr (), dauTrack.tofNSigmaKa ());
112+ }
82113 }
83114 }
84115 PROCESS_SWITCH (sigmaminustask, processData, " Data processing" , true );
@@ -92,20 +123,23 @@ struct sigmaminustask {
92123
93124 rEventSelection.fill (HIST (" hVertexZRec" ), collision.posZ ());
94125 auto kinkCandPerColl = KinkCands.sliceBy (mPerCol , collision.globalIndex ());
126+
95127 for (const auto & kinkCand : kinkCandPerColl) {
128+
96129 auto dauTrack = kinkCand.trackDaug_as <TracksFull>();
97130 auto mothTrack = kinkCand.trackMoth_as <TracksFull>();
98131 if (dauTrack.sign () != mothTrack.sign ()) {
99132 LOG (info) << " Skipping kink candidate with opposite sign daughter and mother: " << kinkCand.globalIndex ();
100133 continue ; // Skip if the daughter has the opposite sign as the mother
101134 }
102- if (abs (dauTrack.tpcNSigmaPi ()) > cutNSigmaPi) {
135+ if (std:: abs (dauTrack.tpcNSigmaPi ()) > cutNSigmaPi) {
103136 continue ;
104137 }
105138
106139 rSigmaMinus.fill (HIST (" h2MassSigmaMinusPt" ), kinkCand.mothSign () * kinkCand.ptMoth (), kinkCand.mSigmaMinus ());
107140 rSigmaMinus.fill (HIST (" h2SigmaMassVsXiMass" ), kinkCand.mXiMinus (), kinkCand.mSigmaMinus ());
108141 rSigmaMinus.fill (HIST (" h2NSigmaPiPt" ), kinkCand.mothSign () * kinkCand.ptMoth (), dauTrack.tpcNSigmaPi ());
142+
109143 // do MC association
110144 auto mcLabSigma = trackLabelsMC.rawIteratorAt (mothTrack.globalIndex ());
111145 auto mcLabPiDau = trackLabelsMC.rawIteratorAt (dauTrack.globalIndex ());
@@ -119,36 +153,93 @@ struct sigmaminustask {
119153 if (piMother.globalIndex () != mcTrackSigma.globalIndex ()) {
120154 continue ;
121155 }
122- if (std::abs (mcTrackSigma.pdgCode ()) != 3112 || std::abs (mcTrackPiDau.pdgCode ()) != 211 ) {
156+ if (std::abs (mcTrackSigma.pdgCode ()) != 3112 ) {
157+ continue ;
158+ }
159+ if (std::abs (mcTrackPiDau.pdgCode ()) != 211 && std::abs (mcTrackPiDau.pdgCode ()) != 2212 ) {
123160 continue ;
124161 }
162+
163+ float MotherMassMC = std::sqrt (piMother.e () * piMother.e () - piMother.p () * piMother.p ());
164+ float MotherpTMC = piMother.pt ();
165+ float deltaXMother = mcTrackPiDau.vx () - piMother.vx ();
166+ float deltaYMother = mcTrackPiDau.vy () - piMother.vy ();
167+ float decayRadiusMC = std::sqrt (deltaXMother * deltaXMother + deltaYMother * deltaYMother);
168+
169+ // Check coherence of MCcollision Id for daughter MCparticle and reconstructed collision
170+ auto mcCollision = mcTrackPiDau.template mcCollision_as <aod::McCollisions>();
171+ bool mcCollisionIdCheck = collision.mcCollisionId () == mcCollision.globalIndex ();
172+
125173 rSigmaMinus.fill (HIST (" h2MassPtMCRec" ), kinkCand.mothSign () * kinkCand.ptMoth (), kinkCand.mSigmaMinus ());
174+ if (mcTrackSigma.pdgCode () > 0 ) {
175+ rSigmaMinus.fill (HIST (" h2MassResolution_plus" ), kinkCand.mSigmaMinus (), kinkCand.mSigmaMinus () - MotherMassMC);
176+ rSigmaMinus.fill (HIST (" h2PtResolution_plus" ), kinkCand.ptMoth (), kinkCand.ptMoth () - MotherpTMC);
177+ } else {
178+ rSigmaMinus.fill (HIST (" h2MassResolution_minus" ), kinkCand.mSigmaMinus (), kinkCand.mSigmaMinus () - MotherMassMC);
179+ rSigmaMinus.fill (HIST (" h2PtResolution_minus" ), kinkCand.ptMoth (), kinkCand.ptMoth () - MotherpTMC);
180+ }
181+
182+ // fill the output table with Mc information
183+ if (fillOutputTree) {
184+ outputDataTableMC (kinkCand.xDecVtx (), kinkCand.yDecVtx (), kinkCand.zDecVtx (),
185+ kinkCand.pxMoth (), kinkCand.pyMoth (), kinkCand.pzMoth (),
186+ kinkCand.pxDaug (), kinkCand.pyDaug (), kinkCand.pzDaug (),
187+ kinkCand.dcaMothPv (), kinkCand.dcaDaugPv (), kinkCand.dcaKinkTopo (),
188+ kinkCand.mothSign (),
189+ dauTrack.tpcNSigmaPi (), dauTrack.tpcNSigmaPr (), dauTrack.tpcNSigmaKa (),
190+ dauTrack.tofNSigmaPi (), dauTrack.tofNSigmaPr (), dauTrack.tofNSigmaKa (),
191+ mcTrackSigma.pdgCode (), mcTrackPiDau.pdgCode (),
192+ MotherpTMC, MotherMassMC, decayRadiusMC, mcCollisionIdCheck);
193+ }
126194 }
127- }
128- }
129- }
195+ } // MC association and selection
196+ } // kink cand loop
197+ } // collision loop
198+
199+ // Loop over all generated particles to fill MC histograms
130200 for (const auto & mcPart : particlesMC) {
131- if (std::abs (mcPart.pdgCode ()) != 3112 || std::abs (mcPart.y ()) > 0.5 ) {
201+ if (std::abs (mcPart.pdgCode ()) != 3112 || std::abs (mcPart.y ()) > cutEtaMotherMC ) { // only sigma mothers and rapidity cut
132202 continue ;
133203 }
134204 if (!mcPart.has_daughters ()) {
135205 continue ; // Skip if no daughters
136206 }
137207 bool hasSigmaDaughter = false ;
208+ int daug_pdg = 0 ;
209+ std::array<float , 3 > secVtx;
210+ std::array<float , 3 > momDaug;
138211 for (const auto & daughter : mcPart.daughters_as <aod::McParticles>()) {
139- if (std::abs (daughter.pdgCode ()) == 211 ) { // Sigma PDG code
212+ if (std::abs (daughter.pdgCode ()) == 211 || std::abs (daughter. pdgCode ()) == 2212 ) { // Pi or proton daughter
140213 hasSigmaDaughter = true ;
141- break ; // Found a pi daughter, exit loop
214+ secVtx = {daughter.vx (), daughter.vy (), daughter.vz ()};
215+ momDaug = {daughter.px (), daughter.py (), daughter.pz ()};
216+ daug_pdg = daughter.pdgCode ();
217+ break ; // Found a daughter, exit loop
142218 }
143219 }
144220 if (!hasSigmaDaughter) {
145- continue ; // Skip if no pi daughter found
221+ continue ; // Skip if no pi/proton daughter found
146222 }
147223 float mcMass = std::sqrt (mcPart.e () * mcPart.e () - mcPart.p () * mcPart.p ());
224+ float mcDecayRadius = std::sqrt ((secVtx[0 ] - mcPart.vx ()) * (secVtx[0 ] - mcPart.vx ()) + (secVtx[1 ] - mcPart.vy ()) * (secVtx[1 ] - mcPart.vy ()));
148225 int sigmaSign = mcPart.pdgCode () > 0 ? 1 : -1 ; // Determine the sign of the Sigma
149226 rSigmaMinus.fill (HIST (" h2MassPtMCGen" ), sigmaSign * mcPart.pt (), mcMass);
227+
228+ // Fill output table with non reconstructed MC candidates
229+ if (fillOutputTree) {
230+ outputDataTableMC (-999 , -999 , -999 ,
231+ -999 , -999 , -999 ,
232+ -999 , -999 , -999 ,
233+ -999 , -999 , -999 ,
234+ sigmaSign,
235+ -999 , -999 , -999 ,
236+ -999 , -999 , -999 ,
237+ mcPart.pdgCode (), daug_pdg,
238+ mcPart.pt (), mcMass, mcDecayRadius, false );
239+ }
150240 }
151241 }
242+
152243 PROCESS_SWITCH (sigmaminustask, processMC, " MC processing" , false );
153244};
154245
0 commit comments