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;
308 for (
auto& ft : mFitterV0) {
311 for (
auto& ft : mFitterCasc) {
314 for (
auto& ft : mFitter3body) {
318 mPIDresponse.setBetheBlochParams(mSVParams->
mBBpars);
324 mTPCVDrift =
v.refVDrift *
v.corrFact;
325 mTPCVDriftCorrFact =
v.corrFact;
326 mTPCVDriftRef =
v.refVDrift;
327 mTPCDriftTimeOffset =
v.getTimeOffset();
328 mTPCBin2Z = mTPCVDrift / mMUS2TPCBin;
333 mTPCCorrMapsHelper = maph;
337void SVertexer::setupThreads()
339 if (!mV0sTmp.empty()) {
342 mV0sTmp.resize(mNThreads);
343 mCascadesTmp.resize(mNThreads);
344 m3bodyTmp.resize(mNThreads);
345 mV0sIdxTmp.resize(mNThreads);
346 mCascadesIdxTmp.resize(mNThreads);
347 m3bodyIdxTmp.resize(mNThreads);
348 mFitterV0.resize(mNThreads);
351 for (
auto& fitter : mFitterV0) {
352 fitter.setFitterID(fitCounter++);
354 fitter.setUseAbsDCA(mSVParams->
useAbsDCA);
355 fitter.setPropagateToPCA(
false);
356 fitter.setMaxR(mSVParams->
maxRIni);
359 fitter.setMaxDZIni(mSVParams->
maxDZIni);
360 fitter.setMaxDXYIni(mSVParams->
maxDXYIni);
361 fitter.setMaxChi2(mSVParams->
maxChi2);
365 fitter.setMaxStep(mSVParams->
maxStep);
366 fitter.setMaxSnp(mSVParams->
maxSnp);
367 fitter.setMinXSeed(mSVParams->
minXSeed);
369 mFitterCasc.resize(mNThreads);
371 for (
auto& fitter : mFitterCasc) {
372 fitter.setFitterID(fitCounter++);
374 fitter.setUseAbsDCA(mSVParams->
useAbsDCA);
375 fitter.setPropagateToPCA(
false);
379 fitter.setMaxDZIni(mSVParams->
maxDZIni);
380 fitter.setMaxDXYIni(mSVParams->
maxDXYIni);
381 fitter.setMaxChi2(mSVParams->
maxChi2);
385 fitter.setMaxStep(mSVParams->
maxStep);
386 fitter.setMaxSnp(mSVParams->
maxSnp);
387 fitter.setMinXSeed(mSVParams->
minXSeed);
390 mFitter3body.resize(mNThreads);
392 for (
auto& fitter : mFitter3body) {
393 fitter.setFitterID(fitCounter++);
395 fitter.setUseAbsDCA(mSVParams->
useAbsDCA);
396 fitter.setPropagateToPCA(
false);
400 fitter.setMaxDZIni(mSVParams->
maxDZIni);
401 fitter.setMaxDXYIni(mSVParams->
maxDXYIni);
402 fitter.setMaxChi2(mSVParams->
maxChi2);
406 fitter.setMaxStep(mSVParams->
maxStep);
407 fitter.setMaxSnp(mSVParams->
maxSnp);
408 fitter.setMinXSeed(mSVParams->
minXSeed);
422 std::array<float, 2> dca;
432 if (!trp.propagateParamToDCA(mMeanVertex.getXYZ(), prop->getNominalBz(), &dca)) {
436 if (std::abs(dca[0]) < mSVParams->
minDCAToPV) {
458 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());
459 mTPCRefitter->setTrackReferenceX(900);
462 std::unordered_map<GIndex, std::pair<int, int>> tmap;
463 std::unordered_map<GIndex, bool> rejmap;
464 int nv = vtxRefs.size() - 1;
465 for (
int i = 0;
i < 2;
i++) {
466 mTracksPool[
i].clear();
467 mVtxFirstTrack[
i].clear();
468 mVtxFirstTrack[
i].resize(nv, -1);
470 for (
int iv = 0; iv < nv; iv++) {
471 const auto& vtref = vtxRefs[iv];
472 int it = vtref.getFirstEntry(), itLim = it + vtref.getEntries();
473 for (; it < itLim; it++) {
474 auto tvid = trackIndex[it];
484 if (processTPCTrack(mTPCTracksArray[tvid], tvid, iv)) {
489 if (tvid.isAmbiguous()) {
490 auto tref = tmap.find(tvid);
491 if (tref != tmap.end()) {
492 mTracksPool[tref->second.second][tref->second.first].vBracket.setMax(iv);
496 if (rejmap.find(tvid) != rejmap.end()) {
503 bool heavyIonisingParticle =
false;
506 if (tpcGID.isIndexSet() && isTPCloaded) {
509 float dEdxTPC = tpcTrack.getdEdx().dEdxTotTPC;
512 heavyIonisingParticle =
true;
515 float dEdxExpected = mPIDresponse.getExpectedSignal(tpcTrack, protonId);
516 float fracDevProton = std::abs((dEdxTPC - dEdxExpected) / dEdxExpected);
517 if (fracDevProton < mSVParams->mFractiondEdxforCascBaryons) {
518 compatibleWithProton =
true;
524 bool shortOBITSOnlyTrack =
false;
529 nITSclu = itsTrack.getNumberOfClusters();
530 if (itsTrack.hasHitOnLayer(6) && itsTrack.hasHitOnLayer(5) && itsTrack.hasHitOnLayer(4) && itsTrack.hasHitOnLayer(3)) {
531 shortOBITSOnlyTrack =
true;
535 if (isITSTPCloaded) {
536 auto& itsABTracklet = recoData.
getITSABRef(itsGID);
537 nITSclu = itsABTracklet.getNClusters();
540 if (!acceptTrack(tvid, trc) && !heavyIonisingParticle) {
541 if (tvid.isAmbiguous()) {
547 if (!hasTPC && nITSclu < mSVParams->mITSSAminNclu && (!shortOBITSOnlyTrack || mSVParams->
mRejectITSonlyOBtrack)) {
551 int posneg = trc.getSign() < 0 ? 1 : 0;
552 float r = std::sqrt(trc.getX() * trc.getX() + trc.getY() * trc.getY());
553 mTracksPool[posneg].emplace_back(TrackCand{trc, tvid, {iv, iv},
r, hasTPC, nITSclu, compatibleWithProton});
555 correctTPCTrack(mTracksPool[posneg].back(), mTPCTracksArray[tvid], -1, -1);
557 if (tvid.isAmbiguous()) {
558 tmap[tvid] = {mTracksPool[posneg].size() - 1, posneg};
563 for (
int pn = 0; pn < 2; pn++) {
564 auto& vtxFirstT = mVtxFirstTrack[pn];
565 const auto& tracksPool = mTracksPool[pn];
566 for (
unsigned i = 0;
i < tracksPool.size();
i++) {
567 const auto& t = tracksPool[
i];
568 for (
int j{t.vBracket.getMin()};
j <= t.vBracket.getMax(); ++
j) {
569 if (vtxFirstT[
j] == -1) {
576 LOG(info) <<
"Collected " << mTracksPool[
POS].size() <<
" positive and " << mTracksPool[
NEG].size() <<
" negative seeds";
580bool SVertexer::checkV0(
const TrackCand& seedP,
const TrackCand& seedN,
int iP,
int iN,
int ithread)
582 auto& fitterV0 = mFitterV0[ithread];
587 if (std::abs(seedP.getTgl() - seedN.getTgl()) > mSVParams->
maxV0TglAbsDiff) {
594 seedP.getCircleParams(mBz, trkPosCircle, sna, csa);
596 seedN.getCircleParams(mBz, trkEleCircle, sna, csa);
598 float c2c = std::hypot(trkPosCircle.
xC - trkEleCircle.
xC,
599 trkPosCircle.
yC - trkEleCircle.
yC);
600 float r2r = trkPosCircle.
rC + trkEleCircle.
rC;
601 float dcr = c2c - r2r;
603 LOG(
debug) <<
"RejD2R " << c2c <<
" " << r2r <<
" " << dcr;
607 float r1_r = trkPosCircle.
rC / r2r;
608 float r2_r = trkEleCircle.
rC / r2r;
609 float dR = std::hypot(r2_r * trkPosCircle.
xC + r1_r * trkEleCircle.
xC, r2_r * trkPosCircle.
yC + r1_r * trkEleCircle.
yC);
619 fitterV0.setCollinear(
true);
623 int nCand = fitterV0.process(seedP, seedN);
626 fitterV0.setMaxDZIni(mSVParams->
maxDZIni);
627 fitterV0.setMaxDXYIni(mSVParams->
maxDXYIni);
628 fitterV0.setMaxChi2(mSVParams->
maxChi2);
629 fitterV0.setCollinear(
false);
636 const auto& v0XYZ = fitterV0.getPCACandidate();
639 float dxv0 = v0XYZ[0] - mMeanVertex.getX(), dyv0 = v0XYZ[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0;
640 if (r2v0 < mMinR2ToMeanVertex) {
641 LOG(
debug) <<
"RejMinR2ToMeanVertex";
644 float rv0 = std::sqrt(r2v0), drv0P = rv0 - seedP.minR, drv0N = rv0 - seedN.minR;
647 LOG(
debug) <<
"RejCausality " << drv0P <<
" " << drv0N;
651 if (!fitterV0.isPropagateTracksToVertexDone(cand) && !fitterV0.propagateTracksToVertex(cand)) {
655 const auto& trPProp = fitterV0.getTrack(0, cand);
656 const auto& trNProp = fitterV0.getTrack(1, cand);
657 std::array<float, 3> pP{}, pN{};
658 trPProp.getPxPyPzGlo(pP);
659 trNProp.getPxPyPzGlo(pN);
664 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
665 float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0;
666 if (pt2V0 < mMinPt2V0) {
670 if (pV0[2] * pV0[2] / pt2V0 > mMaxTgl2V0) {
671 LOG(
debug) <<
"RejTgL " << pV0[2] * pV0[2] / pt2V0;
674 float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0);
676 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];
679 std::array<bool, NHypV0> hypCheckStatus{};
682 if (mV0Hyps[ipid].
check(p2Pos, p2Neg, p2V0, ptV0)) {
683 goodHyp = hypCheckStatus[ipid] =
true;
687 bool goodLamForCascade =
false, goodALamForCascade =
false;
688 bool usesTPCOnly = (seedP.hasTPC && !seedP.hasITS()) || (seedN.hasTPC && !seedN.hasITS());
692 goodLamForCascade =
true;
695 goodALamForCascade =
true;
700 bool good3bodyV0Hyp =
false;
701 for (
int ipid = 2; ipid < 4; ipid++) {
702 float massForLambdaHyp = mV0Hyps[ipid].calcMass(p2Pos, p2Neg, p2V0);
703 if (massForLambdaHyp - mV0Hyps[ipid].getMassV0Hyp() < mV0Hyps[ipid].getMargin(ptV0)) {
704 good3bodyV0Hyp =
true;
710 bool checkFor3BodyDecays = mEnable3BodyDecays &&
714 bool rejectAfter3BodyCheck =
false;
715 bool checkForCascade = mEnableCascades &&
717 r2v0 < mMaxR2ToMeanVertexCascV0 &&
720 bool rejectIfNotCascade =
false;
724 if (!checkFor3BodyDecays && !checkForCascade) {
727 rejectAfter3BodyCheck =
true;
731 float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY;
732 float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0);
734 if (checkForCascade) {
735 if (dca2 > mMaxDCAXY2ToMeanVertexV0Casc || cosPAXY < mSVParams->minCosPAXYMeanVertexCascV0) {
736 LOG(
debug) <<
"Rej for cascade DCAXY2: " << dca2 <<
" << cosPAXY: " << cosPAXY;
737 if (!checkFor3BodyDecays) {
740 rejectAfter3BodyCheck =
true;
744 if (checkFor3BodyDecays) {
745 if (dca2 > mMaxDCAXY2ToMeanVertex3bodyV0 || cosPAXY < mSVParams->minCosPAXYMeanVertex3bodyV0) {
746 LOG(
debug) <<
"Rej for 3 body decays DCAXY2: " << dca2 <<
" << cosPAXY: " << cosPAXY;
747 checkFor3BodyDecays =
false;
751 if (dca2 > mMaxDCAXY2ToMeanVertex || cosPAXY < mSVParams->minCosPAXYMeanVertex) {
752 if (checkForCascade) {
753 rejectIfNotCascade =
true;
754 }
else if (checkFor3BodyDecays) {
755 rejectAfter3BodyCheck =
true;
768 auto vlist = seedP.vBracket.getOverlap(seedN.vBracket);
769 bool candFound =
false;
771 bestCosPA = checkFor3BodyDecays ? std::min(mSVParams->
minCosPA3bodyV0, bestCosPA) : bestCosPA;
775 for (
int iv = vlist.getMin(); iv <= vlist.getMax(); iv++) {
776 const auto& pv = mPVertices[iv];
777 const auto v0XYZ = fitterV0.getPCACandidatePos(cand);
779 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];
780 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
781 if (cosPA < bestCosPA) {
782 LOG(
debug) <<
"Rej. cosPA: " << cosPA;
786 new (&v0new)
V0(v0XYZ, pV0, fitterV0.calcPCACovMatrixFlat(cand), trPProp, trNProp);
787 new (&v0Idxnew)
V0Index(-1, seedP.gid, seedN.gid);
788 v0new.setDCA(fitterV0.getChi2AtPCACandidate(cand));
791 v0new.setCosPA(cosPA);
798 if (bestCosPA < mSVParams->minCosPACascV0) {
799 rejectAfter3BodyCheck =
true;
801 if (bestCosPA < mSVParams->minCosPA && checkForCascade) {
802 rejectIfNotCascade =
true;
804 int nV0Ini = mV0sIdxTmp[ithread].size();
806 if (checkFor3BodyDecays) {
807 int n3bodyDecays = 0;
808 n3bodyDecays += check3bodyDecays(v0Idxnew, v0new, rv0, pV0, p2V0, iN,
NEG, vlist, ithread);
809 n3bodyDecays += check3bodyDecays(v0Idxnew, v0new, rv0, pV0, p2V0, iP,
POS, vlist, ithread);
811 if (rejectAfter3BodyCheck) {
816 int nCascIni = mCascadesIdxTmp[ithread].size(), nV0Used = 0;
817 if (checkForCascade) {
819 nV0Used += checkCascades(v0Idxnew, v0new, rv0, pV0, p2V0, iN,
NEG, vlist, ithread);
822 nV0Used += checkCascades(v0Idxnew, v0new, rv0, pV0, p2V0, iP,
POS, vlist, ithread);
827 for (
unsigned int ic = nCascIni; ic < mCascadesIdxTmp[ithread].size(); ic++) {
828 if (mCascadesIdxTmp[ithread][ic].getV0ID() == -1) {
829 mCascadesIdxTmp[ithread][ic].setV0ID(nV0Ini);
834 if (nV0Used || !rejectIfNotCascade) {
835 mV0sIdxTmp[ithread].push_back(v0Idxnew);
836 if (!rejectIfNotCascade) {
837 mV0sIdxTmp[ithread].back().setStandaloneV0();
840 mV0sIdxTmp[ithread].back().setPhotonOnly();
841 mV0sIdxTmp[ithread].back().setCollinear();
845 mV0sTmp[ithread].push_back(v0new);
850 for (
int iv = nV0Ini; iv < (
int)mV0sIdxTmp[ithread].
size(); iv++) {
851 mStrTracker->
processV0(iv, v0new, v0Idxnew, ithread);
855 return mV0sIdxTmp[ithread].size() - nV0Ini != 0;
859int 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)
862 auto& fitterCasc = mFitterCasc[ithread];
863 auto&
tracks = mTracksPool[posneg];
864 int nCascIni = mCascadesIdxTmp[ithread].size(), nv0use = 0;
867 std::unordered_map<int, int> pvMap;
870 int firstTr = mVtxFirstTrack[posneg][v0vlist.getMin()], nTr =
tracks.size();
874 for (
int it = firstTr; it < nTr; it++) {
875 if (it == avoidTrackID) {
886 if (bach.vBracket.getMin() > v0vlist.getMax()) {
890 auto cascVlist = v0vlist.getOverlap(bach.vBracket);
900 int nCandC = fitterCasc.process(
v0, bach);
905 const auto& cascXYZ = fitterCasc.getPCACandidatePos(candC);
908 float dxc = cascXYZ[0] - mMeanVertex.getX(), dyc = cascXYZ[1] - mMeanVertex.getY(), r2casc = dxc * dxc + dyc * dyc;
909 if (rv0 * rv0 - r2casc < mMinR2DiffV0Casc || r2casc < mMinR2ToMeanVertex) {
914 if (!fitterCasc.isPropagateTracksToVertexDone(candC) && !fitterCasc.propagateTracksToVertex(candC)) {
918 auto& trNeut = fitterCasc.getTrack(0, candC);
919 auto& trBach = fitterCasc.getTrack(1, candC);
922 std::array<float, 3> pNeut, pBach;
923 trNeut.getPxPyPzGlo(pNeut);
924 trBach.getPxPyPzGlo(pBach);
925 std::array<float, 3> pCasc = {pNeut[0] + pBach[0], pNeut[1] + pBach[1], pNeut[2] + pBach[2]};
927 float pt2Casc = pCasc[0] * pCasc[0] + pCasc[1] * pCasc[1], p2Casc = pt2Casc + pCasc[2] * pCasc[2];
928 if (pt2Casc < mMinPt2Casc) {
932 if (pCasc[2] * pCasc[2] / pt2Casc > mMaxTgl2Casc) {
933 LOG(
debug) <<
"Casc tgLambda too high";
941 for (
int iv = cascVlist.getMin(); iv <= cascVlist.getMax(); iv++) {
942 const auto& pv = mPVertices[iv];
944 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];
945 float cosPA = prodXYZcasc / std::sqrt((dx * dx + dy * dy + dz * dz) * p2Casc);
946 if (cosPA < bestCosPA) {
947 LOG(
debug) <<
"Rej. cosPA: " << cosPA;
953 if (cascVtxID == -1) {
954 LOG(
debug) <<
"Casc not compatible with any vertex";
958 const auto& cascPv = mPVertices[cascVtxID];
959 float dxCasc = cascXYZ[0] - cascPv.getX(), dyCasc = cascXYZ[1] - cascPv.getY(), dzCasc = cascXYZ[2] - cascPv.getZ();
960 auto prodPPos = pV0[0] * dxCasc + pV0[1] * dyCasc + pV0[2] * dzCasc;
962 LOG(
debug) <<
"Casc not causally compatible";
966 float p2Bach = pBach[0] * pBach[0] + pBach[1] * pBach[1] + pBach[2] * pBach[2];
967 float ptCasc = std::sqrt(pt2Casc);
968 bool goodHyp =
false;
970 if (mCascHyps[ipid].
check(p2V0, p2Bach, p2Casc, ptCasc)) {
976 LOG(
debug) <<
"Casc not compatible with any hypothesis";
981 Cascade casc(cascXYZ, pCasc, fitterCasc.calcPCACovMatrixFlat(candC), trNeut, trBach);
984 if (!trc.propagateToDCA(cascPv, fitterCasc.getBz(), &dca, 5.) ||
986 LOG(
debug) <<
"Casc not compatible with PV";
987 LOG(
debug) <<
"DCA: " << dca.getY() <<
" " << dca.getZ();
992 LOGP(
debug,
"cascade successfully validated");
996 auto pvIdx = pvMap.find(cascVtxID);
997 if (pvIdx != pvMap.end()) {
998 cascIdx.setV0ID(pvIdx->second);
1000 const auto& pv = mPVertices[cascVtxID];
1001 cascIdx.setV0ID(mV0sIdxTmp[ithread].
size());
1002 pvMap[cascVtxID] = mV0sTmp[ithread].size();
1003 mV0sIdxTmp[ithread].emplace_back(cascVtxID, v0Idx.
getProngs());
1005 mV0sTmp[ithread].push_back(
v0);
1006 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];
1007 mV0sTmp[ithread].back().setCosPA(prodXYZ / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0));
1013 mCascadesIdxTmp[ithread].push_back(cascIdx);
1015 casc.setCosPA(bestCosPA);
1016 casc.setDCA(fitterCasc.getChi2AtPCACandidate(candC));
1017 mCascadesTmp[ithread].push_back(casc);
1028int 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)
1031 auto& fitter3body = mFitter3body[ithread];
1032 auto&
tracks = mTracksPool[posneg];
1033 int n3BodyIni = m3bodyIdxTmp[ithread].size();
1036 int firstTr = mVtxFirstTrack[posneg][v0vlist.getMin()], nTr =
tracks.size();
1045 for (
int it = firstTr; it < nTr; it++) {
1046 if (it == avoidTrackID) {
1053 if (bach.vBracket > v0vlist.getMax()) {
1057 auto decay3bodyVlist = v0vlist.getOverlap(bach.vBracket);
1067 if (bach.getPt() < 0.6) {
1071 int n3bodyVtx = fitter3body.process(
v0.getProng(0),
v0.getProng(1), bach);
1072 if (n3bodyVtx == 0) {
1076 const auto& vertexXYZ = fitter3body.getPCACandidatePos(cand3B);
1079 float dxc = vertexXYZ[0] - mMeanVertex.getX(), dyc = vertexXYZ[1] - mMeanVertex.getY(), dzc = vertexXYZ[2] - mMeanVertex.getZ(), r2vertex = dxc * dxc + dyc * dyc;
1080 if (std::abs(rv0 - std::sqrt(r2vertex)) > mSVParams->
maxRDiffV03body || r2vertex < mMinR2ToMeanVertex) {
1083 float drvtxBach = std::sqrt(r2vertex) - bach.minR;
1084 if (drvtxBach > mSVParams->
causalityRTolerance || drvtxBach < -mSVParams->maxV0ToProngsRDiff) {
1085 LOG(
debug) <<
"RejCausality " << drvtxBach;
1088 if (!fitter3body.isPropagateTracksToVertexDone() && !fitter3body.propagateTracksToVertex()) {
1092 auto& tr0 = fitter3body.getTrack(0, cand3B);
1093 auto& tr1 = fitter3body.getTrack(1, cand3B);
1094 auto& tr2 = fitter3body.getTrack(2, cand3B);
1095 std::array<float, 3>
p0,
p1,
p2;
1096 tr0.getPxPyPzGlo(p0);
1097 tr1.getPxPyPzGlo(
p1);
1098 tr2.getPxPyPzGlo(
p2);
1100 bool goodHyp =
false;
1102 auto decay3bodyVtxID = -1;
1105 std::array<float, 3> pbach = {0, 0, 0}, p3B = {0, 0, 0};
1106 for (
int ipid = 0; ipid <
NHyp3body; ipid++) {
1108 float bachChargeFactor = m3bodyHyps[ipid].getChargeBachProng() / tr2.getAbsCharge();
1109 pbach = {bachChargeFactor *
p2[0], bachChargeFactor *
p2[1], bachChargeFactor *
p2[2]};
1110 p3B = {
p0[0] +
p1[0] + pbach[0],
p0[1] +
p1[1] + pbach[1],
p0[2] +
p1[2] + pbach[2]};
1111 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];
1112 float pt2Candidate = p3B[0] * p3B[0] + p3B[1] * p3B[1], p2Candidate = pt2Candidate + p3B[2] * p3B[2];
1113 float ptCandidate = std::sqrt(pt2Candidate);
1114 if (m3bodyHyps[ipid].
check(sqP0, sqP1, sqPBach, p2Candidate, ptCandidate)) {
1115 if (pt2Candidate < mMinPt23Body) {
1118 if (p3B[2] * p3B[2] > pt2Candidate * mMaxTgl23Body) {
1124 for (
int iv = decay3bodyVlist.getMin(); iv <= decay3bodyVlist.getMax(); iv++) {
1125 const auto& pv = mPVertices[iv];
1127 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];
1128 float cosPA = prodXYZ3body / std::sqrt((dx * dx + dy * dy + dz * dz) * p2Candidate);
1129 if (cosPA < bestCosPA) {
1130 LOG(
debug) <<
"Rej. cosPA: " << cosPA;
1133 decay3bodyVtxID = iv;
1136 if (decay3bodyVtxID == -1) {
1137 LOG(
debug) <<
"3-body decay not compatible with any vertex";
1142 pidHyp = m3bodyHyps[ipid].getPIDHyp();
1143 vtxCosPA = bestCosPA;
1151 const auto& decay3bodyPv = mPVertices[decay3bodyVtxID];
1152 Decay3Body candidate3B(vertexXYZ, p3B, fitter3body.calcPCACovMatrixFlat(cand3B), tr0, tr1, tr2, pidHyp);
1155 if (!trc.propagateToDCA(decay3bodyPv, fitter3body.getBz(), &dca, 5.) ||
1160 candidate3B.setCosPA(vtxCosPA);
1161 candidate3B.setDCA(fitter3body.getChi2AtPCACandidate());
1162 m3bodyTmp[ithread].push_back(candidate3B);
1164 m3bodyIdxTmp[ithread].emplace_back(decay3bodyVtxID, v0Idx.
getProngID(0), v0Idx.
getProngID(1), bach.gid);
1168 mStrTracker->
process3Body(m3bodyIdxTmp[ithread].
size() - 1, candidate3B, decay3bodyIdx, ithread);
1171 return m3bodyIdxTmp[ithread].size() - n3BodyIni;
1175template <
class TVI,
class TCI,
class T3I,
class TR>
1176void SVertexer::extractPVReferences(
const TVI& v0s, TR& vtx2V0Refs,
const TCI& cascades, TR& vtx2CascRefs,
const T3I& vtx3, TR& vtx2body3Refs)
1180 vtx2V0Refs.resize(mPVertices.size());
1181 vtx2CascRefs.clear();
1182 vtx2CascRefs.resize(mPVertices.size());
1183 vtx2body3Refs.clear();
1184 vtx2body3Refs.resize(mPVertices.size());
1185 int nv0 = v0s.size(), nCasc = cascades.size(), n3body = vtx3.size();
1188 int pvID = -1, nForPV = 0;
1189 for (
int iv = 0; iv < nv0; iv++) {
1190 if (pvID < v0s[iv].getVertexID()) {
1192 vtx2V0Refs[pvID].setEntries(nForPV);
1194 pvID = v0s[iv].getVertexID();
1195 vtx2V0Refs[pvID].setFirstEntry(iv);
1201 vtx2V0Refs[pvID].setEntries(nForPV);
1204 for (
int ip = vtx2V0Refs.size(); ip--;) {
1205 if (vtx2V0Refs[ip].getEntries()) {
1206 ent = vtx2V0Refs[ip].getFirstEntry();
1208 vtx2V0Refs[ip].setFirstEntry(ent);
1216 for (
int iv = 0; iv < nCasc; iv++) {
1217 if (pvID < cascades[iv].getVertexID()) {
1219 vtx2CascRefs[pvID].setEntries(nForPV);
1221 pvID = cascades[iv].getVertexID();
1222 vtx2CascRefs[pvID].setFirstEntry(iv);
1228 vtx2CascRefs[pvID].setEntries(nForPV);
1231 for (
int ip = vtx2CascRefs.size(); ip--;) {
1232 if (vtx2CascRefs[ip].getEntries()) {
1233 ent = vtx2CascRefs[ip].getFirstEntry();
1235 vtx2CascRefs[ip].setFirstEntry(ent);
1243 for (
int iv = 0; iv < n3body; iv++) {
1244 const auto& vertex3body = vtx3[iv];
1245 if (pvID < vertex3body.getVertexID()) {
1247 vtx2body3Refs[pvID].setEntries(nForPV);
1249 pvID = vertex3body.getVertexID();
1250 vtx2body3Refs[pvID].setFirstEntry(iv);
1256 vtx2body3Refs[pvID].setEntries(nForPV);
1259 for (
int ip = vtx2body3Refs.size(); ip--;) {
1260 if (vtx2body3Refs[ip].getEntries()) {
1261 ent = vtx2body3Refs[ip].getFirstEntry();
1263 vtx2body3Refs[ip].setFirstEntry(ent);
1273 mNThreads =
n > 0 ?
n : 1;
1286 if (trTPC.hasBothSidesClusters()) {
1289 const auto& vtx = mPVertices[vtxid];
1290 auto twe = vtx.getTimeStamp();
1291 int posneg = trTPC.getSign() < 0 ? 1 : 0;
1293 bool compatibleWithProton =
false;
1297 float dEdxTPC = trTPC.getdEdx().dEdxTotTPC;
1298 float dEdxExpected = mPIDresponse.getExpectedSignal(trTPC, protonId);
1299 float fracDevProton = std::abs((dEdxTPC - dEdxExpected) / dEdxExpected);
1300 if (fracDevProton < mSVParams->mFractiondEdxforCascBaryons) {
1301 compatibleWithProton =
true;
1305 auto& trLoc = mTracksPool[posneg].emplace_back(TrackCand{trTPC, gid, {vtxid, vtxid}, 0.,
true, -1, compatibleWithProton});
1306 auto err = correctTPCTrack(trLoc, trTPC, twe.getTimeStamp(), twe.getTimeStampError());
1308 mTracksPool[posneg].pop_back();
1316 bool dDPV = std::abs(trLoc.getX() * trLoc.getTgl() - trLoc.getZ() + vtx.getZ()) > mSVParams->
mTPCTrack2Beam;
1318 float sna{0}, csa{0};
1320 trLoc.getCircleParams(mBz, trkCircle, sna, csa);
1321 float cR = std::hypot(trkCircle.
xC, trkCircle.
yC);
1322 float drd2 = std::sqrt(cR * cR - trkCircle.
rC * trkCircle.
rC);
1325 if (dCls || dDPV || dRD2) {
1326 mTracksPool[posneg].pop_back();
1345 tTB = tTPC.getTime0();
1346 tTBErr = 0.5 * (tTPC.getDeltaTBwd() + tTPC.getDeltaTFwd());
1348 tTB = tmus * mMUS2TPCBin;
1349 tTBErr = tmusErr * mMUS2TPCBin;
1351 float dDrift = (tTB - tTPC.getTime0()) * mTPCBin2Z;
1352 float driftErr = tTBErr * mTPCBin2Z;
1353 if (driftErr < 0.) {
1357 trc.setZ(tTPC.getZ() + (tTPC.hasASideClustersOnly() ? dDrift : -dDrift));
1360 auto cl = &tTPC.getCluster(mTPCTrackClusIdx, tTPC.getNClusters() - 1, *mTPCClusterIdxStruct, sector,
row);
1361 float x = 0,
y = 0,
z = 0;
1362 mTPCCorrMapsHelper->Transform(sector,
row, cl->getPad(), cl->getTime(),
x,
y,
z, tTB);
1366 trc.
minR = std::sqrt(
x *
x +
y *
y);
1367 LOGP(
debug,
"set MinR = {} for row {}, x:{}, y:{}, z:{}", trc.
minR,
row,
x,
y,
z);
1374 std::array<size_t, 3> calls{};
1375 for (
int i = 0;
i < mNThreads;
i++) {
1376 calls[0] += mFitterV0[
i].getCallID();
1377 calls[1] += mFitterCasc[
i].getCallID();
1378 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, o2::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"