Skip to content

Commit ba707ed

Browse files
authored
[ALICE3] Add xi kink reco (#14991)
1 parent 89b15c7 commit ba707ed

File tree

2 files changed

+147
-32
lines changed

2 files changed

+147
-32
lines changed

ALICE3/TableProducer/OTF/onTheFlyTracker.cxx

Lines changed: 109 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ struct OnTheFlyTracker {
146146
struct : ConfigurableGroup {
147147
std::string prefix = "fastTrackerSettings"; // JSON group name
148148
Configurable<int> minSiliconHits{"minSiliconHits", 6, "minimum number of silicon hits to accept track"};
149+
Configurable<int> minSiliconHitsForKinkReco{"minSiliconHitsForKinkReco", 4, "minimum number of silicon hits to accept track"};
149150
Configurable<int> minSiliconHitsIfTPCUsed{"minSiliconHitsIfTPCUsed", 2, "minimum number of silicon hits to accept track in case TPC info is present"};
150151
Configurable<int> minTPCClusters{"minTPCClusters", 70, "minimum number of TPC hits necessary to consider minSiliconHitsIfTPCUsed"};
151152
Configurable<bool> applyZacceptance{"applyZacceptance", false, "apply z limits to detector layers or not"};
@@ -168,6 +169,7 @@ struct OnTheFlyTracker {
168169
Configurable<bool> findXi{"findXi", false, "if decayXi on, find Xi and fill Tracks table also with Xi"};
169170
Configurable<bool> trackXi{"trackXi", false, "if findXi on, attempt to track Xi"};
170171
Configurable<bool> doXiQA{"doXiQA", false, "QA plots for when treating Xi"};
172+
Configurable<int> doKinkReco{"doKinkReco", 0, "Flag for kink reco setting: 0 - disabled, 1 - complementary, 2 - only"};
171173
} cascadeDecaySettings;
172174

173175
struct : ConfigurableGroup {
@@ -866,7 +868,10 @@ struct OnTheFlyTracker {
866868
std::vector<int> nHits(kCascProngs); // total
867869
std::vector<int> nSiliconHits(kCascProngs); // silicon type
868870
std::vector<int> nTPCHits(kCascProngs); // TPC type
871+
872+
bool tryKinkReco = false;
869873
if (cascadeDecaySettings.decayXi && mcParticle.pdgCode() == kXiMinus) {
874+
bool reconstructedCascade = false;
870875
if (cascadeDecaySettings.doXiQA) {
871876
getHist(TH1, histPath + "hXiBuilding")->Fill(0.0f);
872877
}
@@ -914,23 +919,18 @@ struct OnTheFlyTracker {
914919
}
915920
}
916921

917-
if (cascadeDecaySettings.doXiQA && mcParticle.pdgCode() == kXiMinus) {
918-
if (isReco[0] && isReco[1] && isReco[2]) {
919-
getHist(TH1, histPath + "hXiBuilding")->Fill(2.0f);
920-
getHist(TH2, histPath + "hRecoXi")->Fill(xiDecayRadius2D, mcParticle.pt());
921-
}
922-
if (isReco[0])
923-
getHist(TH2, histPath + "hRecoPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt());
924-
if (isReco[1])
925-
getHist(TH2, histPath + "hRecoPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt());
926-
if (isReco[2])
927-
getHist(TH2, histPath + "hRecoPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt());
922+
if (!isReco[1] || !isReco[2]) {
923+
tryKinkReco = true; // Lambda outside acceptance, set flag for kink reco to be used if mode 1
924+
}
925+
926+
if (isReco[0] && isReco[1] && isReco[2]) {
927+
reconstructedCascade = true;
928928
}
929929

930930
// +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+
931931
// combine particles into actual Xi candidate
932932
// cascade building starts here
933-
if (cascadeDecaySettings.findXi && mcParticle.pdgCode() == kXiMinus && isReco[0] && isReco[1] && isReco[2]) {
933+
if (cascadeDecaySettings.findXi && isReco[0] && isReco[1] && isReco[2] && cascadeDecaySettings.doKinkReco != 2) {
934934
if (cascadeDecaySettings.doXiQA) {
935935
getHist(TH1, histPath + "hXiBuilding")->Fill(3.0f);
936936
}
@@ -1111,24 +1111,111 @@ struct OnTheFlyTracker {
11111111
thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this is the next index to be filled -> should be it
11121112
tracksAlice3.push_back(TrackAlice3{cascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters});
11131113

1114-
if (cascadeDecaySettings.doXiQA) {
1115-
getHist(TH1, histPath + "hXiBuilding")->Fill(6.0f);
1116-
getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(trackParCov.getPt(), cascadeTrack.getPt() - trackParCov.getPt());
1117-
getHist(TH2, histPath + "h2dDeltaEtaVsPt")->Fill(trackParCov.getPt(), cascadeTrack.getEta() - trackParCov.getEta());
1118-
1119-
getHist(TH1, histPath + "hMassLambda")->Fill(thisCascade.mLambda);
1120-
getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi);
1121-
getHist(TH2, histPath + "hFoundVsFindable")->Fill(thisCascade.findableClusters, thisCascade.foundClusters);
1122-
}
1123-
11241114
// add this cascade to vector (will fill cursor later with collision ID)
11251115
cascadesAlice3.push_back(thisCascade);
11261116
}
11271117
}
11281118
} // end cascade building
1119+
1120+
if (isReco[0] && ((cascadeDecaySettings.doKinkReco == 1 && tryKinkReco) || cascadeDecaySettings.doKinkReco == 2)) { // mode 1 or 2
1121+
o2::track::TrackParCov prefectCascadeTrack, trackedCasc;
1122+
const o2::track::TrackParCov& trackedBach = xiDaughterTrackParCovsTracked[0];
1123+
o2::upgrade::convertMCParticleToO2Track(mcParticle, prefectCascadeTrack, pdgDB);
1124+
1125+
// back track is already smeared
1126+
int nCascHits = fastTracker[icfg]->FastTrack(prefectCascadeTrack, trackedCasc, dNdEta);
1127+
reconstructedCascade = (fastTrackerSettings.minSiliconHitsForKinkReco < nCascHits) ? false : true;
1128+
1129+
if (reconstructedCascade) {
1130+
std::array<float, 3> pCasc;
1131+
std::array<float, 3> pBach;
1132+
std::array<float, 3> pV0;
1133+
trackedCasc.getPxPyPzGlo(pCasc);
1134+
trackedBach.getPxPyPzGlo(pBach);
1135+
for (size_t i = 0; i < pCasc.size(); ++i) {
1136+
pV0[i] = pCasc[i] - pBach[i];
1137+
}
1138+
1139+
if (isReco[1] && !isReco[2]) {
1140+
thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 1;
1141+
thisCascade.positiveId = -1;
1142+
} else if (!isReco[1] && isReco[2]) {
1143+
thisCascade.negativeId = -1;
1144+
thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1;
1145+
} else if (isReco[1] && isReco[2]) {
1146+
thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1;
1147+
thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 2;
1148+
} else {
1149+
thisCascade.positiveId = -1;
1150+
thisCascade.negativeId = -1;
1151+
}
1152+
1153+
int nCand = 0;
1154+
bool kinkFitterOK = true;
1155+
try {
1156+
nCand = fitter.process(trackedCasc, trackedBach);
1157+
} catch (...) {
1158+
kinkFitterOK = false;
1159+
}
1160+
1161+
if (nCand == 0) {
1162+
kinkFitterOK = false;
1163+
}
1164+
1165+
if (kinkFitterOK) {
1166+
if (cascadeDecaySettings.doXiQA) {
1167+
getHist(TH1, histPath + "hXiBuilding")->Fill(6.0f);
1168+
}
1169+
}
1170+
1171+
std::array<float, 3> kinkVtx = {-999, -999, -999};
1172+
kinkVtx = fitter.getPCACandidatePos();
1173+
1174+
thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - isReco.size();
1175+
thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this should be ok
1176+
thisCascade.dcaV0dau = -1.f; // unknown
1177+
thisCascade.v0radius = -1.f; // unknown
1178+
thisCascade.dcacascdau = std::sqrt(fitter.getChi2AtPCACandidate());
1179+
thisCascade.cascradius = std::hypot(kinkVtx[0], kinkVtx[1]);
1180+
thisCascade.cascradiusMC = xiDecayRadius2D;
1181+
thisCascade.mLambda = o2::constants::physics::MassLambda;
1182+
thisCascade.findableClusters = nCascHits;
1183+
thisCascade.foundClusters = nCascHits;
1184+
thisCascade.mXi = RecoDecay::m(std::array{std::array{pBach[0], pBach[1], pBach[2]},
1185+
std::array{pV0[0], pV0[1], pV0[2]}},
1186+
std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda});
1187+
1188+
tracksAlice3.push_back(TrackAlice3{trackedCasc, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters});
1189+
1190+
// add this cascade to vector (will fill cursor later with collision ID)
1191+
cascadesAlice3.push_back(thisCascade);
1192+
}
1193+
} // end cascade kink building
1194+
11291195
// +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+
1196+
if (cascadeDecaySettings.doXiQA) {
1197+
if (reconstructedCascade) {
1198+
getHist(TH2, histPath + "hRecoXi")->Fill(xiDecayRadius2D, mcParticle.pt());
1199+
getHist(TH1, histPath + "hMassLambda")->Fill(thisCascade.mLambda);
1200+
getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi);
1201+
// getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(trackParCov.getPt(), cascadeTrack.getPt() - trackParCov.getPt());
1202+
// getHist(TH2, histPath + "h2dDeltaEtaVsPt")->Fill(trackParCov.getPt(), cascadeTrack.getEta() - trackParCov.getEta());
1203+
getHist(TH2, histPath + "hFoundVsFindable")->Fill(thisCascade.findableClusters, thisCascade.foundClusters);
1204+
}
1205+
if (isReco[0]) {
1206+
getHist(TH2, histPath + "hRecoPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt());
1207+
}
1208+
if (isReco[1]) {
1209+
getHist(TH2, histPath + "hRecoPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt());
1210+
}
1211+
if (isReco[2]) {
1212+
getHist(TH2, histPath + "hRecoPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt());
1213+
}
1214+
}
1215+
11301216
continue; // Cascade handling done, should not be considered anymore
11311217
}
1218+
11321219
// V0 handling
11331220
std::vector<o2::track::TrackParCov> v0DaughterTrackParCovsPerfect(2);
11341221
std::vector<o2::track::TrackParCov> v0DaughterTrackParCovsTracked(2);

ALICE3/TableProducer/alice3MulticharmFinder.cxx

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ struct Alice3MulticharmFinder {
200200
int nTPCHitsPiCC;
201201
} thisXiCCcandidate;
202202

203+
struct ProngInfo {
204+
float pt = 1e+10;
205+
float eta = 1e+10;
206+
float dcaXY = 1e+10;
207+
float dcaZ = 1e+10;
208+
};
209+
203210
template <typename TTrackType>
204211
bool buildDecayCandidateTwoBody(TTrackType const& t0, TTrackType const& t1, float mass0, float mass1)
205212
{
@@ -557,10 +564,6 @@ struct Alice3MulticharmFinder {
557564
}
558565

559566
uint32_t nCombinationsC = 0;
560-
auto bach = xiCand.bachTrack_as<Alice3Tracks>(); // de-reference bach track
561-
auto neg = xiCand.negTrack_as<Alice3Tracks>(); // de-reference neg track
562-
auto pos = xiCand.posTrack_as<Alice3Tracks>(); // de-reference pos track
563-
564567
if (!BIT_CHECK(xi.decayMap(), kTrueXiFromXiC)) {
565568
continue;
566569
}
@@ -822,13 +825,38 @@ struct Alice3MulticharmFinder {
822825
picc.hasSigPi(), picc.nSigmaPionRich(),
823826
getPdgCodeForTrack(picc));
824827

828+
ProngInfo bachelor, positive, negative;
829+
if (xiCand.has_bachTrack()) {
830+
auto bach = xiCand.bachTrack_as<Alice3Tracks>(); // de-reference bach track
831+
bachelor.pt = bach.pt();
832+
bachelor.eta = bach.eta();
833+
bachelor.dcaXY = bach.dcaXY();
834+
bachelor.dcaZ = bach.dcaZ();
835+
}
836+
837+
if (xiCand.has_negTrack()) {
838+
auto neg = xiCand.negTrack_as<Alice3Tracks>(); // de-reference neg track
839+
negative.pt = neg.pt();
840+
negative.eta = neg.eta();
841+
negative.dcaXY = neg.dcaXY();
842+
negative.dcaZ = neg.dcaZ();
843+
}
844+
845+
if (xiCand.has_posTrack()) {
846+
auto pos = xiCand.posTrack_as<Alice3Tracks>(); // de-reference pos track
847+
positive.pt = pos.pt();
848+
positive.eta = pos.eta();
849+
positive.dcaXY = pos.dcaXY();
850+
positive.dcaZ = pos.dcaZ();
851+
}
852+
825853
multiCharmExtra(
826-
bach.pt(), bach.eta(),
827-
bach.dcaXY(), bach.dcaZ(),
828-
pos.pt(), pos.eta(),
829-
pos.dcaXY(), pos.dcaZ(),
830-
neg.pt(), neg.eta(),
831-
neg.dcaXY(), neg.dcaZ(),
854+
bachelor.pt, bachelor.eta,
855+
bachelor.dcaXY, bachelor.dcaZ,
856+
positive.pt, positive.eta,
857+
positive.dcaXY, positive.dcaZ,
858+
negative.pt, negative.eta,
859+
negative.dcaXY, negative.dcaZ,
832860
pi1c.eta(), pi2c.eta(), picc.eta());
833861
}
834862
}

0 commit comments

Comments
 (0)