// stimulus_current.mbt — port of SNNModels.jl/src/stimuli/current.jl
//
// A CurrentStimulus injects a current (constant or time-varying) into
// a target population's `I` array each step. Matches Julia's
// `CurrentStimulus(post; param=CurrentNoise(...))` and
// `CurrentStimulus(post, :I; param=CurrentFixed(I_base))` patterns.
//
// Two variants are provided:
// - `CurrentStimulusIF` — bound to an IF population. Uses the IF's
// `i` field. The compose layer dispatches via the `CurrentIF_` variant.
// - `CurrentStimulusArray` — bound to a raw `Array[Float]` (the
// `i` array of any population). This lets AdEx, IZ, HH, Poisson
// etc. share the same current-injection logic without needing a
// dedicated struct per population type. The compose layer
// dispatches via the `CurrentArr_` variant.
///|
/// CurrentStimulus — bound to an IF population. Injects current into
/// the IF's `i` array each step. With `active=true` and `noise_sigma=0`,
/// sets `i[i] = i_base` for every neuron. With `noise_sigma > 0`,
/// adds `N(0, noise_sigma)` noise per step.
pub struct CurrentStimulusIF {
mut i_base : Float
active : Array[Bool]
pop : IF
noise_sigma : Float
rng : Xoshiro
}
///|
/// Construct a constant-current stimulus targeting an IF population.
pub fn CurrentStimulusIF::new(
pop : IF,
i_base : Float,
rng : Xoshiro,
noise_sigma? : Float = 0.0F,
) -> CurrentStimulusIF {
{ i_base, active: [true], pop, noise_sigma, rng }
}
///|
/// Disable / enable the stimulus.
pub fn CurrentStimulusIF::set_active(s : CurrentStimulusIF, v : Bool) -> Unit {
s.active[0] = v
}
///|
/// Update the baseline current at runtime.
pub fn CurrentStimulusIF::set_i_base(s : CurrentStimulusIF, v : Float) -> Unit {
s.i_base = v
}
///|
/// Apply the current stimulus for one step.
pub fn stimulate_current_if(s : CurrentStimulusIF) -> Unit {
if !s.active[0] {
return
}
let pop = s.pop
let n = pop.n
if s.noise_sigma <= 0.0F {
for i in 0.. CurrentStimulusArray {
{ i_base, active: [true], i, n, noise_sigma, rng }
}
///|
/// Disable / enable the array-targeted stimulus.
pub fn CurrentStimulusArray::set_active(
s : CurrentStimulusArray,
v : Bool,
) -> Unit {
s.active[0] = v
}
///|
/// Update the baseline current at runtime.
pub fn CurrentStimulusArray::set_i_base(
s : CurrentStimulusArray,
v : Float,
) -> Unit {
s.i_base = v
}
///|
/// Apply the array-targeted current stimulus for one step.
pub fn stimulate_current_array(s : CurrentStimulusArray) -> Unit {
if !s.active[0] {
return
}
if s.noise_sigma <= 0.0F {
for k in 0..