<!-- Source: https://docs.biosimulant.com/how-to/use-bioworld -->

# How to Use a BioWorld

Use `BioWorld` when you want to register modules, validate connections, run the
graph for a duration, and read outputs or snapshots afterward.

## Create a world

```python

world = biosim.BioWorld(communication_step=0.1)
```

## Inspect module ports

Check what a module accepts and emits before you wire it:

```python
from src.vision_demo import Eye, LGN, SuperiorColliculus

eye = Eye()
print(eye.inputs())
print(eye.outputs())
```

Both return `dict[str, SignalSpec]`. For a packaged model, the manifest's `io`
block should match these ports.

## Add modules with WiringBuilder

```python
builder = biosim.WiringBuilder(world)
builder.add("eye", eye)
builder.add("lgn", LGN())
builder.add("sc", SuperiorColliculus())
```

## Wire connections

```python
builder.connect("eye.visual_stream", ["lgn.retina"])
builder.connect("lgn.thalamus", ["sc.vision"])
builder.apply()
```

**Warning:**

  Always pass destinations as a list such as `["target.port"]`.

## Run the simulation

```python
world.run(duration=10.0)
```

The world drains `ONCE_BEFORE_RUN` modules, advances `EACH_WINDOW` modules across
the communication windows, then drains `ONCE_AFTER_RUN` modules. The legacy
external tick parameter is not part of the current runtime API.

## Read outputs

```python
outputs = world.get_outputs("lgn")
signal = outputs["thalamus"]
print(signal.value, signal.emitted_at)
```

Outputs are typed signals such as `ScalarSignal`, `ArraySignal`, `RecordSignal`,
or `EventSignal`. For events, visuals, and pause or stop controls, see the
[BioWorld API](/references/bioworld-api).

## Propagate final outputs

Legacy downstream temporal modules only observe outputs after those outputs are
committed at a communication boundary. Settle those modules after the run when
needed:

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

Settling calls downstream modules with `advance_window(current_time, current_time)`
and does not advance simulated time. Execute-style modules do not run during
settling; use `ONCE_AFTER_RUN` for finite report, export, or visualisation modules.

## Rerun and sweep parameters

There is no kernel-level reset method. To rerun the same modules from the same
starting state, take a snapshot after setup and restore it before each run:

```python
world.setup()
baseline = world.snapshot()

for _ in range(3):
    world.restore(baseline)
    world.run(duration=5.0)
```

To sweep constructor parameters, build a fresh world for each point:

```python

from src.linear_growth import LinearGrowth

def build_world(rate: float):
    world = biosim.BioWorld(communication_step=1.0)
    module = LinearGrowth(rate=rate, initial_value=1.0)
    world.add_biomodule("growth", module)
    return world, module

results = []
for rate in [0.05, 0.1, 0.2, 0.4]:
    world, module = build_world(rate)
    world.run(duration=100.0)
    results.append({"rate": rate, "final_state": module.snapshot()})
```

## Next steps

- [Create a BioModule](/how-to/create-biomodule)
- [Labs Serve UI](/references/labs-serve)
- [BioWorld API Reference](/references/bioworld-api)
