1use numpy::{IntoPyArray, PyArray1};
15use pyo3::prelude::*;
16use pyo3::types::PyDict;
17
18use crate::neurons;
19
20macro_rules! py_neuron_default {
21 ($pylit:literal, $pyname:ident, $rust:ty $(, state $sname:ident)*) => {
22 #[pyclass(name = $pylit, module = "sc_neurocore_engine.sc_neurocore_engine")]
23 #[derive(Clone)]
24 pub struct $pyname { inner: $rust }
25
26 #[pymethods]
27 impl $pyname {
28 #[new]
29 fn new() -> Self { Self { inner: <$rust>::default() } }
30
31 fn step(&mut self, current: f64) -> i32 { self.inner.step(current) }
32
33 fn reset(&mut self) { self.inner.reset(); }
34
35 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
36 let d = PyDict::new(py);
37 $(d.set_item(stringify!($sname), self.inner.$sname)?;)*
38 Ok(d.into_any().unbind())
39 }
40 }
41 };
42}
43
44py_neuron_default!("MultiTimescaleNeuron", PyMultiTimescaleNeuron, neurons::MultiTimescaleNeuron, state v_fast, state v_medium, state v_slow);
49py_neuron_default!("AttentionGatedNeuron", PyAttentionGatedNeuron, neurons::AttentionGatedNeuron, state v);
50py_neuron_default!("PredictiveCodingNeuron", PyPredictiveCodingNeuron, neurons::PredictiveCodingNeuron, state v, state pred);
51py_neuron_default!("SelfReferentialNeuron", PySelfReferentialNeuron, neurons::SelfReferentialNeuron, state v);
52py_neuron_default!("CompositionalBindingNeuron", PyCompositionalBindingNeuron, neurons::CompositionalBindingNeuron, state phi, state amplitude);
53py_neuron_default!("DifferentiableSurrogateNeuron", PyDifferentiableSurrogateNeuron, neurons::DifferentiableSurrogateNeuron, state v);
54py_neuron_default!("MetaPlasticNeuron", PyMetaPlasticNeuron, neurons::MetaPlasticNeuron, state v, state error_trace, state expected_reward);
55
56py_neuron_default!("ArcaneNeuron", PyArcaneNeuron, neurons::ArcaneNeuron, state v_fast, state v_work, state v_deep);
57
58#[pyclass(
60 name = "RustContinuousAttractorNeuron",
61 module = "sc_neurocore_engine.sc_neurocore_engine"
62)]
63#[derive(Clone)]
64pub struct PyContinuousAttractorNeuron {
65 inner: neurons::ContinuousAttractorNeuron,
66}
67
68#[pymethods]
69impl PyContinuousAttractorNeuron {
70 #[new]
71 #[pyo3(signature = (n_units=16))]
72 fn new(n_units: usize) -> Self {
73 Self {
74 inner: neurons::ContinuousAttractorNeuron::new(n_units),
75 }
76 }
77 fn step(&mut self, current: f64) -> i32 {
78 self.inner.step(current)
79 }
80 fn bump_position(&self) -> usize {
81 self.inner.bump_position()
82 }
83 fn reset(&mut self) {
84 self.inner.reset();
85 }
86 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
87 let d = PyDict::new(py);
88 d.set_item("u", self.inner.u.clone().into_pyarray(py))?;
89 Ok(d.into_any().unbind())
90 }
91}
92
93py_neuron_default!("QuadraticIFNeuron", PyQuadraticIFNeuron, neurons::QuadraticIFNeuron, state v);
98py_neuron_default!("ThetaNeuron", PyThetaNeuron, neurons::ThetaNeuron, state theta);
99py_neuron_default!("PerfectIntegratorNeuron", PyPerfectIntegratorNeuron, neurons::PerfectIntegratorNeuron, state v);
100py_neuron_default!("GatedLIFNeuron", PyGatedLIFNeuron, neurons::GatedLIFNeuron, state v);
101py_neuron_default!("NonlinearLIFNeuron", PyNonlinearLIFNeuron, neurons::NonlinearLIFNeuron, state v, state w);
102py_neuron_default!("SFANeuron", PySFANeuron, neurons::SFANeuron, state v, state g_sfa);
103py_neuron_default!("MATNeuron", PyMATNeuron, neurons::MATNeuron, state v, state theta1, state theta2);
104py_neuron_default!("KLIFNeuron", PyKLIFNeuron, neurons::KLIFNeuron, state v);
105py_neuron_default!("InhibitoryLIFNeuron", PyInhibitoryLIFNeuron, neurons::InhibitoryLIFNeuron, state v, state inh_trace);
106py_neuron_default!("ComplementaryLIFNeuron", PyComplementaryLIFNeuron, neurons::ComplementaryLIFNeuron, state v_pos, state v_neg);
107py_neuron_default!("ParametricLIFNeuron", PyParametricLIFNeuron, neurons::ParametricLIFNeuron, state v);
108py_neuron_default!("NonResettingLIFNeuron", PyNonResettingLIFNeuron, neurons::NonResettingLIFNeuron, state v, state theta);
109py_neuron_default!("AdaptiveThresholdIFNeuron", PyAdaptiveThresholdIFNeuron, neurons::AdaptiveThresholdIFNeuron, state v, state theta);
110py_neuron_default!("SigmaDeltaNeuron", PySigmaDeltaNeuron, neurons::SigmaDeltaNeuron, state sigma);
111py_neuron_default!("EnergyLIFNeuron", PyEnergyLIFNeuron, neurons::EnergyLIFNeuron, state v, state epsilon);
112py_neuron_default!("ClosedFormContinuousNeuron", PyClosedFormContinuousNeuron, neurons::ClosedFormContinuousNeuron, state x);
113
114#[pyclass(
115 name = "IntegerQIFNeuron",
116 module = "sc_neurocore_engine.sc_neurocore_engine"
117)]
118#[derive(Clone)]
119pub struct PyIntegerQIFNeuron {
120 inner: neurons::IntegerQIFNeuron,
121}
122
123#[pymethods]
124impl PyIntegerQIFNeuron {
125 #[new]
126 #[pyo3(signature = (k=6, v_threshold=1024))]
127 fn new(k: i32, v_threshold: i32) -> Self {
128 Self {
129 inner: neurons::IntegerQIFNeuron::new(k, v_threshold),
130 }
131 }
132 fn step(&mut self, current: i32) -> i32 {
133 self.inner.step(current)
134 }
135 fn reset(&mut self) {
136 self.inner.reset();
137 }
138 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
139 let d = PyDict::new(py);
140 d.set_item("v", self.inner.v)?;
141 Ok(d.into_any().unbind())
142 }
143}
144
145#[pyclass(
147 name = "EscapeRateNeuron",
148 module = "sc_neurocore_engine.sc_neurocore_engine"
149)]
150#[derive(Clone)]
151pub struct PyEscapeRateNeuron {
152 inner: neurons::EscapeRateNeuron,
153}
154
155#[pymethods]
156impl PyEscapeRateNeuron {
157 #[new]
158 #[pyo3(signature = (seed=42))]
159 fn new(seed: u64) -> Self {
160 Self {
161 inner: neurons::EscapeRateNeuron::new(seed),
162 }
163 }
164 fn step(&mut self, current: f64) -> i32 {
165 self.inner.step(current)
166 }
167 fn reset(&mut self) {
168 self.inner.reset();
169 }
170 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
171 let d = PyDict::new(py);
172 d.set_item("v", self.inner.v)?;
173 Ok(d.into_any().unbind())
174 }
175}
176
177py_neuron_default!("FitzHughNagumoNeuron", PyFitzHughNagumoNeuron, neurons::FitzHughNagumoNeuron, state v, state w);
182py_neuron_default!("MorrisLecarNeuron", PyMorrisLecarNeuron, neurons::MorrisLecarNeuron, state v, state w);
183py_neuron_default!("HindmarshRoseNeuron", PyHindmarshRoseNeuron, neurons::HindmarshRoseNeuron, state x, state y, state z);
184py_neuron_default!("ResonateAndFireNeuron", PyResonateAndFireNeuron, neurons::ResonateAndFireNeuron, state x, state y);
185py_neuron_default!("FitzHughRinzelNeuron", PyFitzHughRinzelNeuron, neurons::FitzHughRinzelNeuron, state v, state w, state y);
186py_neuron_default!("McKeanNeuron", PyMcKeanNeuron, neurons::McKeanNeuron, state v, state w);
187py_neuron_default!("TermanWangOscillator", PyTermanWangOscillator, neurons::TermanWangOscillator, state v, state w);
188py_neuron_default!("GutkinErmentroutNeuron", PyGutkinErmentroutNeuron, neurons::GutkinErmentroutNeuron, state v, state n);
189py_neuron_default!("WilsonHRNeuron", PyWilsonHRNeuron, neurons::WilsonHRNeuron, state v, state r);
190py_neuron_default!("ChayNeuron", PyChayNeuron, neurons::ChayNeuron, state v, state n, state ca);
191py_neuron_default!("ChayKeizerNeuron", PyChayKeizerNeuron, neurons::ChayKeizerNeuron, state v, state n, state ca);
192py_neuron_default!("ShermanRinzelKeizerNeuron", PyShermanRinzelKeizerNeuron, neurons::ShermanRinzelKeizerNeuron, state v, state n, state s);
193py_neuron_default!("ButeraRespiratoryNeuron", PyButeraRespiratoryNeuron, neurons::ButeraRespiratoryNeuron, state v, state n, state h_nap);
194py_neuron_default!("LearnableNeuronModel", PyLearnableNeuronModel, neurons::LearnableNeuronModel, state v);
195py_neuron_default!("PernarowskiNeuron", PyPernarowskiNeuron, neurons::PernarowskiNeuron, state v, state w, state z);
196
197#[pyclass(
199 name = "AlphaNeuron",
200 module = "sc_neurocore_engine.sc_neurocore_engine"
201)]
202#[derive(Clone)]
203pub struct PyAlphaNeuron {
204 inner: neurons::AlphaNeuron,
205}
206
207#[pymethods]
208impl PyAlphaNeuron {
209 #[new]
210 fn new() -> Self {
211 Self {
212 inner: neurons::AlphaNeuron::new(),
213 }
214 }
215 #[pyo3(signature = (exc_current, inh_current=0.0))]
216 fn step(&mut self, exc_current: f64, inh_current: f64) -> i32 {
217 self.inner.step(exc_current, inh_current)
218 }
219 fn reset(&mut self) {
220 self.inner.reset();
221 }
222 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
223 let d = PyDict::new(py);
224 d.set_item("v", self.inner.v)?;
225 d.set_item("i_exc", self.inner.i_exc)?;
226 d.set_item("i_inh", self.inner.i_inh)?;
227 Ok(d.into_any().unbind())
228 }
229}
230
231#[pyclass(
233 name = "COBALIFNeuron",
234 module = "sc_neurocore_engine.sc_neurocore_engine"
235)]
236#[derive(Clone)]
237pub struct PyCOBALIFNeuron {
238 inner: neurons::COBALIFNeuron,
239}
240
241#[pymethods]
242impl PyCOBALIFNeuron {
243 #[new]
244 fn new() -> Self {
245 Self {
246 inner: neurons::COBALIFNeuron::new(),
247 }
248 }
249 #[pyo3(signature = (current, delta_ge=0.0, delta_gi=0.0))]
250 fn step(&mut self, current: f64, delta_ge: f64, delta_gi: f64) -> i32 {
251 self.inner.step(current, delta_ge, delta_gi)
252 }
253 fn reset(&mut self) {
254 self.inner.reset();
255 }
256 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
257 let d = PyDict::new(py);
258 d.set_item("v", self.inner.v)?;
259 d.set_item("g_e", self.inner.g_e)?;
260 d.set_item("g_i", self.inner.g_i)?;
261 Ok(d.into_any().unbind())
262 }
263}
264
265#[pyclass(
267 name = "EPropALIFNeuron",
268 module = "sc_neurocore_engine.sc_neurocore_engine"
269)]
270#[derive(Clone)]
271pub struct PyEPropALIFNeuron {
272 inner: neurons::EPropALIFNeuron,
273}
274
275#[pymethods]
276impl PyEPropALIFNeuron {
277 #[new]
278 #[pyo3(signature = (tau_m=20.0, tau_a=200.0, dt=1.0))]
279 fn new(tau_m: f64, tau_a: f64, dt: f64) -> Self {
280 Self {
281 inner: neurons::EPropALIFNeuron::new(tau_m, tau_a, dt),
282 }
283 }
284 fn step(&mut self, current: f64) -> i32 {
285 self.inner.step(current)
286 }
287 fn reset(&mut self) {
288 self.inner.reset();
289 }
290 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
291 let d = PyDict::new(py);
292 d.set_item("v", self.inner.v)?;
293 d.set_item("a", self.inner.a)?;
294 d.set_item("e_trace", self.inner.e_trace)?;
295 Ok(d.into_any().unbind())
296 }
297}
298
299#[pyclass(
301 name = "SuperSpikeNeuron",
302 module = "sc_neurocore_engine.sc_neurocore_engine"
303)]
304#[derive(Clone)]
305pub struct PySuperSpikeNeuron {
306 inner: neurons::SuperSpikeNeuron,
307}
308
309#[pymethods]
310impl PySuperSpikeNeuron {
311 #[new]
312 #[pyo3(signature = (tau_m=10.0, tau_e=10.0, dt=1.0))]
313 fn new(tau_m: f64, tau_e: f64, dt: f64) -> Self {
314 Self {
315 inner: neurons::SuperSpikeNeuron::new(tau_m, tau_e, dt),
316 }
317 }
318 fn step(&mut self, current: f64) -> i32 {
319 self.inner.step(current)
320 }
321 fn reset(&mut self) {
322 self.inner.reset();
323 }
324 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
325 let d = PyDict::new(py);
326 d.set_item("v", self.inner.v)?;
327 d.set_item("trace", self.inner.trace)?;
328 Ok(d.into_any().unbind())
329 }
330}
331
332#[pyclass(
334 name = "BendaHerzNeuron",
335 module = "sc_neurocore_engine.sc_neurocore_engine"
336)]
337#[derive(Clone)]
338pub struct PyBendaHerzNeuron {
339 inner: neurons::BendaHerzNeuron,
340}
341
342#[pymethods]
343impl PyBendaHerzNeuron {
344 #[new]
345 #[pyo3(signature = (seed=42))]
346 fn new(seed: u64) -> Self {
347 Self {
348 inner: neurons::BendaHerzNeuron::new(seed),
349 }
350 }
351 fn step(&mut self, current: f64) -> i32 {
352 self.inner.step(current)
353 }
354 fn reset(&mut self) {
355 self.inner.reset();
356 }
357 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
358 let d = PyDict::new(py);
359 d.set_item("a", self.inner.a)?;
360 Ok(d.into_any().unbind())
361 }
362}
363
364py_neuron_default!("ChialvoMapNeuron", PyChialvoMapNeuron, neurons::ChialvoMapNeuron, state x, state y);
369py_neuron_default!("RulkovMapNeuron", PyRulkovMapNeuron, neurons::RulkovMapNeuron, state x, state y);
370py_neuron_default!("IbarzTanakaMapNeuron", PyIbarzTanakaMapNeuron, neurons::IbarzTanakaMapNeuron, state x, state y);
371py_neuron_default!("MedvedevMapNeuron", PyMedvedevMapNeuron, neurons::MedvedevMapNeuron, state x);
372py_neuron_default!("CazellesMapNeuron", PyCazellesMapNeuron, neurons::CazellesMapNeuron, state x, state y);
373py_neuron_default!("CourageNekorkinMapNeuron", PyCourageNekorkinMapNeuron, neurons::CourageNekorkinMapNeuron, state x, state y);
374
375py_neuron_default!("HodgkinHuxleyNeuron", PyHodgkinHuxleyNeuron, neurons::HodgkinHuxleyNeuron, state v, state m, state h, state n);
380py_neuron_default!("TraubMilesNeuron", PyTraubMilesNeuron, neurons::TraubMilesNeuron, state v, state m, state h, state n);
381py_neuron_default!("WangBuzsakiNeuron", PyWangBuzsakiNeuron, neurons::WangBuzsakiNeuron, state v, state h, state n);
382py_neuron_default!("ConnorStevensNeuron", PyConnorStevensNeuron, neurons::ConnorStevensNeuron, state v, state m, state h, state n, state a, state b);
383py_neuron_default!("DestexheThalamicNeuron", PyDestexheThalamicNeuron, neurons::DestexheThalamicNeuron, state v, state h_na, state n_k, state m_t, state h_t);
384py_neuron_default!("HuberBraunNeuron", PyHuberBraunNeuron, neurons::HuberBraunNeuron, state v, state a_sd, state a_sr);
385py_neuron_default!("GolombFSNeuron", PyGolombFSNeuron, neurons::GolombFSNeuron, state v, state h, state n, state p);
386py_neuron_default!("PospischilNeuron", PyPospischilNeuron, neurons::PospischilNeuron, state v, state m, state h, state n, state p);
387py_neuron_default!("MainenSejnowskiNeuron", PyMainenSejnowskiNeuron, neurons::MainenSejnowskiNeuron, state vs, state va, state m, state h, state n);
388py_neuron_default!("DeSchutterPurkinjeNeuron", PyDeSchutterPurkinjeNeuron, neurons::DeSchutterPurkinjeNeuron, state v, state h_na, state n_k, state m_cap, state h_cap, state q_kca, state ca);
389py_neuron_default!("PlantR15Neuron", PyPlantR15Neuron, neurons::PlantR15Neuron, state v, state m, state h, state n, state ca);
390py_neuron_default!("PrescottNeuron", PyPrescottNeuron, neurons::PrescottNeuron, state v, state w);
391py_neuron_default!("MihalasNieburNeuron", PyMihalasNieburNeuron, neurons::MihalasNieburNeuron, state v, state theta, state i1, state i2);
392py_neuron_default!("GLIFNeuron", PyGLIFNeuron, neurons::GLIFNeuron, state v, state theta, state i_asc1, state i_asc2);
393py_neuron_default!("AvRonCardiacNeuron", PyAvRonCardiacNeuron, neurons::AvRonCardiacNeuron, state v, state h, state n, state s);
394py_neuron_default!("DurstewitzDopamineNeuron", PyDurstewitzDopamineNeuron, neurons::DurstewitzDopamineNeuron, state v, state h_na, state n_k);
395py_neuron_default!("HillTononiNeuron", PyHillTononiNeuron, neurons::HillTononiNeuron, state v, state h_na, state n_k, state m_h, state h_t, state na_i);
396py_neuron_default!("BertramPhantomBurster", PyBertramPhantomBurster, neurons::BertramPhantomBurster, state v, state s1, state s2);
397py_neuron_default!("YamadaNeuron", PyYamadaNeuron, neurons::YamadaNeuron, state v, state n, state q);
398
399#[pyclass(
401 name = "GIFPopulationNeuron",
402 module = "sc_neurocore_engine.sc_neurocore_engine"
403)]
404#[derive(Clone)]
405pub struct PyGIFPopulationNeuron {
406 inner: neurons::GIFPopulationNeuron,
407}
408
409#[pymethods]
410impl PyGIFPopulationNeuron {
411 #[new]
412 #[pyo3(signature = (seed=42))]
413 fn new(seed: u64) -> Self {
414 Self {
415 inner: neurons::GIFPopulationNeuron::new(seed),
416 }
417 }
418 fn step(&mut self, current: f64) -> i32 {
419 self.inner.step(current)
420 }
421 fn reset(&mut self) {
422 self.inner.reset();
423 }
424 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
425 let d = PyDict::new(py);
426 d.set_item("v", self.inner.v)?;
427 d.set_item("theta", self.inner.theta)?;
428 d.set_item("eta", self.inner.eta)?;
429 Ok(d.into_any().unbind())
430 }
431}
432
433#[pyclass(
439 name = "PinskyRinzelNeuron",
440 module = "sc_neurocore_engine.sc_neurocore_engine"
441)]
442#[derive(Clone)]
443pub struct PyPinskyRinzelNeuron {
444 inner: neurons::PinskyRinzelNeuron,
445}
446
447#[pymethods]
448impl PyPinskyRinzelNeuron {
449 #[new]
450 fn new() -> Self {
451 Self {
452 inner: neurons::PinskyRinzelNeuron::new(),
453 }
454 }
455 #[pyo3(signature = (current_soma, current_dend=0.0))]
456 fn step(&mut self, current_soma: f64, current_dend: f64) -> i32 {
457 self.inner.step(current_soma, current_dend)
458 }
459 fn reset(&mut self) {
460 self.inner.reset();
461 }
462 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
463 let d = PyDict::new(py);
464 d.set_item("v_s", self.inner.v_s)?;
465 d.set_item("v_d", self.inner.v_d)?;
466 Ok(d.into_any().unbind())
467 }
468}
469
470#[pyclass(
472 name = "HayL5PyramidalNeuron",
473 module = "sc_neurocore_engine.sc_neurocore_engine"
474)]
475#[derive(Clone)]
476pub struct PyHayL5PyramidalNeuron {
477 inner: neurons::HayL5PyramidalNeuron,
478}
479
480#[pymethods]
481impl PyHayL5PyramidalNeuron {
482 #[new]
483 fn new() -> Self {
484 Self {
485 inner: neurons::HayL5PyramidalNeuron::new(),
486 }
487 }
488 #[pyo3(signature = (current_soma, current_tuft=0.0))]
489 fn step(&mut self, current_soma: f64, current_tuft: f64) -> i32 {
490 self.inner.step(current_soma, current_tuft)
491 }
492 fn reset(&mut self) {
493 self.inner.reset();
494 }
495 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
496 let d = PyDict::new(py);
497 d.set_item("v_s", self.inner.v_s)?;
498 d.set_item("v_t", self.inner.v_t)?;
499 d.set_item("v_a", self.inner.v_a)?;
500 Ok(d.into_any().unbind())
501 }
502}
503
504py_neuron_default!("MarderSTGNeuron", PyMarderSTGNeuron, neurons::MarderSTGNeuron, state v, state ca);
505py_neuron_default!("BoothRinzelNeuron", PyBoothRinzelNeuron, neurons::BoothRinzelNeuron, state vs, state vd, state ca);
506py_neuron_default!("DendrifyNeuron", PyDendrifyNeuron, neurons::DendrifyNeuron, state v_s, state v_d);
507
508#[pyclass(
510 name = "RallCableNeuron",
511 module = "sc_neurocore_engine.sc_neurocore_engine"
512)]
513#[derive(Clone)]
514pub struct PyRallCableNeuron {
515 inner: neurons::RallCableNeuron,
516}
517
518#[pymethods]
519impl PyRallCableNeuron {
520 #[new]
521 #[pyo3(signature = (n_comp=5))]
522 fn new(n_comp: usize) -> Self {
523 Self {
524 inner: neurons::RallCableNeuron::new(n_comp),
525 }
526 }
527 fn step(&mut self, current: f64) -> i32 {
528 self.inner.step(current)
529 }
530 fn reset(&mut self) {
531 self.inner.reset();
532 }
533 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
534 let d = PyDict::new(py);
535 d.set_item("v", self.inner.v.clone())?;
536 Ok(d.into_any().unbind())
537 }
538}
539
540#[pyclass(
542 name = "TwoCompartmentLIFNeuron",
543 module = "sc_neurocore_engine.sc_neurocore_engine"
544)]
545#[derive(Clone)]
546pub struct PyTwoCompartmentLIFNeuron {
547 inner: neurons::TwoCompartmentLIFNeuron,
548}
549
550#[pymethods]
551impl PyTwoCompartmentLIFNeuron {
552 #[new]
553 fn new() -> Self {
554 Self {
555 inner: neurons::TwoCompartmentLIFNeuron::new(),
556 }
557 }
558 #[pyo3(signature = (i_soma, i_dend=0.0))]
559 fn step(&mut self, i_soma: f64, i_dend: f64) -> i32 {
560 self.inner.step(i_soma, i_dend)
561 }
562 fn reset(&mut self) {
563 self.inner.reset();
564 }
565 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
566 let d = PyDict::new(py);
567 d.set_item("v_s", self.inner.v_s)?;
568 d.set_item("v_d", self.inner.v_d)?;
569 Ok(d.into_any().unbind())
570 }
571}
572
573#[pyclass(
578 name = "PoissonNeuron",
579 module = "sc_neurocore_engine.sc_neurocore_engine"
580)]
581#[derive(Clone)]
582pub struct PyPoissonNeuron {
583 inner: neurons::PoissonNeuron,
584}
585
586#[pymethods]
587impl PyPoissonNeuron {
588 #[new]
589 #[pyo3(signature = (rate_hz=100.0, dt_ms=1.0, seed=42))]
590 fn new(rate_hz: f64, dt_ms: f64, seed: u64) -> Self {
591 Self {
592 inner: neurons::PoissonNeuron::new(rate_hz, dt_ms, seed),
593 }
594 }
595 #[pyo3(signature = (rate_override=-1.0))]
596 fn step(&mut self, rate_override: f64) -> i32 {
597 self.inner.step(rate_override)
598 }
599 fn reset(&mut self) {
600 self.inner.reset();
601 }
602}
603
604#[pyclass(
605 name = "InhomogeneousPoissonNeuron",
606 module = "sc_neurocore_engine.sc_neurocore_engine"
607)]
608#[derive(Clone)]
609pub struct PyInhomogeneousPoissonNeuron {
610 inner: neurons::InhomogeneousPoissonNeuron,
611}
612
613#[pymethods]
614impl PyInhomogeneousPoissonNeuron {
615 #[new]
616 #[pyo3(signature = (dt_ms=1.0, seed=42))]
617 fn new(dt_ms: f64, seed: u64) -> Self {
618 Self {
619 inner: neurons::InhomogeneousPoissonNeuron::new(dt_ms, seed),
620 }
621 }
622 fn step(&mut self, rate_hz: f64) -> i32 {
623 self.inner.step(rate_hz)
624 }
625 fn reset(&mut self) {
626 self.inner.reset();
627 }
628}
629
630#[pyclass(
631 name = "GammaRenewalNeuron",
632 module = "sc_neurocore_engine.sc_neurocore_engine"
633)]
634#[derive(Clone)]
635pub struct PyGammaRenewalNeuron {
636 inner: neurons::GammaRenewalNeuron,
637}
638
639#[pymethods]
640impl PyGammaRenewalNeuron {
641 #[new]
642 #[pyo3(signature = (rate_hz=50.0, shape_k=3, seed=42))]
643 fn new(rate_hz: f64, shape_k: u32, seed: u64) -> Self {
644 Self {
645 inner: neurons::GammaRenewalNeuron::new(rate_hz, shape_k, seed),
646 }
647 }
648 #[pyo3(signature = (rate_override=-1.0))]
649 fn step(&mut self, rate_override: f64) -> i32 {
650 self.inner.step(rate_override)
651 }
652 fn reset(&mut self) {
653 self.inner.reset();
654 }
655}
656
657#[pyclass(
658 name = "StochasticIFNeuron",
659 module = "sc_neurocore_engine.sc_neurocore_engine"
660)]
661#[derive(Clone)]
662pub struct PyStochasticIFNeuron {
663 inner: neurons::StochasticIFNeuron,
664}
665
666#[pymethods]
667impl PyStochasticIFNeuron {
668 #[new]
669 #[pyo3(signature = (seed=42))]
670 fn new(seed: u64) -> Self {
671 Self {
672 inner: neurons::StochasticIFNeuron::new(seed),
673 }
674 }
675 fn step(&mut self, current: f64) -> i32 {
676 self.inner.step(current)
677 }
678 fn reset(&mut self) {
679 self.inner.reset();
680 }
681 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
682 let d = PyDict::new(py);
683 d.set_item("v", self.inner.v)?;
684 Ok(d.into_any().unbind())
685 }
686}
687
688#[pyclass(
689 name = "GalvesLocherbachNeuron",
690 module = "sc_neurocore_engine.sc_neurocore_engine"
691)]
692#[derive(Clone)]
693pub struct PyGalvesLocherbachNeuron {
694 inner: neurons::GalvesLocherbachNeuron,
695}
696
697#[pymethods]
698impl PyGalvesLocherbachNeuron {
699 #[new]
700 #[pyo3(signature = (seed=42))]
701 fn new(seed: u64) -> Self {
702 Self {
703 inner: neurons::GalvesLocherbachNeuron::new(seed),
704 }
705 }
706 fn step(&mut self, weighted_input: f64) -> i32 {
707 self.inner.step(weighted_input)
708 }
709 fn reset(&mut self) {
710 self.inner.reset();
711 }
712 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
713 let d = PyDict::new(py);
714 d.set_item("v", self.inner.v)?;
715 Ok(d.into_any().unbind())
716 }
717}
718
719py_neuron_default!("SpikeResponseNeuron", PySpikeResponseNeuron, neurons::SpikeResponseNeuron, state v, state time_since_spike);
720
721#[pyclass(name = "GLMNeuron", module = "sc_neurocore_engine.sc_neurocore_engine")]
723#[derive(Clone)]
724pub struct PyGLMNeuron {
725 inner: neurons::GLMNeuron,
726}
727
728#[pymethods]
729impl PyGLMNeuron {
730 #[new]
731 #[pyo3(signature = (n_k=10, n_h=20, seed=42))]
732 fn new(n_k: usize, n_h: usize, seed: u64) -> Self {
733 Self {
734 inner: neurons::GLMNeuron::new(n_k, n_h, seed),
735 }
736 }
737 fn step(&mut self, stimulus: f64) -> i32 {
738 self.inner.step(stimulus)
739 }
740 fn reset(&mut self) {
741 self.inner.reset();
742 }
743}
744
745#[pyclass(
747 name = "WilsonCowanUnit",
748 module = "sc_neurocore_engine.sc_neurocore_engine"
749)]
750#[derive(Clone)]
751pub struct PyWilsonCowanUnit {
752 inner: neurons::WilsonCowanUnit,
753}
754
755#[pymethods]
756impl PyWilsonCowanUnit {
757 #[new]
758 fn new() -> Self {
759 Self {
760 inner: neurons::WilsonCowanUnit::new(),
761 }
762 }
763 #[pyo3(signature = (ext_input=0.0))]
764 fn step(&mut self, ext_input: f64) -> f64 {
765 self.inner.step(ext_input)
766 }
767 fn reset(&mut self) {
768 self.inner.reset();
769 }
770 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
771 let d = PyDict::new(py);
772 d.set_item("e", self.inner.e)?;
773 d.set_item("i", self.inner.i)?;
774 Ok(d.into_any().unbind())
775 }
776}
777
778#[pyclass(
780 name = "JansenRitUnit",
781 module = "sc_neurocore_engine.sc_neurocore_engine"
782)]
783#[derive(Clone)]
784pub struct PyJansenRitUnit {
785 inner: neurons::JansenRitUnit,
786}
787
788#[pymethods]
789impl PyJansenRitUnit {
790 #[new]
791 fn new() -> Self {
792 Self {
793 inner: neurons::JansenRitUnit::new(),
794 }
795 }
796 #[pyo3(signature = (p_ext=220.0))]
797 fn step(&mut self, p_ext: f64) -> f64 {
798 self.inner.step(p_ext)
799 }
800 fn reset(&mut self) {
801 self.inner.reset();
802 }
803 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
804 let d = PyDict::new(py);
805 d.set_item("y", self.inner.y.to_vec())?;
806 Ok(d.into_any().unbind())
807 }
808}
809
810#[pyclass(
812 name = "WongWangUnit",
813 module = "sc_neurocore_engine.sc_neurocore_engine"
814)]
815#[derive(Clone)]
816pub struct PyWongWangUnit {
817 inner: neurons::WongWangUnit,
818}
819
820#[pymethods]
821impl PyWongWangUnit {
822 #[new]
823 #[pyo3(signature = (seed=42))]
824 fn new(seed: u64) -> Self {
825 Self {
826 inner: neurons::WongWangUnit::new(seed),
827 }
828 }
829 #[pyo3(signature = (stim1=0.0, stim2=0.0))]
830 fn step(&mut self, stim1: f64, stim2: f64) -> (f64, f64) {
831 self.inner.step(stim1, stim2)
832 }
833 fn reset(&mut self) {
834 self.inner.reset();
835 }
836 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
837 let d = PyDict::new(py);
838 d.set_item("s1", self.inner.s1)?;
839 d.set_item("s2", self.inner.s2)?;
840 Ok(d.into_any().unbind())
841 }
842}
843
844#[pyclass(
846 name = "ErmentroutKopellPopulation",
847 module = "sc_neurocore_engine.sc_neurocore_engine"
848)]
849#[derive(Clone)]
850pub struct PyErmentroutKopellPopulation {
851 inner: neurons::ErmentroutKopellPopulation,
852}
853
854#[pymethods]
855impl PyErmentroutKopellPopulation {
856 #[new]
857 fn new() -> Self {
858 Self {
859 inner: neurons::ErmentroutKopellPopulation::new(),
860 }
861 }
862 #[pyo3(signature = (ext_input=0.0))]
863 fn step(&mut self, ext_input: f64) -> f64 {
864 self.inner.step(ext_input)
865 }
866 fn reset(&mut self) {
867 self.inner.reset();
868 }
869 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
870 let d = PyDict::new(py);
871 d.set_item("r", self.inner.r)?;
872 d.set_item("v", self.inner.v)?;
873 Ok(d.into_any().unbind())
874 }
875}
876
877#[pyclass(
879 name = "WendlingNeuron",
880 module = "sc_neurocore_engine.sc_neurocore_engine"
881)]
882#[derive(Clone)]
883pub struct PyWendlingNeuron {
884 inner: neurons::WendlingNeuron,
885}
886
887#[pymethods]
888impl PyWendlingNeuron {
889 #[new]
890 fn new() -> Self {
891 Self {
892 inner: neurons::WendlingNeuron::new(),
893 }
894 }
895 #[pyo3(signature = (p_ext=220.0))]
896 fn step(&mut self, p_ext: f64) -> f64 {
897 self.inner.step(p_ext)
898 }
899 fn reset(&mut self) {
900 self.inner.reset();
901 }
902}
903
904#[pyclass(
906 name = "LarterBreakspearNeuron",
907 module = "sc_neurocore_engine.sc_neurocore_engine"
908)]
909#[derive(Clone)]
910pub struct PyLarterBreakspearNeuron {
911 inner: neurons::LarterBreakspearNeuron,
912}
913
914#[pymethods]
915impl PyLarterBreakspearNeuron {
916 #[new]
917 fn new() -> Self {
918 Self {
919 inner: neurons::LarterBreakspearNeuron::new(),
920 }
921 }
922 #[pyo3(signature = (coupling=0.0))]
923 fn step(&mut self, coupling: f64) -> f64 {
924 self.inner.step(coupling)
925 }
926 fn reset(&mut self) {
927 self.inner.reset();
928 }
929 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
930 let d = PyDict::new(py);
931 d.set_item("v", self.inner.v)?;
932 d.set_item("w", self.inner.w)?;
933 d.set_item("z", self.inner.z)?;
934 Ok(d.into_any().unbind())
935 }
936}
937
938#[pyclass(
943 name = "LoihiCUBANeuron",
944 module = "sc_neurocore_engine.sc_neurocore_engine"
945)]
946#[derive(Clone)]
947pub struct PyLoihiCUBANeuron {
948 inner: neurons::LoihiCUBANeuron,
949}
950
951#[pymethods]
952impl PyLoihiCUBANeuron {
953 #[new]
954 fn new() -> Self {
955 Self {
956 inner: neurons::LoihiCUBANeuron::new(),
957 }
958 }
959 fn step(&mut self, weighted_input: i32) -> i32 {
960 self.inner.step(weighted_input)
961 }
962 fn reset(&mut self) {
963 self.inner.reset();
964 }
965 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
966 let d = PyDict::new(py);
967 d.set_item("v", self.inner.v)?;
968 d.set_item("u", self.inner.u)?;
969 Ok(d.into_any().unbind())
970 }
971}
972
973#[pyclass(
974 name = "Loihi2Neuron",
975 module = "sc_neurocore_engine.sc_neurocore_engine"
976)]
977#[derive(Clone)]
978pub struct PyLoihi2Neuron {
979 inner: neurons::Loihi2Neuron,
980}
981
982#[pymethods]
983impl PyLoihi2Neuron {
984 #[new]
985 fn new() -> Self {
986 Self {
987 inner: neurons::Loihi2Neuron::new(),
988 }
989 }
990 fn step(&mut self, weighted_input: i32) -> i32 {
991 self.inner.step(weighted_input)
992 }
993 fn reset(&mut self) {
994 self.inner.reset();
995 }
996 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
997 let d = PyDict::new(py);
998 d.set_item("s1", self.inner.s1)?;
999 d.set_item("s2", self.inner.s2)?;
1000 d.set_item("s3", self.inner.s3)?;
1001 Ok(d.into_any().unbind())
1002 }
1003}
1004
1005#[pyclass(
1006 name = "TrueNorthNeuron",
1007 module = "sc_neurocore_engine.sc_neurocore_engine"
1008)]
1009#[derive(Clone)]
1010pub struct PyTrueNorthNeuron {
1011 inner: neurons::TrueNorthNeuron,
1012}
1013
1014#[pymethods]
1015impl PyTrueNorthNeuron {
1016 #[new]
1017 #[pyo3(signature = (threshold=100))]
1018 fn new(threshold: i32) -> Self {
1019 Self {
1020 inner: neurons::TrueNorthNeuron::new(threshold),
1021 }
1022 }
1023 fn step(&mut self, weighted_input: i32) -> i32 {
1024 self.inner.step(weighted_input)
1025 }
1026 fn reset(&mut self) {
1027 self.inner.reset();
1028 }
1029 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1030 let d = PyDict::new(py);
1031 d.set_item("v", self.inner.v)?;
1032 Ok(d.into_any().unbind())
1033 }
1034}
1035
1036py_neuron_default!("BrainScaleSAdExNeuron", PyBrainScaleSAdExNeuron, neurons::BrainScaleSAdExNeuron, state v, state w);
1037py_neuron_default!("SpiNNakerLIFNeuron", PySpiNNakerLIFNeuron, neurons::SpiNNakerLIFNeuron, state v, state refrac_count);
1038
1039#[pyclass(
1040 name = "SpiNNaker2Neuron",
1041 module = "sc_neurocore_engine.sc_neurocore_engine"
1042)]
1043#[derive(Clone)]
1044pub struct PySpiNNaker2Neuron {
1045 inner: neurons::SpiNNaker2Neuron,
1046}
1047
1048#[pymethods]
1049impl PySpiNNaker2Neuron {
1050 #[new]
1051 fn new() -> Self {
1052 Self {
1053 inner: neurons::SpiNNaker2Neuron::new(),
1054 }
1055 }
1056 fn step(&mut self, current: i32) -> i32 {
1057 self.inner.step(current)
1058 }
1059 fn reset(&mut self) {
1060 self.inner.reset();
1061 }
1062 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1063 let d = PyDict::new(py);
1064 d.set_item("v", self.inner.v)?;
1065 Ok(d.into_any().unbind())
1066 }
1067}
1068
1069py_neuron_default!("DPINeuron", PyDPINeuron, neurons::DPINeuron, state i_mem);
1070
1071#[pyclass(
1072 name = "AkidaNeuron",
1073 module = "sc_neurocore_engine.sc_neurocore_engine"
1074)]
1075#[derive(Clone)]
1076pub struct PyAkidaNeuron {
1077 inner: neurons::AkidaNeuron,
1078}
1079
1080#[pymethods]
1081impl PyAkidaNeuron {
1082 #[new]
1083 #[pyo3(signature = (threshold=100))]
1084 fn new(threshold: i32) -> Self {
1085 Self {
1086 inner: neurons::AkidaNeuron::new(threshold),
1087 }
1088 }
1089 fn step(&mut self, weight: i32) -> i32 {
1090 self.inner.step(weight)
1091 }
1092 fn reset(&mut self) {
1093 self.inner.reset();
1094 }
1095 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1096 let d = PyDict::new(py);
1097 d.set_item("v", self.inner.v)?;
1098 d.set_item("rank", self.inner.rank)?;
1099 Ok(d.into_any().unbind())
1100 }
1101}
1102
1103py_neuron_default!("NeuroGridNeuron", PyNeuroGridNeuron, neurons::NeuroGridNeuron, state v_s, state v_d);
1104
1105#[pyclass(
1110 name = "McCullochPittsNeuron",
1111 module = "sc_neurocore_engine.sc_neurocore_engine"
1112)]
1113#[derive(Clone)]
1114pub struct PyMcCullochPittsNeuron {
1115 inner: neurons::McCullochPittsNeuron,
1116}
1117
1118#[pymethods]
1119impl PyMcCullochPittsNeuron {
1120 #[new]
1121 #[pyo3(signature = (theta=1.0))]
1122 fn new(theta: f64) -> Self {
1123 Self {
1124 inner: neurons::McCullochPittsNeuron::new(theta),
1125 }
1126 }
1127 fn step(&self, weighted_input: f64) -> i32 {
1128 self.inner.step(weighted_input)
1129 }
1130}
1131
1132#[pyclass(
1134 name = "SigmoidRateNeuron",
1135 module = "sc_neurocore_engine.sc_neurocore_engine"
1136)]
1137#[derive(Clone)]
1138pub struct PySigmoidRateNeuron {
1139 inner: neurons::SigmoidRateNeuron,
1140}
1141
1142#[pymethods]
1143impl PySigmoidRateNeuron {
1144 #[new]
1145 fn new() -> Self {
1146 Self {
1147 inner: neurons::SigmoidRateNeuron::new(),
1148 }
1149 }
1150 fn step(&mut self, current: f64) -> f64 {
1151 self.inner.step(current)
1152 }
1153 fn reset(&mut self) {
1154 self.inner.reset();
1155 }
1156 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1157 let d = PyDict::new(py);
1158 d.set_item("r", self.inner.r)?;
1159 Ok(d.into_any().unbind())
1160 }
1161}
1162
1163#[pyclass(
1165 name = "ThresholdLinearRateNeuron",
1166 module = "sc_neurocore_engine.sc_neurocore_engine"
1167)]
1168#[derive(Clone)]
1169pub struct PyThresholdLinearRateNeuron {
1170 inner: neurons::ThresholdLinearRateNeuron,
1171}
1172
1173#[pymethods]
1174impl PyThresholdLinearRateNeuron {
1175 #[new]
1176 fn new() -> Self {
1177 Self {
1178 inner: neurons::ThresholdLinearRateNeuron::new(),
1179 }
1180 }
1181 fn step(&mut self, current: f64) -> f64 {
1182 self.inner.step(current)
1183 }
1184 fn reset(&mut self) {
1185 self.inner.reset();
1186 }
1187}
1188
1189#[pyclass(
1191 name = "AstrocyteModel",
1192 module = "sc_neurocore_engine.sc_neurocore_engine"
1193)]
1194#[derive(Clone)]
1195pub struct PyAstrocyteModel {
1196 inner: neurons::AstrocyteModel,
1197}
1198
1199#[pymethods]
1200impl PyAstrocyteModel {
1201 #[new]
1202 fn new() -> Self {
1203 Self {
1204 inner: neurons::AstrocyteModel::new(),
1205 }
1206 }
1207 fn step(&mut self, current: f64) -> f64 {
1208 self.inner.step(current)
1209 }
1210 fn reset(&mut self) {
1211 self.inner.reset();
1212 }
1213 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1214 let d = PyDict::new(py);
1215 d.set_item("ca", self.inner.ca)?;
1216 d.set_item("h", self.inner.h)?;
1217 d.set_item("ip3", self.inner.ip3)?;
1218 Ok(d.into_any().unbind())
1219 }
1220}
1221
1222#[pyclass(
1224 name = "TsodyksMarkramNeuron",
1225 module = "sc_neurocore_engine.sc_neurocore_engine"
1226)]
1227#[derive(Clone)]
1228pub struct PyTsodyksMarkramNeuron {
1229 inner: neurons::TsodyksMarkramNeuron,
1230}
1231
1232#[pymethods]
1233impl PyTsodyksMarkramNeuron {
1234 #[new]
1235 fn new() -> Self {
1236 Self {
1237 inner: neurons::TsodyksMarkramNeuron::new(),
1238 }
1239 }
1240 #[pyo3(signature = (current, presynaptic_spike=false))]
1241 fn step(&mut self, current: f64, presynaptic_spike: bool) -> i32 {
1242 self.inner.step(current, presynaptic_spike)
1243 }
1244 fn reset(&mut self) {
1245 self.inner.reset();
1246 }
1247 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1248 let d = PyDict::new(py);
1249 d.set_item("v", self.inner.v)?;
1250 d.set_item("x", self.inner.x)?;
1251 d.set_item("u", self.inner.u)?;
1252 Ok(d.into_any().unbind())
1253 }
1254}
1255
1256py_neuron_default!("LiquidTimeConstantNeuron", PyLiquidTimeConstantNeuron, neurons::LiquidTimeConstantNeuron, state x);
1257
1258#[pyclass(
1260 name = "CompteWMNeuron",
1261 module = "sc_neurocore_engine.sc_neurocore_engine"
1262)]
1263#[derive(Clone)]
1264pub struct PyCompteWMNeuron {
1265 inner: neurons::CompteWMNeuron,
1266}
1267
1268#[pymethods]
1269impl PyCompteWMNeuron {
1270 #[new]
1271 fn new() -> Self {
1272 Self {
1273 inner: neurons::CompteWMNeuron::new(),
1274 }
1275 }
1276 #[pyo3(signature = (current, spike_in=false))]
1277 fn step(&mut self, current: f64, spike_in: bool) -> i32 {
1278 self.inner.step(current, spike_in)
1279 }
1280 fn reset(&mut self) {
1281 self.inner.reset();
1282 }
1283 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1284 let d = PyDict::new(py);
1285 d.set_item("v", self.inner.v)?;
1286 d.set_item("s_nmda", self.inner.s_nmda)?;
1287 Ok(d.into_any().unbind())
1288 }
1289}
1290
1291#[pyclass(
1293 name = "SiegertTransferFunction",
1294 module = "sc_neurocore_engine.sc_neurocore_engine"
1295)]
1296#[derive(Clone)]
1297pub struct PySiegertTransferFunction {
1298 inner: neurons::SiegertTransferFunction,
1299}
1300
1301#[pymethods]
1302impl PySiegertTransferFunction {
1303 #[new]
1304 fn new() -> Self {
1305 Self {
1306 inner: neurons::SiegertTransferFunction::new(),
1307 }
1308 }
1309 fn step(&self, current: f64) -> f64 {
1310 self.inner.step(current)
1311 }
1312}
1313
1314#[pyclass(
1319 name = "FractionalLIFNeuron",
1320 module = "sc_neurocore_engine.sc_neurocore_engine"
1321)]
1322#[derive(Clone)]
1323pub struct PyFractionalLIFNeuron {
1324 inner: neurons::FractionalLIFNeuron,
1325}
1326
1327#[pymethods]
1328impl PyFractionalLIFNeuron {
1329 #[new]
1330 #[pyo3(signature = (alpha=0.8, max_hist=50))]
1331 fn new(alpha: f64, max_hist: usize) -> Self {
1332 Self {
1333 inner: neurons::FractionalLIFNeuron::new(alpha, max_hist),
1334 }
1335 }
1336 fn step(&mut self, current: f64) -> i32 {
1337 self.inner.step(current)
1338 }
1339 fn reset(&mut self) {
1340 self.inner.reset();
1341 }
1342 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1343 let d = PyDict::new(py);
1344 d.set_item("v", self.inner.v)?;
1345 Ok(d.into_any().unbind())
1346 }
1347}
1348
1349#[pyclass(
1350 name = "ParallelSpikingNeuron",
1351 module = "sc_neurocore_engine.sc_neurocore_engine"
1352)]
1353#[derive(Clone)]
1354pub struct PyParallelSpikingNeuron {
1355 inner: neurons::ParallelSpikingNeuron,
1356}
1357
1358#[pymethods]
1359impl PyParallelSpikingNeuron {
1360 #[new]
1361 #[pyo3(signature = (kernel_size=8, v_threshold=1.0))]
1362 fn new(kernel_size: usize, v_threshold: f64) -> Self {
1363 Self {
1364 inner: neurons::ParallelSpikingNeuron::new(kernel_size, v_threshold),
1365 }
1366 }
1367 fn step(&mut self, current: f64) -> i32 {
1368 self.inner.step(current)
1369 }
1370 fn reset(&mut self) {
1371 self.inner.reset();
1372 }
1373}
1374
1375#[pyclass(
1376 name = "AmariNeuralField",
1377 module = "sc_neurocore_engine.sc_neurocore_engine"
1378)]
1379#[derive(Clone)]
1380pub struct PyAmariNeuralField {
1381 inner: neurons::AmariNeuralField,
1382}
1383
1384#[pymethods]
1385impl PyAmariNeuralField {
1386 #[new]
1387 #[pyo3(signature = (n=64))]
1388 fn new(n: usize) -> Self {
1389 Self {
1390 inner: neurons::AmariNeuralField::new(n),
1391 }
1392 }
1393 fn step(&mut self, input: Vec<f64>) -> f64 {
1394 self.inner.step(&input)
1395 }
1396 fn reset(&mut self) {
1397 self.inner.reset();
1398 }
1399 fn get_state<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
1400 self.inner.u.clone().into_pyarray(py)
1401 }
1402}
1403
1404pub fn register_neuron_classes(m: &Bound<'_, PyModule>) -> PyResult<()> {
1409 m.add_class::<PyMultiTimescaleNeuron>()?;
1411 m.add_class::<PyAttentionGatedNeuron>()?;
1412 m.add_class::<PyPredictiveCodingNeuron>()?;
1413 m.add_class::<PySelfReferentialNeuron>()?;
1414 m.add_class::<PyCompositionalBindingNeuron>()?;
1415 m.add_class::<PyDifferentiableSurrogateNeuron>()?;
1416 m.add_class::<PyContinuousAttractorNeuron>()?;
1417 m.add_class::<PyMetaPlasticNeuron>()?;
1418 m.add_class::<PyQuadraticIFNeuron>()?;
1420 m.add_class::<PyThetaNeuron>()?;
1421 m.add_class::<PyPerfectIntegratorNeuron>()?;
1422 m.add_class::<PyGatedLIFNeuron>()?;
1423 m.add_class::<PyNonlinearLIFNeuron>()?;
1424 m.add_class::<PySFANeuron>()?;
1425 m.add_class::<PyMATNeuron>()?;
1426 m.add_class::<PyEscapeRateNeuron>()?;
1427 m.add_class::<PyKLIFNeuron>()?;
1428 m.add_class::<PyInhibitoryLIFNeuron>()?;
1429 m.add_class::<PyComplementaryLIFNeuron>()?;
1430 m.add_class::<PyParametricLIFNeuron>()?;
1431 m.add_class::<PyNonResettingLIFNeuron>()?;
1432 m.add_class::<PyAdaptiveThresholdIFNeuron>()?;
1433 m.add_class::<PySigmaDeltaNeuron>()?;
1434 m.add_class::<PyEnergyLIFNeuron>()?;
1435 m.add_class::<PyIntegerQIFNeuron>()?;
1436 m.add_class::<PyClosedFormContinuousNeuron>()?;
1437 m.add_class::<PyFitzHughNagumoNeuron>()?;
1439 m.add_class::<PyMorrisLecarNeuron>()?;
1440 m.add_class::<PyHindmarshRoseNeuron>()?;
1441 m.add_class::<PyResonateAndFireNeuron>()?;
1442 m.add_class::<PyFitzHughRinzelNeuron>()?;
1443 m.add_class::<PyMcKeanNeuron>()?;
1444 m.add_class::<PyTermanWangOscillator>()?;
1445 m.add_class::<PyBendaHerzNeuron>()?;
1446 m.add_class::<PyAlphaNeuron>()?;
1447 m.add_class::<PyCOBALIFNeuron>()?;
1448 m.add_class::<PyGutkinErmentroutNeuron>()?;
1449 m.add_class::<PyWilsonHRNeuron>()?;
1450 m.add_class::<PyChayNeuron>()?;
1451 m.add_class::<PyChayKeizerNeuron>()?;
1452 m.add_class::<PyShermanRinzelKeizerNeuron>()?;
1453 m.add_class::<PyButeraRespiratoryNeuron>()?;
1454 m.add_class::<PyEPropALIFNeuron>()?;
1455 m.add_class::<PySuperSpikeNeuron>()?;
1456 m.add_class::<PyLearnableNeuronModel>()?;
1457 m.add_class::<PyPernarowskiNeuron>()?;
1458 m.add_class::<PyChialvoMapNeuron>()?;
1460 m.add_class::<PyRulkovMapNeuron>()?;
1461 m.add_class::<PyIbarzTanakaMapNeuron>()?;
1462 m.add_class::<PyMedvedevMapNeuron>()?;
1463 m.add_class::<PyCazellesMapNeuron>()?;
1464 m.add_class::<PyCourageNekorkinMapNeuron>()?;
1465 m.add_class::<PyHodgkinHuxleyNeuron>()?;
1467 m.add_class::<PyTraubMilesNeuron>()?;
1468 m.add_class::<PyWangBuzsakiNeuron>()?;
1469 m.add_class::<PyConnorStevensNeuron>()?;
1470 m.add_class::<PyDestexheThalamicNeuron>()?;
1471 m.add_class::<PyHuberBraunNeuron>()?;
1472 m.add_class::<PyGolombFSNeuron>()?;
1473 m.add_class::<PyPospischilNeuron>()?;
1474 m.add_class::<PyMainenSejnowskiNeuron>()?;
1475 m.add_class::<PyDeSchutterPurkinjeNeuron>()?;
1476 m.add_class::<PyPlantR15Neuron>()?;
1477 m.add_class::<PyPrescottNeuron>()?;
1478 m.add_class::<PyMihalasNieburNeuron>()?;
1479 m.add_class::<PyGLIFNeuron>()?;
1480 m.add_class::<PyGIFPopulationNeuron>()?;
1481 m.add_class::<PyAvRonCardiacNeuron>()?;
1482 m.add_class::<PyDurstewitzDopamineNeuron>()?;
1483 m.add_class::<PyHillTononiNeuron>()?;
1484 m.add_class::<PyBertramPhantomBurster>()?;
1485 m.add_class::<PyYamadaNeuron>()?;
1486 m.add_class::<PyPinskyRinzelNeuron>()?;
1488 m.add_class::<PyHayL5PyramidalNeuron>()?;
1489 m.add_class::<PyMarderSTGNeuron>()?;
1490 m.add_class::<PyRallCableNeuron>()?;
1491 m.add_class::<PyBoothRinzelNeuron>()?;
1492 m.add_class::<PyDendrifyNeuron>()?;
1493 m.add_class::<PyTwoCompartmentLIFNeuron>()?;
1494 m.add_class::<PyPoissonNeuron>()?;
1496 m.add_class::<PyInhomogeneousPoissonNeuron>()?;
1497 m.add_class::<PyGammaRenewalNeuron>()?;
1498 m.add_class::<PyStochasticIFNeuron>()?;
1499 m.add_class::<PyGalvesLocherbachNeuron>()?;
1500 m.add_class::<PySpikeResponseNeuron>()?;
1501 m.add_class::<PyGLMNeuron>()?;
1502 m.add_class::<PyWilsonCowanUnit>()?;
1503 m.add_class::<PyJansenRitUnit>()?;
1504 m.add_class::<PyWongWangUnit>()?;
1505 m.add_class::<PyErmentroutKopellPopulation>()?;
1506 m.add_class::<PyWendlingNeuron>()?;
1507 m.add_class::<PyLarterBreakspearNeuron>()?;
1508 m.add_class::<PyLoihiCUBANeuron>()?;
1510 m.add_class::<PyLoihi2Neuron>()?;
1511 m.add_class::<PyTrueNorthNeuron>()?;
1512 m.add_class::<PyBrainScaleSAdExNeuron>()?;
1513 m.add_class::<PySpiNNakerLIFNeuron>()?;
1514 m.add_class::<PySpiNNaker2Neuron>()?;
1515 m.add_class::<PyDPINeuron>()?;
1516 m.add_class::<PyAkidaNeuron>()?;
1517 m.add_class::<PyNeuroGridNeuron>()?;
1518 m.add_class::<PyMcCullochPittsNeuron>()?;
1520 m.add_class::<PySigmoidRateNeuron>()?;
1521 m.add_class::<PyThresholdLinearRateNeuron>()?;
1522 m.add_class::<PyAstrocyteModel>()?;
1523 m.add_class::<PyTsodyksMarkramNeuron>()?;
1524 m.add_class::<PyLiquidTimeConstantNeuron>()?;
1525 m.add_class::<PyCompteWMNeuron>()?;
1526 m.add_class::<PySiegertTransferFunction>()?;
1527 m.add_class::<PyFractionalLIFNeuron>()?;
1528 m.add_class::<PyParallelSpikingNeuron>()?;
1529 m.add_class::<PyAmariNeuralField>()?;
1530 m.add_class::<PyLeakyCompeteFireNeuron>()?;
1531 m.add_class::<PyArcaneNeuron>()?;
1532 Ok(())
1533}
1534
1535#[pyclass(
1537 name = "LeakyCompeteFireNeuron",
1538 module = "sc_neurocore_engine.sc_neurocore_engine"
1539)]
1540#[derive(Clone)]
1541pub struct PyLeakyCompeteFireNeuron {
1542 inner: neurons::LeakyCompeteFireNeuron,
1543}
1544
1545#[pymethods]
1546impl PyLeakyCompeteFireNeuron {
1547 #[new]
1548 #[pyo3(signature = (n_units=4))]
1549 fn new(n_units: usize) -> Self {
1550 Self {
1551 inner: neurons::LeakyCompeteFireNeuron::new(n_units),
1552 }
1553 }
1554 fn step(&mut self, currents: Vec<f64>) -> Vec<i32> {
1555 self.inner.step(¤ts)
1556 }
1557 fn reset(&mut self) {
1558 self.inner.reset();
1559 }
1560 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1561 let d = PyDict::new(py);
1562 d.set_item("v", self.inner.v.clone())?;
1563 Ok(d.into_any().unbind())
1564 }
1565}