@@ -73,6 +73,8 @@ struct cksspinalignment {
7373 Configurable<bool > cfgEvtRCTFlagCheckerLimitAcceptAsBad{" cfgEvtRCTFlagCheckerLimitAcceptAsBad" , true , " Evt sel: RCT flag checker treat Limited Acceptance As Bad" };
7474 } rctCut;
7575
76+ Configurable<bool > useNoCollInTimeRangeStandard{" useNoCollInTimeRangeStandard" , false , " Apply kNoCollInTimeRangeStandard selection bit" };
77+ Configurable<bool > useGoodITSLayersAll{" useGoodITSLayersAll" , true , " Apply kIsGoodITSLayersAll selection bit" };
7678 Configurable<int > cfgCutOccupancy{" cfgCutOccupancy" , 2000 , " Occupancy cut" };
7779
7880 // events
@@ -101,6 +103,13 @@ struct cksspinalignment {
101103 Configurable<float > cutTOFBetaPiMeson{" cutTOFBetaPiMeson" , 3.0 , " Maximum beta cut for pi meson track" };
102104 } grpPion;
103105
106+ enum PionPidBits : uint8_t {
107+ kPID1 = 1u << 0 , // selectionPID
108+ kPID2 = 1u << 1 , // selectionPID2
109+ kPID3 = 1u << 2 , // selectionPID3
110+ kPID4 = 1u << 3 // selectionPID4
111+ };
112+
104113 // Configs for V0
105114 Configurable<float > confV0PtMin{" confV0PtMin" , 0 .f , " Minimum transverse momentum of V0" };
106115 Configurable<float > confV0PtMax{" confV0PtMax" , 1000 .f , " Maximum transverse momentum of V0" };
@@ -120,6 +129,10 @@ struct cksspinalignment {
120129 Configurable<float > confDaughTPCncrwsMin{" confDaughTPCncrwsMin" , 70 .f , " V0 Daugh sel: Min. nCrws TPC" };
121130 Configurable<float > confDaughPIDCuts{" confDaughPIDCuts" , 3 , " PID selections for Kshortpion daughters" };
122131
132+ // configurable for chargedkstar
133+ Configurable<float > cfgKstarMassMin{" cfgKstarMassMin" , 0 .75f , " K* mass min" };
134+ Configurable<float > cfgKstarMassMax{" cfgKstarMassMax" , 1 .05f , " K* mass max" };
135+
123136 Configurable<int > iMNbins{" iMNbins" , 50 , " Number of bins in invariant mass" };
124137 Configurable<float > lbinIM{" lbinIM" , 1.09 , " lower bin value in IM histograms" };
125138 Configurable<float > hbinIM{" hbinIM" , 1.14 , " higher bin value in IM histograms" };
@@ -130,6 +143,8 @@ struct cksspinalignment {
130143 {
131144 rctChecker.init (rctCut.cfgEvtRCTFlagCheckerLabel , rctCut.cfgEvtRCTFlagCheckerZDCCheck , rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad );
132145 AxisSpec thnAxisInvMass{iMNbins, lbinIM, hbinIM, " #it{M} (GeV/#it{c}^{2})" };
146+
147+ histos.add (" hCent" , " hCent" , kTH1F , {{8 , 0 , 80.0 }});
133148 histos.add (" hEvtSelInfo" , " hEvtSelInfo" , kTH1F , {{5 , 0 , 5.0 }});
134149 histos.add (" hTrkSelInfo" , " hTrkSelInfo" , kTH1F , {{5 , 0 , 5.0 }});
135150 histos.add (" hKShortMass" , " hKShortMass" , kTH1F , {thnAxisInvMass});
@@ -157,6 +172,81 @@ struct cksspinalignment {
157172 return false ;
158173 }
159174
175+ template <typename T>
176+ bool selectionPID2 (const T& candidate)
177+ {
178+ if (!candidate.hasTOF () && std::abs (candidate.tpcNSigmaPi ()) < grpPion.nsigmaCutTPCPiMeson ) {
179+ return true ;
180+ }
181+ if (candidate.hasTOF () && candidate.beta () > grpPion.cutTOFBetaPiMeson && std::sqrt (candidate.tpcNSigmaPi () * candidate.tpcNSigmaPi () + candidate.tofNSigmaPi () * candidate.tofNSigmaPi ()) < grpPion.nsigmaCutTOFPiMeson ) {
182+ return true ;
183+ }
184+ return false ;
185+ }
186+
187+ template <typename T>
188+ bool selectionPID3 (const T& candidate)
189+ {
190+ auto px = candidate.px ();
191+ auto py = candidate.py ();
192+ // auto pz = candidate.pz();
193+ auto pt = std::sqrt (px * px + py * py);
194+ float lowmom = 0.5 ;
195+ if (pt < lowmom) {
196+ if (!candidate.hasTOF () && std::abs (candidate.tpcNSigmaPi ()) < grpPion.nsigmaCutTPCPiMeson ) {
197+ return true ;
198+ } else if (candidate.hasTOF () && std::sqrt (candidate.tpcNSigmaPi () * candidate.tpcNSigmaPi () + candidate.tofNSigmaPi () * candidate.tofNSigmaPi ()) < grpPion.nsigmaCutTOFPiMeson ) {
199+ return true ;
200+ }
201+ } else if (candidate.hasTOF () && std::sqrt (candidate.tpcNSigmaPi () * candidate.tpcNSigmaPi () + candidate.tofNSigmaPi () * candidate.tofNSigmaPi ()) < grpPion.nsigmaCutTOFPiMeson ) {
202+ return true ;
203+ }
204+ return false ;
205+ }
206+
207+ template <typename T>
208+ bool selectionPID4 (const T& candidate)
209+ {
210+ // Use total momentum p (as you said). If you really want pT, replace with sqrt(px^2+py^2).
211+ const float px = candidate.px ();
212+ const float py = candidate.py ();
213+ // const float pz = candidate.pz();
214+ const float pt = std::sqrt (px * px + py * py);
215+
216+ constexpr float pSwitch = 0 .5f ; // GeV/c
217+
218+ const float nTPC = candidate.tpcNSigmaPi ();
219+
220+ // Low momentum: TPC-only, TOF not required and not used
221+ if (pt < pSwitch) {
222+ return std::abs (nTPC) < grpPion.nsigmaCutTPCPiMeson ; // e.g. 3
223+ }
224+
225+ // High momentum: TOF hit mandatory + separate 3σ cuts
226+ if (!candidate.hasTOF ()) {
227+ return false ;
228+ }
229+
230+ const float nTOF = candidate.tofNSigmaPi ();
231+ return (std::abs (nTPC) < grpPion.nsigmaCutTPCPiMeson ) &&
232+ (std::abs (nTOF) < grpPion.nsigmaCutTOFPiMeson );
233+ }
234+
235+ template <typename T>
236+ uint8_t pionPidMask (const T& trk)
237+ {
238+ uint8_t m = 0 ;
239+ if (selectionPID (trk))
240+ m |= kPID1 ;
241+ if (selectionPID2 (trk))
242+ m |= kPID2 ;
243+ if (selectionPID3 (trk))
244+ m |= kPID3 ;
245+ if (selectionPID4 (trk))
246+ m |= kPID4 ;
247+ return m;
248+ }
249+
160250 template <typename Collision, typename V0>
161251 bool selectionV0 (Collision const & collision, V0 const & candidate)
162252 {
@@ -280,11 +370,12 @@ struct cksspinalignment {
280370 std::vector<float > dcaBetweenDaughter = {};
281371 std::vector<float > v0Lifetime = {};
282372 // std::vector<float> armenteros = {};
283- std::vector<float > pionBachelorIndex = {};
373+ std::vector<int > pionBachelorIndex = {};
284374 // std::vector<float> pionBachelorSign = {};
285- std::vector<float > pionBachelorTPC = {};
286- std::vector<float > pionBachelorTOF = {};
287- std::vector<float > pionBachelorTOFHit = {};
375+ // std::vector<float> pionBachelorTPC = {};
376+ // std::vector<float> pionBachelorTOF = {};
377+ // std::vector<int8_t> pionBachelorTOFHit = {};
378+ std::vector<uint8_t > pionBachelorPidMask = {};
288379
289380 int numbV0 = 0 ;
290381 auto centrality = collision.centFT0C ();
@@ -296,10 +387,12 @@ struct cksspinalignment {
296387 // auto psiTPCR = collision.psiTPCR();
297388 // auto psiTPCL = collision.psiTPCL();
298389 histos.fill (HIST (" hEvtSelInfo" ), 0.5 );
299- if ((rctCut.requireRCTFlagChecker && rctChecker (collision)) && collision.selection_bit (aod::evsel::kNoSameBunchPileup ) && collision.selection_bit (aod::evsel::kIsGoodZvtxFT0vsPV ) && collision.selection_bit (aod::evsel::kNoTimeFrameBorder ) && collision.selection_bit (aod::evsel::kNoITSROFrameBorder ) && collision.selection_bit (o2::aod::evsel::kNoCollInTimeRangeStandard ) && collision.sel8 () && collision.selection_bit (o2::aod::evsel::kIsGoodITSLayersAll ) && occupancy < cfgCutOccupancy) {
390+ // if ((!rctCut.requireRCTFlagChecker || rctChecker(collision)) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && collision.sel8() && collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll) && occupancy < cfgCutOccupancy) {
391+ if ((!rctCut.requireRCTFlagChecker || rctChecker (collision)) && collision.selection_bit (aod::evsel::kNoSameBunchPileup ) && collision.selection_bit (aod::evsel::kIsGoodZvtxFT0vsPV ) && collision.selection_bit (aod::evsel::kNoTimeFrameBorder ) && collision.selection_bit (aod::evsel::kNoITSROFrameBorder ) && (!useNoCollInTimeRangeStandard || collision.selection_bit (o2::aod::evsel::kNoCollInTimeRangeStandard )) && collision.sel8 () && (!useGoodITSLayersAll || collision.selection_bit (o2::aod::evsel::kIsGoodITSLayersAll )) && occupancy < cfgCutOccupancy) {
300392 histos.fill (HIST (" hEvtSelInfo" ), 1.5 );
301393 if (collision.triggereventep ()) {
302394 histos.fill (HIST (" hEvtSelInfo" ), 2.5 );
395+ histos.fill (HIST (" hCent" ), centrality);
303396
304397 for (const auto & track1 : tracks) {
305398 histos.fill (HIST (" hTrkSelInfo" ), 0.5 );
@@ -312,8 +405,12 @@ struct cksspinalignment {
312405 continue ;
313406 }
314407 histos.fill (HIST (" hTrkSelInfo" ), 2.5 );
315-
316- if (grpPion.usePID && !selectionPID (track1)) {
408+ /*
409+ if (grpPion.usePID && !selectionPID2(track1)) {
410+ continue;
411+ }*/
412+ const uint8_t mask = pionPidMask (track1);
413+ if (grpPion.usePID && mask == 0 ) {
317414 continue ;
318415 }
319416 histos.fill (HIST (" hTrkSelInfo" ), 3.5 );
@@ -322,21 +419,22 @@ struct cksspinalignment {
322419 auto track1sign = track1.sign ();
323420 if (track1sign == 0 )
324421 continue ;
325- auto track1nsigTPC = track1.tpcNSigmaPi ();
422+ /* auto track1nsigTPC = track1.tpcNSigmaPi();
326423 auto track1nsigTOF = -999.9;
327424 auto track1TOFHit = -1;
328425 if (track1.hasTOF()) {
329426 track1TOFHit = 1;
330427 track1nsigTOF = track1.tofNSigmaPi();
331428 histos.fill(HIST("hTrkSelInfo"), 4.5);
332- }
429+ } */
333430 pionbach = ROOT::Math::PxPyPzMVector (track1.px (), track1.py (), track1.pz (), o2::constants::physics::MassPionCharged);
334431 pionBachelor.push_back (pionbach);
335432 pionBachelorIndex.push_back (track1ID);
336433 // pionBachelorSign.push_back(track1sign);
337- pionBachelorTPC.push_back (track1nsigTPC);
338- pionBachelorTOF.push_back (track1nsigTOF);
339- pionBachelorTOFHit.push_back (track1TOFHit);
434+ // pionBachelorTPC.push_back(track1nsigTPC);
435+ // pionBachelorTOF.push_back(track1nsigTOF);
436+ // pionBachelorTOFHit.push_back(track1TOFHit);
437+ pionBachelorPidMask.push_back (mask);
340438 }
341439 for (const auto & v0 : V0s) {
342440 histos.fill (HIST (" hV0Info" ), 0.5 );
@@ -365,23 +463,66 @@ struct cksspinalignment {
365463 }
366464 numbV0 = numbV0 + 1 ;
367465 }
368- if (numbV0 > 1 && v0Cospa.size () > 1 ) {
369- histos.fill (HIST (" hEvtSelInfo" ), 3.5 );
370- kshortpionEvent (centrality, vz, collision.index (), psiFT0C, psiFT0A, psiTPC);
371- auto indexEvent = kshortpionEvent.lastIndex ();
372- // // Fill track table for Charged KStar//////////////////
373- for (auto icks = kshortMother.begin (); icks != kshortMother.end (); ++icks) {
374- auto iter = std::distance (kshortMother.begin (), icks);
375- kshortDummy = kshortMother.at (iter);
376- // chargedkstarDummy = chargedkstarMother.at(iter);
377-
378- kshortTrack (indexEvent, v0Cospa.at (iter), v0Radius.at (iter), dcaPositive.at (iter), dcaNegative.at (iter), dcaBetweenDaughter.at (iter), v0Lifetime.at (iter), kshortDummy.Px (), kshortDummy.Py (), kshortDummy.Pz (), kshortDummy.M (), positiveIndex.at (iter), negativeIndex.at (iter));
466+ if (numbV0 > 1 && v0Cospa.size () > 1 && !kshortMother.empty () && !pionBachelor.empty ()) {
467+
468+ std::vector<uint8_t > useK0 (kshortMother.size (), 0 );
469+ std::vector<uint8_t > usePi (pionBachelor.size (), 0 );
470+ bool anyPair = false ;
471+ for (size_t ik0 = 0 ; ik0 < kshortMother.size (); ++ik0) {
472+ const auto & k0 = kshortMother[ik0];
473+ const int posId = positiveIndex[ik0];
474+ const int negId = negativeIndex[ik0];
475+
476+ for (size_t ipi = 0 ; ipi < pionBachelor.size (); ++ipi) {
477+ const int piId = pionBachelorIndex[ipi];
478+
479+ // avoid self-combination: bachelor pion can't be a V0 daughter
480+ if (piId == posId || piId == negId) {
481+ continue ;
482+ }
483+
484+ const auto kstar = k0 + pionBachelor[ipi];
485+ const float m = kstar.M ();
486+
487+ if (m < cfgKstarMassMin || m > cfgKstarMassMax) {
488+ continue ;
489+ }
490+
491+ useK0[ik0] = 1 ;
492+ usePi[ipi] = 1 ;
493+ anyPair = true ;
494+ }
379495 }
380- for (auto ipi = pionBachelor.begin (); ipi != pionBachelor.end (); ++ipi) {
381- auto iterpi = std::distance (pionBachelor.begin (), ipi);
382- pionDummy = pionBachelor.at (iterpi);
383496
384- pionTrack (indexEvent, pionDummy.Px (), pionDummy.Py (), pionDummy.Pz (), pionBachelorTPC.at (iterpi), pionBachelorTOFHit.at (iterpi), pionBachelorTOF.at (iterpi), pionBachelorIndex.at (iterpi));
497+ // only write event + tables if at least one K* candidate exists in window
498+ if (anyPair) {
499+ histos.fill (HIST (" hEvtSelInfo" ), 3.5 );
500+ // kshortpionEvent(centrality, vz, collision.index(), psiFT0C, psiFT0A, psiTPC);
501+ kshortpionEvent (centrality, vz, psiFT0C, psiFT0A, psiTPC);
502+ auto indexEvent = kshortpionEvent.lastIndex ();
503+ // write only used K0s
504+ for (size_t ik0 = 0 ; ik0 < kshortMother.size (); ++ik0) {
505+ if (!useK0[ik0]) {
506+ continue ;
507+ }
508+ kshortDummy = kshortMother[ik0];
509+ kshortTrack (indexEvent, v0Cospa[ik0], v0Radius[ik0], dcaPositive[ik0], dcaNegative[ik0], dcaBetweenDaughter[ik0], v0Lifetime[ik0], kshortDummy.Px (), kshortDummy.Py (), kshortDummy.Pz (), kshortDummy.M (), positiveIndex[ik0], negativeIndex[ik0]);
510+ }
511+ // write only used pions
512+ for (size_t ipi = 0 ; ipi < pionBachelor.size (); ++ipi) {
513+ if (!usePi[ipi]) {
514+ continue ;
515+ }
516+ pionDummy = pionBachelor[ipi];
517+ /*
518+ pionTrack(indexEvent,
519+ pionDummy.Px(), pionDummy.Py(), pionDummy.Pz(),
520+ pionBachelorTPC[ipi],
521+ pionBachelorTOFHit[ipi],
522+ pionBachelorTOF[ipi],
523+ pionBachelorIndex[ipi]);*/
524+ pionTrack (indexEvent, pionDummy.Px (), pionDummy.Py (), pionDummy.Pz (), pionBachelorIndex[ipi], pionBachelorPidMask[ipi]);
525+ }
385526 }
386527 }
387528 }
0 commit comments