|
15 | 15 | /// \since June 1, 2021 |
16 | 16 |
|
17 | 17 | #include <cmath> |
| 18 | +#include "TVector3.h" |
18 | 19 | #include "CCDB/BasicCCDBManager.h" |
19 | 20 | #include "DataFormatsParameters/GRPMagField.h" |
20 | 21 | #include "DataFormatsParameters/GRPObject.h" |
|
25 | 26 | #include "Framework/AnalysisDataModel.h" |
26 | 27 | #include "Framework/ASoAHelpers.h" |
27 | 28 | #include "ReconstructionDataFormats/Track.h" |
| 29 | +#include "ReconstructionDataFormats/TrackParametrization.h" |
28 | 30 | #include "Common/Core/RecoDecay.h" |
29 | 31 | #include "Common/Core/trackUtilities.h" |
30 | 32 | #include "PWGLF/DataModel/LFStrangenessTables.h" |
@@ -73,10 +75,38 @@ struct strangenessFilter { |
73 | 75 | HistogramRegistry QAHistosTriggerParticles{"QAHistosTriggerParticles", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; |
74 | 76 | HistogramRegistry QAHistosStrangenessTracking{"QAHistosStrangenessTracking", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; |
75 | 77 | HistogramRegistry EventsvsMultiplicity{"EventsvsMultiplicity", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; |
76 | | - OutputObj<TH1D> hProcessedEvents{TH1D("hProcessedEvents", "Strangeness - event filtered;; Number of events", 16, -1., 15.)}; |
| 78 | + OutputObj<TH1D> hProcessedEvents{TH1D("hProcessedEvents", "Strangeness - event filtered;; Number of events", 17, -1., 16.)}; |
77 | 79 | OutputObj<TH1F> hCandidate{TH1F("hCandidate", "; Candidate pass selection; Number of events", 30, 0., 30.)}; |
78 | 80 | OutputObj<TH1F> hEvtvshMinPt{TH1F("hEvtvshMinPt", " Number of h-Omega events with pT_h higher than thrd; min p_{T, trigg} (GeV/c); Number of events", 11, 0., 11.)}; |
79 | 81 |
|
| 82 | + // Dedicated selection criteria for lambda-lambda |
| 83 | + struct : ConfigurableGroup { |
| 84 | + Configurable<float> cfgv0radiusMin{"cfgv0radiusMin", 1.2, "minimum decay radius"}; |
| 85 | + Configurable<float> cfgDCAPosToPVMin{"cfgDCAPosToPVMin", 0.05, "minimum DCA to PV for positive track"}; |
| 86 | + Configurable<float> cfgDCANegToPVMin{"cfgDCANegToPVMin", 0.2, "minimum DCA to PV for negative track"}; |
| 87 | + Configurable<float> cfgv0CosPA{"cfgv0CosPA", 0.995, "minimum v0 cosine"}; |
| 88 | + Configurable<float> cfgDCAV0Dau{"cfgDCAV0Dau", 1.0, "maximum DCA between daughters"}; |
| 89 | + Configurable<float> cfgV0PtMin{"cfgV0PtMin", 0, "minimum pT for lambda"}; |
| 90 | + Configurable<float> cfgV0RapMin{"cfgV0RapMin", -0.5, "maximum rapidity"}; |
| 91 | + Configurable<float> cfgV0RapMax{"cfgV0RapMax", 0.5, "maximum rapidity"}; |
| 92 | + Configurable<float> cfgV0LifeTime{"cfgV0LifeTime", 30., "maximum lambda lifetime"}; |
| 93 | + Configurable<int16_t> cfgDaughTPCnclsMin{"cfgDaughTPCnclsMin", 70, "minimum fired crossed rows"}; |
| 94 | + Configurable<uint8_t> cfgITSNclus{"cfgITSNclus", 1, "minimum its cluster"}; |
| 95 | + Configurable<float> cfgRCrossedFindable{"cfgRCrossedFindable", 0.0, "minimum ratio of crossed rows over findable clusters"}; |
| 96 | + Configurable<float> cfgDaughPIDCutsTPCPr{"cfgDaughPIDCutsTPCPr", 5, "proton nsigma for TPC"}; |
| 97 | + Configurable<float> cfgDaughPIDCutsTPCPi{"cfgDaughPIDCutsTPCPi", 5, "pion nsigma for TPC"}; |
| 98 | + Configurable<float> cfgDaughEtaMin{"cfgDaughEtaMin", -0.8, "minimum daughter eta"}; |
| 99 | + Configurable<float> cfgDaughEtaMax{"cfgDaughEtaMax", 0.8, "maximum daughter eta"}; |
| 100 | + Configurable<float> cfgDaughPrPt{"cfgDaughPrPt", 0.5, "minimum daughter proton pt"}; |
| 101 | + Configurable<float> cfgDaughPiPt{"cfgDaughPiPt", 0.5, "minimum daughter pion pt"}; |
| 102 | + Configurable<float> cfgLambdaMassWindow{"cfgLambdaMassWindow", 0.01, "window for lambda mass selection"}; |
| 103 | + Configurable<float> cfgCompV0Rej{"cfgCompV0Rej", 0.01, "competing V0 rejection"}; |
| 104 | + Configurable<float> cfgMinCPAV0V0{"cfgMinCPAV0V0", 0.8, "minimum CPA of v0v0"}; |
| 105 | + Configurable<float> cfgMaxRadiusV0V0{"cfgMaxRadiusV0V0", 10.0, "maximum radius of v0v0"}; |
| 106 | + Configurable<float> cfgMaxDistanceV0V0{"cfgMaxDistanceV0V0", 5.0, "maximum distance of v0v0"}; |
| 107 | + Configurable<float> cfgMaxDCAV0V0{"cfgMaxDCAV0V0", 5.0, "maximum DCA of v0v0"}; |
| 108 | + } cfgLLCuts; |
| 109 | + |
80 | 110 | // Selection criteria for cascades |
81 | 111 | Configurable<bool> useCascadeMomentumAtPrimVtx{"useCascadeMomentumAtPrimVtx", false, "use cascade momentum at PV"}; |
82 | 112 | Configurable<bool> doextraQA{"doextraQA", 1, "do extra QA"}; |
@@ -178,6 +208,81 @@ struct strangenessFilter { |
178 | 208 | return track.pt() > hMinPt && std::abs(track.eta()) < hEta && track.tpcNClsCrossedRows() >= tpcmincrossedrows && track.tpcCrossedRowsOverFindableCls() >= 0.8f && track.tpcChi2NCl() <= 4.f && track.itsChi2NCl() <= 36.f && (track.itsClusterMap() & 0x7) != 0; |
179 | 209 | } |
180 | 210 |
|
| 211 | + float getV0V0DCA(TVector3 v01pos, TVector3 v01mom, TVector3 v02pos, TVector3 v02mom) |
| 212 | + { |
| 213 | + TVector3 posdiff = v02pos - v01pos; |
| 214 | + TVector3 cross = v01mom.Cross(v02mom); |
| 215 | + TVector3 dcaVec = (posdiff.Dot(cross) / cross.Mag2()) * cross; |
| 216 | + return dcaVec.Mag(); |
| 217 | + } |
| 218 | + float getV0V0CPA(TVector3 v01mom, TVector3 v02mom) |
| 219 | + { |
| 220 | + return v01mom.Dot(v02mom) / (v01mom.Mag() * v02mom.Mag()); |
| 221 | + } |
| 222 | + float getV0V0Distance(TVector3 v01pos, TVector3 v02pos) |
| 223 | + { |
| 224 | + TVector3 posdiff = v02pos - v01pos; |
| 225 | + return posdiff.Mag(); |
| 226 | + } |
| 227 | + float getV0V0Radius(TVector3 v01pos, TVector3 v01mom, TVector3 v02pos, TVector3 v02mom) |
| 228 | + { |
| 229 | + TVector3 posdiff = v02pos - v01pos; |
| 230 | + v01mom *= 1. / v01mom.Mag(); |
| 231 | + v02mom *= 1. / v02mom.Mag(); |
| 232 | + float dd = 1. - TMath::Power(v01mom.Dot(v02mom), 2); |
| 233 | + if (dd < 1e-5) |
| 234 | + return 999; |
| 235 | + float tt = posdiff.Dot(v01mom - v01mom.Dot(v02mom) * v02mom) / dd; |
| 236 | + float ss = -posdiff.Dot(v02mom - v01mom.Dot(v02mom) * v01mom) / dd; |
| 237 | + TVector3 radVec = v01pos + v02pos + tt * v01mom + ss * v02mom; |
| 238 | + radVec *= 0.5; |
| 239 | + return radVec.Mag(); |
| 240 | + } |
| 241 | + bool isSelectedV0V0(TVector3 v01pos, TVector3 v01mom, TVector3 v02pos, TVector3 v02mom) |
| 242 | + { |
| 243 | + if (getV0V0DCA(v01pos, v01mom, v02pos, v02mom) > cfgLLCuts.cfgMaxDCAV0V0) |
| 244 | + return false; |
| 245 | + if (getV0V0CPA(v01mom, v02mom) < cfgLLCuts.cfgMinCPAV0V0) |
| 246 | + return false; |
| 247 | + if (getV0V0Distance(v01pos, v02pos) > cfgLLCuts.cfgMaxDistanceV0V0) |
| 248 | + return false; |
| 249 | + if (getV0V0Radius(v01pos, v01mom, v02pos, v02mom) > cfgLLCuts.cfgMaxRadiusV0V0) |
| 250 | + return false; |
| 251 | + |
| 252 | + return true; |
| 253 | + } |
| 254 | + |
| 255 | + template <typename T> |
| 256 | + bool isSelectedV0Daughter(T const& track) |
| 257 | + { |
| 258 | + if (track.tpcNClsCrossedRows() < cfgLLCuts.cfgDaughTPCnclsMin) |
| 259 | + return false; |
| 260 | + if (track.tpcCrossedRowsOverFindableCls() < cfgLLCuts.cfgRCrossedFindable) |
| 261 | + return false; |
| 262 | + if (track.itsNCls() < cfgLLCuts.cfgITSNclus) |
| 263 | + return false; |
| 264 | + if (track.eta() > cfgLLCuts.cfgDaughEtaMax) |
| 265 | + return false; |
| 266 | + if (track.eta() < cfgLLCuts.cfgDaughEtaMin) |
| 267 | + return false; |
| 268 | + |
| 269 | + return true; |
| 270 | + } |
| 271 | + template <typename T> |
| 272 | + bool isSelectedV0DaughterPID(T const& track, int pid) // pid 0: proton, pid 1: pion |
| 273 | + { |
| 274 | + if (pid == 0 && std::abs(track.tpcNSigmaPr()) > cfgLLCuts.cfgDaughPIDCutsTPCPr) |
| 275 | + return false; |
| 276 | + if (pid == 1 && std::abs(track.tpcNSigmaPi()) > cfgLLCuts.cfgDaughPIDCutsTPCPi) |
| 277 | + return false; |
| 278 | + if (pid == 0 && track.pt() < cfgLLCuts.cfgDaughPrPt) |
| 279 | + return false; |
| 280 | + if (pid == 1 && track.pt() < cfgLLCuts.cfgDaughPiPt) |
| 281 | + return false; |
| 282 | + |
| 283 | + return true; |
| 284 | + } |
| 285 | + |
181 | 286 | void init(o2::framework::InitContext&) |
182 | 287 | { |
183 | 288 | // set V0 parameters in the helper |
@@ -223,6 +328,7 @@ struct strangenessFilter { |
223 | 328 | hProcessedEvents->GetXaxis()->SetBinLabel(14, aod::filtering::OmegaHighMult::columnLabel()); |
224 | 329 | hProcessedEvents->GetXaxis()->SetBinLabel(15, aod::filtering::DoubleOmega::columnLabel()); |
225 | 330 | hProcessedEvents->GetXaxis()->SetBinLabel(16, aod::filtering::OmegaXi::columnLabel()); |
| 331 | + hProcessedEvents->GetXaxis()->SetBinLabel(17, "LL"); |
226 | 332 |
|
227 | 333 | hCandidate->GetXaxis()->SetBinLabel(1, "All"); |
228 | 334 | hCandidate->GetXaxis()->SetBinLabel(2, "PassBuilderSel"); |
@@ -449,14 +555,14 @@ struct strangenessFilter { |
449 | 555 |
|
450 | 556 | void fillTriggerTable(bool keepEvent[]) |
451 | 557 | { |
452 | | - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9], keepEvent[10], keepEvent[11]); |
| 558 | + strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9], keepEvent[10], keepEvent[11], keepEvent[12]); |
453 | 559 | } |
454 | 560 |
|
455 | | - void process(CollisionCandidates const& collision, TrackCandidates const& tracks, aod::Cascades const& cascadesBase, aod::AssignedTrackedCascades const& trackedCascades, aod::AssignedTrackedV0s const& /*trackedV0s*/, aod::AssignedTracked3Bodys const& /*tracked3Bodys*/, aod::V0s const&, aod::BCs const&, aod::FT0s const& /*ft0s*/) |
| 561 | + void process(CollisionCandidates const& collision, TrackCandidates const& tracks, aod::Cascades const& cascadesBase, aod::AssignedTrackedCascades const& trackedCascades, aod::AssignedTrackedV0s const& /*trackedV0s*/, aod::AssignedTracked3Bodys const& /*tracked3Bodys*/, aod::V0s const& v0Base, aod::BCs const&, aod::FT0s const& /*ft0s*/) |
456 | 562 | { |
457 | 563 | // Is event good? [0] = Omega, [1] = high-pT hadron + Omega, [2] = 2Xi, [3] = 3Xi, [4] = 4Xi, [5] single-Xi, [6] Omega with high radius |
458 | 564 | // [7] tracked Xi, [8] tracked Omega, [9] Omega + high mult event |
459 | | - bool keepEvent[12]{}; // explicitly zero-initialised |
| 565 | + bool keepEvent[13]{}; // explicitly zero-initialised |
460 | 566 | std::vector<std::array<int64_t, 2>> v0sFromOmegaID; |
461 | 567 | std::vector<std::array<int64_t, 2>> v0sFromXiID; |
462 | 568 |
|
@@ -573,6 +679,102 @@ struct strangenessFilter { |
573 | 679 | const auto primaryVertex = getPrimaryVertex(collision); |
574 | 680 | o2::dataformats::DCA impactParameterTrk; |
575 | 681 |
|
| 682 | + std::vector<std::tuple<int64_t, int64_t, TVector3, TVector3>> v0sSelTuple; |
| 683 | + for (auto& v00 : v0Base) { // loop over v0 for pre selection |
| 684 | + hCandidate->Fill(0.5); // All candidates |
| 685 | + |
| 686 | + if (v00.v0Type() != 1) { |
| 687 | + continue; |
| 688 | + } |
| 689 | + |
| 690 | + const auto posTrack0 = v00.posTrack_as<TrackCandidates>(); |
| 691 | + const auto negTrack0 = v00.negTrack_as<TrackCandidates>(); |
| 692 | + |
| 693 | + if (!isSelectedV0Daughter(posTrack0) || !isSelectedV0Daughter(negTrack0)) { |
| 694 | + continue; |
| 695 | + } |
| 696 | + |
| 697 | + auto trackParPos0 = getTrackParCov(posTrack0); |
| 698 | + auto trackParNeg0 = getTrackParCov(negTrack0); |
| 699 | + |
| 700 | + if (!mStraHelper.buildV0Candidate(v00.collisionId(), pvPos[0], pvPos[1], pvPos[2], posTrack0, negTrack0, trackParPos0, trackParNeg0)) { |
| 701 | + continue; |
| 702 | + } |
| 703 | + |
| 704 | + if (std::hypot(mStraHelper.v0.position[0], mStraHelper.v0.position[1]) < cfgLLCuts.cfgv0radiusMin) { |
| 705 | + continue; |
| 706 | + } |
| 707 | + if (std::fabs(mStraHelper.v0.positiveDCAxy) < cfgLLCuts.cfgDCAPosToPVMin) { |
| 708 | + continue; |
| 709 | + } |
| 710 | + if (std::fabs(mStraHelper.v0.negativeDCAxy) < cfgLLCuts.cfgDCANegToPVMin) { |
| 711 | + continue; |
| 712 | + } |
| 713 | + if (TMath::Cos(mStraHelper.v0.pointingAngle) < cfgLLCuts.cfgv0CosPA) { |
| 714 | + continue; |
| 715 | + } |
| 716 | + if (std::fabs(mStraHelper.v0.daughterDCA) > cfgLLCuts.cfgDCAV0Dau) { |
| 717 | + continue; |
| 718 | + } |
| 719 | + if (std::hypot(mStraHelper.v0.momentum[0], mStraHelper.v0.momentum[1]) < cfgLLCuts.cfgV0PtMin) { |
| 720 | + continue; |
| 721 | + } |
| 722 | + double yLambda = RecoDecay::y(array{mStraHelper.v0.momentum[0], mStraHelper.v0.momentum[1], mStraHelper.v0.momentum[2]}, o2::constants::physics::MassLambda0); |
| 723 | + if (yLambda < cfgLLCuts.cfgV0RapMin) { |
| 724 | + continue; |
| 725 | + } |
| 726 | + if (yLambda > cfgLLCuts.cfgV0RapMax) { |
| 727 | + continue; |
| 728 | + } |
| 729 | + double distovertotmom = std::hypot(mStraHelper.v0.position[0] - collision.posX(), mStraHelper.v0.position[1] - collision.posY(), mStraHelper.v0.position[2] - collision.posZ()) / (std::hypot(mStraHelper.v0.momentum[0], mStraHelper.v0.momentum[1], mStraHelper.v0.momentum[2]) + 1e-13); |
| 730 | + if (distovertotmom * o2::constants::physics::MassLambda0 > cfgLLCuts.cfgV0LifeTime) { |
| 731 | + continue; |
| 732 | + } |
| 733 | + |
| 734 | + int Tag = 0; |
| 735 | + if (isSelectedV0DaughterPID(posTrack0, 0) && isSelectedV0DaughterPID(negTrack0, 1)) { |
| 736 | + if (cfgLLCuts.cfgLambdaMassWindow > std::fabs(mStraHelper.v0.massLambda - o2::constants::physics::MassLambda0)) { |
| 737 | + if (cfgLLCuts.cfgCompV0Rej < std::fabs(mStraHelper.v0.massK0Short - o2::constants::physics::MassLambda0)) { |
| 738 | + Tag++; |
| 739 | + } |
| 740 | + } |
| 741 | + } // lambda |
| 742 | + if (isSelectedV0DaughterPID(posTrack0, 1) && isSelectedV0DaughterPID(negTrack0, 0)) { |
| 743 | + if (cfgLLCuts.cfgLambdaMassWindow > std::fabs(mStraHelper.v0.massAntiLambda - o2::constants::physics::MassLambda0)) { |
| 744 | + if (cfgLLCuts.cfgCompV0Rej < std::fabs(mStraHelper.v0.massK0Short - o2::constants::physics::MassLambda0)) { |
| 745 | + Tag++; |
| 746 | + } |
| 747 | + } |
| 748 | + } // anti lambda |
| 749 | + if (Tag != 1) { // Select when only one hypothesis is satisfied |
| 750 | + continue; |
| 751 | + } |
| 752 | + |
| 753 | + TVector3 v0pos(mStraHelper.v0.position[0], mStraHelper.v0.position[1], mStraHelper.v0.position[2]); |
| 754 | + TVector3 v0mom(mStraHelper.v0.momentum[0], mStraHelper.v0.momentum[1], mStraHelper.v0.momentum[2]); |
| 755 | + |
| 756 | + v0sSelTuple.emplace_back(posTrack0.globalIndex(), negTrack0.globalIndex(), v0pos, v0mom); |
| 757 | + } |
| 758 | + |
| 759 | + for (size_t i = 0; i < v0sSelTuple.size(); ++i) { |
| 760 | + for (size_t j = i + 1; j < v0sSelTuple.size(); ++j) { |
| 761 | + auto d00 = std::get<0>(v0sSelTuple[i]); |
| 762 | + auto d01 = std::get<1>(v0sSelTuple[i]); |
| 763 | + auto d10 = std::get<0>(v0sSelTuple[j]); |
| 764 | + auto d11 = std::get<1>(v0sSelTuple[j]); |
| 765 | + if (d00 == d10 || d00 == d11 || d01 == d10 || d01 == d11) { |
| 766 | + continue; |
| 767 | + } |
| 768 | + auto v00pos = std::get<2>(v0sSelTuple[i]); |
| 769 | + auto v00mom = std::get<3>(v0sSelTuple[i]); |
| 770 | + auto v01pos = std::get<2>(v0sSelTuple[j]); |
| 771 | + auto v01mom = std::get<3>(v0sSelTuple[j]); |
| 772 | + if (isSelectedV0V0(v00pos, v00mom, v01pos, v01mom)) { |
| 773 | + keepEvent[12] = true; |
| 774 | + } |
| 775 | + } |
| 776 | + } |
| 777 | + |
576 | 778 | for (auto& casc : cascadesBase) { // loop over cascades |
577 | 779 | hCandidate->Fill(0.5); // All candidates |
578 | 780 |
|
@@ -1149,7 +1351,9 @@ struct strangenessFilter { |
1149 | 1351 | if (keepEvent[11]) { |
1150 | 1352 | hProcessedEvents->Fill(14.5); |
1151 | 1353 | } |
1152 | | - |
| 1354 | + if (keepEvent[12]) { |
| 1355 | + hProcessedEvents->Fill(15.5); |
| 1356 | + } |
1153 | 1357 | // Filling the table |
1154 | 1358 | fillTriggerTable(keepEvent); |
1155 | 1359 | } |
|
0 commit comments