quantal_stp_synapse#

class brainpy.state.quantal_stp_synapse(weight=1.0, delay=Quantity(1., "ms"), receptor_type=0, U=0.5, u=<object object>, n=1, a=<object object>, tau_rec=Quantity(800., "ms"), tau_fac=Quantity(0., "ms"), post=None, name=None)#

NEST-compatible quantal_stp_synapse connection model.

Probabilistic synapse model with short-term plasticity based on stochastic quantal vesicle release. Implements the Tsodyks-Markram model with discrete release sites, where each presynaptic spike triggers probabilistic release from a finite pool of vesicle docking sites.

Mathematical Model

Each synapse maintains four state variables:

  • u – dynamic release probability per site (evolves with facilitation)

  • n – total number of release sites (fixed)

  • a – currently available (recovered) release sites

  • t_lastspike – timestamp of last presynaptic spike

1. State Evolution Between Spikes

Upon arrival of a presynaptic spike at time \(t_s\), if a previous spike occurred at \(t_{\mathrm{last}}\) (i.e., t_lastspike >= 0):

\[ \begin{align}\begin{aligned}h = t_s - t_{\mathrm{last}}\\p_{\mathrm{decay}} = e^{-h/\tau_{\mathrm{rec}}}\\\begin{split}u_{\mathrm{decay}} = \begin{cases} 0, & \tau_{\mathrm{fac}} < 10^{-10} \\ e^{-h/\tau_{\mathrm{fac}}}, & \text{otherwise} \end{cases}\end{split}\\u \leftarrow U + u(1 - U) \, u_{\mathrm{decay}}\end{aligned}\end{align} \]

The release probability u undergoes:

  • Depression baseline: decays toward baseline U

  • Facilitation: modulated by exponential decay with time constant \(\tau_{\mathrm{fac}}\)

  • Special case: if \(\tau_{\mathrm{fac}} < 10^{-10}\), no facilitation occurs (\(u_{\mathrm{decay}} = 0\)), and u is reset to U

2. Stochastic Recovery of Release Sites

Depleted sites recover probabilistically. For each of the \(n - a\) depleted sites, an independent Bernoulli trial with success probability \(1 - p_{\mathrm{decay}}\) determines recovery. This implements exponential-distributed recovery times in discrete form.

3. Stochastic Vesicle Release

For each of the a currently available sites, an independent Bernoulli trial with success probability u determines whether that site releases a vesicle. Let \(n_{\mathrm{release}}\) denote the total number of sites that released.

4. Synaptic Transmission

If \(n_{\mathrm{release}} > 0\):

\[w_{\mathrm{eff}} = n_{\mathrm{release}} \cdot w\]

where w is the baseline per-site weight. The effective weight \(w_{\mathrm{eff}}\) is delivered to the postsynaptic neuron after the synaptic delay. The number of available sites is updated:

\[a \leftarrow a - n_{\mathrm{release}}\]

If \(n_{\mathrm{release}} = 0\), no event is sent (synaptic failure).

5. Timestamp Update

Regardless of whether an event was transmitted, the last spike time is updated:

\[t_{\mathrm{lastspike}} \leftarrow t_s\]

Implementation Fidelity

The update ordering matches NEST models/quantal_stp_synapse.h::send exactly:

  1. Update u (facilitation)

  2. Recover depleted sites

  3. Draw released sites

  4. Send event if any release occurred

  5. Update t_lastspike

Probabilistic Properties

  • Expected release: \(\mathbb{E}[n_{\mathrm{release}}] = a \cdot u\)

  • Variance: \(\mathrm{Var}[n_{\mathrm{release}}] = a \cdot u \cdot (1 - u)\)

  • Failure probability: \(P(\text{no release}) = (1 - u)^a\)

For small u and moderate a, the distribution of released vesicles is approximately Poisson with rate \(\lambda = a \cdot u\).

Event Timing Semantics

As in NEST, the model operates on discrete spike timestamps and ignores sub-step temporal offsets. Each event processed at simulation step t uses the on-grid timestamp t + dt for all decay calculations.

