tsodyks2_synapse#
- class brainpy.state.tsodyks2_synapse(weight=1.0, delay=Quantity(1., "ms"), receptor_type=0, U=0.5, u=<object object>, x=1.0, tau_rec=Quantity(800., "ms"), tau_fac=Quantity(0., "ms"), post=None, name=None)#
NEST-compatible
tsodyks2_synapseconnection model.Short description
Synapse type with short-term depression and facilitation.
Description
tsodyks2_synapsemirrors NESTmodels/tsodyks2_synapse.h. The model stores per-connection state variables:x: current scaling factor of synaptic efficacy,u: current release probability,t_lastspike: last presynaptic spike stamp.
Together with fixed model parameters
U,tau_recandtau_fac, incoming spikes are processed in the same order as NEST:1. State propagation
For
h = t_spike - t_lastspike, if this is not the first spike (i.e.t_lastspike >= 0), propagate state to the current spike:\[ \begin{align}\begin{aligned}x \leftarrow 1 + (x - xu - 1)e^{-h/\tau_{rec}}\\u \leftarrow U + u(1-U)e^{-h/\tau_{fac}}\end{aligned}\end{align} \]with the NEST special case
tau_fac == 0:\[e^{-h/\tau_{fac}} \equiv 0\]2. Effective weight computation
Compute effective synaptic weight for this spike:
\[w_{eff} = x u w\]3. Event scheduling
Schedule event delivery with inherited static-synapse delay semantics.
4. State update
Set
t_lastspike = t_spike.This model scales the baseline synaptic weight only and is suitable for current- or conductance-based postsynaptic dynamics.
Event timing semantics
As in NEST, updates use spike stamps and ignore precise sub-step offsets. In this backend, each presynaptic event at simulation step
tis evaluated at on-grid stampt + dt.Mathematical formulation
The tsodyks2_synapse model implements a simplified version of the Tsodyks-Markram short-term plasticity mechanism that tracks only two key dynamic variables rather than the full resource state model.
State variables
\(x(t)\) – scaling factor representing available resources
\(u(t)\) – utilization (release probability)
\(t_{\mathrm{last}}\) – timestamp of last presynaptic spike
Parameters:
\(U\) – baseline utilization increment (facilitation magnitude)
\(\tau_{rec}\) – recovery time constant (depression timescale)
\(\tau_{fac}\) – facilitation time constant
\(w\) – baseline synaptic weight
Dynamics:
Upon arrival of a presynaptic spike at time \(t_s\), with inter-spike interval \(h = t_s - t_{\mathrm{last}}\):
If \(t_{\mathrm{last}} \geq 0\) (not the first spike), propagate state variables:
\[ \begin{align}\begin{aligned}x(t_s) = 1 + [x(t_{\mathrm{last}}) - x(t_{\mathrm{last}})u(t_{\mathrm{last}}) - 1] \exp\left(-\frac{h}{\tau_{rec}}\right)\\u(t_s) = U + u(t_{\mathrm{last}})(1-U)\exp\left(-\frac{h}{\tau_{fac}}\right)\end{aligned}\end{align} \]with the special case when \(\tau_{fac} = 0\):
\[\exp\left(-\frac{h}{\tau_{fac}}\right) \equiv 0\]Compute effective synaptic strength:
\[w_{\mathrm{eff}} = x(t_s) \cdot u(t_s) \cdot w\]Update last spike time:
\[t_{\mathrm{last}} \leftarrow t_s\]
Biological interpretation:
Depression (\(x\) dynamics): After each spike, \(x\) decreases by factor \(xu\), representing depletion of available resources. It recovers exponentially with time constant \(\tau_{rec}\).
Facilitation (\(u\) dynamics): The utilization \(u\) increases toward \(U\) after each spike, representing calcium-dependent facilitation of release probability. It decays exponentially with time constant \(\tau_{fac}\).
Combined effect: The effective synaptic weight \(w_{\mathrm{eff}}\) is the product of available resources (\(x\)), release probability (\(u\)), and baseline weight (\(w\)).
Parameter regimes:
Depression-dominated: \(\tau_{rec} \gg \tau_{fac}\), \(U\) moderate. Resources deplete faster than facilitation builds up.
Facilitation-dominated: \(\tau_{fac} \gg \tau_{rec}\), \(U\) small. Facilitation accumulates across multiple spikes.
Pure depression: \(\tau_{fac} = 0\), fixed \(u = U\). No facilitation dynamics.
Computational considerations
Event-driven updates: State propagation occurs only at spike times, making the model computationally efficient for sparse spike trains.
Exponential approximation: For very small \(h\), numerical precision may be limited. NEST uses the convention that \(\tau_{fac} = 0\) exactly eliminates facilitation rather than using a threshold.
First spike handling: The condition \(t_{\mathrm{last}} < 0\) distinguishes the first spike, which uses initial \(x\) and \(u\) values directly without propagation.
Multiplicative weight scaling: Unlike
tsodyks_synapse, this model does not track postsynaptic current dynamics separately. The effective weight \(w_{\mathrm{eff}}\) directly modulates the delivered event.
Comparison with tsodyks_synapse
The tsodyks2_synapse model differs from tsodyks_synapse in several ways:
State representation:
tsodyks2: Two variables (\(x\), \(u\))
tsodyks: Three variables (\(x\), \(y\), \(u\)) plus postsynaptic current \(\tau_{psc}\)
Update equations:
tsodyks2: Simplified model where \(x\) represents effective resources after accounting for utilization
tsodyks: Full resource model with explicit recovered (\(x\)), active (\(y\)), and inactive (\(z = 1-x-y\)) resource fractions
Postsynaptic dynamics:
tsodyks2: No built-in postsynaptic filtering; \(w_{\mathrm{eff}}\) directly scales the event
tsodyks: Includes \(\tau_{psc}\) for postsynaptic current dynamics
Use cases:
tsodyks2: Simpler, faster, suitable when postsynaptic filtering is handled separately (e.g., by neuron model)
tsodyks: More detailed, includes postsynaptic current kinetics in the synapse model
- Parameters:
weight (
floatorarray-like, optional) – Baseline synaptic weight \(w\). Dimensionless scalar or array. Default:1.0.delay (
floatorQuantity, optional) – Synaptic transmission delay. Must be a positive time value in milliseconds. Acceptssaiunit.Quantitywith time units or float (interpreted as ms). Default:1.0 * u.ms.receptor_type (
int, optional) – Receiver port/receptor identifier for multi-receptor postsynaptic neurons. Non-negative integer. Default:0.U (
floatorarray-like, optional) – Utilization increment parameter \(U\). Must be in[0, 1]. Controls the magnitude of facilitation per spike. Dimensionless scalar. Default:0.5.u (
floatorarray-likeorUNSET, optional) – Initial release probability \(u(0)\). Must be in[0, 1]. If not provided, defaults toU. Dimensionless scalar. Default:U.x (
floatorarray-like, optional) – Initial scaling factor of synaptic efficacy \(x(0)\). Represents initial available resources. Dimensionless scalar. Typical range[0, 1], though values> 1are allowed. Default:1.0.tau_rec (
floatorQuantity, optional) – Recovery (depression) time constant \(\tau_{rec}\). Must be strictly positive (> 0). Controls the timescale of resource replenishment. Acceptssaiunit.Quantitywith time units or float (interpreted as ms). Default:800.0 * u.ms.tau_fac (
floatorQuantity, optional) – Facilitation time constant \(\tau_{fac}\). Must be non-negative (>= 0). When zero, facilitation is disabled and \(u\) remains constant at \(U\). Acceptssaiunit.Quantitywith time units or float (interpreted as ms). Default:0.0 * u.ms.post (
object, optional) – Default postsynaptic receiver object. If provided, this receiver will be used by default insend()andupdate()calls when no explicit receiver is specified. Default:None.name (
str, optional) – Optional name identifier for this connection object. Used for debugging and introspection. Default:None.
Parameter Mapping
The following table maps NEST parameter names to brainpy.state equivalents and describes their interpretation:
NEST Parameter
brainpy.state
Type
Description
weightweightfloat
Baseline synaptic weight \(w\)
delaydelayQuantity (ms)
Transmission delay in milliseconds
receptor_ typereceptor_ typeint
Target receptor port identifier
UUfloat [0,1]
Utilization increment
uufloat [0,1]
Initial/current release probability
xxfloat
Initial/current efficacy scaling
tau_rectau_recQuantity (ms)
Recovery time constant
tau_factau_facQuantity (ms)
Facilitation time constant
Notes
This model transmits spike-like events only. The
event_typeis fixed to'spike'.The state variables
x,u, andt_lastspikeare mutable connection states. Current values can be retrieved viaget()and modified viaset().When
tau_fac == 0exactly, facilitation is disabled and \(u\) remains constant. This matches NEST’s behavior and avoids numerical issues with \(\exp(-h/0)\).Calling
init_state()resets the event queue and restoresx,u, andt_lastspiketo their configured initial values.The model uses event-driven updates: state propagation occurs only at spike times, not at every simulation timestep.
- Raises:
ValueError – If
Uoruis not in the range[0, 1].ValueError – If
tau_recis not strictly positive (<= 0).ValueError – If
tau_facis negative (< 0).ValueError – If any scalar parameter has size
!= 1when converted to array.
See also
tsodyks_synapseFull resource-based STP model with postsynaptic current.
static_synapseBase class providing delay and weight handling.
tsodyks_synapse_homHomogeneous-weight variant of tsodyks_synapse.
References
Examples
Create a depression-dominated synapse (fast recovery, no facilitation):
>>> import brainpy.state as bst >>> import saiunit as u >>> syn = bst.tsodyks2_synapse( ... weight=1.0, ... delay=1.5 * u.ms, ... U=0.5, ... tau_rec=100.0 * u.ms, ... tau_fac=0.0 * u.ms ... ) >>> syn.init_state()
Create a facilitation-dominated synapse (slow recovery, long facilitation):
>>> syn_fac = bst.tsodyks2_synapse( ... weight=0.5, ... U=0.15, ... tau_rec=800.0 * u.ms, ... tau_fac=1000.0 * u.ms ... )
Inspect current synapse state:
>>> state = syn.get() >>> print(f"x={state['x']}, u={state['u']}") x=1.0, u=0.5
Simulate a spike train and observe depression:
>>> import brainstate as bst >>> import jax.numpy as jnp >>> # Create postsynaptic target >>> class SimpleTarget(bst.nn.Dynamics): ... def __init__(self): ... super().__init__() ... self.input = 0.0 ... def update(self, inp=0.0): ... self.input = inp >>> target = SimpleTarget() >>> syn = bst.tsodyks2_synapse( ... weight=1.0, ... delay=0.1 * u.ms, ... U=0.5, ... tau_rec=200.0 * u.ms, ... tau_fac=0.0 * u.ms, ... post=target ... ) >>> syn.init_state() >>> # Simulate high-frequency spike train >>> with bst.environ.context(dt=0.1 * u.ms): ... for i in range(10): ... delivered = syn.update(pre_spike=1.0) ... state = syn.get() ... print(f"Step {i}: x={state['x']:.3f}, w_eff={state['x']*state['u']:.3f}")
- get()[source]#
Return current public parameters and mutable state.
Retrieves a dictionary containing all NEST-compatible parameters and current dynamic state variables. This is useful for introspection, checkpointing, and parameter queries.
- Returns:
Dictionary with the following keys:
'weight': float Baseline synaptic weight.'delay': float Synaptic delay in milliseconds.'receptor_type': int Target receptor port identifier.'U': float Utilization increment parameter (fixed).'u': float Current release probability (mutable state).'x': float Current efficacy scaling factor (mutable state).'tau_rec': float Recovery time constant in milliseconds.'tau_fac': float Facilitation time constant in milliseconds.'synapse_model': str Model identifier string'tsodyks2_synapse'.
- Return type:
Notes
The returned
uandxvalues reflect the current synapse state, which changes after each spike.All time constants are returned as float values in milliseconds, with units stripped.
The
synapse_modelkey is included for NEST compatibility and model identification.
Examples
>>> import brainpy.state as bst >>> import saiunit as u >>> syn = bst.tsodyks2_synapse(weight=2.0, U=0.4, tau_rec=500*u.ms) >>> syn.init_state() >>> params = syn.get() >>> print(params['U'], params['x']) 0.4 1.0
- init_state(batch_size=None, **kwargs)[source]#
Initialize or reset synapse state variables.
Resets the event delivery queue and restores dynamic state variables (
x,u,t_lastspike) to their configured initial values. This method should be called before starting a simulation or when reinitializing the model.- Parameters:
Notes
The initial values of
xanduare determined by the values provided during object construction (or lastset()call).t_lastspikeis always reset to-1.0to indicate no prior spike has occurred.The inherited event queue from
static_synapseis also cleared.
- send(multiplicity=1.0, *, post=None, receptor_type=None)[source]#
Schedule one outgoing event with NEST
tsodyks2_synapsedynamics.Processes a presynaptic spike event by:
Propagating synapse state (
x,u) from the last spike time to the current spike time using exponential decay equations.Computing the effective synaptic weight as \(w_{\mathrm{eff}} = x \cdot u \cdot w \cdot \text{multiplicity}\).
Scheduling delayed delivery of the weighted event to the postsynaptic target.
Updating
t_lastspiketo the current spike timestamp.
This method implements the exact NEST
tsodyks2_synapseupdate semantics, including the special case fortau_fac == 0.- Parameters:
multiplicity (
floatorarray-like, optional) – Presynaptic spike multiplicity. Scales the effective weight linearly. For standard point-neuron spikes, this is1.0. For population models or weighted spike counts, can be > 1. Default:1.0.post (
object, optional) – Target postsynaptic receiver for this event. IfNone, uses the default receiver set during construction. Default:None.receptor_type (
intorarray-like, optional) – Target receptor port for this event. IfNone, uses the defaultreceptor_typeset during construction. Default:None.
- Returns:
Trueif an event was scheduled (multiplicity non-zero),Falseotherwise.- Return type:
Notes
If
multiplicityis zero or evaluates to zero after conversion, no event is scheduled and state is not updated.The spike timestamp is computed as
current_time + dt, wheredtis the simulation timestep. This matches NEST’s on-grid spike timing convention.For the first spike (
t_lastspike < 0), state propagation is skipped and initialxanduvalues are used directly.State variables
xanduare updated in place during this call, affecting all subsequent spikes.The effective weight calculation includes the multiplicity factor, so multiple coincident spikes can be represented as a single call with
multiplicity > 1.
Examples
>>> import brainpy.state as bst >>> import saiunit as u >>> # Create synapse with target >>> class Target(bst.nn.Dynamics): ... def __init__(self): ... super().__init__() ... self.current = 0.0 >>> target = Target() >>> syn = bst.tsodyks2_synapse( ... weight=1.0, ... delay=1.0 * u.ms, ... U=0.5, ... tau_rec=100.0 * u.ms, ... post=target ... ) >>> syn.init_state() >>> # Send a spike >>> with bst.environ.context(dt=0.1 * u.ms): ... success = syn.send(multiplicity=1.0) >>> print(success) True >>> # Send multiple spikes in quick succession >>> for i in range(5): ... syn.send(multiplicity=1.0) ... state = syn.get() ... print(f"Spike {i+1}: x={state['x']:.3f}, u={state['u']:.3f}")
- set(*, weight=<object object>, delay=<object object>, receptor_type=<object object>, U=<object object>, u=<object object>, x=<object object>, tau_rec=<object object>, tau_fac=<object object>, post=<object object>)[source]#
Set NEST-style public parameters and mutable state.
Updates one or more synapse parameters or state variables. All arguments are keyword-only and optional. Only provided parameters are modified; others retain their current values. New values are validated before assignment.
- Parameters:
weight (
floatorarray-like, optional) – New baseline synaptic weight. If not provided, unchanged.delay (
floatorQuantity, optional) – New synaptic delay in milliseconds. Must be positive. If not provided, unchanged.receptor_type (
int, optional) – New target receptor port identifier. If not provided, unchanged.U (
floatorarray-like, optional) – New utilization increment parameter. Must be in[0, 1]. If not provided, unchanged.u (
floatorarray-like, optional) – New current release probability. Must be in[0, 1]. If not provided, unchanged.x (
floatorarray-like, optional) – New current efficacy scaling factor. If not provided, unchanged.tau_rec (
floatorQuantity, optional) – New recovery time constant in milliseconds. Must be> 0. If not provided, unchanged.tau_fac (
floatorQuantity, optional) – New facilitation time constant in milliseconds. Must be>= 0. If not provided, unchanged.post (
object, optional) – New default postsynaptic receiver. If not provided, unchanged.
- Raises:
ValueError – If
Uoruis not in[0, 1].ValueError – If
tau_recis not strictly positive.ValueError – If
tau_facis negative.ValueError – If any scalar parameter has incorrect shape.
Notes
Setting
uorxmodifies the current synapse state, affecting subsequent spike processing.The initial values (
_u0,_x0) are updated to match newuandxvalues, soinit_state()will restore these new values.All validation is performed before any state modification, ensuring atomicity (either all changes succeed or none do).
Examples
>>> import brainpy.state as bst >>> import saiunit as u >>> syn = bst.tsodyks2_synapse(weight=1.0, U=0.5) >>> syn.init_state() >>> # Modify parameters >>> syn.set(U=0.3, tau_rec=300.0 * u.ms) >>> # Modify current state >>> syn.set(u=0.8, x=0.5) >>> params = syn.get() >>> print(params['U'], params['u'], params['x']) 0.3 0.8 0.5
- update(pre_spike=0.0, *, post=None, receptor_type=None)[source]#
Deliver due events, then schedule current-step presynaptic input.
Primary update method called at each simulation timestep. Performs two operations in sequence:
Delivery phase: Delivers all events scheduled for the current timestep to their target receivers (accumulated from past spikes with appropriate delays).
Reception phase: Processes current presynaptic input by aggregating spike counts and calling
send()to schedule new delayed events.
This method integrates with the event queue system inherited from
static_synapseand handles both current and delta input collection viasum_current_inputs()andsum_delta_inputs().- Parameters:
pre_spike (
floatorarray-like, optional) – Presynaptic spike input at the current timestep. Represents spike multiplicity (typically0.0for no spike,1.0for a single spike). Can be > 1 for population models. Default:0.0.post (
object, optional) – Target postsynaptic receiver for new events. IfNone, uses the default receiver set during construction. Default:None.receptor_type (
intorarray-like, optional) – Target receptor port for new events. IfNone, uses the defaultreceptor_typeset during construction. Default:None.
- Returns:
Number of events delivered to postsynaptic targets during the delivery phase of this timestep.
- Return type:
Notes
The method first delivers events from the queue, then processes new presynaptic input. This ordering ensures causality: events generated at timestep \(t\) are delivered at \(t + d\), where \(d\) is the delay in timesteps.
Current inputs are accumulated from multiple sources via
sum_current_inputs(), allowing multiple projections to target the same synapse.Delta inputs (instantaneous inputs delivered in the same timestep) are also accumulated via
sum_delta_inputs().If the total aggregated input is zero, no new event is scheduled and synapse state remains unchanged.
Examples
>>> import brainpy.state as bst >>> import saiunit as u >>> # Create synapse with target >>> class Target(bst.nn.Dynamics): ... def __init__(self): ... super().__init__() ... self.current = 0.0 ... def update(self, inp=0.0): ... self.current += inp >>> target = Target() >>> syn = bst.tsodyks2_synapse( ... weight=1.0, ... delay=1.0 * u.ms, ... U=0.5, ... tau_rec=200.0 * u.ms, ... post=target ... ) >>> syn.init_state() >>> target.init_state() >>> # Simulate spike train >>> with bst.environ.context(dt=0.1 * u.ms): ... for t in range(20): ... spike = 1.0 if t in [0, 5, 10] else 0.0 ... n_delivered = syn.update(pre_spike=spike) ... if n_delivered > 0: ... print(f"Step {t}: delivered {n_delivered} events")