Model: PyNN Cell Types
NeuroML2 includes PyNN-compatible cell types, all expressible as ODEs:
- IF_curr_alpha: \(C\frac{dv}{dt} = -g_L(v - E_L) + I_{syn}\)
- IF_cond_exp: \(C\frac{dv}{dt} = -g_L(v - E_L) - g_{syn}(v - E_{syn})\)
- EIF_cond_exp: AdEx model (same as Ex8)
- HH_cond_exp: Hodgkin-Huxley (same as Ex1)
1. Define AdEx (EIF) in TVBO
from tvbo import SimulationExperiment
exp = SimulationExperiment.from_string("""
label: "NeuroML Ex14: PyNN AdEx Cell"
dynamics:
name: AdaptiveExponentialIF
parameters:
C: { value: 281.0 }
gL: { value: 30.0 }
EL: { value: -70.6 }
VT: { value: -50.4 }
thresh: { value: -40.4 }
reset: { value: -48.5 }
delT: { value: 2.0 }
tauw: { value: 40.0 }
a: { value: 4.0 }
b: { value: 0.08 }
I_ext: { value: 0.8 }
state_variables:
v:
equation:
rhs: "(-gL*(v - EL) + gL*delT*exp((v - VT)/delT) - w + I_ext) / C"
initial_value: -70.6
variable_of_interest: true
w:
equation:
rhs: "(a*(v - EL) - w) / tauw"
initial_value: 0.0
events:
spike:
condition: { rhs: "v > thresh" }
affect: { rhs: "v = reset; w = w + b" }
network:
number_of_nodes: 1
integration:
method: euler
step_size: 0.025
duration: 300.0
time_scale: ms
""")
print(f"Model: {exp.dynamics.name}")
Model: AdaptiveExponentialIF
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_Ex14__PyNN_AdEx_Cell"/>
<!-- ════════════════════════════════════════════════════════════════
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"/>
<Unit symb
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_Ex14_PyNN.xml")
for name, arr in ref_outputs.items():
print(f" {name}: shape={arr.shape}")
ex14.dat: shape=(50001, 9)
ex14_g.dat: shape=(50001, 3)
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 All PyNN Variants (Reference)
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, 4))
for i in range(1, min(ref_arr.shape[1], 6)):
ax.plot(t, ref_arr[:, i] * 1000, alpha=0.8, label=f'Cell {i}')
ax.set_xlabel("Time (ms)")
ax.set_ylabel("Voltage (mV)")
ax.set_title(f"Ex14: PyNN Cells — {name}")
ax.legend(fontsize=7)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
All four PyNN cell types are expressible as TVBO ODE systems: IaF (Ex0), conductance-based IaF, AdEx (Ex8), and HH (Ex1).