Public
Edited
Feb 3, 2024
1 star
Insert cell
Insert cell
Insert cell
Object.values(birds_hourly[22]).slice(0,24)
Insert cell
Insert cell
birds_hourly
Insert cell
Insert cell
stacked = stack(birds)
Insert cell
total_by_bird = stacked.reduce((a, b) => ({...a, [b.name]: b.height.reduce((a,b) => a + b)}), {});
Insert cell
sorted = stack(birds.sort((a, b) => total_by_bird[b['Com_Name']] - total_by_bird[a['Com_Name']]));
Insert cell
songbirds = stack([birds[9], birds[7], birds[10], birds[11], birds[13], birds[16], birds[17], birds[19], birds[22], birds[23]])
Insert cell
// to_plot = sorted;
// to_plot = stack([birds[5], birds[15]]);

// NARRATIVE
// to_plot = stack([birds[0]])
// to_plot = stack([birds[0], birds[5]])
// to_plot = stack([birds[0], birds[5], birds[14]])
// to_plot = stack([birds[0], birds[5], birds[14], birds[20]])
// to_plot = stack([birds[0], birds[5], birds[14], birds[6], birds[3]])
// to_plot = stack([birds[0], birds[5], birds[14], birds[3], birds[1]])
// to_plot = stack([birds[2]])
// to_plot = stack([birds[4], birds[2]])
// to_plot = stack([birds[4], birds[21]])
// to_plot = stack([birds[7], birds[10], birds[13], birds[16], birds[19]])
// to_plot = stack([birds[7], birds[10], birds[11], birds[13], birds[16], birds[17], birds[19], birds[23]])
// to_plot = stack([birds[9], birds[7], birds[10], birds[11], birds[13], birds[16], birds[17], birds[19], birds[23]])
to_plot = stack(birds)
Insert cell
test = stack(birds).map(v => v.name)
Insert cell
max_value = to_plot[to_plot.length-1].high.reduce((a, b) => b > a ? b : a)
Insert cell
width = 928
Insert cell
height = width
Insert cell
margin = 10
Insert cell
innerRadius = 150
Insert cell
outerRadius = width / 2 - margin;
Insert cell
y = d3
.scaleRadial()
// .domain([d3.min(data, d => d.minmin), d3.max(data, d => d.maxmax)])
.domain([0, max_value])
.range([innerRadius, outerRadius]);
Insert cell
colorScale = d3.scaleOrdinal(d3.schemeTableau10);
Insert cell
TIME_STEPS = 96;
Insert cell
viewof offset = Inputs.range([-Math.PI, Math.PI], {value: 0, step: Math.PI/100, label: "Offset"})
Insert cell
x = d3
.scaleLinear()
.domain([0, TIME_STEPS])
.range([Math.PI + offset, 3 * Math.PI + offset]);
Insert cell
chart2 = {
const BIRD_COUNT = 25;

const line = d3
.lineRadial()
.curve(d3.curveCatmullRomClosed)
.angle((d, i) => {
return x(i);
});

const area = d3
.areaRadial()
.curve(d3.curveCatmullRomClosed)
.angle((d, i) => x(i));

function argMax(array) {
return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
}

const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-width / 2, -height / 2, width, height])
.attr("style", "width: 100%; height: auto; font: 10px sans-serif;")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round");

var bird_groups = svg.append("g").attr("id", "bird_paths")
.selectAll("g")
.data(to_plot)
.join("g")
.attr("id", d => d.name);

var bird_group_paths = bird_groups
.append("path")
.attr("id", d => "birdpath" + d.name)
.attr("fill", d => colorScale(d.name))
.attr("stroke-width", 1.5)
.attr(
"d", d => {
return area
.innerRadius(v => y(v[0]))
.outerRadius(v => y(v[1]))
(d3.transpose([d.low, d.high]));
});

var text_groups = svg.append("g").attr("id", "bird_labels")
.selectAll("g")
.data(to_plot)
.join("g")
.attr("id", d => "label" + d.name);

text_groups.append("rect")
.attr("x", d => y(d.low[argMax(d.height)] * 0.7 + d.high[argMax(d.height)] * 0.3) * Math.sin(x(argMax(d.height))) - (d.name.length * 5.8 + 15)/2)
.attr("y", d => -y(d.low[argMax(d.height)] * 0.7 + d.high[argMax(d.height)] * 0.3) * Math.cos(x(argMax(d.height))) - 11 + (d.name == "European Robin" ? 20 : 0))
// .attr("x", d => x(48) - d.name.length * 4)
// .attr("y", d => -y((d.low[48] + d.high[48])/2) - 11)
.attr("width", d=> d.name.length * 5.8 + 15)
.attr("height", 14)
.attr("ry", 7)
.attr("rx", 7)
// .style("fill", "white")
.style("fill", d => d3.color(colorScale(d.name)).brighter(1))
.style("opacity", 0.5);

var text_group_labels = text_groups.append("text")
// .attr("x", x(48))
// .attr("y", d => -y((d.low[48] + d.high[48])/2))
.attr("x", d => y(d.low[argMax(d.height)] * 0.7 + d.high[argMax(d.height)] * 0.3) * Math.sin(x(argMax(d.height))))
.attr("y", d => -y(d.low[argMax(d.height)] * 0.7 + d.high[argMax(d.height)] * 0.3) * Math.cos(x(argMax(d.height))))
.attr("dy", d => d.name == "European Robin" ? 20 : 0)
.text(d => d.name)
.attr("text-anchor", "middle")
.attr("font-size", 12)
.style("opacity", 1.0);


const grid = svg.append("g");

var grids = [];

for (var i = 0; i < 10; i += 1) {
grids[i] = i * 50;
}

var gridEls = grid.selectAll("circle").data(grids).enter().append("circle").attr("cx", 0)
.attr("cy", 0)
.attr("r", d => y(d))
.style("fill", "none")
.style("stroke", "#ccc")
.attr("stroke-opacity", 0.5);

svg
.append("g")
.selectAll()
.data([0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88])
.join("g")
.each((d, i) => {
console.log(d, i);
return true;
})
.call((g) =>
g
.append("path")
.attr("stroke", "#ccc")
.attr("stroke-opacity", 0.5)
.attr(
"d",
(d) => `
M${d3.pointRadial(x(d), innerRadius)}
L${d3.pointRadial(x(d), width*1.42)}
`
)
)
.call((g) =>
g
.append("path")
.attr("id", (d) => "text" + d)
.datum((d) => [d, d - 25])
.attr("fill", "none")
.attr(
"d",
([a, b]) => `
M${d3.pointRadial(x(a), innerRadius)}
A${innerRadius},${innerRadius} 0,0,1 ${d3.pointRadial(
x(b),
innerRadius
)}
`
)
)
.call((g) =>
g
.append("text")
.append("textPath")
.attr("startOffset", 6)
.attr("xlink:href", (d) => "#text" + d)
.text((d) => d / 4 + ":00")
);
return svg.node();
}
Insert cell
Insert cell
birds.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
max_max = to_plot.map(v => v.height.reduce((a,b) => b > a ? b : a)).reduce((a,b) => b > a ? b : a)
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