Public
Edited
Jul 1
4 forks
19 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
MAPHEIGHT = screen.height - 200
Insert cell
Insert cell
Insert cell
Insert cell
label = (i) => (labels[i] ? ` (${labels[i]})` : "") // for title tooltip
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
color = ({
domain: d3.range(n * n),
range: d3.cross(blues, oranges).map(mixblend)
})
Insert cell
function mixblend([a, b]) {
a = d3.rgb(a);
b = d3.rgb(b);
const l = Math.min(250, b.r + b.g + b.b);
a.r *= b.r / l;
a.g *= b.g / l;
a.b *= b.b / l;
return a.hex();
}
Insert cell
quantilesPrecipitation = d3
.scaleQuantile()
.domain(mainMapClimateData.ppt) // Use the precipitation data
.range(d3.range(n)) // Map the data to quantiles
.quantiles() // Get the quantiles
Insert cell
quantilesTemperature = d3
.scaleQuantile()
.domain(mainMapClimateData.temp) // Use the precipitation data
.range(d3.range(n)) // Map the data to quantiles
.quantiles() // Get the quantiles
Insert cell
function interpolateBivariate(n, v1, v2) {
const r = d3.range(n);
const s1 = d3.scaleQuantile(v1, r);
const s2 = d3.scaleQuantile(v2, r);
const interpolate = Plot.interpolatorBarycentric();
return function (I, w, h, X, Y) {
I = I.filter((i) => !isNaN(v1[i]) && !isNaN(v2[i]));
const V1 = interpolate(I, w, h, X, Y, v1);
const V2 = interpolate(I, w, h, X, Y, v2);
return Uint8Array.from(V1, (_, i) => n * s1(V1[i]) + s2(V2[i]));
};
}

Insert cell
Insert cell
countries = await FileAttachment("countries-10m.json")
.json()
.then((world) =>
topojson.feature(world, {
type: "GeometryCollection",
// Maldives has a wrong winding order.
geometries: world.objects.countries.geometries.filter(
({ properties: { name } }) => name !== "Maldives"
)
})
)
Insert cell
land = FileAttachment("CNTR_RG_10M_2024_4326.json")
.json()
.then((world) =>
topojson.feature(world, {
type: "GeometryCollection",
// Maldives has a wrong winding order.
geometries: world.objects.CNTR_RG_10M_2024_4326.geometries.filter(
({ properties: { name } }) => name !== "Maldives"
)
})
)
Insert cell
states = FileAttachment("us-states.json").json()
Insert cell
Insert cell
mainMapClimateData = {
let _ppt = await locationConfigs[location].data.ppt.arrayBuffer().then(cdf);
let _tmax = await locationConfigs[location].data.tmax.arrayBuffer().then(cdf);
let _tmin = await locationConfigs[location].data.tmin.arrayBuffer().then(cdf);

let tmax = await Float32Array.from(_tmax.getDataVariable("tmax"), (d) =>
d !== -32768 ? d * 0.01 - 99 : NaN
);
let tmin = await Float32Array.from(_tmin.getDataVariable("tmin"), (d) =>
d !== -32768 ? d * 0.01 - 99 : NaN
);
let ppt = Float32Array.from(_ppt.getDataVariable("ppt"), (d) =>
d !== -2147483648 ? d * 0.1 : NaN
).map((d) => (d < 10 ? NaN : d));
let lx = _tmax.getDataVariable("lon");
let ly = _tmax.getDataVariable("lat");
let l = lx.length;
let temp = tmax.map((max, i) => (max + tmin[i]) / 2);
let lon = (d, i) => lx[i % l];
let lat = (d, i) => ly[(i / l) | 0];

return {
ppt,
tmax,
tmin,
tmax,
tmin,
ppt,
lx,
ly,
l,
temp,
lon,
lat
};
}
Insert cell
Insert cell
insetMapClimateData = {
if (locationConfigs[location].data.inset) {
let _ppt = await locationConfigs[location].data.inset.ppt
.arrayBuffer()
.then(cdf);
let _tmax = await locationConfigs[location].data.inset.tmax
.arrayBuffer()
.then(cdf);
let _tmin = await locationConfigs[location].data.inset.tmin
.arrayBuffer()
.then(cdf);
let tmax = Float32Array.from(_tmax.getDataVariable("tmax"), (d) =>
d !== -32768 ? d * 0.01 - 99 : NaN
);
let tmin = Float32Array.from(_tmin.getDataVariable("tmin"), (d) =>
d !== -32768 ? d * 0.01 - 99 : NaN
);
let ppt = Float32Array.from(_ppt.getDataVariable("ppt"), (d) =>
d !== -2147483648 ? d * 0.1 : NaN
).map((d) => (d < 10 ? NaN : d));
let lx = _tmax.getDataVariable("lon");
let ly = _tmax.getDataVariable("lat");
let l = lx.length;
let temp = tmax.map((max, i) => (max + tmin[i]) / 2);
let lon = (d, i) => lx[i % l];
let lat = (d, i) => ly[(i / l) | 0];
return {
ppt,
tmax,
tmin,
tmax,
tmin,
ppt,
lx,
ly,
l,
temp,
lon,
lat
};
}

return;
}
Insert cell
Insert cell
Insert cell
requests = {
const vars = ["ppt", "tmax", "tmin"];
const URLS = [];
//UK
// const LAT_MIN = 49.674;
// const LON_MIN = -14.015517;
// const LAT_MAX = 61.061;
// const LON_MAX = 2.0919117;

// Europe
const LAT_MIN = 32;
const LON_MIN = -24.2;
const LAT_MAX = 71.2;
const LON_MAX = 62;

//South america
// const LAT_MIN = -55; // Southern tip
// const LON_MIN = -81.3; // Western tip
// const LAT_MAX = 13; // Northern tip
// const LON_MAX = -34.8; // Eastern tip

//continental US
// const LAT_MIN = 24.396308; // Southern tip
// const LON_MIN = -125; // Western tip
// const LAT_MAX = 49.384358; // Northern tip
// const LON_MAX = -66.93457; // Eastern tip

// Iberian peninsula
// const LAT_MIN = 35.9; // Southernmost point
// const LON_MIN = -9.5; // Westernmost point
// const LAT_MAX = 43.8; // Northernmost point
// const LON_MAX = 4.3; // Easternmost point

//canaries
// const LAT_MIN = 27.6; // Southernmost point of the Canary Islands
// const LON_MIN = -18.2; // Westernmost point of the Canary Islands
// const LAT_MAX = 29.5; // Northernmost point of the Canary Islands
// const LON_MAX = -13.3; // Easternmost point of the Canary Islands

vars.forEach((param) => {
URLS.push(
`http://thredds.northwestknowledge.net:8080/thredds/ncss/agg_terraclimate_${param}_1958_CurrentYear_GLOBE.nc?var=${param}&south=${LAT_MIN}&north=${LAT_MAX}&west=${LON_MIN}&east=${LON_MAX}&disableProjSubset=on&addLatLon=true&horizStride=1&accept=netcdf`
);
});

return URLS;
}
Insert cell
//ppt_raw = await fetch(requests[0])
Insert cell
Insert cell
function cdf(buffer) {
return new netcdfjs.NetCDFReader(buffer);
}
Insert cell
netcdfjs = import("https://cdn.skypack.dev/netcdfjs@3.0.0?min")
Insert cell
Plot = require(await FileAttachment("plot.umd.js").url()) // https://github.com/observablehq/plot/pull/2243
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