gap_junction#
- class brainpy.state.gap_junction(weight=1.0, name=None)#
NEST-compatible
gap_junctionconnection model for electrical synaptic coupling.This class implements electrical gap junction connections that transmit
GapJunctionEventdata and contribute currents proportional to membrane voltage differences between coupled neurons. It follows the connection-level semantics of NEST’smodels/gap_junction.{h,cpp}implementation, including waveform-relaxation (WFR) support for multi-timestep integration.- Parameters:
- interpolation_coefficients#
Buffer of summed interpolation coefficients from incoming events, shape
(min_delay_steps * (interpolation_order + 1),).- Type:
ndarray
Parameter Mapping
NEST Name
brainpy.state Name
Description
weight
weight
Gap junction conductance (nS)
delay
unsupported
Delay not allowed for gap junctions
Mathematical Formulation
1. Gap Junction Current
The gap junction current for a post-synaptic neuron \(i\) coupled to pre-synaptic neurons \(j\) is given by:
\[I_{\text{gap},i} = -\sum_j g_{ij} V_i + P_{\text{interp}}(t)\]where:
\(g_{ij}\) is the gap junction conductance (weight) from neuron \(j\) to \(i\)
\(V_i\) is the membrane potential of the post-synaptic neuron
\(P_{\text{interp}}(t)\) is the interpolation polynomial constructed from pre-synaptic voltage contributions
2. Waveform Relaxation (WFR) Event Accumulation
During WFR cycles, incoming
GapJunctionEventobjects update two quantities:\[\begin{split}\Sigma g_{ij} &\leftarrow \Sigma g_{ij} + w_{ij} \\ c_k &\leftarrow c_k + w_{ij} \cdot a_k\end{split}\]where:
\(w_{ij}\) is the connection weight
\(a_k\) are source neuron interpolation coefficients
\(c_k\) are target-side summed coefficients for polynomial reconstruction
3. Interpolation Polynomials
The interpolation term \(P_{\text{interp}}(t)\) depends on the WFR order:
Order 0 (constant interpolation):
\[P_{\text{interp}}(t) = c_0\]Order 1 (linear interpolation):
\[P_{\text{interp}}(t) = c_0 + c_1 \cdot t\]Order 3 (cubic Hermite interpolation):
\[P_{\text{interp}}(t) = c_0 + c_1 \cdot t + c_2 \cdot t^2 + c_3 \cdot t^3\]
where \(t \in [0, 1]\) is the normalized time within the current WFR substep.
Implementation Details
1. Update Ordering (matching NEST)
The WFR cycle follows this sequence:
Begin WFR window: Clear
sumj_g_ijand interpolation coefficient buffer.Event accumulation: For each arriving secondary event, add weight and weighted coefficients.
ODE substeps: Evaluate \(I_{\text{gap}}\) from current voltage, lag, interpolation order, and normalized substep time.
End WFR window: Reset runtime buffers for the next window.
2. Symmetric Connectivity Requirement
Gap junctions require symmetric connections: if neuron \(i\) is coupled to neuron \(j\) with weight \(w_{ij}\), then neuron \(j\) must also be coupled to neuron \(i\) with weight \(w_{ji}\). Asymmetric configurations will produce incorrect dynamics.
3. Delay Constraint
Unlike chemical synapses, gap junctions are instantaneous (or near-instantaneous) electrical connections. Setting a delay raises a
ValueError.4. Coefficient Buffer Sizing
For WFR with
min_delay_stepslags and interpolation order \(n\), the coefficient buffer size is:\[\text{buffer\_size} = \text{min\_delay\_steps} \times (n + 1)\]Examples
Basic gap junction setup:
>>> import brainpy_state as bp >>> import saiunit as u >>> >>> # Create gap junction with 10 nS conductance >>> gap = bp.nest.gap_junction(weight=10.0) >>> >>> # Query connection properties >>> gap.get_status() {'weight': 10.0, 'delay': None, 'requires_symmetric': True, 'supports_wfr': True, 'supported_wfr_interpolation_orders': (0, 1, 3)}
WFR cycle simulation:
>>> import numpy as np >>> >>> # Initialize WFR with 5 delay steps and linear interpolation >>> gap.begin_wfr_cycle(min_delay_steps=5, interpolation_order=1) >>> >>> # Simulate incoming event with pre-synaptic coefficients >>> pre_coeffs = np.array([1.0, 0.5, 1.2, 0.8, 1.5, 0.3, 1.1, 0.9, 1.3, 0.7]) >>> gap.handle_gap_event(coeffarray=pre_coeffs) >>> >>> # Evaluate gap current at lag 2, normalized time t=0.5 >>> V_post = -65.0 # mV >>> I_gap = gap.evaluate_gap_current(V_m=V_post, lag=2, t=0.5) >>> print(f"Gap junction current: {I_gap:.2f}") Gap junction current: ...
Error: attempting to set delay:
>>> gap.set_delay(1.5) ValueError: gap_junction connection has no delay
See also
hh_psc_alpha_gapHodgkin-Huxley neuron with gap junction support
hh_cond_beta_gap_traubTraub HH neuron with gap junction support
Notes
Delay is intentionally unsupported: Matches NEST’s constraint that gap junctions have no synaptic delay.
Connection-level semantics only: This class represents gap junction connection properties. Neuron-specific ODE dynamics (voltage interpolation, coefficient broadcasting) remain in the neuron model.
Interpolation coefficient ownership: The neuron model owns and updates interpolation coefficients based on its voltage history. This class only accumulates weighted coefficients from incoming events.
Thread safety: Not thread-safe. Runtime state (
sumj_g_ij,interpolation_coefficients) assumes single-threaded access within each WFR cycle.
References
- begin_wfr_cycle(min_delay_steps, interpolation_order=0)[source]#
Initialize a new waveform-relaxation (WFR) cycle.
Resets runtime state (
sumj_g_ijandinterpolation_coefficients) and allocates the coefficient buffer based on the number of delay steps and the interpolation order.- Parameters:
min_delay_steps (
intorarray-like) – Minimum delay in discrete timesteps (must be > 0). Determines the number of lag slots in the interpolation coefficient buffer.interpolation_order (
int, optional) –Interpolation polynomial order. Must be in
{0, 1, 3}:0– Constant interpolation (piecewise constant).1– Linear interpolation.3– Cubic Hermite interpolation.
Default:
0.
- Raises:
If
min_delay_steps <= 0. - Ifinterpolation_orderis not in{0, 1, 3}.
Notes
The coefficient buffer size is
min_delay_steps * (interpolation_order + 1). For example, withmin_delay_steps=5andinterpolation_order=1, the buffer will have 10 elements (2 coefficients per lag).Examples
>>> gap = bp.nest.gap_junction(weight=2.0) >>> gap.begin_wfr_cycle(min_delay_steps=3, interpolation_order=1) >>> gap.interpolation_coefficients.shape (6,) # 3 lags * 2 coefficients per lag >>> gap.sumj_g_ij 0.0
See also
reset_runtime_stateClear runtime state without reallocating buffer
handle_gap_eventAccumulate incoming gap junction events
- evaluate_gap_current(V_m, lag, t=0.0, interpolation_order=None)[source]#
Evaluate the gap junction current at a specific WFR lag and substep time.
Computes the gap junction current contribution using the accumulated weight sum and interpolation coefficients from incoming events. The current is computed as:
\[I_{\text{gap}} = -\Sigma g_{ij} \cdot V_m + P_{\text{interp}}(t)\]where \(P_{\text{interp}}(t)\) is the interpolation polynomial evaluated at normalized time \(t \in [0, 1]\) within the current substep.
- Parameters:
V_m (
floatorarray-like) – Post-synaptic membrane potential (scalar or array). Units should match the voltage scale used in the neuron model (typically mV).lag (
int) – WFR lag index (delay step offset). Must be in range[0, n_lags), wheren_lags = buffer_size / (interpolation_order + 1).t (
floatorarray-like, optional) – Normalized substep time in \([0, 1]\). Represents the position within the current integration step. Default:0.0.interpolation_order (
intorNone, optional) – Interpolation order override. IfNone, uses the order set inbegin_wfr_cycle(). Must be in{0, 1, 3}.
- Returns:
Gap junction current \(I_{\text{gap}}\). Shape matches
V_m. Units depend on weight scaling (typically nA for conductance-based models).- Return type:
floatorndarray- Raises:
If
interpolation_coefficientsbuffer is empty (callbegin_wfr_cycle()first). - If buffer size is incompatible withinterpolation_order. - Iflagis out of bounds. - Ifinterpolation_orderis not in{0, 1, 3}.
Notes
Interpolation formulas:
Order 0 (constant):
\[P_{\text{interp}}(t) = c_0\]Order 1 (linear):
\[P_{\text{interp}}(t) = c_0 + c_1 \cdot t\]Order 3 (cubic Hermite):
\[P_{\text{interp}}(t) = c_0 + c_1 \cdot t + c_2 \cdot t^2 + c_3 \cdot t^3\]
Coefficient indexing: Coefficients are stored in a flat array with layout
[lag0_c0, lag0_c1, ..., lag1_c0, lag1_c1, ...]. For lag \(L\) and order \(n\), coefficients start at index \(L \times (n + 1)\).Examples
Constant interpolation (order 0):
>>> import numpy as np >>> gap = bp.nest.gap_junction(weight=2.0) >>> gap.begin_wfr_cycle(min_delay_steps=3, interpolation_order=0) >>> gap.handle_gap_event(coeffarray=np.array([10.0, 20.0, 30.0])) >>> V_post = -65.0 # mV >>> I_gap = gap.evaluate_gap_current(V_m=V_post, lag=1) >>> I_gap 170.0 # -2.0 * (-65.0) + 40.0
Linear interpolation (order 1):
>>> gap2 = bp.nest.gap_junction(weight=1.5) >>> gap2.begin_wfr_cycle(min_delay_steps=2, interpolation_order=1) >>> gap2.handle_gap_event(coeffarray=np.array([5.0, 10.0, 15.0, 20.0])) >>> I_gap = gap2.evaluate_gap_current(V_m=-70.0, lag=0, t=0.5) >>> # I_gap = -1.5 * (-70.0) + (7.5 + 15.0 * 0.5) >>> I_gap 120.0
Cubic interpolation (order 3):
>>> gap3 = bp.nest.gap_junction(weight=1.0) >>> gap3.begin_wfr_cycle(min_delay_steps=1, interpolation_order=3) >>> gap3.handle_gap_event(coeffarray=np.array([1.0, 2.0, 3.0, 4.0])) >>> I_gap = gap3.evaluate_gap_current(V_m=-60.0, lag=0, t=0.3) >>> # I_gap = -1.0 * (-60.0) + (1.0 + 2.0*0.3 + 3.0*0.09 + 4.0*0.027) >>> I_gap 62.438
See also
begin_wfr_cycleInitialize WFR cycle with interpolation order
handle_gap_eventAccumulate gap junction events
reset_runtime_stateClear accumulated state
- get(key='status')[source]#
Retrieve a specific status parameter or the full status dictionary.
- Parameters:
key (
str, optional) – Parameter name to retrieve. Use'status'for the full dictionary. Default:'status'.- Returns:
If
key == 'status', returns the full status dictionary. Otherwise, returns the value associated withkey.- Return type:
Any- Raises:
KeyError – If
keyis not a valid status parameter name.
Examples
>>> gap = bp.nest.gap_junction(weight=3.5) >>> gap.get('weight') 3.5 >>> gap.get('requires_symmetric') True >>> gap.get() # defaults to 'status' {'weight': 3.5, 'delay': None, ...}
See also
get_statusFull status dictionary retrieval
- get_status()[source]#
Retrieve the current connection status and parameters.
- Returns:
- Status dictionary containing:
'weight'(float): Current gap junction weight.'delay'(None): AlwaysNone(delays not supported).'requires_symmetric'(bool): Symmetric connectivity requirement.'supports_wfr'(bool): WFR support flag.'supported_wfr_interpolation_orders'(tuple): Tuple of supported interpolation orders(0, 1, 3).
- Return type:
dict[str,Any]
Examples
>>> gap = bp.nest.gap_junction(weight=2.5) >>> status = gap.get_status() >>> status['weight'] 2.5 >>> status['delay'] is None True
See also
set_statusUpdate connection parameters
getRetrieve specific status keys
- handle_gap_event(coeffarray, weight=None)[source]#
Process an incoming gap junction event and accumulate contributions.
Updates runtime state by adding the event weight to
sumj_g_ijand accumulating weighted interpolation coefficients. This method matches NEST’shandle(GapJunctionEvent&)semantics.- Parameters:
- Raises:
If
coeffarrayis empty. - Ifcoeffarraysize does not match the current buffer size. - Ifweightis provided but not a scalar.
Notes
Accumulation rule:
\[\begin{split}\Sigma g_{ij} &\leftarrow \Sigma g_{ij} + w \\ c_k &\leftarrow c_k + w \cdot a_k\end{split}\]where \(w\) is the event weight and \(a_k\) are the incoming coefficients.
Buffer initialization: If the coefficient buffer is empty when the first event arrives, it is initialized to match the incoming array size.
Examples
>>> import numpy as np >>> gap = bp.nest.gap_junction(weight=2.0) >>> gap.begin_wfr_cycle(min_delay_steps=3, interpolation_order=0) >>> pre_coeffs = np.array([1.0, 1.5, 2.0]) >>> gap.handle_gap_event(coeffarray=pre_coeffs) >>> gap.sumj_g_ij 2.0 >>> gap.interpolation_coefficients array([2. , 3. , 4. ]) # weight * coeffarray
Multiple events accumulate:
>>> gap.handle_gap_event(coeffarray=np.array([0.5, 0.5, 0.5])) >>> gap.sumj_g_ij 4.0 # 2.0 + 2.0 >>> gap.interpolation_coefficients array([3. , 4. , 5. ]) # previous + 2.0 * [0.5, 0.5, 0.5]
See also
prepare_secondary_eventCreate event payload
evaluate_gap_currentCompute gap junction current from accumulated events
- prepare_secondary_event(coeffarray)[source]#
Prepare a secondary gap junction event payload for transmission.
Packages the connection weight and pre-synaptic interpolation coefficients into a dictionary suitable for transmission as a
GapJunctionEventin a WFR simulation.- Parameters:
coeffarray (
array-like) – Pre-synaptic neuron’s interpolation coefficients. Must be a non-empty 1D array. For interpolation order \(n\) andmin_delay_stepslags, the expected size ismin_delay_steps * (n + 1).- Returns:
- Event payload containing:
'weight'(float): Connection weight.'coeffarray'(ndarray): 1D float64 array of interpolation coefficients.
- Return type:
dict[str,Any]- Raises:
ValueError – If
coeffarrayis empty or cannot be converted to a 1D array.
Examples
>>> import numpy as np >>> gap = bp.nest.gap_junction(weight=3.0) >>> pre_coeffs = np.array([0.5, 1.0, 1.5]) >>> event = gap.prepare_secondary_event(pre_coeffs) >>> event['weight'] 3.0 >>> event['coeffarray'] array([0.5, 1. , 1.5])
See also
handle_gap_eventProcess incoming gap junction events
- property properties: dict[str, Any]#
Get static connection model properties.
- Returns:
- Dictionary containing:
'requires_symmetric'(bool): AlwaysTrue.'supports_wfr'(bool): AlwaysTrue.
- Return type:
dict[str,Any]
Examples
>>> gap = bp.nest.gap_junction(weight=5.0) >>> gap.properties {'requires_symmetric': True, 'supports_wfr': True}
- reset_runtime_state()[source]#
Clear runtime state accumulated from gap junction events.
Resets
sumj_g_ijto0.0and zeros out the interpolation coefficient buffer without reallocating it. This method is typically called at the end of a WFR cycle to prepare for the next cycle.Examples
>>> gap = bp.nest.gap_junction(weight=2.0) >>> gap.begin_wfr_cycle(min_delay_steps=3, interpolation_order=0) >>> gap.handle_gap_event(coeffarray=np.array([1.0, 2.0, 3.0])) >>> gap.sumj_g_ij 2.0 >>> gap.reset_runtime_state() >>> gap.sumj_g_ij 0.0 >>> np.all(gap.interpolation_coefficients == 0.0) True
See also
begin_wfr_cycleInitialize WFR cycle (resets and reallocates buffer)
handle_gap_eventAccumulate gap junction events
- set_delay(_)[source]#
Attempt to set delay (always raises an error).
Gap junctions are instantaneous electrical connections and do not support synaptic delays. This method exists for API compatibility with NEST but always raises a
ValueError.- Parameters:
_ (
Any) – Ignored (delay value).- Raises:
ValueError – Always raised with message
'gap_junction connection has no delay'.
Examples
>>> gap = bp.nest.gap_junction() >>> gap.set_delay(1.5) ValueError: gap_junction connection has no delay
See also
set_statusGeneral parameter update method (also rejects delay)
- set_status(status=None, **kwargs)[source]#
Update connection parameters from a status dictionary or keyword arguments.
- Parameters:
status (
dict[str,Any]orNone, optional) – Dictionary of parameter updates. Keys must be valid parameter names.**kwargs – Additional parameter updates passed as keyword arguments. These override values in
statusif both are provided.
- Raises:
ValueError – If attempting to set
'delay'(gap junctions have no delay).
Examples
>>> gap = bp.nest.gap_junction(weight=1.0) >>> gap.set_status({'weight': 5.0}) >>> gap.get_status()['weight'] 5.0 >>> gap.set_status(weight=10.0) >>> gap.weight 10.0
Error case:
>>> gap.set_status({'delay': 1.0}) ValueError: gap_junction connection has no delay
See also
get_statusRetrieve current status
set_weightUpdate weight parameter directly
- set_weight(weight)[source]#
Update the gap junction conductance weight.
- Parameters:
weight (
floatorarray-like) – New gap junction weight (must be scalar).- Raises:
ValueError – If
weightis not a scalar value.
Examples
>>> gap = bp.nest.gap_junction(weight=1.0) >>> gap.set_weight(5.5) >>> gap.weight 5.5
See also
set_statusUpdate multiple parameters at once