Skip to content

feat(data-model): add EventHeader for per-event weight and provenance#17

Open
matclim wants to merge 1 commit into
ShipSoft:mainfrom
matclim:header
Open

feat(data-model): add EventHeader for per-event weight and provenance#17
matclim wants to merge 1 commit into
ShipSoft:mainfrom
matclim:header

Conversation

@matclim

@matclim matclim commented Jul 17, 2026

Copy link
Copy Markdown

Add SHiP::EventHeader, a per-event metadata record carrying an event weight and the id of the originating event.

The weight (default 1.0) supports weighted generation such as forced or oversampled muon DIS, where each replica of a source muon is written as its own event and down-weighted accordingly. originalEventId (default -1) records which source event a replica came from — event-level provenance, distinct from MCParticle::motherId, which links particles within an event.

The struct is a single per-event record like SimResult, so it is registered in the ROOT dictionary without a std::vector counterpart, and added to both the installed header set and the dictionary inputs. RNTuple and TTree round-trip tests cover it, and the TTree dictionary-presence check now includes SHiP::EventHeader. Purely additive: existing classes and files are unchanged, so old files simply lack the new field.

Summary by CodeRabbit

  • New Features

    • Added SHiP::EventHeader to store per-event metadata, including event weight and originalEventId provenance.
    • Exposed the new event metadata type via the public library interface and ensured it’s supported for ROOT dictionary-based I/O.
  • Documentation

    • Updated the README “Data classes” table to include SHiP::EventHeader under event metadata.
  • Tests

    • Extended ROOT TTree and RNTuple round-trip tests to write and verify EventHeader values correctly.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds SHiP::EventHeader with event weight and parent-event provenance fields, exposes it through CMake and ROOT dictionaries, documents it, and validates TTree and RNTuple persistence with round-trip tests.

Changes

EventHeader integration

Layer / File(s) Summary
EventHeader contract and ROOT registration
include/SHiP/EventHeader.hpp, include/SHiP/LinkDef.h, CMakeLists.txt, README.md
Defines EventHeader, registers it for ROOT dictionary generation, exposes it as a public header, and adds it to the data-class documentation.
EventHeader test helpers
tests/test_utils.hpp
Adds deterministic EventHeader fixtures and equality comparison support.
ROOT round-trip coverage
tests/test_rntuple_io.cpp, tests/test_ttree_io.cpp
Writes, reads, and compares EventHeader values in RNTuple and TTree tests, including dictionary presence and cleanup handling.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Test as Round-trip tests
  participant Utils as test::makeEventHeader
  participant Writer as TTree/RNTuple writer
  participant Storage as ROOT storage
  participant Reader as TTree/RNTuple reader
  participant Compare as test::equal

  Test->>Utils: Create deterministic EventHeader
  Utils-->>Writer: Provide eventHeader values
  Writer->>Storage: Write eventHeader
  Storage-->>Reader: Read eventHeader
  Reader->>Compare: Compare with expected EventHeader
  Compare-->>Test: Return round-trip result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding EventHeader for per-event weight and provenance metadata.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@matclim
