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
18type CompleteTracePacket<'py> = (
19    Bound<'py, PyArray1<f64>>,
20    Bound<'py, PyArray1<f64>>,
21    i64,
22    f64,
23    f64,
24);
25
26py_neuron_default!("ChialvoMapNeuron", PyChialvoMapNeuron, ChialvoMapNeuron, state x, state y);
27
28/// Register the Chialvo-map class and simulator with the extension module.
29pub(super) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
30    module.add_class::<PyChialvoMapNeuron>()?;
31    module.add_function(wrap_pyfunction!(py_chialvo_map_simulate, module)?)?;
32    module.add_function(wrap_pyfunction!(py_chialvo_map_simulate_complete, module)?)?;
33    Ok(())
34}
35
36/// N-step Chialvo simulation with complete fast and recovery traces.
37///
38/// The returned packet contains post-step `x` and `y` arrays, the maintained
39/// upward-crossing count, and both final states. The underlying engine batch
40/// is failure-atomic.
41#[pyfunction]
42#[pyo3(signature = (x0, y0, a, b, c, k, x_threshold, n_steps, current))]
43#[allow(clippy::too_many_arguments)]
44fn py_chialvo_map_simulate_complete<'py>(
45    py: Python<'py>,
46    x0: f64,
47    y0: f64,
48    a: f64,
49    b: f64,
50    c: f64,
51    k: f64,
52    x_threshold: f64,
53    n_steps: usize,
54    current: f64,
55) -> PyResult<CompleteTracePacket<'py>> {
56    let mut neuron = ChialvoMapNeuron {
57        x: x0,
58        y: y0,
59        a,
60        b,
61        c,
62        k,
63        x_threshold,
64    };
65    let (x_trace, y_trace, spikes) = neuron
66        .simulate_complete(n_steps, current)
67        .map_err(PyFloatingPointError::new_err)?;
68    Ok((
69        x_trace.into_pyarray(py),
70        y_trace.into_pyarray(py),
71        spikes,
72        neuron.x,
73        neuron.y,
74    ))
75}
76
77/// N-step Chialvo (1995) two-dimensional-map simulation.
78///
79/// The recurrence matches
80/// `sc_neurocore.neurons.models.chialvo_map.ChialvoMapNeuron.simulate`. The
81/// returned trace records `x` after every simultaneous map update; the event
82/// count uses the maintained upward `x_threshold` crossing convention. The
83/// checked path rejects non-finite state, parameters, input, or candidates
84/// without committing a corrupt state.
85#[pyfunction]
86#[pyo3(signature = (x0, y0, a, b, c, k, x_threshold, n_steps, current))]
87#[allow(clippy::too_many_arguments)]
88fn py_chialvo_map_simulate<'py>(
89    py: Python<'py>,
90    x0: f64,
91    y0: f64,
92    a: f64,
93    b: f64,
94    c: f64,
95    k: f64,
96    x_threshold: f64,
97    n_steps: usize,
98    current: f64,
99) -> PyResult<(Bound<'py, PyArray1<f64>>, i64, f64, f64)> {
100    let mut neuron = ChialvoMapNeuron {
101        x: x0,
102        y: y0,
103        a,
104        b,
105        c,
106        k,
107        x_threshold,
108    };
109    let (trace, spikes) = neuron
110        .simulate(n_steps, current)
111        .map_err(PyFloatingPointError::new_err)?;
112    Ok((trace.into_pyarray(py), spikes, neuron.x, neuron.y))
113}