Published
Edited
Oct 27, 2020
Insert cell
Insert cell
drawMap(3, {})
Insert cell
Insert cell
Insert cell
Insert cell
import { slider } from '@jashkenas/inputs'
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { range, sum } from '@nuuuwan/list-utils'
Insert cell
import {
drawRegionMap,
drawRegionDorlingCartogram,
REGION_TYPE,
REGION_INDEX
} from '@nuuuwan/sri-lanka-regions'
Insert cell
import { getRandomColor, hsla } from '@nuuuwan/color-utils'
Insert cell
import { getSVG, drawText, drawText2, drawCircle } from '@nuuuwan/svg-utils'
Insert cell
import { addDefaults } from '@nuuuwan/option-utils'
Insert cell
Insert cell
(await getData())[0]
Insert cell
async function getDataByTimeAndDSD() {
const dsdNameToId = Object.assign(
Object.entries(REGION_INDEX[REGION_TYPE.DSD]).reduce(function(
dsdNameToId,
[id, d]
) {
dsdNameToId[d.name] = id;
return dsdNameToId;
},
{}),
{
Sainthamarathu: 'LK-5225',
Walallawita: 'LK-1339',
"K.F.G. & G. Korale": 'LK-2130',
Panduwasnuwara: 'LK-6148',
"N. Palatha Central": 'LK-7115',
"N. Palatha East": 'LK-7133',
"Arachchikattuwa PS": 'LK-6230',
Kantalai: 'LK-5321',
Hildummulla: 'LK-8142',
"Dehiwala-Mount Lavinia": 'LK-1130',
Hanwella: 'LK-1115',
Ambalanthota: 'LK-3315',
"Valikamam East": 'LK-4118',
"Valikamam North": 'LK-4112',
"Valikamam South": 'LK-4115',
"Valikamam South-West": 'LK-4109',
"Valikamam West": 'LK-4106',
"Thenmaradchy (Chavakachcheri)": 'LK-4130',
"Vadamaradchi South-West": 'LK-4121',
"Vadamaradchy North": 'LK-4127'
}
);

const data = await getData();

const dataByTimeAndDSD = data.reduce(function(dataByTimeAndDSD, d) {
const ut = getUnixTimeFromDateStr(d.ds);
const dsdName = d.polygon_name;
const dsdID = dsdNameToId[dsdName];
if (!dataByTimeAndDSD[ut]) {
dataByTimeAndDSD[ut] = {};
}
if (!dataByTimeAndDSD[ut][dsdID]) {
dataByTimeAndDSD[ut][dsdID] = parseFloat(
d.all_day_ratio_single_tile_users
);
}
return dataByTimeAndDSD;
}, {});
return Object.entries(dataByTimeAndDSD)
.map(function([ts, dataForTimeByDSD]) {
return Object({
ut: parseInt(ts),
dataByDSD: Object.entries(dataForTimeByDSD)
.map(function([dsdID, p]) {
return Object({ dsdID, p });
})
.sort((a, b) => a.dsdID.localeCompare(b.dsdID))
});
})
.sort((a, b) => b.ut - a.ut);
}
Insert cell
DATA_BY_TIME_AND_DSD = await getDataByTimeAndDSD()
Insert cell
MAX_DAYS_AGO = DATA_BY_TIME_AND_DSD.length
Insert cell
Insert cell
Insert cell
function drawMap(days_ago, options = {}) {
const dataByTimeAndDSD = DATA_BY_TIME_AND_DSD;
const latestDataByDSD = dataByTimeAndDSD[days_ago];
if (!latestDataByDSD) {
return null;
}
const ut = latestDataByDSD.ut;
const dataByDSD = latestDataByDSD.dataByDSD;
const dsdToP = dataByDSD.reduce(function(dsdToP, d) {
dsdToP[d.dsdID] = d.p;
return dsdToP;
}, {});

options = addDefaults(options, {
width: 600,
height: 1000,
legendWidth: 100,
maxRadius: 10
});

function pToColor(p) {
if (p !== undefined) {
let h = (1 - p * 2) * 240;
if (h < 0) {
h = 0;
}
return hsla(h, 100, 50, 1.0);
}
return '#eee';
}

options = addDefaults(options, {
fRegionInfoToColor: function(regionInfo) {
return pToColor(dsdToP[regionInfo.regionID]);
},
caption: `% of Population that stayed within 600m of home on ${formatDate(
ut
)}`,
fAppendLabel: function(regionInfo, svg, x, y, r) {},
fAppendLegend: function(svg) {
const LEGEND_ITEM_HEIGHT = 20;
const xOffset = options.width - options.legendWidth;

[
[0.1, '10%'],
['0.2', '20%'],
[0.3, '30%'],
[0.4, '40%'],
[0.5, '≥ 50%'],
[undefined, 'No Data']
].map(function([p, label], i) {
drawText2(
svg,
[xOffset + LEGEND_ITEM_HEIGHT, (i + 2) * LEGEND_ITEM_HEIGHT],
label,
{ textAnchor: 'start' }
);
drawCircle(
svg,
xOffset,
(i + 2) * LEGEND_ITEM_HEIGHT,
LEGEND_ITEM_HEIGHT / 3,
{ fill: pToColor(p), stroke: 'gray' }
);
});
}
});

return drawRegionMap('LK', REGION_TYPE.DSD, options);
}
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