Skip to content

test: Seeding benchmarks on the synthetic event - #5808

Draft
andiwand wants to merge 4 commits into
acts-project:mainfrom
andiwand:test-fatras-synthetic-seeding-benchmarks
Draft

test: Seeding benchmarks on the synthetic event#5808
andiwand wants to merge 4 commits into
acts-project:mainfrom
andiwand:test-fatras-synthetic-seeding-benchmarks

Conversation

@andiwand

@andiwand andiwand commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Four benchmarks on a generated event rather than on a recorded one: the
generator itself, and the grid triplet, orthogonal triplet and GBTS seeders on
what it makes. They share SyntheticEventOptions, so a run of one is the same
event as a run of another and the three seeders are comparable.

Each reports what it found against the generator truth -- seeds, true seeds and
matched primaries above a momentum threshold -- so a change in throughput can be
read next to what it cost in efficiency. The layout, the pile-up, the secondary
rates and the module granularity are all on the command line, which is what
makes the combinatorial load a knob rather than a property of a fixed sample.

--- END COMMIT MESSAGE ---

Fifth in the stack described in #5806; it sits on
feat-fatras-synthetic-odd-layout and includes everything below it, so its diff
here shows those commits too. It is independent of #5807.

Its own change is 2255 lines across 8 files, of which 1728 are the three seeder
benchmarks and 315 the options and triplet cuts they share.

What the benchmarks say today

--layout itk-pixel, pile-up 200, 239k space points, 1376 seedable primaries,
single threaded on a laptop RelWithDebInfo build:

efficiency seeds time
spherical grid 95.9 % 38.4k 1.60 s
cylindrical grid 96.4 % 34.3k 1.99 s
orthogonal k-d tree 96.7 % 32.4k 6.41 s
GBTS 92.2 % 6.6k 0.19 s

Generating the event costs 120 ms, so the generator is not what any of these
measure.

Notes for review

Efficiency is a weak measure here and the four points between GBTS and the
k-d tree should not be read as a ranking. It counts a primary as found when one
seed of it survives, and a primary that crosses every layer of the pixels offers
a seeder many chances at that. Read the times and the candidate pair counts, which each
benchmark reports so that a tuning run can be read without a profiler, and use a
harder measure than "at least one true seed" if efficiency is the question.

A seed counts as true when three of its space points come from one primary,
not when all of them do. The distinction is invisible for the triplet seeders,
whose seeds are always three space points, but GBTS returns four to eleven, and
scoring it on every space point matching costs it four points of efficiency that
say nothing about the seeder.

The GBTS connection table here is written for these layouts, not trained on
them
, so its efficiency is not a statement about GBTS as ATLAS runs it. What it
loses sits at the barrel-endcap transition, which is where a hand-written table is
weakest. The cuts themselves are Athena's: ActsTrk::GbtsSeedingTool overrides
only the connector file, the ML lookup table and minPt, and its remaining
defaults agree with the ACTS ones property by property.

The spherical grid has no ATLAS counterpart to copy from. Its middle-axis
numbers were scanned on this event and each is at the point where efficiency stops
paying for the time it costs; the reasoning is in SphericalGridConfig.

These are benchmarks rather than tests: they are built by
ACTS_BUILD_BENCHMARKS and not run in CI.

@github-actions github-actions Bot added this to the next milestone Jul 30, 2026
@github-actions github-actions Bot added Component - Fatras Affects the Fatras module Component - Documentation Affects the documentation labels Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📊: Physics performance monitoring for f98e36d

Full contents

physmon summary

❗️: Downstream build failure

  • eic-shell EICrecon (cc @acts-project/epic-contacts)

@andiwand
andiwand force-pushed the test-fatras-synthetic-seeding-benchmarks branch 3 times, most recently from 69f2017 to 47aa377 Compare August 1, 2026 06:27
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Public API surface diff

+194 added, 0 breaking.

➕ Added public API

