// stimulus_poisson_layer_tripod.mbt — PoissonLayer Stimulus targeting
// TripodHet compartments (:soma, :d1, or :d2).
//
// Mirrors SNNModels.jl's `Stimulus(poisson_layer, E, :glu, :d1,
// conn=(μ, ρ))` pattern. Uses the PoissonLayer parameter from
// v0.10.21 but writes to TripodHet's compartment-specific glu/gaba
// buffer instead of an IF population's glu/gaba.
//
// Wiring:
// for each pre-neuron i:
// draw k ~ Poisson(rate * dt)
// if k > 0:
// for each post-neuron j where weights[j, i] is connected:
// post.glu_d1[j] += weights[j, i] (or :soma / :d2)
// target_compartment ∈ {"soma", "d1", "d2"}
// target_kind ∈ {"glu", "gaba"} (excitatory vs inhibitory)
///|
/// PoissonLayerStimulusTripod — wraps a PoissonLayer + per-(pre, post)
/// sparse weights to deliver Poisson spikes to a specific TripodHet
/// compartment buffer.
pub struct PoissonLayerStimulusTripod {
param : PoissonLayer
post : TripodHet
weights : Array[Float] // row-major [post.N, param.n_sources]
connectivity : Array[Bool] // row-major [post.N, param.n_sources]
target_compartment : String // "soma" | "d1" | "d2"
target_kind : String // "glu" | "gaba"
rng : Xoshiro
}
///|
/// Construct a PoissonLayerStimulusTripod. Draws per-(pre, post)
/// weights at construction: with probability `p_conn` the
/// connection exists, weight ~ Normal(μ, σ) (Fixed if dist=="Fixed").
pub fn PoissonLayerStimulusTripod::new(
param : PoissonLayer,
post : TripodHet,
target_compartment : String,
target_kind : String,
mu : Float,
sigma : Float,
p_conn : Float,
rng : Xoshiro,
) -> PoissonLayerStimulusTripod {
let n_pre = param.n_sources
let n_post = post.n
let weights : Array[Float] = Array::make(n_post * n_pre, 0.0F)
let connectivity : Array[Bool] = Array::make(n_post * n_pre, false)
let use_normal = param.dist == "Normal"
for i in 0.. Array[Float] {
match (s.target_compartment, s.target_kind) {
("soma", "glu") => s.post.glu_s
("soma", _) => s.post.gaba_s
("d1", "glu") => s.post.glu_d1
("d1", _) => s.post.gaba_d1
("d2", "glu") => s.post.glu_d2
("d2", _) => s.post.gaba_d2
_ => s.post.glu_d1
}
}
///|
/// One-step stimulation: draw Poisson for each active source, and
/// if it fires, add the (pre, post) weight to the post-synaptic
/// compartment buffer (glu or gaba, :soma/:d1/:d2).
pub fn stimulate_layer_tripod(
s : PoissonLayerStimulusTripod,
time : Float,
dt : Float,
) -> Unit {
let _ = time
let n_pre = s.param.n_sources
let n_post = s.post.n
let lambda = s.param.rate * dt
let buf = target_buffer_tripod(s)
if lambda <= 0.0F {
return
}
for i in 0.. 0 {
for j in 0..