Parameters:
  • weight (float or array_like, optional) – Baseline per-site synaptic weight w (dimensionless or with units). The effective transmitted weight is \(w_{\mathrm{eff}} = n_{\mathrm{release}} \cdot w\). Default: 1.0.

  • delay (float or array_like, optional) – Synaptic transmission delay. Must be positive and include time units. Default: 1.0 * u.ms.

  • receptor_type (int, optional) – Target receptor port identifier on the postsynaptic neuron. Used to route synaptic input to specific receptor channels. Default: 0.

  • U (float or array_like, optional) – Baseline release probability per site. Must be in [0, 1]. Controls the equilibrium facilitation level. Default: 0.5.

  • u (float or array_like, optional) – Initial release probability per site. Must be in [0, 1]. If not specified, defaults to U. Default: U.

  • n (int or array_like, optional) – Total number of release sites (vesicle docking sites). Must be a non-negative integer. Default: 1.

  • a (int or array_like, optional) – Initial number of available (recovered) release sites. Must be a non-negative integer not exceeding n. If not specified, defaults to n (all sites initially available). Default: n.

  • tau_rec (float or array_like, optional) – Recovery time constant for depleted sites. Must be positive and include time units. Governs the rate of site replenishment. Default: 800.0 * u.ms.

  • tau_fac (float or array_like, optional) – Facilitation time constant. Must be non-negative and include time units. If zero or very small (\(< 10^{-10}\) ms), facilitation is disabled and u is reset to U on each spike. Default: 0.0 * u.ms (no facilitation).

  • post (object, optional) – Default postsynaptic receiver object. Can be overridden in send() and update() calls.

  • name (str, optional) – Unique identifier for this synapse instance.

Parameter Mapping

Direct correspondence with NEST quantal_stp_synapse:

brainpy.state

NEST

Description

weight

weight

Per-site baseline weight

delay

delay

Transmission delay (ms)

receptor_type

receptor_type

Receptor port identifier

U

U

Baseline release probability

u

u

Current release probability

n

n

Total release sites

a

a

Available release sites

tau_rec

tau_rec

Recovery time constant (ms)

tau_fac

tau_fac

Facilitation time constant (ms)

Notes

Random Number Generation

All probabilistic operations use the NumPy global random number generator (np.random.random()). For reproducible simulations, seed the generator with np.random.seed() before initialization.

State Initialization

Calling init_state() resets the mutable state variables (u, a, t_lastspike) to their configured initial values. The reset values are stored internally as _u0 and _a0 when parameters are set.

Computational Cost

The per-spike cost scales as \(O(n)\) due to the independent Bernoulli trials for each site. For large n (e.g., \(n > 100\)), consider using the continuous Tsodyks-Markram model (tsodyks_synapse) as an efficient approximation.

Biophysical Interpretation

  • n: number of active zones or docking sites

  • u: vesicle release probability (calcium-dependent)

  • U: baseline release probability (intrinsic to synapse type)

  • tau_rec: vesicle recycling / replenishment time

  • tau_fac: residual calcium decay time (controls facilitation)

Comparison with tsodyks_synapse

tsodyks_synapse uses continuous-valued resource variables and deterministic updates. quantal_stp_synapse uses discrete site counts and stochastic release, producing trial-to-trial variability consistent with experimental observations of synaptic unreliability.

See also

tsodyks_synapse

Deterministic continuous Tsodyks-Markram model

tsodyks2_synapse

Alternative Tsodyks-Markram formulation

static_synapse

Static synaptic connection without plasticity

References

Examples

Basic usage with default parameters

>>> import brainpy.state as bp
>>> import saiunit as u
>>> # Single release site, 50% release probability
>>> syn = bp.quantal_stp_synapse(weight=1.0, U=0.5, n=1)
>>> syn.init_state()

Multi-site synapse with facilitation

>>> # 10 release sites, facilitating synapse
>>> syn = bp.quantal_stp_synapse(
...     weight=0.1,
...     U=0.3,
...     n=10,
...     tau_rec=800.0 * u.ms,
...     tau_fac=50.0 * u.ms
... )
>>> syn.init_state()

Depressing synapse (no facilitation)

>>> # High initial release probability, slow recovery
>>> syn = bp.quantal_stp_synapse(
...     weight=0.5,
...     U=0.8,
...     n=5,
...     tau_rec=1000.0 * u.ms,
...     tau_fac=0.0 * u.ms  # No facilitation
... )
>>> syn.init_state()

Simulating paired-pulse response

>>> import numpy as np
>>> np.random.seed(42)  # For reproducibility
>>> syn = bp.quantal_stp_synapse(
...     weight=1.0, U=0.5, n=10, tau_rec=500.0 * u.ms,
...     tau_fac=50.0 * u.ms
... )
>>> syn.init_state()
>>> # First pulse
>>> response1 = syn.send(multiplicity=1.0)
>>> # Second pulse 50 ms later (simulate time advance)
>>> syn.t_lastspike = 0.0
>>> # ... (advance simulation time by 50 ms)
>>> response2 = syn.send(multiplicity=1.0)

