一键导入
writing-models
How to specify a Dynamics in TVBO — the YAML and Python forms, parameter / state-variable / equation conventions, and common pitfalls.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
How to specify a Dynamics in TVBO — the YAML and Python forms, parameter / state-variable / equation conventions, and common pitfalls.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
How TVBO's code generation works — template engines, backend dispatch in tvbo/codegen/, and the contract for adding a new backend.
How TVBO's code generation works — template engines, backend dispatch in tvbo/codegen/, and the contract for adding a new backend.
Ruthless editor who detects and destroys AI-generated slop — the hollow filler phrases, fake enthusiasm, recycled structures, and performative depth that make text instantly recognizable as machine-written. Rewrites content to sound like a human with something to say.
How to run a SimulationExperiment in TVBO — choosing a backend, calling run/plot, and what each optional extra (jax, tvb, pyrates, julia) provides.
How to write Python docstrings in TVBO so that quartodoc renders them correctly in the API site. Google style, markdown body, type info on signature (not in the docstring).
How to specify a Dynamics in TVBO — the YAML and Python forms, parameter / state-variable / equation conventions, and common pitfalls.
| name | writing-models |
| description | How to specify a Dynamics in TVBO — the YAML and Python forms, parameter / state-variable / equation conventions, and common pitfalls. |
| metadata | {"audience":"user","applies_to":["**/*.yaml","**/*.yml","**/*.py"],"tags":["models","dynamics","yaml"],"requires_extras":[]} |
A Dynamics is the smallest building block: a set of named parameters and state variables governed by ODE equations. It can be written as YAML or constructed directly in Python.
name: LorenzAttractor
parameters:
sigma:
value: 10
label: Prandtl number
rho:
value: 28
label: Rayleigh number
beta:
value: 2.6666666666666665
state_variables:
X:
equation:
lhs: \dot{X}
rhs: sigma * (Y - X)
Y:
equation:
lhs: \dot{Y}
rhs: X * (rho - Z) - Y
Z:
equation:
lhs: \dot{Z}
rhs: X * Y - beta * Z
from tvbo import Dynamics
lorenz = Dynamics(
parameters={
"sigma": {"value": 10.0},
"rho": {"value": 28.0},
"beta": {"value": 8 / 3},
},
state_variables={
"X": {"equation": {"rhs": "sigma * (Y - X)"}},
"Y": {"equation": {"rhs": "X * (rho - Z) - Y"}},
"Z": {"equation": {"rhs": "X * Y - beta * Z"}},
},
)
TVBO components are declarative: a Dynamics is either specified inline (as
above), loaded from YAML, or pointed at semantically via an iri. The
IRI's prefix names the source — tvbo: for the built-in ontology, but the
same mechanism is intended to dispatch to other prefixes (e.g. neuroml:)
that resolve from other ontologies / data sources.
# Direct construction (Python API)
dyn = Dynamics.from_db("ReducedWongWangExcInh")
# As a semantic pointer inside a SimulationExperiment dict
dynamics = {"name": "ReducedWongWang", "iri": "tvbo:ReducedWongWangExcInh"}
A bare name string (dynamics="ReducedWongWangExcInh") is not a semantic
pointer — there's no prefix, so the resolver cannot tell which source to
query. Always include the iri.
lhs is LaTeX, not Python. \dot{X} for a time-derivative. Omit lhs to default to \dot{<state>}.rhs is a SymPy-parseable expression. Names must match parameters and state variables. Greek letters as full words: sigma, not σ.label on a parameter is human-readable metadata (renders in the platform browser). Keep name machine-friendly.value on a state variable.tvbo/datamodel/** — that's generated from schema/*.yaml. Use the Dynamics class.{} / [] to a LinkML slot — a JsonObj in your data is the symptom of mis-configured YAML / a Python object leaking into the schema. The active datamodel (tvbo/datamodel/schema.py) is the jsonasobj2 / YAMLRoot dataclass form. Inlined dicts/lists are coerced into typed classes only in __post_init__ (i.e. at construction). Mutating a slot afterwards does not re-run that coercion:
parameters, dynamics, coupling, nodes, edges, transforms, …) → mutate the existing container in place: .update(...) / container["X"] = ... for dict slots, .append(...) for list slots. To get a typed entry, insert a constructed class: net.dynamics["X"] = Dynamics(...).
net.dynamics = {...} — a raw dict goes through jsonasobj2's JsonObj.__setattr__, which wraps it in a bare JsonObj (it later breaks .items() / .values() on round-trip).net.nodes = [{...}] — a raw list isn't wrapped in JsonObj, but its entries stay uncoerced plain dicts, never Node instances..update({...}) / ["X"] = {...} avoids the JsonObj, but a raw dict still isn't normalized — prefer inserting a constructed class instance.= is correct. Assign a scalar directly (net.number_of_nodes = 76); for a nested-object slot assign a constructed LinkML class instance (net.coordinate_space = CommonCoordinateSpace(...)), never a raw {} (which becomes a bare JsonObj).Network(dynamics={...}, nodes=[...])) so __post_init__ normalizes it into typed classes for you.This holds as long as the active datamodel is the dataclass/
YAMLRootone. If TVBO switches to the pydantic datamodel (tvbo/datamodel/pydantic.py), dict-assignment may become valid (pydantic validates/coerces) — unverified.
tvbo.classes.noise.tvbo.classes.event.tvbo.classes.perturbation.tvbo.classes.coupling + tvbo.classes.network.tvbo.classes.continuation.See the running-simulations skill for what to do once you have a Dynamics.