Skip to main content

sc_neurocore_engine/bindings/
pernarowski.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 — Pernarowski neuron PyO3 binding
8
9//! Python binding for the Pernarowski autonomous beta-cell burster.
10
11use numpy::{IntoPyArray, PyArray1};
12use pyo3::prelude::*;
13use pyo3::types::PyDict;
14
15use crate::neurons::PernarowskiNeuron;
16
17py_neuron_default!("PernarowskiNeuron", PyPernarowskiNeuron, PernarowskiNeuron, state v, state w, state z);
18
19/// Register the Pernarowski class and simulator with the extension module.
20pub(super) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
21    module.add_class::<PyPernarowskiNeuron>()?;
22    module.add_function(wrap_pyfunction!(py_pernarowski_simulate, module)?)?;
23    Ok(())
24}
25
26/// N-step Pernarowski (1994) pancreatic beta-cell burster simulation.
27///
28/// Parity contract with
29/// `sc_neurocore.neurons.models.pernarowski.PernarowskiNeuron.simulate`: for the
30/// same parameters and constant input the returned `v` trace, upward-crossing
31/// spike count, and final `(v, w, z)` state are bit-identical to the Python RK4
32/// reference (the cubic uses `v.powi(3)` = `v*v*v`, matching the Python `v*v*v`;
33/// no transcendental functions).
34#[pyfunction]
35#[pyo3(signature = (v0, w0, z0, alpha, beta, eps1, eps2, gamma, dt, v_threshold, n_steps, current))]
36#[allow(clippy::too_many_arguments)]
37fn py_pernarowski_simulate<'py>(
38    py: Python<'py>,
39    v0: f64,
40    w0: f64,
41    z0: f64,
42    alpha: f64,
43    beta: f64,
44    eps1: f64,
45    eps2: f64,
46    gamma: f64,
47    dt: f64,
48    v_threshold: f64,
49    n_steps: usize,
50    current: f64,
51) -> (Bound<'py, PyArray1<f64>>, i64, f64, f64, f64) {
52    let mut neuron = PernarowskiNeuron {
53        v: v0,
54        w: w0,
55        z: z0,
56        alpha,
57        beta,
58        eps1,
59        eps2,
60        gamma,
61        dt,
62        v_threshold,
63    };
64    let (trace, spikes) = neuron.simulate(n_steps, current);
65    (trace.into_pyarray(py), spikes, neuron.v, neuron.w, neuron.z)
66}