sc_neurocore_engine/bindings/
mckean.rs1use crate::neurons::McKeanNeuron;
11use numpy::{IntoPyArray, PyReadonlyArray1};
12use pyo3::exceptions::PyValueError;
13use pyo3::prelude::*;
14use pyo3::types::PyDict;
15
16#[pyclass(
17 name = "McKeanNeuron",
18 module = "sc_neurocore_engine.sc_neurocore_engine"
19)]
20#[derive(Clone)]
21pub struct PyMcKeanNeuron {
22 inner: McKeanNeuron,
23}
24
25#[pymethods]
26impl PyMcKeanNeuron {
27 #[new]
28 #[pyo3(signature=(v=0.0,w=0.0,a=0.25,lambda_=1.0,mu=1.0,b=0.01,dt=0.1))]
29 fn new(v: f64, w: f64, a: f64, lambda_: f64, mu: f64, b: f64, dt: f64) -> PyResult<Self> {
30 let inner = McKeanNeuron {
31 v,
32 w,
33 a,
34 lambda: lambda_,
35 mu,
36 b,
37 dt,
38 };
39 if !inner.valid() {
40 return Err(PyValueError::new_err(
41 "invalid McKean state or configuration",
42 ));
43 }
44 Ok(Self { inner })
45 }
46 fn step(&mut self, current: f64) -> PyResult<i32> {
47 self.inner.try_step(current).map_err(PyValueError::new_err)
48 }
49 fn reset(&mut self) {
50 self.inner.reset();
51 }
52 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
53 let d = PyDict::new(py);
54 d.set_item("v", self.inner.v)?;
55 d.set_item("w", self.inner.w)?;
56 Ok(d.into_any().unbind())
57 }
58}
59
60#[pyfunction]
61#[pyo3(signature=(v,w,a,lambda_,mu,b,dt,currents))]
62#[allow(clippy::too_many_arguments)]
63fn py_mckean_simulate<'py>(
64 py: Python<'py>,
65 v: f64,
66 w: f64,
67 a: f64,
68 lambda_: f64,
69 mu: f64,
70 b: f64,
71 dt: f64,
72 currents: PyReadonlyArray1<'py, f64>,
73) -> PyResult<Py<PyAny>> {
74 let mut n = McKeanNeuron {
75 v,
76 w,
77 a,
78 lambda: lambda_,
79 mu,
80 b,
81 dt,
82 };
83 if !n.valid() {
84 return Err(PyValueError::new_err(
85 "invalid McKean state or configuration",
86 ));
87 }
88 let mut voltages = Vec::with_capacity(currents.len()?);
89 let mut recovery = Vec::with_capacity(currents.len()?);
90 let mut events = Vec::with_capacity(currents.len()?);
91 for ¤t in currents.as_slice()? {
92 events.push(n.try_step(current).map_err(PyValueError::new_err)?);
93 voltages.push(n.v);
94 recovery.push(n.w);
95 }
96 let d = PyDict::new(py);
97 d.set_item("voltages", voltages.into_pyarray(py))?;
98 d.set_item("recovery", recovery.into_pyarray(py))?;
99 d.set_item("events", events.into_pyarray(py))?;
100 d.set_item("v_final", n.v)?;
101 d.set_item("w_final", n.w)?;
102 Ok(d.into_any().unbind())
103}
104
105pub(super) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
106 module.add_class::<PyMcKeanNeuron>()?;
107 module.add_function(wrap_pyfunction!(py_mckean_simulate, module)?)?;
108 Ok(())
109}