Public
Edited
Jan 5, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
meta = fetch(
`https://api.targomo.com/statistics/collection/meta/71?apiKey=${targomoKey()}`
).then((response) => response.json())
Insert cell
Insert cell
stats = Object.values(meta.stats)
.filter((d) => [0, 5, 6, 22, 44].includes(d.statistic_id))
.map((d) => ({
key: `w${d.statistic_id}`,
value: d.statistic_id,
label: d.descriptions.en
}))
Insert cell
Insert cell
Insert cell
serviceUrl = "https://api.targomo.com/westcentraleurope"
Insert cell
Insert cell
Insert cell
mgConfig = ({
multiGraphLayerGeometryDetailPerTile: 6,
multiGraphLayerMinGeometryDetailLevel: 5,
multiGraphLayerMaxGeometryDetailLevel: 25,
multiGraphLayerGeometryDetailLevel: 25,
multiGraphAggregationType: "none",
multiGraphSerializationFormat: "mvt",
multiGraphSerializationMaxGeometryCount: 100000,
multiGraphReferencedStatisticIds: stats.reduce((acc, cur) => {
// map each statistic id to a reference key
acc[cur.key] = cur.value;
return acc;
}, {}),
multiGraphAggregationInputParameters: {
reachability: {}, // this includes reachability in the pipeline
// add each key from multiGraphReferencedStatisticIds, with an empty object
...stats.reduce((acc, cur) => {
acc[cur.key] = {};
return acc;
}, {})
},
multiGraphDomainType: "statistic_geometry", // use statistics data as a routing aggregation
travelType: "walk", // or bike|car|transit
forceRecalculate: false,
maxEdgeWeight,
multiGraphLayerType: "identity",
multiGraphDomainStatisticCollectionId: "71", // stats collection 71 (Spain)
multiGraphLayerUnboundedStatistics: true, // include unreached cells as well (and use unreached for breakpoints)
serviceUrl,
serviceKey: targomoKey(),
multiGraphPreAggregationPipeline: {
// this tells multigraph to incorporate reachability into the results
reachability: {
type: "routing_union",
aggregationInputParameters: {
[view.name]: {} // must match id from source
}
}
},
sources: [
{
id: "source_1",
x: view.center[1],
y: view.center[0]
}
]
})
Insert cell
Insert cell
Insert cell
mgID = {
return await fetch(
`https://api.targomo.com/statistics/multigraph?key=${targomoKey()}&serviceUrl=${serviceUrl}`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(mgConfig)
}
).then((response) => response.text());
}
Insert cell
Insert cell
Insert cell
mgOverview = {
const url = `https://api.targomo.com/statistics/multigraph/${mgID}?key=${targomoKey()}&serviceUrl=${serviceUrl}`;
let results = {};

while (!results.status || results.status !== "COMPLETED") {
// status will not equal "COMPLETED" until calculation is complete
try {
const response = await fetch(url);
const data = await response.json();

results = { ...data };

// try again in a second
await new Promise((resolve) => setTimeout(resolve, 1000));
} catch (error) {
console.error("Error fetching data:", error);
}
}

return results;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
scoresConfig = ({
locations: [
{
id: "source_1",
lng: view.center[1],
lat: view.center[0]
}
],
criteria: stats.reduce((acc, cur) => {
acc[cur.key] = {
type: "statisticsSum", // for ABSOLUTE stats. mathAggregation could be used for PERCENT stats
statisticCollectionId: 71,
statisticsIds: [cur.value],
maxEdgeWeight: maxEdgeWeight,
edgeWeight: "time",
travelMode: {
walk: {}
},
coreServiceUrl: "https://api.targomo.com/westcentraleurope/"
};
return acc;
}, {})
})
Insert cell
Insert cell
Insert cell
reachableSums = {
return await fetch(
`https://api.targomo.com/quality/v1/scores?apiKey=${targomoKey()}`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(scoresConfig)
}
).then((response) => response.json());
}
Insert cell
Insert cell
Insert cell
Insert cell
// function to generate color def
colorDef = (mgOverview, statName, scale) => {
const breaks = mgOverview.multiGraphInfo.layersInfo[statName]
.sort((a, b) => a.maxZoom - b.maxZoom)
.map((d, i) => [
[
"interpolate",
["linear"],
["get", statName],
...d.kmeansValueBreaks
.map((b, i) => [b, scale(i / (d.kmeansValueBreaks.length - 1))])
.flat()
],
d.maxZoom
]);

return ["step", ["zoom"], ...breaks.flat(), "#000"];
}
Insert cell
Insert cell
colorDef(mgOverview, displayStat.key, d3.interpolateBlues)
Insert cell
Insert cell
Insert cell
{
if (mgOverview) {
// if present, remove
if (map.getLayer(`statistics-reached`)) {
map.removeLayer(`statistics-reached`);
}
// if present, remove
if (map.getSource(`statistics-reached`)) {
map.removeSource(`statistics-reached`);
}
// if present, remove
if (map.getLayer(`statistics-unreached`)) {
map.removeLayer(`statistics-unreached`);
}
// if present, remove
if (map.getSource(`statistics-unreached`)) {
map.removeSource(`statistics-unreached`);
}

map.addLayer(
{
id: `statistics-reached`,
type: "fill",
source: {
type: "vector",
tiles: [`${mvtUrl}?apiKey=${targomoKey()}&serviceUrl=${serviceUrl}`],
attribution:
'<a href="https://www.targomo.com/developers/resources/attribution/" target="_blank">&copy; Targomo</a>'
},
"source-layer": "aggregation", // the layer name is always "statistics" for tiled MVTs
layout: {},
filter: ["to-boolean", ["get", "reachability"]], // filter for only reachable cells
paint: {
"fill-opacity": 0.6,
"fill-color": colorDef(
mgOverview,
displayStat.key,
d3.interpolateYlOrRd
),
"fill-outline-color": "rgba(0,0,0,0)" // borders need to be transparent to avoid showing tile edges
}
},
"place_other"
);

if (show_unreachable) {
map.addLayer(
{
id: `statistics-unreached`,
type: "fill",
source: {
type: "vector",
tiles: [`${mvtUrl}?key=${targomoKey()}&serviceUrl=${serviceUrl}`],
attribution:
'<a href="https://www.targomo.com/developers/resources/attribution/" target="_blank">&copy; Targomo</a>'
},
"source-layer": "aggregation", // the layer name is always "statistics" for tiled MVTs
layout: {},
filter: ["!", ["to-boolean", ["get", "reachability"]]], // filter for only unreachable cells
paint: {
"fill-opacity": 0.4,
"fill-color": colorDef(
mgOverview,
displayStat.key,
d3.interpolateGreys
),
"fill-outline-color": "rgba(0,0,0,0)" // borders need to be transparent to avoid showing tile edges
}
},
"place_other"
);
}
}
return md`_adding MVT layers to the map_`;
}
Insert cell
Insert cell
Insert cell
view = ({
name: "source_1",
center: [40.437787974977084, -3.6922014932864045],
zoom: 13,
basemap: tgmCoreClient("westcentraleurope").basemaps.getGLStyleURL("Light")
})
Insert cell
Insert cell
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