Skip to main content

sc_neurocore_engine/bindings/
izhikevich2007.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// SC-NeuroCore — Izhikevich 2007 PyO3 binding
8
9//! Python binding for the NeuroML Izhikevich 2007 model.
10
11use numpy::{IntoPyArray, PyArray1};
12use pyo3::exceptions::PyFloatingPointError;
13use pyo3::prelude::*;
14
15/// Register the Izhikevich 2007 batch simulator with the extension module.
16pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
17    module.add_function(wrap_pyfunction!(py_izhikevich2007_simulate, module)?)?;
18    Ok(())
19}
20
21/// Parity contract with
22/// `sc_neurocore.neurons.models.izhikevich2007.Izhikevich2007Neuron.simulate`:
23/// for the same parameters and constant input the returned `v` trace, spike
24/// count, and final `(v, u)` state are bit-identical to the Python RK4 reference
25/// (the NeuroML right-hand side `k (v-vr)(v-vt)/C` is exact arithmetic — products,
26/// a sum and a division, no transcendental functions).
27#[pyfunction]
28#[pyo3(signature = (v0, u0, cap, k, vr, vt, vpeak, a, b, c, d, dt, n_steps, current))]
29#[allow(clippy::too_many_arguments)]
30fn py_izhikevich2007_simulate<'py>(
31    py: Python<'py>,
32    v0: f64,
33    u0: f64,
34    cap: f64,
35    k: f64,
36    vr: f64,
37    vt: f64,
38    vpeak: f64,
39    a: f64,
40    b: f64,
41    c: f64,
42    d: f64,
43    dt: f64,
44    n_steps: usize,
45    current: f64,
46) -> PyResult<(Bound<'py, PyArray1<f64>>, i64, f64, f64)> {
47    let mut neuron = crate::rk4_neurons::Izhikevich2007Rk4 {
48        v: v0,
49        u: u0,
50        cap,
51        k,
52        vr,
53        vt,
54        vpeak,
55        a,
56        b,
57        c,
58        d,
59        dt,
60    };
61    let (trace, spikes) = neuron
62        .simulate(n_steps, current)
63        .map_err(PyFloatingPointError::new_err)?;
64    Ok((trace.into_pyarray(py), spikes, neuron.v, neuron.u))
65}