lowering

adapters.smallscale.lowering

Backend-neutral network lowering for small-scale simulators.

The functions here turn a TVB-O Network (nodes with size, edges with a connectivity rule, Dynamics/Coupling/Event biology) into the two structures every point-neuron backend needs:

  • populations — nodes grouped by their Dynamics, each a block of Node.size cells, with a stable base index per node so edges can address individual cells; and
  • connections — the explicit cell-to-cell :class:ConnectionRecord set that a connectivity rule (all_to_all/one_to_one) lowers to, with self-connections filtered and per-connection weight/delay extracted.

Everything here is independent of how a backend emits a synapse — that (LEMS XML, Brian2 Synapses, …) stays in the backend adapter. The backend injects its own role vocabulary (which Dynamics are cells vs current sources vs event sources) so the same lowering serves NeuroML, Brian2 and the rest unchanged.

Classes

Name Description
ConnectionRecord One lowered cell-to-cell connection — the contract every backend consumes.

ConnectionRecord

adapters.smallscale.lowering.ConnectionRecord()

One lowered cell-to-cell connection — the contract every backend consumes.

Produced by connectivity-rule expansion; a plain dict at runtime so templates and adapters can index it directly. The neutral core is from_pop/from_idxto_pop/to_idx through synapse with an optional per-connection weight/delay. from_rule records whether the connection came from a lowered connectivity rule (vs a single explicit edge). Backends may attach their own keys (e.g. conn_class for LEMS projection classification) without changing this core.

Functions

Name Description
assign_cell_population Assign a cell population id and per-node base indices, filling the maps.
classify_node_role Classify a node group as a cell, current-input, or event-source.
connectivity_pairs Expand a population-level connectivity rule into (src_idx, tgt_idx) pairs.
expand_edge_connections Yield (from_idx, to_idx, from_rule) for one synapse edge.
expand_input_targets Local target cell indices an input edge fans out to.
group_nodes_by_dynamics Group nodes by their Dynamics name, preserving first-encounter order.
merge_params Merge parameter dicts with later dicts overriding earlier ones.
node_dynamics_name The Dynamics name a node runs.
safe_id Make a string safe for XML id attribute.
unique_component_id A component id derived from name that no other component already holds.

assign_cell_population

adapters.smallscale.lowering.assign_cell_population(
    dyn_name,
    group_nodes,
    node_pop_map,
    node_size_map,
)

Assign a cell population id and per-node base indices, filling the maps.

Each node contributes Node.size cells laid out contiguously; the running base index lets an edge address an individual cell within the population. Mutates node_pop_map (node_id -> (pop_id, base)) and node_size_map (node_id -> size) in place, and returns (pop_id, node_ids, size).

classify_node_role

adapters.smallscale.lowering.classify_node_role(dyn_name, dyn_lib_obj, vocab)

Classify a node group as a cell, current-input, or event-source.

The biological type is read from Dynamics.iri (neuroml:<type>); a Dynamics without such an iri is a plain cell named by itself. vocab is the backend’s role vocabulary — a mapping with current_input and event_source keys to sets of type names — so the same lowering serves any backend by swapping the sets.

Returns (role, nml_type) with role one of "cell", "current_input", "event_source".

connectivity_pairs

adapters.smallscale.lowering.connectivity_pairs(rule, src_size, tgt_size)

Expand a population-level connectivity rule into (src_idx, tgt_idx) pairs.

Given the ConnectivityRule (or its string value) and the source/target population sizes, yields the local cell-index pairs a projection (or per-cell input list) enumerates. This is the “allToAll lowering”: the user declares one population-to-population Edge and the adapter generates the i x j connection set, so no O(N**2) explicit edges ever appear in the input.

Self-connection filtering (the diagonal of a self-projection) is applied by the caller on the resolved global cell indices, so this helper simply yields the raw pattern.

Parameters

Name Type Description Default
rule Connectivity pattern (all_to_all or one_to_one). required
src_size Number of cells in the source population. required
tgt_size Number of cells in the target population. required

Yields

Name Type Description
(src_idx, tgt_idx) local cell indices.

expand_edge_connections

adapters.smallscale.lowering.expand_edge_connections(
    edge,
    *,
    src_pop,
    src_base,
    tgt_pop,
    tgt_base,
    src_size,
    tgt_size,
)

Yield (from_idx, to_idx, from_rule) for one synapse edge.

An Edge with a connectivity rule is a population-to-population projection: expand it into the individual cell-to-cell connections here, skipping the diagonal of a self-projection when allow_self_connections is False. Without a rule the Edge is a single explicit cell-to-cell connection. from_rule marks whether the connection came from a lowered rule.

expand_input_targets

adapters.smallscale.lowering.expand_input_targets(tgt_base, tgt_size, rule)

Local target cell indices an input edge fans out to.

A connectivity rule attaches an independent copy of the input component to every target cell (rule expansion over a size-1 “source”); without a rule the input hits the node’s base cell only.

group_nodes_by_dynamics

adapters.smallscale.lowering.group_nodes_by_dynamics(nodes, default_dyn_name)

Group nodes by their Dynamics name, preserving first-encounter order.

merge_params

adapters.smallscale.lowering.merge_params(*param_dicts)

Merge parameter dicts with later dicts overriding earlier ones.

The canonical order is dynamics-library → node/edge → per-connection, i.e. the same precedence as the {**dyn, **node, **edge} spreads the backends build by hand. Keys are taken verbatim; values are not copied.

node_dynamics_name

adapters.smallscale.lowering.node_dynamics_name(node, default_dyn_name)

The Dynamics name a node runs.

Node.dynamics is a name-reference slot, so it may arrive as a bare name or as a resolved Dynamics; a node that declares none falls back to default_dyn_name — the experiment’s top-level dynamics. One rule, shared by every backend, so they cannot disagree about which model a node runs.

safe_id

adapters.smallscale.lowering.safe_id(s)

Make a string safe for XML id attribute.

unique_component_id

adapters.smallscale.lowering.unique_component_id(name, taken, kind='component')

A component id derived from name that no other component already holds.

Components are named after their Dynamics, so two differently parameterised uses of one Dynamics would collide and the second would be dropped.

Parameters

Name Type Description Default
name the Dynamics name to derive the id from. required
taken ids already assigned; the returned id is added to it. required
kind what is being named, for the disambiguation warning. 'component'

Returns

Name Type Description
safe_id(name), or that with a numeric suffix when it is taken.