Skip to main content

sc_neurocore_engine/bindings/
chialvo_map.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 — Chialvo-map PyO3 binding
8
9//! Python binding for the checked Chialvo two-dimensional map.
10
11use numpy::{IntoPyArray, PyArray1};
12use pyo3::exceptions::PyFloatingPointError;
13use pyo3::prelude::*;
14use pyo3::types::PyDict;
15
16use crate::neurons::ChialvoMapNeuron;
17
18py_neuron_default!("ChialvoMapNeuron", PyChialvoMapNeuron, ChialvoMapNeuron, state x, state y);
19
20/// Register the Chialvo-map class and simulator with the extension module.
21pub(super) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
22    module.add_class::<PyChialvoMapNeuron>()?;
23    module.add_function(wrap_pyfunction!(py_chialvo_map_simulate, module)?)?;
24    Ok(())
25}
26
27/// N-step Chialvo (1995) two-dimensional-map simulation.
28///
29/// The recurrence matches
30/// `sc_neurocore.neurons.models.chialvo_map.ChialvoMapNeuron.simulate`. The
31/// returned trace records `x` after every simultaneous map update; the event
32/// count uses the maintained upward `x_threshold` crossing convention. The
33/// checked path rejects non-finite state, parameters, input, or candidates
34/// without committing a corrupt state.
35#[pyfunction]
36#[pyo3(signature = (x0, y0, a, b, c, k, x_threshold, n_steps, current))]
37#[allow(clippy::too_many_arguments)]
38fn py_chialvo_map_simulate<'py>(
39    py: Python<'py>,
40    x0: f64,
41    y0: f64,
42    a: f64,
43    b: f64,
44    c: f64,
45    k: f64,
46    x_threshold: f64,
47    n_steps: usize,
48    current: f64,
49) -> PyResult<(Bound<'py, PyArray1<f64>>, i64, f64, f64)> {
50    let mut neuron = ChialvoMapNeuron {
51        x: x0,
52        y: y0,
53        a,
54        b,
55        c,
56        k,
57        x_threshold,
58    };
59    let (trace, spikes) = neuron
60        .simulate(n_steps, current)
61        .map_err(PyFloatingPointError::new_err)?;
62    Ok((trace.into_pyarray(py), spikes, neuron.x, neuron.y))
63}