Published
Edited
Mar 14, 2020
Fork of Tree of Life
2 forks
33 stars
Andy's Walgreens COVID-19 Tracker TrackerBelgium Vaccination Tracker - Progress of the vaccination campaignVaccination against covid-19 in France500,000 COVID-19 DeathsCovid-19 vaccinations: BubblesTime Spiral with a COVID DemoCOVID MasksGrid Cartogram component with live COVID demos (plus a MapEditor)The US COVID SyringeCOVID-19 DKCOVID-19 World Community Mobility Report by GoogleCOVID 19Chicago COVID ZIP SparklinesThe COVID Syringeభారతదేశంలో కోవిడ్-19SVG DataGrid with many features and a live COVID Dashboard demoThe spread of Covid-19 in New MexicoHeatmap of COVID-19 Confirmed Cases by Age over Time in JapanThe CoViD-19 ReportCovid19 WorldwideMassachusetts Coronavirus Cases by TownChoropleth map about Covid19 in FranceWell ordered coronavirus heatmaps for US and the WorldCOVID-19 Racial/Ethnic Mortality AnalysisProPublica's COVID Arrow MapClustering students to slow virus spread inside schoolsCOVID-19 in the USAWho Is Wearing Masks in the U.S.Covid-19 Viz RoundupCoronavirus StatsThe Covid-19 Crisis' Impact on the Number of US Flight PassengersCOVID-19 Daily New CasesCOVID-19 CasesCOVID–19 Bubble Chart with D3 RenderCoronavirus Deaths by Race / EthnicityHow many SARS-CoV-2 tests are we running in the U.S.?COVID-19 Onset vs. ConfirmationPeaks in confirmed daily deaths due to COVID-19 so farCOVID-19 in the U.S.Recreating John Burn-Murdoch’s Coronavirus trackerTracking COVID-19 Cases in VietnamCOVID-19 in NYC by Zip Code & IncomeVisualizing the Network Meta-Analysis of Covid-19 Studiesxkcd COVID-19 spread sketchCOVID-19's deaths in EuropeCovid-19 (corona virus) deaths per 1,000,000 peopleCOVID-19 Bubble map or spike map? (Twitter debate)A Timeline of Shelter-in-PlaceWhere’s that $2 trillion going?Estimating SARS-COV-2 infectionsCODAVIM - CountySARS-CoV-2 Epi CurveCOVID-19 Curves (U.S.)COVID-19 Cases by CountyCOVID-19 world growth rateA graphical experiment of exponential spreadCOVID-19 by US countyCOVID-19 Confirmed vs. New cases"Live" Logistic Coronavirus Death CounterInfografiche: COVID-19 in ItaliaCoronavirus (COVID-19) GlobeBar Chart Race, COVID-19 outbreak Worldwide to 24th March 2020US Coronavirus testing by statesUnited States Coronavirus Daily Cases Map (COVID-19)COVID-19 Numbers by State, Side by SideRecreating NYT U.S. Cases MapCOVID-19 in Washington stateCOVID-19 outbreak in maps and chartsCOVID-19 Spreading trendsRestaurants during COVID-19 social distancingCOVID-19 Countries Trajectories in 3DStates that aren't reporting aspects of their COVID-19 testing processNextstrain Prototyping - Issue 817Reviewing COVID-19 SARS-CoV-2 preprints from medRxiv and bioRxivCoronavirus worldwide evolutionCovid-19 New Cases PunchcardCovid-19 cases per district in Germany.COVID-19 Cases, Deaths, and Recoveries (Select Country)Quarantine NowEmissions in WuhanCOVID-19(nCOV-2019) Outbreak in S.KoreaMovement of population between provinces in 2019-nCoVComparing COVID-19 GrowthCovid-19 derived chartCoronavirus Trends (COVID-19)Netherlands Coronavirus Daily Cases Map (COVID-19)Map and timeline of Corona outbreak
SARS-CoV-2 Phylogenetic Tree
Coronavirus data (covid-19)Visualizing the Logic of Exponential Viral SpreadItaly Coronavirus Daily Cases Map (COVID-19)COVID-19 Fatality Rate
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const root = d3.hierarchy(data, d => d.branchset)
.sum(d => d.branchset ? 0 : 1)
.sort((a, b) => (a.value - b.value) || d3.ascending(a.data.length, b.data.length));

cluster(root);
setRadius(root, root.data.length = 0, innerRadius / maxLength(root));

const svg = d3.create("svg")
.attr("viewBox", [-outerRadius, -outerRadius, width, width])
.attr("font-family", "sans-serif")
.attr("font-size", 10);

svg.append("style").text(`

.link--active {
stroke: #000 !important;
stroke-width: 1.5px;
}

.link-extension--active {
stroke-opacity: .6;
}

.label--active {
font-weight: bold;
}

`);

