Published
Edited
May 18, 2020
Insert cell
Insert cell
Insert cell
Insert cell
viewof prb_id = number({value: "33782", title: "Selected Probe", submit: true})
Insert cell
viewof months = number({value: 12, title: "number of months back", submit: true})
Insert cell
//prb_id = 33782;
Insert cell
start = stop.minus({months: months || 12})
Insert cell
stop = luxon.DateTime.utc();
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3TimeDays = discoIntervals
.reduce((acc, e, i) => {
const d = acc.find(de => luxon.DateTime.fromJSDate(de.date).equals(e.from.startOf('day')));
if (d) {
d.details.push({ date: e.from.toJSDate(), toDate: e.to.toJSDate(), value: e.duration, name: e.event });
}
else {
acc.push({ date: e.from.startOf('day').toJSDate(), details: [{ date: e.from.toJSDate(), toDate: e.to.toJSDate(), value: e.duration, name: e.event }]});
}
return acc
}, [])
.map(de => (
{ ...de, init: function () {
this.total = this.details.reduce(function (prev, e) {
return prev + (e.name === "connect" ? e.value : 0);
}, 0);
return this;
}
}.init()
)
).sort((a,b) => a.date > b.date);
Insert cell
discoIntervals = apiRawDiscos
.sort((p1,p2) => p1.timestamp > p2.timestamp ? 1 : -1)
.map(p => ({ type: p.event, date: luxon.DateTime.fromSeconds(p.timestamp) }))
.reduce((acc, e, i, discos) => {
const from = e.date;
const to = discos[i+1] && discos[i+1].date;
if (!to) { return acc ;};
if (from.startOf('day').equals(to.startOf('day'))) {
acc.push({
from: from,
to: to,
unqiueEvent: `${e.type} ${i}-_`,
event: e.type,
i:i,
duration: luxon.Interval.fromDateTimes(from, to).toDuration().as("seconds")
})
} else {
const numDays = luxon.Interval.fromDateTimes(from, to).count("days") - 1;
acc.push({
from: from,
to: from.endOf("day"),
unqiueEvent: `${e.type} ${i}-from`,
event: e.type,
numDays: numDays,
duration: luxon.Interval.fromDateTimes(from, from.endOf("day")).toDuration().as("seconds")
})
for (const ii in [...Array(numDays).keys()]) {
const lowerBound = from.startOf("day").plus({days: (Number(ii) + 1)});
const upperBound = from.endOf("day").plus({days: (Number(ii) + 1)});

if (ii < (numDays - 1)) {
acc.push({
from: lowerBound,
to: upperBound,
numDays: numDays,
uniqueEvent: `${e.type} ${i}-${ii}-intermediate`,
event: e.type,
duration: luxon.Interval.fromDateTimes(lowerBound, upperBound).toDuration().as("seconds")
});
}
else {
acc.push({
from: lowerBound,
to: to,
numDays: numDays,
unqiueEvent: `${e.type} ${i}-${ii}-to`,
event: e.type,
duration: luxon.Interval.fromDateTimes(lowerBound, to).toDuration().as("seconds")
});
}
};
}
return acc
}, [])
Insert cell
apiRawDiscos = await fetch(`https://atlas.ripe.net/api/v2/measurements/7000/results/?stop=${Math.floor(stop.toMillis() / 1000)}&start=${Math.floor(start.toMillis() / 1000)}&probe_ids=${prb_id}&format=json`).then(d => d.json());
Insert cell
Insert cell
Insert cell

settings = calendarHeatmap.settings = ({
gutter: 0.05,
item_gutter: 0.15,
width: 1000,
height: 200,
item_size: 10,
label_padding: 40,
max_block_height: 20,
transition_duration: 500,
tooltip_width: 250,
tooltip_padding: 15,
futureColor:'#8c2d04',
pastColor:'#0bccea',
todayColor:'#3182bd'
});
Insert cell
Insert cell
Insert cell
moment = require("https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js");
Insert cell
d3 = require("https://d3js.org/d3.v5.min.js")
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
luxon = import("luxon");
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