ReferencesBioWorld API

BioWorld API

BioWorld is the communication-step orchestrator. It drains finite before/after modules, advances each-window modules, commits outputs atomically, and routes signals through validated connections.

Creating a world

import biosimulant as biosim
 
world = biosim.BioWorld(communication_step=0.1)

communication_step is required. It defines the synchronization cadence for inter-module exchange.

Execution model

  • Ready ONCE_BEFORE_RUN modules drain in deterministic dependency layers at the run start boundary.
  • Every run advances in windows [t, t + communication_step].
  • Inputs for a window are collected from the committed signal store at the start boundary.
  • The world invokes every EACH_WINDOW module across the same positive window.
  • The world normalizes and commits all outputs atomically at the end boundary.
  • Ready ONCE_AFTER_RUN modules drain after the final window commit.
  • The kernel has no execution-order scheduling contract. Tied-time ordering is intentionally not part of the public semantics.

Outputs produced during one window are visible to downstream modules on a later communication turn. This keeps tied-time behavior order-independent.

Running a simulation

world.run(duration=10.0)

duration is the simulation-time horizon. The world does not accept the legacy external tick parameter.

If the world has not been set up yet, run() calls setup() automatically before the first window.

Final propagation

world.run(duration=10.0)
world.settle(steps=1)

settle() performs zero-time communication turns after the requested duration. It schedules only modules downstream of outputs published at the last boundary, delivers their committed inputs, calls advance_window(current_time, current_time), and commits any outputs they publish as the next propagation frontier.

Use settling for legacy temporal report, export, or visualization modules that should consume final producer outputs. Canonical modules are excluded from zero-time settling; use ONCE_AFTER_RUN for finite final analysis. Once-policy dependency chains drain automatically.

Runtime events

from biosimulant import WorldEvent
 
def listener(event, payload):
    print(event.value, payload)
 
world.on(listener)
world.run(duration=1.0)
world.off(listener)
EventWhen
STARTEDBefore the first communication window
STEPAfter each committed communication window
FINISHEDAfter the run exits, including stopped runs
PAUSEDWhen a paused run reaches a pause boundary
RESUMEDWhen a paused run resumes
STOPPEDWhen a cooperative stop request is honored
ERRORWhen an exception escapes the run loop

STEP payloads include progress fields such as t, window_start, window_end, start, end, duration, progress, progress_pct, and remaining.

Control flow

world.request_pause()
world.request_resume()
world.request_stop()

These controls are cooperative. They take effect at communication boundaries, not mid-window.

Snapshots and branching

baseline = world.snapshot()
 
world.run(duration=5.0)
world.restore(baseline)
 
branch = world.branch()
branch.run(duration=5.0)

Snapshots capture:

  • current simulation time
  • committed signal store
  • per-connection event and stale-read delivery state
  • per-module snapshot payloads
  • once-policy completion state
  • setup config

BioWorld does not expose a kernel-level reset() method. For repeatable reruns, restore a snapshot or build a fresh world.

Signal semantics

  • Source timestamps are preserved as emitted_at.
  • State signals are held until that source module publishes a non-empty replacement mapping.
  • Event signals persist in the store but are delivered once per connection per source timestamp.
  • Staleness is checked against the consuming port’s SignalSpec.max_age and stale_policy.

Visuals

visuals = world.collect_visuals()
for entry in visuals:
    print(entry["module"], len(entry["visuals"]))

Modules that implement visualize() can publish transport-safe visualization specs for Labs Serve UI and platform consumers.

If a separate downstream module builds the visualization, give it ExecutionPolicy.ONCE_AFTER_RUN. It then runs after the final window with the final committed inputs. Settle turns do not invoke execute() modules.

See Also