const linkExtension = svg.append("g")
.attr("fill", "none")
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.25)
.selectAll("path")
.data(root.links().filter(d => !d.target.children))
.join("path")
.each(function(d) { d.target.linkExtensionNode = this; })
.attr("d", linkExtensionConstant);

const link = svg.append("g")
.attr("fill", "none")
.attr("stroke", "currentColor")
.selectAll("path")
.data(root.links())
.join("path")
.each(function(d) { d.target.linkNode = this; })
.attr("d", linkConstant)
.attr("stroke", d => color(name(d.target)));

svg.append("g")
.selectAll("text")
.data(root.leaves())
.join("text")
.attr("dy", "0.31em")
.attr("transform", d => `rotate(${d.x - 90}) translate(${innerRadius + 4},0)${d.x < 180 ? "" : " rotate(180)"}`)
.attr("text-anchor", d => d.x < 180 ? "start" : "end")
.attr("fill", d => color(name(d)))
.text(d => name(d) || "N/A")
.on("mouseover", mouseovered(true))
.on("mouseout", mouseovered(false))
.append("title")
.text(d => d.data.name.replace(/_/g, " "));

function update(checked) {
const t = d3.transition().duration(750);
linkExtension.transition(t).attr("d", checked ? linkExtensionVariable : linkExtensionConstant);
link.transition(t).attr("d", checked ? linkVariable : linkConstant);
}

function mouseovered(active) {
return function(d) {
d3.select(this).classed("label--active", active);
d3.select(d.linkExtensionNode).classed("link-extension--active", active).raise();
do d3.select(d.linkNode).classed("link--active", active).raise();
while (d = d.parent);
};
}

return Object.assign(svg.node(), {update});
}
Insert cell
chart.update(showLength)
Insert cell
cluster = d3.cluster()
.size([360, innerRadius])
.separation((a, b) => 1)
Insert cell
function name(d) {
if (d.height === 0) {
const parts = d.data.name.split("_");
for (let i = 0; i < parts.length; ++i) {
if (/^\d{4}(?:-\d{2}(?:-\d{2})?)?$/.test(parts[i])) {
return parts[i + 1]
.replace(/-.*/, "")
.replace(/([a-z])([A-Z])/, (_, a, b) => [a, b].join(" "));
}
}
}
}
Insert cell
color = d3.scaleOrdinal()
.domain(["United States", "China"])
.range(d3.schemeTableau10)
.unknown(null)
Insert cell
// Compute the maximum cumulative length of any node in the tree.
function maxLength(d) {
return d.data.length + (d.children ? d3.max(d.children, maxLength) : 0);
}
Insert cell
// Set the radius of each node by recursively summing and scaling the distance from the root.
function setRadius(d, y0, k) {
d.radius = (y0 += d.data.length) * k;
if (d.children) d.children.forEach(d => setRadius(d, y0, k));
}
Insert cell
function linkVariable(d) {
return linkStep(d.source.x, d.source.radius, d.target.x, d.target.radius);
}
Insert cell
function linkConstant(d) {
return linkStep(d.source.x, d.source.y, d.target.x, d.target.y);
}
Insert cell
function linkExtensionVariable(d) {
return linkStep(d.target.x, d.target.radius, d.target.x, innerRadius);
}
Insert cell
function linkExtensionConstant(d) {
return linkStep(d.target.x, d.target.y, d.target.x, innerRadius);
}
Insert cell
function linkStep(startAngle, startRadius, endAngle, endRadius) {
const c0 = Math.cos(startAngle = (startAngle - 90) / 180 * Math.PI);
const s0 = Math.sin(startAngle);
const c1 = Math.cos(endAngle = (endAngle - 90) / 180 * Math.PI);
const s1 = Math.sin(endAngle);
return "M" + startRadius * c0 + "," + startRadius * s0
+ (endAngle === startAngle ? "" : "A" + startRadius + "," + startRadius + " 0 0 " + (endAngle > startAngle ? 1 : 0) + " " + startRadius * c1 + "," + startRadius * s1)
+ "L" + endRadius * c1 + "," + endRadius * s1;
}
Insert cell
data = parseNewick(await FileAttachment("ncov-2019.txt").text())
Insert cell
width = 954
Insert cell
outerRadius = width / 2
Insert cell
innerRadius = outerRadius - 80
Insert cell
// https://github.com/jasondavies/newick.js
function parseNewick(a){for(var e=[],r={},s=a.split(/\s*(;|\(|\)|,|:)\s*/),t=0;t<s.length;t++){var n=s[t];switch(n){case"(":var c={};r.branchset=[c],e.push(r),r=c;break;case",":var c={};e[e.length-1].branchset.push(c),r=c;break;case")":r=e.pop();break;case":":break;default:var h=s[t-1];")"==h||"("==h||","==h?r.name=n:":"==h&&(r.length=parseFloat(n))}}return r}
Insert cell
d3 = require("d3@5")
Insert cell
import {swatches} from "@d3/color-legend"
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