Runtime parameter modification

>>> syn.set(U=0.7, tau_rec=300.0 * u.ms)
>>> status = syn.get()
>>> print(status['U'], status['tau_rec'])
0.7 300.0
get()[source]#

Return current public parameters and mutable state.

Retrieves all NEST-compatible parameters and the current values of mutable state variables. This method is useful for inspecting synapse configuration and monitoring state evolution during simulation.

Returns:

Dictionary containing:

  • Inherited static synapse parameters (weight, delay, receptor_type)

  • Ufloat

    Baseline release probability

  • ufloat

    Current release probability

  • tau_recfloat

    Recovery time constant (ms, unitless value)

  • tau_facfloat

    Facilitation time constant (ms, unitless value)

  • nint

    Total number of release sites

  • aint

    Current number of available sites

  • synapse_modelstr

    Fixed string 'quantal_stp_synapse' for NEST compatibility

Return type:

dict

Notes

The returned dictionary is a snapshot of the current state. Modifying the dictionary does not affect the synapse. Use set() to update parameters.

Examples

>>> syn = bp.quantal_stp_synapse(U=0.5, n=10)
>>> syn.init_state()
>>> status = syn.get()
>>> print(status['u'], status['a'])
0.5 10
init_state(batch_size=None, **kwargs)[source]#

Initialize or reset synapse state to configured initial values.

Resets the three mutable state variables to their initial configuration:

  • u: reset to _u0 (initial release probability)

  • a: reset to _a0 (initial available sites)

  • t_lastspike: reset to -1.0 (no prior spike)

This method should be called before simulation or when resetting between trials.

Parameters:
  • batch_size (int, optional) – Ignored (retained for API compatibility with batch-aware models).

  • **kwargs – Additional keyword arguments (ignored).

Notes

The initial values _u0 and _a0 are cached internally when parameters are set via __init__() or set(). Modifying u or a directly during simulation does not affect these cached values.

send(multiplicity=1.0, *, post=None, receptor_type=None)[source]#

Schedule one outgoing synaptic event with quantal STP dynamics.

Processes a presynaptic spike by updating facilitation state, recovering depleted sites, drawing stochastic vesicle release, and scheduling transmission to the postsynaptic target. This method implements the NEST quantal_stp_synapse::send algorithm exactly.

Processing Steps

  1. Facilitation Update: If a previous spike exists (t_lastspike >= 0), compute inter-spike interval and update release probability u according to decay and facilitation rules.

  2. Site Recovery: For each depleted site, perform a Bernoulli trial with recovery probability \(1 - e^{-h/\tau_{\mathrm{rec}}}\).

  3. Vesicle Release: For each available site, perform a Bernoulli trial with release probability u. Count total released sites as n_release.

  4. Event Transmission: If n_release > 0, schedule a delayed event with effective weight \(w_{\mathrm{eff}} = n_{\mathrm{release}} \cdot w \cdot \text{multiplicity}\) and update available sites: a <- a - n_release.

  5. Timestamp Update: Store current spike time in t_lastspike, regardless of whether transmission occurred.

Parameters:
  • multiplicity (float or array_like, optional) – Presynaptic spike count or scaling factor. The effective transmitted weight is \(w_{\mathrm{eff}} = n_{\mathrm{release}} \cdot w \cdot \text{multiplicity}\). If zero or negligible, processing is skipped. Default: 1.0.

  • post (object, optional) – Target postsynaptic receiver. If None, uses the default receiver set during initialization.

  • receptor_type (int or array_like, optional) – Target receptor port. If None, uses the default receptor type set during initialization.

Returns:

True if at least one vesicle was released and an event was transmitted; False if synaptic failure occurred (no release) or if multiplicity was zero.

Return type:

bool

Notes

Synaptic Failure

Due to stochastic release, transmission may fail even with positive multiplicity. The failure probability is \((1 - u)^a\). For small u or a, failures are common.

Timestamp Semantics

The spike timestamp is computed as current_time + dt, representing the end of the current simulation step. This matches NEST’s on-grid spike timing convention.

Random Number Generation

Each call may invoke the RNG up to \(n\) times (worst case: all sites depleted, all recover, all release). For reproducibility, seed np.random before simulation.

Examples

