Skip to content

feat: Composable vertex position generators with event number#5308

Draft
paulgessinger wants to merge 8 commits intoacts-project:mainfrom
paulgessinger:feat/composable-vertex-generators
Draft

feat: Composable vertex position generators with event number#5308
paulgessinger wants to merge 8 commits intoacts-project:mainfrom
paulgessinger:feat/composable-vertex-generators

Conversation

@paulgessinger
Copy link
Copy Markdown
Member

Summary

  • Extends PrimaryVertexPositionGenerator interface to receive the event number, enabling vertex generators that vary their output over time
  • Adds AdditiveVertexPositionGenerator that composes multiple generators by summing their outputs
  • Adds LumiBlockVertexPositionGenerator that produces a beamspot offset constant within a configurable luminosity block, changing between blocks via a deterministic PRNG seeded by block number
  • Includes Python bindings for both new generators

Example usage (Python)

vtxGen = acts.examples.AdditiveVertexGenerator(
    generators=[
        acts.examples.GaussianVertexGenerator(
            stddev=acts.Vector4(0.0125 * u.mm, 0.0125 * u.mm, 55.5 * u.mm, 1.0 * u.ns),
        ),
        acts.examples.LumiBlockVertexGenerator(
            blockSize=1000,
            stddev=acts.Vector4(0.01 * u.mm, 0.01 * u.mm, 1.0 * u.mm, 0.0),
        ),
    ]
)

Test plan

  • Verify existing vertex generator behavior is unchanged (event number parameter is ignored by all existing generators)
  • Test AdditiveVertexGenerator composition in Python
  • Test LumiBlockVertexGenerator produces consistent offsets within a block and different offsets across blocks

🤖 Generated with Claude Code

…port

Extend PrimaryVertexPositionGenerator interface to receive the event
number, enabling generators that vary their output over time. Add two
new generators:

- AdditiveVertexPositionGenerator: composes multiple generators by
  summing their outputs, allowing layered vertex smearing strategies.
- LumiBlockVertexPositionGenerator: produces a beamspot offset that is
  constant within a configurable luminosity block and changes between
  blocks using a deterministic PRNG seeded by block number.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the Component - Examples Affects the Examples module label Apr 1, 2026
@github-actions github-actions bot added this to the next milestone Apr 1, 2026
paulgessinger and others added 2 commits April 1, 2026 16:52
…xGenerator

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bind PrimaryVertexPositionGenerator.__call__ to Python so generators
can be invoked directly in tests. Add tests that verify:
- FixedVertexGenerator returns the configured position
- GaussianVertexGenerator produces varying positions
- AdditiveVertexGenerator sums constituent outputs correctly
- LumiBlockVertexGenerator is consistent within a block and varies
  across blocks
- Composed Gaussian + LumiBlock generator behaves correctly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
std::size_t eventNumber) const override {
std::size_t block = eventNumber / blockSize;
// Deterministic per block: same block always gives the same offset.
std::mt19937 blockRng(block);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even simpler than I imagined it first. should we allow to inject a seed here / actually inject the user provided seed somehow?

or get a random number from the central RNG+seed and use it as a seed here overall

Copy link
Copy Markdown
Member Author

@paulgessinger paulgessinger Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's probably a good call. We just need to make sure it generates the exact same offset inside the block. Ideally the global seed that is passed in via the RNG instance should be respected.

@andiwand andiwand marked this pull request as draft April 1, 2026 15:02
paulgessinger and others added 2 commits April 2, 2026 09:02
Wraps another vertex generator and applies a deterministic per-lumi-block
rotation (beam tilt) to its spatial output. The tilt angles around x and y
are drawn from Gaussians seeded by a salted block number, so they are
uncorrelated with LumiBlockVertexPositionGenerator when using the same
block size.

Includes Python bindings and tests verifying per-block consistency,
length preservation, seed decorrelation, and full composition with
Gaussian + tilt + positional shift.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Missed call site that also invokes the vertex generator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

📊: Physics performance monitoring for 3500352

Full contents

physmon summary

paulgessinger and others added 3 commits April 2, 2026 12:03
Replace the RandomEngine typedef (std::mt19937) with a thin wrapper class
that stores the seed it was constructed with. This lets lumi-block vertex
generators derive deterministic, user-seed-dependent per-block RNG seeds
via boost::hash_combine(rng.seed(), blockNumber).

The wrapper satisfies UniformRandomBitGenerator so all existing code
(distributions, templates, function signatures) works unchanged.

Update LumiBlockVertexPositionGenerator and
LumiBlockRotationVertexPositionGenerator to incorporate rng.seed() into
their per-block seeds, ensuring different user seeds produce different
beamspot trajectories.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add combinedWith(extra) method to RandomEngine that returns a new engine
whose seed is hash_combine(this->seed(), extra). This encapsulates the
seed derivation pattern in one place.

Simplify lumi-block generators to use rng.combinedWith(block) instead of
manual boost::hash_combine calls. The rotation generator chains
rng.combinedWith(block).combinedWith(salt) for decorrelation.

Move boost/functional/hash.hpp include from VertexGenerators.hpp into
RandomNumbers.hpp where the hash logic now lives.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove redundant m_engine() from RandomEngine default constructor initializer list
- Use CTAD for std::normal_distribution in LumiBlockVertexPositionGenerator and LumiBlockRotationVertexPositionGenerator

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 2, 2026

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

Labels

Component - Examples Affects the Examples module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants