Published
Edited
Sep 18, 2019
2 forks
Insert cell
Insert cell
d3 = require("d3")
Insert cell
quad1Msm = fetch("https://atlas.ripe.net/api/v2/measurements/22861362/latest/?fields=created_timestamp,is_error,error_message,responses.0.response_time,responses.0.abuf.answers.0.data_string,responses.0.abuf.header.return_code&use_keys=1").then(d => d.json())
Insert cell
locsRtts = Object.entries(quad1Msm).map(r => {
let prb = de_prbs.results.find(p => p.id===Number(r[0]));
return {
prb_id: r[0],
rtt: r[1][0][3],
coords: prb && prb.geometry.coordinates,
loc: r[1][0][4]
}
}
).filter(l => l.loc)
Insert cell
totStats = Object.assign({ min: d3.min(locsRtts, d => d.rtt), max: d3.max(locsRtts, d => d.rtt)})
Insert cell
locStats = Array.from(new Set(locsRtts.map(l => l.loc))).map((l,i) => {
let ls = locsRtts.filter(r => r.loc===l)
return {
loc: l,
color: locColor[i % locColor.length],
name: airportCodes.find(lm => lm.iata_code===l) && airportCodes.find(a => a.iata_code===l).municipality,
count: ls.length,
min: d3.min(ls, d => d.rtt),
max: d3.max(ls, d => d.rtt),
median: d3.median(ls, d => d.rtt),
} }).sort((a,b) => b.count - a.count)
Insert cell
Insert cell
de_prbs = fetch("https://atlas.ripe.net/api/v2/probes/archive?status=1,2").then(d => d.json())
Insert cell
Insert cell
Insert cell
map = html`<svg viewBox="0 0 ${width} ${height}" style="display: block;">
<style>
.world { stroke: #eeeeee; stroke-width: 0.5; fill-opacity: 0.5 }
.hop-loc { fill: none; stroke-width: 1.5; stroke: black; }
.probe-loc { stroke-width: 2; stroke: none; fill: white; fill-opacity: 0.8 }
.l-path { fill: none; stroke-width: 2; stroke: lightBlue; }
.kreis { fill-opacity: 0.8; }
</style>
<defs>
<path id="outline" d="${path(outline)}" />
<clipPath id="clip"><use xlink:href="${new URL("#outline", location)}" /></clipPath>
</defs>
<svg><g class="world" clip-path="url(${new URL("#clip", location)})">
<use xlink:href="${new URL("#outline", location)}" fill="#fff" />
${land.features.map(l => `<path class="kreis" d="${path(l.geometry)}" style="fill: ${popKreisColor(l.properties.pop_density)}"></path>`)}
</g></svg>
<g class="probe-loc">
${locsRtts.map(p => { let c = projection(p.coords); return `
<circle stroke-width=0.8 cx="${c[0]}" cy="${c[1]}" r="${circleSize(p.rtt)}" style="fill: ${locStats.find(lc => lc.loc===p.loc).color}; fill-opacity: 0.4; stroke: ${locStats.find(lc => lc.loc===p.loc).color}"/>
<circle class="probe-loc" cx="${c[0]}" cy="${c[1]}" r="1" style="fill: ${locStats.find(lc => lc.loc===p.loc).color}"/>
`})}
</g>
<use xlink:href="${new URL("#outline", location)}" fill="none" stroke="#000" />
</svg>`
Insert cell
circleSize = d3.scaleLinear().domain([80,900]).range([4,15]).interpolate(d3.interpolateNumber)
Insert cell
circleSize(400)
Insert cell
Insert cell
popKreisColor = d3.scaleLinear()
.domain([30, 1380])
.range(["#FFFDF0", "#cccccc"])
.interpolate(d3.interpolateLab);
Insert cell
path = d3.geoPath(projection.scale(6150).rotate([-10,-53]))
Insert cell
// projection = d3.geoEqualEarth()
projection = d3.geoMercator()
Insert cell
height = 1200
Insert cell
world = fetch("https://www-static.ripe.net/static/rnd-ui/openipmap/production/maps/country_deu_adm2.topo.json").then(r => r.json())
Insert cell
outline = ({type: "Sphere"})
Insert cell
land = topojson.feature(world, world.objects["country_deu_adm2"])
Insert cell
topojson = import("topojson-client@3")
Insert cell
airportCodes = d3.csv("https://raw.githubusercontent.com/datasets/airport-codes/master/data/airport-codes.csv").then(d => d)
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