>>> import numpy as np
>>> np.random.seed(42)
>>> syn = bp.quantal_stp_synapse(weight=1.0, U=0.5, n=10)
>>> syn.init_state()
>>> transmitted = syn.send(multiplicity=1.0)
>>> if transmitted:
...     print(f"Released vesicles, available sites now: {syn.a}")
... else:
...     print("Synaptic failure")
set(*, weight=<object object>, delay=<object object>, receptor_type=<object object>, U=<object object>, u=<object object>, n=<object object>, a=<object object>, tau_rec=<object object>, tau_fac=<object object>, post=<object object>)[source]#

Set NEST-style public parameters and state variables.

Updates synapse parameters and optionally resets mutable state. All parameters are validated before being applied. If validation fails, the synapse state remains unchanged.

Parameters:
  • weight (float or array_like, optional) – New baseline per-site weight. If not provided, current value is retained.

  • delay (float or array_like, optional) – New synaptic delay (must include time units). If not provided, current value is retained.

  • receptor_type (int, optional) – New receptor port identifier. If not provided, current value is retained.

  • U (float or array_like, optional) – New baseline release probability. Must be in [0, 1]. If not provided, current value is retained.

  • u (float or array_like, optional) – New current release probability. Must be in [0, 1]. If not provided, current value is retained. Also updates _u0 (the reset value used by init_state()).

  • n (int or array_like, optional) – New total number of release sites. Must be a non-negative integer. If not provided, current value is retained.

  • a (int or array_like, optional) – New number of available sites. Must be a non-negative integer not exceeding n. If not provided, current value is retained. Also updates _a0 (the reset value used by init_state()).

  • tau_rec (float or array_like, optional) – New recovery time constant (must include time units and be positive). If not provided, current value is retained.

  • tau_fac (float or array_like, optional) – New facilitation time constant (must include time units and be non-negative). If not provided, current value is retained.

  • post (object, optional) – New default postsynaptic receiver. If not provided, current value is retained.

Raises:

ValueError – If any parameter fails validation: - U or u not in [0, 1] - n or a not an integer - tau_rec <= 0 - tau_fac < 0

Notes

State Reset Values

Setting u or a updates both the current state and the cached initial values (_u0, _a0). This means subsequent calls to init_state() will use the new values as the reset target.

Atomic Update

All validations are performed before any state is modified. If any parameter is invalid, the entire operation is aborted without side effects.

Examples

>>> syn = bp.quantal_stp_synapse(U=0.5, n=10)
>>> syn.set(U=0.7, tau_rec=300.0 * u.ms)
>>> syn.set(a=5)  # Partially deplete available sites
>>> syn.init_state()  # Now resets to a=5 (new initial value)
update(pre_spike=0.0, *, post=None, receptor_type=None)[source]#

Deliver due events and process current presynaptic input.

Performs two operations in sequence:

  1. Event Delivery: Delivers all queued synaptic events scheduled for the current simulation step to their target postsynaptic receivers.

  2. Input Processing: Aggregates all current-step presynaptic input (from pre_spike argument and registered input sources via current_inputs and delta_inputs), then calls send() if the total input is non-zero.

This method is typically called once per simulation step as part of the projection’s update loop.

Parameters:
  • pre_spike (float or array_like, optional) – Presynaptic spike input for the current step (dimensionless or with units). This value is summed with inputs from registered sources before processing. Default: 0.0.

  • post (object, optional) – Target postsynaptic receiver for the outgoing event (if any). If None, uses the default receiver.

  • receptor_type (int or array_like, optional) – Target receptor port for the outgoing event (if any). If None, uses the default receptor type.

Returns:

Number of synaptic events delivered to postsynaptic targets during this step. This count reflects events scheduled in prior steps, not the current send() call.

Return type:

int

Notes

Update Order

Event delivery precedes input processing. This means events generated in the current step are delivered delay steps later, consistent with NEST’s event-driven semantics.

Input Aggregation

The method sums three input sources:

  • Direct pre_spike argument

  • Registered current_inputs (via add_current_input())

  • Registered delta_inputs (via add_delta_input())

If the total is zero (within numerical tolerance), send() is skipped.

Examples

>>> syn = bp.quantal_stp_synapse(weight=1.0, U=0.5, n=10)
>>> syn.init_state()
>>> # Process spike input
>>> delivered = syn.update(pre_spike=1.0)
>>> # Check how many events were delivered this step
>>> print(f"Delivered {delivered} events")