31#define BOOST_TEST_MODULE ITSMFT GenericTrack
32#define BOOST_TEST_MAIN
33#define BOOST_TEST_DYN_LINK
34#include <boost/test/unit_test.hpp>
68 track.innerState.kind = SurfaceKind::Cylinder;
69 track.outerState.kind = SurfaceKind::Cylinder;
72 track.hitLayers.set(0);
73 track.firstClusterRef = 0;
74 track.clusterRefEnd = 1;
87 static_assert(std::is_trivially_copyable_v<GenericTrack>);
90 static_assert(std::is_standard_layout_v<TrackClusterReference>);
91 static_assert(std::is_trivially_copyable_v<TrackClusterReference>);
92 static_assert(std::is_trivially_copyable_v<o2::its::TimeStamp>);
132 single.clusterRefEnd = 1;
140 multi.clusterRefEnd = 4;
152 withHole.clusterRefEnd = 2;
153 withHole.hitLayers.set(0);
154 withHole.hitLayers.set(2);
164 pastEnd.clusterRefEnd = 6;
169 exactlyAtSize.clusterRefEnd = 5;
174 reversed.clusterRefEnd = 1;
186class FakeClusterDecoder
193 gsl::span<const unsigned char>::iterator& patterns,
201 decoded.global = {
static_cast<float>(sensorID),
static_cast<float>(cluster.
getRow()),
static_cast<float>(cluster.
getCol())};
202 decoded.cylinderFrame = {10.f + sensorID, 1.f, 2.f, 0.1f};
203 decoded.rowColumnCovariance = {clusterData.sig2Row, 0.f, clusterData.sig2Col};
204 decoded.nPixels = clusterData.nPixels;
205 decoded.layer = sensorID;
216 std::vector<SurfaceDescriptor> surfaces;
226BuiltLayout makeCombinedLayout()
228 std::vector<SurfaceDescriptor> surfaces;
233 const std::vector<uint16_t> componentOffsets = {0, 3};
237constexpr std::array<unsigned char, 3> onePixelPattern{1, 1, 0x80};
239std::vector<unsigned char> makePatternBytes(
size_t nClusters)
241 std::vector<unsigned char> bytes;
242 bytes.reserve(
nClusters * onePixelPattern.size());
244 bytes.insert(bytes.end(), onePixelPattern.begin(), onePixelPattern.end());
260void loadThreeMeasurementFrame(
TimeFrame& frame,
const BuiltLayout& layout,
261 std::vector<std::vector<uint32_t>>* externalIndicesBySurface =
nullptr,
262 std::vector<std::vector<uint32_t>>* clusterSizesBySurface =
nullptr)
266 0, 0, std::make_shared<BoundedMemoryResource>()));
268 const std::vector<CompClusterExt> itsClusters{
272 const auto itsPatterns = makePatternBytes(itsClusters.size());
273 const std::vector<ROFRecord> itsRofs{
ROFRecord{{0, 0}, 0, 0, 2}};
274 const std::array<LayerId, 2> itsLayerToSurface{
LayerId{0},
LayerId{1}};
275 static const FakeClusterDecoder itsDecoder{o2::detectors::DetID::ITS,
false};
278 const auto mftPatterns = makePatternBytes(mftClusters.size());
279 const std::vector<ROFRecord> mftRofs{
ROFRecord{{0, 0}, 0, 0, 1}};
280 const std::array<LayerId, 1> mftLayerToSurface{
LayerId{3}};
281 static const FakeClusterDecoder mftDecoder{o2::detectors::DetID::MFT,
true};
283 std::array<test::TestClusterSourceInput, 2>
sources{};
285 sources[0].detector = o2::detectors::DetID::ITS;
286 sources[0].clusters = itsClusters;
287 sources[0].patterns = itsPatterns;
289 sources[0].dictionary = &dict();
290 sources[0].layerToSurface = itsLayerToSurface;
292 sources[0].setDecoder(itsDecoder);
295 sources[1].detector = o2::detectors::DetID::MFT;
296 sources[1].clusters = mftClusters;
297 sources[1].patterns = mftPatterns;
299 sources[1].dictionary = &dict();
300 sources[1].layerToSurface = mftLayerToSurface;
302 sources[1].setDecoder(mftDecoder);
304 BOOST_REQUIRE_NO_THROW(test::loadSources(frame, layout.getCatalog(), gsl::span<const test::TestClusterSourceInput>(
sources), {0, 0},
305 externalIndicesBySurface, clusterSizesBySurface));
312 const auto layout = makeCombinedLayout();
314 loadThreeMeasurementFrame(frame, layout);
343 const auto layout = makeCombinedLayout();
345 loadThreeMeasurementFrame(frame, layout);
353 const std::vector<TrackClusterReference> trackClusterIndices{
360 track.firstClusterRef = 0;
361 track.clusterRefEnd =
static_cast<uint32_t
>(trackClusterIndices.size());
362 track.hitLayers.set(0);
363 track.hitLayers.set(1);
364 track.hitLayers.set(3);
365 BOOST_REQUIRE(isValidTrackRange(track,
static_cast<uint32_t
>(trackClusterIndices.size())));
367 bool foundITSZero =
false, foundITSOne =
false, foundMFT =
false;
368 for (uint32_t
i = track.firstClusterRef;
i < track.clusterRefEnd; ++
i) {
369 const auto&
reference = trackClusterIndices[
i];
371 BOOST_REQUIRE(measurement !=
nullptr);
387 const auto layout = makeCombinedLayout();
389 loadThreeMeasurementFrame(frame, layout);
391 const std::vector<TrackClusterReference> trackClusterIndices{
398 track.firstClusterRef = 0;
399 track.clusterRefEnd =
static_cast<uint32_t
>(trackClusterIndices.size());
400 track.hitLayers.set(0);
401 track.hitLayers.set(1);
402 track.hitLayers.set(3);
405 BOOST_REQUIRE(isValidTrackRange(track,
static_cast<uint32_t
>(trackClusterIndices.size())));
406 for (uint32_t
i = track.firstClusterRef;
i < track.clusterRefEnd; ++
i) {
407 const auto&
reference = trackClusterIndices[
i];
409 BOOST_REQUIRE(measurement !=
nullptr);
417 const std::vector<TrackClusterReference> holeIndices{
423 holeTrack.clusterRefEnd = 2;
424 holeTrack.hitLayers.set(0);
425 holeTrack.hitLayers.set(3);
428 BOOST_REQUIRE(isValidTrackRange(holeTrack,
static_cast<uint32_t
>(holeIndices.size())));
429 for (uint32_t
i = holeTrack.firstClusterRef;
i < holeTrack.clusterRefEnd; ++
i) {
432 BOOST_REQUIRE(measurement !=
nullptr);
433 observedHole.set(
reference.layer.value());
447class LegacyLikeDecoder
454 gsl::span<const unsigned char>::iterator& patterns,
462 decoded.global = {
static_cast<float>(sensorID) * 10.f,
static_cast<float>(cluster.
getRow()),
static_cast<float>(cluster.
getCol())};
463 decoded.cylinderFrame = {
static_cast<float>(sensorID) + 100.f,
static_cast<float>(cluster.
getRow()) + 1.f,
static_cast<float>(cluster.
getCol()) + 2.f, 0.01f * sensorID};
464 decoded.rowColumnCovariance = {clusterData.sig2Row, 0.f, clusterData.sig2Col};
465 decoded.nPixels = clusterData.nPixels;
466 decoded.layer = sensorID;
474std::vector<SurfaceDescriptor> makeITSTestCatalog()
476 std::vector<SurfaceDescriptor> surfaces;
484std::vector<LayerId> identitySurfaces(uint16_t nLayers)
494struct TimeFrameFixture {
496 std::vector<std::vector<uint32_t>> externalIndicesBySurface;
497 std::vector<std::vector<uint32_t>> clusterSizesBySurface;
498 std::vector<LayerId> layerMapping{identitySurfaces(
ITSNLayers)};
501 std::vector<SurfaceDescriptor> catalog{makeITSTestCatalog()};
502 LegacyLikeDecoder decoder{o2::detectors::DetID::ITS};
509 BOOST_REQUIRE(
tf.configure(std::move(layout), 0, 0,
510 std::make_shared<BoundedMemoryResource>()));
517 const auto patterns = makePatternBytes(
clusters.size());
518 const std::vector<ROFRecord> rofs{
ROFRecord{{100, 5}, 0, 0, 1}};
519 test::loadTimeFrameSource(tf, decoder, origin, timing,
clusters, patterns, rofs, &dict(),
nullptr, o2::detectors::DetID::ITS,
520 gsl::span<const LayerId>{layerMapping},
tf.getDetectorConfiguration().getSurfaceCatalog(),
521 &externalIndicesBySurface, &clusterSizesBySurface);
525struct TestGenericTrack {
527 std::vector<TrackClusterReference> references;
530TestGenericTrack makeTestGenericTrack()
532 TestGenericTrack record;
533 record.track.innerState.kind = SurfaceKind::Cylinder;
534 record.track.outerState.kind = SurfaceKind::Cylinder;
535 record.track.timestamp = {120.f, 20.f};
536 record.track.hitLayers.set(0);
537 record.references.push_back({
LayerId{0}, 0, 0});
541uint32_t storeTestGenericTrack(
TimeFrame& frame, TestGenericTrack record)
558 track.firstClusterRef = 0;
559 track.clusterRefEnd = 2;
560 track.hitLayers.set(0);
561 track.hitLayers.set(1);
562 tf.getGenericTracks().push_back(track);
570 TimeFrameFixture fixture;
571 BOOST_REQUIRE_NO_THROW(fixture.load());
573 populateCommonResults(fixture.tf);
574 BOOST_REQUIRE_EQUAL(fixture.tf.getGenericTracks().size(), 1u);
575 BOOST_REQUIRE_EQUAL(fixture.tf.getTrackLabels().size(), 1u);
576 BOOST_REQUIRE_EQUAL(fixture.tf.getTrackClusterIndices().size(), 2u);
581 BOOST_REQUIRE_NO_THROW(fixture.load());
582 BOOST_CHECK(fixture.tf.getGenericTracks().empty());
584 BOOST_CHECK(fixture.tf.getTrackClusterIndices().empty());
589 TimeFrameFixture fixture;
590 BOOST_REQUIRE_NO_THROW(fixture.load());
592 populateCommonResults(fixture.tf);
593 BOOST_REQUIRE_EQUAL(fixture.tf.getGenericTracks().size(), 1u);
594 BOOST_REQUIRE_EQUAL(fixture.tf.getTrackLabels().size(), 1u);
595 BOOST_REQUIRE_EQUAL(fixture.tf.getTrackClusterIndices().size(), 2u);
596 BOOST_REQUIRE(fixture.tf.getTotalMeasurements() > 0u);
601 const auto patterns = makePatternBytes(
clusters.size());
602 const std::vector<ROFRecord> rofs{
ROFRecord{{200, 5}, 0, 0, 1}};
603 const auto& orderedSurfaces = fixture.layerMapping;
604 BOOST_CHECK_EXCEPTION(test::loadTimeFrameSource(fixture.tf, fixture.decoder, fixture.origin, fixture.timing,
clusters, patterns, rofs,
605 &dict(),
nullptr, o2::detectors::DetID::TPC,
606 gsl::span<const LayerId>{orderedSurfaces}, fixture.tf.getDetectorConfiguration().getSurfaceCatalog()),
607 std::runtime_error, [](
const std::runtime_error& error) {
return std::string(error.what()).find(
"Unsupported source detector") != std::string::npos; });
610 BOOST_CHECK(fixture.tf.getGenericTracks().empty());
612 BOOST_CHECK(fixture.tf.getTrackClusterIndices().empty());
618 populateCommonResults(
tf);
620 BOOST_REQUIRE_EQUAL(
tf.getGenericTracks().size(), 1u);
621 BOOST_REQUIRE_EQUAL(
tf.getTrackLabels().size(), 1u);
622 BOOST_REQUIRE_EQUAL(
tf.getTrackClusterIndices().size(), 2u);
623 BOOST_REQUIRE(isValidTrackRange(
tf.getGenericTracks()[0],
static_cast<uint32_t
>(
tf.getTrackClusterIndices().size())));
637 reloaded.clusterRefEnd = 1;
638 tf.getGenericTracks().push_back(reloaded);
655 for (
const auto& interval : std::array<o2::its::TimeEstBC, 2>{{{5, 9}, {0, 100000}}}) {
656 const auto expected = interval.makeSymmetrical();
665 TimeFrameFixture fixture;
666 BOOST_REQUIRE_NO_THROW(fixture.load());
668 auto later = makeTestGenericTrack();
669 later.track.timestamp = {220.f, 20.f};
670 later.track.chi2 = 1.f;
671 auto earlier = makeTestGenericTrack();
672 earlier.track.timestamp = {120.f, 20.f};
673 earlier.track.chi2 = 2.f;
679 const std::vector<uint32_t> selection{0u, 1u};
681 BOOST_REQUIRE(ordered);
682 BOOST_REQUIRE_EQUAL(ordered->size(), 2u);
700 BOOST_REQUIRE(ordered);
701 const std::vector<uint32_t>
expected{1, 2, 0};
702 BOOST_CHECK_EQUAL_COLLECTIONS(ordered->begin(), ordered->end(),
expected.begin(),
expected.end());
706 for (
const auto& timestamp : std::array<o2::its::TimeStamp, 4>{{{0.f, 0.f}, {1.f, -1.f}, {std::numeric_limits<float>::infinity(), 1.f}, {1.f, std::numeric_limits<float>::quiet_NaN()}}}) {
714 for (
const uint32_t
length : {9u, 10u}) {
717 legacy.mROFLength =
length;
718 legacy.mROFDelay = 3;
721 for (
const auto& interval : intervals) {
722 const auto timestamp = interval.makeSymmetrical();
724 if (
expected.getTimeStampError() > legacy.mROFLength * .5f) {
725 expected.setTimeStampError(legacy.mROFLength * .5f);
737 TimeFrameFixture fixture;
738 BOOST_REQUIRE_NO_THROW(fixture.load());
739 const auto record = makeTestGenericTrack();
740 storeTestGenericTrack(fixture.tf, record);
741 const auto surfaces = gsl::span<const LayerId>{fixture.layerMapping};
743 BOOST_REQUIRE(selected);
744 BOOST_REQUIRE_EQUAL(selected->size(), 1u);
746 const std::array<LayerId, 1> foreignSurfaces{
LayerId{3}};
748 BOOST_REQUIRE(foreign);
750 const auto refs = fixture.tf.getTrackClusterIndices().size();
751 fixture.tf.getGenericTracks()[0].clusterRefEnd = refs + 1;
753 fixture.tf.getGenericTracks()[0].clusterRefEnd = refs;
754 fixture.tf.getTrackClusterIndices()[0].layer = LayerId::invalid();
764 clock.mROFLength = 40;
765 clock.mROFDelay = 100;
766 const std::vector<ROFRecord> input{{{100, 5}, 0, 7, 3}, {{100, 6}, 1, 2, 3}};
769 const std::vector<o2::its::TimeStamp>
times{{110.f, 0.f}, {120.f, 0.f}, {150.f, 0.f}, {1000.f, 0.f}};
771 BOOST_REQUIRE_EQUAL(
output.size(), 2u);
776 for (
size_t i = 0;
i < input.size(); ++
i) {
header::DataOrigin origin
std::vector< unsigned long > times
Definition of the ITSMFT compact cluster.
Passive common TimeFrame owner.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Runtime-plan-owned, detector-neutral CA workspace.
int ID
Detector identifiers: continuous, starting from 0.
UShort_t getSensorID() const
static constexpr unsigned short InvalidPatternID
SurfaceCatalogView getSurfaceCatalog() const noexcept
GLuint GLsizei GLsizei * length
uint8_t itsSharedClusterMap uint8_t
constexpr std::array< std::string_view, BasicOp::Conditional+1 > mapping
a map between BasicOp and tokens in string expressions
const bool const int nLayers
const bool const int TrackITSInternal< NLayers > & track
ClusterData< T > extractClusterData(const CompClusterExt &c, gsl::span< const unsigned char >::iterator &patterns, const TopologyDictionary *dict)
std::optional< std::vector< uint32_t > > selectGenericTracksForSurfaces(const TimeFrame &frame, gsl::span< const LayerId > sourceSurfaces)
uint32_t trackClusterIndicesSize noexcept
o2::its::TimeStamp makeOutputTimestamp(o2::its::TimeStamp timestamp, const o2::its::LayerTiming &clock) noexcept
constexpr int ITSNLayers
ITS CA layer count.
void finalizeROFs(std::vector< o2::itsmft::ROFRecord > &rofs, const std::vector< o2::its::TimeStamp > ×, const TrackPublicationTimingContext &context)
std::optional< std::vector< uint32_t > > makeLegacyOutputOrder(const TimeFrame &frame, std::vector< uint32_t > selection, const o2::its::LayerTiming &clock)
BOOST_AUTO_TEST_CASE(Cluster_messageable)
std::unique_ptr< GPUReconstructionTimeframe > tf
SurfaceTrackState outerState
o2::its::TimeStamp timestamp
SurfaceTrackState innerState
auto & getGenericTracks()
auto & getTrackClusterIndices()
bool isConfigured() const noexcept
const SurfaceMeasurement * getSurfaceMeasurement(LayerId layer, uint32_t clusterId) const noexcept
gsl::span< const GlobalMeasurement > getGlobalMeasurements(LayerId surface) const
bool configure(DetectorConfiguration &&layout, std::size_t maxEdges, std::size_t maxCells, std::shared_ptr< BoundedMemoryResource > memoryPool)
std::map< std::string, ID > expected
coder decode(ctfImage, triggersD, clustersD)
std::vector< Cluster > clusters
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())