1use numpy::{IntoPyArray, PyArray1};
16use pyo3::prelude::*;
17use pyo3::types::PyDict;
18
19use crate::neuron;
20use crate::neurons;
21
22macro_rules! py_neuron_default {
23 ($pylit:literal, $pyname:ident, $rust:ty $(, state $sname:ident)*) => {
24 #[pyclass(name = $pylit, module = "sc_neurocore_engine.sc_neurocore_engine")]
25 #[derive(Clone)]
26 pub struct $pyname { inner: $rust }
27
28 #[pymethods]
29 impl $pyname {
30 #[new]
31 fn new() -> Self { Self { inner: <$rust>::default() } }
32
33 fn step(&mut self, current: f64) -> i32 { self.inner.step(current) }
34
35 fn reset(&mut self) { self.inner.reset(); }
36
37 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
38 let d = PyDict::new(py);
39 $(d.set_item(stringify!($sname), self.inner.$sname)?;)*
40 Ok(d.into_any().unbind())
41 }
42 }
43 };
44}
45
46py_neuron_default!("MultiTimescaleNeuron", PyMultiTimescaleNeuron, neurons::MultiTimescaleNeuron, state v_fast, state v_medium, state v_slow);
51py_neuron_default!("AttentionGatedNeuron", PyAttentionGatedNeuron, neurons::AttentionGatedNeuron, state v);
52py_neuron_default!("PredictiveCodingNeuron", PyPredictiveCodingNeuron, neurons::PredictiveCodingNeuron, state v, state pred);
53py_neuron_default!("SelfReferentialNeuron", PySelfReferentialNeuron, neurons::SelfReferentialNeuron, state v);
54py_neuron_default!("CompositionalBindingNeuron", PyCompositionalBindingNeuron, neurons::CompositionalBindingNeuron, state phi, state amplitude);
55py_neuron_default!("DifferentiableSurrogateNeuron", PyDifferentiableSurrogateNeuron, neurons::DifferentiableSurrogateNeuron, state v);
56py_neuron_default!("MetaPlasticNeuron", PyMetaPlasticNeuron, neurons::MetaPlasticNeuron, state v, state error_trace, state expected_reward);
57
58py_neuron_default!("ArcaneNeuron", PyArcaneNeuron, neurons::ArcaneNeuron, state v_fast, state v_work, state v_deep);
59
60py_neuron_default!("RustAdaptiveThresholdMoENeuron", PyAdaptiveThresholdMoENeuron, neurons::AdaptiveThresholdMoENeuron, state v, state v_th);
62
63py_neuron_default!("RustCochlearHairCell", PyCochlearHairCell, neurons::CochlearHairCell, state v, state glutamate_release);
65
66#[pyclass(
68 name = "RustHybridLinearAttentionNeuron",
69 module = "sc_neurocore_engine.sc_neurocore_engine"
70)]
71#[derive(Clone)]
72pub struct PyHybridLinearAttentionNeuron {
73 inner: neurons::HybridLinearAttentionNeuron,
74}
75
76#[pymethods]
77impl PyHybridLinearAttentionNeuron {
78 #[new]
79 #[pyo3(signature = (dim=16))]
80 fn new(dim: usize) -> Self {
81 Self {
82 inner: neurons::HybridLinearAttentionNeuron::new(dim),
83 }
84 }
85 fn step(&mut self, current: f64) -> i32 {
86 self.inner.step(current)
87 }
88 fn step_qkv(&mut self, query: f64, key: f64, value: f64) -> f64 {
89 self.inner.step_qkv(query, key, value)
90 }
91 fn reset(&mut self) {
92 self.inner.reset();
93 }
94 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
95 let d = PyDict::new(py);
96 d.set_item("v", self.inner.v)?;
97 Ok(d.into_any().unbind())
98 }
99}
100
101#[pyclass(
103 name = "RustQuantumInspiredLIFNeuron",
104 module = "sc_neurocore_engine.sc_neurocore_engine"
105)]
106#[derive(Clone)]
107pub struct PyQuantumInspiredLIFNeuron {
108 inner: neurons::QuantumInspiredLIFNeuron,
109}
110
111#[pymethods]
112impl PyQuantumInspiredLIFNeuron {
113 #[new]
114 fn new() -> Self {
115 Self {
116 inner: neurons::QuantumInspiredLIFNeuron::new(),
117 }
118 }
119 fn step(&mut self, current: f64) -> i32 {
120 self.inner.step(current)
121 }
122 fn step_complex(&mut self, i_re: f64, i_im: f64) -> i32 {
123 self.inner.step_complex(i_re, i_im)
124 }
125 fn reset(&mut self) {
126 self.inner.reset();
127 }
128 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
129 let d = PyDict::new(py);
130 d.set_item("z_re", self.inner.z_re)?;
131 d.set_item("z_im", self.inner.z_im)?;
132 Ok(d.into_any().unbind())
133 }
134}
135
136#[pyclass(
138 name = "RustDendriticNMDANeuron",
139 module = "sc_neurocore_engine.sc_neurocore_engine"
140)]
141#[derive(Clone)]
142pub struct PyDendriticNMDANeuron {
143 inner: neurons::DendriticNMDANeuron,
144}
145
146#[pymethods]
147impl PyDendriticNMDANeuron {
148 #[new]
149 fn new() -> Self {
150 Self {
151 inner: neurons::DendriticNMDANeuron::new(),
152 }
153 }
154 fn step(&mut self, i_soma: f64, glutamate: f64) -> i32 {
155 self.inner.step(i_soma, glutamate)
156 }
157 fn reset(&mut self) {
158 self.inner.reset();
159 }
160 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
161 let d = PyDict::new(py);
162 d.set_item("v_soma", self.inner.v_soma)?;
163 d.set_item("v_dend", self.inner.v_dend)?;
164 Ok(d.into_any().unbind())
165 }
166}
167
168#[pyclass(
170 name = "RustMulticompartmentMCNNeuron",
171 module = "sc_neurocore_engine.sc_neurocore_engine"
172)]
173#[derive(Clone)]
174pub struct PyMulticompartmentMCNNeuron {
175 inner: neurons::MulticompartmentMCNNeuron,
176}
177
178#[pymethods]
179impl PyMulticompartmentMCNNeuron {
180 #[new]
181 fn new() -> Self {
182 Self {
183 inner: neurons::MulticompartmentMCNNeuron::new(),
184 }
185 }
186 fn step(&mut self, current: f64) -> i32 {
187 self.inner.step(current)
188 }
189 fn step_compartments(&mut self, x_basal: f64, x_apical: f64, i_soma: f64) -> i32 {
190 self.inner.step_compartments(x_basal, x_apical, i_soma)
191 }
192 fn reset(&mut self) {
193 self.inner.reset();
194 }
195 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
196 let d = PyDict::new(py);
197 d.set_item("u", self.inner.u)?;
198 d.set_item("v_basal", self.inner.v_basal)?;
199 d.set_item("v_apical", self.inner.v_apical)?;
200 Ok(d.into_any().unbind())
201 }
202}
203
204#[pyclass(
206 name = "RustAstrocyteLIFNeuron",
207 module = "sc_neurocore_engine.sc_neurocore_engine"
208)]
209#[derive(Clone)]
210pub struct PyAstrocyteLIFNeuron {
211 inner: neurons::AstrocyteLIFNeuron,
212}
213
214#[pymethods]
215impl PyAstrocyteLIFNeuron {
216 #[new]
217 fn new() -> Self {
218 Self {
219 inner: neurons::AstrocyteLIFNeuron::new(),
220 }
221 }
222 fn step(&mut self, current: f64) -> i32 {
223 self.inner.step(current)
224 }
225 fn step_with_pre(&mut self, i_ext: f64, pre_spike: bool) -> i32 {
226 self.inner.step_with_pre(i_ext, pre_spike)
227 }
228 fn reset(&mut self) {
229 self.inner.reset();
230 }
231 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
232 let d = PyDict::new(py);
233 d.set_item("v", self.inner.v)?;
234 d.set_item("ca", self.inner.ca)?;
235 Ok(d.into_any().unbind())
236 }
237}
238
239#[pyclass(
241 name = "RustDirectionSelectiveRGC",
242 module = "sc_neurocore_engine.sc_neurocore_engine"
243)]
244#[derive(Clone)]
245pub struct PyDirectionSelectiveRGC {
246 inner: neurons::DirectionSelectiveRGC,
247}
248
249#[pymethods]
250impl PyDirectionSelectiveRGC {
251 #[new]
252 #[pyo3(signature = (is_on=true))]
253 fn new(is_on: bool) -> Self {
254 Self {
255 inner: if is_on {
256 neurons::DirectionSelectiveRGC::new_on()
257 } else {
258 neurons::DirectionSelectiveRGC::new_off()
259 },
260 }
261 }
262 fn step(&mut self, current: f64) -> i32 {
263 self.inner.step(current)
264 }
265 fn step_rf(&mut self, intensity: f64, surround_mean: f64) -> i32 {
266 self.inner.step_rf(intensity, surround_mean)
267 }
268 fn reset(&mut self) {
269 self.inner.reset();
270 }
271 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
272 let d = PyDict::new(py);
273 d.set_item("v", self.inner.v)?;
274 d.set_item("is_on_centre", self.inner.is_on_centre)?;
275 Ok(d.into_any().unbind())
276 }
277}
278
279#[pyclass(
281 name = "RustTripletStdpSynapse",
282 module = "sc_neurocore_engine.sc_neurocore_engine"
283)]
284#[derive(Clone)]
285pub struct PyTripletStdpSynapse {
286 inner: crate::synapses::TripletStdpSynapse,
287}
288
289#[pymethods]
290impl PyTripletStdpSynapse {
291 #[new]
292 #[pyo3(signature = (weight=0.5, w_min=0.0, w_max=1.0))]
293 fn new(weight: f64, w_min: f64, w_max: f64) -> Self {
294 Self {
295 inner: crate::synapses::TripletStdpSynapse::new(weight, w_min, w_max),
296 }
297 }
298 fn step(&mut self, pre_spike: bool, post_spike: bool) {
299 self.inner.step(pre_spike, post_spike);
300 }
301 #[getter]
302 fn weight(&self) -> f64 {
303 self.inner.weight
304 }
305 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
306 let d = PyDict::new(py);
307 d.set_item("weight", self.inner.weight)?;
308 d.set_item("r1", self.inner.r1)?;
309 d.set_item("o1", self.inner.o1)?;
310 d.set_item("r2", self.inner.r2)?;
311 d.set_item("o2", self.inner.o2)?;
312 Ok(d.into_any().unbind())
313 }
314}
315
316#[pyclass(
318 name = "RustShortTermPlasticitySynapse",
319 module = "sc_neurocore_engine.sc_neurocore_engine"
320)]
321#[derive(Clone)]
322pub struct PyShortTermPlasticitySynapse {
323 inner: crate::synapses::ShortTermPlasticitySynapse,
324}
325
326#[pymethods]
327impl PyShortTermPlasticitySynapse {
328 #[new]
329 fn new() -> Self {
330 Self {
331 inner: crate::synapses::ShortTermPlasticitySynapse::new_depressing(),
332 }
333 }
334 #[staticmethod]
335 fn depressing() -> Self {
336 Self {
337 inner: crate::synapses::ShortTermPlasticitySynapse::new_depressing(),
338 }
339 }
340 #[staticmethod]
341 fn facilitating() -> Self {
342 Self {
343 inner: crate::synapses::ShortTermPlasticitySynapse::new_facilitating(),
344 }
345 }
346 fn step(&mut self, pre_spike: bool) -> f64 {
347 self.inner.step(pre_spike)
348 }
349 fn reset(&mut self) {
350 self.inner.reset();
351 }
352 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
353 let d = PyDict::new(py);
354 d.set_item("x", self.inner.x)?;
355 d.set_item("u", self.inner.u)?;
356 Ok(d.into_any().unbind())
357 }
358}
359
360#[pyclass(
362 name = "RustDopamineStdpSynapse",
363 module = "sc_neurocore_engine.sc_neurocore_engine"
364)]
365#[derive(Clone)]
366pub struct PyDopamineStdpSynapse {
367 inner: crate::synapses::DopamineStdpSynapse,
368}
369
370#[pymethods]
371impl PyDopamineStdpSynapse {
372 #[new]
373 #[pyo3(signature = (weight=0.5, w_min=0.0, w_max=1.0))]
374 fn new(weight: f64, w_min: f64, w_max: f64) -> Self {
375 Self {
376 inner: crate::synapses::DopamineStdpSynapse::new(weight, w_min, w_max),
377 }
378 }
379 fn step(&mut self, pre_spike: bool, post_spike: bool, reward: f64) {
380 self.inner.step(pre_spike, post_spike, reward);
381 }
382 fn reset(&mut self) {
383 self.inner.reset();
384 }
385 #[getter]
386 fn weight(&self) -> f64 {
387 self.inner.weight
388 }
389 #[getter]
390 fn dopamine(&self) -> f64 {
391 self.inner.dopamine
392 }
393 #[getter]
394 fn eligibility(&self) -> f64 {
395 self.inner.eligibility
396 }
397 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
398 let d = PyDict::new(py);
399 d.set_item("weight", self.inner.weight)?;
400 d.set_item("eligibility", self.inner.eligibility)?;
401 d.set_item("dopamine", self.inner.dopamine)?;
402 d.set_item("trace_pre", self.inner.trace_pre)?;
403 d.set_item("trace_post", self.inner.trace_post)?;
404 Ok(d.into_any().unbind())
405 }
406}
407
408#[pyclass(
410 name = "RustContinuousAttractorNeuron",
411 module = "sc_neurocore_engine.sc_neurocore_engine"
412)]
413#[derive(Clone)]
414pub struct PyContinuousAttractorNeuron {
415 inner: neurons::ContinuousAttractorNeuron,
416}
417
418#[pymethods]
419impl PyContinuousAttractorNeuron {
420 #[new]
421 #[pyo3(signature = (n_units=16))]
422 fn new(n_units: usize) -> Self {
423 Self {
424 inner: neurons::ContinuousAttractorNeuron::new(n_units),
425 }
426 }
427 fn step(&mut self, current: f64) -> i32 {
428 self.inner.step(current)
429 }
430 fn bump_position(&self) -> usize {
431 self.inner.bump_position()
432 }
433 fn reset(&mut self) {
434 self.inner.reset();
435 }
436 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
437 let d = PyDict::new(py);
438 d.set_item("u", self.inner.u.clone().into_pyarray(py))?;
439 Ok(d.into_any().unbind())
440 }
441}
442
443py_neuron_default!("QuadraticIFNeuron", PyQuadraticIFNeuron, neurons::QuadraticIFNeuron, state v);
448py_neuron_default!("ThetaNeuron", PyThetaNeuron, neurons::ThetaNeuron, state theta);
449py_neuron_default!("PerfectIntegratorNeuron", PyPerfectIntegratorNeuron, neurons::PerfectIntegratorNeuron, state v);
450py_neuron_default!("GatedLIFNeuron", PyGatedLIFNeuron, neurons::GatedLIFNeuron, state v);
451py_neuron_default!("NonlinearLIFNeuron", PyNonlinearLIFNeuron, neurons::NonlinearLIFNeuron, state v, state w);
452py_neuron_default!("SFANeuron", PySFANeuron, neurons::SFANeuron, state v, state g_sfa);
453py_neuron_default!("MATNeuron", PyMATNeuron, neurons::MATNeuron, state v, state theta1, state theta2);
454py_neuron_default!("KLIFNeuron", PyKLIFNeuron, neurons::KLIFNeuron, state v);
455py_neuron_default!("InhibitoryLIFNeuron", PyInhibitoryLIFNeuron, neurons::InhibitoryLIFNeuron, state v, state inh_trace);
456py_neuron_default!("ComplementaryLIFNeuron", PyComplementaryLIFNeuron, neurons::ComplementaryLIFNeuron, state v_pos, state v_neg);
457py_neuron_default!("ParametricLIFNeuron", PyParametricLIFNeuron, neurons::ParametricLIFNeuron, state v);
458py_neuron_default!("NonResettingLIFNeuron", PyNonResettingLIFNeuron, neurons::NonResettingLIFNeuron, state v, state theta);
459py_neuron_default!("AdaptiveThresholdIFNeuron", PyAdaptiveThresholdIFNeuron, neurons::AdaptiveThresholdIFNeuron, state v, state theta);
460py_neuron_default!("SigmaDeltaNeuron", PySigmaDeltaNeuron, neurons::SigmaDeltaNeuron, state sigma);
461py_neuron_default!("EnergyLIFNeuron", PyEnergyLIFNeuron, neurons::EnergyLIFNeuron, state v, state epsilon);
462py_neuron_default!("ClosedFormContinuousNeuron", PyClosedFormContinuousNeuron, neurons::ClosedFormContinuousNeuron, state x);
463
464#[pyclass(
465 name = "IntegerQIFNeuron",
466 module = "sc_neurocore_engine.sc_neurocore_engine"
467)]
468#[derive(Clone)]
469pub struct PyIntegerQIFNeuron {
470 inner: neurons::IntegerQIFNeuron,
471}
472
473#[pymethods]
474impl PyIntegerQIFNeuron {
475 #[new]
476 #[pyo3(signature = (k=6, v_threshold=1024))]
477 fn new(k: i32, v_threshold: i32) -> Self {
478 Self {
479 inner: neurons::IntegerQIFNeuron::new(k, v_threshold),
480 }
481 }
482 fn step(&mut self, current: i32) -> i32 {
483 self.inner.step(current)
484 }
485 fn reset(&mut self) {
486 self.inner.reset();
487 }
488 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
489 let d = PyDict::new(py);
490 d.set_item("v", self.inner.v)?;
491 Ok(d.into_any().unbind())
492 }
493}
494
495#[pyclass(
497 name = "EscapeRateNeuron",
498 module = "sc_neurocore_engine.sc_neurocore_engine"
499)]
500#[derive(Clone)]
501pub struct PyEscapeRateNeuron {
502 inner: neurons::EscapeRateNeuron,
503}
504
505#[pymethods]
506impl PyEscapeRateNeuron {
507 #[new]
508 #[pyo3(signature = (seed=42))]
509 fn new(seed: u64) -> Self {
510 Self {
511 inner: neurons::EscapeRateNeuron::new(seed),
512 }
513 }
514 fn step(&mut self, current: f64) -> i32 {
515 self.inner.step(current)
516 }
517 fn reset(&mut self) {
518 self.inner.reset();
519 }
520 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
521 let d = PyDict::new(py);
522 d.set_item("v", self.inner.v)?;
523 Ok(d.into_any().unbind())
524 }
525}
526
527py_neuron_default!("FitzHughNagumoNeuron", PyFitzHughNagumoNeuron, neurons::FitzHughNagumoNeuron, state v, state w);
532py_neuron_default!("MorrisLecarNeuron", PyMorrisLecarNeuron, neurons::MorrisLecarNeuron, state v, state w);
533py_neuron_default!("HindmarshRoseNeuron", PyHindmarshRoseNeuron, neurons::HindmarshRoseNeuron, state x, state y, state z);
534py_neuron_default!("ResonateAndFireNeuron", PyResonateAndFireNeuron, neurons::ResonateAndFireNeuron, state x, state y);
535py_neuron_default!("BalancedResonateAndFireNeuron", PyBalancedResonateAndFireNeuron, neurons::BalancedResonateAndFireNeuron, state x, state y, state q);
536py_neuron_default!("FitzHughRinzelNeuron", PyFitzHughRinzelNeuron, neurons::FitzHughRinzelNeuron, state v, state w, state y);
537py_neuron_default!("McKeanNeuron", PyMcKeanNeuron, neurons::McKeanNeuron, state v, state w);
538py_neuron_default!("TermanWangOscillator", PyTermanWangOscillator, neurons::TermanWangOscillator, state v, state w);
539py_neuron_default!("GutkinErmentroutNeuron", PyGutkinErmentroutNeuron, neurons::GutkinErmentroutNeuron, state v, state n);
540py_neuron_default!("WilsonHRNeuron", PyWilsonHRNeuron, neurons::WilsonHRNeuron, state v, state r);
541py_neuron_default!("ChayNeuron", PyChayNeuron, neurons::ChayNeuron, state v, state n, state ca);
542py_neuron_default!("ChayKeizerNeuron", PyChayKeizerNeuron, neurons::ChayKeizerNeuron, state v, state n, state ca);
543py_neuron_default!("ShermanRinzelKeizerNeuron", PyShermanRinzelKeizerNeuron, neurons::ShermanRinzelKeizerNeuron, state v, state n, state s);
544py_neuron_default!("ButeraRespiratoryNeuron", PyButeraRespiratoryNeuron, neurons::ButeraRespiratoryNeuron, state v, state n, state h_nap);
545py_neuron_default!("LearnableNeuronModel", PyLearnableNeuronModel, neurons::LearnableNeuronModel, state v);
546py_neuron_default!("PernarowskiNeuron", PyPernarowskiNeuron, neurons::PernarowskiNeuron, state v, state w, state z);
547
548#[pyclass(
550 name = "AlphaNeuron",
551 module = "sc_neurocore_engine.sc_neurocore_engine"
552)]
553#[derive(Clone)]
554pub struct PyAlphaNeuron {
555 inner: neurons::AlphaNeuron,
556}
557
558#[pymethods]
559impl PyAlphaNeuron {
560 #[new]
561 fn new() -> Self {
562 Self {
563 inner: neurons::AlphaNeuron::new(),
564 }
565 }
566 #[pyo3(signature = (exc_current, inh_current=0.0))]
567 fn step(&mut self, exc_current: f64, inh_current: f64) -> i32 {
568 self.inner.step(exc_current, inh_current)
569 }
570 fn reset(&mut self) {
571 self.inner.reset();
572 }
573 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
574 let d = PyDict::new(py);
575 d.set_item("v", self.inner.v)?;
576 d.set_item("i_exc", self.inner.i_exc)?;
577 d.set_item("i_inh", self.inner.i_inh)?;
578 Ok(d.into_any().unbind())
579 }
580}
581
582#[pyclass(
584 name = "COBALIFNeuron",
585 module = "sc_neurocore_engine.sc_neurocore_engine"
586)]
587#[derive(Clone)]
588pub struct PyCOBALIFNeuron {
589 inner: neurons::COBALIFNeuron,
590}
591
592#[pymethods]
593impl PyCOBALIFNeuron {
594 #[new]
595 fn new() -> Self {
596 Self {
597 inner: neurons::COBALIFNeuron::new(),
598 }
599 }
600 #[pyo3(signature = (current, delta_ge=0.0, delta_gi=0.0))]
601 fn step(&mut self, current: f64, delta_ge: f64, delta_gi: f64) -> i32 {
602 self.inner.step(current, delta_ge, delta_gi)
603 }
604 fn reset(&mut self) {
605 self.inner.reset();
606 }
607 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
608 let d = PyDict::new(py);
609 d.set_item("v", self.inner.v)?;
610 d.set_item("g_e", self.inner.g_e)?;
611 d.set_item("g_i", self.inner.g_i)?;
612 Ok(d.into_any().unbind())
613 }
614}
615
616#[pyclass(
618 name = "EPropALIFNeuron",
619 module = "sc_neurocore_engine.sc_neurocore_engine"
620)]
621#[derive(Clone)]
622pub struct PyEPropALIFNeuron {
623 inner: neurons::EPropALIFNeuron,
624}
625
626#[pymethods]
627impl PyEPropALIFNeuron {
628 #[new]
629 #[pyo3(signature = (tau_m=20.0, tau_a=200.0, dt=1.0))]
630 fn new(tau_m: f64, tau_a: f64, dt: f64) -> Self {
631 Self {
632 inner: neurons::EPropALIFNeuron::new(tau_m, tau_a, dt),
633 }
634 }
635 fn step(&mut self, current: f64) -> i32 {
636 self.inner.step(current)
637 }
638 fn reset(&mut self) {
639 self.inner.reset();
640 }
641 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
642 let d = PyDict::new(py);
643 d.set_item("v", self.inner.v)?;
644 d.set_item("a", self.inner.a)?;
645 d.set_item("e_trace", self.inner.e_trace)?;
646 Ok(d.into_any().unbind())
647 }
648}
649
650#[pyclass(
652 name = "SuperSpikeNeuron",
653 module = "sc_neurocore_engine.sc_neurocore_engine"
654)]
655#[derive(Clone)]
656pub struct PySuperSpikeNeuron {
657 inner: neurons::SuperSpikeNeuron,
658}
659
660#[pymethods]
661impl PySuperSpikeNeuron {
662 #[new]
663 #[pyo3(signature = (tau_m=10.0, tau_e=10.0, dt=1.0))]
664 fn new(tau_m: f64, tau_e: f64, dt: f64) -> Self {
665 Self {
666 inner: neurons::SuperSpikeNeuron::new(tau_m, tau_e, dt),
667 }
668 }
669 fn step(&mut self, current: f64) -> i32 {
670 self.inner.step(current)
671 }
672 fn reset(&mut self) {
673 self.inner.reset();
674 }
675 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
676 let d = PyDict::new(py);
677 d.set_item("v", self.inner.v)?;
678 d.set_item("trace", self.inner.trace)?;
679 Ok(d.into_any().unbind())
680 }
681}
682
683#[pyclass(
685 name = "BendaHerzNeuron",
686 module = "sc_neurocore_engine.sc_neurocore_engine"
687)]
688#[derive(Clone)]
689pub struct PyBendaHerzNeuron {
690 inner: neurons::BendaHerzNeuron,
691}
692
693#[pymethods]
694impl PyBendaHerzNeuron {
695 #[new]
696 #[pyo3(signature = (seed=42))]
697 fn new(seed: u64) -> Self {
698 Self {
699 inner: neurons::BendaHerzNeuron::new(seed),
700 }
701 }
702 fn step(&mut self, current: f64) -> i32 {
703 self.inner.step(current)
704 }
705 fn reset(&mut self) {
706 self.inner.reset();
707 }
708 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
709 let d = PyDict::new(py);
710 d.set_item("a", self.inner.a)?;
711 Ok(d.into_any().unbind())
712 }
713}
714
715py_neuron_default!("BrunelWangNeuron", PyBrunelWangNeuron, neurons::BrunelWangNeuron, state v, state ref_remaining);
716
717py_neuron_default!("ChialvoMapNeuron", PyChialvoMapNeuron, neurons::ChialvoMapNeuron, state x, state y);
722py_neuron_default!("RulkovMapNeuron", PyRulkovMapNeuron, neurons::RulkovMapNeuron, state x, state y);
723py_neuron_default!("IbarzTanakaMapNeuron", PyIbarzTanakaMapNeuron, neurons::IbarzTanakaMapNeuron, state x, state y);
724py_neuron_default!("MedvedevMapNeuron", PyMedvedevMapNeuron, neurons::MedvedevMapNeuron, state x);
725py_neuron_default!("CazellesMapNeuron", PyCazellesMapNeuron, neurons::CazellesMapNeuron, state x, state y);
726py_neuron_default!("CourageNekorkinMapNeuron", PyCourageNekorkinMapNeuron, neurons::CourageNekorkinMapNeuron, state x, state y);
727py_neuron_default!("AiharaMapNeuron", PyAiharaMapNeuron, neurons::AiharaMapNeuron, state x, state y);
728py_neuron_default!("KilincBhattMapNeuron", PyKilincBhattMapNeuron, neurons::KilincBhattMapNeuron, state x, state theta);
729py_neuron_default!("ErmentroutKopellMapNeuron", PyErmentroutKopellMapNeuron, neurons::ErmentroutKopellMapNeuron, state theta);
730
731py_neuron_default!("HodgkinHuxleyNeuron", PyHodgkinHuxleyNeuron, neurons::HodgkinHuxleyNeuron, state v, state m, state h, state n);
736py_neuron_default!("TraubMilesNeuron", PyTraubMilesNeuron, neurons::TraubMilesNeuron, state v, state m, state h, state n);
737py_neuron_default!("WangBuzsakiNeuron", PyWangBuzsakiNeuron, neurons::WangBuzsakiNeuron, state v, state h, state n);
738py_neuron_default!("ConnorStevensNeuron", PyConnorStevensNeuron, neurons::ConnorStevensNeuron, state v, state m, state h, state n, state a, state b);
739py_neuron_default!("DestexheThalamicNeuron", PyDestexheThalamicNeuron, neurons::DestexheThalamicNeuron, state v, state h_na, state n_k, state m_t, state h_t);
740py_neuron_default!("HuberBraunNeuron", PyHuberBraunNeuron, neurons::HuberBraunNeuron, state v, state a_sd, state a_sr);
741py_neuron_default!("GolombFSNeuron", PyGolombFSNeuron, neurons::GolombFSNeuron, state v, state h, state n, state p);
742py_neuron_default!("PospischilNeuron", PyPospischilNeuron, neurons::PospischilNeuron, state v, state m, state h, state n, state p);
743py_neuron_default!("MainenSejnowskiNeuron", PyMainenSejnowskiNeuron, neurons::MainenSejnowskiNeuron, state vs, state va, state m, state h, state n);
744py_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);
745py_neuron_default!("PlantR15Neuron", PyPlantR15Neuron, neurons::PlantR15Neuron, state v, state m, state h, state n, state ca);
746py_neuron_default!("PrescottNeuron", PyPrescottNeuron, neurons::PrescottNeuron, state v, state w);
747py_neuron_default!("MihalasNieburNeuron", PyMihalasNieburNeuron, neurons::MihalasNieburNeuron, state v, state theta, state i1, state i2);
748py_neuron_default!("GLIFNeuron", PyGLIFNeuron, neurons::GLIFNeuron, state v, state theta, state i_asc1, state i_asc2);
749py_neuron_default!("AvRonCardiacNeuron", PyAvRonCardiacNeuron, neurons::AvRonCardiacNeuron, state v, state h, state n, state s);
750py_neuron_default!("DurstewitzDopamineNeuron", PyDurstewitzDopamineNeuron, neurons::DurstewitzDopamineNeuron, state v, state h_na, state n_k);
751py_neuron_default!("HillTononiNeuron", PyHillTononiNeuron, neurons::HillTononiNeuron, state v, state h_na, state n_k, state m_h, state h_t, state na_i);
752py_neuron_default!("BertramPhantomBurster", PyBertramPhantomBurster, neurons::BertramPhantomBurster, state v, state s1, state s2);
753py_neuron_default!("YamadaNeuron", PyYamadaNeuron, neurons::YamadaNeuron, state v, state n, state q);
754
755#[pyclass(
757 name = "GIFPopulationNeuron",
758 module = "sc_neurocore_engine.sc_neurocore_engine"
759)]
760#[derive(Clone)]
761pub struct PyGIFPopulationNeuron {
762 inner: neurons::GIFPopulationNeuron,
763}
764
765#[pymethods]
766impl PyGIFPopulationNeuron {
767 #[new]
768 #[pyo3(signature = (seed=42))]
769 fn new(seed: u64) -> Self {
770 Self {
771 inner: neurons::GIFPopulationNeuron::new(seed),
772 }
773 }
774 fn step(&mut self, current: f64) -> i32 {
775 self.inner.step(current)
776 }
777 fn reset(&mut self) {
778 self.inner.reset();
779 }
780 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
781 let d = PyDict::new(py);
782 d.set_item("v", self.inner.v)?;
783 d.set_item("theta", self.inner.theta)?;
784 d.set_item("eta", self.inner.eta)?;
785 Ok(d.into_any().unbind())
786 }
787}
788
789#[pyclass(
795 name = "PinskyRinzelNeuron",
796 module = "sc_neurocore_engine.sc_neurocore_engine"
797)]
798#[derive(Clone)]
799pub struct PyPinskyRinzelNeuron {
800 inner: neurons::PinskyRinzelNeuron,
801}
802
803#[pymethods]
804impl PyPinskyRinzelNeuron {
805 #[new]
806 fn new() -> Self {
807 Self {
808 inner: neurons::PinskyRinzelNeuron::new(),
809 }
810 }
811 #[pyo3(signature = (current_soma, current_dend=0.0))]
812 fn step(&mut self, current_soma: f64, current_dend: f64) -> i32 {
813 self.inner.step(current_soma, current_dend)
814 }
815 fn reset(&mut self) {
816 self.inner.reset();
817 }
818 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
819 let d = PyDict::new(py);
820 d.set_item("v_s", self.inner.v_s)?;
821 d.set_item("v_d", self.inner.v_d)?;
822 Ok(d.into_any().unbind())
823 }
824}
825
826#[pyclass(
828 name = "HayL5PyramidalNeuron",
829 module = "sc_neurocore_engine.sc_neurocore_engine"
830)]
831#[derive(Clone)]
832pub struct PyHayL5PyramidalNeuron {
833 inner: neurons::HayL5PyramidalNeuron,
834}
835
836#[pymethods]
837impl PyHayL5PyramidalNeuron {
838 #[new]
839 fn new() -> Self {
840 Self {
841 inner: neurons::HayL5PyramidalNeuron::new(),
842 }
843 }
844 #[pyo3(signature = (current_soma, current_tuft=0.0))]
845 fn step(&mut self, current_soma: f64, current_tuft: f64) -> i32 {
846 self.inner.step(current_soma, current_tuft)
847 }
848 fn reset(&mut self) {
849 self.inner.reset();
850 }
851 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
852 let d = PyDict::new(py);
853 d.set_item("v_s", self.inner.v_s)?;
854 d.set_item("v_t", self.inner.v_t)?;
855 d.set_item("v_a", self.inner.v_a)?;
856 Ok(d.into_any().unbind())
857 }
858}
859
860py_neuron_default!("MarderSTGNeuron", PyMarderSTGNeuron, neurons::MarderSTGNeuron, state v, state ca);
861py_neuron_default!("BoothRinzelNeuron", PyBoothRinzelNeuron, neurons::BoothRinzelNeuron, state vs, state vd, state ca);
862py_neuron_default!("DendrifyNeuron", PyDendrifyNeuron, neurons::DendrifyNeuron, state v_s, state v_d);
863
864#[pyclass(
866 name = "RallCableNeuron",
867 module = "sc_neurocore_engine.sc_neurocore_engine"
868)]
869#[derive(Clone)]
870pub struct PyRallCableNeuron {
871 inner: neurons::RallCableNeuron,
872}
873
874#[pymethods]
875impl PyRallCableNeuron {
876 #[new]
877 #[pyo3(signature = (n_comp=5))]
878 fn new(n_comp: usize) -> Self {
879 Self {
880 inner: neurons::RallCableNeuron::new(n_comp),
881 }
882 }
883 fn step(&mut self, current: f64) -> i32 {
884 self.inner.step(current)
885 }
886 fn reset(&mut self) {
887 self.inner.reset();
888 }
889 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
890 let d = PyDict::new(py);
891 d.set_item("v", self.inner.v.clone())?;
892 Ok(d.into_any().unbind())
893 }
894}
895
896#[pyclass(
898 name = "TwoCompartmentLIFNeuron",
899 module = "sc_neurocore_engine.sc_neurocore_engine"
900)]
901#[derive(Clone)]
902pub struct PyTwoCompartmentLIFNeuron {
903 inner: neurons::TwoCompartmentLIFNeuron,
904}
905
906#[pymethods]
907impl PyTwoCompartmentLIFNeuron {
908 #[new]
909 fn new() -> Self {
910 Self {
911 inner: neurons::TwoCompartmentLIFNeuron::new(),
912 }
913 }
914 #[pyo3(signature = (i_soma, i_dend=0.0))]
915 fn step(&mut self, i_soma: f64, i_dend: f64) -> i32 {
916 self.inner.step(i_soma, i_dend)
917 }
918 fn reset(&mut self) {
919 self.inner.reset();
920 }
921 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
922 let d = PyDict::new(py);
923 d.set_item("v_s", self.inner.v_s)?;
924 d.set_item("v_d", self.inner.v_d)?;
925 Ok(d.into_any().unbind())
926 }
927}
928
929#[pyclass(
934 name = "PoissonNeuron",
935 module = "sc_neurocore_engine.sc_neurocore_engine"
936)]
937#[derive(Clone)]
938pub struct PyPoissonNeuron {
939 inner: neurons::PoissonNeuron,
940}
941
942#[pymethods]
943impl PyPoissonNeuron {
944 #[new]
945 #[pyo3(signature = (rate_hz=100.0, dt_ms=1.0, seed=42))]
946 fn new(rate_hz: f64, dt_ms: f64, seed: u64) -> Self {
947 Self {
948 inner: neurons::PoissonNeuron::new(rate_hz, dt_ms, seed),
949 }
950 }
951 #[pyo3(signature = (rate_override=-1.0))]
952 fn step(&mut self, rate_override: f64) -> i32 {
953 self.inner.step(rate_override)
954 }
955 fn reset(&mut self) {
956 self.inner.reset();
957 }
958}
959
960#[pyclass(
961 name = "InhomogeneousPoissonNeuron",
962 module = "sc_neurocore_engine.sc_neurocore_engine"
963)]
964#[derive(Clone)]
965pub struct PyInhomogeneousPoissonNeuron {
966 inner: neurons::InhomogeneousPoissonNeuron,
967}
968
969#[pymethods]
970impl PyInhomogeneousPoissonNeuron {
971 #[new]
972 #[pyo3(signature = (dt_ms=1.0, seed=42))]
973 fn new(dt_ms: f64, seed: u64) -> Self {
974 Self {
975 inner: neurons::InhomogeneousPoissonNeuron::new(dt_ms, seed),
976 }
977 }
978 fn step(&mut self, rate_hz: f64) -> i32 {
979 self.inner.step(rate_hz)
980 }
981 fn reset(&mut self) {
982 self.inner.reset();
983 }
984}
985
986#[pyclass(
987 name = "GammaRenewalNeuron",
988 module = "sc_neurocore_engine.sc_neurocore_engine"
989)]
990#[derive(Clone)]
991pub struct PyGammaRenewalNeuron {
992 inner: neurons::GammaRenewalNeuron,
993}
994
995#[pymethods]
996impl PyGammaRenewalNeuron {
997 #[new]
998 #[pyo3(signature = (rate_hz=50.0, shape_k=3, seed=42))]
999 fn new(rate_hz: f64, shape_k: u32, seed: u64) -> Self {
1000 Self {
1001 inner: neurons::GammaRenewalNeuron::new(rate_hz, shape_k, seed),
1002 }
1003 }
1004 #[pyo3(signature = (rate_override=-1.0))]
1005 fn step(&mut self, rate_override: f64) -> i32 {
1006 self.inner.step(rate_override)
1007 }
1008 fn reset(&mut self) {
1009 self.inner.reset();
1010 }
1011}
1012
1013#[pyclass(
1014 name = "StochasticIFNeuron",
1015 module = "sc_neurocore_engine.sc_neurocore_engine"
1016)]
1017#[derive(Clone)]
1018pub struct PyStochasticIFNeuron {
1019 inner: neurons::StochasticIFNeuron,
1020}
1021
1022#[pymethods]
1023impl PyStochasticIFNeuron {
1024 #[new]
1025 #[pyo3(signature = (seed=42))]
1026 fn new(seed: u64) -> Self {
1027 Self {
1028 inner: neurons::StochasticIFNeuron::new(seed),
1029 }
1030 }
1031 fn step(&mut self, current: f64) -> i32 {
1032 self.inner.step(current)
1033 }
1034 fn reset(&mut self) {
1035 self.inner.reset();
1036 }
1037 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1038 let d = PyDict::new(py);
1039 d.set_item("v", self.inner.v)?;
1040 Ok(d.into_any().unbind())
1041 }
1042}
1043
1044#[pyclass(
1045 name = "GalvesLocherbachNeuron",
1046 module = "sc_neurocore_engine.sc_neurocore_engine"
1047)]
1048#[derive(Clone)]
1049pub struct PyGalvesLocherbachNeuron {
1050 inner: neurons::GalvesLocherbachNeuron,
1051}
1052
1053#[pymethods]
1054impl PyGalvesLocherbachNeuron {
1055 #[new]
1056 #[pyo3(signature = (seed=42))]
1057 fn new(seed: u64) -> Self {
1058 Self {
1059 inner: neurons::GalvesLocherbachNeuron::new(seed),
1060 }
1061 }
1062 fn step(&mut self, weighted_input: f64) -> i32 {
1063 self.inner.step(weighted_input)
1064 }
1065 fn reset(&mut self) {
1066 self.inner.reset();
1067 }
1068 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1069 let d = PyDict::new(py);
1070 d.set_item("v", self.inner.v)?;
1071 Ok(d.into_any().unbind())
1072 }
1073}
1074
1075py_neuron_default!("SpikeResponseNeuron", PySpikeResponseNeuron, neurons::SpikeResponseNeuron, state v, state time_since_spike);
1076
1077#[pyclass(name = "GLMNeuron", module = "sc_neurocore_engine.sc_neurocore_engine")]
1079#[derive(Clone)]
1080pub struct PyGLMNeuron {
1081 inner: neurons::GLMNeuron,
1082}
1083
1084#[pymethods]
1085impl PyGLMNeuron {
1086 #[new]
1087 #[pyo3(signature = (n_k=10, n_h=20, seed=42))]
1088 fn new(n_k: usize, n_h: usize, seed: u64) -> Self {
1089 Self {
1090 inner: neurons::GLMNeuron::new(n_k, n_h, seed),
1091 }
1092 }
1093 fn step(&mut self, stimulus: f64) -> i32 {
1094 self.inner.step(stimulus)
1095 }
1096 fn reset(&mut self) {
1097 self.inner.reset();
1098 }
1099}
1100
1101#[pyclass(
1103 name = "WilsonCowanUnit",
1104 module = "sc_neurocore_engine.sc_neurocore_engine"
1105)]
1106#[derive(Clone)]
1107pub struct PyWilsonCowanUnit {
1108 inner: neurons::WilsonCowanUnit,
1109}
1110
1111#[pymethods]
1112impl PyWilsonCowanUnit {
1113 #[new]
1114 fn new() -> Self {
1115 Self {
1116 inner: neurons::WilsonCowanUnit::new(),
1117 }
1118 }
1119 #[pyo3(signature = (ext_input=0.0))]
1120 fn step(&mut self, ext_input: f64) -> f64 {
1121 self.inner.step(ext_input)
1122 }
1123 fn reset(&mut self) {
1124 self.inner.reset();
1125 }
1126 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1127 let d = PyDict::new(py);
1128 d.set_item("e", self.inner.e)?;
1129 d.set_item("i", self.inner.i)?;
1130 Ok(d.into_any().unbind())
1131 }
1132}
1133
1134#[pyclass(
1136 name = "JansenRitUnit",
1137 module = "sc_neurocore_engine.sc_neurocore_engine"
1138)]
1139#[derive(Clone)]
1140pub struct PyJansenRitUnit {
1141 inner: neurons::JansenRitUnit,
1142}
1143
1144#[pymethods]
1145impl PyJansenRitUnit {
1146 #[new]
1147 fn new() -> Self {
1148 Self {
1149 inner: neurons::JansenRitUnit::new(),
1150 }
1151 }
1152 #[pyo3(signature = (p_ext=220.0))]
1153 fn step(&mut self, p_ext: f64) -> f64 {
1154 self.inner.step(p_ext)
1155 }
1156 fn reset(&mut self) {
1157 self.inner.reset();
1158 }
1159 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1160 let d = PyDict::new(py);
1161 d.set_item("y", self.inner.y.to_vec())?;
1162 Ok(d.into_any().unbind())
1163 }
1164}
1165
1166#[pyclass(
1168 name = "WongWangUnit",
1169 module = "sc_neurocore_engine.sc_neurocore_engine"
1170)]
1171#[derive(Clone)]
1172pub struct PyWongWangUnit {
1173 inner: neurons::WongWangUnit,
1174}
1175
1176#[pymethods]
1177impl PyWongWangUnit {
1178 #[new]
1179 #[pyo3(signature = (seed=42))]
1180 fn new(seed: u64) -> Self {
1181 Self {
1182 inner: neurons::WongWangUnit::new(seed),
1183 }
1184 }
1185 #[pyo3(signature = (stim1=0.0, stim2=0.0))]
1186 fn step(&mut self, stim1: f64, stim2: f64) -> (f64, f64) {
1187 self.inner.step(stim1, stim2)
1188 }
1189 fn reset(&mut self) {
1190 self.inner.reset();
1191 }
1192 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1193 let d = PyDict::new(py);
1194 d.set_item("s1", self.inner.s1)?;
1195 d.set_item("s2", self.inner.s2)?;
1196 Ok(d.into_any().unbind())
1197 }
1198}
1199
1200#[pyclass(
1202 name = "ErmentroutKopellPopulation",
1203 module = "sc_neurocore_engine.sc_neurocore_engine"
1204)]
1205#[derive(Clone)]
1206pub struct PyErmentroutKopellPopulation {
1207 inner: neurons::ErmentroutKopellPopulation,
1208}
1209
1210#[pymethods]
1211impl PyErmentroutKopellPopulation {
1212 #[new]
1213 fn new() -> Self {
1214 Self {
1215 inner: neurons::ErmentroutKopellPopulation::new(),
1216 }
1217 }
1218 #[pyo3(signature = (ext_input=0.0))]
1219 fn step(&mut self, ext_input: f64) -> f64 {
1220 self.inner.step(ext_input)
1221 }
1222 fn reset(&mut self) {
1223 self.inner.reset();
1224 }
1225 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1226 let d = PyDict::new(py);
1227 d.set_item("r", self.inner.r)?;
1228 d.set_item("v", self.inner.v)?;
1229 Ok(d.into_any().unbind())
1230 }
1231}
1232
1233#[pyclass(
1235 name = "WendlingNeuron",
1236 module = "sc_neurocore_engine.sc_neurocore_engine"
1237)]
1238#[derive(Clone)]
1239pub struct PyWendlingNeuron {
1240 inner: neurons::WendlingNeuron,
1241}
1242
1243#[pymethods]
1244impl PyWendlingNeuron {
1245 #[new]
1246 fn new() -> Self {
1247 Self {
1248 inner: neurons::WendlingNeuron::new(),
1249 }
1250 }
1251 #[pyo3(signature = (p_ext=220.0))]
1252 fn step(&mut self, p_ext: f64) -> f64 {
1253 self.inner.step(p_ext)
1254 }
1255 fn reset(&mut self) {
1256 self.inner.reset();
1257 }
1258}
1259
1260#[pyclass(
1262 name = "LarterBreakspearNeuron",
1263 module = "sc_neurocore_engine.sc_neurocore_engine"
1264)]
1265#[derive(Clone)]
1266pub struct PyLarterBreakspearNeuron {
1267 inner: neurons::LarterBreakspearNeuron,
1268}
1269
1270#[pymethods]
1271impl PyLarterBreakspearNeuron {
1272 #[new]
1273 fn new() -> Self {
1274 Self {
1275 inner: neurons::LarterBreakspearNeuron::new(),
1276 }
1277 }
1278 #[pyo3(signature = (coupling=0.0))]
1279 fn step(&mut self, coupling: f64) -> f64 {
1280 self.inner.step(coupling)
1281 }
1282 fn reset(&mut self) {
1283 self.inner.reset();
1284 }
1285 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1286 let d = PyDict::new(py);
1287 d.set_item("v", self.inner.v)?;
1288 d.set_item("w", self.inner.w)?;
1289 d.set_item("z", self.inner.z)?;
1290 Ok(d.into_any().unbind())
1291 }
1292}
1293
1294#[pyclass(
1299 name = "LoihiCUBANeuron",
1300 module = "sc_neurocore_engine.sc_neurocore_engine"
1301)]
1302#[derive(Clone)]
1303pub struct PyLoihiCUBANeuron {
1304 inner: neurons::LoihiCUBANeuron,
1305}
1306
1307#[pymethods]
1308impl PyLoihiCUBANeuron {
1309 #[new]
1310 fn new() -> Self {
1311 Self {
1312 inner: neurons::LoihiCUBANeuron::new(),
1313 }
1314 }
1315 fn step(&mut self, weighted_input: i32) -> i32 {
1316 self.inner.step(weighted_input)
1317 }
1318 fn reset(&mut self) {
1319 self.inner.reset();
1320 }
1321 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1322 let d = PyDict::new(py);
1323 d.set_item("v", self.inner.v)?;
1324 d.set_item("u", self.inner.u)?;
1325 Ok(d.into_any().unbind())
1326 }
1327}
1328
1329#[pyclass(
1330 name = "Loihi2Neuron",
1331 module = "sc_neurocore_engine.sc_neurocore_engine"
1332)]
1333#[derive(Clone)]
1334pub struct PyLoihi2Neuron {
1335 inner: neurons::Loihi2Neuron,
1336}
1337
1338#[pymethods]
1339impl PyLoihi2Neuron {
1340 #[new]
1341 fn new() -> Self {
1342 Self {
1343 inner: neurons::Loihi2Neuron::new(),
1344 }
1345 }
1346 fn step(&mut self, weighted_input: i32) -> i32 {
1347 self.inner.step(weighted_input)
1348 }
1349 fn reset(&mut self) {
1350 self.inner.reset();
1351 }
1352 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1353 let d = PyDict::new(py);
1354 d.set_item("s1", self.inner.s1)?;
1355 d.set_item("s2", self.inner.s2)?;
1356 d.set_item("s3", self.inner.s3)?;
1357 Ok(d.into_any().unbind())
1358 }
1359}
1360
1361#[pyclass(
1362 name = "TrueNorthNeuron",
1363 module = "sc_neurocore_engine.sc_neurocore_engine"
1364)]
1365#[derive(Clone)]
1366pub struct PyTrueNorthNeuron {
1367 inner: neurons::TrueNorthNeuron,
1368}
1369
1370#[pymethods]
1371impl PyTrueNorthNeuron {
1372 #[new]
1373 #[pyo3(signature = (threshold=100))]
1374 fn new(threshold: i32) -> Self {
1375 Self {
1376 inner: neurons::TrueNorthNeuron::new(threshold),
1377 }
1378 }
1379 fn step(&mut self, weighted_input: i32) -> i32 {
1380 self.inner.step(weighted_input)
1381 }
1382 fn reset(&mut self) {
1383 self.inner.reset();
1384 }
1385 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1386 let d = PyDict::new(py);
1387 d.set_item("v", self.inner.v)?;
1388 Ok(d.into_any().unbind())
1389 }
1390}
1391
1392py_neuron_default!("BrainScaleSAdExNeuron", PyBrainScaleSAdExNeuron, neurons::BrainScaleSAdExNeuron, state v, state w);
1393py_neuron_default!("SpiNNakerLIFNeuron", PySpiNNakerLIFNeuron, neurons::SpiNNakerLIFNeuron, state v, state refrac_count);
1394
1395#[pyclass(
1396 name = "SpiNNaker2Neuron",
1397 module = "sc_neurocore_engine.sc_neurocore_engine"
1398)]
1399#[derive(Clone)]
1400pub struct PySpiNNaker2Neuron {
1401 inner: neurons::SpiNNaker2Neuron,
1402}
1403
1404#[pymethods]
1405impl PySpiNNaker2Neuron {
1406 #[new]
1407 fn new() -> Self {
1408 Self {
1409 inner: neurons::SpiNNaker2Neuron::new(),
1410 }
1411 }
1412 fn step(&mut self, current: i32) -> i32 {
1413 self.inner.step(current)
1414 }
1415 fn reset(&mut self) {
1416 self.inner.reset();
1417 }
1418 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1419 let d = PyDict::new(py);
1420 d.set_item("v", self.inner.v)?;
1421 Ok(d.into_any().unbind())
1422 }
1423}
1424
1425py_neuron_default!("DPINeuron", PyDPINeuron, neurons::DPINeuron, state i_mem);
1426
1427#[pyclass(
1428 name = "AkidaNeuron",
1429 module = "sc_neurocore_engine.sc_neurocore_engine"
1430)]
1431#[derive(Clone)]
1432pub struct PyAkidaNeuron {
1433 inner: neurons::AkidaNeuron,
1434}
1435
1436#[pymethods]
1437impl PyAkidaNeuron {
1438 #[new]
1439 #[pyo3(signature = (threshold=100))]
1440 fn new(threshold: i32) -> Self {
1441 Self {
1442 inner: neurons::AkidaNeuron::new(threshold),
1443 }
1444 }
1445 fn step(&mut self, weight: i32) -> i32 {
1446 self.inner.step(weight as f64)
1447 }
1448 fn reset(&mut self) {
1449 self.inner.reset();
1450 }
1451 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1452 let d = PyDict::new(py);
1453 d.set_item("v", self.inner.v)?;
1454 d.set_item("rank", self.inner.rank)?;
1455 Ok(d.into_any().unbind())
1456 }
1457}
1458
1459py_neuron_default!("NeuroGridNeuron", PyNeuroGridNeuron, neurons::NeuroGridNeuron, state v_s, state v_d);
1460
1461#[pyclass(
1466 name = "McCullochPittsNeuron",
1467 module = "sc_neurocore_engine.sc_neurocore_engine"
1468)]
1469#[derive(Clone)]
1470pub struct PyMcCullochPittsNeuron {
1471 inner: neurons::McCullochPittsNeuron,
1472}
1473
1474#[pymethods]
1475impl PyMcCullochPittsNeuron {
1476 #[new]
1477 #[pyo3(signature = (theta=1.0))]
1478 fn new(theta: f64) -> Self {
1479 Self {
1480 inner: neurons::McCullochPittsNeuron::new(theta),
1481 }
1482 }
1483 fn step(&self, weighted_input: f64) -> i32 {
1484 self.inner.step(weighted_input)
1485 }
1486}
1487
1488#[pyclass(
1490 name = "SigmoidRateNeuron",
1491 module = "sc_neurocore_engine.sc_neurocore_engine"
1492)]
1493#[derive(Clone)]
1494pub struct PySigmoidRateNeuron {
1495 inner: neurons::SigmoidRateNeuron,
1496}
1497
1498#[pymethods]
1499impl PySigmoidRateNeuron {
1500 #[new]
1501 fn new() -> Self {
1502 Self {
1503 inner: neurons::SigmoidRateNeuron::new(),
1504 }
1505 }
1506 fn step(&mut self, current: f64) -> f64 {
1507 self.inner.step(current)
1508 }
1509 fn reset(&mut self) {
1510 self.inner.reset();
1511 }
1512 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1513 let d = PyDict::new(py);
1514 d.set_item("r", self.inner.r)?;
1515 Ok(d.into_any().unbind())
1516 }
1517}
1518
1519#[pyclass(
1521 name = "ThresholdLinearRateNeuron",
1522 module = "sc_neurocore_engine.sc_neurocore_engine"
1523)]
1524#[derive(Clone)]
1525pub struct PyThresholdLinearRateNeuron {
1526 inner: neurons::ThresholdLinearRateNeuron,
1527}
1528
1529#[pymethods]
1530impl PyThresholdLinearRateNeuron {
1531 #[new]
1532 fn new() -> Self {
1533 Self {
1534 inner: neurons::ThresholdLinearRateNeuron::new(),
1535 }
1536 }
1537 fn step(&mut self, current: f64) -> f64 {
1538 self.inner.step(current)
1539 }
1540 fn reset(&mut self) {
1541 self.inner.reset();
1542 }
1543}
1544
1545#[pyclass(
1547 name = "AstrocyteModel",
1548 module = "sc_neurocore_engine.sc_neurocore_engine"
1549)]
1550#[derive(Clone)]
1551pub struct PyAstrocyteModel {
1552 inner: neurons::AstrocyteModel,
1553}
1554
1555#[pymethods]
1556impl PyAstrocyteModel {
1557 #[new]
1558 fn new() -> Self {
1559 Self {
1560 inner: neurons::AstrocyteModel::new(),
1561 }
1562 }
1563 fn step(&mut self, current: f64) -> f64 {
1564 self.inner.step(current)
1565 }
1566 fn reset(&mut self) {
1567 self.inner.reset();
1568 }
1569 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1570 let d = PyDict::new(py);
1571 d.set_item("ca", self.inner.ca)?;
1572 d.set_item("h", self.inner.h)?;
1573 d.set_item("ip3", self.inner.ip3)?;
1574 Ok(d.into_any().unbind())
1575 }
1576}
1577
1578#[pyclass(
1580 name = "TsodyksMarkramNeuron",
1581 module = "sc_neurocore_engine.sc_neurocore_engine"
1582)]
1583#[derive(Clone)]
1584pub struct PyTsodyksMarkramNeuron {
1585 inner: neurons::TsodyksMarkramNeuron,
1586}
1587
1588#[pymethods]
1589impl PyTsodyksMarkramNeuron {
1590 #[new]
1591 fn new() -> Self {
1592 Self {
1593 inner: neurons::TsodyksMarkramNeuron::new(),
1594 }
1595 }
1596 #[pyo3(signature = (current, presynaptic_spike=false))]
1597 fn step(&mut self, current: f64, presynaptic_spike: bool) -> i32 {
1598 self.inner.step(current, presynaptic_spike)
1599 }
1600 fn reset(&mut self) {
1601 self.inner.reset();
1602 }
1603 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1604 let d = PyDict::new(py);
1605 d.set_item("v", self.inner.v)?;
1606 d.set_item("x", self.inner.x)?;
1607 d.set_item("u", self.inner.u)?;
1608 Ok(d.into_any().unbind())
1609 }
1610}
1611
1612py_neuron_default!("LiquidTimeConstantNeuron", PyLiquidTimeConstantNeuron, neurons::LiquidTimeConstantNeuron, state x);
1613
1614#[pyclass(
1616 name = "CompteWMNeuron",
1617 module = "sc_neurocore_engine.sc_neurocore_engine"
1618)]
1619#[derive(Clone)]
1620pub struct PyCompteWMNeuron {
1621 inner: neurons::CompteWMNeuron,
1622}
1623
1624#[pymethods]
1625impl PyCompteWMNeuron {
1626 #[new]
1627 fn new() -> Self {
1628 Self {
1629 inner: neurons::CompteWMNeuron::new(),
1630 }
1631 }
1632 #[pyo3(signature = (current, spike_in=false))]
1633 fn step(&mut self, current: f64, spike_in: bool) -> i32 {
1634 self.inner.step(current, spike_in)
1635 }
1636 fn reset(&mut self) {
1637 self.inner.reset();
1638 }
1639 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1640 let d = PyDict::new(py);
1641 d.set_item("v", self.inner.v)?;
1642 d.set_item("s_nmda", self.inner.s_nmda)?;
1643 Ok(d.into_any().unbind())
1644 }
1645}
1646
1647#[pyclass(
1649 name = "SiegertTransferFunction",
1650 module = "sc_neurocore_engine.sc_neurocore_engine"
1651)]
1652#[derive(Clone)]
1653pub struct PySiegertTransferFunction {
1654 inner: neurons::SiegertTransferFunction,
1655}
1656
1657#[pymethods]
1658impl PySiegertTransferFunction {
1659 #[new]
1660 fn new() -> Self {
1661 Self {
1662 inner: neurons::SiegertTransferFunction::new(),
1663 }
1664 }
1665 fn step(&self, current: f64) -> f64 {
1666 self.inner.step(current)
1667 }
1668}
1669
1670#[pyclass(
1675 name = "FractionalLIFNeuron",
1676 module = "sc_neurocore_engine.sc_neurocore_engine"
1677)]
1678#[derive(Clone)]
1679pub struct PyFractionalLIFNeuron {
1680 inner: neurons::FractionalLIFNeuron,
1681}
1682
1683#[pymethods]
1684impl PyFractionalLIFNeuron {
1685 #[new]
1686 #[pyo3(signature = (alpha=0.8, max_hist=50))]
1687 fn new(alpha: f64, max_hist: usize) -> Self {
1688 Self {
1689 inner: neurons::FractionalLIFNeuron::new(alpha, max_hist),
1690 }
1691 }
1692 fn step(&mut self, current: f64) -> i32 {
1693 self.inner.step(current)
1694 }
1695 fn reset(&mut self) {
1696 self.inner.reset();
1697 }
1698 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1699 let d = PyDict::new(py);
1700 d.set_item("v", self.inner.v)?;
1701 Ok(d.into_any().unbind())
1702 }
1703}
1704
1705#[pyclass(
1706 name = "ParallelSpikingNeuron",
1707 module = "sc_neurocore_engine.sc_neurocore_engine"
1708)]
1709#[derive(Clone)]
1710pub struct PyParallelSpikingNeuron {
1711 inner: neurons::ParallelSpikingNeuron,
1712}
1713
1714#[pymethods]
1715impl PyParallelSpikingNeuron {
1716 #[new]
1717 #[pyo3(signature = (kernel_size=8, v_threshold=1.0))]
1718 fn new(kernel_size: usize, v_threshold: f64) -> Self {
1719 Self {
1720 inner: neurons::ParallelSpikingNeuron::new(kernel_size, v_threshold),
1721 }
1722 }
1723 fn step(&mut self, current: f64) -> i32 {
1724 self.inner.step(current)
1725 }
1726 fn reset(&mut self) {
1727 self.inner.reset();
1728 }
1729}
1730
1731#[pyclass(
1732 name = "AmariNeuralField",
1733 module = "sc_neurocore_engine.sc_neurocore_engine"
1734)]
1735#[derive(Clone)]
1736pub struct PyAmariNeuralField {
1737 inner: neurons::AmariNeuralField,
1738}
1739
1740#[pymethods]
1741impl PyAmariNeuralField {
1742 #[new]
1743 #[pyo3(signature = (n=64))]
1744 fn new(n: usize) -> Self {
1745 Self {
1746 inner: neurons::AmariNeuralField::new(n),
1747 }
1748 }
1749 fn step(&mut self, input: Vec<f64>) -> f64 {
1750 self.inner.step(&input)
1751 }
1752 fn reset(&mut self) {
1753 self.inner.reset();
1754 }
1755 fn get_state<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
1756 self.inner.u.clone().into_pyarray(py)
1757 }
1758}
1759
1760py_neuron_default!("PVFastSpikingNeuron", PyPVFastSpikingNeuron, neurons::PVFastSpikingNeuron, state v, state h, state n, state p);
1765py_neuron_default!("SSTNeuron", PySSTNeuron, neurons::SSTNeuron, state v, state m, state h, state n, state p, state s, state r);
1766py_neuron_default!("VIPNeuron", PyVIPNeuron, neurons::VIPNeuron, state v, state h, state n, state a, state b);
1767py_neuron_default!("ChandelierNeuron", PyChandelierNeuron, neurons::ChandelierNeuron, state v, state h, state n, state d, state p);
1768py_neuron_default!("CerebellarBasketNeuron", PyCerebellarBasketNeuron, neurons::CerebellarBasketNeuron, state v, state h, state n, state a, state b, state ca);
1769py_neuron_default!("MartinottiNeuron", PyMartinottiNeuron, neurons::MartinottiNeuron, state v, state m, state h, state n, state p, state s);
1770
1771py_neuron_default!("AlphaMotorNeuron", PyAlphaMotorNeuron, neurons::AlphaMotorNeuron, state v, state h, state n, state m_pic, state ca);
1776py_neuron_default!("GammaMotorNeuron", PyGammaMotorNeuron, neurons::GammaMotorNeuron, state v, state adapt);
1777py_neuron_default!("UpperMotorNeuron", PyUpperMotorNeuron, neurons::UpperMotorNeuron, state v, state m, state h, state n, state p, state s);
1778py_neuron_default!("RenshawCell", PyRenshawCell, neurons::RenshawCell, state v, state h, state n, state adapt);
1779py_neuron_default!("MotorUnit", PyMotorUnit, neurons::MotorUnit, state v, state adapt, state force);
1780
1781py_neuron_default!("GranuleCell", PyGranuleCell, neurons::GranuleCell, state v, state m, state h, state n, state ca);
1783py_neuron_default!("GolgiCell", PyGolgiCell, neurons::GolgiCell, state v, state m, state h, state p_na, state n, state a, state b, state w, state m_t, state s, state c_n, state r, state ca);
1784py_neuron_default!("StellateCell", PyStellateCell, neurons::StellateCell, state v, state h, state n, state p);
1785py_neuron_default!("LugaroCell", PyLugaroCell, neurons::LugaroCell, state v, state adapt);
1786py_neuron_default!("UnipolarBrushCell", PyUnipolarBrushCell, neurons::UnipolarBrushCell, state v, state persistent);
1787py_neuron_default!("DCNNeuron", PyDCNNeuron, neurons::DCNNeuron, state v, state h, state n, state p, state s, state r, state ca);
1788
1789py_neuron_default!("PersistentNaNeuron", PyPersistentNaNeuron, neurons::PersistentNaNeuron, state v, state h, state n, state p);
1791py_neuron_default!("IhNeuron", PyIhNeuron, neurons::IhNeuron, state v, state h, state n, state r);
1792py_neuron_default!("TTypeCaNeuron", PyTTypeCaNeuron, neurons::TTypeCaNeuron, state v, state h, state n, state s);
1793py_neuron_default!("ATypeKNeuron", PyATypeKNeuron, neurons::ATypeKNeuron, state v, state h, state n, state a, state b);
1794py_neuron_default!("BKNeuron", PyBKNeuron, neurons::BKNeuron, state v, state h, state n, state ca);
1795py_neuron_default!("SKNeuron", PySKNeuron, neurons::SKNeuron, state v, state h, state n, state ca);
1796py_neuron_default!("NMDANeuron", PyNMDANeuron, neurons::NMDANeuron, state v, state h, state n, state s_nmda);
1797
1798py_neuron_default!("MontbrioMeanField", PyMontbrioMeanField, neurons::MontbrioMeanField, state r, state v);
1800py_neuron_default!("BrunelNetwork", PyBrunelNetwork, neurons::BrunelNetwork, state r_e, state r_i);
1801py_neuron_default!("TUMNetwork", PyTUMNetwork, neurons::TUMNetwork, state r, state x, state u);
1802py_neuron_default!("ElBoustaniNetwork", PyElBoustaniNetwork, neurons::ElBoustaniNetwork, state r_e, state r_i, state s);
1803
1804py_neuron_default!("GradedSynapseNeuron", PyGradedSynapseNeuron, neurons::GradedSynapseNeuron, state v);
1806py_neuron_default!("GapJunctionNeuron", PyGapJunctionNeuron, neurons::GapJunctionNeuron, state v);
1807py_neuron_default!("FrankenhaeUserHuxleyAxon", PyFHAxon, neurons::FrankenhaeUserHuxleyAxon, state v, state m, state h, state n, state p);
1808py_neuron_default!("NodeOfRanvier", PyNodeOfRanvier, neurons::NodeOfRanvier, state v, state m, state h, state p, state s);
1809py_neuron_default!("MyelinatedAxon", PyMyelinatedAxon, neurons::MyelinatedAxon, state v_inter);
1810py_neuron_default!("CardiacPurkinjeFibre", PyCardiacPurkinjeFibre, neurons::CardiacPurkinjeFibre, state v, state d, state f, state y);
1811py_neuron_default!("SmoothMuscleCell", PySmoothMuscleCell, neurons::SmoothMuscleCell, state v, state ca, state ca_store);
1812py_neuron_default!("EndocrineBetaCell", PyEndocrineBetaCell, neurons::EndocrineBetaCell, state v, state n, state ca);
1813
1814macro_rules! py_sensory_graded {
1820 ($pylit:literal, $pyname:ident, $rust:ty $(, state $sname:ident)*) => {
1821 #[pyclass(name = $pylit, module = "sc_neurocore_engine.sc_neurocore_engine")]
1822 #[derive(Clone)]
1823 pub struct $pyname { inner: $rust }
1824
1825 #[pymethods]
1826 impl $pyname {
1827 #[new]
1828 fn new() -> Self { Self { inner: <$rust>::default() } }
1829
1830 fn step(&mut self, input: f64) -> f64 { self.inner.step(input) }
1831
1832 fn reset(&mut self) { self.inner.reset(); }
1833
1834 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1835 let d = PyDict::new(py);
1836 $(d.set_item(stringify!($sname), self.inner.$sname)?;)*
1837 Ok(d.into_any().unbind())
1838 }
1839 }
1840 };
1841}
1842
1843py_sensory_graded!("InnerHairCell", PyInnerHairCell, neurons::InnerHairCell, state v, state ca, state q, state c, state w);
1844py_sensory_graded!("OuterHairCell", PyOuterHairCell, neurons::OuterHairCell, state v, state motility);
1845py_sensory_graded!("RodPhotoreceptor", PyRodPhotoreceptor, neurons::RodPhotoreceptor, state v, state cgmp, state ca);
1846py_sensory_graded!("ConePhotoreceptor", PyConePhotoreceptor, neurons::ConePhotoreceptor, state v, state cgmp);
1847py_sensory_graded!("TasteReceptorCell", PyTasteReceptorCell, neurons::TasteReceptorCell, state v, state ca, state ip3, state atp_release);
1848
1849py_neuron_default!("MerkelCell", PyMerkelCell, neurons::MerkelCell, state v, state adapt);
1851py_neuron_default!("Nociceptor", PyNociceptor, neurons::Nociceptor, state v, state sensitisation);
1852py_neuron_default!("OlfactoryReceptorNeuron", PyOlfactoryReceptorNeuron, neurons::OlfactoryReceptorNeuron, state v, state camp, state adapt, state pde4);
1853
1854py_neuron_default!("RetinalGanglionCell", PyRetinalGanglionCell, neurons::RetinalGanglionCell, state baseline, state on_centre);
1856py_neuron_default!("PacinianCorpuscle", PyPacinianCorpuscle, neurons::PacinianCorpuscle, state v, state prev_pressure, state adapt);
1857
1858#[pyclass(
1863 name = "AdExNeuron",
1864 module = "sc_neurocore_engine.sc_neurocore_engine"
1865)]
1866#[derive(Clone)]
1867pub struct PyAdExNeuron {
1868 inner: neuron::AdExNeuron,
1869}
1870
1871#[pymethods]
1872impl PyAdExNeuron {
1873 #[new]
1874 fn new() -> Self {
1875 Self {
1876 inner: neuron::AdExNeuron::new(),
1877 }
1878 }
1879 fn step(&mut self, current: f64) -> i32 {
1880 self.inner.step(current)
1881 }
1882 fn reset(&mut self) {
1883 self.inner.reset();
1884 }
1885 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1886 let d = PyDict::new(py);
1887 d.set_item("v", self.inner.v)?;
1888 d.set_item("w", self.inner.w)?;
1889 Ok(d.into_any().unbind())
1890 }
1891}
1892
1893#[pyclass(
1894 name = "ExpIfNeuron",
1895 module = "sc_neurocore_engine.sc_neurocore_engine"
1896)]
1897#[derive(Clone)]
1898pub struct PyExpIfNeuron {
1899 inner: neuron::ExpIfNeuron,
1900}
1901
1902#[pymethods]
1903impl PyExpIfNeuron {
1904 #[new]
1905 fn new() -> Self {
1906 Self {
1907 inner: neuron::ExpIfNeuron::new(),
1908 }
1909 }
1910 fn step(&mut self, current: f64) -> i32 {
1911 self.inner.step(current)
1912 }
1913 fn reset(&mut self) {
1914 self.inner.reset();
1915 }
1916 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1917 let d = PyDict::new(py);
1918 d.set_item("v", self.inner.v)?;
1919 Ok(d.into_any().unbind())
1920 }
1921}
1922
1923#[pyclass(
1924 name = "LapicqueNeuron",
1925 module = "sc_neurocore_engine.sc_neurocore_engine"
1926)]
1927#[derive(Clone)]
1928pub struct PyLapicqueNeuron {
1929 inner: neuron::LapicqueNeuron,
1930}
1931
1932#[pymethods]
1933impl PyLapicqueNeuron {
1934 #[new]
1935 #[pyo3(signature = (tau=20.0, resistance=1.0, threshold=1.0, dt=1.0))]
1936 fn new(tau: f64, resistance: f64, threshold: f64, dt: f64) -> Self {
1937 Self {
1938 inner: neuron::LapicqueNeuron::new(tau, resistance, threshold, dt),
1939 }
1940 }
1941 fn step(&mut self, current: f64) -> i32 {
1942 self.inner.step(current)
1943 }
1944 fn reset(&mut self) {
1945 self.inner.reset();
1946 }
1947 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
1948 let d = PyDict::new(py);
1949 d.set_item("v", self.inner.v)?;
1950 Ok(d.into_any().unbind())
1951 }
1952}
1953
1954pub fn register_neuron_classes(m: &Bound<'_, PyModule>) -> PyResult<()> {
1959 m.add_class::<PyMultiTimescaleNeuron>()?;
1961 m.add_class::<PyAttentionGatedNeuron>()?;
1962 m.add_class::<PyPredictiveCodingNeuron>()?;
1963 m.add_class::<PySelfReferentialNeuron>()?;
1964 m.add_class::<PyCompositionalBindingNeuron>()?;
1965 m.add_class::<PyDifferentiableSurrogateNeuron>()?;
1966 m.add_class::<PyContinuousAttractorNeuron>()?;
1967 m.add_class::<PyMetaPlasticNeuron>()?;
1968 m.add_class::<PyAdaptiveThresholdMoENeuron>()?;
1970 m.add_class::<PyHybridLinearAttentionNeuron>()?;
1971 m.add_class::<PyQuantumInspiredLIFNeuron>()?;
1972 m.add_class::<PyQuadraticIFNeuron>()?;
1974 m.add_class::<PyThetaNeuron>()?;
1975 m.add_class::<PyPerfectIntegratorNeuron>()?;
1976 m.add_class::<PyGatedLIFNeuron>()?;
1977 m.add_class::<PyNonlinearLIFNeuron>()?;
1978 m.add_class::<PySFANeuron>()?;
1979 m.add_class::<PyMATNeuron>()?;
1980 m.add_class::<PyEscapeRateNeuron>()?;
1981 m.add_class::<PyKLIFNeuron>()?;
1982 m.add_class::<PyInhibitoryLIFNeuron>()?;
1983 m.add_class::<PyComplementaryLIFNeuron>()?;
1984 m.add_class::<PyParametricLIFNeuron>()?;
1985 m.add_class::<PyNonResettingLIFNeuron>()?;
1986 m.add_class::<PyAdaptiveThresholdIFNeuron>()?;
1987 m.add_class::<PySigmaDeltaNeuron>()?;
1988 m.add_class::<PyEnergyLIFNeuron>()?;
1989 m.add_class::<PyIntegerQIFNeuron>()?;
1990 m.add_class::<PyClosedFormContinuousNeuron>()?;
1991 m.add_class::<PyFitzHughNagumoNeuron>()?;
1993 m.add_class::<PyMorrisLecarNeuron>()?;
1994 m.add_class::<PyHindmarshRoseNeuron>()?;
1995 m.add_class::<PyResonateAndFireNeuron>()?;
1996 m.add_class::<PyBalancedResonateAndFireNeuron>()?;
1997 m.add_class::<PyFitzHughRinzelNeuron>()?;
1998 m.add_class::<PyMcKeanNeuron>()?;
1999 m.add_class::<PyTermanWangOscillator>()?;
2000 m.add_class::<PyBendaHerzNeuron>()?;
2001 m.add_class::<PyBrunelWangNeuron>()?;
2002 m.add_class::<PyAlphaNeuron>()?;
2003 m.add_class::<PyCOBALIFNeuron>()?;
2004 m.add_class::<PyGutkinErmentroutNeuron>()?;
2005 m.add_class::<PyWilsonHRNeuron>()?;
2006 m.add_class::<PyChayNeuron>()?;
2007 m.add_class::<PyChayKeizerNeuron>()?;
2008 m.add_class::<PyShermanRinzelKeizerNeuron>()?;
2009 m.add_class::<PyButeraRespiratoryNeuron>()?;
2010 m.add_class::<PyEPropALIFNeuron>()?;
2011 m.add_class::<PySuperSpikeNeuron>()?;
2012 m.add_class::<PyLearnableNeuronModel>()?;
2013 m.add_class::<PyPernarowskiNeuron>()?;
2014 m.add_class::<PyChialvoMapNeuron>()?;
2016 m.add_class::<PyRulkovMapNeuron>()?;
2017 m.add_class::<PyIbarzTanakaMapNeuron>()?;
2018 m.add_class::<PyMedvedevMapNeuron>()?;
2019 m.add_class::<PyCazellesMapNeuron>()?;
2020 m.add_class::<PyCourageNekorkinMapNeuron>()?;
2021 m.add_class::<PyAiharaMapNeuron>()?;
2022 m.add_class::<PyKilincBhattMapNeuron>()?;
2023 m.add_class::<PyErmentroutKopellMapNeuron>()?;
2024 m.add_class::<PyHodgkinHuxleyNeuron>()?;
2026 m.add_class::<PyTraubMilesNeuron>()?;
2027 m.add_class::<PyWangBuzsakiNeuron>()?;
2028 m.add_class::<PyConnorStevensNeuron>()?;
2029 m.add_class::<PyDestexheThalamicNeuron>()?;
2030 m.add_class::<PyHuberBraunNeuron>()?;
2031 m.add_class::<PyGolombFSNeuron>()?;
2032 m.add_class::<PyPospischilNeuron>()?;
2033 m.add_class::<PyMainenSejnowskiNeuron>()?;
2034 m.add_class::<PyDeSchutterPurkinjeNeuron>()?;
2035 m.add_class::<PyPlantR15Neuron>()?;
2036 m.add_class::<PyPrescottNeuron>()?;
2037 m.add_class::<PyMihalasNieburNeuron>()?;
2038 m.add_class::<PyGLIFNeuron>()?;
2039 m.add_class::<PyGIFPopulationNeuron>()?;
2040 m.add_class::<PyAvRonCardiacNeuron>()?;
2041 m.add_class::<PyDurstewitzDopamineNeuron>()?;
2042 m.add_class::<PyHillTononiNeuron>()?;
2043 m.add_class::<PyBertramPhantomBurster>()?;
2044 m.add_class::<PyYamadaNeuron>()?;
2045 m.add_class::<PyPinskyRinzelNeuron>()?;
2047 m.add_class::<PyHayL5PyramidalNeuron>()?;
2048 m.add_class::<PyMarderSTGNeuron>()?;
2049 m.add_class::<PyRallCableNeuron>()?;
2050 m.add_class::<PyBoothRinzelNeuron>()?;
2051 m.add_class::<PyDendrifyNeuron>()?;
2052 m.add_class::<PyTwoCompartmentLIFNeuron>()?;
2053 m.add_class::<PyDendriticNMDANeuron>()?;
2055 m.add_class::<PyMulticompartmentMCNNeuron>()?;
2056 m.add_class::<PyAstrocyteLIFNeuron>()?;
2057 m.add_class::<PyPoissonNeuron>()?;
2059 m.add_class::<PyInhomogeneousPoissonNeuron>()?;
2060 m.add_class::<PyGammaRenewalNeuron>()?;
2061 m.add_class::<PyStochasticIFNeuron>()?;
2062 m.add_class::<PyGalvesLocherbachNeuron>()?;
2063 m.add_class::<PySpikeResponseNeuron>()?;
2064 m.add_class::<PyGLMNeuron>()?;
2065 m.add_class::<PyWilsonCowanUnit>()?;
2066 m.add_class::<PyJansenRitUnit>()?;
2067 m.add_class::<PyWongWangUnit>()?;
2068 m.add_class::<PyErmentroutKopellPopulation>()?;
2069 m.add_class::<PyWendlingNeuron>()?;
2070 m.add_class::<PyLarterBreakspearNeuron>()?;
2071 m.add_class::<PyLoihiCUBANeuron>()?;
2073 m.add_class::<PyLoihi2Neuron>()?;
2074 m.add_class::<PyTrueNorthNeuron>()?;
2075 m.add_class::<PyBrainScaleSAdExNeuron>()?;
2076 m.add_class::<PySpiNNakerLIFNeuron>()?;
2077 m.add_class::<PySpiNNaker2Neuron>()?;
2078 m.add_class::<PyDPINeuron>()?;
2079 m.add_class::<PyAkidaNeuron>()?;
2080 m.add_class::<PyNeuroGridNeuron>()?;
2081 m.add_class::<PyMcCullochPittsNeuron>()?;
2083 m.add_class::<PySigmoidRateNeuron>()?;
2084 m.add_class::<PyThresholdLinearRateNeuron>()?;
2085 m.add_class::<PyAstrocyteModel>()?;
2086 m.add_class::<PyTsodyksMarkramNeuron>()?;
2087 m.add_class::<PyLiquidTimeConstantNeuron>()?;
2088 m.add_class::<PyCompteWMNeuron>()?;
2089 m.add_class::<PySiegertTransferFunction>()?;
2090 m.add_class::<PyFractionalLIFNeuron>()?;
2091 m.add_class::<PyParallelSpikingNeuron>()?;
2092 m.add_class::<PyAmariNeuralField>()?;
2093 m.add_class::<PyLeakyCompeteFireNeuron>()?;
2094 m.add_class::<PyArcaneNeuron>()?;
2095 m.add_class::<PyAdExNeuron>()?;
2097 m.add_class::<PyExpIfNeuron>()?;
2098 m.add_class::<PyLapicqueNeuron>()?;
2099 m.add_class::<PyPVFastSpikingNeuron>()?;
2101 m.add_class::<PySSTNeuron>()?;
2102 m.add_class::<PyVIPNeuron>()?;
2103 m.add_class::<PyChandelierNeuron>()?;
2104 m.add_class::<PyCerebellarBasketNeuron>()?;
2105 m.add_class::<PyMartinottiNeuron>()?;
2106 m.add_class::<PyAlphaMotorNeuron>()?;
2108 m.add_class::<PyGammaMotorNeuron>()?;
2109 m.add_class::<PyUpperMotorNeuron>()?;
2110 m.add_class::<PyRenshawCell>()?;
2111 m.add_class::<PyMotorUnit>()?;
2112 m.add_class::<PyInnerHairCell>()?;
2114 m.add_class::<PyOuterHairCell>()?;
2115 m.add_class::<PyRodPhotoreceptor>()?;
2116 m.add_class::<PyConePhotoreceptor>()?;
2117 m.add_class::<PyRetinalGanglionCell>()?;
2118 m.add_class::<PyMerkelCell>()?;
2119 m.add_class::<PyPacinianCorpuscle>()?;
2120 m.add_class::<PyNociceptor>()?;
2121 m.add_class::<PyOlfactoryReceptorNeuron>()?;
2122 m.add_class::<PyTasteReceptorCell>()?;
2123 m.add_class::<PyDirectionSelectiveRGC>()?;
2125 m.add_class::<PyCochlearHairCell>()?;
2126 m.add_class::<PyGranuleCell>()?;
2128 m.add_class::<PyGolgiCell>()?;
2129 m.add_class::<PyStellateCell>()?;
2130 m.add_class::<PyLugaroCell>()?;
2131 m.add_class::<PyUnipolarBrushCell>()?;
2132 m.add_class::<PyDCNNeuron>()?;
2133 m.add_class::<PyPersistentNaNeuron>()?;
2135 m.add_class::<PyIhNeuron>()?;
2136 m.add_class::<PyTTypeCaNeuron>()?;
2137 m.add_class::<PyATypeKNeuron>()?;
2138 m.add_class::<PyBKNeuron>()?;
2139 m.add_class::<PySKNeuron>()?;
2140 m.add_class::<PyNMDANeuron>()?;
2141 m.add_class::<PyMontbrioMeanField>()?;
2143 m.add_class::<PyBrunelNetwork>()?;
2144 m.add_class::<PyTUMNetwork>()?;
2145 m.add_class::<PyElBoustaniNetwork>()?;
2146 m.add_class::<PyGradedSynapseNeuron>()?;
2148 m.add_class::<PyGapJunctionNeuron>()?;
2149 m.add_class::<PyFHAxon>()?;
2150 m.add_class::<PyNodeOfRanvier>()?;
2151 m.add_class::<PyMyelinatedAxon>()?;
2152 m.add_class::<PyCardiacPurkinjeFibre>()?;
2153 m.add_class::<PySmoothMuscleCell>()?;
2154 m.add_class::<PyEndocrineBetaCell>()?;
2155 m.add_class::<PyTripletStdpSynapse>()?;
2157 m.add_class::<PyShortTermPlasticitySynapse>()?;
2158 m.add_class::<PyDopamineStdpSynapse>()?;
2159 Ok(())
2160}
2161
2162#[pyclass(
2164 name = "LeakyCompeteFireNeuron",
2165 module = "sc_neurocore_engine.sc_neurocore_engine"
2166)]
2167#[derive(Clone)]
2168pub struct PyLeakyCompeteFireNeuron {
2169 inner: neurons::LeakyCompeteFireNeuron,
2170}
2171
2172#[pymethods]
2173impl PyLeakyCompeteFireNeuron {
2174 #[new]
2175 #[pyo3(signature = (n_units=4))]
2176 fn new(n_units: usize) -> Self {
2177 Self {
2178 inner: neurons::LeakyCompeteFireNeuron::new(n_units),
2179 }
2180 }
2181 fn step(&mut self, currents: Vec<f64>) -> Vec<i32> {
2182 self.inner.step(¤ts)
2183 }
2184 fn reset(&mut self) {
2185 self.inner.reset();
2186 }
2187 fn get_state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
2188 let d = PyDict::new(py);
2189 d.set_item("v", self.inner.v.clone())?;
2190 Ok(d.into_any().unbind())
2191 }
2192}