eiChart = {
let margin = {top: 0, bottom: 0, left: 120, right: 300, buffer: 50};
let x = d3.scaleLinear().domain([0, maxT]).range([margin.left, width - margin.right]);
let y = d3.scaleLinear().domain([2, -5]).range([margin.top + 30, height - margin.bottom]);
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const nRepeats = 1;
let xAxis = svg.append("g")
.attr("transform", `translate(0,${height - 50})`)
.call(d3.axisBottom(x).ticks(10).tickSizeOuter(0))
svg
.append("g")
.append("text")
.attr("x", margin.left + (width - margin.left - margin.right) / 2)
.attr("y", height - 10)
.attr("font-size", "14px")
.attr("text-anchor", "middle")
.attr("fill", "black")
.text(() => {return "Time (ms)"})
svg
.append("g")
.append("text")
.attr("x", width - (margin.right - margin.buffer - 10)/2 - 10)
.attr("y", height - 10)
.attr("font-size", "14px")
.attr("text-anchor", "middle")
.attr("fill", "black")
.text(() => {return "Interval (ms)"})
svg
.append("text")
.attr("x", 0)
.attr("y", 18)
.attr("text-anchor", "center")
.attr("fill", "black")
.text(() => {return "Spike train"})
svg
.append("text")
.attr("x", 0)
.attr("y", y(0) + 5)
.attr("fill", "grey")
.text(() => {return "0 voltage"})
svg
.append("text")
.attr("x", 0)
.attr("y", y(1) + 5)
.attr("fill", "red")
.text(() => {return "Threshold"})
svg
.append("text")
.attr("x", width - (margin.right - margin.buffer - 10)/ 2 - 10)
.attr("y", height/2 - 60)
.attr("fill", "#69b3a2")
.attr("text-anchor", "middle")
.text(() => {return "Inter spike intervals"})
let [r, u] = lif_neuron_ei(maxT, alpha, beta, excRate, inhRate, constantDrive);
let g = svg.append("g")
.attr("stroke", "black")
.selectAll("g")
.data(r)
.join("g")
.attr("transform", d => `translate(${x(d)})`);
// Create ticks for raster plots
g.append("line")
.attr("y1", 0)
.attr("y2", 20);
// Create line for u(t)
let line = d3.line()
.x(d => x(d.x))
.y(d => y(d.y));
g = svg.append("path")
.datum([{x: 0, y: 0}, {x: maxT, y:0}])
.attr("stroke", "lightgrey")
.attr("d", line)
g = svg.append("path")
.datum([{x: 0, y: 1}, {x: maxT, y:1}])
.attr("stroke", "red")
.attr("d", line)
line = d3.line()
.x((d, i) => x(i))
.y((d, i) => y(d));
let lineData = line(u);
g = svg
.append("path")
.datum(u)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 1)
// Calculate the histogram of spike timing deltas
let deltas = [];
for(var i = 0; i < r.length - 1; i++) {
deltas.push(r[i+1] - r[i]);
}
x = d3.scaleLinear()
.domain([0, 100])
.range([width - margin.right + margin.buffer, width - 10]);
svg.append("g")
.attr("transform", "translate(0," + (height - 50) + ")")
.call(d3.axisBottom(x));
// set the parameters for the histogram
var histogram = d3.histogram()
.value((x) => x) // I need to give the vector of value
.domain(x.domain()) // then the domain of the graphic
.thresholds(x.ticks(70)); // then the numbers of bins
// And apply this function to data to get the bins
var bins = histogram(deltas);
// Y axis: scale and draw:
y = d3.scaleLinear()
.range([0, height / 2]);
y.domain([0, d3.max(bins, function(d) { return d.length; })]); // d3.hist has to be called before the Y axis obviously
//svg.append("g")
// .call(d3.axisLeft(y));
// append the bar rectangles to the svg element
svg.selectAll("rect")
.data(bins)
.enter()
.append("rect")
.attr("x", 1)
.attr("transform", function(d) { return "translate(" + x(d.x0) + "," + (height - 50 - y(d.length)) + ")"; })
.attr("width", function(d) { return x(d.x1) - x(d.x0) -1 ; })
.attr("height", function(d) { return y(d.length); })
.style("fill", "#69b3a2")
return svg.node();
}