NMT Single-Neuron Compatibility
SNNLab implementation of the Neuromorphic Toolbox's sigmoid-gated sodium/potassium neuron.
Abstract
Task 1 of the Neuromorphic Toolbox proposal (P23) asks us to reproduce a single sodium/potassium spiking neuron’s response to a current step in SNNLab, then compare its voltage and spike times with Toolbox reference traces.
Results
Single-neuron current response
The current step produces 4 spikes. The sodium gate responds faster than the potassium gate; the delayed rise in potassium conductance accompanies repolarisation and the voltage undershoot after each spike (Figure 1).
A: membrane voltage in black; red dots mark sampled upward −20 mV crossings. B: sodium gate voltage in black and potassium gate voltage in red; these are filtered voltages, not gate probabilities. C: corresponding sodium and potassium conductances, with the same colours. D: injected current, held constant over each input interval. All panels share the same time axis; the dashed line marks current onset at 10 ms. States are sampled after each timestep, with initial values added at zero for display. Capacitance, conductance and current use the consistent nF/µS/nA convention; the proposal does not specify their units explicitly.
Methods
1. Implement the proposal’s equations
The proposal defines a leaky membrane with sodium and potassium currents. For each channel , the gate voltage follows membrane voltage with time constant :
Here is time in ms, and are in mV, is in ms, is the channel conductance, is its maximum conductance, is the sigmoid slope in mV, and is its midpoint in mV. The sigmoid maps the dimensionless argument to a value between zero and one; itself is a voltage, not a probability.
The membrane equation is
Here is membrane capacitance, is injected current, is leak conductance, is the leak reversal potential, and and are the sodium and potassium reversal potentials. We embed the proposal’s numerical values in nF, µS and nA, which are consistent with mV and ms; the proposal does not explicitly label the capacitance, conductance or current units. Saved values appear in the appendix.
Forward Euler must advance the gates before the membrane. At timestep index , with step length , we compute
Superscripts denote sampled timesteps; applies over . The gate and conductance updates produce panels B and C, and the membrane update produces panel A. There is no voltage reset.
2. Express the dynamics as SNNLab extensions
The implementation below is loaded directly from this experiment’s
custom/dynamics.py. SNNLab supplies the previous tensor state, timestep,
configuration and incoming currents through NeuronContext. The callback
returns the new state and binary upward-crossing events. The initializer
sets voltage and both gates to −70 mV; the synapse passes current unchanged.
import torch
def conductances(voltage_na, voltage_k, cfg):
return (
cfg["g_na_us"]
* torch.sigmoid(cfg["gamma_na_per_mv"] * (voltage_na - cfg["bias_na_mv"])),
cfg["g_k_us"]
* torch.sigmoid(cfg["gamma_k_per_mv"] * (voltage_k - cfg["bias_k_mv"])),
)
def initial_state(ctx):
voltage = torch.full(
ctx.shape,
ctx.config["initial_voltage_mv"],
dtype=ctx.dtype,
device=ctx.device,
)
g_na, g_k = conductances(voltage, voltage, ctx.config)
return dict(
voltage=voltage,
z_na=voltage.clone(),
z_k=voltage.clone(),
g_na=g_na,
g_k=g_k,
)
def step(ctx):
cfg, state, dt = ctx.config, ctx.state, ctx.dt_ms
voltage = state["voltage"]
z_na = state["z_na"] + dt / cfg["tau_na_ms"] * (voltage - state["z_na"])
z_k = state["z_k"] + dt / cfg["tau_k_ms"] * (voltage - state["z_k"])
g_na, g_k = conductances(z_na, z_k, cfg)
ionic = (
cfg["leak_us"] * (voltage - cfg["leak_reversal_mv"])
+ g_na * (voltage - cfg["e_na_mv"])
+ g_k * (voltage - cfg["e_k_mv"])
)
current = ctx.excitatory - ctx.inhibitory
updated = voltage + dt * (current - ionic) / cfg["capacitance_nf"]
threshold = cfg["spike_threshold_mv"]
spikes = ((voltage < threshold) & (updated >= threshold)).to(voltage.dtype)
return {
**state,
"voltage": updated,
"z_na": z_na,
"z_k": z_k,
"g_na": g_na,
"g_k": g_k,
}, spikes
def inject_current(ctx):
"""Pass the projected signed current unchanged, without decay or clipping."""
return {"value": ctx.drive.to(ctx.state["value"].dtype)}
The recipe registers these importable callbacks once per process, then uses
CustomNeuron and CustomSynapse in the authored network. This registration
excerpt exposes the gate voltages and conductances as named state ports:
from snnlab import extensions, lang
from experiments.exp146.custom import dynamics
extensions.register_neuron(
"pinglab.exp146.toolbox_ei/v1",
dynamics.step,
initialize=dynamics.initial_state,
input_unit="nA",
state_units={"z_na": "mV", "z_k": "mV", "g_na": "uS", "g_k": "uS"},
capture_safe=True,
)
extensions.register_synapse(
"pinglab.exp146.injected_current/v1",
dynamics.inject_current,
output_unit="nA",
capture_safe=True,
)
The network contains one custom neuron and a continuous input connected to its excitatory port through the current extension at unit weight, with direct initialization scaling. The recipe passes the saved neuron settings as the custom neuron’s configuration. Native graph outputs retain voltage, gates, conductances, injected current and crossing events.
3. Run the current-step protocol and check the traces
Voltage and both gates start at −70 mV. We execute 50,000 steps of ms, for a total of 50 ms, with float64 arithmetic on CPU. Injected current is zero before 10 ms and 0.8 nA from 10 ms to the end (panel D). An upward crossing satisfies mV and mV; its recorded time is , without interpolation.
An independent scalar Euler implementation checks the saved trajectory.
The maximum voltage difference was 4.55e-13 mV, with identical spike counts and a maximum crossing-time difference of 0 ms.
The proposed acceptance thresholds are a maximum voltage error below 0.1 mV, crossing-time error below 0.05 ms and identical spike counts. Passing the independent numerical comparison does not establish agreement with the Toolbox: its reference traces have not been supplied.
Network diagram
Circuit exported from the executed compiled bundle. Sodium and potassium dynamics live inside the custom neuron; the input projection passes injected current without decay. No recurrent graph connection or spike reset is used. is the injected-current drive and the neuron. labels the native identity input projection. Weight indices give target first, source second. Recording aliases are omitted.
Parameters
Values come from the native simulation-start snapshot and its recorded compute configuration. Na / K pairs refer to sodium / potassium. The proposal’s gate voltages are filtered membrane voltages. Each step advances both gates from the preceding voltage, evaluates their sigmoid conductances, then advances the membrane voltage with those new conductances and the current interval’s input.
| Parameter | Saved value |
|---|---|
| Network | |
| Neurons | 1 |
| Injected-current weight | 1 |
| Synapse | Memoryless pass-through current |
| Neuron | |
| Capacitance (nF) | 0.01 |
| Leak conductance (µS) / reversal (mV) | 0.01 / -70 |
| Na / K maximum conductance (µS) | 1 / 10 |
| Na / K reversal (mV) | 50 / -85 |
| Na / K gate time constant (ms) | 1 / 10 |
| Na / K sigmoid slope (mV⁻¹) | 1 / 1 |
| Na / K sigmoid midpoint (mV) | -60 / -60 |
| Initial membrane and gate voltages (mV) | -70 |
| Observed upward-crossing threshold (mV) | -20 |
| Input and simulation | |
| Integration | gate-first forward Euler |
| Timestep / duration (ms) | 0.001 / 50 |
| Pulse onset (ms) / amplitude (nA) | 10 / 0.8 |
| Device / dtype | cpu / float64 |
| Unit convention | mV, ms, nF, uS, nA; C/g/I units assumed |
| Validation | |
| Voltage tolerance (mV) | 0.1 |
| Spike-time tolerance (ms) | 0.05 |
| Toolbox reference | Toolbox reference traces not supplied |
Dataset
Upstream: —
Downstream: —
Current runset
| Run | Date | Duration | Size | Evidence | Storage | Ran on | Verification |
|---|---|---|---|---|---|---|---|
| exp146-r003-present | 1s | 286.2 KB | Current | R2 | Local | Local: absent; R2: catalog-verified | |
| exp146-r002-analyse | <1s | 1.9 MB | Current | R2 | Local | Local: absent; R2: catalog-verified | |
| exp146-r001-compute | 5s | 1.9 MB | Current | R2 | Local | Local: absent; R2: catalog-verified |