# experiment { #tvbo.classes.experiment }

`classes.experiment`

The `SimulationExperiment` host object that ties a whole simulation together.

A `SimulationExperiment` binds local [`Dynamics`](../classes/dynamics.qmd), a [`Network`](../classes/network.qmd), coupling, integration settings, monitors, and stimulation into a single, YAML-round-trippable object. It is the entry point for constructing an experiment (from YAML, a file, the platform, or a TVB simulator), configuring and resolving its coupling/delay metadata, rendering backend code, and running it on any of the supported backends (`tvb`, `tvboptim`, `jax`, `pde`, `cuda`, `python`).

## Attributes

| Name | Description |
| --- | --- |
| [DYNAMICS_NAMED_COLLECTIONS](#tvbo.classes.experiment.DYNAMICS_NAMED_COLLECTIONS) | The same, for the slots a `Dynamics` carries. See `_reject_unnamed_members`. |
| [NAMED_COLLECTIONS](#tvbo.classes.experiment.NAMED_COLLECTIONS) | Keyed slots whose key is a name — one the rest of the spec addresses and codegen emits. |
| [logger](#tvbo.classes.experiment.logger) |  |
| [sessionid](#tvbo.classes.experiment.sessionid) |  |

## Classes

| Name | Description |
| --- | --- |
| [SimulationExperiment](#tvbo.classes.experiment.SimulationExperiment) | The central runnable object in TVBO: a complete brain-network simulation spec. |

### SimulationExperiment { #tvbo.classes.experiment.SimulationExperiment }

```python
classes.experiment.SimulationExperiment(**kwargs)
```

The central runnable object in TVBO: a complete brain-network simulation spec.

Bundles `dynamics`, `network` (with its `coupling`), `integration`, `observations`, and any analysis layers (stimulation, algorithms, explorations, …) into one declarative specification. The same instance can be:

- **executed** in any registered backend (`run("jax")`, `run("tvb")`, …)
- **serialized** to YAML, BIDS, openMINDS, or LEMS
- **rendered** as code for inspection or external use (`render_code(...)`)
- **reported** as Markdown or HTML (`report(...)`)

Construct via direct kwargs, from a `Dynamics` instance, by name from the curated database (`from_db`), or by loading a YAML / BIDS export.

#### Examples {.doc-section .doc-section-examples}

```python from tvbo import Dynamics, SimulationExperiment

exp = SimulationExperiment(dynamics=Dynamics.from_db("Generic2dOscillator")) result = exp.run("jax", duration=5_000)

# Or fully declarative exp = SimulationExperiment( dynamics={"iri": "tvbo:ReducedWongWangExcInh"}, network={"parcellation": {"atlas": {"iri": "tvbo:DesikanKilliany"}}, "tractogram":   {"iri": "tvbo:dTOR"}, "coupling":     {"long_range": {"iri": "tvbo:Linear"}}}, integration={"method": "Heun", "duration": 10_000, "noise": None}, )
```

See the [Simulation experiments](/2-specify/SimulationExperiments.qmd) page for the full constructor surface and the [`running-simulations`](../../../skills/running-simulations/SKILL.md) skill for backend choices.

#### Attributes

| Name | Description |
| --- | --- |
| [coupling](#tvbo.classes.experiment.SimulationExperiment.coupling) | The network's default coupling — the first it declares. Read-only. |
| [dataset_observation_targets](#tvbo.classes.experiment.SimulationExperiment.dataset_observation_targets) | Map each dataset-sourced observation to its measure name. |
| [horizon](#tvbo.classes.experiment.SimulationExperiment.horizon) | Number of history steps needed given delays and dt, like the old `horizon` attribute. |
| [max_delay](#tvbo.classes.experiment.SimulationExperiment.max_delay) | Compute the maximum delay (ms) from the current network/connectome. |
| [metadata](#tvbo.classes.experiment.SimulationExperiment.metadata) | The experiment itself, exposed as its own metadata container. |
| [network_observation_measures](#tvbo.classes.experiment.SimulationExperiment.network_observation_measures) | Map each network-sourced observation to its network measure. |
| [noise_sigma_array](#tvbo.classes.experiment.SimulationExperiment.noise_sigma_array) | Per-state-variable noise sigma values. |
| [parameters](#tvbo.classes.experiment.SimulationExperiment.parameters) | The full collection of experiment parameters as a nested `Bunch`. |

#### Methods

| Name | Description |
| --- | --- |
| [add_stimulus](#tvbo.classes.experiment.SimulationExperiment.add_stimulus) | Attach a stimulus to the experiment. |
| [bake_real_node_labels](#tvbo.classes.experiment.SimulationExperiment.bake_real_node_labels) | Replace the model network's placeholder labels with real ones in place. |
| [collect_initial_conditions](#tvbo.classes.experiment.SimulationExperiment.collect_initial_conditions) | Build the initial-history `TimeSeries` for the simulation. |
| [collect_state](#tvbo.classes.experiment.SimulationExperiment.collect_state) | Assemble a `SimulationState` pytree for the JAX-style backends. |
| [configure](#tvbo.classes.experiment.SimulationExperiment.configure) | Resolve coupling declarations and normalize delay flags. |
| [copy](#tvbo.classes.experiment.SimulationExperiment.copy) | Return a deep copy of this experiment. |
| [dataset_batch_size](#tvbo.classes.experiment.SimulationExperiment.dataset_batch_size) | Subjects per on-device batch (``dataset.batch_size``), or ``None`` for auto. |
| [dataset_bundle_files](#tvbo.classes.experiment.SimulationExperiment.dataset_bundle_files) | Per enumerated subject, the source file(s) a self-contained kit must carry. |
| [dataset_on_device](#tvbo.classes.experiment.SimulationExperiment.dataset_on_device) | True when the cohort's per-subject fits run as one on-device vmap batch. |
| [dataset_reconcile_index](#tvbo.classes.experiment.SimulationExperiment.dataset_reconcile_index) | Indices into the model network's nodes for *shared_labels* (keyed). |
| [dataset_reconcile_indices](#tvbo.classes.experiment.SimulationExperiment.dataset_reconcile_indices) | Model-side gather index for each ``by_label`` dataset target (keyed). |
| [dataset_subject_ids](#tvbo.classes.experiment.SimulationExperiment.dataset_subject_ids) | Enumerate the cohort for the per-subject workflow fan-out. |
| [execute](#tvbo.classes.experiment.SimulationExperiment.execute) | Render and build the executable object for a backend without running it. |
| [freeze_yaml](#tvbo.classes.experiment.SimulationExperiment.freeze_yaml) | Render a self-contained spec YAML with the connectome frozen alongside. |
| [from_datamodel](#tvbo.classes.experiment.SimulationExperiment.from_datamodel) | Create from a datamodel instance by copying its already-normalized state. |
| [from_db](#tvbo.classes.experiment.SimulationExperiment.from_db) | Load a SimulationExperiment by name from the tvbo database. |
| [from_file](#tvbo.classes.experiment.SimulationExperiment.from_file) | Load a `SimulationExperiment` from a YAML file on disk. |
| [from_openminds](#tvbo.classes.experiment.SimulationExperiment.from_openminds) | Create a SimulationExperiment from openMINDS JSON-LD. |
| [from_platform](#tvbo.classes.experiment.SimulationExperiment.from_platform) | Load a simulation experiment from the tvbo platform API. |
| [from_pydantic](#tvbo.classes.experiment.SimulationExperiment.from_pydantic) | Create a SimulationExperiment from a Pydantic model instance. |
| [from_pyrates](#tvbo.classes.experiment.SimulationExperiment.from_pyrates) | Load a SimulationExperiment from a PyRates YAML template file. |
| [from_string](#tvbo.classes.experiment.SimulationExperiment.from_string) | Create a SimulationExperiment from a YAML string. |
| [from_tvb_simulator](#tvbo.classes.experiment.SimulationExperiment.from_tvb_simulator) | Build a `SimulationExperiment` from a configured TVB `Simulator`. |
| [generate_report](#tvbo.classes.experiment.SimulationExperiment.generate_report) | Backward-compatible alias for :meth:`report`. |
| [get_experiment_file_prefix](#tvbo.classes.experiment.SimulationExperiment.get_experiment_file_prefix) | Build a BIDS-style filename prefix for this experiment. |
| [get_network_stem](#tvbo.classes.experiment.SimulationExperiment.get_network_stem) | BIDS basename for the frozen connectome companion beside a result. |
| [get_parameters_collection](#tvbo.classes.experiment.SimulationExperiment.get_parameters_collection) | Collect all experiment parameters into a nested `Bunch`. |
| [get_result_stem](#tvbo.classes.experiment.SimulationExperiment.get_result_stem) | BIDS result basename (no extension), generated with pybids ``build_path``. |
| [list_db](#tvbo.classes.experiment.SimulationExperiment.list_db) | List available experiments in the tvbo database. |
| [list_platform_experiments](#tvbo.classes.experiment.SimulationExperiment.list_platform_experiments) | List available experiments on the tvbo platform. |
| [plot](#tvbo.classes.experiment.SimulationExperiment.plot) | Plot experiment outputs directly or compose multi-panel layouts. |
| [render](#tvbo.classes.experiment.SimulationExperiment.render) | Unified entry point for rendering the experiment in any output format. |
| [render_code](#tvbo.classes.experiment.SimulationExperiment.render_code) | Render generated code in *format* (back-compat shim around the registry). |
| [render_yaml](#tvbo.classes.experiment.SimulationExperiment.render_yaml) | Deprecated Render the YAML representation as a string. |
| [report](#tvbo.classes.experiment.SimulationExperiment.report) | Render a human-readable report for this experiment. |
| [resolve_dataset_observations](#tvbo.classes.experiment.SimulationExperiment.resolve_dataset_observations) | Resolve per-subject dataset-sourced targets for one subject. |
| [resolve_dataset_observations_batched](#tvbo.classes.experiment.SimulationExperiment.resolve_dataset_observations_batched) | Resolve every cohort subject's dataset target and stack over subjects. |
| [resolve_network_observations](#tvbo.classes.experiment.SimulationExperiment.resolve_network_observations) | Resolve network-sourced observations to their matrices. |
| [run](#tvbo.classes.experiment.SimulationExperiment.run) | Configure, build, and run the experiment on a backend. |
| [save](#tvbo.classes.experiment.SimulationExperiment.save) | Render via :meth:`render` and persist to disk. |
| [save_code](#tvbo.classes.experiment.SimulationExperiment.save_code) | Render the experiment as TVB Python code and write it to disk. |
| [setup_monitors](#tvbo.classes.experiment.SimulationExperiment.setup_monitors) | Populate monitors in metadata from simple inputs or runtime wrappers. |
| [supported_export_formats](#tvbo.classes.experiment.SimulationExperiment.supported_export_formats) | Return metadata for API/UI export format dropdowns. |
| [symbolic](#tvbo.classes.experiment.SimulationExperiment.symbolic) | Symbolic representation of the full experiment equations. |
| [to_openminds](#tvbo.classes.experiment.SimulationExperiment.to_openminds) | Export experiment to openMINDS JSON-LD format. |
| [to_yaml](#tvbo.classes.experiment.SimulationExperiment.to_yaml) | Export the experiment to YAML format. |

##### add_stimulus { #tvbo.classes.experiment.SimulationExperiment.add_stimulus }

```python
classes.experiment.SimulationExperiment.add_stimulus(stimulus)
```

Attach a stimulus to the experiment.

###### Parameters {.doc-section .doc-section-parameters}

| Name     | Type   | Description                                                                                                                                     | Default    |
|----------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------|------------|
| stimulus |        | Either a `Stimulus` instance, or a name/ontology class (`str` or `owlready2.ThingClass`) resolved to a `Stimulus` via `Stimulus.from_ontology`. | _required_ |

##### bake_real_node_labels { #tvbo.classes.experiment.SimulationExperiment.bake_real_node_labels }

```python
classes.experiment.SimulationExperiment.bake_real_node_labels()
```

Replace the model network's placeholder labels with real ones in place.

A network sourced by a ``bids:`` entity block carries only ``region_N`` placeholders until run time; freezing drops that block, so the real labels (hydrated from the db) are written onto the network's nodes here. This keeps a frozen kit self-contained and label reconciliation (never positional) working on reload. Returns True when labels were applied.

##### collect_initial_conditions { #tvbo.classes.experiment.SimulationExperiment.collect_initial_conditions }

```python
classes.experiment.SimulationExperiment.collect_initial_conditions()
```

Build the initial-history `TimeSeries` for the simulation.

Constructs a history buffer of shape `(horizon, n_state_vars, n_nodes, n_modes)` spanning the delay window `[-max_delay, 0]`. A state variable that declares a `distribution` is sampled per node; every other one is seeded from its scalar `initial_value`.

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                                                                      |
|--------|--------|--------------------------------------------------------------------------------------------------|
|        |        | A `TimeSeries` whose time axis is the history window and whose data is the seeded initial state. |

##### collect_state { #tvbo.classes.experiment.SimulationExperiment.collect_state }

```python
classes.experiment.SimulationExperiment.collect_state(initial_conditions=None)
```

Assemble a `SimulationState` pytree for the JAX-style backends.

Gathers the parameter collection (expanding coupling parameters with shape annotations and wrapping array-valued parameters as ndarrays so the JAX backend receives real arrays), the network, integration step/step-count, and the noise wrapper into a single state object.

###### Parameters {.doc-section .doc-section-parameters}

| Name               | Type               | Description                                                                                                                          | Default   |
|--------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------|-----------|
| initial_conditions | TimeSeries \| None | History to seed the state with. When omitted, initial conditions are collected from the experiment via `collect_initial_conditions`. | `None`    |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                                                                        |
|--------|--------|----------------------------------------------------------------------------------------------------|
|        |        | A `SimulationState` carrying initial conditions, network, `dt`, step count, noise, and parameters. |

##### configure { #tvbo.classes.experiment.SimulationExperiment.configure }

```python
classes.experiment.SimulationExperiment.configure()
```

Resolve coupling declarations and normalize delay flags.

Runs at the execution boundary and is backend-agnostic and idempotent: the resolved state persists on the experiment so YAML re-serialization and metadata export reflect what was actually executed. Delayed integration/coupling is disabled when the connectome has no path lengths or the conduction speed is infinite (all delays zero). Declarative stimulus events are lowered at the same boundary, turning `target_variable` into a name and `target_regions` into node indices — the fields codegen consumes.

##### copy { #tvbo.classes.experiment.SimulationExperiment.copy }

```python
classes.experiment.SimulationExperiment.copy(**overrides)
```

Return a deep copy of this experiment.

Use keyword overrides to set attributes on the returned copy.

Errors are not swallowed; if a field can't be copied, an exception is raised.

##### dataset_batch_size { #tvbo.classes.experiment.SimulationExperiment.dataset_batch_size }

```python
classes.experiment.SimulationExperiment.dataset_batch_size()
```

Subjects per on-device batch (``dataset.batch_size``), or ``None`` for auto.

Bounds how many subjects the cohort driver holds in one vectorised batch, so a large cohort is chunked in-process instead of vmapped all at once. ``None`` lets the driver size the batch against the working-memory budget (as for exploration ``n_parallel: auto``). Only meaningful on-device.

##### dataset_bundle_files { #tvbo.classes.experiment.SimulationExperiment.dataset_bundle_files }

```python
classes.experiment.SimulationExperiment.dataset_bundle_files(
    entity_overrides=None,
)
```

Per enumerated subject, the source file(s) a self-contained kit must carry.

For each dataset-sourced observation, resolve the subject's matching sidecar under ``dataset.bids_root`` and pair it with the payload(s) it references, so a workflow kit can bundle exactly the empirical targets its fan-out consumes and drop its dependence on a machine-specific data tree. *entity_overrides* pins or tightens the BIDS entities used for selection (e.g. ``{'atlas': 'HCPMMP1', 'suffix': 'relmat'}``) — the exact variant is chosen when a subject directory holds several. ``suffix`` overrides the trailing filename component; every other key overrides a ``key-value`` entity. The overrides disambiguate among the variants a subject already has; the cohort itself is still enumerated by the observation's own query (:meth:`dataset_subject_ids`).

Returns ``{subject_id: [sidecar, payload, …]}`` (existing files, de-duplicated in first-seen order); empty when the experiment has no dataset target.

##### dataset_on_device { #tvbo.classes.experiment.SimulationExperiment.dataset_on_device }

```python
classes.experiment.SimulationExperiment.dataset_on_device()
```

True when the cohort's per-subject fits run as one on-device vmap batch.

Driven by ``dataset.batch_mode == on_device`` (default ``fan_out`` keeps the per-subject workflow fan-out). Only meaningful when the experiment actually has a per-subject dataset-sourced target to batch over.

##### dataset_reconcile_index { #tvbo.classes.experiment.SimulationExperiment.dataset_reconcile_index }

```python
classes.experiment.SimulationExperiment.dataset_reconcile_index(
    shared_labels,
    model_labels=None,
)
```

Indices into the model network's nodes for *shared_labels* (keyed).

The simulated observation selects this sub-block so it aligns, label for label, with a ``by_label``-reconciled empirical target. Pass *model_labels* to avoid re-resolving them.

##### dataset_reconcile_indices { #tvbo.classes.experiment.SimulationExperiment.dataset_reconcile_indices }

```python
classes.experiment.SimulationExperiment.dataset_reconcile_indices()
```

Model-side gather index for each ``by_label`` dataset target (keyed).

For every observation sourced from ``dataset.subject.<measure>`` with ``reconcile: by_label``, returns the positions of the shared node labels within the model network's node order — derived from the labels, never from position. The shared label set is identical across the cohort, so it is resolved once from the first cohort subject (reading only its node labels, not its matrix). Codegen uses this to gather the simulated observable onto the same shared labels as the reconciled empirical target before comparing them. Returns ``{}`` (no gather) when nothing is dataset-sourced or the data cannot be resolved.

##### dataset_subject_ids { #tvbo.classes.experiment.SimulationExperiment.dataset_subject_ids }

```python
classes.experiment.SimulationExperiment.dataset_subject_ids()
```

Enumerate the cohort for the per-subject workflow fan-out.

An explicit ``dataset.subjects`` list wins (a curated subset). Otherwise the subjects are discovered by querying ``dataset.bids_root`` with the first dataset-sourced observation's ``query`` — the same filter that resolves each shard's target, so discovery and resolution never diverge. Returns sorted subject IDs without the ``sub-`` prefix; empty when the experiment has no dataset-sourced observation.

##### execute { #tvbo.classes.experiment.SimulationExperiment.execute }

```python
classes.experiment.SimulationExperiment.execute(
    format='tvb',
    rendered_code=None,
    **kwargs,
)
```

Render and build the executable object for a backend without running it.

Calls `configure` to normalize coupling/delay metadata, renders the backend code, and executes it to produce a ready-to-run artefact. The return type depends on `format`:

- `"tvb"`: a configured `tvb` `Simulator`.
- `"tvboptim"` / `"tvb-optim"`: a `Bunch` namespace of the generated functions.
- `"autodiff"` / `"jax"`: the JAX `kernel` callable (JIT-compiled unless `jit=False`).
- `"pde"` / `"pde-fem"` / `"pde-python"`: the generated namespace.

###### Parameters {.doc-section .doc-section-parameters}

| Name          | Type   | Description                                                                                                                                                                                                                                                                                                                                                       | Default   |
|---------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
| format        |        | Backend identifier selecting what to build.                                                                                                                                                                                                                                                                                                                       | `'tvb'`   |
| rendered_code |        | Optional pre-rendered backend script to execute instead of calling `render_code(format)`. When given, no code is generated: the string is executed as-is, so a kit frozen once (via `render(format)`) runs on a stock tvbo runtime with no codegen step. Must match `format`. When `None` (default) the behaviour is unchanged — the code is rendered on the fly. | `None`    |
| **kwargs      |        | Backend-specific options. Forwarded to the TVB simulator factory, to `render_code`, or interpreted as JAX flags (`jit`, `_return_namespace`) depending on `format`.                                                                                                                                                                                               | `{}`      |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                             |
|--------|--------|---------------------------------------------------------|
|        |        | The backend-specific executable object described above. |

###### Raises {.doc-section .doc-section-raises}

| Name   | Type       | Description                                       |
|--------|------------|---------------------------------------------------|
|        | ValueError | If `format` is not one of the supported backends. |

##### freeze_yaml { #tvbo.classes.experiment.SimulationExperiment.freeze_yaml }

```python
classes.experiment.SimulationExperiment.freeze_yaml(
    out_dir,
    network_stem='network',
)
```

Render a self-contained spec YAML with the connectome frozen alongside.

When the experiment has a resolved multi-node network, its matrices are written as an HDF5 companion (``<network_stem>.h5`` + ``.yaml`` sidecar) in *out_dir* and the returned YAML references them via ``network.data_file`` (inline coupling / transforms / parameters preserved). This makes the spec reproducible on reload without the original data sources — the same mechanism the workflow emitter uses. Without such a network the plain metadata YAML already round-trips and is returned unchanged.

##### from_datamodel { #tvbo.classes.experiment.SimulationExperiment.from_datamodel }

```python
classes.experiment.SimulationExperiment.from_datamodel(dm)
```

Create from a datamodel instance by copying its already-normalized state.

This avoids the ``_as_dict`` → re-init round-trip which breaks on ``inlined_as_dict`` fields (the keyed dict is not valid ``**kwargs`` for the inner class constructor).  Instead we directly copy the ``__dict__`` from the fully-normalised LinkML object and then set the convenience aliases that ``__init__`` would normally provide.

Ontology population for the integrator and the coupling runs here rather than at construction, because the generated classes own their ``__init__``. Both calls are idempotent and only fill what is missing; the lookup is by ``method`` / ``name`` when ``iri`` is unset.

##### from_db { #tvbo.classes.experiment.SimulationExperiment.from_db }

```python
classes.experiment.SimulationExperiment.from_db(name)
```

Load a SimulationExperiment by name from the tvbo database.

##### from_file { #tvbo.classes.experiment.SimulationExperiment.from_file }

```python
classes.experiment.SimulationExperiment.from_file(filepath)
```

Load a `SimulationExperiment` from a YAML file on disk.

The resolved source path is recorded on the instance as `_source_file`, so later serialization can reference its origin. The recipe's `code/` subdirectory goes on the import path first, so a custom builder or callable resolves by bare module name without a `PYTHONPATH` prefix — it has to happen before loading, because construction resolves the network builder eagerly.

###### Parameters {.doc-section .doc-section-parameters}

| Name     | Type   | Description                                  | Default    |
|----------|--------|----------------------------------------------|------------|
| filepath | str    | Path to a YAML file defining the experiment. | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                           |
|--------|--------|-------------------------------------------------------|
|        |        | A new `SimulationExperiment` populated from the file. |

##### from_openminds { #tvbo.classes.experiment.SimulationExperiment.from_openminds }

```python
classes.experiment.SimulationExperiment.from_openminds(source)
```

Create a SimulationExperiment from openMINDS JSON-LD.



###### Parameters {.doc-section .doc-section-parameters}

source : str or dict
    Either a file path to a JSON-LD file, or a dict containing
    JSON-LD data.



###### Returns: {.doc-section .doc-section-returns}

SimulationExperiment
    New instance constructed from the openMINDS data.



###### Example: {.doc-section .doc-section-example}

>>> exp = SimulationExperiment.from_openminds("experiment.jsonld")
>>> exp = SimulationExperiment.from_openminds({"@type": "tvbo:SimulationExperiment", ...})

##### from_platform { #tvbo.classes.experiment.SimulationExperiment.from_platform }

```python
classes.experiment.SimulationExperiment.from_platform(
    name,
    base_url=TVBO_PLATFORM_URL,
)
```

Load a simulation experiment from the tvbo platform API.

Fetches the full LinkML-valid YAML definition from the platform.



###### Parameters {.doc-section .doc-section-parameters}

name : str
    Experiment label/ID (e.g., "RWW_BOLD_FC_Optimization").
base_url : str
    Platform base URL.



###### Returns: {.doc-section .doc-section-returns}

SimulationExperiment Experiment loaded from the platform.

##### from_pydantic { #tvbo.classes.experiment.SimulationExperiment.from_pydantic }

```python
classes.experiment.SimulationExperiment.from_pydantic(pyd_obj)
```

Create a SimulationExperiment from a Pydantic model instance.

###### Parameters {.doc-section .doc-section-parameters}

| Name    | Type   | Description                                                            | Default    |
|---------|--------|------------------------------------------------------------------------|------------|
| pyd_obj | Any    | A Pydantic BaseModel instance (e.g., from tvbo.datamodel.tvbopydantic) | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type                 | Description                   |
|--------|----------------------|-------------------------------|
|        | SimulationExperiment | SimulationExperiment instance |

##### from_pyrates { #tvbo.classes.experiment.SimulationExperiment.from_pyrates }

```python
classes.experiment.SimulationExperiment.from_pyrates(filepath)
```

Load a SimulationExperiment from a PyRates YAML template file.

Parses all OperatorTemplates in the file and creates a keyed dict of Dynamics objects.



###### Parameters {.doc-section .doc-section-parameters}

filepath : str
    Path to PyRates YAML file.



###### Returns: {.doc-section .doc-section-returns}

SimulationExperiment
    New instance with primary dynamics and network.dynamics for multi-operator files.



###### Example: {.doc-section .doc-section-example}

>>> exp = SimulationExperiment.from_pyrates("synaptic_plasticity.yaml")
>>> print(exp.dynamics.name)  # 'tsodyks'
>>> print(list(exp.network.dynamics.keys()))  # ['tsodyks', 'depression', 'facilitation']

##### from_string { #tvbo.classes.experiment.SimulationExperiment.from_string }

```python
classes.experiment.SimulationExperiment.from_string(yaml_string)
```

Create a SimulationExperiment from a YAML string.

This is useful for defining experiments inline in notebooks or scripts using human-readable YAML syntax.



###### Parameters {.doc-section .doc-section-parameters}

yaml_string : str
    YAML-formatted string defining the experiment.



###### Returns: {.doc-section .doc-section-returns}

SimulationExperiment
    New instance populated from the YAML definition.



###### Example: {.doc-section .doc-section-example}

>>> exp = SimulationExperiment.from_string('''
... id: 1
... label: My Experiment
... dynamics:
...   name: JansenRit
...   parameters:
...     A: {value: 3.25}
... ''')

##### from_tvb_simulator { #tvbo.classes.experiment.SimulationExperiment.from_tvb_simulator }

```python
classes.experiment.SimulationExperiment.from_tvb_simulator(tvb_simulator)
```

Build a `SimulationExperiment` from a configured TVB `Simulator`.

Delegates to the [TVB adapter](../adapters/tvb.qmd) to capture the simulator's model, connectivity, coupling, integrator, and monitors, then constructs an equivalent experiment from that datamodel.

###### Parameters {.doc-section .doc-section-parameters}

| Name          | Type   | Description                                       | Default    |
|---------------|--------|---------------------------------------------------|------------|
| tvb_simulator |        | A configured `tvb.simulator.simulator.Simulator`. | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                               |
|--------|--------|-----------------------------------------------------------|
|        |        | A new `SimulationExperiment` mirroring the TVB simulator. |

##### generate_report { #tvbo.classes.experiment.SimulationExperiment.generate_report }

```python
classes.experiment.SimulationExperiment.generate_report(
    format='markdown',
    template_name='tvbo-report-experiment',
    outputfile=None,
    derivative_notation='dot',
)
```

Backward-compatible alias for :meth:`report`.

##### get_experiment_file_prefix { #tvbo.classes.experiment.SimulationExperiment.get_experiment_file_prefix }

```python
classes.experiment.SimulationExperiment.get_experiment_file_prefix()
```

Build a BIDS-style filename prefix for this experiment.

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                                                                                                    |
|--------|--------|--------------------------------------------------------------------------------------------------------------------------------|
|        |        | A string of the form `ses-<id>_desc-<label>`, where the description falls back to the dynamics label, name, or `"simulation"`. |

##### get_network_stem { #tvbo.classes.experiment.SimulationExperiment.get_network_stem }

```python
classes.experiment.SimulationExperiment.get_network_stem()
```

BIDS basename for the frozen connectome companion beside a result.

The result's own stem with ``_network`` in place of ``_result``: one suffix, which is all BIDS allows. The companion was previously ``<stem>_result_network``, two suffixes and no legal reading.

##### get_parameters_collection { #tvbo.classes.experiment.SimulationExperiment.get_parameters_collection }

```python
classes.experiment.SimulationExperiment.get_parameters_collection(**kwargs)
```

Collect all experiment parameters into a nested `Bunch`.

Traverses the experiment metadata, gathering parameters from the dynamics, coupling, network, and integration into a single container keyed by component.

###### Parameters {.doc-section .doc-section-parameters}

| Name     | Type   | Description                                                                                                                                             | Default   |
|----------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
| **kwargs |        | Traversal options. `keys_to_exclude` is a list of keys to skip; `connectivity` and `coupling_inputs` are always excluded when any exclusions are given. | `{}`      |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                                  |
|--------|--------|--------------------------------------------------------------|
|        |        | A `Bunch` mapping component names to their parameter values. |

##### get_result_stem { #tvbo.classes.experiment.SimulationExperiment.get_result_stem }

```python
classes.experiment.SimulationExperiment.get_result_stem()
```

BIDS result basename (no extension), generated with pybids ``build_path``.

Returns e.g. ``exp-<id>_model-<name>_result`` — the shared stem for this experiment's ``<stem>.h5`` data file and ``<stem>.yaml`` provenance sidecar, identical whether written by a local run or the HPC gather pass. The naming is driven by ``tvbo.adapters.bids.RESULT_PATTERNS`` (a pybids rule string), so it stays BIDS-compliant and customizable in one place.

##### list_db { #tvbo.classes.experiment.SimulationExperiment.list_db }

```python
classes.experiment.SimulationExperiment.list_db()
```

List available experiments in the tvbo database.

##### list_platform_experiments { #tvbo.classes.experiment.SimulationExperiment.list_platform_experiments }

```python
classes.experiment.SimulationExperiment.list_platform_experiments(
    base_url=TVBO_PLATFORM_URL,
)
```

List available experiments on the tvbo platform.



###### Parameters {.doc-section .doc-section-parameters}

base_url : str
    Platform base URL.



###### Returns: {.doc-section .doc-section-returns}

list[dict] List of experiment summaries.

##### plot { #tvbo.classes.experiment.SimulationExperiment.plot }

```python
classes.experiment.SimulationExperiment.plot(
    layout=None,
    panels=None,
    run_kwargs=None,
    auto=True,
    **kwargs,
)
```

Plot experiment outputs directly or compose multi-panel layouts.

By default (``auto=True``), this runs the experiment once, infers task-aware panels, and renders a flexible subplot_mosaic layout.

##### render { #tvbo.classes.experiment.SimulationExperiment.render }

```python
classes.experiment.SimulationExperiment.render(format='yaml', **kwargs)
```

Unified entry point for rendering the experiment in any output format.

Dispatches via the :mod:`tvbo.export.registry`.  All supported formats (YAML, openMINDS, markdown/PDF report, TVB, JAX, tvboptim, Julia, NeuroML/LEMS, …) are looked up by canonical key or alias.



###### Parameters {.doc-section .doc-section-parameters}

format : str
    Target output format.  See :func:`tvbo.export.list_formats` for the current set. **kwargs Forwarded to the underlying renderer.



###### Returns: {.doc-section .doc-section-returns}

str

##### render_code { #tvbo.classes.experiment.SimulationExperiment.render_code }

```python
classes.experiment.SimulationExperiment.render_code(format='tvb', **kwargs)
```

Render generated code in *format* (back-compat shim around the registry).

##### render_yaml { #tvbo.classes.experiment.SimulationExperiment.render_yaml }

```python
classes.experiment.SimulationExperiment.render_yaml()
```

Deprecated Render the YAML representation as a string.

Use to_yaml(filepath=None) instead.

##### report { #tvbo.classes.experiment.SimulationExperiment.report }

```python
classes.experiment.SimulationExperiment.report(
    format='markdown',
    template_name='tvbo-report-experiment',
    outputfile=None,
    derivative_notation='dot',
    mul_symbol=None,
)
```

Render a human-readable report for this experiment.

- Reuses the model/dynamics report template via Mako include to avoid redundancy.
- Summarizes integration, network/connectome, coupling, monitors, stimulation, and software info.

Parameters
- format: optional explicit fallback format ('markdown' or 'pdf')
- template_name: base name of the template without extension
- outputfile: optional path to write the rendered report; when provided, extension defines output format (.md or .pdf)
- derivative_notation: 'dot' for `\\dot{x}`, anything else for `dx/dt`
- mul_symbol: how products are written in the rendered equations — ``None`` (default) for implicit juxtaposition, or any symbol ``sympy.latex`` accepts (``'dot'``, ``'times'``, ``'*'``)

##### resolve_dataset_observations { #tvbo.classes.experiment.SimulationExperiment.resolve_dataset_observations }

```python
classes.experiment.SimulationExperiment.resolve_dataset_observations(
    active_subject,
)
```

Resolve per-subject dataset-sourced targets for one subject.

For each observation whose ``source`` is ``dataset.subject.<measure>``: query ``dataset.bids_root`` for the subject's matching file, load it as a Network, read ``<measure>``, and reconcile its nodes to the model network. ``reconcile: by_label`` maps each target node to the model's canonical label (alias-aware — a divergent nomenclature such as ``THALAMUS_LEFT`` for ``L_Thalamus`` still matches via the atlas ``alternateName`` crosswalk), then selects the shared labels in the model's order. Alignment is by name on both the empirical target and the simulated observable — never by row index — so a differing node count or order (or a swapped hemisphere block) cannot silently misalign the comparison. The realised coverage is logged, and falls back to requiring full coverage unless the observation sets ``min_coverage``.

Returns ``{obs_name: xarray.DataArray}`` keyed by canonical node label on both axes, restricted to the labels shared with the model network. The model-side gather (which model nodes the shared labels are) is available via :meth:`dataset_reconcile_index` so the simulated observation selects the same sub-block.

##### resolve_dataset_observations_batched { #tvbo.classes.experiment.SimulationExperiment.resolve_dataset_observations_batched }

```python
classes.experiment.SimulationExperiment.resolve_dataset_observations_batched(
    subjects=None,
)
```

Resolve every cohort subject's dataset target and stack over subjects.

Returns ``({obs_name: ndarray (n_subjects, ...)}, subject_ids)``. Each subject is reconciled by :meth:`resolve_dataset_observations`, so the per-subject arrays already share one node-label set (identical across the cohort) and stack cleanly along a leading subject axis. This batched target feeds the on-device ``jax.vmap`` cohort driver; the shared network stays in the model closure, only these per-subject targets vary per lane.

##### resolve_network_observations { #tvbo.classes.experiment.SimulationExperiment.resolve_network_observations }

```python
classes.experiment.SimulationExperiment.resolve_network_observations()
```

Resolve network-sourced observations to their matrices.

Pairs :attr:`network_observation_measures` with the data the network carries (:attr:`Network.observations`), yielding ``{obs_name: matrix}`` ready to pass into the generated ``run_experiment(network_observations=...)``. Raises a clear error if a declared measure's data is absent.

##### run { #tvbo.classes.experiment.SimulationExperiment.run }

```python
classes.experiment.SimulationExperiment.run(
    format=None,
    initial_conditions=None,
    results_root=None,
    rendered_code=None,
    **kwargs,
)
```

Configure, build, and run the experiment on a backend.

Dispatches on `format` to the corresponding backend (`tvb`, `tvboptim`, `jax`/`autodiff`, `cuda`, `python`, or `pde`), executes the simulation, and wraps the output in an [`ExperimentResult`](../data/types.qmd).

###### Parameters {.doc-section .doc-section-parameters}

| Name               | Type   | Description                                                                                                                                                                                                                                                                                                                                                      | Default   |
|--------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
| format             |        | Backend identifier selecting how to run the experiment. When omitted, it is resolved from the experiment's declared ``execution.backend`` (e.g. a spiking model that sets ``brian2``), falling back to ``tvboptim``.                                                                                                                                             | `None`    |
| initial_conditions |        | Optional history to seed the simulation (used by the JAX backend); defaults to conditions collected from the experiment.                                                                                                                                                                                                                                         | `None`    |
| results_root       |        | Directory under which sibling experiments' saved results are searched when this experiment's `initial_state.method == from_experiment` (see `_resolve_from_experiment_seed`). Defaults to the current directory; the CLI passes the run's output-directory parent.                                                                                               | `None`    |
| rendered_code      |        | Optional pre-rendered backend script executed instead of generating code at run time (forwarded to `execute`). All orchestration around it — subject/dataset resolution, seeds, network observations, saving — is unchanged, so a frozen script and the from-spec render produce byte-identical results. `None` (default) keeps the render-at-runtime behaviour. | `None`    |
| **kwargs           |        | Backend-specific run options. A `duration` value is applied to the integration settings before running; other keys (e.g. `benchmark`, `mode`) are passed through to the backend runner.                                                                                                                                                                          | `{}`      |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                                                                                          |
|--------|--------|----------------------------------------------------------------------------------------------------------------------|
|        |        | An `ExperimentResult` holding the integrated time series and any observations, with `source` set to this experiment. |

Everything the backend needs but the spec does not carry inline is resolved just before the call: network-sourced observations such as an empirical FC target, this subject's dataset-sourced targets reconciled to the model's node labels, parameters sourced from another experiment's operating point (injected as `seed_params`), and exploration-builder arguments sourced from another experiment (injected as `builder_data`). Each is set only when present, so an experiment declaring none is unaffected.

##### save { #tvbo.classes.experiment.SimulationExperiment.save }

```python
classes.experiment.SimulationExperiment.save(
    path,
    format=None,
    metadata_only=True,
    **kwargs,
)
```

Render via :meth:`render` and persist to disk.



###### Parameters {.doc-section .doc-section-parameters}

path : str or Path
    Output file path **or** directory.  When a directory is given the filename is derived from :meth:`get_experiment_file_prefix` and the correct extension for *format* (BIDS-style).
format : str, optional
    Export format key (e.g. ``'yaml'``, ``'tvb'``, ``'neuroml'``). When omitted, inferred from *path* suffix.
metadata_only : bool
    When ``True`` (default) only the textual/metadata artefact is written.  When ``False`` and the experiment has a network, the network arrays are also saved as an HDF5 sidecar file next to *path*.

##### save_code { #tvbo.classes.experiment.SimulationExperiment.save_code }

```python
classes.experiment.SimulationExperiment.save_code(dir, file_name=None)
```

Render the experiment as TVB Python code and write it to disk.

###### Parameters {.doc-section .doc-section-parameters}

| Name      | Type   | Description                                                                                                   | Default    |
|-----------|--------|---------------------------------------------------------------------------------------------------------------|------------|
| dir       |        | Target directory (or full path when combined with a BIDS-style auto-generated filename).                      | _required_ |
| file_name |        | Optional filename to write inside `dir`; when omitted, the path is derived from `get_experiment_file_prefix`. | `None`     |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                |
|--------|--------|--------------------------------------------|
|        |        | The path of the written file, as a string. |

##### setup_monitors { #tvbo.classes.experiment.SimulationExperiment.setup_monitors }

```python
classes.experiment.SimulationExperiment.setup_monitors(**kwargs)
```

Populate monitors in metadata from simple inputs or runtime wrappers.

##### supported_export_formats { #tvbo.classes.experiment.SimulationExperiment.supported_export_formats }

```python
classes.experiment.SimulationExperiment.supported_export_formats()
```

Return metadata for API/UI export format dropdowns.

##### symbolic { #tvbo.classes.experiment.SimulationExperiment.symbolic }

```python
classes.experiment.SimulationExperiment.symbolic(
    integrate=False,
    indexed=False,
    delays=False,
)
```

Symbolic representation of the full experiment equations.

Produces different styles of mathematical output depending on the combination of flags:

+----------+--------+-------+--------------------------------------------+ | integrate| indexed| delays| Description                                | +==========+========+=======+============================================+ | False    | False  | False | Dynamics separated, coupling terms as free | |          |        |       | symbols.  Coupling equations shown in      | |          |        |       | ``'coupling'`` dict.                       | +----------+--------+-------+--------------------------------------------+ | True     | False  | False | Coupling substituted into dynamics.        | |          |        |       | State vars remain ``y0(t)``.               | +----------+--------+-------+--------------------------------------------+ | False    | True   | False | State vars indexed ``y0_i(t)``.            | |          |        |       | Coupling shown separately with ``[i],[j]``. | +----------+--------+-------+--------------------------------------------+ | True     | True   | False | Fully integrated with node indices.        | |          |        |       | Ready for network presentation.            | +----------+--------+-------+--------------------------------------------+ | *        | (True) | True  | Like above but incoming states carry       | |          |        |       | ``y1[j, t - tau[i,j]]`` time delay.        | |          |        |       | ``delays=True`` implies ``indexed=True``.  | +----------+--------+-------+--------------------------------------------+

Every symbol substituted here — the node index `y0(t)` → `y0_i(t)`, the coupling terms, `t` — is taken from the model's own table rather than rebuilt. The table's symbols carry assumptions, `Function("y0") != Function("y0", real=True)`, and `subs` across that mismatch replaces nothing at all instead of raising.



###### Parameters {.doc-section .doc-section-parameters}

integrate : bool
    Substitute coupling expressions into state equations.
indexed : bool
    Add node index ``_i`` to state / derived variables.
delays : bool
    Show time delays on incoming coupling states. Implies ``indexed=True``.



###### Returns: {.doc-section .doc-section-returns}

dict
    Keys: ``'state'``, ``'coupling'``, ``'functions'``, ``'derived_parameters'``, ``'derived'``, ``'parameters'``.

##### to_openminds { #tvbo.classes.experiment.SimulationExperiment.to_openminds }

```python
classes.experiment.SimulationExperiment.to_openminds(
    filepath=None,
    base_id=None,
    include_context=True,
)
```

Export experiment to openMINDS JSON-LD format.



###### Parameters {.doc-section .doc-section-parameters}

filepath : str, optional
    If provided, write JSON-LD to this file path.
base_id : str, optional
    Base URI for generating @id values (e.g., "https://example.org/simulations").
include_context : bool
    Whether to include the @context in the output. Default True.



###### Returns: {.doc-section .doc-section-returns}

dict
    OpenMINDS-compatible JSON-LD dictionary.



###### Example: {.doc-section .doc-section-example}

>>> exp = SimulationExperiment(...)
>>> jsonld = exp.to_openminds()
>>> exp.to_openminds("output.jsonld", base_id="https://example.org")

##### to_yaml { #tvbo.classes.experiment.SimulationExperiment.to_yaml }

```python
classes.experiment.SimulationExperiment.to_yaml(filepath=None, format='tvbo')
```

Export the experiment to YAML format.



###### Parameters {.doc-section .doc-section-parameters}

filepath : str, optional
    Path to write the YAML file. If None, returns the YAML string.
format : str
    Output format: "tvbo" (default) or "pyrates".



###### Returns: {.doc-section .doc-section-returns}

str YAML string or filepath if written to file.