sc_neurocore_engine/bindings/
brunel.rs1use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};
12use pyo3::exceptions::PyValueError;
13use pyo3::prelude::*;
14
15use crate::brunel;
16
17pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
19 module.add_class::<PyBrunelNetwork>()?;
20 Ok(())
21}
22
23#[pyclass(
24 name = "BrunelNetwork",
25 module = "sc_neurocore_engine.sc_neurocore_engine"
26)]
27pub struct PyBrunelNetwork {
28 inner: brunel::BrunelNetwork,
29}
30
31#[pymethods]
32impl PyBrunelNetwork {
33 #[new]
34 #[pyo3(signature = (
35 n_neurons,
36 w_indptr,
37 w_indices,
38 w_data,
39 leak_k,
40 gain_k,
41 ext_lambda,
42 ext_weight_fp,
43 data_width=16,
44 fraction=8,
45 v_rest=0,
46 v_reset=0,
47 v_threshold=256,
48 refractory_period=2,
49 seed=42
50 ))]
51 #[allow(clippy::too_many_arguments)]
52 fn new(
53 n_neurons: usize,
54 w_indptr: PyReadonlyArray1<'_, i64>,
55 w_indices: PyReadonlyArray1<'_, i64>,
56 w_data: PyReadonlyArray1<'_, i16>,
57 leak_k: i16,
58 gain_k: i16,
59 ext_lambda: f64,
60 ext_weight_fp: i16,
61 data_width: u32,
62 fraction: u32,
63 v_rest: i16,
64 v_reset: i16,
65 v_threshold: i16,
66 refractory_period: i32,
67 seed: u64,
68 ) -> PyResult<Self> {
69 let indptr = w_indptr
70 .as_slice()
71 .map_err(|e| PyValueError::new_err(format!("Cannot read w_indptr: {e}")))?;
72 let indices = w_indices
73 .as_slice()
74 .map_err(|e| PyValueError::new_err(format!("Cannot read w_indices: {e}")))?;
75 let data = w_data
76 .as_slice()
77 .map_err(|e| PyValueError::new_err(format!("Cannot read w_data: {e}")))?;
78
79 let row_offsets: Vec<usize> = indptr.iter().map(|&v| v as usize).collect();
80 let col_indices: Vec<usize> = indices.iter().map(|&v| v as usize).collect();
81 let values: Vec<i16> = data.to_vec();
82
83 let inner = brunel::BrunelNetwork::new(
84 n_neurons,
85 row_offsets,
86 col_indices,
87 values,
88 data_width,
89 fraction,
90 v_rest,
91 v_reset,
92 v_threshold,
93 refractory_period,
94 leak_k,
95 gain_k,
96 ext_lambda,
97 ext_weight_fp,
98 seed,
99 )
100 .map_err(PyValueError::new_err)?;
101
102 Ok(Self { inner })
103 }
104
105 fn run<'py>(&mut self, py: Python<'py>, n_steps: usize) -> Bound<'py, PyArray1<u32>> {
106 let counts = self.inner.run(n_steps);
107 counts.into_pyarray(py)
108 }
109}