New types / aliases / enums / variables / concepts (27)
  • enums ActsFatras::Synthetic::EnergyLossModel
  • enums ActsFatras::Synthetic::SurfaceShape
  • enums ActsFatras::Synthetic::SurfaceSide
  • type ActsFatras::Synthetic::BandComposition
  • type ActsFatras::Synthetic::BarrelEndcapDescription
  • type ActsFatras::Synthetic::DetectorLayer
  • type ActsFatras::Synthetic::DetectorLayout
  • type ActsFatras::Synthetic::DetectorLayoutBuilder
  • type ActsFatras::Synthetic::DetectorSurface
  • type ActsFatras::Synthetic::DiscDescription
  • type ActsFatras::Synthetic::Event
  • type ActsFatras::Synthetic::EventConfig
  • type ActsFatras::Synthetic::EventGenerator
  • type ActsFatras::Synthetic::EventSummary
  • type ActsFatras::Synthetic::GeneratedParticle
  • type ActsFatras::Synthetic::GenerationConfig
  • type ActsFatras::Synthetic::MaterialConfig
  • type ActsFatras::Synthetic::MeasurementConfig
  • type ActsFatras::Synthetic::PassiveSurfaceDescription
  • type ActsFatras::Synthetic::PropagationConfig
  • type ActsFatras::Synthetic::RingBounds
  • type ActsFatras::Synthetic::SecondaryConfig
  • type ActsFatras::Synthetic::SecondarySamplingConfig
  • type ActsFatras::Synthetic::SeedingSummary
  • type ActsFatras::Synthetic::SimulationConfig
  • type ActsFatras::Synthetic::SurfaceMaterial
  • variables ActsFatras::Synthetic::kNoSurface
New call signatures (incl. defaulted-arg overloads) (42)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addCylinder(float, float, std::uint32_t)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addDisc(SurfaceSide, float, float, float, std::uint32_t)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addDisc(SurfaceSide, float, std::span< const RingBounds >)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addPassiveCylinder(float)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addPassiveCylinder(float, float)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addPassiveCylinder(float, float, float)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addPassiveDisc(SurfaceSide, float)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addPassiveDisc(SurfaceSide, float, float)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::addPassiveDisc(SurfaceSide, float, float, float)
  • ActsFatras::Synthetic::DetectorLayoutBuilder::build()
  • ActsFatras::Synthetic::EventConfig::itkPixelTtbarPu200()
  • ActsFatras::Synthetic::EventConfig::openDataDetectorTtbarPu200()
  • ActsFatras::Synthetic::EventConfig::particleMass() const
  • ActsFatras::Synthetic::EventGenerator::EventGenerator(const DetectorLayout &, const EventConfig &)
  • ActsFatras::Synthetic::EventGenerator::generate()
  • ActsFatras::Synthetic::EventGenerator::generate(Event &)
  • ActsFatras::Synthetic::EventGenerator::reset(std::uint32_t)
  • ActsFatras::Synthetic::GeneratedParticle::primary() const
  • ActsFatras::Synthetic::GenerationConfig::numPrimaries() const
  • ActsFatras::Synthetic::SurfaceMaterial::SurfaceMaterial()
  • ActsFatras::Synthetic::SurfaceMaterial::SurfaceMaterial(const Acts::MaterialSlab &)
  • ActsFatras::Synthetic::SurfaceMaterial::SurfaceMaterial(const BandComposition &, std::vector< float >, const std::vector< float > &, const std::vector< float > &)
  • ActsFatras::Synthetic::SurfaceMaterial::SurfaceMaterial(std::vector< float >, std::vector< Acts::MaterialSlab >)
  • ActsFatras::Synthetic::SurfaceMaterial::at(const float) const
  • ActsFatras::Synthetic::SurfaceMaterial::average() const
  • ActsFatras::Synthetic::SurfaceMaterial::scaleThickness(const float)
  • ActsFatras::Synthetic::evaluateSeeds(const Event &, const Acts::SeedContainer &, float)
  • ActsFatras::Synthetic::evaluateSeeds(const Event &, const Acts::SeedContainer &, float, std::size_t)
  • ActsFatras::Synthetic::generateEvent(const DetectorLayout &, const EventConfig &)
  • ActsFatras::Synthetic::genericDetectorPixelDescription()
  • ActsFatras::Synthetic::itkPixelDescription()
  • ActsFatras::Synthetic::makeGenericDetectorPixelLayout()
  • ActsFatras::Synthetic::makeItkPixelLayout()
  • ActsFatras::Synthetic::makeLayout(const BarrelEndcapDescription &)
  • ActsFatras::Synthetic::makeOpenDataDetectorPixelLayout()
  • ActsFatras::Synthetic::materialSlab(float, float, float, float, float, float)
  • ActsFatras::Synthetic::openDataDetectorPixelDescription()
  • ActsFatras::Synthetic::subdivideRings(std::span< const RingBounds >, std::uint32_t)
  • ActsFatras::Synthetic::summarize(const Event &, float)
  • ActsFatras::Synthetic::uniformRings(float, float, std::uint32_t)
  • ActsFatras::Synthetic::updateSurfaceExtents(DetectorLayout &)
  • ActsFatras::Synthetic::writeEventCsv(const Event &, const DetectorLayout &, const std::string &)
