2121#include < limits>
2222#include < ranges>
2323#include < type_traits>
24- #include " ReconstructionDataFormats/Vertex.h"
2524
2625#ifdef OPTIMISATION_OUTPUT
2726#include < format>
4241#include " ITStracking/IndexTableUtils.h"
4342#include " ITStracking/Tracklet.h"
4443#include " ReconstructionDataFormats/Track.h"
44+ #include " CommonUtils/TreeStreamRedirector.h"
4545
4646using o2::base::PropagatorF;
4747
@@ -456,9 +456,56 @@ template <int NLayers>
456456void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
457457{
458458 const auto & propagator = o2::base::Propagator::Instance ();
459+ auto & cells = mTimeFrame ->getCells ()[0 ];
460+
461+ // / DEBUG OUTPUT
462+ // dump cells and pot. their labels
463+ auto ts = new utils::TreeStreamRedirector (" cells.root" );
464+ auto & s = (*ts) << " seeding" ;
465+ for (int iCell{0 }; iCell < cells.size (); ++iCell) {
466+ auto cell = cells[iCell];
467+ dataformats::VertexBase vtx;
468+ dataformats::DCA dca;
469+ float z = cell.getZAt (0 ., getBz ());
470+ if (z < -999 .f ) {
471+ if (mTimeFrame ->hasMeanVertex ()) {
472+ z = mTimeFrame ->getMeanVertex ()->getZ ();
473+ } else {
474+ continue ;
475+ }
476+ }
477+ if (mTimeFrame ->hasMeanVertex ()) {
478+ mTimeFrame ->getMeanVertex ()->setMeanXYVertexAtZ (vtx, z);
479+ }
480+ const auto & cls = cell.getClusters ();
481+ const int sta = cell.getUserField ();
482+ int startBC = std::numeric_limits<int >::max (), endBC = std::numeric_limits<int >::min ();
483+ for (int i{sta}; i < 3 ; ++i) {
484+ int rof = mTimeFrame ->getClusterROF (i, cls[i]);
485+ int rofStartBC = mTimeFrame ->getROFOverlapTableView ().getLayer (i).getROFStartInBC (rof);
486+ int rofEndBC = mTimeFrame ->getROFOverlapTableView ().getLayer (i).getROFEndInBC (rof);
487+ startBC = o2::gpu::CAMath::Min (startBC, rofStartBC);
488+ endBC = o2::gpu::CAMath::Max (endBC, rofEndBC);
489+ }
490+ auto cellC = cell;
491+ if (propagator->propagateToDCA (vtx, cellC, getBz (), 2 .0f , o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dca, nullptr , 0 , mRecoParams [iteration].params .SeedingDCATolerance )) {
492+ s << " cell=" << (const o2::track::TrackParCov&)cell
493+ << " cellPV=" << (o2::track::TrackParCov)cellC
494+ << " vtx=" << vtx
495+ << " staBC=" << startBC
496+ << " endBC=" << endBC;
497+ if (mTimeFrame ->hasMCinformation () && mRecoParams [iteration].params .createArtefactLabels ) {
498+ s << " cellLbl=" << mTimeFrame ->getCellsLabel (0 )[iCell];
499+ }
500+ s << " \n " ;
501+ }
502+ }
503+ ts->Close ();
504+ delete ts;
505+ ts = nullptr ;
506+
459507 mTaskArena ->execute ([&] {
460508 // we get cells from the first three layers
461- auto & cells = mTimeFrame ->getCells ()[0 ];
462509 bounded_vector<LinearizedTrack> ltracks;
463510 ltracks.resize (cells.size ());
464511 tbb::parallel_for (size_t (0 ), cells.size (), [&](size_t iCell) {
@@ -478,11 +525,11 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
478525 if (mTimeFrame ->hasMeanVertex ()) {
479526 mTimeFrame ->getMeanVertex ()->setMeanXYVertexAtZ (vtx, z);
480527 }
481- if (!propagator->propagateToDCA (vtx, cell, getBz (), 2 .0f , o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dca, nullptr , 0 , mRecoParams [iteration].params .seedingDCATolerance )) {
528+ if (!propagator->propagateToDCA (vtx, cell, getBz (), 2 .0f , o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dca, nullptr , 0 , mRecoParams [iteration].params .SeedingDCATolerance )) {
482529 ltracks[iCell].markDead ();
483530 return ;
484531 }
485- if (dca.getY () * dca.getY () / (dca.getSigmaY2 ()) >= mRecoParams [iteration].params .seedingDCAMaxPull ) {
532+ if (dca.getY () * dca.getY () / (dca.getSigmaY2 ()) >= mRecoParams [iteration].params .SeedingDCAMaxPull ) {
486533 ltracks[iCell].markDead ();
487534 return ;
488535 }
@@ -531,6 +578,11 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
531578 // scan gives association in time and z
532579 const auto dbRes = mDBScan .cluster (ltracks.data (), ltracks.size ());
533580 bounded_vector<VertexSeed> vtxSeeds (dbRes.nClusters , mMemoryPool .get ());
581+ bounded_vector<std::pair<o2::MCCompLabel, float >> vtxSeedsLbl (dbRes.nClusters , mMemoryPool .get ());
582+ // we only care about the source&event of the tracks, not the trackId
583+ auto composeVtxLabel = [](const o2::MCCompLabel& lbl) -> o2::MCCompLabel {
584+ return {o2::MCCompLabel::maxTrackID (), lbl.getEventID (), lbl.getSourceID (), lbl.isFake ()};
585+ };
534586 tbb::parallel_for (0 , dbRes.nClusters , [&](const int32_t iCls) {
535587 // create vertex seeds based on meanvertex and scanned z which one can take as start
536588 auto & seed = vtxSeeds[iCls];
@@ -539,11 +591,11 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
539591 mTimeFrame ->getMeanVertex ()->setMeanXYVertexAtZ (seed, seed.getZ ());
540592 }
541593 seed.idx = iCls;
542- seed.tukeyC = mRecoParams [iteration].params .seedingTukeyStartIter ;
594+ seed.tukeyC = mRecoParams [iteration].params .SeedingTukeyStartIter ;
543595 seed.scaleSig2ITuk2I = 1 .f / (seed.tukeyC * seed.tukeyC );
544596 const auto & range = dbRes.ranges [iCls];
545597 // fit iteratively
546- for (int iter{0 }; iter < mRecoParams [iteration].params .seedingMaxFitIter ; ++iter) {
598+ for (int iter{0 }; iter < mRecoParams [iteration].params .SeedingMaxFitIter ; ++iter) {
547599 seed.iteration = iter;
548600 // 1. update tukey scaling
549601 seed.updateTukeyScale (ltracks.data (), dbRes.labels .data (), ltracks.size (), range);
@@ -558,7 +610,7 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
558610 seed.accountTrack (lt);
559611 }
560612 // 4. if needed relax scaling
561- if (seed.getNContributors () < mRecoParams [iteration].params .seedingMinTracksIter ) {
613+ if (seed.getNContributors () < mRecoParams [iteration].params .SeedingMinTracksIter ) {
562614 seed.status = VertexSeed::kIterateRelaxScale ;
563615 continue ;
564616 }
@@ -577,7 +629,7 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
577629 seed.solveVertex ();
578630 // 7. check for convergence
579631 float avgChi2 = seed.wghChi2 / o2::gpu::CAMath::Max (1 .f , seed.wghSum );
580- if (avgChi2 < mRecoParams [iteration].params .seedingMaxChi2Iter ) {
632+ if (avgChi2 < mRecoParams [iteration].params .SeedingMaxChi2Iter ) {
581633 seed.status = VertexSeed::kConverged ;
582634 break ;
583635 }
@@ -591,7 +643,7 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
591643 continue ;
592644 }
593645 float chi2Red = lt.getChi2 (seed);
594- if (chi2Red > mRecoParams [iteration].params .seedingMaxChi2Iter ) {
646+ if (chi2Red > mRecoParams [iteration].params .SeedingMaxChi2Iter ) {
595647 continue ;
596648 }
597649 startBC = o2::gpu::CAMath::Min (startBC, lt.time .getTimeStamp ());
@@ -601,7 +653,47 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
601653 seed.getTimeStamp ().setTimeStampError (endBC - startBC);
602654 // add additional errors
603655 for (int i{0 }; i < dataformats::VertexBase::kNCov ; ++i) {
604- seed.setCov (seed.getCov (i) + mRecoParams [iteration].params .seedingVertexExtraErr2 [i], i);
656+ seed.setCov (seed.getCov (i) + mRecoParams [iteration].params .SeedingVertexExtraErr2 [i], i);
657+ }
658+ // if mc is present calculate labels and purity
659+ if (mTimeFrame ->hasMCinformation ()) {
660+ // use boyer-moore voting
661+ int accepted{0 }, weight{0 };
662+ o2::MCCompLabel lbl;
663+ for (uint32_t entry{range.getFirstEntry ()}; entry < range.getEntriesBound (); ++entry) {
664+ const auto & lt = ltracks[entry];
665+ if (lt.isDead () || dbRes.labels [entry] != iCls) {
666+ continue ;
667+ }
668+ if (seed.acceptTrack (lt)) {
669+ ++accepted;
670+ // create cell label
671+ const auto & cell = mTimeFrame ->getCells ()[0 ][lt.cellIdx ];
672+ o2::MCCompLabel cl;
673+ for (const auto & lab1 : mTimeFrame ->getClusterLabels (0 , cell.getFirstClusterIndex ())) {
674+ for (const auto & lab2 : mTimeFrame ->getClusterLabels (1 , cell.getSecondClusterIndex ())) {
675+ if (lab1 == lab2 && lab1.isValid ()) {
676+ cl = lab1;
677+ break ;
678+ }
679+ }
680+ if (cl.isValid ()) {
681+ break ;
682+ }
683+ }
684+ if (weight == 0 ) {
685+ lbl = cl;
686+ weight = 1 ;
687+ } else {
688+ (cl == lbl) ? ++weight : --weight;
689+ }
690+ }
691+ }
692+ if (accepted > 0 ) {
693+ vtxSeedsLbl[iCls] = {lbl, static_cast <float >(weight) / static_cast <float >(accepted)};
694+ } else {
695+ vtxSeedsLbl[iCls] = {lbl, 0 };
696+ }
605697 }
606698 });
607699 // TODO reduce debris vertices (eliminate small mult vertices within vicinity of high multiplicity ones)
@@ -611,6 +703,9 @@ void TrackerTraits<NLayers>::findCellSeeds(const int iteration)
611703 continue ;
612704 }
613705 mTimeFrame ->addPrimaryVertex (vtxSeeds[i]);
706+ if (mTimeFrame ->hasMCinformation ()) {
707+ mTimeFrame ->addPrimaryVertexLabel (vtxSeedsLbl[i]);
708+ }
614709 }
615710 });
616711}
@@ -1413,9 +1508,9 @@ void TrackerTraits<NLayers>::updateTrackingParameters(const std::vector<RecoIter
14131508 if (static bool onceDone{false }; !onceDone) {
14141509 onceDone = true ;
14151510 dbscan::DBSCANParams p;
1416- p.minPts = mRecoParams [0 ].params .seedingDBScanMinPt ;
1417- p.eps [0 ] = mRecoParams [0 ].params .seedingDBScanEpsZ ;
1418- p.eps [1 ] = mRecoParams [0 ].params .seedingDBScanEpsT ;
1511+ p.minPts = mRecoParams [0 ].params .SeedingDBScanMinPt ;
1512+ p.eps [0 ] = mRecoParams [0 ].params .SeedingDBScanEpsZ ;
1513+ p.eps [1 ] = mRecoParams [0 ].params .SeedingDBScanEpsT ;
14191514 mDBScan = dbscan::DBSCAN (p);
14201515 }
14211516}
0 commit comments