Skip to content

Expose System::getNumOfObsForOutput / getObsForOutput for in-process embedders#72

Merged
jrfaeder merged 2 commits into
RuleWorld:masterfrom
wshlavacek:bngsim/embedding-api
May 12, 2026
Merged

Expose System::getNumOfObsForOutput / getObsForOutput for in-process embedders#72
jrfaeder merged 2 commits into
RuleWorld:masterfrom
wshlavacek:bngsim/embedding-api

Conversation

@wshlavacek
Copy link
Copy Markdown

Summary

Two one-line accessors on NFcore::System for index-based read access to
the output observable list:

int          System::getNumOfObsForOutput() const;
Observable * System::getObsForOutput(int index) const;

Both are inline header-only and read directly from the existing
obsToOutput vector.

Why

The current public surface for reading observables from a System* is
getObservableByName(std::string), which assumes the caller already
knows the observable names. The CLI output path
(outputAllObservableNames() plus .gdat headers) covers end-users
running the NFsim binary, but doesn't help an in-process consumer
that wants to capture observable counts directly from a System.

These accessors close that gap without changing simulation behavior or
adding any new state.

What it changes

+ int getNumOfObsForOutput() const { return static_cast<int>(obsToOutput.size()); }
+ Observable * getObsForOutput(int index) const { return obsToOutput.at(index); }
  • Pure reads of existing private state via std::vector::size() and
    std::vector::at().
  • No new fields, no new dependencies, no header pollution.
  • The standalone CLI is unchanged: outputAllObservableNames and the
    .gdat output path are not touched, and existing validate/ tests
    continue to pass.

Example

NFcore::System *sys = NFinput::initializeFromXML(xml_path, /*...*/);
sys->prepareForSimulation();
sys->stepTo(10.0);

for (int i = 0; i < sys->getNumOfObsForOutput(); ++i) {
    NFcore::Observable *obs = sys->getObsForOutput(i);
    std::cout << obs->getName() << " = " << obs->getCount() << "\n";
}

Verified

  • macOS clang build clean.
  • validate/basicModels/v39.xml smoke run produces unchanged output.

Add two one-line public accessors on NFcore::System for index-based
read access to the obsToOutput vector:

  int          getNumOfObsForOutput() const
  Observable * getObsForOutput(int index) const

Motivation: in-process / library callers currently cannot enumerate
observables programmatically. Public access is limited to
getObservableByName(string), which assumes the caller already knows
the names — chicken-and-egg for a generic embedder. The CLI
output path (outputAllObservableNames + .gdat headers) covers
end-users running NFsim as a binary, but does not help anyone
linking libnfsim.

These accessors are pure read access into the existing private
obsToOutput vector via std::vector::size() and std::vector::at().
They do not change simulation behavior, do not add fields, and do
not call into anything else. Risk surface is bounded to the
two-line diff.

Following the precedent of RuleWorld#67 (per-instance RNG), this is a tiny
embedding-oriented contribution that keeps the standalone NFsim CLI
behavior identical while making libnfsim consumable by in-process
hosts (BNGsim, RuleMonkey-style harnesses, future Python/Julia
bindings).

No new tests ship: existing validate.py coverage exercises the
binary path unchanged. Happy to add a small test if reviewers want
one — a CLI flag that prints i:name via the accessors, or a
dedicated mini-executable, would both work.
@wshlavacek wshlavacek requested a review from jrfaeder May 9, 2026 01:52
@jrfaeder jrfaeder merged commit 9777c71 into RuleWorld:master May 12, 2026
3 checks passed
@wshlavacek wshlavacek deleted the bngsim/embedding-api branch May 19, 2026 15:37
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