New public data members (125)
  • ActsFatras::Synthetic::BandComposition::ar
  • ActsFatras::Synthetic::BandComposition::molarDensityX0
  • ActsFatras::Synthetic::BandComposition::thickness
  • ActsFatras::Synthetic::BandComposition::z
  • ActsFatras::Synthetic::BarrelEndcapDescription::barrelHalfLengthsZ
  • ActsFatras::Synthetic::BarrelEndcapDescription::barrelMaterials
  • ActsFatras::Synthetic::BarrelEndcapDescription::barrelModules
  • ActsFatras::Synthetic::BarrelEndcapDescription::barrelOverlapOffset
  • ActsFatras::Synthetic::BarrelEndcapDescription::barrelOverlapProbabilities
  • ActsFatras::Synthetic::BarrelEndcapDescription::barrelRadii
  • ActsFatras::Synthetic::BarrelEndcapDescription::beamPipeMaterial
  • ActsFatras::Synthetic::BarrelEndcapDescription::beamPipeRadius
  • ActsFatras::Synthetic::BarrelEndcapDescription::discOverlapOffset
  • ActsFatras::Synthetic::BarrelEndcapDescription::discOverlapProbability
  • ActsFatras::Synthetic::BarrelEndcapDescription::discs
  • ActsFatras::Synthetic::BarrelEndcapDescription::escapeHalfZ
  • ActsFatras::Synthetic::BarrelEndcapDescription::escapeRadius
  • ActsFatras::Synthetic::BarrelEndcapDescription::passiveSurfaces
  • ActsFatras::Synthetic::DetectorLayer::layer
  • ActsFatras::Synthetic::DetectorLayer::maxBound
  • ActsFatras::Synthetic::DetectorLayer::minBound
  • ActsFatras::Synthetic::DetectorLayer::moduleIndex
  • ActsFatras::Synthetic::DetectorLayer::refCoord
  • ActsFatras::Synthetic::DetectorLayer::shape
  • ActsFatras::Synthetic::DetectorLayer::side
  • ActsFatras::Synthetic::DetectorLayout::escapeHalfZ
  • ActsFatras::Synthetic::DetectorLayout::escapeRadius
  • ActsFatras::Synthetic::DetectorLayout::layers
  • ActsFatras::Synthetic::DetectorLayout::surfaces
  • ActsFatras::Synthetic::DetectorSurface::layers
  • ActsFatras::Synthetic::DetectorSurface::material
  • ActsFatras::Synthetic::DetectorSurface::maxBound
  • ActsFatras::Synthetic::DetectorSurface::minBound
  • ActsFatras::Synthetic::DetectorSurface::overlapOffset
  • ActsFatras::Synthetic::DetectorSurface::overlapProbability
  • ActsFatras::Synthetic::DetectorSurface::refCoord
  • ActsFatras::Synthetic::DetectorSurface::shape
  • ActsFatras::Synthetic::DiscDescription::absZ
  • ActsFatras::Synthetic::DiscDescription::material
  • ActsFatras::Synthetic::DiscDescription::rings
  • ActsFatras::Synthetic::Event::particles
  • ActsFatras::Synthetic::Event::spacePoints
  • ActsFatras::Synthetic::EventConfig::bFieldZ
  • ActsFatras::Synthetic::EventConfig::generation
  • ActsFatras::Synthetic::EventConfig::particlePdg
  • ActsFatras::Synthetic::EventConfig::seed
  • ActsFatras::Synthetic::EventConfig::simulation
  • ActsFatras::Synthetic::EventSummary::primaries
  • ActsFatras::Synthetic::EventSummary::primaryHits
  • ActsFatras::Synthetic::EventSummary::secondaries
  • ActsFatras::Synthetic::EventSummary::secondaryHits
  • ActsFatras::Synthetic::EventSummary::seedablePrimaries
  • ActsFatras::Synthetic::EventSummary::spacePoints
  • ActsFatras::Synthetic::GeneratedParticle::charge
  • ActsFatras::Synthetic::GeneratedParticle::d0
  • ActsFatras::Synthetic::GeneratedParticle::eta
  • ActsFatras::Synthetic::GeneratedParticle::generation
  • ActsFatras::Synthetic::GeneratedParticle::numHits
  • ActsFatras::Synthetic::GeneratedParticle::phi
  • ActsFatras::Synthetic::GeneratedParticle::productionRadius
  • … and 65 more

