Published
Edited
Oct 1, 2021
Importers
Insert cell
# Test Results Plot
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

const line = d3.line()
.x(d => x(d[0]))
.y(d => y(d[1]))

let lines = svg.selectAll("path");

const gx = svg.append("g")
.call(xAxis, x);

const gy = svg.append("g")
.call(yAxis, y)

return Object.assign(svg.node(), {
update(data) {
lines = lines
.data(data, d=>d.id)
.join(
enter => enter.append("path")
.attr("stroke-width", "1")
.attr("stroke", "steelblue")
.attr("fill", "none")
.attr("opacity", 0.3)
.attr("d", (d) => line(d.measurement))
.style("mix-blend-mode", "multiply")
)
svg.call(hover, lines);
}
})
}
Insert cell
function hover(svg, path) {
debugger;
if ("ontouchstart" in document) svg
.style("-webkit-tap-highlight-color", "transparent")
.on("touchmove", moved)
.on("touchstart", entered)
.on("touchend", left)
else svg
.on("mousemove", moved)
.on("mouseenter", entered)
.on("mouseleave", left);

const dot = svg.append("g")
.attr("display", "none");

dot.append("circle")
.attr("r", 2.5);

dot.append("text")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("y", -8);

function moved(event) {
event.preventDefault();
const pointer = d3.pointer(event, this);
const xm = x.invert(pointer[0]);
const ym = y.invert(pointer[1]);
debugger;
const i = d3.bisectCenter(d3.range(maxVal), xm);
const s = d3.least(data, d => Math.abs(d.measurement[i][1] - ym));
path.attr("stroke", d => d === s ? "steelblue" : "#ddd")
.attr("opacity", d => d === s ? "1.0" : "0.3")
.filter(d => d === s)
.raise();
dot.attr("transform", `translate(${x(i)},${y(s.measurement[i][1])})`);
dot.select("text").text(`run: ${s.id}`);
}

function entered() {
// debugger;
path.style("mix-blend-mode", null).attr("stroke", "#ddd");
dot.attr("display", null);
}

function left() {
// debugger;
path.style("mix-blend-mode", "multiply");
path.attr("opacity", 0.3).attr("stroke", "steelblue");
dot.attr("display", "none");
}
}
Insert cell
chart.update(randomData)
Insert cell
margin = ({top: 20, right: 30, bottom: 30, left: 40})
Insert cell
maxVal = 300
Insert cell
x = d3.scaleLinear()
.domain([0, maxVal])
.range([margin.left, width - margin.right])
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(randomData.map(run => d3.max(run.measurement, x=>x[1])))])
.range([height - margin.bottom, margin.top])
Insert cell
xAxis = (g, scale = x) => g
.attr("transform", `translate(0, ${height-margin.bottom})`)
.call(d3.axisBottom(scale).ticks(width/80).tickSizeOuter(0))
Insert cell
yAxis = (g, scale = y) => g
.attr("transform", `translate(${margin.left}, 0)`)
.call(d3.axisLeft(scale).ticks(height/40).tickSizeOuter(0))
Insert cell
height = 400
Insert cell
line = randomLine()
Insert cell
data = {
while (true){
let d = [
{
id: 0,
measurement: d3.range(maxVal).map(x=>[x, line(x)])
}
]
yield d;
await Promises.delay(60000)
}
}
Insert cell
randomData = {
var max_id = data.reduce((a,b) => a.id > b.id? a:b).id
while (true){
var line = randomLine()

data.unshift({
id: ++max_id,
measurement: d3.range(maxVal).map(x=>[x, line(x)])
});
yield data;
await Promises.delay(1000);
}
}
Insert cell
function randomLine() {

const good = Math.random() > 0.2? true : false;
const noise_params = [
[Math.random(), 0.01, 10],
[Math.random(), Math.random(), Math.random()],
[Math.random(), Math.random(), Math.random()]
];
return function line(x) {
//noise
var y;
var components = noise_params.map(
(a) => {
var phase = a[0];
var frequency = a[1];
var amplitude = a[2];
return Math.sin(frequency * ((phase * 2 * Math.PI) + x)) * amplitude
})
var amplitudes = [2,1.5,1]
var component_sum = components.map((e,i)=>e*amplitudes[i]).reduce((a,b)=> a+b);

//line
var m = 1 + 0.5 * noise_params[1][0];
var c = 30 * noise_params[1][1];

var ramp = good ? (m*x) + c : c
return ramp + component_sum + Math.random()*10;
}
}
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