@oceanum/layers
deck.gl layers for visualising gridded data from Oceanum Datamesh zarr datasets.
This library renders deck.gl layers with automatic data fetching from pre-cached zarr archives on the Datamesh. It handles time/level dimension selection, viewport-based spatial chunk loading, and debounced fetching — all through a simple props-based API.
npm install @oceanum/layers
npm install @deck.gl/core @deck.gl/layers @luma.gl/core
import { OceanumPcolorLayer } from "@oceanum/layers";
import DeckGL from "@deck.gl/react";
const SERVICE_URL = "https://layers.app.oceanum.io";
function App() {
const [time, setTime] = useState("2024-01-15T00:00:00Z");
const layers = [
new OceanumPcolorLayer({
id: "wave-height",
serviceUrl: SERVICE_URL,
authHeaders: { "X-DATAMESH-TOKEN": DATAMESH_TOKEN },
datasource: "oceanum_wave_glob05",
variable: "hs",
time,
colormap: {
scale: [
"#313695",
"#4575b4",
"#74add1",
"#abd9e9",
"#fee090",
"#fdae61",
"#f46d43",
"#d73027",
],
domain: [0, 1, 2, 3, 4, 5, 6, 8],
},
opacity: 0.8,
}),
];
return <DeckGL layers={layers} />;
}
Renders a scalar variable as coloured grid cells.
new OceanumPcolorLayer({
id: 'sst',
serviceUrl: 'https://layers.app.oceanum.io',
datasource: 'my_dataset',
variable: 'temperature',
time: '2024-01-15T00:00:00Z',
colormap: { scale: [...], domain: [...] },
});
| Prop | Type | Default | Description |
|---|---|---|---|
variable |
string |
required | Scalar variable name in the zarr dataset |
color |
[r,g,b] |
[200,200,200] |
Fallback colour when no colormap |
material |
boolean\|object |
false |
Phong material for lighting |
Renders animated particles flowing through a vector field.
new OceanumParticleLayer({
id: "wind",
serviceUrl: "https://layers.app.oceanum.io",
datasource: "era5_wind",
uVariable: "u10",
vVariable: "v10",
time: "2024-01-15T00:00:00Z",
npart: 5000,
speed: 2.0,
});
| Prop | Type | Default | Description |
|---|---|---|---|
uVariable |
string |
— | U (eastward) component variable |
vVariable |
string |
— | V (northward) component variable |
magnitudeVariable |
string |
— | Magnitude variable (alternative to u/v) |
directionVariable |
string |
— | Direction variable (alternative to u/v) |
speed |
number |
1.0 |
Animation speed multiplier |
npart |
number |
1000 |
Number of particles |
size |
number |
3 |
Particle size in pixels |
length |
number |
12 |
Particle trail length |
directionConvention |
string |
'NAUTICAL_FROM' |
'NAUTICAL_FROM', 'NAUTICAL_TO', or 'CARTESIAN_RADIANS' |
Provide either (uVariable + vVariable) or (magnitudeVariable + directionVariable).
Renders mesh-based arrows for a vector field. Same variable props as ParticleLayer.
new OceanumPartmeshLayer({
id: "currents",
serviceUrl: "https://layers.app.oceanum.io",
datasource: "ocean_currents",
uVariable: "uo",
vVariable: "vo",
time: "2024-01-15T00:00:00Z",
});
| Prop | Type | Default | Description |
|---|---|---|---|
uVariable / vVariable |
string |
— | Vector component pair |
magnitudeVariable / directionVariable |
string |
— | Alternative vector pair |
speed |
number |
1.0 |
Animation speed multiplier |
size |
number |
3 |
Arrow size in pixels |
directionConvention |
string |
'NAUTICAL_FROM' |
Direction convention |
Renders contour lines with labels for a scalar variable.
new OceanumContourLayer({
id: "pressure",
serviceUrl: "https://layers.app.oceanum.io",
datasource: "era5_surface",
variable: "msl",
time: "2024-01-15T00:00:00Z",
levels: [990, 995, 1000, 1005, 1010, 1015, 1020, 1025],
});
| Prop | Type | Default | Description |
|---|---|---|---|
variable |
string |
required | Scalar variable name |
levels |
number[] |
[] |
Contour level values |
labelSize |
number |
12 |
Label font size |
labelColor |
[r,g,b,a] |
[255,255,255,255] |
Label colour |
smoothing |
boolean |
false |
Smooth contour lines |
numLabels |
number |
1 |
Labels per contour line |
All layers share these props:
| Prop | Type | Default | Description |
|---|---|---|---|
serviceUrl |
string |
required | Root URL of the zarr service |
authHeaders |
object |
{} |
HTTP headers for authentication |
datasource |
string |
required | Dataset name (subpath of the service URL) |
instance |
string |
latest | Zarr group name. Defaults to the latest (last lexicographically) |
time |
string\|Date |
first | ISO 8601 string or Date. Resolved to nearest available time step |
level |
number |
0 |
0-based index into the level dimension |
colormap |
object |
null |
{ scale: string[], domain: number[] } |
opacity |
number |
1.0 |
Layer opacity (0-1) |
altitude |
number |
0.0 |
Altitude offset |
globalWrap |
boolean |
false |
Wrap across the antimeridian |
scale |
number |
1.0 |
Value multiplier before colormapping |
offset |
number |
0.0 |
Value offset before colormapping |
pickable |
boolean |
false |
Enable picking |
visible |
boolean |
true |
Layer visibility |
viewportPadding |
number |
0.1 |
Spatial padding fraction beyond viewport edges |
debounceWait |
number |
100 |
Debounce delay (ms) for slice requests |
onDataLoad |
function |
— | Called when metadata loads. Receives { dataset, times, nlevels, instance } |
onError |
object |
— | Error hooks object (see below) |
The zarr archives are expected to have:
_coordinates attribute in the root .zattrs mapping dimension roles:
{ "x": "longitude", "y": "latitude", "t": "time", "z": "level" }
(time, [level], latitude, longitude)If you are building a public web app, do not expose your Datamesh token in client-side code. Instead, put a small reverse proxy between the browser and the zarr service. The proxy injects the token server-side, so your layers need no authHeaders at all or you can include your own authentication header for validation at the proxy:
new OceanumPcolorLayer({
id: 'wave-height',
serviceUrl: 'https://your-proxy.workers.dev', // proxy URL instead of default
// No authHeaders needed
datasource: 'oceanum_wave_glob05',
variable: 'hs',
time: '2024-01-15T00:00:00Z',
colormap: { scale: [...], domain: [...] },
});
This repo includes ready-to-deploy proxy examples:
packages/layers/proxy/cloudflare/index.jspackages/layers/proxy/express/index.jsSee the full Proxy Guide for setup instructions and security considerations.
The onError prop accepts per-state callbacks:
onError: {
onMetadataError: (err) => { /* dataset open failed */ },
onChunkError: (err) => { /* chunk fetch failed */ },
onVariableError: (err) => { /* variable not found */ },
onValidationError: (err) => { /* invalid props */ },
}
| Hook | When | Layer Behaviour |
|---|---|---|
onMetadataError |
Dataset open fails | Renders nothing |
onChunkError |
Chunk fetch fails | Keeps last valid slice |
onVariableError |
Variable not found in dataset | Renders nothing |
onValidationError |
Invalid prop combination | Renders nothing |