sc_neurocore_engine/bindings/
mihalas_niebur.rs1use numpy::{IntoPyArray, PyArray1};
12use pyo3::exceptions::PyFloatingPointError;
13use pyo3::prelude::*;
14use pyo3::types::PyDict;
15
16use crate::neurons::MihalasNieburNeuron;
17
18type MihalasNieburBatchOutput<'py> = (Bound<'py, PyArray1<f64>>, i64, f64, f64, f64, f64);
19
20py_neuron_default!(
21 "MihalasNieburNeuron",
22 PyMihalasNieburNeuron,
23 MihalasNieburNeuron,
24 state v,
25 state theta,
26 state i1,
27 state i2
28);
29
30pub(super) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
32 module.add_class::<PyMihalasNieburNeuron>()?;
33 module.add_function(wrap_pyfunction!(py_mihalas_niebur_simulate, module)?)?;
34 Ok(())
35}
36
37#[pyfunction]
39#[pyo3(signature = (
40 v0, theta0, i1_0, i2_0, v_rest, v_reset, theta_reset, theta_inf,
41 leak_rate, threshold_voltage_coupling, threshold_decay_rate,
42 current_decay_rate_1, current_decay_rate_2, current_retention_1,
43 current_retention_2, current_jump_1, current_jump_2, dt, n_steps, current
44))]
45#[allow(clippy::too_many_arguments)]
46fn py_mihalas_niebur_simulate<'py>(
47 py: Python<'py>,
48 v0: f64,
49 theta0: f64,
50 i1_0: f64,
51 i2_0: f64,
52 v_rest: f64,
53 v_reset: f64,
54 theta_reset: f64,
55 theta_inf: f64,
56 leak_rate: f64,
57 threshold_voltage_coupling: f64,
58 threshold_decay_rate: f64,
59 current_decay_rate_1: f64,
60 current_decay_rate_2: f64,
61 current_retention_1: f64,
62 current_retention_2: f64,
63 current_jump_1: f64,
64 current_jump_2: f64,
65 dt: f64,
66 n_steps: usize,
67 current: f64,
68) -> PyResult<MihalasNieburBatchOutput<'py>> {
69 let mut neuron = MihalasNieburNeuron {
70 v: v0,
71 theta: theta0,
72 i1: i1_0,
73 i2: i2_0,
74 v_rest,
75 v_reset,
76 theta_reset,
77 theta_inf,
78 leak_rate,
79 threshold_voltage_coupling,
80 threshold_decay_rate,
81 current_decay_rate_1,
82 current_decay_rate_2,
83 current_retention_1,
84 current_retention_2,
85 current_jump_1,
86 current_jump_2,
87 dt,
88 };
89 let Some((trace, events)) = neuron.try_simulate(n_steps, current) else {
90 return Err(PyFloatingPointError::new_err(
91 "Mihalas-Niebur Rust batch rejected an invalid candidate",
92 ));
93 };
94 Ok((
95 trace.into_pyarray(py),
96 events,
97 neuron.v,
98 neuron.theta,
99 neuron.i1,
100 neuron.i2,
101 ))
102}