Stage, geometry and field reference
What the registered stages (tasks C1–C12), geometries and fields (B2–B5) and sparse guidance (D2) do in the code on
main (2026-11-02, after the fix waves F1–F9). Roadmap items that are not implemented are marked Not implemented. Defaults are those of the code; a stage called without
a parameter uses them.
Conventions
A stage runs as
{"name": ..., "operator": ..., "params": {...}, "when": ..., "repeat": k}in a Project’sschedule(neurogenesis.stages.run_schedule). Each repeat gets its own random stream, seeded from (seed, stage name, repeat).Every parameter is a
Param(Const,Gene,Field,Fit,Expr; seeneurogenesis/params.py) or a plain value. AFieldparam gives per-cell values only where the stage passes cell positions toresolve; this is noted below as “per cell”. Elsewhere aFieldparam resolves to the field object itself and the stage fails.whenis an expression evaluated by the restricted evaluatorneurogenesis.expressions.eval_expr(noeval), withN,N_alive,E,rep,tissue,genome,np.Units: one tick = 1 ms; positions and distances in space units (the Project’s coordinates); weights and thresholds in integer kernel units. Delays are limited only by the storage bound of 255 ticks (multi-word spike history in all four kernels; stages accept a
max_delayParam).cost(N, E, params)returns (bytes, ops);neurogenesis.stages.base.schedule_costsums it over a schedule, andneurogenesis.devcost.estimate_development(command line:python -m neurogenesis estimate --project p.json) predicts N and E stage by stage, the peak memory and the time on this machine.Neutral means the stage leaves the tissue unchanged. Every toolbox stage called with empty params is a no-op (tested for every registered stage except
legacy_grow_stage, which needs itsplan).
Population (C1–C3, C14, neurogenesis/stages/population.py)
seed_cells (C1). Adds cells: N sampled uniformly in a geometry or placed at one position, a density
in a geometry, or a point set.
Param |
Default |
Meaning |
|---|---|---|
|
0 |
number of cells; |
|
none |
name of a geometry in the Project (or a |
|
none |
(3,) position used for all cells when |
|
0, 0 |
integer labels of the new cells |
|
0.0 |
standard deviation of a Gaussian offset added to each position (space units) |
|
none |
cells per unit volume in |
|
none |
upper bound of a density field (required with a field) |
|
none |
upper bound on the cells added with |
|
none |
a list of positions (2D points get z = 0), a pattern dict ( |
Limits: one of geometry / position / points is required (ValueError otherwise). The volume is measured by
Monte Carlo (65 536 points, about 1 % error) from the stage’s random stream; flat geometries are measured by area. The
cost assumes N = 100 (or max_cells) unless N is a constant.
proliferate (C2). Each cycling alive cell (Tissue.cycling) divides with probability prob; the daughter is appended, the mother stays.
Param |
Default |
Meaning |
|---|---|---|
|
0.0 |
division probability per cell and call (per cell; an |
|
0.1 |
standard deviation of the daughter’s Gaussian displacement from the mother (space units, per cell) |
|
none |
cell type of the daughters (per cell); if absent daughters copy the mother’s type |
|
none |
upper bound on alive cells; if divisions would exceed it, a random subset divides so the bound holds exactly |
|
0.0 |
probability that a division is asymmetric (needs |
|
none |
cell type of the new daughter in an asymmetric division; the mother keeps its type (Götz & Huttner 2005, Nat Rev Mol Cell Biol) |
|
0.0 |
standard deviation of Gaussian noise added to both daughters’ expression, clipped at 0 |
|
none |
birth stage given to new daughters; if absent, one more than the latest alive |
Daughters copy the mother’s region, expression, sign, cycling (True by default for cells from seed_cells and
proliferate) and neuron parameters and record parent_id and clone_id; both daughters get generation = mother's + 1
(Tissue.generation). Dead cells and postmitotic cells (cycling == False, e.g. from place_by_hand or
cell_cycle_clock) do not divide.
apoptosis (C3). Kills cells, then compacts the tissue (connectivity re-indexed).
Param |
Default |
Meaning |
|---|---|---|
|
none |
death probability per cell (per cell) |
|
none |
radius (space units, per cell) for counting neighbours |
|
10 |
cells with more than this many neighbours within |
|
none |
neurotrophic death: cells with fewer incoming / outgoing synapses die |
All criteria are off when absent. Neighbour counts use a dense N × N distance matrix for N <= 2048 and the cell list
(CellList, D1) above. Limits: synapse counts ignore weights and activity.
cell_cycle_clock (C14). Called once per cell cycle before proliferate (Takahashi, Nowakowski & Caviness 1995,
J Neurosci; 1996, J Neurosci; Caviness et al. 2000). Each cycling alive cell (Tissue.cycling) advances its cycle
counter (Tissue.generation) and leaves the cell cycle (cycling = False) with probability
Q(generation) = min(1, k · generation^a) or from a per-generation table Q (q_table).
Param |
Default |
Meaning |
|---|---|---|
|
0.0, 1.97 |
power-law parameters for |
|
none |
per-generation exit probability table (1-indexed by cycle |
|
none |
per-generation cycle length table or formula ( |
Leaving cells get cycling = False and their exit generation (birth cycle) and birth_time are frozen across later
cycles, while the immediately following proliferate completes the current cycle’s division for all cells that entered
the cycle (producing two postmitotic daughters for leaving progenitors and two cycling progenitors for self-renewing
ones). Reference neocortical profile: examples/profiles/cell_cycle_clock.json.
Migration and sorting (C4–C5, neurogenesis/stages/migration.py)
migrate (C4). Moves alive cells for steps sub-steps per call (Marín & Rubenstein 2003, Annu Rev Neurosci).
Param |
Default |
Meaning |
|---|---|---|
|
1 |
sub-steps per call; |
|
0.0 |
step length along |
|
(1, 0, 0) |
step direction (per cell, e.g. a vector field), normalised |
|
False |
step away from |
|
(0, 0, 0) |
centre for radial steps |
|
none, 0.0 |
move along the unit gradient of a named scalar field (central differences, step |
|
none, 0 |
a cell stops once its layer label (first column of the field, e.g. |
|
0.0 |
soft repulsion through the cell list: each cell of a pair closer than this moves half the overlap |
|
none |
evaluated at the new position; True or a value > 0 cancels the step for that cell |
|
none |
geometry name; a step that would leave it is cancelled |
|
False |
(per cell) remove the component of |
Limits: deterministic (no random motion). Tangential steps are straight, so they drift outwards by O(speed²/r) per
step. Not implemented: the inside-out layering test case as a test of migrate alone.
sort (C5). Two modes, run in this order when both are given; with neither, a no-op.
Ordering: reassigns the cells’ coordinates along
axisso that their order along it followskey("birth_stage","expression"(column 0) or a per-cell array), keeping the perpendicular coordinates.Differential adhesion (Steinberg 1963, Science): for
stepsiterations, neighbours withinradius(cell list) attract or repel according toadhesion[type_i, type_j](negative = repulsion), at raterate; cells closer thancontact(defaultradius / 2) push apart. The matrix must cover every living cell’s type.
Param |
Default |
Meaning |
|---|---|---|
|
(0, 0, 1), |
ordering mode (active when either is given) |
|
none |
types × types matrix (adhesion mode) |
|
0.1, radius/2, 0.1, 1 |
adhesion-mode interaction radius, contact distance, rate, iterations |
Limits: no random motility, so weak cross-type adhesion gives local clumps rather than full separation.
mosaic (C5). Homotypic exclusion zones: for steps iterations, living cells of the same type closer than
radius move apart by rate × half their overlap (cell list), plus optional Gaussian motility jitter from the stage
random stream; types restricts it to some cell types and boundary keeps cells in a geometry. This raises the
nearest-neighbour regularity index of each type (Galli-Resta et al. 1997, J Neurosci); other types are ignored.
Param |
Default |
Meaning |
|---|---|---|
|
0.0 |
exclusion radius (space units); <= 0 is the no-op |
|
1, 1.0, 0.0 |
iterations, fraction of the overlap removed, motility std |
|
all, none |
cell types that interact; geometry that cells may not leave (cells already outside it move freely) |
Expression and differentiation (C6–C7, C15, neurogenesis/stages/differentiation.py)
express (C6). One gene-regulatory step on the expression matrix (N, K):
E ← E·(1 − decay·dt) + sigmoid(W·E + Σ_m f_m·w_m + W_n·Σ_neighbours E)·dt.
Param |
Default |
Meaning |
|---|---|---|
|
0 |
number of genes; |
|
zeros |
K × K regulatory weights |
|
[] |
list of |
|
0.0 |
contact radius (space units) for neighbour input through the cell list; 0 disables it |
|
zeros |
K × K weights |
|
1.0, 0.0 |
step size and linear decay rate |
|
|
|
|
2.0, 1.0 |
Hill coefficient and half-activation input |
|
unset |
K distinct gene names stored in |
|
[] |
genes (names or column indices) set to 0 in every cell after the step (a null allele) |
Dead cells are kept (only the runner compacts). Limits: with K > 0 the step is not a no-op even with zero weights (sigmoid(0) = 0.5 is
added); weight matrices of the wrong shape are silently replaced by zeros (the Hill activation is 0 for zero input). The
cost is O(N K²) (plus the cell-list query when radius > 0) and uses a Gene’s upper bound for K.
differentiate (C7). Applies a rule table types: for each entry, in order, cells matching condition get the
listed properties (later entries override earlier ones).
Entry key |
Meaning |
|---|---|
|
cell type set on matching cells (default 0) |
|
expression over |
|
sign and weight magnitude; |
|
neuron parameters set on the matching cells |
Every value in an entry (sign, base_weight and the neuron parameters) may be a Param; a Field value
is applied per cell. An empty or absent types is a no-op. Limits: type_id and condition are plain values; a
condition must give one value per cell.
temporal_competence (C15). Progressive, irreversible progenitor competence cascade (McConnell & Kaznowski 1991,
Science; McConnell 1995, Neuron; Isshiki et al. 2001, Cell). Updates competence channels in Tissue.expression for
cycling alive cells (alive & cycling, plus cells exiting in the current cycle’s cell_cycle_clock); postmitotic cells
from earlier cycles keep their competence frozen.
Param |
Default |
Meaning |
|---|---|---|
|
none (no-op) |
list of cascade specs |
|
none |
optional list of |
|
|
intrinsic competence driver ( |
|
none |
optional environmental |
differentiate conditions read expr[c] (or generation), so one rule table assigns birth-order-dependent fates.
Reference neocortical birth-order windows: examples/profiles/temporal_competence.json.
Connectivity (C8–C9, neurogenesis/stages/connectivity.py)
cluster_boutons (C19). Cell-type specific connection multiplicity.
Param |
Default |
Meaning |
|---|---|---|
|
none |
a dict of |
grow_axons (C8). The guidance rules of neurogenesis.development.rules as a stage, per projection
(source region → target region). Target point sigmoid(4·(x_src − 0.5)·Bᵀ + c) in local [0, 1]³ coordinates, then
p = p0·exp(−d²/2σ²) over target cells, one Bernoulli draw per pair.
Param |
Default |
Meaning |
|---|---|---|
|
the |
list of |
|
none |
per projection ( |
|
[] |
rule names applied in order; unknown names raise |
|
1.0 |
space units per tick; delay = round(distance / velocity) clipped to [1, |
|
unlimited (255, the storage bound) |
ticks; also a Param of |
|
512, 1.0 |
weight clip and inhibitory factor (overridden per projection by |
|
unset |
unset: dense Ns × Nd when max(Ns, Nd) <= 2048, else sparse guidance (D2, cell list); |
|
{} |
region names → ids; region boxes for local coordinates (default: the bounding box of the region’s cells); per-region identities |
Guidance values are resolved at any depth, so a Gene may be one entry of B. Weights are w · (1 or −inh) · U(0.9, 1.1), rounded and clipped. The stage does not read
genome["guidance"] (use Gene values inside guidance), and raises ValueError when neither projections nor
guidance is given, when a listed projection has no guidance entry, or when a region name is not in region_map; a
region without alive cells is a no-op for that projection. Target rules (e.g. topographic, lamina,
expression_gradient, which reads the source cells’ named expression columns) run before the dense or sparse path,
so both paths support them. Limits: the dense path uses O(Ns·Nd) memory (only up to 2048 cells per side by default); no probability rule (not even no_autapse) applies unless listed; the sparse path supports only the
identity_expression, no_autapse and source_sign probability rules and uses a fixed cutoff of 5σ.
place_by_hand (C9). Appends cells at explicit positions (M, 3), with region (0), cycling (False by
default) and optional cell_type, birth_stage, sign, mode, shift_v, shift_s, base_weight, threshold,
directions (scalars or one value per cell). No positions = no-op.
connect_by_hand (C9). Appends synapses pre[i] → post[i] (current cell indices, not cell ids) with weight
(1.0, truncated to an integer) and delay (1 tick). Indices outside [0, N) and delays outside [1, 255] raise
ValueError. Empty lists = no-op. Two more supervised inputs (run before the index lists):
matrix: a dense N × N weight matrix (row = pre, column = post, 0 = no synapse), allowed up to N = 2048 cells, withdelay_matrix(N × N) or a scalardelay.rules: a list of connection rules, each{pre, post, prob, weight, delay | velocity, max_distance, sigma, dale, allow_autapse}.pre/postselect living cells by a dict ofregion/cell_typevalues or a boolean expression overcell_type,region,birth_stage,generation,sign,x,y,z. Withoutmax_distancethe number of synapses is drawn from Binomial(N_pre · N_post, prob) and distinct pairs are drawn without building an N_pre × N_post array (O(E)); withmax_distancecandidates come from the cell list, each kept withprob(times exp(−d²/2σ²) withsigma).velocitysets delay = round(distance / velocity) clipped to [1, 255] with a warning;dalegives each synapse the presynaptic sign; autapses are dropped unlessallow_autapse. Values may beParams.
Maturation (C10–C12, neurogenesis/stages/refinement.py)
Plasticity mask (K6). tissue.connectivity.plastic is an optional per-synapse bool array; absent (None, the
default) means every synapse is plastic and the stages below behave exactly as without it. Synapses with
plastic == False keep their weight in refine_by_activity, scale and neuromodulate and are never removed by
prune (scale still counts them in each cell’s incoming sum). The mask follows take / concat / append,
compact, subset, concatenate; new synapses are plastic. to_network / from_network carry it only as the
in-memory attribute _plastic of the network (network files do not store it).
prune (C10). Removes synapses with |w| < threshold (default 0, neutral). With min_coactivity, it also
removes synapses whose presynaptic spikes, arriving after the synapse delay, were followed by a postsynaptic spike
within window ticks (default 5) fewer than min_coactivity times (“use it or lose it”, Katz & Shatz 1996, Science).
Activity comes from spikes (a (T, N) raster) or a lif_int simulation of ticks (100) with optional
ext_current; dead cells are compacted first. Cost O(T · E).
scale (C10). Multiplies each cell’s incoming weights so that their absolute sum equals target, then rounds to
integers. Without target it is a no-op. rate (default 1) moves only that fraction of the way per call
(1 + rate · (factor − 1)), a discrete time constant (Turrigiano et al. 1998, Nature). Limits: small weights can round
to 0.
refine_by_activity (C11). Simulates the tissue with the JAX lif_int kernel for ticks, then applies a plasticity
rule of neurogenesis.spiking.plasticity once to the weights. Dead cells are compacted first.
Param |
Default |
Meaning |
|---|---|---|
|
100 |
simulated ticks (ms) |
|
none (no-op) |
|
|
none |
cell ids (or indices) made Poisson drivers ( |
|
False |
restore every cell’s |
|
none |
external current per cell (array, or |
|
none |
a (ticks, N) spike raster used instead of simulating |
|
none |
spontaneous waves: |
|
none |
motor twitches with sensory feedback: |
|
false |
keep the (ticks, N) spike raster on the tissue ( |
Without rule the stage is a no-op . Limits: plasticity acts on magnitudes and keeps synapse signs; weights
are cast to integers. The three-factor eligibility counts arrivals that coincide with a postsynaptic spike in the same tick. Not implemented: pruning inside the stage (follow with prune), other neuron models.
competitive_elimination (C22, neurogenesis/stages/competition.py). Competitive synapse elimination (Willshaw
1981, Proc R Soc Lond B; Gouzé, Lasry & Changeux 1983, Biol Cybern; Balice-Gordon & Lichtman 1994, Nature). Each
input’s score is its coactivity with its target (presynaptic spikes, after the delay, followed by a target spike within
window ticks, default 5). On every target that spiked at least min_target_spikes times (default 1), inputs scoring
below fraction (default 0 = no-op) of the best input onto that target lose delta (default 0) of their magnitude
(sign kept, floored at 0) or, with remove (default false), are removed. Silent targets change nothing; synchronous
inputs score alike and are all kept; non-plastic synapses (K6) compete but are never changed. Activity: spikes (a
(T, N) raster) or the raster recorded by refine_by_activity with record: true; without either it is a no-op
(ticks, default 100, only sizes the cost). Grouping by target: one sort and np.maximum.reduceat; cost O(T · E).
Differs from prune (absolute weight or coactivity thresholds).
partner_select (C18, neurogenesis/stages/partner.py). Keeps a candidate synapse with probability
compat[i][j] (a Param matrix, pre channel i × post channel j, clipped to [0, 1]). A cell’s channel is its
cell_type (default), the argmax of its expression (channels: "expression") or an explicit per-cell list; channels
outside the matrix are kept. Filters synapses from grow_axons, arbor_synapses or connect_by_hand; an identity
matrix reproduces the identity_expression rule. Neutral: no compat = no-op. Cost O(E). Transmitter–receptor
matching (P2) is not implemented.
fasciculate (C16, neurogenesis/stages/fasciculation.py). Follower axons bundle along pioneer tracts through
homophilic adhesion (L1, NCAM, Fasciclin II). For morphological arbors, active neurite growth cone nodes steer towards
nearby pioneer branch tangents within radius, weighted by adhesion_matrix [pre_type, post_type]; defasciculation
occurs where defasciculation_field exceeds threshold. For point-to-point connections, bundles correlate target
offsets. Neutral: no adhesion_matrix = no-op. Cost O(N + E).
choice_point (C17, neurogenesis/stages/fasciculation.py). Midline and choice points where guidance receptors or target
rules switch. When cells or growth cones enter a choice point geometry or choice_field, guidance receptor channels
are updated (e.g. switching attraction to repulsion to prevent re-crossing). For projections, routes via an intermediate
waypoint_region. Neutral: no geometry, choice_field or waypoint_region = no-op. Cost O(N + E).
tissue_expand (C24, neurogenesis/stages/expansion.py). Dilates the positions of living cells about a centre
(default: their centroid) by 1 + kappa * N_new / N_total along the chosen axes, where N_new counts the cells
added since the previous call. Proliferation then pushes existing cells outward, so density stays bounded while the
count grows (in this simulation, with kappa 0.668 and growth x1.5 per cycle: about x5 per tangential axis over 8 cycles).
The first call only records the count (or give n_prev); call it once before the first proliferate. Synapses keep
their delays unless recompute_delays (with conduction_velocity, max_delay). Neutral kappa 0 = no-op. Cost O(N).
critical_period_gate (C23, neurogenesis/stages/critical_period.py). Opens and closes a critical period of
plasticity by setting the K6 plastic mask of the gated synapses (those onto target_type cells, all by default):
False before opening, True while open, False after closing. Opening when the maturity of inhibition from
source_type cells reaches open_threshold, closing after close_after gate calls or when maturity reaches
close_threshold, as maturing parvalbumin-cell inhibition opens and perineuronal nets close the ocular-dominance
critical period (Hensch 2005, Nat Rev Neurosci; Hubel & Wiesel 1970, J Physiol); reopen restores plasticity, as
removing the nets with chondroitinase ABC does (Pizzorusso et al. 2002, Science). Call it before each plasticity stage;
its state (phase, gate calls since opening) is kept on the tissue as _critical_period (not carried by subset /
concatenate). Synapses added later are plastic until the next call.
Param |
Default |
Meaning |
|---|---|---|
|
none |
cell type id(s) whose inhibitory (w < 0) synapses measure maturity |
|
all cells |
cell type id(s) whose incoming synapses are measured and gated |
|
|
|
|
none |
a maturity value ( |
|
none |
opens when maturity >= this |
|
false |
open / close now (place the entry at the wanted stage index of the schedule) |
|
none |
closes this many gate calls after opening |
|
none |
closes when maturity >= this (ignored after a reopening) |
|
false |
reopens: plastic again, |
Neutral: without open_threshold, open, close and reopen the stage is a no-op (any of them activates the gate,
so before opening the gated synapses are not plastic). Cost O(N + E). Mouse and cat ages: examples/profiles/critical_period_gate.json.
myelinate (C12). Multiplies delays by factor (alias delay_factor; absent = no-op; 1.0 is neutral), rounds
and clips to [1, max_delay] ticks (default 255) with a warning when clipped. By default every synapse is scaled; given criteria select
synapses passing all of them: min_delay (long projections, ticks), pre_region / post_region (lists of region
ids), min_rate (presynaptic rate in Hz, from spikes or a simulation of ticks; activity-dependent myelination,
Gibson et al. 2014, Science; needs a compacted tissue).
freeze (C13, neurogenesis/stages/freeze.py). Validates the tissue (finite positions, synapse indices in
range, delays in [1, 255], |weight| <= 32767 and, with dale, outgoing signs equal to the presynaptic sign) and raises
FreezeError listing every problem; the tissue is unchanged. With path it writes the compiled network (NGB1 for a
.ngb suffix, else JSON). The functions freeze(tissue) → SNNNetwork and develop(project, genome, seed) (run the
schedule, then freeze) do the same from Python.
Arbors (N1–N3, neurogenesis/arbors.py, neurogenesis/stages/arbors.py)
ArborStore holds the trees of all cells as struct of arrays: xyz, radius, parent (−1 = root, always
parent[i] < i), compartment (0 undefined, 1 soma, 2 axon, 3 dendrite, 5 neurite, other integers are user labels)
and cell (index into the tissue). It lives in Tissue.morphology and follows compact, subset and concatenate.
path_length_to_root, depth (pointer jumping, O(M log depth)), take (drop nodes, children re-attached to the nearest
kept ancestor), downsample(step) and to_budget(max_nodes_per_cell) (keep roots, branch points, terminals and
compartment changes); read_swc / write_swc for SWC files (scale converts units).
grow_arbors (N2). Grows neurites from each selected cell’s soma for steps steps (absent or <= 0 = no-op).
Param |
Default |
Meaning |
|---|---|---|
|
|
label of the new nodes ( |
|
1 |
tips started per cell (per cell, read at the soma) |
|
1.0, 0.2 |
elongation per step (space units); Gaussian turning (radians) |
|
0.0, 0.5 |
branching probability per tip and step; angle of the new branch |
|
0.0, 0.0 |
stop probability per tip and step; removal probability of each new terminal at the end |
|
random |
initial direction (vector, or per cell) |
|
none, 0.0 |
tips turn up the gradient of this scalar field (negative: down) |
|
none |
a step into |
|
all, 0, 10⁶ |
|
arbor_synapses (N3). Synapses from geometric proximity (Peters’ rule): axonal nodes (pre_compartments,
default axon and neurite) within contact_distance of dendritic nodes (post_compartments, default dendrite, neurite,
soma) of another cell, found through the cell list over nodes. Each contact is kept with p_contact (1.0), at most
max_per_pair (1) per cell pair, closest first. Delay = round(axonal path length / axon_velocity (1.0) +
dendritic path length / dendrite_velocity (ignored if absent)), clipped to [1, 255] ticks with a counted warning.
Weight weight (1) with the presynaptic sign (dale, True). Each synapse records pre_node, post_node,
path_length and dendritic_distance. No arbors or no contact_distance is the no-op. The cost assumes 50 nodes per
cell unless expected_nodes is given.
Pharmacology (P1–P3, neurogenesis/pharmacology.py, neurogenesis/stages/pharmacology.py)
A profile (JSON: id, transmitters (at most 7, bit k of Tissue.transmitter), receptors) maps each receptor
class (the value of a synapse’s receptor_class) to a transmitter, a sign (+1, −1 or "pre": the weight keeps
its sign), a gain (number or Param), optional reversal_mV, tau_ms (recorded for conductance models) and
contexts ({context: {sign, gain}}, e.g. depolarising GABA-A in immature neurons, Ben-Ari 2002, Nat Rev Neurosci).
load_profile takes a dict, a path, or an id searched in $NEUROGENESIS_PROFILES and ./profiles/. The default
profile (one classic receptor, sign "pre") changes no weight, so existing networks keep their fingerprints. An
example profile with cited entries is in examples/profiles/example_receptors.json.
set_transmitters:rules= [{condition,transmitters: [names],add}] set each cell’s transmitter bitmask (co-transmission: several names; Dale’s principle is not enforced).express_receptors:rules= [{condition,receptor,level(aFieldis read per cell)}] setTissue.receptor_expression(one column per receptor of theprofile).assign_receptors: each synapse’s receptor class among the receptors whose transmitter the presynaptic cell releases, in proportion to their postsynaptic expression (mode"sample"from the stage stream, or"max"); synapses without an expressed candidate keep their class. O(E R).pharmacology: compiles weights in acontext: sign from the receptor, magnitude × gain, and synapses whose presynaptic cell lacks the receptor’s transmitter set to 0 (require_transmitter). Run it in context"immature"beforerefine_by_activityand"mature"after it for a sign switch during development; gains multiply at every call, so give gains other than 1 in one compilation only.transporter_switch(C21): per-cell chloride reversal potential from maturation, the NKCC1 → KCC2 switch (Rivera et al. 1999, Nature; Ben-Ari 2002, Nat Rev Neurosci). E_Cl =e_immature+ (e_mature−e_immature) · sigmoid((age −midpoint+activity_gain·activity) /width). Age isage(aParam) ornowminus the cell’sclock("birth_time", default, in the unit ofcell_cycle_clock’s T_C;"birth_stage", stage index;"generation", cycles);nowdefaults to the largest clock value (youngest cell: age 0);midpoint(0) andwidth(1) are in the age’s unit.activity(per cell, default 0:refine_by_activitydoes not record it yet) advances the switch byactivity_gain(0 = purely programmed). Synapses whosereceptor_classis inreceptors(names inprofile, or indices) gete_rev= E_Cl of their postsynaptic cell, used by the conductance models (two_compartment,hh);lif_intignorese_rev, so withv_rest(mV) their weights also take the sign of E_Cl −v_rest. Run it afterpharmacology(which rewritese_revfrom the profile). Withoutreceptors,e_immatureore_mature: no-op. O(N + E). Rodent defaults (E_Cl −45 → −75 mV, switch P5–P10) with citations:examples/profiles/transporter_switch.json. Conditions use the variables ofdifferentiateconditions. Each stage without its params (rules/profile) is a no-op. Conductance-based synapses (P4) are in the spiking models (docs/NEURON_MODELS.md) and neuromodulation (P5) is theneuromodulatestage below. Not implemented: the legacyreceptor_signrule is not re-expressed as a profile.
Neuromodulation and dendrites (P5, N5, neurogenesis/neuromodulation.py, neurogenesis/dendritic.py)
neuromodulate (P5). Three-factor plasticity (spiking.plasticity.ThreeFactorRule) over a recorded spike raster
spikes (T × N array, a plain value), gated by a modulator released by modulator_cells (volume transmission). The
level at a cell is the sum over modulator cells of their spike trains filtered with tau_ms, weighted by
exp(−distance / space_constant); dw = eta × eligibility × level, the eligibility summing pre-synaptic arrivals
(after the synaptic delay) that coincide with post-synaptic spikes, filtered with tau_e. Weights keep their sign and
their magnitude is clipped to [w_min, w_max]; synapses with plastic == False (K6) keep their weight. Every
parameter but spikes is a Param (a Gene-controlled eta is tested); a Field resolves to the field object, so use
scalar sources.
Param |
Default |
Meaning |
|---|---|---|
|
none |
cell indices releasing the modulator (none or empty = no-op) |
|
50.0, 50.0 |
spatial decay (space units) and time constant (ticks) of the modulator |
|
0.05, 50.0 |
learning rate; eligibility time constant (ticks) |
|
20.0, 20.0 |
accepted for a timing-dependent eligibility; the current rule does not use them |
|
0.0, 1000.0 |
bounds of the weight magnitude |
|
all rows |
rows of |
No |
||
receive synapses, in blocks of at most 2²⁰ pairs; memory is O(T N) (the per-cell modulator level) and time |
||
O(T S P + T E) for S modulator cells and P postsynaptic cells. The spike raster must be supplied (the stage does |
||
not simulate). |
dendritic_attenuate (N5). Passive dendritic filtering: each synaptic weight is multiplied by
exp(−d / length_constant), where d is the synapse’s dendritic distance (computed from post_node and the
morphology’s path length to the soma when missing); a non-zero weight keeps a magnitude of at least 1. With
dendrite_velocity, round(d / velocity) ticks are added to the delay; with distal_compartment_threshold, the target
cells of synapses at or beyond that distance are marked compartment 1 (distal).
Param |
Default |
Meaning |
|---|---|---|
|
100.0 |
dendritic length constant (space units); a |
|
none |
space units per tick for the added dendritic delay; a |
|
none |
distance (space units) beyond which targets are marked distal; a |
Empty params = no-op. Limits: synapses without a dendritic distance are left unattenuated; the added delays are still
clipped to max_delay (default 255 ticks), with a warning when clipped.
Geometry (B2, neurogenesis/geometry/mesh.py, voxel.py)
mesh(MeshGeometry(vertices, faces, resolution=32),from_obj,from_stlfor ASCII and binary STL).containsby ray parity, vectorised over points and faces in blocks of at most 2²⁰ pairs;sample_pointsdraws uniformly in aresolution³ voxel cache (inside and surface voxels) and keeps points that pass the exact test. JSON stores vertices, faces and resolution as lists.voxel_mask(VoxelMaskGeometry(mask, origin, pitch)): a boolean (X, Y, Z) occupancy array;containsby lookup,sample_pointsuniform over occupied voxels.from_npz/save_npzread and writemaskwith an axis-aligned 4 × 4affineororigin+voxel_size(a rotated affine raises); a file-backed mask serialises as{"type": "voxel_mask", "npz": path}.
Fields (B3–B5, neurogenesis/fields/)
Fields are evaluated with values(points) and registered by type name in the Project’s fields. run_schedule binds
each field to the run’s genome (Field.bind), so Param values inside a field are resolved.
GridField(data, origin, spacing, method="nearest")(B3): 2D or 3D grids, scalar or with trailing vector components;nearestorlinear(bilinear,trilinear) sampling, clamped at the edges.AnalyticField(expr)(B3): an expression inx,y,z,exp,sin,cos,piand whitelisted NumPy functions, evaluated by the restricted evaluator.VectorField(stacked scalar fields) andLabelField(integer labels on a grid, nearest lookup, a background value outside, optional names) (B3).LayerStackField(base_field, thicknesses, labels=None)(B3): the base field is a depth; returns(label, w)per point,win [0, 1] the relative depth inside the layer. Thicknesses are numbers orParams.Point patterns and maps (B4,
maps.py):regular_points,jittered_points,poisson_disc_points(minimum distanceradius) return point arrays;PointSetFieldregisters a point set as a field (givenpoints, or apatternwithbounds,spacing/jitter/radiusand its ownseed, regenerated identically on load); its values are the distance to the nearest point (cell list), andseed_cellsaccepts it aspoints.PinwheelFieldgives an orientation angle in [0, π) from singularities with charges (pinwheel_mapreturns it sampled on a grid);pinwheel_chargesmeasures the charge around given centres;find_pinwheels(angles, origin, spacing)locates the pinwheels of any 2D angle grid (winding of 2θ around each grid square, charge ±1/2);bandpass_pinwheels(..., return_pinwheels=True)also returns the positions and charges of its pinwheels.Operations (B5,
ops.py, NumPy only):Add(a, b),Subtract(a, b),Multiply(a, b)(fields or constants),Threshold(field, threshold, below, above),GaussianSmooth(grid_field, sigma),DistanceTransform(bounds, spacing, target_points)(distance to a point set on a grid),Gradient(of a grid field, or central differences for any field),DistanceToBoundary(distance to a geometry’s or a label region’s boundary, optionally signed, grid-based with error under one spacing). Composite fields passbind(genome)to their sub-fields, andcollect_project_genesfindsGenes inside field definitions. Large operations work in blocks of at most 2²⁰ pairs.
Sparse guidance (D2, neurogenesis/development/sparse_guidance.py)
sparse_guidance(ctx, plan, rng, c=5.0, exact=False) returns (pre, post, p) for one projection. With exact=True it
computes the dense probabilities and draws exactly as the dense code. With exact=False it queries target cells within
c·σ of each target point through CellList (memory O(candidates)) and supports only the identity_expression,
no_autapse and source_sign probability rules (others raise NotImplementedError). Limits: the sparse mode draws
different random numbers from the dense mode, so it does not reproduce dense networks for the same seed; the legacy
grow() does not use it, and it is not the default for large tissues (grow_axons uses it only with exact=False).