30#define BOOST_TEST_MODULE ITSMFT ComputeLayerCells orchestration
31#define BOOST_TEST_MAIN
32#define BOOST_TEST_DYN_LINK
41#include <boost/test/unit_test.hpp>
43#include <oneapi/tbb/task_arena.h>
61#include "MFTTracking/Constants.h"
74constexpr float Bz = 0.5f;
80class NeverDecodedDecoder
105class FixedMeasurementDecoder
108 struct MeasurementPair {
114 void setMeasurement(
int layer,
const MeasurementPair& measurement) { mByLayer[
layer] = measurement; }
118 gsl::span<const unsigned char>::iterator&,
124 const auto it = mByLayer.find(
layer);
125 BOOST_REQUIRE(it != mByLayer.end());
126 result = it->second.decoded;
134 std::map<int, MeasurementPair> mByLayer;
143std::vector<LayerId> identitySurfaces(uint16_t nLayers)
145 std::vector<LayerId> mapping;
146 mapping.reserve(nLayers);
147 for (uint16_t
i = 0;
i < nLayers; ++
i) {
156 gsl::span<const SurfaceKind> kinds, gsl::span<const float> layerxX0)
158 std::vector<SurfaceDescriptor> surfaces;
159 surfaces.reserve(nLayers);
160 for (uint16_t
i = 0;
i < nLayers; ++
i) {
161 const auto kind = kinds[
i];
164 surfaces.back().referenceCoordinate =
kind == SurfaceKind::Cylinder
165 ? 3.f +
static_cast<float>(
i)
166 : -0.4f - 0.2f *
static_cast<float>(
i);
167 const float xOverX0 = layerxX0[
i];
168 surfaces.back().material.xOverX0 = xOverX0;
180 measurement.radius = std::hypot(
x,
y);
181 measurement.phi = std::atan2(
y,
x);
182 measurement.clusterId =
static_cast<uint32_t
>(
id);
186struct TestLocalMeasurement {
187 float xTrackingFrame{0.f};
188 float alphaTrackingFrame{0.f};
189 std::array<float, 2> positionTrackingFrame{};
190 std::array<float, 3> covarianceTrackingFrame{};
193TestLocalMeasurement makeBarrelHit(
float xTF,
float alpha,
float y,
float z,
float sigma2Y = 1.e-4f,
float sigma2Z = 1.e-4f)
195 return {xTF,
alpha, {
y,
z}, {sigma2Y, 0.f, sigma2Z}};
198TestLocalMeasurement makeDiskHit(
float z,
float x,
float y,
float sigma2X = 1.e-2f,
float sigma2Y = 1.e-2f)
200 return {
z, 0.f, {
x,
y}, {sigma2X, 0.f, sigma2Y}};
208FixedMeasurementDecoder::MeasurementPair barrelMeasurementFor(
const GlobalMeasurement& cluster,
const TestLocalMeasurement& hit)
210 FixedMeasurementDecoder::MeasurementPair measurement{};
211 measurement.decoded.global = {cluster.
x, cluster.
y, cluster.
z};
212 measurement.decoded.cylinderFrame = {hit.xTrackingFrame, hit.positionTrackingFrame[0],
213 hit.positionTrackingFrame[1], hit.alphaTrackingFrame};
214 measurement.decoded.rowColumnCovariance = {hit.covarianceTrackingFrame[0],
215 hit.covarianceTrackingFrame[1],
216 hit.covarianceTrackingFrame[2]};
220FixedMeasurementDecoder::MeasurementPair diskMeasurementFor(
const GlobalMeasurement& cluster,
const TestLocalMeasurement& hit)
222 FixedMeasurementDecoder::MeasurementPair measurement{};
223 measurement.decoded.global = {cluster.
x, cluster.
y, cluster.
z};
224 measurement.decoded.rowColumnCovariance = {hit.covarianceTrackingFrame[0], 0.f,
225 hit.covarianceTrackingFrame[2]};
235 for (
int hit = 0; hit < 3; ++hit) {
236 for (
int coordinate = 0; coordinate < 3; ++coordinate) {
246 BOOST_CHECK_EQUAL(trackSeed.getHitLayerMask().value(), cell.getHitLayerMask().value());
247 for (
int slot = 0; slot < 3; ++slot) {
248 const auto reference = cell.getClusterReference(slot);
252 BOOST_CHECK_EQUAL(trackSeed.getFirstTrackletIndex(), cell.getFirstTrackletIndex());
253 BOOST_CHECK_EQUAL(trackSeed.getSecondTrackletIndex(), cell.getSecondTrackletIndex());
254 BOOST_CHECK_EQUAL(trackSeed.getTimeStamp().getTimeStamp(), cell.getTimeStamp().getTimeStamp());
255 BOOST_CHECK_EQUAL(trackSeed.getTimeStamp().getTimeStampError(), cell.getTimeStamp().getTimeStampError());
273 BOOST_CHECK_EQUAL(lhs.getTimeStamp().getTimeStamp(), rhs.getTimeStamp().getTimeStamp());
274 BOOST_CHECK_EQUAL(lhs.getTimeStamp().getTimeStampError(), rhs.getTimeStamp().getTimeStampError());
278 for (
int parameter = 0; parameter < 5; ++parameter) {
279 BOOST_CHECK_EQUAL(lhs.state().parameters[parameter], rhs.state().parameters[parameter]);
281 for (
int covariance = 0; covariance < 15; ++covariance) {
282 BOOST_CHECK_EQUAL(lhs.state().covariance[covariance], rhs.state().covariance[covariance]);
284 BOOST_CHECK_EQUAL(lhs.state().referenceCoordinate, rhs.state().referenceCoordinate);
293 int cellPathId,
const Triplet& cell,
299 traits, view, cellPathId, cell, trackSeed));
300 checkTrackSeedContents(trackSeed, cell, expectedKind);
311struct RigFrameStorage {
312 RigFrameStorage() : pool(std::make_shared<BoundedMemoryResource>()) { frame.setMemoryPool(pool); }
314 std::shared_ptr<BoundedMemoryResource> pool;
318template <
int NLayers>
319struct Rig : RigFrameStorage {
324 mKinds(NLayers,
kind)
326 resetReferenceTrackingParameters(
params[0], det);
337 params[0].PassFlags.reset(IterationStep::RebuildClusterLUT);
346 void establishLayout()
348 catalog = makeCatalog(
static_cast<uint16_t
>(NLayers), mDet, gsl::span<const SurfaceKind>{mKinds}, gsl::span<const float>(
params[0].LayerxX0));
349 const auto orderedSurfaces = identitySurfaces(
static_cast<uint16_t
>(NLayers));
350 const SurfaceCatalogView catalogView{catalog.data(),
static_cast<uint32_t
>(catalog.size())};
352 configuration.
catalog = catalogView;
356 BOOST_REQUIRE(tracker.initialize(frame, configuration));
357 tf = &frame.getScratch();
358 const auto& layout = frame.getDetectorConfiguration();
360 NeverDecodedDecoder decoder{mDet};
363 const std::vector<CompClusterExt> noClusters;
364 const std::vector<unsigned char> noPatterns;
365 const std::vector<ROFRecord> noRofs;
366 BOOST_REQUIRE_NO_THROW(test::loadTimeFrameSource(frame, decoder,
origin, timing, noClusters, noPatterns, noRofs, &dict(),
nullptr, mDet,
367 gsl::span<const LayerId>{orderedSurfaces}, layout.getSurfaceCatalog()));
375 std::vector<ReferenceTrackingParameters>
params;
381 std::array<gsl::span<const GlobalMeasurement>,
MaxLayoutSurfaces> measurementSpans;
383 std::shared_ptr<tbb::task_arena> arena;
385 std::vector<SurfaceDescriptor> catalog;
389 std::vector<SurfaceKind> mKinds;
392template <
int NLayers>
398template <
int NLayers>
401 return rig.tracker.getIterationConfigurations()[0].getTopologyView(rig.frame.getDetectorConfiguration().getSurfaceCatalog());
415template <
int NLayers>
416void loadCandidateClusters(Rig<NLayers>& rig,
417 const std::array<GlobalMeasurement, 3>&
clusters,
418 const std::array<TestLocalMeasurement, 3>& hits)
420 FixedMeasurementDecoder decoder{rig.detector(), rig.kind()};
421 std::vector<CompClusterExt> compClusters;
422 compClusters.reserve(3);
425 const auto measurement = rig.kind(
layer) == SurfaceKind::Disk
428 decoder.setMeasurement(
layer, measurement);
430 const std::vector<unsigned char> noPatterns;
431 const std::vector<ROFRecord> rofs{
ROFRecord{{0, 0}, 0, 0, 3}};
434 const auto layerMapping = identitySurfaces(
static_cast<uint16_t
>(NLayers));
435 BOOST_REQUIRE_NO_THROW(test::loadTimeFrameSource(rig.frame, decoder,
origin, timing, compClusters, noPatterns, rofs, &dict(),
nullptr, rig.detector(),
436 gsl::span<const LayerId>{layerMapping}, rig.frame.getDetectorConfiguration().getSurfaceCatalog()));
442template <
typename TopologyView>
443int findCellIndex(
const TopologyView& topology,
int inner,
int middle,
int outer)
445 for (
int i = 0;
i < topology.nPaths; ++
i) {
446 const auto& cell = topology.getPath(
CellPathId{
static_cast<uint16_t
>(
i)});
447 const auto&
first = topology.getEdge(cell.first);
448 const auto& second = topology.getEdge(cell.second);
449 if (
first.from.value() == inner &&
first.to.value() == middle && second.from.value() == middle && second.to.value() == outer) {
459 const float transverseChord = std::hypot(second.
x -
first.x, second.
y -
first.y);
460 BOOST_REQUIRE_GT(transverseChord, 1.e-6f);
461 const float tanLambda = (second.
z -
first.z) / transverseChord;
462 const float phi = std::atan2(
first.y - second.
y,
first.x - second.
x);
463 return {0, 0, tanLambda, phi, timestamp};
473template <
int NLayers>
474void injectCandidateTracklets(Rig<NLayers>& rig,
int cellIndex,
const std::array<GlobalMeasurement, 3>&
clusters)
476 const auto topology = topologyView(rig);
477 const auto& cell = topology.getPath(
CellPathId{
static_cast<uint16_t
>(cellIndex)});
478 const auto&
first = topology.getEdge(cell.first);
479 const auto& second = topology.getEdge(cell.second);
480 const int layers[3] = {
first.from.value(),
first.to.value(), second.to.value()};
482 for (
int i = 0;
i < 3; ++
i) {
483 BOOST_REQUIRE_EQUAL(rig.frame.getClusters()[layers[
i]].size(), 1u);
490 rig.tf->getTracklets()[cell.first.value()].push_back(candidateTracklet(
clusters[0],
clusters[1], ts));
491 rig.tf->getTracklets()[cell.second.value()].push_back(candidateTracklet(
clusters[1],
clusters[2], ts));
493 auto& secondLUT = rig.tf->getTrackletsLookupTable()[cell.second.value()];
509template <
int NLayers,
size_t N>
510void loadCandidateClustersAtLayers(Rig<NLayers>& rig,
511 const std::array<int, N>& layers,
512 const std::array<GlobalMeasurement, N>&
clusters,
513 const std::array<TestLocalMeasurement, N>& hits)
515 FixedMeasurementDecoder decoder{rig.detector(), rig.kind()};
516 std::vector<CompClusterExt> compClusters;
517 compClusters.reserve(N);
518 for (
size_t i = 0;
i < N; ++
i) {
520 const auto measurement = rig.kind(layers[
i]) == SurfaceKind::Disk
523 decoder.setMeasurement(layers[
i], measurement);
525 const std::vector<unsigned char> noPatterns;
526 const std::vector<ROFRecord> rofs{
ROFRecord{{0, 0}, 0, 0,
static_cast<int>(N)}};
529 const auto layerMapping = identitySurfaces(
static_cast<uint16_t
>(NLayers));
530 BOOST_REQUIRE_NO_THROW(test::loadTimeFrameSource(rig.frame, decoder,
origin, timing, compClusters, noPatterns, rofs, &dict(),
nullptr, rig.detector(),
531 gsl::span<const LayerId>{layerMapping}, rig.frame.getDetectorConfiguration().getSurfaceCatalog()));
536template <
typename TopologyView>
537int findEdgeId(
const TopologyView& topology,
int from,
int to)
539 for (
int i = 0;
i < topology.nEdges; ++
i) {
540 const auto& t = topology.getEdge(
EdgeId{
static_cast<uint16_t
>(
i)});
541 if (t.from.value() == from && t.to.value() == to) {
558template <
int NLayers,
size_t N>
559void injectChainCandidateTracklets(Rig<NLayers>& rig,
const std::array<int, N>& layers,
const std::array<GlobalMeasurement, N>&
clusters)
561 static_assert(N >= 3,
"a chain needs at least 3 layers to form one cell");
562 const auto topology = topologyView(rig);
563 for (
size_t i = 0;
i < N; ++
i) {
564 BOOST_REQUIRE_EQUAL(rig.frame.getClusters()[layers[
i]].size(), 1u);
571 for (
size_t i = 0;
i + 1 < N; ++
i) {
572 const int edgeId = findEdgeId(topology, layers[
i], layers[
i + 1]);
573 BOOST_REQUIRE_GE(edgeId, 0);
574 rig.tf->getTracklets()[edgeId].push_back(candidateTracklet(
clusters[
i],
clusters[
i + 1], ts));
575 auto& lut = rig.tf->getTrackletsLookupTable()[edgeId];
582std::array<TestLocalMeasurement, 3> makeLocalMeasurements(
583 const std::array<SurfaceKind, 3>& kinds,
584 const std::array<GlobalMeasurement, 3>&
clusters)
586 std::array<TestLocalMeasurement, 3> hits{};
589 hits[
layer] = kinds[
layer] == SurfaceKind::Disk
590 ? makeDiskHit(position.z, position.x, position.y)
591 : makeBarrelHit(position.x, 0.f, position.y, position.z);
596template <
int NLayers>
597void checkDirectTrackSeedConstruction(
const std::array<SurfaceKind, 3>& kinds,
598 const std::array<GlobalMeasurement, 3>&
clusters)
600 Rig<NLayers> rig{o2::detectors::DetID::ITS, kinds[0]};
601 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
604 rig.params[0].LayerxX0[
layer] = 0.f;
606 rig.establishLayout();
607 loadCandidateClusters(rig,
clusters, makeLocalMeasurements(kinds,
clusters));
609 auto view = prepare(rig);
610 const int cellPathId = findCellIndex(topologyView(rig), 0, 1, 2);
611 BOOST_REQUIRE_GE(cellPathId, 0);
619 rig.traits, view, cellPathId, cell,
first));
621 rig.traits, view, cellPathId, cell, second));
623 checkTrackSeedContents(
first, cell, kinds[0]);
624 checkTrackSeedsEqual(
first, second);
627constexpr std::array<SurfaceKind, 3> CylinderCylinderCylinder{
628 SurfaceKind::Cylinder, SurfaceKind::Cylinder, SurfaceKind::Cylinder};
629constexpr std::array<SurfaceKind, 3> DiskDiskDisk{
630 SurfaceKind::Disk, SurfaceKind::Disk, SurfaceKind::Disk};
631constexpr std::array<SurfaceKind, 3> CylinderDiskCylinder{
632 SurfaceKind::Cylinder, SurfaceKind::Disk, SurfaceKind::Cylinder};
633constexpr std::array<SurfaceKind, 3> DiskCylinderDisk{
634 SurfaceKind::Disk, SurfaceKind::Cylinder, SurfaceKind::Disk};
636const std::array<GlobalMeasurement, 3> NominalTrackSeedClusters{
637 makeGlobalCluster(3.0f, 0.100f, 0.90f, 0),
638 makeGlobalCluster(4.0f, 0.150f, 1.05f, 0),
639 makeGlobalCluster(5.0f, 0.201f, 1.25f, 0)};
645 checkDirectTrackSeedConstruction<ITSNLayers>(CylinderCylinderCylinder, NominalTrackSeedClusters);
650 checkDirectTrackSeedConstruction<ITSNLayers>(DiskDiskDisk, NominalTrackSeedClusters);
655 checkDirectTrackSeedConstruction<ITSNLayers>(CylinderDiskCylinder, NominalTrackSeedClusters);
660 checkDirectTrackSeedConstruction<ITSNLayers>(DiskCylinderDisk, NominalTrackSeedClusters);
665 Rig<ITSNLayers> rig{o2::detectors::DetID::ITS, SurfaceKind::Cylinder};
666 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
668 rig.setSurfaceKind(
layer, CylinderDiskCylinder[
layer]);
669 rig.params[0].LayerxX0[
layer] = 0.f;
671 rig.establishLayout();
673 const std::array<GlobalMeasurement, 3> degenerateClusters{
674 makeGlobalCluster(3.f, 0.1f, 0.9f, 0),
675 makeGlobalCluster(3.f, 0.1f, 1.0f, 0),
676 makeGlobalCluster(3.f, 0.1f, 1.1f, 0)};
677 loadCandidateClusters(rig, degenerateClusters,
678 makeLocalMeasurements(CylinderDiskCylinder, degenerateClusters));
679 auto view = prepare(rig);
680 const int cellPathId = findCellIndex(topologyView(rig), 0, 1, 2);
681 BOOST_REQUIRE_GE(cellPathId, 0);
686 sentinelState.
kind = SurfaceKind::Disk;
687 sentinelState.referenceCoordinate = -42.f;
688 sentinelState.parameters[0] = 13.f;
689 TrackSeed destination{cell, sentinelState, 71.f};
693 rig.traits, view, cellPathId, cell, destination));
695 checkTrackSeedsEqual(destination, before);
702 Rig<ITSNLayers> rig{o2::detectors::DetID::ITS, SurfaceKind::Cylinder};
703 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
704 rig.params[0].LayerxX0[0] = 0.005f;
705 rig.params[0].LayerxX0[1] = 0.005f;
706 rig.params[0].LayerxX0[2] = 0.f;
707 rig.establishLayout();
709 const std::array<GlobalMeasurement, 3>
clusters{makeGlobalCluster(3.0f, 0.100f, 0.9f, 0),
710 makeGlobalCluster(4.0f, 0.150f, 1.05f, 0),
711 makeGlobalCluster(5.0f, 0.201f, 1.20f, 0)};
712 loadCandidateClusters(rig,
clusters,
713 {makeBarrelHit(3.f, 0.f, 0.100f, 0.9f),
714 makeBarrelHit(4.f, 0.f, 0.150f, 1.05f),
715 makeBarrelHit(5.f, 0.f, 0.201f, 1.20f)});
719 const auto topology = topologyView(rig);
720 const int cellIndex = findCellIndex(topology, 0, 1, 2);
721 BOOST_REQUIRE_GE(cellIndex, 0);
723 injectCandidateTracklets(rig, cellIndex,
clusters);
727 int othercellIndex = -1;
728 for (
int i = 0;
i < topology.nPaths; ++
i) {
729 if (
i != cellIndex) {
734 BOOST_REQUIRE_GE(othercellIndex, 0);
738 BOOST_CHECK(rig.tf->getCells()[othercellIndex].empty());
739 BOOST_CHECK(rig.tf->getCellsLookupTable()[othercellIndex].empty());
740 BOOST_CHECK(rig.tf->getCellsLabel(othercellIndex).empty());
742 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
743 const auto& producedCell = rig.tf->getCells()[cellIndex][0];
744 BOOST_CHECK(producedCell.tripletFactor().isValid());
745 for (
int slot = 0; slot < 3; ++slot) {
746 const auto reference = producedCell.getClusterReference(slot);
751 BOOST_REQUIRE_EQUAL(rig.tf->getCellsLookupTable()[cellIndex].size(), 2u);
757 BOOST_CHECK(rig.tf->getCellsLabel(cellIndex).empty());
762 const auto layerGlobalMeasurements = gsl::span<const gsl::span<const GlobalMeasurement>>{view.layerGlobalMeasurements};
763 const auto& oracleGlobalInner = layerGlobalMeasurements[0][producedCell.getFirstClusterIndex()];
764 const auto& oracleGlobalMiddle = layerGlobalMeasurements[1][producedCell.getSecondClusterIndex()];
765 const auto& oracleGlobalOuter = layerGlobalMeasurements[2][producedCell.getThirdClusterIndex()];
766 const std::array<GlobalMeasurement, 3> measurements{
767 oracleGlobalInner, oracleGlobalMiddle, oracleGlobalOuter};
770 checkTripletFitFactorEqual(producedCell.tripletFactor(), oracleFactor);
771 checkTrackSeedMaterialization(rig.traits, view, cellIndex, producedCell,
772 SurfaceKind::Cylinder);
777 auto acceptedCells = [](
float trackletMinPt) {
778 Rig<ITSNLayers> rig{o2::detectors::DetID::ITS, SurfaceKind::Cylinder};
779 rig.params[0].TrackletMinPt = trackletMinPt;
780 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
781 rig.params[0].LayerxX0[0] = 0.005f;
782 rig.params[0].LayerxX0[1] = 0.01f;
783 rig.params[0].LayerxX0[2] = 0.f;
784 rig.establishLayout();
786 const std::array<GlobalMeasurement, 3>
clusters{
787 makeGlobalCluster(3.f, 0.100f, 0.9f),
788 makeGlobalCluster(4.f, 0.150f, 1.05f),
789 makeGlobalCluster(5.f, 0.201f, 1.22f)};
790 loadCandidateClusters(rig,
clusters,
791 {makeBarrelHit(3.f, 0.f, 0.100f, 0.9f, 1.e-6f, 1.e-6f),
792 makeBarrelHit(4.f, 0.f, 0.150f, 1.05f, 1.e-6f, 1.e-6f),
793 makeBarrelHit(5.f, 0.f, 0.201f, 1.22f, 1.e-6f, 1.e-6f)});
795 auto view = prepare(rig);
796 const auto topology = topologyView(rig);
797 const int cellIndex = findCellIndex(topology, 0, 1, 2);
798 BOOST_REQUIRE_GE(cellIndex, 0);
799 injectCandidateTracklets(rig, cellIndex,
clusters);
801 return rig.tf->getCells()[cellIndex].size();
810 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
811 rig.params[0].TrackletMinPt = 0.3f;
812 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
813 rig.params[0].LayerxX0[0] = 0.015f;
814 rig.params[0].LayerxX0[1] = 0.017f;
815 rig.params[0].LayerxX0[2] = 0.02f;
816 rig.establishLayout();
818 const std::array<GlobalMeasurement, 3>
clusters{
819 makeGlobalCluster(1.f, 0.f, -0.4f),
820 makeGlobalCluster(1.01f, 0.f, -0.6f),
821 makeGlobalCluster(1.01995f, 0.000998f, -0.8f)};
822 loadCandidateClusters(rig,
clusters,
823 {makeDiskHit(-0.4f, 1.f, 0.f),
824 makeDiskHit(-0.6f, 1.01f, 0.f),
825 makeDiskHit(-0.8f, 1.01995f, 0.000998f)});
827 auto view = prepare(rig);
828 const auto topology = topologyView(rig);
829 const int cellIndex = findCellIndex(topology, 0, 1, 2);
830 BOOST_REQUIRE_GE(cellIndex, 0);
831 injectCandidateTracklets(rig, cellIndex,
clusters);
839 auto acceptedCells = [](
float deltaPhi,
float deltaZ) {
840 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
841 rig.params[0].TrackletMinPt = 0.3f;
842 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
843 rig.params[0].LayerxX0[1] = 0.017f;
844 rig.establishLayout();
848 const float outerX = 1.01f + 0.01f * std::cos(deltaPhi);
849 const float outerY = 0.01f * std::sin(deltaPhi);
850 const std::array<GlobalMeasurement, 3>
clusters{
851 makeGlobalCluster(1.f, 0.f, -0.4f),
852 makeGlobalCluster(1.01f, 0.f, -0.4f - deltaZ),
853 makeGlobalCluster(outerX, outerY, -0.4f - 2.f * deltaZ)};
854 loadCandidateClusters(rig,
clusters,
859 auto view = prepare(rig);
860 const int cellIndex = findCellIndex(topologyView(rig), 0, 1, 2);
861 BOOST_REQUIRE_GE(cellIndex, 0);
862 injectCandidateTracklets(rig, cellIndex,
clusters);
864 return rig.tf->getCells()[cellIndex].size();
867 for (
const float deltaZ : {0.2f, 0.8f}) {
875 auto acceptedCells = [](
float meanTanLambda,
float deltaLambda) {
876 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
877 rig.params[0].TrackletMinPt = 0.3f;
878 rig.params[0].LayerxX0[1] = 0.017f;
879 rig.establishLayout();
883 const float meanLambda = std::atan(meanTanLambda);
884 const float middleZ = -0.4f + 0.01f * std::tan(meanLambda - 0.5f * deltaLambda);
885 const float outerZ = middleZ + 0.01f * std::tan(meanLambda + 0.5f * deltaLambda);
886 const std::array<GlobalMeasurement, 3>
clusters{
887 makeGlobalCluster(1.f, 0.f, -0.4f),
888 makeGlobalCluster(1.01f, 0.f, middleZ),
889 makeGlobalCluster(1.02f, 0.f, outerZ)};
890 loadCandidateClusters(rig,
clusters,
895 auto view = prepare(rig);
896 const int cellIndex = findCellIndex(topologyView(rig), 0, 1, 2);
897 BOOST_REQUIRE_GE(cellIndex, 0);
898 injectCandidateTracklets(rig, cellIndex,
clusters);
900 return rig.tf->getCells()[cellIndex].size();
903 for (
const float sign : {-1.f, 1.f}) {
914 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
915 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
916 rig.params[0].TrackletMinPt = 0.3f;
917 rig.params[0].LayerxX0[0] = 0.015f;
918 rig.params[0].LayerxX0[1] = 0.017f;
919 rig.params[0].LayerxX0[2] = 0.02f;
920 rig.establishLayout();
922 const std::array<GlobalMeasurement, 3>
clusters{makeGlobalCluster(1.0f, 0.5f, -0.4f, 0),
923 makeGlobalCluster(1.3f, 0.62f, -0.6f, 0),
924 makeGlobalCluster(1.7f, 0.78f, -0.9f, 0)};
925 loadCandidateClusters(rig,
clusters,
926 {makeDiskHit(-0.4f, 1.0f, 0.5f),
927 makeDiskHit(-0.6f, 1.3f, 0.62f),
928 makeDiskHit(-0.9f, 1.7f, 0.78f)});
930 auto view = prepare(rig);
932 const auto topology = topologyView(rig);
933 const int cellIndex = findCellIndex(topology, 0, 1, 2);
934 BOOST_REQUIRE_GE(cellIndex, 0);
936 injectCandidateTracklets(rig, cellIndex,
clusters);
940 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
941 const auto& producedCell = rig.tf->getCells()[cellIndex][0];
942 BOOST_CHECK(producedCell.tripletFactor().isValid());
943 for (
int slot = 0; slot < 3; ++slot) {
944 const auto reference = producedCell.getClusterReference(slot);
949 const auto layerGlobalMeasurements = gsl::span<const gsl::span<const GlobalMeasurement>>{view.layerGlobalMeasurements};
950 const auto& oracleGlobalInner = layerGlobalMeasurements[0][producedCell.getFirstClusterIndex()];
951 const auto& oracleGlobalMiddle = layerGlobalMeasurements[1][producedCell.getSecondClusterIndex()];
952 const auto& oracleGlobalOuter = layerGlobalMeasurements[2][producedCell.getThirdClusterIndex()];
953 const std::array<GlobalMeasurement, 3> measurements{
954 oracleGlobalInner, oracleGlobalMiddle, oracleGlobalOuter};
957 checkTripletFitFactorEqual(producedCell.tripletFactor(), oracleFactor);
958 checkTrackSeedMaterialization(rig.traits, view, cellIndex, producedCell,
968 std::vector<int> lut;
970 int cl0{-1}, cl1{-1}, cl2{-1};
973 auto run = [](
int nThreads) {
974 Rig<ITSNLayers> rig{o2::detectors::DetID::ITS, SurfaceKind::Cylinder, nThreads};
975 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
976 rig.params[0].LayerxX0[0] = 0.005f;
977 rig.params[0].LayerxX0[1] = 0.005f;
978 rig.establishLayout();
980 const std::array<GlobalMeasurement, 3>
clusters{makeGlobalCluster(3.0f, 0.100f, 0.9f, 0),
981 makeGlobalCluster(4.0f, 0.150f, 1.05f, 0),
982 makeGlobalCluster(5.0f, 0.201f, 1.20f, 0)};
983 loadCandidateClusters(rig,
clusters,
984 {makeBarrelHit(3.f, 0.f, 0.100f, 0.9f),
985 makeBarrelHit(4.f, 0.f, 0.150f, 1.05f),
986 makeBarrelHit(5.f, 0.f, 0.201f, 1.20f)});
988 auto view = prepare(rig);
990 const auto topology = topologyView(rig);
991 const int cellIndex = findCellIndex(topology, 0, 1, 2);
992 BOOST_REQUIRE_GE(cellIndex, 0);
994 injectCandidateTracklets(rig, cellIndex,
clusters);
999 r.cellIndex = cellIndex;
1000 const auto& lut = rig.tf->getCellsLookupTable()[cellIndex];
1001 r.lut.assign(lut.begin(), lut.end());
1002 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1003 const auto& cell = rig.tf->getCells()[cellIndex][0];
1004 r.factor = cell.tripletFactor();
1005 r.cl0 = cell.getFirstClusterIndex();
1006 r.cl1 = cell.getSecondClusterIndex();
1007 r.cl2 = cell.getThirdClusterIndex();
1011 const auto onePass = run(1);
1012 const auto twoPass = run(4);
1015 BOOST_CHECK_EQUAL_COLLECTIONS(onePass.lut.begin(), onePass.lut.end(), twoPass.lut.begin(), twoPass.lut.end());
1016 checkTripletFitFactorEqual(onePass.factor, twoPass.factor);
1024 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
1025 rig.params[0].TrackletMinPt = 0.3f;
1026 rig.establishLayout();
1030 const std::array<GlobalMeasurement, 3>
clusters{makeGlobalCluster(1.0f, 0.5f, -0.4f, 0),
1031 makeGlobalCluster(1.3f, 0.62f, -0.6f, 0),
1032 makeGlobalCluster(1.7f, 0.78f, -1.0f, 0)};
1033 loadCandidateClusters(rig,
clusters,
1034 {makeDiskHit(-0.4f, 1.0f, 0.5f),
1035 makeDiskHit(-0.6f, 1.3f, 0.62f),
1036 makeDiskHit(-1.0f, 1.7f, 0.78f)});
1037 auto view = prepare(rig);
1038 const auto topology = topologyView(rig);
1039 const int cellIndex = findCellIndex(topology, 0, 1, 2);
1040 BOOST_REQUIRE_GE(cellIndex, 0);
1041 injectCandidateTracklets(rig, cellIndex,
clusters);
1043 const auto&
path = topology.getPath(
CellPathId{
static_cast<uint16_t
>(cellIndex)});
1044 const auto&
first = rig.tf->getTracklets()[
path.first.value()][0];
1045 const auto& second = rig.tf->getTracklets()[
path.second.value()][0];
1046 const float deltaLambda = std::abs(std::atan(
first.tanLambda) - std::atan(second.tanLambda));
1047 const float angularTolerance = view.configuration.kernelParameters.nSigmaCut * rig.tf->getEdgeMSAngle(
path.second.value());
1048 BOOST_REQUIRE_GT(deltaLambda, angularTolerance);
1050 const std::array<GlobalMeasurement, 3> measurements{view.layerGlobalMeasurements[0][0],
1051 view.layerGlobalMeasurements[1][0],
1052 view.layerGlobalMeasurements[2][0]};
1055 BOOST_REQUIRE(factor.isValid());
1058 BOOST_CHECK(rig.tf->getCells()[cellIndex].empty());
1065 std::vector<int> lut;
1067 int cl0{-1}, cl1{-1}, cl2{-1};
1070 auto run = [](
int nThreads) {
1071 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk, nThreads};
1072 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
1073 rig.params[0].TrackletMinPt = 0.3f;
1074 rig.establishLayout();
1078 const std::array<GlobalMeasurement, 3>
clusters{makeGlobalCluster(1.0f, 0.5f, -0.4f, 0),
1079 makeGlobalCluster(1.3f, 0.62f, -0.6f, 0),
1080 makeGlobalCluster(1.6f, 0.74f, -0.8f, 0)};
1081 loadCandidateClusters(rig,
clusters,
1082 {makeDiskHit(-0.4f, 1.0f, 0.5f),
1083 makeDiskHit(-0.6f, 1.3f, 0.62f),
1084 makeDiskHit(-0.8f, 1.6f, 0.74f)});
1086 auto view = prepare(rig);
1088 const auto topology = topologyView(rig);
1089 const int cellIndex = findCellIndex(topology, 0, 1, 2);
1090 BOOST_REQUIRE_GE(cellIndex, 0);
1092 injectCandidateTracklets(rig, cellIndex,
clusters);
1097 r.cellIndex = cellIndex;
1098 const auto& lut = rig.tf->getCellsLookupTable()[cellIndex];
1099 r.lut.assign(lut.begin(), lut.end());
1100 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1101 const auto& cell = rig.tf->getCells()[cellIndex][0];
1102 r.factor = cell.tripletFactor();
1103 r.cl0 = cell.getFirstClusterIndex();
1104 r.cl1 = cell.getSecondClusterIndex();
1105 r.cl2 = cell.getThirdClusterIndex();
1109 const auto onePass = run(1);
1110 const auto twoPass = run(4);
1113 BOOST_CHECK_EQUAL_COLLECTIONS(onePass.lut.begin(), onePass.lut.end(), twoPass.lut.begin(), twoPass.lut.end());
1114 checkTripletFitFactorEqual(onePass.factor, twoPass.factor);
1122 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
1123 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
1124 rig.params[0].TrackletMinPt = 0.3f;
1125 rig.establishLayout();
1128 const std::array<GlobalMeasurement, 3>
clusters{makeGlobalCluster(1.0f, 0.5f, -0.4f, 0),
1129 makeGlobalCluster(1.3f, 0.62f, -0.6f, 0),
1130 makeGlobalCluster(1.6f, 0.74f, -0.8f, 0)};
1131 loadCandidateClusters(rig,
clusters,
1132 {makeDiskHit(-0.4f, 1.0f, 0.5f),
1133 makeDiskHit(-0.6f, 1.3f, 0.62f),
1134 makeDiskHit(-0.8f, 1.6f, 0.74f)});
1136 auto view = prepare(rig);
1138 const auto topology = topologyView(rig);
1139 const int cellIndex = findCellIndex(topology, 0, 1, 2);
1140 BOOST_REQUIRE_GE(cellIndex, 0);
1142 injectCandidateTracklets(rig, cellIndex,
clusters);
1145 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1146 const auto firstFactor = rig.tf->getCells()[cellIndex][0].tripletFactor();
1157 injectCandidateTracklets(rig, cellIndex,
clusters);
1160 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1161 checkTripletFitFactorEqual(rig.tf->getCells()[cellIndex][0].tripletFactor(), firstFactor);
1176 Rig<ITSNLayers> rig{o2::detectors::DetID::ITS, SurfaceKind::Cylinder};
1177 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
1179 rig.params[0].LayerxX0[
layer] = 0.005f;
1181 rig.establishLayout();
1189 constexpr std::array<int, 5> layers{0, 1, 2, 3, 4};
1190 constexpr std::array<float, 5> xs{3.f, 4.f, 5.f, 6.f, 7.f};
1191 constexpr std::array<float, 5> ys{0.0009f, 0.0016f, 0.0025f, 0.0036f, 0.0049f};
1192 constexpr std::array<float, 5> zs{0.90f, 1.05f, 1.20f, 1.35f, 1.50f};
1193 std::array<GlobalMeasurement, 5>
clusters;
1194 std::array<TestLocalMeasurement, 5> hits;
1195 for (
size_t i = 0;
i < 5; ++
i) {
1196 clusters[
i] = makeGlobalCluster(xs[
i], ys[
i], zs[
i], 0);
1197 hits[
i] = makeBarrelHit(xs[
i], 0.f, ys[
i], zs[
i]);
1199 loadCandidateClustersAtLayers(rig, layers,
clusters, hits);
1201 auto view = prepare(rig);
1203 const auto topology = topologyView(rig);
1204 injectChainCandidateTracklets(rig, layers,
clusters);
1208 const std::array<std::array<int, 3>, 3> triples{{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}};
1209 std::array<int, 3> topologyIds{};
1210 std::vector<bool> participating(topology.nPaths,
false);
1211 for (
size_t i = 0;
i < triples.size(); ++
i) {
1212 const auto& triple = triples[
i];
1213 const int cellIndex = findCellIndex(topology, triple[0], triple[1], triple[2]);
1214 BOOST_REQUIRE_GE(cellIndex, 0);
1215 topologyIds[
i] = cellIndex;
1216 participating[cellIndex] =
true;
1218 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1219 const auto& producedCell = rig.tf->getCells()[cellIndex][0];
1225 BOOST_REQUIRE_EQUAL(rig.tf->getCellsLookupTable()[cellIndex].size(), 2u);
1230 for (
int i = 0;
i < topology.nPaths; ++
i) {
1231 if (!participating[
i]) {
1237 for (
size_t i = 0;
i < topologyIds.size(); ++
i) {
1238 BOOST_CHECK_EQUAL(rig.tf->getCells()[topologyIds[
i]][0].getLevel(),
static_cast<int>(
i + 1));
1240 BOOST_CHECK(rig.tf->getCellsNeighbours()[topologyIds[
i]].empty());
1243 BOOST_REQUIRE_EQUAL(rig.tf->getCellsNeighbours()[topologyIds[
i]].size(), 1u);
1245 BOOST_CHECK_EQUAL(rig.tf->getCellsNeighboursTopology()[topologyIds[
i]][0], topologyIds[
i - 1]);
1256 Rig<MFTNLayers> rig{o2::detectors::DetID::MFT, SurfaceKind::Disk};
1257 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
1258 rig.params[0].TrackletMinPt = 0.3f;
1259 rig.establishLayout();
1261 constexpr std::array<int, 5> layers{0, 1, 2, 3, 4};
1262 constexpr std::array<float, 5> xs{1.0f, 1.3f, 1.6f, 1.9f, 2.2f};
1263 constexpr std::array<float, 5> ys{0.50f, 0.62f, 0.74f, 0.86f, 0.98f};
1264 constexpr std::array<float, 5> zs{-0.40f, -0.60f, -0.80f, -1.00f, -1.20f};
1265 std::array<GlobalMeasurement, 5>
clusters;
1266 std::array<TestLocalMeasurement, 5> hits;
1267 for (
size_t i = 0;
i < 5; ++
i) {
1268 clusters[
i] = makeGlobalCluster(xs[
i], ys[
i], zs[
i], 0);
1269 hits[
i] = makeDiskHit(zs[
i], xs[
i], ys[
i]);
1271 loadCandidateClustersAtLayers(rig, layers,
clusters, hits);
1273 auto view = prepare(rig);
1275 const auto topology = topologyView(rig);
1276 injectChainCandidateTracklets(rig, layers,
clusters);
1280 const std::array<std::array<int, 3>, 3> triples{{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}};
1281 std::array<int, 3> topologyIds{};
1282 std::vector<bool> participating(topology.nPaths,
false);
1283 for (
size_t i = 0;
i < triples.size(); ++
i) {
1284 const auto& triple = triples[
i];
1285 const int cellIndex = findCellIndex(topology, triple[0], triple[1], triple[2]);
1286 BOOST_REQUIRE_GE(cellIndex, 0);
1287 topologyIds[
i] = cellIndex;
1288 participating[cellIndex] =
true;
1290 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1291 const auto& producedCell = rig.tf->getCells()[cellIndex][0];
1294 BOOST_REQUIRE_EQUAL(rig.tf->getCellsLookupTable()[cellIndex].size(), 2u);
1299 for (
int i = 0;
i < topology.nPaths; ++
i) {
1300 if (!participating[
i]) {
1306 for (
size_t i = 0;
i < topologyIds.size(); ++
i) {
1307 BOOST_CHECK_EQUAL(rig.tf->getCells()[topologyIds[
i]][0].getLevel(),
static_cast<int>(
i + 1));
1309 BOOST_CHECK(rig.tf->getCellsNeighbours()[topologyIds[
i]].empty());
1312 BOOST_REQUIRE_EQUAL(rig.tf->getCellsNeighbours()[topologyIds[
i]].size(), 1u);
1314 BOOST_CHECK_EQUAL(rig.tf->getCellsNeighboursTopology()[topologyIds[
i]][0], topologyIds[
i - 1]);
1327 Rig<ITSNLayers> rig{o2::detectors::DetID::ITS, SurfaceKind::Cylinder};
1328 rig.params[0].MaxChi2ClusterAttachment = 1.e6f;
1329 rig.params[0].MaxHoles = 1;
1330 rig.holeLayers =
LayerMask{
static_cast<uint16_t
>(1u << 1)};
1331 rig.establishLayout();
1333 constexpr std::array<int, 3> layers{0, 2, 3};
1334 const std::array<GlobalMeasurement, 3>
clusters{
1335 makeGlobalCluster(3.f, 0.10f, 0.90f, 0),
1336 makeGlobalCluster(5.f, 0.20f, 1.20f, 0),
1337 makeGlobalCluster(6.f, 0.25f, 1.35f, 0)};
1338 const std::array<TestLocalMeasurement, 3> hits{
1339 makeBarrelHit(3.f, 0.f, 0.10f, 0.90f),
1340 makeBarrelHit(5.f, 0.f, 0.20f, 1.20f),
1341 makeBarrelHit(6.f, 0.f, 0.25f, 1.35f)};
1342 loadCandidateClustersAtLayers(rig, layers,
clusters, hits);
1344 auto view = prepare(rig);
1346 const auto topology = topologyView(rig);
1347 injectChainCandidateTracklets(rig, layers,
clusters);
1351 const int cellIndex = findCellIndex(topology, 0, 2, 3);
1352 BOOST_REQUIRE_GE(cellIndex, 0);
1353 BOOST_REQUIRE_EQUAL(rig.tf->getCells()[cellIndex].size(), 1u);
1354 const auto& producedCell = rig.tf->getCells()[cellIndex][0];
1357 BOOST_REQUIRE_EQUAL(rig.tf->getCellsLookupTable()[cellIndex].size(), 2u);
1361 for (
int i = 0;
i < topology.nPaths; ++
i) {
1362 if (
i != cellIndex) {
header::DataOrigin origin
Definition of the ITSMFT compact cluster.
Shared CA tracking configuration for ITS and MFT.
Passive common TimeFrame owner.
Runtime-plan-owned, detector-neutral CA workspace.
GPU-portable whole-track seed for common CA tracking.
int ID
Detector identifiers: continuous, starting from 0.
UShort_t getSensorID() const
static constexpr unsigned short InvalidPatternID
const SurfaceTrackState & state
static constexpr int MaxSurfaces
void setNThreads(int n, std::shared_ptr< tbb::task_arena > &arena)
Shared CA tracker traits: same ITS-style tracklet/cell/road logic; MFT uses x-y LUT and forward refit...
GLfloat GLfloat GLfloat alpha
GLsizei const GLfloat * value
GLenum const GLfloat * params
GLsizei const GLchar *const * path
GLenum GLuint GLint GLint layer
GLdouble GLdouble GLdouble z
TrackingPlan makeTrackingPlan(const TrackingParameters ¶meters)
constexpr int ITSNLayers
ITS CA layer count.
constexpr uint32_t MaxLayoutSurfaces
bool makeTripletFitFactor(const std::array< GlobalMeasurement, 3 > &measurements, TripletFitFactor &factor) noexcept
BOOST_AUTO_TEST_CASE(Cluster_messageable)
std::unique_ptr< GPUReconstructionTimeframe > tf
SurfaceCatalogView catalog
std::shared_ptr< BoundedMemoryResource > memoryPool
static IterationContext prepare(Tracker &tracker, TimeFrame &frame, int iteration, std::array< gsl::span< const GlobalMeasurement >, MaxLayoutSurfaces > &measurementSpans)
static void computeCells(TrackerTraits &traits, IterationContext &view)
static bool buildTrackSeed(TrackerTraits &traits, IterationContext &view, int cellPathId, const Triplet &cell, TrackSeed &output)
static void findNeighbours(TrackerTraits &traits, IterationContext &view)
coder decode(ctfImage, triggersD, clustersD)
std::vector< Cluster > clusters
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())