Public
Edited
Nov 26, 2023
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dates = Array.from(groupedByDate.keys())
Insert cell
minDateTime = d3.min(parsedData, (d) => d.dateTime)
Insert cell
maxDateTime = new Date(minDateTime.getTime() + 1000 * 60 * 60 * 24) // basically 24h later
Insert cell
Insert cell
data = Array.from(d3.group(parsedData, (d) => d.state))
Insert cell
groupedData = {
const a = parsedData
.filter((d) => d.state === 0)
.map((d) => ({ ...d, v: d.v1 }));
const b = parsedData
.filter((d) => d.state === 1)
.map((d) => ({ ...d, v: d.v1 }));
const c = parsedData
.filter((d) => d.state === 0)
.map((d) => ({ ...d, v: d.v2 }));
const d = parsedData
.filter((d) => d.state === 1)
.map((d) => ({ ...d, v: d.v2 }));
return [
[{ state: 0, target: "v1", id: "0-v1", idx: 0 }, a],
[{ state: 0, target: "v2", id: "0-v2", idx: 1 }, b],
[{ state: 1, target: "v1", id: "1-v1", idx: 2 }, c],
[{ state: 1, target: "v2", id: "1-v2", idx: 3 }, d]
];
}
Insert cell
Insert cell
Insert cell
chart = {
const w = d3.min([width, 600]);
const h = w;
const margin = 150;
const innerRadius = w / 5;
const outerRadius = w / 2 - margin;

const xUtc = d3
.scaleUtc()
.domain([minDateTime, maxDateTime])
.range([0, Math.PI * 2]);
const y = d3
.scaleRadial()
.domain([
d3.min(processedData, (d) => d.min),
d3.max(processedData, (d) => d.max)
])
.range([innerRadius, outerRadius]);

const positiveFill = d3
.scaleSequential(d3.interpolateRdBu)
.domain(d3.extent(processedData, (d) => d.diff));

const arc = d3
.arc()
.innerRadius((d) => y(d.min))
.outerRadius((d) => y(d.max))
.startAngle((d) => xUtc(d.dateTime))
.endAngle((d) => xUtc(d.nextDateTime))
.padAngle(0.01)
.padRadius(innerRadius);

const line = d3
.lineRadial()
.curve(d3.curveLinearClosed)
.angle((d) => xUtc(d.dateTime))
.radius((d) => y(d.v));

const svg = d3
.create("svg")
.attr("viewBox", [-w / 2, -h / 2, w, h])
.attr("width", w)
.attr("height", h)
.attr("style", "max-width: 100%; height: auto;")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round");

// svg.append('g').selectAll().data(x.ticks()).join('g').

const render = (_state) => {
console.log("rendering state", _state);
let dataFiltered = data;
if (_state !== "both")
dataFiltered = data.filter(([k, v]) => k === Number(_state));
let dataFill = processedData.filter(
(d) => _state === "both" || d.state === Number(_state)
);
let dataLine = groupedData.filter(
([k]) => _state === "both" || k.state === Number(_state)
);
const fills = svg
.selectAll("path.fill")
.data(dataFill)
.join(
(enter) =>
enter
.append("path")
.attr("class", "fill")
.attr("fill", (d) => (d.diff > 0 ? "blue" : "red"))
.attr("opacity", 0.5)
.attr("d", arc),
(update) =>
update
.attr("fill", (d) => (d.diff > 0 ? "blue" : "red"))
.attr("d", arc),
(exit) => exit.remove()
);
const lines = svg
.selectAll("path.line")
.data(dataLine, ([k, v]) => k.id)
.join(
(enter) =>
enter
.append("path")
.attr("class", "line")
.attr("opacity", 0.5)
.attr("stroke", ([k]) => d3.schemeCategory10[k.idx])
.attr("stroke-width", "1px")
.attr("fill", "none")
.attr("data-id", ([k]) => k.id)
.attr("d", ([k, v]) => line(v)),
(update) =>
update
.attr("stroke", ([k]) => d3.schemeCategory10[k.idx])
.attr("d", ([k, v]) => line(v)),
(exit) => exit.remove()
);
};
render(mutable stateNow);
return Object.assign(svg.node(), { render });
}
Insert cell
{
const xUtc = d3
.scaleUtc()
.domain([minDateTime, maxDateTime])
.range([0, Math.PI * 2]);
const y = d3
.scaleRadial()
.domain([
d3.min(processedData, (d) => d.min),
d3.max(processedData, (d) => d.max)
])
.range([0, 100]);

const positiveFill = d3
.scaleSequential(d3.interpolateRdBu)
.domain(d3.extent(processedData, (d) => d.diff));

const line = d3
.lineRadial()
.curve(d3.curveLinearClosed)
.angle((d) => xUtc(d.dateTime))
.radius((d) => y(d.v));

return line(groupedData[0][1]);
}
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