@@ -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 );
0 commit comments