matclim requested a review from olantwin July 17, 2026 21:47
@matclim matclim self-assigned this Jul 17, 2026
Comment thread include/SHiP/EventHeader.hpp Outdated
/// Per-event metadata — one record per event
struct EventHeader {
double weight{1.0}; ///< Event weight (e.g. P_DIS / nReplicas)
std::int64_t parentEventId{-1}; ///< Originating event id, e.g. the muon

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.

May I suggest renaming this to original_event_id or something like that?

Comment thread include/SHiP/EventHeader.hpp Outdated

/// Per-event metadata — one record per event
struct EventHeader {
double weight{1.0}; ///< Event weight (e.g. P_DIS / nReplicas)

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.

This should be a fixed-width type for portability. E.g. std::float64_t

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Tried it, but std::float64_t turns out not to be usable in a class that needs a ROOT dictionary. rootcling fails outright:

include/SHiP/EventHeader.hpp:10:8: error: no type named 'float64_t' in namespace 'std'
  std::float64_t weight{1.0};
  ~~~~~^
Error: rootcling: compilation failure (libSHiPDataModel..._dictUmbrella.h)

The cause is a compiler asymmetry. libstdc++'s defines std::float64_t only under #ifdef STDCPP_FLOAT64_T. GCC defines that macro, so the ordinary compile succeeds — but rootcling embeds cling, which is Clang-based and doesn't define it, so the header expands to nothing during dictionary generation and the type doesn't exist. Worth noting std::float64_t is also a distinct type (_Float64), not an alias for double, so even past the parse there'd be a second question of whether ROOT's streamer machinery maps it to a basic type at all.

Instead I've kept double and asserted the property directly:

static_assert(std::numeric_limits<double>::is_iec559 && sizeof(double) == 8,
              "EventHeader::weight requires IEEE-754 binary64 double");

This should give the same portability guarantee at compile time — the build fails loudly on any platform where double isn't binary64 — without breaking dictionary generation. The rationale is also recorded in a comment in the header so the next person doesn't retry it.

One consistency point worth raising: every other floating-point member in the model is plain double (MCParticle::energy, SimHit::energyDeposit, pathLength, RecParticle::ipPV, and the std::array<double, 3> members), so weight would otherwise be the only fixed-width float. If we do want fixed-width floats across the model, that seems like its own PR, and it would need a ROOT-side solution first.

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.

You're right, I used double everywhere else. It's always easier to spot these things in other people's code, just like typos...
Could the issue be with C++23 being required for std::float64_t?

For this PR, let's just stick with double, I'll have a look whether we can move all doubles to something of machine-independent size.

Add SHiP::EventHeader, a per-event metadata record carrying an event
weight and the id of the originating event.

The weight (default 1.0) supports weighted generation such as forced or
oversampled muon DIS, where each replica of a source muon is written as
its own event and down-weighted accordingly. parentEventId (default -1)
records which source event a replica came from — event-level provenance,
distinct from MCParticle::motherId, which links particles within an
event.

The struct is a single per-event record like SimResult, so it is
registered in the ROOT dictionary without a std::vector counterpart, and
added to both the installed header set and the dictionary inputs. RNTuple
and TTree round-trip tests cover it, and the TTree dictionary-presence
check now includes SHiP::EventHeader. Purely additive: existing classes
and files are unchanged, so old files simply lack the new field.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@include/SHiP/EventHeader.hpp`:
- Around line 15-22: Rename EventHeader::originalEventId to the contracted
parentEventId and update every producer, consumer, helper, and serialization
round-trip expectation to use the new member consistently. Preserve the existing
default value and provenance semantics while ensuring no references to
originalEventId remain in the public API or related schema handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 683cbe87-70db-437f-8ce7-7e36f55d613f

📥 Commits

Reviewing files that changed from the base of the PR and between bf06169 and e905e8c.

📒 Files selected for processing (7)
  • CMakeLists.txt
  • README.md
  • include/SHiP/EventHeader.hpp
  • include/SHiP/LinkDef.h
  • tests/test_rntuple_io.cpp
  • tests/test_ttree_io.cpp
  • tests/test_utils.hpp
🚧 Files skipped from review as they are similar to previous changes (5)
  • include/SHiP/LinkDef.h
  • tests/test_utils.hpp
  • CMakeLists.txt
  • README.md
  • tests/test_ttree_io.cpp

Comment on lines +15 to +22
/// Per-event metadata — one record per event
struct EventHeader {
double weight{1.0}; ///< Event weight (e.g. P_DIS / nReplicas)
std::int64_t originalEventId{-1}; ///< Originating event id, e.g. the muon
///< event that seeded this replica
///< (-1 = none). Event-level provenance,
///< distinct from MCParticle::motherId,
///< which links particles within an event.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use the contracted parentEventId member name.

The PR contract specifies parentEventId, but this public record exposes originalEventId. Rename the member and update all producers, consumers, helpers, and round-trip expectations consistently; otherwise downstream code and serialized schemas will observe a different API.

Proposed fix
-  std::int64_t originalEventId{-1};
+  std::int64_t parentEventId{-1};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@include/SHiP/EventHeader.hpp` around lines 15 - 22, Rename
EventHeader::originalEventId to the contracted parentEventId and update every
producer, consumer, helper, and serialization round-trip expectation to use the
new member consistently. Preserve the existing default value and provenance
semantics while ensuring no references to originalEventId remain in the public
API or related schema handling.

@olantwin olantwin mentioned this pull request Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants