44 mRecoCont = &recoData;
45 mNV0s = mNCascades = mN3Bodies = 0;
46 updateTimeDependentParams();
49 int ntrP = mTracksPool[
POS].size(), ntrN = mTracksPool[
NEG].size();
55 int dynGrp = std::min(4, std::max(1, mNThreads / 2));
56#pragma omp parallel for schedule(dynamic, dynGrp) num_threads(mNThreads)
58 for (
int itp = 0; itp < ntrP; itp++) {
59 auto& seedP = mTracksPool[
POS][itp];
60 const int firstN = mVtxFirstTrack[
NEG][seedP.vBracket.getMin()];
62 LOG(
debug) <<
"No partner is found for pos.track " << itp <<
" out of " << ntrP;
65 for (
int itn = firstN; itn < ntrN; itn++) {
66 auto& seedN = mTracksPool[
NEG][itn];
67 if (seedN.vBracket > seedP.vBracket) {
68 LOG(
debug) <<
"Brackets do not match";
75 int iThread = omp_get_thread_num();
79 checkV0(seedP, seedN, itp, itn, iThread);
95 for (
int ith = 0; ith < mNThreads; ith++) {
96 mNV0s += mV0sIdxTmp[ith].size();
97 mNCascades += mCascadesIdxTmp[ith].size();
98 mN3Bodies += m3bodyIdxTmp[ith].size();
100 std::vector<vid> v0SortID, cascSortID, nbodySortID;
101 v0SortID.reserve(mNV0s);
102 cascSortID.reserve(mNCascades);
103 nbodySortID.reserve(mN3Bodies);
104 for (
int ith = 0; ith < mNThreads; ith++) {
105 for (
int j = 0;
j < (
int)mV0sIdxTmp[ith].
size();
j++) {
106 v0SortID.emplace_back(vid{ith,
j, mV0sIdxTmp[ith][
j].getVertexID()});
108 for (
int j = 0;
j < (
int)mCascadesIdxTmp[ith].
size();
j++) {
109 cascSortID.emplace_back(vid{ith,
j, mCascadesIdxTmp[ith][
j].getVertexID()});
111 for (
int j = 0;
j < (
int)m3bodyIdxTmp[ith].
size();
j++) {
112 nbodySortID.emplace_back(vid{ith,
j, m3bodyIdxTmp[ith][
j].getVertexID()});
115 std::sort(v0SortID.begin(), v0SortID.end(), [](
const vid&
a,
const vid&
b) { return a.vtxID < b.vtxID; });
116 std::sort(cascSortID.begin(), cascSortID.end(), [](
const vid&
a,
const vid&
b) { return a.vtxID < b.vtxID; });
117 std::sort(nbodySortID.begin(), nbodySortID.end(), [](
const vid&
a,
const vid&
b) { return a.vtxID < b.vtxID; });
122 auto& body3Idx = pc.
outputs().
make<std::vector<Decay3BodyIndex>>(
o2f::Output{
"GLO",
"DECAYS3BODY_IDX", 0});
131 v0sIdx.reserve(mNV0s);
133 fullv0s.reserve(mNV0s);
136 cascsIdx.reserve(mNCascades);
138 fullcascs.reserve(mNCascades);
141 body3Idx.reserve(mN3Bodies);
143 full3body.reserve(mN3Bodies);
146 for (
const auto&
id : v0SortID) {
147 auto& v0idx = mV0sIdxTmp[
id.thrID][
id.entry];
148 int pos = v0sIdx.size();
149 v0sIdx.push_back(v0idx);
150 v0idx.setVertexID(
pos);
152 fullv0s.push_back(mV0sTmp[
id.thrID][
id.
entry]);
156 for (
int ith = 0; ith < mNThreads; ith++) {
157 for (
size_t ic = 0; ic < mCascadesIdxTmp[ith].size(); ic++) {
158 auto& cidx = mCascadesIdxTmp[ith][ic];
159 cidx.setV0ID(mV0sIdxTmp[ith][cidx.getV0ID()].getVertexID());
163 for (
const auto&
id : cascSortID) {
164 cascsIdx.push_back(mCascadesIdxTmp[
id.thrID][
id.
entry]);
165 mCascadesIdxTmp[
id.thrID][
id.entry].setVertexID(cascCnt++);
167 fullcascs.push_back(mCascadesTmp[
id.thrID][
id.
entry]);
171 for (
const auto&
id : nbodySortID) {
172 body3Idx.push_back(m3bodyIdxTmp[
id.thrID][
id.
entry]);
173 m3bodyIdxTmp[
id.thrID][
id.entry].setVertexID(b3cnt++);
175 full3body.push_back(m3bodyTmp[
id.thrID][
id.
entry]);
180 for (
int ith = 0; ith < mNThreads; ith++) {
181 mNStrangeTracks += mStrTracker->
getNTracks(ith);
184 std::vector<o2::dataformats::StrangeTrack> strTracksTmp;
185 std::vector<o2::strangeness_tracking::ClusAttachments> strClusTmp;
186 std::vector<o2::MCCompLabel> mcLabTmp;
187 strTracksTmp.reserve(mNStrangeTracks);
188 strClusTmp.reserve(mNStrangeTracks);
190 mcLabTmp.reserve(mNStrangeTracks);
193 for (
int ith = 0; ith < mNThreads; ith++) {
197 for (
int i = 0;
i < (
int)strTracks.size();
i++) {
198 auto& t = strTracks[
i];
200 t.mDecayRef = mV0sIdxTmp[ith][t.mDecayRef].getVertexID();
202 t.mDecayRef = mCascadesIdxTmp[ith][t.mDecayRef].getVertexID();
204 t.mDecayRef = m3bodyIdxTmp[ith][t.mDecayRef].getVertexID();
206 LOGP(fatal,
"Unknown strange track decay reference type {} for index {}",
int(t.mPartType), t.mDecayRef);
209 strTracksTmp.push_back(t);
210 strClusTmp.push_back(strClust[
i]);
212 mcLabTmp.push_back(stcTrMCLab[
i]);
217 auto& strTracksOut = pc.
outputs().
make<std::vector<o2::dataformats::StrangeTrack>>(
o2f::Output{
"GLO",
"STRANGETRACKS", 0});
218 auto& strClustOut = pc.
outputs().
make<std::vector<o2::strangeness_tracking::ClusAttachments>>(
o2f::Output{
"GLO",
"CLUSUPDATES", 0});
220 strTracksOut.resize(mNStrangeTracks);
221 strClustOut.resize(mNStrangeTracks);
223 mcLabsOut.resize(mNStrangeTracks);
226 std::vector<int> sortIdx(strTracksTmp.size());
227 std::iota(sortIdx.begin(), sortIdx.end(), 0);
229 if (mNThreads > 1 && mNStrangeTracks > 1) {
230 std::sort(sortIdx.begin(), sortIdx.end(), [&strTracksTmp](
int i1,
int i2) { return strTracksTmp[i1].mDecayRef < strTracksTmp[i2].mDecayRef; });
233 for (
int i = 0;
i < (
int)sortIdx.size();
i++) {
234 strTracksOut[
i] = strTracksTmp[sortIdx[
i]];
235 strClustOut[
i] = strClusTmp[sortIdx[
i]];
237 mcLabsOut[
i] = mcLabTmp[sortIdx[
i]];
242 auto& strTrMCLableOut = pc.
outputs().
make<std::vector<o2::MCCompLabel>>(
o2f::Output{
"GLO",
"STRANGETRACKS_MC", 0});
243 strTrMCLableOut.swap(mcLabsOut);
247 for (
int ith = 0; ith < mNThreads; ith++) {
248 mV0sTmp[ith].clear();
249 mCascadesTmp[ith].clear();
250 m3bodyTmp[ith].clear();
251 mV0sIdxTmp[ith].clear();
252 mCascadesIdxTmp[ith].clear();
253 m3bodyIdxTmp[ith].clear();
256 extractPVReferences(v0sIdx, v0Refs, cascsIdx, cascRefs, body3Idx, vtx3bodyRefs);
265void SVertexer::updateTimeDependentParams()
268 static bool updatedOnce =
false;
273 LOGP(fatal,
"TPC tracks requested but not provided");
311 for (
auto& ft : mFitterV0) {
314 for (
auto& ft : mFitterCasc) {
317 for (
auto& ft : mFitter3body) {
321 mPIDresponse.setBetheBlochParams(mSVParams->
mBBpars);
327 mTPCVDrift =
v.refVDrift *
v.corrFact;
328 mTPCVDriftCorrFact =
v.corrFact;
329 mTPCVDriftRef =
v.refVDrift;
330 mTPCDriftTimeOffset =
v.getTimeOffset();
331 mTPCBin2Z = mTPCVDrift / mMUS2TPCBin;
336 mTPCCorrMapsHelper = maph;
340void SVertexer::setupThreads()
342 if (!mV0sTmp.empty()) {
345 mV0sTmp.resize(mNThreads);
346 mCascadesTmp.resize(mNThreads);
347 m3bodyTmp.resize(mNThreads);
348 mV0sIdxTmp.resize(mNThreads);
349 mCascadesIdxTmp.resize(mNThreads);
350 m3bodyIdxTmp.resize(mNThreads);
351 mFitterV0.resize(mNThreads);
354 for (
auto& fitter : mFitterV0) {
355 fitter.setFitterID(fitCounter++);
357 fitter.setUseAbsDCA(mSVParams->
useAbsDCA);
358 fitter.setPropagateToPCA(
false);
359 fitter.setMaxR(mSVParams->
maxRIni);
362 fitter.setMaxDZIni(mSVParams->
maxDZIni);
363 fitter.setMaxDXYIni(mSVParams->
maxDXYIni);
364 fitter.setMaxChi2(mSVParams->
maxChi2);
368 fitter.setMaxStep(mSVParams->
maxStep);
369 fitter.setMaxSnp(mSVParams->
maxSnp);
370 fitter.setMinXSeed(mSVParams->
minXSeed);
372 mFitterCasc.resize(mNThreads);
374 for (
auto& fitter : mFitterCasc) {
375 fitter.setFitterID(fitCounter++);
377 fitter.setUseAbsDCA(mSVParams->
useAbsDCA);
378 fitter.setPropagateToPCA(
false);
382 fitter.setMaxDZIni(mSVParams->
maxDZIni);
383 fitter.setMaxDXYIni(mSVParams->
maxDXYIni);
384 fitter.setMaxChi2(mSVParams->
maxChi2);
388 fitter.setMaxStep(mSVParams->
maxStep);
389 fitter.setMaxSnp(mSVParams->
maxSnp);
390 fitter.setMinXSeed(mSVParams->
minXSeed);
393 mFitter3body.resize(mNThreads);
395 for (
auto& fitter : mFitter3body) {
396 fitter.setFitterID(fitCounter++);
398 fitter.setUseAbsDCA(mSVParams->
useAbsDCA);
399 fitter.setPropagateToPCA(
false);
403 fitter.setMaxDZIni(mSVParams->
maxDZIni);
404 fitter.setMaxDXYIni(mSVParams->
maxDXYIni);
405 fitter.setMaxChi2(mSVParams->
maxChi2);
409 fitter.setMaxStep(mSVParams->
maxStep);
410 fitter.setMaxSnp(mSVParams->
maxSnp);
411 fitter.setMinXSeed(mSVParams->
minXSeed);
425 std::array<float, 2> dca;
435 if (!trp.propagateParamToDCA(mMeanVertex.getXYZ(), prop->getNominalBz(), &dca)) {
439 if (std::abs(dca[0]) < mSVParams->
minDCAToPV) {
461 mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, mTPCCorrMapsHelper,
o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(),
nullptr,
o2::base::Propagator::Instance());
462 mTPCRefitter->setTrackReferenceX(900);
465 std::unordered_map<GIndex, std::pair<int, int>> tmap;
466 std::unordered_map<GIndex, bool> rejmap;
467 int nv = vtxRefs.size() - 1;
468 for (
int i = 0;
i < 2;
i++) {
469 mTracksPool[
i].clear();
470 mVtxFirstTrack[
i].clear();
471 mVtxFirstTrack[
i].resize(nv, -1);
473 for (
int iv = 0; iv < nv; iv++) {
474 const auto& vtref = vtxRefs[iv];
475 int it = vtref.getFirstEntry(), itLim = it + vtref.getEntries();
476 for (; it < itLim; it++) {
477 auto tvid = trackIndex[it];
487 if (processTPCTrack(mTPCTracksArray[tvid], tvid, iv)) {
492 if (tvid.isAmbiguous()) {
493 auto tref = tmap.find(tvid);
494 if (tref != tmap.end()) {
495 mTracksPool[tref->second.second][tref->second.first].vBracket.setMax(iv);
499 if (rejmap.find(tvid) != rejmap.end()) {
506 bool heavyIonisingParticle =
false;
509 if (tpcGID.isIndexSet() && isTPCloaded) {
512 float dEdxTPC = tpcTrack.getdEdx().dEdxTotTPC;
515 heavyIonisingParticle =
true;
518 float dEdxExpected = mPIDresponse.getExpectedSignal(tpcTrack, protonId);
519 float fracDevProton = std::abs((dEdxTPC - dEdxExpected) / dEdxExpected);
520 if (fracDevProton < mSVParams->mFractiondEdxforCascBaryons) {
521 compatibleWithProton =
true;
527 bool shortOBITSOnlyTrack =
false;
532 nITSclu = itsTrack.getNumberOfClusters();
533 if (itsTrack.hasHitOnLayer(6) && itsTrack.hasHitOnLayer(5) && itsTrack.hasHitOnLayer(4) && itsTrack.hasHitOnLayer(3)) {
534 shortOBITSOnlyTrack =
true;
538 if (isITSTPCloaded) {
539 auto& itsABTracklet = recoData.
getITSABRef(itsGID);
540 nITSclu = itsABTracklet.getNClusters();
543 if (!acceptTrack(tvid, trc) && !heavyIonisingParticle) {
544 if (tvid.isAmbiguous()) {
549 if ((isTPCloaded && !hasTPC) && (isITSloaded && (nITSclu < mSVParams->mITSSAminNclu && (!shortOBITSOnlyTrack || mSVParams->
mRejectITSonlyOBtrack)))) {
553 int posneg = trc.getSign() < 0 ? 1 : 0;
554 float r = std::sqrt(trc.getX() * trc.getX() + trc.getY() * trc.getY());
555 mTracksPool[posneg].emplace_back(TrackCand{trc, tvid, {iv, iv},
r, hasTPC, nITSclu, compatibleWithProton});
557 correctTPCTrack(mTracksPool[posneg].back(), mTPCTracksArray[tvid], -1, -1);
559 if (tvid.isAmbiguous()) {
560 tmap[tvid] = {mTracksPool[posneg].size() - 1, posneg};
565 for (
int pn = 0; pn < 2; pn++) {
566 auto& vtxFirstT = mVtxFirstTrack[pn];
567 const auto& tracksPool = mTracksPool[pn];
568 for (
unsigned i = 0;
i < tracksPool.size();
i++) {
569 const auto& t = tracksPool[
i];
570 for (
int j{t.vBracket.getMin()};
j <= t.vBracket.getMax(); ++
j) {
571 if (vtxFirstT[
j] == -1) {
578 LOG(info) <<
"Collected " << mTracksPool[
POS].size() <<
" positive and " << mTracksPool[
NEG].size() <<
" negative seeds";
582bool SVertexer::checkV0(
const TrackCand& seedP,
const TrackCand& seedN,
int iP,
int iN,
int ithread)
584 auto& fitterV0 = mFitterV0[ithread];
589 if (std::abs(seedP.getTgl() - seedN.getTgl()) > mSVParams->
maxV0TglAbsDiff) {
596 seedP.getCircleParams(mBz, trkPosCircle, sna, csa);
598 seedN.getCircleParams(mBz, trkEleCircle, sna, csa);
600 float c2c = std::hypot(trkPosCircle.
xC - trkEleCircle.
xC,
601 trkPosCircle.
yC - trkEleCircle.
yC);
602 float r2r = trkPosCircle.
rC + trkEleCircle.
rC;
603 float dcr = c2c - r2r;
605 LOG(
debug) <<
"RejD2R " << c2c <<
" " << r2r <<
" " << dcr;
609 float r1_r = trkPosCircle.
rC / r2r;
610 float r2_r = trkEleCircle.
rC / r2r;
611 float dR = std::hypot(r2_r * trkPosCircle.
xC + r1_r * trkEleCircle.
xC, r2_r * trkPosCircle.
yC + r1_r * trkEleCircle.
yC);
621 fitterV0.setCollinear(
true);
625 int nCand = fitterV0.process(seedP, seedN);
628 fitterV0.setMaxDZIni(mSVParams->
maxDZIni);
629 fitterV0.setMaxDXYIni(mSVParams->
maxDXYIni);
630 fitterV0.setMaxChi2(mSVParams->
maxChi2);
631 fitterV0.setCollinear(
false);
638 const auto& v0XYZ = fitterV0.getPCACandidate();
641 float dxv0 = v0XYZ[0] - mMeanVertex.getX(), dyv0 = v0XYZ[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0;
642 if (r2v0 < mMinR2ToMeanVertex) {
643 LOG(
debug) <<
"RejMinR2ToMeanVertex";
646 float rv0 = std::sqrt(r2v0), drv0P = rv0 - seedP.minR, drv0N = rv0 - seedN.minR;
649 LOG(
debug) <<
"RejCausality " << drv0P <<
" " << drv0N;
653 if (!fitterV0.isPropagateTracksToVertexDone(cand) && !fitterV0.propagateTracksToVertex(cand)) {
657 const auto& trPProp = fitterV0.getTrack(0, cand);
658 const auto& trNProp = fitterV0.getTrack(1, cand);
659 std::array<float, 3> pP{}, pN{};
660 trPProp.getPxPyPzGlo(pP);
661 trNProp.getPxPyPzGlo(pN);
666 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
667 float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0;
668 if (pt2V0 < mMinPt2V0) {
672 if (pV0[2] * pV0[2] / pt2V0 > mMaxTgl2V0) {
673 LOG(
debug) <<
"RejTgL " << pV0[2] * pV0[2] / pt2V0;
676 float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0);
678 float p2Pos = pP[0] * pP[0] + pP[1] * pP[1] + pP[2] * pP[2], p2Neg = pN[0] * pN[0] + pN[1] * pN[1] + pN[2] * pN[2];
681 std::array<bool, NHypV0> hypCheckStatus{};
684 if (mV0Hyps[ipid].
check(p2Pos, p2Neg, p2V0, ptV0)) {
685 goodHyp = hypCheckStatus[ipid] =
true;
689 bool goodLamForCascade =
false, goodALamForCascade =
false;
690 bool usesTPCOnly = (seedP.hasTPC && !seedP.hasITS()) || (seedN.hasTPC && !seedN.hasITS());
694 goodLamForCascade =
true;
697 goodALamForCascade =
true;
702 bool good3bodyV0Hyp =
false;
703 for (
int ipid = 2; ipid < 4; ipid++) {
704 float massForLambdaHyp = mV0Hyps[ipid].calcMass(p2Pos, p2Neg, p2V0);
705 if (massForLambdaHyp - mV0Hyps[ipid].getMassV0Hyp() < mV0Hyps[ipid].getMargin(ptV0)) {
706 good3bodyV0Hyp =
true;
712 bool checkFor3BodyDecays = mEnable3BodyDecays &&
716 bool rejectAfter3BodyCheck =
false;
717 bool checkForCascade = mEnableCascades &&
719 r2v0 < mMaxR2ToMeanVertexCascV0 &&
722 bool rejectIfNotCascade =
false;
726 if (!checkFor3BodyDecays && !checkForCascade) {
729 rejectAfter3BodyCheck =
true;
733 float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY;
734 float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0);
736 if (checkForCascade) {
737 if (dca2 > mMaxDCAXY2ToMeanVertexV0Casc || cosPAXY < mSVParams->minCosPAXYMeanVertexCascV0) {
738 LOG(
debug) <<
"Rej for cascade DCAXY2: " << dca2 <<
" << cosPAXY: " << cosPAXY;
739 if (!checkFor3BodyDecays) {
742 rejectAfter3BodyCheck =
true;
746 if (checkFor3BodyDecays) {
747 if (dca2 > mMaxDCAXY2ToMeanVertex3bodyV0 || cosPAXY < mSVParams->minCosPAXYMeanVertex3bodyV0) {
748 LOG(
debug) <<
"Rej for 3 body decays DCAXY2: " << dca2 <<
" << cosPAXY: " << cosPAXY;
749 checkFor3BodyDecays =
false;
753 if (dca2 > mMaxDCAXY2ToMeanVertex || cosPAXY < mSVParams->minCosPAXYMeanVertex) {
754 if (checkForCascade) {
755 rejectIfNotCascade =
true;
756 }
else if (checkFor3BodyDecays) {
757 rejectAfter3BodyCheck =
true;
770 auto vlist = seedP.vBracket.getOverlap(seedN.vBracket);
771 bool candFound =
false;
773 bestCosPA = checkFor3BodyDecays ? std::min(mSVParams->
minCosPA3bodyV0, bestCosPA) : bestCosPA;
777 for (
int iv = vlist.getMin(); iv <= vlist.getMax(); iv++) {
778 const auto& pv = mPVertices[iv];
779 const auto v0XYZ = fitterV0.getPCACandidatePos(cand);
781 float dx = v0XYZ[0] - pv.getX(), dy = v0XYZ[1] - pv.getY(), dz = v0XYZ[2] - pv.getZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2];
782 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
783 if (cosPA < bestCosPA) {
784 LOG(
debug) <<
"Rej. cosPA: " << cosPA;
788 new (&v0new)
V0(v0XYZ, pV0, fitterV0.calcPCACovMatrixFlat(cand), trPProp, trNProp);
789 new (&v0Idxnew)
V0Index(-1, seedP.gid, seedN.gid);
790 v0new.setDCA(fitterV0.getChi2AtPCACandidate(cand));
793 v0new.setCosPA(cosPA);
800 if (bestCosPA < mSVParams->minCosPACascV0) {
801 rejectAfter3BodyCheck =
true;
803 if (bestCosPA < mSVParams->minCosPA && checkForCascade) {
804 rejectIfNotCascade =
true;
806 int nV0Ini = mV0sIdxTmp[ithread].size();
808 if (checkFor3BodyDecays) {
809 int n3bodyDecays = 0;
810 n3bodyDecays += check3bodyDecays(v0Idxnew, v0new, rv0, pV0, p2V0, iN,
NEG, vlist, ithread);
811 n3bodyDecays += check3bodyDecays(v0Idxnew, v0new, rv0, pV0, p2V0, iP,
POS, vlist, ithread);
813 if (rejectAfter3BodyCheck) {
818 int nCascIni = mCascadesIdxTmp[ithread].size(), nV0Used = 0;
819 if (checkForCascade) {
821 nV0Used += checkCascades(v0Idxnew, v0new, rv0, pV0, p2V0, iN,
NEG, vlist, ithread);
824 nV0Used += checkCascades(v0Idxnew, v0new, rv0, pV0, p2V0, iP,
POS, vlist, ithread);
829 for (
unsigned int ic = nCascIni; ic < mCascadesIdxTmp[ithread].size(); ic++) {
830 if (mCascadesIdxTmp[ithread][ic].getV0ID() == -1) {
831 mCascadesIdxTmp[ithread][ic].setV0ID(nV0Ini);
836 if (nV0Used || !rejectIfNotCascade) {
837 mV0sIdxTmp[ithread].push_back(v0Idxnew);
838 if (!rejectIfNotCascade) {
839 mV0sIdxTmp[ithread].back().setStandaloneV0();
842 mV0sIdxTmp[ithread].back().setPhotonOnly();
843 mV0sIdxTmp[ithread].back().setCollinear();
847 mV0sTmp[ithread].push_back(v0new);
852 for (
int iv = nV0Ini; iv < (
int)mV0sIdxTmp[ithread].
size(); iv++) {
853 mStrTracker->
processV0(iv, v0new, v0Idxnew, ithread);
857 return mV0sIdxTmp[ithread].size() - nV0Ini != 0;
861int SVertexer::checkCascades(
const V0Index& v0Idx,
const V0&
v0,
float rv0, std::array<float, 3> pV0,
float p2V0,
int avoidTrackID,
int posneg, VBracket v0vlist,
int ithread)
864 auto& fitterCasc = mFitterCasc[ithread];
865 auto&
tracks = mTracksPool[posneg];
866 int nCascIni = mCascadesIdxTmp[ithread].size(), nv0use = 0;
869 std::unordered_map<int, int> pvMap;
872 int firstTr = mVtxFirstTrack[posneg][v0vlist.getMin()], nTr =
tracks.size();
876 for (
int it = firstTr; it < nTr; it++) {
877 if (it == avoidTrackID) {
888 if (bach.vBracket.getMin() > v0vlist.getMax()) {
892 auto cascVlist = v0vlist.getOverlap(bach.vBracket);
902 int nCandC = fitterCasc.process(
v0, bach);
907 const auto& cascXYZ = fitterCasc.getPCACandidatePos(candC);
910 float dxc = cascXYZ[0] - mMeanVertex.getX(), dyc = cascXYZ[1] - mMeanVertex.getY(), r2casc = dxc * dxc + dyc * dyc;
911 if (rv0 * rv0 - r2casc < mMinR2DiffV0Casc || r2casc < mMinR2ToMeanVertex) {
916 if (!fitterCasc.isPropagateTracksToVertexDone(candC) && !fitterCasc.propagateTracksToVertex(candC)) {
920 auto& trNeut = fitterCasc.getTrack(0, candC);
921 auto& trBach = fitterCasc.getTrack(1, candC);
924 std::array<float, 3> pNeut, pBach;
925 trNeut.getPxPyPzGlo(pNeut);
926 trBach.getPxPyPzGlo(pBach);
927 std::array<float, 3> pCasc = {pNeut[0] + pBach[0], pNeut[1] + pBach[1], pNeut[2] + pBach[2]};
929 float pt2Casc = pCasc[0] * pCasc[0] + pCasc[1] * pCasc[1], p2Casc = pt2Casc + pCasc[2] * pCasc[2];
930 if (pt2Casc < mMinPt2Casc) {
934 if (pCasc[2] * pCasc[2] / pt2Casc > mMaxTgl2Casc) {
935 LOG(
debug) <<
"Casc tgLambda too high";
943 for (
int iv = cascVlist.getMin(); iv <= cascVlist.getMax(); iv++) {
944 const auto& pv = mPVertices[iv];
946 float dx = cascXYZ[0] - pv.getX(), dy = cascXYZ[1] - pv.getY(), dz = cascXYZ[2] - pv.getZ(), prodXYZcasc = dx * pCasc[0] + dy * pCasc[1] + dz * pCasc[2];
947 float cosPA = prodXYZcasc / std::sqrt((dx * dx + dy * dy + dz * dz) * p2Casc);
948 if (cosPA < bestCosPA) {
949 LOG(
debug) <<
"Rej. cosPA: " << cosPA;
955 if (cascVtxID == -1) {
956 LOG(
debug) <<
"Casc not compatible with any vertex";
960 const auto& cascPv = mPVertices[cascVtxID];
961 float dxCasc = cascXYZ[0] - cascPv.getX(), dyCasc = cascXYZ[1] - cascPv.getY(), dzCasc = cascXYZ[2] - cascPv.getZ();
962 auto prodPPos = pV0[0] * dxCasc + pV0[1] * dyCasc + pV0[2] * dzCasc;
964 LOG(
debug) <<
"Casc not causally compatible";
968 float p2Bach = pBach[0] * pBach[0] + pBach[1] * pBach[1] + pBach[2] * pBach[2];
969 float ptCasc = std::sqrt(pt2Casc);
970 bool goodHyp =
false;
972 if (mCascHyps[ipid].
check(p2V0, p2Bach, p2Casc, ptCasc)) {
978 LOG(
debug) <<
"Casc not compatible with any hypothesis";
983 Cascade casc(cascXYZ, pCasc, fitterCasc.calcPCACovMatrixFlat(candC), trNeut, trBach);
986 if (!trc.propagateToDCA(cascPv, fitterCasc.getBz(), &dca, 5.) ||
988 LOG(
debug) <<
"Casc not compatible with PV";
989 LOG(
debug) <<
"DCA: " << dca.getY() <<
" " << dca.getZ();
994 LOGP(
debug,
"cascade successfully validated");
998 auto pvIdx = pvMap.find(cascVtxID);
999 if (pvIdx != pvMap.end()) {
1000 cascIdx.setV0ID(pvIdx->second);
1002 const auto& pv = mPVertices[cascVtxID];
1003 cascIdx.setV0ID(mV0sIdxTmp[ithread].
size());
1004 pvMap[cascVtxID] = mV0sTmp[ithread].size();
1005 mV0sIdxTmp[ithread].emplace_back(cascVtxID, v0Idx.
getProngs());
1007 mV0sTmp[ithread].push_back(
v0);
1008 float dx =
v0.getX() - pv.getX(), dy =
v0.getY() - pv.getY(), dz =
v0.getZ() - pv.getZ(), prodXYZ = dx * pV0[0] + dy * pV0[1] + dz * pV0[2];
1009 mV0sTmp[ithread].back().setCosPA(prodXYZ / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0));
1015 mCascadesIdxTmp[ithread].push_back(cascIdx);
1017 casc.setCosPA(bestCosPA);
1018 casc.setDCA(fitterCasc.getChi2AtPCACandidate(candC));
1019 mCascadesTmp[ithread].push_back(casc);
1030int SVertexer::check3bodyDecays(
const V0Index& v0Idx,
const V0&
v0,
float rv0, std::array<float, 3> pV0,
float p2V0,
int avoidTrackID,
int posneg, VBracket v0vlist,
int ithread)
1033 auto& fitter3body = mFitter3body[ithread];
1034 auto&
tracks = mTracksPool[posneg];
1035 int n3BodyIni = m3bodyIdxTmp[ithread].size();
1038 int firstTr = mVtxFirstTrack[posneg][v0vlist.getMin()], nTr =
tracks.size();
1047 for (
int it = firstTr; it < nTr; it++) {
1048 if (it == avoidTrackID) {
1055 if (bach.vBracket > v0vlist.getMax()) {
1059 auto decay3bodyVlist = v0vlist.getOverlap(bach.vBracket);
1069 if (bach.getPt() < 0.6) {
1073 int n3bodyVtx = fitter3body.process(
v0.getProng(0),
v0.getProng(1), bach);
1074 if (n3bodyVtx == 0) {
1078 const auto& vertexXYZ = fitter3body.getPCACandidatePos(cand3B);
1081 float dxc = vertexXYZ[0] - mMeanVertex.getX(), dyc = vertexXYZ[1] - mMeanVertex.getY(), dzc = vertexXYZ[2] - mMeanVertex.getZ(), r2vertex = dxc * dxc + dyc * dyc;
1082 if (std::abs(rv0 - std::sqrt(r2vertex)) > mSVParams->
maxRDiffV03body || r2vertex < mMinR2ToMeanVertex) {
1085 float drvtxBach = std::sqrt(r2vertex) - bach.minR;
1086 if (drvtxBach > mSVParams->
causalityRTolerance || drvtxBach < -mSVParams->maxV0ToProngsRDiff) {
1087 LOG(
debug) <<
"RejCausality " << drvtxBach;
1090 if (!fitter3body.isPropagateTracksToVertexDone() && !fitter3body.propagateTracksToVertex()) {
1094 auto& tr0 = fitter3body.getTrack(0, cand3B);
1095 auto& tr1 = fitter3body.getTrack(1, cand3B);
1096 auto& tr2 = fitter3body.getTrack(2, cand3B);
1097 std::array<float, 3>
p0,
p1,
p2;
1098 tr0.getPxPyPzGlo(p0);
1099 tr1.getPxPyPzGlo(
p1);
1100 tr2.getPxPyPzGlo(
p2);
1102 bool goodHyp =
false;
1104 auto decay3bodyVtxID = -1;
1107 std::array<float, 3> pbach = {0, 0, 0}, p3B = {0, 0, 0};
1108 for (
int ipid = 0; ipid <
NHyp3body; ipid++) {
1110 float bachChargeFactor = m3bodyHyps[ipid].getChargeBachProng() / tr2.getAbsCharge();
1111 pbach = {bachChargeFactor *
p2[0], bachChargeFactor *
p2[1], bachChargeFactor *
p2[2]};
1112 p3B = {
p0[0] +
p1[0] + pbach[0],
p0[1] +
p1[1] + pbach[1],
p0[2] +
p1[2] + pbach[2]};
1113 float sqP0 =
p0[0] *
p0[0] +
p0[1] *
p0[1] +
p0[2] *
p0[2], sqP1 =
p1[0] *
p1[0] +
p1[1] *
p1[1] +
p1[2] *
p1[2], sqPBach = pbach[0] * pbach[0] + pbach[1] * pbach[1] + pbach[2] * pbach[2];
1114 float pt2Candidate = p3B[0] * p3B[0] + p3B[1] * p3B[1], p2Candidate = pt2Candidate + p3B[2] * p3B[2];
1115 float ptCandidate = std::sqrt(pt2Candidate);
1116 if (m3bodyHyps[ipid].
check(sqP0, sqP1, sqPBach, p2Candidate, ptCandidate)) {
1117 if (pt2Candidate < mMinPt23Body) {
1120 if (p3B[2] * p3B[2] > pt2Candidate * mMaxTgl23Body) {
1126 for (
int iv = decay3bodyVlist.getMin(); iv <= decay3bodyVlist.getMax(); iv++) {
1127 const auto& pv = mPVertices[iv];
1129 float dx = vertexXYZ[0] - pv.getX(), dy = vertexXYZ[1] - pv.getY(), dz = vertexXYZ[2] - pv.getZ(), prodXYZ3body = dx * p3B[0] + dy * p3B[1] + dz * p3B[2];
1130 float cosPA = prodXYZ3body / std::sqrt((dx * dx + dy * dy + dz * dz) * p2Candidate);
1131 if (cosPA < bestCosPA) {
1132 LOG(
debug) <<
"Rej. cosPA: " << cosPA;
1135 decay3bodyVtxID = iv;
1138 if (decay3bodyVtxID == -1) {
1139 LOG(
debug) <<
"3-body decay not compatible with any vertex";
1144 pidHyp = m3bodyHyps[ipid].getPIDHyp();
1145 vtxCosPA = bestCosPA;
1153 const auto& decay3bodyPv = mPVertices[decay3bodyVtxID];
1154 Decay3Body candidate3B(vertexXYZ, p3B, fitter3body.calcPCACovMatrixFlat(cand3B), tr0, tr1, tr2, pidHyp);
1157 if (!trc.propagateToDCA(decay3bodyPv, fitter3body.getBz(), &dca, 5.) ||
1162 candidate3B.setCosPA(vtxCosPA);
1163 candidate3B.setDCA(fitter3body.getChi2AtPCACandidate());
1164 m3bodyTmp[ithread].push_back(candidate3B);
1166 m3bodyIdxTmp[ithread].emplace_back(decay3bodyVtxID, v0Idx.
getProngID(0), v0Idx.
getProngID(1), bach.gid);
1170 mStrTracker->
process3Body(m3bodyIdxTmp[ithread].
size() - 1, candidate3B, decay3bodyIdx, ithread);
1173 return m3bodyIdxTmp[ithread].size() - n3BodyIni;
1177template <
class TVI,
class TCI,
class T3I,
class TR>
1178void SVertexer::extractPVReferences(
const TVI& v0s, TR& vtx2V0Refs,
const TCI& cascades, TR& vtx2CascRefs,
const T3I& vtx3, TR& vtx2body3Refs)
1182 vtx2V0Refs.resize(mPVertices.size());
1183 vtx2CascRefs.clear();
1184 vtx2CascRefs.resize(mPVertices.size());
1185 vtx2body3Refs.clear();
1186 vtx2body3Refs.resize(mPVertices.size());
1187 int nv0 = v0s.size(), nCasc = cascades.size(), n3body = vtx3.size();
1190 int pvID = -1, nForPV = 0;
1191 for (
int iv = 0; iv < nv0; iv++) {
1192 if (pvID < v0s[iv].getVertexID()) {
1194 vtx2V0Refs[pvID].setEntries(nForPV);
1196 pvID = v0s[iv].getVertexID();
1197 vtx2V0Refs[pvID].setFirstEntry(iv);
1203 vtx2V0Refs[pvID].setEntries(nForPV);
1206 for (
int ip = vtx2V0Refs.size(); ip--;) {
1207 if (vtx2V0Refs[ip].getEntries()) {
1208 ent = vtx2V0Refs[ip].getFirstEntry();
1210 vtx2V0Refs[ip].setFirstEntry(ent);
1218 for (
int iv = 0; iv < nCasc; iv++) {
1219 if (pvID < cascades[iv].getVertexID()) {
1221 vtx2CascRefs[pvID].setEntries(nForPV);
1223 pvID = cascades[iv].getVertexID();
1224 vtx2CascRefs[pvID].setFirstEntry(iv);
1230 vtx2CascRefs[pvID].setEntries(nForPV);
1233 for (
int ip = vtx2CascRefs.size(); ip--;) {
1234 if (vtx2CascRefs[ip].getEntries()) {
1235 ent = vtx2CascRefs[ip].getFirstEntry();
1237 vtx2CascRefs[ip].setFirstEntry(ent);
1245 for (
int iv = 0; iv < n3body; iv++) {
1246 const auto& vertex3body = vtx3[iv];
1247 if (pvID < vertex3body.getVertexID()) {
1249 vtx2body3Refs[pvID].setEntries(nForPV);
1251 pvID = vertex3body.getVertexID();
1252 vtx2body3Refs[pvID].setFirstEntry(iv);
1258 vtx2body3Refs[pvID].setEntries(nForPV);
1261 for (
int ip = vtx2body3Refs.size(); ip--;) {
1262 if (vtx2body3Refs[ip].getEntries()) {
1263 ent = vtx2body3Refs[ip].getFirstEntry();
1265 vtx2body3Refs[ip].setFirstEntry(ent);
1275 mNThreads =
n > 0 ?
n : 1;
1288 if (trTPC.hasBothSidesClusters()) {
1291 const auto& vtx = mPVertices[vtxid];
1292 auto twe = vtx.getTimeStamp();
1293 int posneg = trTPC.getSign() < 0 ? 1 : 0;
1295 bool compatibleWithProton =
false;
1299 float dEdxTPC = trTPC.getdEdx().dEdxTotTPC;
1300 float dEdxExpected = mPIDresponse.getExpectedSignal(trTPC, protonId);
1301 float fracDevProton = std::abs((dEdxTPC - dEdxExpected) / dEdxExpected);
1302 if (fracDevProton < mSVParams->mFractiondEdxforCascBaryons) {
1303 compatibleWithProton =
true;
1307 auto& trLoc = mTracksPool[posneg].emplace_back(TrackCand{trTPC, gid, {vtxid, vtxid}, 0.,
true, -1, compatibleWithProton});
1308 auto err = correctTPCTrack(trLoc, trTPC, twe.getTimeStamp(), twe.getTimeStampError());
1310 mTracksPool[posneg].pop_back();
1318 bool dDPV = std::abs(trLoc.getX() * trLoc.getTgl() - trLoc.getZ() + vtx.getZ()) > mSVParams->
mTPCTrack2Beam;
1320 float sna{0}, csa{0};
1322 trLoc.getCircleParams(mBz, trkCircle, sna, csa);
1323 float cR = std::hypot(trkCircle.
xC, trkCircle.
yC);
1324 float drd2 = std::sqrt(cR * cR - trkCircle.
rC * trkCircle.
rC);
1327 if (dCls || dDPV || dRD2) {
1328 mTracksPool[posneg].pop_back();
1347 tTB = tTPC.getTime0();
1348 tTBErr = 0.5 * (tTPC.getDeltaTBwd() + tTPC.getDeltaTFwd());
1350 tTB = tmus * mMUS2TPCBin;
1351 tTBErr = tmusErr * mMUS2TPCBin;
1353 float dDrift = (tTB - tTPC.getTime0()) * mTPCBin2Z;
1354 float driftErr = tTBErr * mTPCBin2Z;
1355 if (driftErr < 0.) {
1359 trc.setZ(tTPC.getZ() + (tTPC.hasASideClustersOnly() ? dDrift : -dDrift));
1362 auto cl = &tTPC.getCluster(mTPCTrackClusIdx, tTPC.getNClusters() - 1, *mTPCClusterIdxStruct, sector,
row);
1363 float x = 0,
y = 0,
z = 0;
1364 mTPCCorrMapsHelper->Transform(sector,
row, cl->getPad(), cl->getTime(),
x,
y,
z, tTB);
1368 trc.
minR = std::sqrt(
x *
x +
y *
y);
1369 LOGP(
debug,
"set MinR = {} for row {}, x:{}, y:{}, z:{}", trc.
minR,
row,
x,
y,
z);
1376 std::array<size_t, 3> calls{};
1377 for (
int i = 0;
i < mNThreads;
i++) {
1378 calls[0] += mFitterV0[
i].getCallID();
1379 calls[1] += mFitterCasc[
i].getCallID();
1380 calls[2] += mFitter3body[
i].getCallID();
Helper class to access correction maps.
Some ALICE geometry constants of common interest.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
constexpr int p1()
constexpr to accelerate the coordinates changing
Reference on ITS/MFT clusters set.
calibration data from laser track calibration
Helper class to obtain TPC clusters / digits / labels from DPL.
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const SVertexerParams & Instance()
TO BE DONE: extend to generic N body vertex.
GIndex getProngID(int i) const
const std::array< GIndex, N > & getProngs() const
decltype(auto) make(const Output &spec, Args... args)
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
void processV0(int iv0, const V0 &v0, const V0Index &v0Idx, int iThread=0)
std::vector< StrangeTrack > & getStrangeTrackVec(int iThread=0)
void processCascade(int icasc, const Cascade &casc, const CascadeIndex &cascIdx, const V0 &cascV0, int iThread=0)
std::vector< ClusAttachments > & getClusAttachments(int iThread=0)
void process3Body(int i3body, const Decay3Body &dec3body, const Decay3BodyIndex &dec3bodyIdx, int iThread=0)
size_t getNTracks(int ithread=0) const
bool loadData(const o2::globaltracking::RecoContainer &recoData)
std::vector< o2::MCCompLabel > & getStrangeTrackLabels(int iThread=0)
bool getMCTruthOn() const
static constexpr ID HyperHelium4
static constexpr ID Electron
static constexpr ID HyperTriton
static constexpr ID Lambda
static constexpr ID Helium3
static constexpr ID HyperHelium5
static constexpr ID Deuteron
static constexpr ID OmegaMinus
static constexpr ID Photon
static constexpr ID Proton
static constexpr ID Triton
static constexpr ID XiMinus
static constexpr ID Hyperhydrog4
static constexpr ID Alpha
void setTPCCorrMaps(o2::gpu::CorrectionMapsHelper *maph)
std::array< size_t, 3 > getNFitterCalls() const
void process(const o2::globaltracking::RecoContainer &recoTracks, o2::framework::ProcessingContext &pc)
void setTPCVDrift(const o2::tpc::VDriftCorrFact &v)
o2::dataformats::V0Index V0Index
void produceOutput(o2::framework::ProcessingContext &pc)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t
constexpr float XTPCInnerRef
reference radius at which TPC provides the tracks
Defining PrimaryVertex explicitly as messageable.
void check(const std::vector< std::string > &arguments, const std::vector< ConfigParamSpec > &workflowOptions, const std::vector< DeviceSpec > &deviceSpecs, CheckMatrix &matrix)
std::vector< T, fair::mq::pmr::polymorphic_allocator< T > > vector
struct o2::upgrades_utils::@454 tracks
structure to keep trigger-related info
GTrackID getITSContributorGID(GTrackID source) const
bool isTrackSourceLoaded(int src) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
auto getTPCTracksClusterRefs() const
auto getPrimaryVertexMatchedTrackRefs() const
const o2::itsmft::TrkClusRef & getITSABRef(GTrackID gid) const
GTrackID getTPCContributorGID(GTrackID source) const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
gsl::span< const unsigned char > clusterShMapTPC
externally set TPC clusters sharing map
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
std::unique_ptr< o2::tpc::internal::getWorkflowTPCInput_ret > inputsTPCclusters
auto getTPCTracks() const
gsl::span< const unsigned int > occupancyMapTPC
externally set TPC clusters occupancy map
int maxPVContributors
max number PV contributors to allow in V0
float pidCutsHhydrog4[SVertexHypothesis::NPIDParams]
float minCosPA
min cos of PA to PV for prompt V0 candidates
bool mRejectITSonlyOBtrack
float pidCutsHe5L3body[SVertex3Hypothesis::NPIDParams]
float maxDCAXYToMeanVertex
max DCA of V0 from beam line (mean vertex) for prompt V0 candidates
float pidCutsPhoton[SVertexHypothesis::NPIDParams]
bool useAbsDCA
use abs dca minimization
bool usePropagator
use external propagator
float maxDCAXYToMeanVertex3bodyV0
max DCA of V0 from beam line (mean vertex) for 3body V0 candidates
float maxRIni
don't consider as a seed (circles intersection) if its R exceeds this
uint8_t mITSSAminNcluCascades
bool checkCascadeHypothesis
bool createFullCascades
fill cascades prongs/kinematics
float maxDCAXYToMeanVertexV0Casc
max DCA of V0 from beam line (mean vertex) for cascade V0 candidates
float minParamChange
stop when tracks X-params being minimized change by less that this value
float causalityRTolerance
V0 radius cannot exceed its contributors minR by more than this value.
float maxSnp
max snp when external propagator is used
float minXSeed
minimal X of seed in prong frame (within the radial resolution track should not go to negative X)
float maximalCascadeWidth
int matCorr
material correction to use
int mTPCTrackMinNClusters
float maxV0TglAbsDiff
max absolute difference in Tgl for V0 for photons only
float maxDZIni
don't consider as a seed (circles intersection) if Z distance exceeds this
float maxStep
max step size when external propagator is used
float pidCutsK0[SVertexHypothesis::NPIDParams]
float pidCutsHe4L3body[SVertex3Hypothesis::NPIDParams]
float minPtV0
v0 minimum pT
float minPtV0FromCascade
v0 minimum pT for v0 to be used in cascading (lowest pT Run 2 lambda: 0.4)
float mTPCTrackMaxDCAXY2ToMeanVertex
max DCA^2 of V0 from beam line (mean vertex) for prompt V0 candidates, for photon TPC-only track only
bool mRequireTPCforCascBaryons
float pidCutsLambda[SVertexHypothesis::NPIDParams]
bool createFull3Bodies
fill 3-body decays prongs/kinematics
float minRelChi2Change
stop when chi2 changes by less than this value
float maxChi2
max dca from prongs to vertex
bool selectBestV0
match only the best v0 for each cascade candidate
float mFractiondEdxforCascBaryons
float minRFor3DField
above this radius use 3D field
bool refitWithMatCorr
refit V0 applying material corrections
float pidCutsH3L3body[SVertex3Hypothesis::NPIDParams]
float minRDiffV0Casc
cascade should be at least this radial distance below V0
float pidCutsOmegaMinus[SVertexHypothesis::NPIDParams]
float minRToMeanVertex
min radial distance of V0 from beam line (mean vertex)
float pidCutsXiMinus[SVertexHypothesis::NPIDParams]
float maxRDiffV03body
Maximum difference between V0 and 3body radii.
float mTPCTrackMaxDXYIni
don't consider as a seed (circles intersection) if XY distance exceeds this, for photon TPC-only trac...
float minDCAToPV
min DCA to PV of single track to accept
float mTPCTrackMaxDZIni
don't consider as a seed (circles intersection) if Z distance exceeds this, for photon TPC-only track...
float pidCutsHTriton[SVertexHypothesis::NPIDParams]
float maxDXYIni
don't consider as a seed (circles intersection) if XY distance exceeds this
float maxRToMeanVertexCascV0
float mTPCTrackMaxChi2
max DCA from prongs to vertex for photon TPC-only track only
float pidCutsH4L3body[SVertex3Hypothesis::NPIDParams]
bool createFullV0s
fill V0s prongs/kinematics
float maxTglV0
maximum tgLambda of V0
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"