schematic
plot.schematic
Population-schematic diagrams for neural-mass / mean-field / spiking models.
Renders the excitatory/inhibitory population circuit of a model: population nodes plus typed, signed connections — synapse type (NMDA / AMPA / GABA / …) sets the line colour, biophysical sign sets the terminal (excitatory ▶, inhibitory ●) — within a population, between populations, as recurrent self-loops, and across n_areas coupled areas. It is the standing “what is this model” diagram every recipe wants (Deco 2014 Fig. 1a/2a, Jansen-Rit, …).
Rendering backend = graphviz layout + matplotlib draw. graphviz (the dot engine) solves node placement and edge-spline routing — its strength — and matplotlib draws the result with full styling control: crisp custom arrowheads, endpoints snapped to node edges, small compact self-loops, neuron-dot population glyphs, and publication typography. This beats either alone (graphviz styling is rigid; hand-placed matplotlib arrows don’t route cleanly).
Two entry points:
- Declarative — build
Population/Connectionobjects →PopulationSchematic. - Model-derived —
PopulationSchematic.from_dynamics(dynamics)reads a tvboDynamics: populations are its state variables (S_E→E); connections are recovered by expanding the derived variables into each state variable’s dfun and classifying every cross-population term by the sign of its coefficient and the synapse named in the multiplying parameter.
Flexible layout/style, all via plot(...) keywords:
layout:"stacked"(E-row over I-row, the DMF look) ·"mirror"([I E]…[E I], the paired-area spiking look) ·"row"(single rank).glyph:"circle"·"neurons"(dotted population = spiking) · a callable.self_loop,coupling_blob,ellipsis,legend/legend_labels,synapse_colors,node_size,ranksep/nodesep— all tunable.
Attributes
| Name | Description |
|---|---|
| SYNAPSE_COLORS |
Classes
| Name | Description |
|---|---|
| Connection | Directed connection source → target. |
| Population | One neural population (a node). sign = "excitatory" (open node) / "inhibitory" (filled). label is the glyph inside the node (defaults to name). |
| PopulationSchematic | A renderable population circuit: populations + typed/signed connections over N areas. |
Connection
plot.schematic.Connection(
source,
target,
synapse=None,
sign='excitatory',
scope='local',
label=None,
recurrent=None,
)Directed connection source → target.
synapse (NMDA/AMPA/GABA) sets colour; sign (excitatory ▶ / inhibitory ●) sets the terminal; scope is "local" (within an area) or "long_range" (between adjacent areas). recurrent (self-loop) is inferred from source == target when omitted.
Population
plot.schematic.Population(name, sign='excitatory', label=None)One neural population (a node). sign = "excitatory" (open node) / "inhibitory" (filled). label is the glyph inside the node (defaults to name).
PopulationSchematic
plot.schematic.PopulationSchematic(populations, connections, n_areas=1)A renderable population circuit: populations + typed/signed connections over N areas.
Methods
| Name | Description |
|---|---|
| from_dynamics | Derive the schematic from a :class:Dynamics, reading populations off its state variables and connections off its equations. |
| plot | Render the schematic onto ax (created if None). Returns the axis. |
from_dynamics
plot.schematic.PopulationSchematic.from_dynamics(
dynamics,
n_areas=1,
long_range_synapse='AMPA',
synapse_map=None,
coupling_symbols=('c_glob', 'coupling', 'gx', 'local_coupling'),
)Derive the schematic from a :class:Dynamics, reading populations off its state variables and connections off its equations.
coupling_symbols names the symbols that mark a long-range input, which becomes a connection carrying long_range_synapse; synapse_map overrides the synapse inferred for a given connection.
plot
plot.schematic.PopulationSchematic.plot(
ax=None,
layout='stacked',
glyph='circle',
node_size=0.7,
self_loop=(0.62, 0.55),
coupling_blob=False,
ellipsis=None,
legend=True,
legend_labels=None,
legend_loc='below',
synapse_colors=None,
fontsize=None,
ranksep=1.15,
nodesep=1.0,
hide=None,
long_range_targets=None,
fill_width=2.6,
fit='tight',
figsize=(7.8, 4.0),
)Render the schematic onto ax (created if None). Returns the axis.
layout ∈ {stacked, mirror, row}; glyph ∈ {circle, neurons} or a callable(ax, x, y, r, sign, label); self_loop = (height, width) or None; coupling_blob shades a blob between the inner excitatory nodes (mirror layout); ellipsis draws … on both ends (defaults to True for stacked with N>1); legend_labels overrides the synapse legend text (e.g. {"AMPA": "AMPA, NMDA"}).
Hiding connections (declare in the figure caption when you do): hide — a predicate callable(Connection) -> bool to drop any connection; and long_range_targets — a convenience restricting long-range projections to those target populations (e.g. ["E"] = E→E only, no FFI, for the spiking Fig 1a view).
Width control (two independent knobs): fill_width (float, default 2.6) stretches the circuit horizontally to at least this width:height aspect (how wide the circuit spreads; None/0 disables); and fit controls how the axes box maps to that circuit — "tight" shrinks the box to the circuit (minimal whitespace, panels may differ in width) · "width" keeps the box’s given width and pads the data limits (panels in a mosaic column stay the SAME width) · a float forces that exact width:height box aspect. Circles stay round in all.
Functions
| Name | Description |
|---|---|
| plot_population_schematic | Convenience: derive a schematic from dynamics and render it (see PopulationSchematic). |
plot_population_schematic
plot.schematic.plot_population_schematic(
dynamics=None,
ax=None,
n_areas=1,
long_range_synapse='AMPA',
synapse_map=None,
**plot_kwargs,
)Convenience: derive a schematic from dynamics and render it (see PopulationSchematic).