Model: STDP Synapse
Demonstrates STDP where synapse weight changes depend on relative pre/post spike timing. The STDP trace variables follow ODEs:
\[\frac{dA_{pre}}{dt} = -A_{pre}/\tau_{pre}, \quad \frac{dA_{post}}{dt} = -A_{post}/\tau_{post}\]
The network uses HH pre-cells driving IaF post-cells. TVBO models the core IaF cell dynamics.
1. Define IaF Cell in TVBO
from tvbo import SimulationExperiment
exp = SimulationExperiment.from_string("""
label: "NeuroML Ex11: IaF Cell (STDP Network)"
dynamics:
name: IntegrateAndFire
parameters:
leakReversal: { value: -50.0 }
tau: { value: 30.0 }
thresh: { value: -55.0 }
reset: { value: -70.0 }
state_variables:
v:
equation: { rhs: "(leakReversal - v) / tau" }
initial_value: -50.0
variable_of_interest: true
events:
spike:
condition: { rhs: "v > thresh" }
affect: { rhs: "v = reset" }
network:
number_of_nodes: 1
integration:
method: euler
step_size: 0.005
duration: 200.0
time_scale: ms
""" )
print (f"Model: { exp. dynamics. name} " )
2. Render LEMS XML
xml = exp.render("lems" )
print (xml[:1200 ])
<Lems>
<!-- Tell jLEMS/jNeuroML which component is the simulation entry point. -->
<Target component="sim_NeuroML_Ex11__IaF_Cell__STDP_Network_"/>
<!-- ════════════════════════════════════════════════════════════════
Dimensions & Units (inline — no external includes needed)
════════════════════════════════════════════════════════════════ -->
<!-- Dimensions -->
<Dimension name="none"/>
<Dimension name="time" t="1"/>
<Dimension name="voltage" m="1" l="2" t="-3" i="-1"/>
<Dimension name="per_time" t="-1"/>
<Dimension name="conductance" m="-1" l="-2" t="3" i="2"/>
<Dimension name="capacitance" m="-1" l="-2" t="4" i="2"/>
<Dimension name="current" i="1"/>
<Dimension name="resistance" m="1" l="2" t="-3" i="-2"/>
<Dimension name="concentration" l="-3" n="1"/>
<Dimension name="substance" n="1"/>
<Dimension name="charge" t="1" i="1"/>
<Dimension name="temperature" k="1"/>
<!-- Units -->
<Unit symbol="s" dimension="time" power="0"/>
<Unit symbol="ms" dimension="time" power="-3"/>
<Unit symbol="us" dimension="time" power="-6"/>
<Unit symbol="V" dimension="voltage" power="0"/>
<Unit symbol="mV" dimension="voltage" power="-3"/>
<
3. Run Reference
import sys, os
sys.path.insert(0 , os.path.dirname(os.path.abspath("." )))
from _nml_helpers import run_lems_example
ref_outputs = run_lems_example("LEMS_NML2_Ex11_STDP.xml" )
for name, arr in ref_outputs.items():
print (f" { name} : shape= { arr. shape} " )
auto.dat: shape=(30001, 4)
4. Run TVBO
import numpy as np
result = exp.run("neuroml" )
da = result.integration.data
tvbo_arr = np.column_stack([da.coords['time' ].values, da.values])
print (f"TVBO: shape= { tvbo_arr. shape} " )
5. Plot Reference Network
import matplotlib.pyplot as plt
import numpy as np
for name, ref_arr in ref_outputs.items():
t = ref_arr[:, 0 ] * 1000
fig, ax = plt.subplots(figsize= (10 , 3 ))
for i in range (1 , min (ref_arr.shape[1 ], 5 )):
ax.plot(t, ref_arr[:, i], alpha= 0.8 , label= f'col { i} ' )
ax.set_xlabel("Time (ms)" )
ax.set_title(f"Ex11: STDP — { name} " )
ax.legend(fontsize= 7 )
ax.grid(True , alpha= 0.3 )
plt.tight_layout()
plt.show()
The STDP trace ODEs (\(dA/dt = -A/\tau\) ) are expressible as TVBO state variables. The weight update rule on spike events uses the event mechanism. The network topology is NeuroML-native.