Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-20 08:19:53

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/EventData/SeedContainer.hpp"
0013 #include "Acts/EventData/SpacePointContainer.hpp"
0014 #include "Acts/Seeding/GbtsGeometry.hpp"
0015 #include "Acts/Seeding/GbtsLayerConnection.hpp"
0016 #include "Acts/Seeding/GbtsRoiDescriptor.hpp"
0017 #include "Acts/Seeding/GbtsTrackingFilter.hpp"
0018 #include "Acts/Seeding/GraphBasedTrackSeeder.hpp"
0019 
0020 #include <algorithm>
0021 #include <array>
0022 #include <cmath>
0023 #include <cstdint>
0024 #include <memory>
0025 #include <numbers>
0026 #include <optional>
0027 #include <sstream>
0028 #include <string>
0029 #include <utility>
0030 #include <vector>
0031 
0032 // Regression harness for the GBTS seeding chain, which has no other test
0033 // coverage. The expected values are recorded from the current implementation,
0034 // not derived independently: they detect behaviour changes, not physics errors.
0035 
0036 namespace Acts::Test {
0037 
0038 namespace {
0039 
0040 using namespace Acts::UnitLiterals;
0041 using Experimental::GbtsLayerType;
0042 
0043 /// Half-length in z of every barrel layer, reused as the z0 and RoI z range.
0044 constexpr float kBarrelHalfZ = 150.f;
0045 
0046 /// Radial extent of every endcap disc.
0047 constexpr float kDiscMinR = 30.f;
0048 constexpr float kDiscMaxR = 220.f;
0049 
0050 /// Eta bin width declared by the connector table, as in createLinkingScheme.py.
0051 constexpr float kEtaBinWidth = 0.2f;
0052 
0053 /// One layer of the toy detector. GBTS reads the subdetector off the layer id:
0054 /// 8xxxx is barrel, 9xxxx the positive and 7xxxx the negative endcap. 80000 is
0055 /// the innermost barrel layer (extra z0 cuts), barrel ids 1000 apart are
0056 /// adjacent.
0057 struct LayerSpec {
0058   std::int32_t id{};
0059   GbtsLayerType type{};
0060   /// r for a barrel layer, z for an endcap disc.
0061   float refCoord{};
0062   /// z range for a barrel layer, r range for an endcap disc.
0063   float minBound{};
0064   float maxBound{};
0065 };
0066 
0067 constexpr LayerSpec barrelLayer(std::int32_t id, float radius) {
0068   return {id, GbtsLayerType::Barrel, radius, -kBarrelHalfZ, kBarrelHalfZ};
0069 }
0070 
0071 constexpr LayerSpec discLayer(std::int32_t id, float z) {
0072   return {id, GbtsLayerType::Endcap, z, kDiscMinR, kDiscMaxR};
0073 }
0074 
0075 /// Layers plus the connector links between them, outer (src) to inner (dst).
0076 struct ToyDetector {
0077   std::vector<LayerSpec> layers;
0078   std::vector<std::pair<std::int32_t, std::int32_t>> links;
0079   /// Outer radius bound used by the doublet rz filter.
0080   float maxOuterRadius{};
0081 };
0082 
0083 ToyDetector barrelDetector() {
0084   return {{barrelLayer(80000, 40.f), barrelLayer(81000, 80.f),
0085            barrelLayer(82000, 120.f), barrelLayer(83000, 160.f)},
0086           {{81000, 80000}, {82000, 81000}, {83000, 82000}},
0087           200.f};
0088 }
0089 
0090 /// Barrel plus both endcaps. The discs are spaced so that every track in the
0091 /// tau range of makeForwardTracks crosses at least four layers.
0092 ToyDetector forwardDetector() {
0093   constexpr std::array<float, 4> discZ = {200.f, 260.f, 320.f, 380.f};
0094 
0095   ToyDetector detector = barrelDetector();
0096   detector.maxOuterRadius = 300.f;
0097 
0098   for (const std::int32_t idBase : {90000, 70000}) {
0099     const float sign = idBase == 90000 ? 1.f : -1.f;
0100     std::int32_t previousId = 0;
0101 
0102     for (std::size_t i = 0; i < discZ.size(); ++i) {
0103       const std::int32_t id = idBase + 1000 * static_cast<std::int32_t>(i);
0104       detector.layers.push_back(discLayer(id, sign * discZ[i]));
0105 
0106       if (i == 0) {
0107         // a track reaching the first disc still has hits in one of these
0108         // barrel layers, never in 83000
0109         for (const std::int32_t innerId : {80000, 81000, 82000}) {
0110           detector.links.emplace_back(id, innerId);
0111         }
0112       } else {
0113         detector.links.emplace_back(id, previousId);
0114       }
0115       previousId = id;
0116     }
0117   }
0118 
0119   return detector;
0120 }
0121 
0122 /// Connector table for GbtsLayerConnectionMap::fromStream: `nLinks etaBinWidth`
0123 /// then `lIdx stage src dst height width nEntries` per link. height = width = 0
0124 /// leaves out the bin table and the stage column does not fix the processing
0125 /// order: GbtsGeometry rederives both from the layer geometry.
0126 std::string makeConnectorText(const ToyDetector& detector) {
0127   std::ostringstream os;
0128   os << detector.links.size() << " " << kEtaBinWidth << "\n";
0129   for (std::size_t i = 0; i < detector.links.size(); ++i) {
0130     const auto& [src, dst] = detector.links[i];
0131     os << i << " " << i << " " << src << " " << dst << " 0 0 0\n";
0132   }
0133   return os.str();
0134 }
0135 
0136 std::shared_ptr<Experimental::GbtsGeometry> makeGeometry(
0137     const ToyDetector& detector) {
0138   std::vector<Experimental::GbtsLayerDescription> layers;
0139   layers.reserve(detector.layers.size());
0140   for (const LayerSpec& spec : detector.layers) {
0141     Experimental::GbtsLayerDescription layer;
0142     layer.id = spec.id;
0143     layer.type = spec.type;
0144     layer.refCoord = spec.refCoord;
0145     layer.minBound = spec.minBound;
0146     layer.maxBound = spec.maxBound;
0147     layers.push_back(layer);
0148   }
0149 
0150   const std::string connectorText = makeConnectorText(detector);
0151   std::istringstream stream{connectorText};
0152   return std::make_shared<Experimental::GbtsGeometry>(
0153       layers, Experimental::GbtsLayerConnectionMap::fromStream(stream, false));
0154 }
0155 
0156 /// Straight track from the origin: fixed phi, z = r * tau, tau = cot(theta).
0157 /// Zero curvature and constant tau ratio pass the doublet and triplet cuts.
0158 struct Track {
0159   float phi{};
0160   float tau{};
0161 };
0162 
0163 /// Radius and z where the track crosses the layer, empty if it misses it.
0164 std::optional<std::pair<float, float>> intersect(const LayerSpec& layer,
0165                                                  const Track& track) {
0166   if (layer.type == GbtsLayerType::Barrel) {
0167     const float z = layer.refCoord * track.tau;
0168     if (z < layer.minBound || z > layer.maxBound) {
0169       return std::nullopt;
0170     }
0171     return std::make_pair(layer.refCoord, z);
0172   }
0173 
0174   // a disc is only reachable from the side it sits on
0175   if (track.tau == 0.f || (layer.refCoord > 0.f) != (track.tau > 0.f)) {
0176     return std::nullopt;
0177   }
0178   const float r = layer.refCoord / track.tau;
0179   if (r < layer.minBound || r > layer.maxBound) {
0180     return std::nullopt;
0181   }
0182   return std::make_pair(r, layer.refCoord);
0183 }
0184 
0185 /// Evenly spaced tracks over [phiMin, phiMax] x [tauMin, tauMax].
0186 std::vector<Track> makeTracks(std::size_t nTracks, float phiMin, float phiMax,
0187                               float tauMin, float tauMax) {
0188   std::vector<Track> tracks;
0189   tracks.reserve(nTracks);
0190   for (std::size_t i = 0; i < nTracks; ++i) {
0191     const float frac = static_cast<float>(i) / nTracks;
0192     Track track;
0193     // half a step offset so a full phi range has no track on the wrap-around
0194     track.phi = phiMin + (phiMax - phiMin) * (frac + 0.5f / nTracks);
0195     track.tau = tauMin + (tauMax - tauMin) * frac;
0196     tracks.push_back(track);
0197   }
0198   return tracks;
0199 }
0200 
0201 /// Far apart in phi and tau: no cross-track edges, one clean seed per track.
0202 /// |tau| below 150/160 keeps every hit inside the barrel z bounds.
0203 std::vector<Track> makeSparseTracks() {
0204   return makeTracks(12, -std::numbers::pi_v<float>, std::numbers::pi_v<float>,
0205                     -0.6f, 0.6f);
0206 }
0207 
0208 /// Close enough in phi and tau for cross-track edges, so the graph
0209 /// combinatorics, the tracking filter and clone removal all do real work.
0210 std::vector<Track> makeDenseTracks() {
0211   return makeTracks(40, -0.05f, 0.05f, -0.05f, 0.05f);
0212 }
0213 
0214 /// Well separated tracks over both endcaps. The tau range starts in the
0215 /// barrel-endcap transition, where a seed mixes layer types, and ends where the
0216 /// barrel is missed entirely.
0217 std::vector<Track> makeForwardTracks() {
0218   constexpr float pi = std::numbers::pi_v<float>;
0219   std::vector<Track> tracks = makeTracks(8, -pi, 0.f, 1.05f, 6.3f);
0220   const std::vector<Track> negative = makeTracks(8, 0.f, pi, -1.05f, -6.3f);
0221   tracks.insert(tracks.end(), negative.begin(), negative.end());
0222   return tracks;
0223 }
0224 
0225 /// Dense forward tracks, all crossing the innermost barrel layer and all four
0226 /// discs of the positive endcap.
0227 std::vector<Track> makeDenseForwardTracks() {
0228   return makeTracks(20, -0.05f, 0.05f, 1.9f, 2.1f);
0229 }
0230 
0231 /// One hit per crossed layer per track, in the container layout
0232 /// GraphBasedSeedingAlgorithm::makeSpContainer produces. `trackId` is test-only
0233 /// bookkeeping: with endcaps the number of hits varies per track.
0234 SpacePointContainer makeSpacePoints(const ToyDetector& detector,
0235                                     const std::vector<Track>& tracks) {
0236   SpacePointContainer container(SpacePointColumns::CopiedFromIndex |
0237                                 SpacePointColumns::X | SpacePointColumns::Y |
0238                                 SpacePointColumns::Z | SpacePointColumns::R |
0239                                 SpacePointColumns::Phi);
0240 
0241   auto layerColumn = container.createColumn<std::uint32_t>("layerId");
0242   auto clusterWidthColumn = container.createColumn<float>("clusterWidth");
0243   auto localPositionColumn = container.createColumn<float>("localPositionY");
0244   auto trackColumn = container.createColumn<std::uint32_t>("trackId");
0245 
0246   container.reserve(tracks.size() * detector.layers.size());
0247 
0248   for (std::size_t track = 0; track < tracks.size(); ++track) {
0249     for (std::size_t layer = 0; layer < detector.layers.size(); ++layer) {
0250       const auto crossing = intersect(detector.layers[layer], tracks[track]);
0251       if (!crossing.has_value()) {
0252         continue;
0253       }
0254       const auto [r, z] = *crossing;
0255 
0256       auto sp = container.createSpacePoint();
0257       sp.x() = r * std::cos(tracks[track].phi);
0258       sp.y() = r * std::sin(tracks[track].phi);
0259       sp.z() = z;
0260       sp.r() = r;
0261       sp.phi() = tracks[track].phi;
0262       sp.copiedFromIndex() = sp.index();
0263       // the dense layer index, not the GBTS layer id
0264       sp.extra(layerColumn) = static_cast<std::uint32_t>(layer);
0265       sp.extra(clusterWidthColumn) = 0.f;
0266       sp.extra(localPositionColumn) = 0.f;
0267       sp.extra(trackColumn) = static_cast<std::uint32_t>(track);
0268     }
0269   }
0270 
0271   return container;
0272 }
0273 
0274 SeedContainer runSeeding(const ToyDetector& detector,
0275                          const SpacePointContainer& spacePoints) {
0276   auto geometry = makeGeometry(detector);
0277 
0278   const auto numLayers = static_cast<std::uint32_t>(detector.layers.size());
0279 
0280   Experimental::GraphBasedTrackSeeder::Config config;
0281   config.minPt = 1_GeV;
0282   config.minZ0 = -kBarrelHalfZ;
0283   config.maxZ0 = kBarrelHalfZ;
0284   config.maxOuterRadius = detector.maxOuterRadius;
0285   // the toy setup has no ML lookup table and no cluster widths
0286   config.useMl = false;
0287 
0288   const Experimental::GraphBasedTrackSeeder seeder(
0289       Experimental::GraphBasedTrackSeeder::DerivedConfig(config), geometry,
0290       getDefaultLogger("GbtsTest", Logging::Level::WARNING));
0291 
0292   const Experimental::GbtsTrackingFilter filter(
0293       Experimental::GbtsTrackingFilter::Config{}, geometry);
0294 
0295   const Experimental::GbtsRoiDescriptor roi(0, -4.5, 4.5, 0, -std::numbers::pi,
0296                                             std::numbers::pi, 0, -kBarrelHalfZ,
0297                                             kBarrelHalfZ);
0298 
0299   const Experimental::GraphBasedTrackSeeder::Options options(2_T);
0300 
0301   const std::vector<bool> isPixelLayer(numLayers, true);
0302 
0303   SeedContainer seeds;
0304   seeds.assignSpacePointContainer(spacePoints);
0305 
0306   seeder.createSeeds(spacePoints, roi, isPixelLayer, filter, options, seeds);
0307 
0308   return seeds;
0309 }
0310 
0311 /// One line per seed, `quality:sp,sp,...`, sorted by first space point. The
0312 /// container order is not pinned: seeds are sorted by quality with an unstable
0313 /// sort, so ties come out differently between standard libraries.
0314 std::string formatSeeds(const SeedContainer& seeds) {
0315   std::vector<std::pair<std::uint32_t, std::string>> lines;
0316   for (const auto& seed : seeds) {
0317     const auto indices = seed.spacePointIndices();
0318     std::ostringstream line;
0319     line << seed.quality() << ":";
0320     for (const auto index : indices) {
0321       line << index << ",";
0322     }
0323     lines.emplace_back(indices[0], line.str());
0324   }
0325   std::ranges::sort(lines);
0326 
0327   std::ostringstream os;
0328   for (const auto& entry : lines) {
0329     os << entry.second << "\n";
0330   }
0331   return os.str();
0332 }
0333 
0334 /// Number of hits each track left in the container.
0335 std::vector<std::size_t> hitsPerTrack(const SpacePointContainer& spacePoints,
0336                                       std::size_t nTracks) {
0337   auto trackColumn = spacePoints.column<std::uint32_t>("trackId");
0338   std::vector<std::size_t> counts(nTracks, 0);
0339   for (const auto& sp : spacePoints) {
0340     counts.at(sp.extra(trackColumn)) += 1;
0341   }
0342   return counts;
0343 }
0344 
0345 /// Invariants that hold independently of the recorded values: a seed collects
0346 /// hits of a single track in radial order.
0347 void checkSeedsAreWellFormed(const SeedContainer& seeds,
0348                              const SpacePointContainer& spacePoints) {
0349   auto trackColumn = spacePoints.column<std::uint32_t>("trackId");
0350 
0351   for (const auto& seed : seeds) {
0352     const auto indices = seed.spacePointIndices();
0353     BOOST_REQUIRE_GE(indices.size(), 3u);
0354 
0355     BOOST_REQUIRE_LT(indices[0], spacePoints.size());
0356     const std::uint32_t track = spacePoints.at(indices[0]).extra(trackColumn);
0357 
0358     float previousR = -1.f;
0359     for (const auto index : indices) {
0360       BOOST_REQUIRE_LT(index, spacePoints.size());
0361       const auto sp = spacePoints.at(index);
0362       BOOST_CHECK_EQUAL(sp.extra(trackColumn), track);
0363       BOOST_CHECK_GT(sp.r(), previousR);
0364       previousR = sp.r();
0365     }
0366   }
0367 }
0368 
0369 /// Exactly one seed per track, holding every hit of that track.
0370 void checkOneSeedPerTrack(const SeedContainer& seeds,
0371                           const SpacePointContainer& spacePoints,
0372                           const std::vector<Track>& tracks) {
0373   BOOST_CHECK_EQUAL(seeds.size(), tracks.size());
0374   checkSeedsAreWellFormed(seeds, spacePoints);
0375 
0376   auto trackColumn = spacePoints.column<std::uint32_t>("trackId");
0377   const std::vector<std::size_t> hits =
0378       hitsPerTrack(spacePoints, tracks.size());
0379 
0380   std::vector<std::size_t> seedsPerTrack(tracks.size(), 0);
0381   for (const auto& seed : seeds) {
0382     const auto indices = seed.spacePointIndices();
0383     const std::uint32_t track = spacePoints.at(indices[0]).extra(trackColumn);
0384     BOOST_CHECK_EQUAL(indices.size(), hits.at(track));
0385     seedsPerTrack.at(track) += 1;
0386   }
0387   for (const std::size_t count : seedsPerTrack) {
0388     BOOST_CHECK_EQUAL(count, 1u);
0389   }
0390 }
0391 
0392 }  // namespace
0393 
0394 BOOST_AUTO_TEST_SUITE(GbtsSeeding)
0395 
0396 // Guards the fixture itself: a broken input must not look like a regression.
0397 BOOST_AUTO_TEST_CASE(BarrelInputIsWellFormed) {
0398   const ToyDetector detector = barrelDetector();
0399   const std::vector<Track> tracks = makeSparseTracks();
0400   const SpacePointContainer spacePoints = makeSpacePoints(detector, tracks);
0401 
0402   BOOST_CHECK_EQUAL(spacePoints.size(), tracks.size() * detector.layers.size());
0403 
0404   auto layerColumn = spacePoints.column<std::uint32_t>("layerId");
0405   for (const auto& sp : spacePoints) {
0406     BOOST_CHECK_LT(sp.extra(layerColumn), detector.layers.size());
0407     BOOST_CHECK_LE(std::abs(sp.z()), kBarrelHalfZ);
0408   }
0409 }
0410 
0411 // One seed per track, all four hits, in radial order.
0412 BOOST_AUTO_TEST_CASE(SeedsFromSeparatedTracks) {
0413   const ToyDetector detector = barrelDetector();
0414   const std::vector<Track> tracks = makeSparseTracks();
0415   const SpacePointContainer spacePoints = makeSpacePoints(detector, tracks);
0416 
0417   const SeedContainer seeds = runSeeding(detector, spacePoints);
0418 
0419   checkOneSeedPerTrack(seeds, spacePoints, tracks);
0420 
0421   const std::string expected =
0422       "-10.5:0,1,2,3,\n"
0423       "-10.5:4,5,6,7,\n"
0424       "-10.5:8,9,10,11,\n"
0425       "-10.5:12,13,14,15,\n"
0426       "-10.5:16,17,18,19,\n"
0427       "-10.5:20,21,22,23,\n"
0428       "-10.5:24,25,26,27,\n"
0429       "-10.5:28,29,30,31,\n"
0430       "-10.5:32,33,34,35,\n"
0431       "-10.5:36,37,38,39,\n"
0432       "-10.5:40,41,42,43,\n"
0433       "-10.5:44,45,46,47,\n";
0434   BOOST_CHECK_EQUAL(formatSeeds(seeds), expected);
0435 }
0436 
0437 // Dense tracks put several candidates per node into the sliding window.
0438 BOOST_AUTO_TEST_CASE(SeedsFromDenseTracks) {
0439   const ToyDetector detector = barrelDetector();
0440   const std::vector<Track> tracks = makeDenseTracks();
0441   const SpacePointContainer spacePoints = makeSpacePoints(detector, tracks);
0442 
0443   const SeedContainer seeds = runSeeding(detector, spacePoints);
0444 
0445   // dumped rather than pinned: under heavy branching which candidates survive
0446   // depends on float rounding and differs between platforms
0447   BOOST_TEST_MESSAGE("dense seeds:\n" << formatSeeds(seeds));
0448 
0449   // clone removal resolves the branching back to one complete seed per track
0450   checkOneSeedPerTrack(seeds, spacePoints, tracks);
0451 }
0452 
0453 // Guards the forward fixture: every track must reach the four layers a seed
0454 // needs, and the tau range must straddle the barrel-endcap transition.
0455 BOOST_AUTO_TEST_CASE(ForwardInputIsWellFormed) {
0456   const ToyDetector detector = forwardDetector();
0457   const std::vector<Track> tracks = makeForwardTracks();
0458   const SpacePointContainer spacePoints = makeSpacePoints(detector, tracks);
0459 
0460   for (const std::size_t count : hitsPerTrack(spacePoints, tracks.size())) {
0461     BOOST_CHECK_GE(count, 4u);
0462   }
0463 
0464   auto layerColumn = spacePoints.column<std::uint32_t>("layerId");
0465   auto trackColumn = spacePoints.column<std::uint32_t>("trackId");
0466 
0467   std::vector<bool> hasBarrel(tracks.size(), false);
0468   std::vector<bool> hasEndcap(tracks.size(), false);
0469   for (const auto& sp : spacePoints) {
0470     const LayerSpec& layer = detector.layers.at(sp.extra(layerColumn));
0471     const std::uint32_t track = sp.extra(trackColumn);
0472     if (layer.type == GbtsLayerType::Barrel) {
0473       hasBarrel[track] = true;
0474       BOOST_CHECK_LE(std::abs(sp.z()), kBarrelHalfZ);
0475     } else {
0476       hasEndcap[track] = true;
0477       BOOST_CHECK_GE(sp.r(), kDiscMinR);
0478       BOOST_CHECK_LE(sp.r(), kDiscMaxR);
0479     }
0480   }
0481 
0482   auto isSet = [](bool value) { return value; };
0483   BOOST_CHECK(std::ranges::all_of(hasEndcap, isSet));
0484   BOOST_CHECK(std::ranges::any_of(hasBarrel, isSet));
0485   BOOST_CHECK(!std::ranges::all_of(hasBarrel, isSet));
0486 }
0487 
0488 // Covers the endcap eta binning and the barrel-endcap and endcap-endcap bin
0489 // compatibility. The layer type branches in the tracking filter and in the
0490 // triplet cuts also run, but ideal tracks pass every cut by the same margin, so
0491 // a change there does not move these values.
0492 BOOST_AUTO_TEST_CASE(SeedsFromForwardTracks) {
0493   const ToyDetector detector = forwardDetector();
0494   const std::vector<Track> tracks = makeForwardTracks();
0495   const SpacePointContainer spacePoints = makeSpacePoints(detector, tracks);
0496 
0497   const SeedContainer seeds = runSeeding(detector, spacePoints);
0498 
0499   checkOneSeedPerTrack(seeds, spacePoints, tracks);
0500 
0501   // the five hit seeds are the tracks that clear the barrel early enough to
0502   // cross all four discs
0503   const std::string expected =
0504       "-10.5:0,1,2,3,\n"
0505       "-11.2:4,5,6,7,8,\n"
0506       "-11.2:9,10,11,12,13,\n"
0507       "-11.2:14,15,16,17,18,\n"
0508       "-11.2:19,20,21,22,23,\n"
0509       "-10.5:24,25,26,27,\n"
0510       "-10.5:28,29,30,31,\n"
0511       "-10.5:32,33,34,35,\n"
0512       "-10.5:36,37,38,39,\n"
0513       "-11.2:40,41,42,43,44,\n"
0514       "-11.2:45,46,47,48,49,\n"
0515       "-11.2:50,51,52,53,54,\n"
0516       "-11.2:55,56,57,58,59,\n"
0517       "-10.5:60,61,62,63,\n"
0518       "-10.5:64,65,66,67,\n"
0519       "-10.5:68,69,70,71,\n";
0520   BOOST_CHECK_EQUAL(formatSeeds(seeds), expected);
0521 }
0522 
0523 // Dense forward tracks add the endcap combinatorics on top.
0524 BOOST_AUTO_TEST_CASE(SeedsFromDenseForwardTracks) {
0525   const ToyDetector detector = forwardDetector();
0526   const std::vector<Track> tracks = makeDenseForwardTracks();
0527   const SpacePointContainer spacePoints = makeSpacePoints(detector, tracks);
0528 
0529   const SeedContainer seeds = runSeeding(detector, spacePoints);
0530 
0531   BOOST_TEST_MESSAGE("dense forward seeds:\n" << formatSeeds(seeds));
0532 
0533   checkOneSeedPerTrack(seeds, spacePoints, tracks);
0534 }
0535 
0536 BOOST_AUTO_TEST_SUITE_END()
0537 
0538 }  // namespace Acts::Test