@andiwand
andiwand force-pushed the test-fatras-synthetic-seeding-benchmarks branch 6 times, most recently from 6c96fe8 to aa6b150 Compare August 5, 2026 09:11
@andiwand
andiwand force-pushed the test-fatras-synthetic-seeding-benchmarks branch 3 times, most recently from 27423c3 to f98e36d Compare August 6, 2026 13:16
andiwand and others added 4 commits August 7, 2026 16:32
`ActsFatras::Synthetic` is a second, much smaller fast simulation that shares
none of the Fatras machinery: no tracking geometry, no propagator, no input
data. It fills an `Acts::SpacePointContainer` directly and makes an ATLAS-like
pile-up of 200 in tens of milliseconds, which is what a seeding benchmark needs
and what the propagator-based simulation cannot provide. Space points carry the
layer and the particle they came from, so a caller needs no truth matching.

The geometry is cylinders at a fixed radius and discs at a fixed z as plain
structs, so a helix crosses every surface in closed form. The restriction is on
the shape alone: every cylinder has its own half-length and every disc its own
rings, so a real endcap is described as the staggered discs and rings it is.
Surfaces carry the material their detector's map reports, banded along the
coordinate they extend in, and that material is the whole of the physics model:
`x/X0` scatters and makes electrons, `x/L0` makes nuclear products, and the slab
takes the energy. Nothing is fitted on top of it.

Both material effects displace the *measured* position of a hit and leave the
trajectory a nominal helix -- a scatter by the angle times the lever arm, energy
loss by half the curvature change times that lever arm squared -- which is what
gives a seed the spread a seeder cuts on at a fraction of the cost of stepping.

It is deliberately coarse: a tool for throughput and combinatorics studies
rather than for physics performance. The Generic pixel description ships with
it; the descriptions of real detectors and the configurations fitted to them
follow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMdYgLmPKFybPzSr8wZxhd
The ATLAS ITk pixels transcribed from the ITKLayouts constants, there being no
ACTS ITk geometry to reduce: seventy-five staggered discs carrying ninety-five
rings, the material each surface holds banded along it, and the supports the
layers are carried on.

With it the configuration fitted against a GNN4ITk ttbar dump at a pile-up of
200, on one half of the sample and checked on the other. What it reproduces is
in the group documentation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMdYgLmPKFybPzSr8wZxhd
The Open Data Detector pixels read off the geometry ACTS builds and kept here so
that the layout is available without DD4hep. Positions are of the sensitive
silicon rather than of the layers the ODD declares, a module carrying its sensor
1.8 mm inside the nominal radius, and each of the seven endcap layers is two
staggered single-ring discs rather than one disc of two rings.

With it the configuration fitted against ColliderML at a pile-up of 200, on one
half of the sample and checked on the other. Where it falls short -- the
secondary momentum, the |d0| reach and the forward production -- is in the group
documentation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMdYgLmPKFybPzSr8wZxhd
Four benchmarks on a generated event rather than on a recorded one: the
generator itself, and the grid triplet, orthogonal triplet and GBTS seeders on
what it makes. They share `SyntheticEventOptions`, so a run of one is the same
event as a run of another and the three seeders are comparable.

Each reports what it found against the generator truth -- seeds, true seeds and
matched primaries above a momentum threshold -- so a change in throughput can be
read next to what it cost in efficiency. The layout, the pile-up, the secondary
rates and the module granularity are all on the command line, which is what
makes the combinatorial load a knob rather than a property of a fixed sample.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMdYgLmPKFybPzSr8wZxhd
@andiwand
andiwand force-pushed the test-fatras-synthetic-seeding-benchmarks branch from f98e36d to f6aed53 Compare August 7, 2026 14:38
@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 New Bugs (required ≤ 0)
B Reliability Rating on New Code (required ≥ A)
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component - Documentation Affects the documentation Component - Fatras Affects the Fatras module Public API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant