Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
class LIF {
constructor(tau_rc=0.2, v_init=0, tau_ref=0.002, v_th=1){
this.tau_rc = tau_rc;
this.tau_ref = tau_ref;
this.v = v_init;
this.v_th = v_th;
this.output = 0;
this.refractory_time = 0;
}

step(I, t_step) {
this.refractory_time -= t_step; // Subtract the amount of time thhat passed from our refractory time
if(this.refractory_time < 0) { // If we aren't in our refractory period, update the voltage
this.v = this.v * (1 - t_step/this.tau_rc) + (I * t_step / this.tau_rc);
}

if(this.v >= this.v_th) { // Fired
this.refractory_time = this.tau_ref; // Set refractory time

this.output = 1 / t_step; // Fire
this.v = 0; // Reset potential
} else {
this.output = 0; // Don't fire
}
return this.output;
}
}
Insert cell
Insert cell
class ALIF {
constructor(tau_rc=0.2, v_init=0, tau_ref=0.002, v_th=1, tau_inh = 0.05, inc_inh = 1) { // <-- MODIFIED (added ", tau_inh = 0.05, inc_inh = 1")
this.tau_rc = tau_rc;
this.tau_ref = tau_ref;
this.v = v_init;
this.v_th = v_th;
this.output = 0;
this.refractory_time = 0;

// vvv ADDED vvv
this.inh = 0;
this.tau_inh = tau_inh;
this.inc_inh = inc_inh;
// ^^^ ADDED ^^^
}

step(I, t_step) {
this.refractory_time -= t_step; // Subtract the amount of time thhat passed from our refractory time
if(this.refractory_time < 0) { // If we aren't in our refractory period, update the voltage
this.v = this.v * (1 - t_step/this.tau_rc) + (I * t_step / this.tau_rc);
}
// vvv ADDED vvv
this.inh = this.inh * (1 - t_step/this.tau_inh);
// ^^^ ADDED ^^^

if(this.v >= this.v_th + this.inh) { // <-- MODIFIED (added "+ this.inh")
// vvv ADDED vvv
this.inh += this.inc_inh;
// ^^^ ADDED ^^^
this.refractory_time = this.tau_ref; // Set refractory time

this.output = 1 / t_step; // Fire
this.v = 0; // Reset potential
} else {
this.output = 0; // Don't fire
}
}
}
Insert cell
function plotSpikes(inp, tau_inh = 5, inc_inh = 0.2, runtime=0.8) {
const TIME_STEP = 1e-3;
const NUM_STEPS = runtime / TIME_STEP; // Simulate for runtime seconds

const J = () => inp;

const neuron = new ALIF(0.02, 0, 0.2);
neuron.tau_inh = tau_inh;
neuron.inc_inh = inc_inh;
neuron.tau_ref = 1e-2;

const v_history = [ {t: 0, v: neuron.v} ];

let numSpikes = 0;
for(let i = 0; i < NUM_STEPS; i++) {
const j = J((i+1)*TIME_STEP);
neuron.step(j, TIME_STEP);
const out = neuron.output * TIME_STEP;
if(out > 0) {
numSpikes++;
}
v_history.push({t: (i+1)*TIME_STEP, v: neuron.v, vth: neuron.v_th + neuron.inh, j, out });
}
// const plot = Plot.line(v_history, {x: "t", y: "out"}).plot();
const plot = Plot.plot({
y: {
grid: true,
label: 'j'
},
marks: [
Plot.line(v_history, {x: "t", y: "vth", stroke: "blue"}),
Plot.line(v_history, {x: "t", y: "v", stroke: "red"}),
Plot.line(v_history, {x: "t", y: "out", stroke: "black", strokeWidth: 4}),
]
});
return html`<div>${plot.outerHTML}<div><strong>An input of ${inp} produces ${numSpikes} spike${numSpikes===1 ?'' : 's'} in ${runtime} seconds</strong> (${numSpikes / runtime} Hz)</div></div>`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
plotSpikes(1.3, tau_inh, inc_inh, t_short)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function getFiringRate(inp, neuron, runtime=10) {
const TIME_STEP = 1e-3;
const NUM_STEPS = runtime / TIME_STEP; // Simulate for runtime seconds
const J = () => inp;
let numSpikes = 0;
for(let i = 0; i < NUM_STEPS; i++) {
const j = J((i+1)*TIME_STEP);
neuron.step(j, TIME_STEP);
const out = neuron.output;
if(out > 0) {
numSpikes++;
}
}
return numSpikes / runtime;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more