WMS: Web Map Service
WMS is a standard of the Open Geospatial Consortium (OGC).
WMS provides a simple HTTP interface for requesting geo-registered map images from one or more distributed geospatial databases.
References
These are links to OGC standards and websites:
Arraylake implements WMS version 1.3.0, supporting the GetCapabilities, GetMap, and GetLegendGraphic requests.
GetFeatureInfo is not yet supported and returns an OperationNotSupported service exception.
WMS shares its rendering pipeline with the Tiles service: the same coordinate detection, styling, colormaps, and multiscale (pyramid) support apply to both. If you are building a web map with a tiling library such as MapLibre, Mapbox, or Leaflet, prefer the Tiles service; use WMS when integrating with GIS tools (QGIS, ArcGIS) or other software that speaks the WMS protocol or needs a simple static image.
Activating WMS for Arraylake Datasets
Enable WMS Service
WMS can be activated using the Arraylake command line interface (CLI):
al compute enable {org} wms
Arraylake currently only supports enabling WMS on an organization-wide basis. This is subject to change in future releases.
Dataset Requirements
WMS works best when datasets are compliant with CF Conventions, particularly around coordinates.
Specifically it looks for the CRS in a grid_mapping variable (or falls back to a variable named spatial_ref or crs if a grid mapping variable is not detected).
If neither of these are present, we assume the CRS to be EPSG:4326.
If a projected CRS is detected, we search for projected X and Y coordinates (those with the standard_name attribute set as projection_x_coordinate and projection_y_coordinate).
If a geographic CRS is detected, we search for latitude and longitude coordinate variables (those with standard_name attribute set as latitude or longitude or units attribute with degrees_north and degrees_east).
If these attributes are present, we attempt to make a best guess using the names of the coordinate variables present.
We strongly recommend you annotate your dataset explicitly by adding a grid mapping variable, and the associated coordinate variables with the right standard_name and units attributes.
WMS URL Structure
WMS endpoints can be accessed via the following URL schema, referred to as {base_url} below.
https://compute.earthmover.io/v1/services/wms/{org}/{repo}/{branch|commit|tag}/{path/to/group}/wms
Where
{org}is the name of your Arraylake organization{repo}is the name of the Repo{branch|commit|tag}is the branch, commit, or tag within the Repo to use to fulfill the request{path/to/group}is the path to group within the Repo that contains anxarrayDataset. If the dataset is stored in the root group, this should be omitted.
All examples use the HTTP GET protocol.
Specific examples in this guide use the public GFS forecast Repo.
Queries
GetCapabilities
Returns the service metadata: available layers, their bounding boxes, dimensions (e.g. time), and styles.
The response is XML by default; pass format=json (or send an Accept: application/json header) to receive the same document as JSON.
curl "https://compute.earthmover.io/v1/services/wms/earthmover-public/noaa-gfs-forecast/main/wms?service=WMS&version=1.3.0&request=GetCapabilities"
Requests for version 1.1.1 are answered with a 1.3.0 capabilities document, per the WMS version negotiation rules.
GetMap
Renders a map image for a layer.
curl "https://compute.earthmover.io/v1/services/wms/earthmover-public/noaa-gfs-forecast/main/wms?service=WMS&version=1.3.0&request=GetMap&layers=temperature_2m&styles=raster/default&crs=EPSG:3857&bbox=-20037508,-20037508,20037508,20037508&width=512&height=512&colorscalerange=-30,40"
Required parameters:
version: must be1.3.0;layers: the name of the variable to render;bbox: the region to render asminx,miny,maxx,maxy, expressed in the requested CRS;widthandheight: the image size in pixels;
Optional parameters:
crs: the Coordinate Reference System to render to. Any CRS resolvable by pyproj (e.g. any EPSG code) is supported. Defaults toEPSG:4326;styles:raster/{colormap}, where{colormap}is any of matplotlib's colormaps. Defaults toraster/default;colorscalerange=min,max: the range of the color scale. When omitted, the variable'svalid_min/valid_maxattributes are used if present, otherwise the range is autoscaled from the data;colormap: a custom colormap as a JSON-encoded dictionary with numeric keys (0–255) and hex color values, overridingstyles;abovemaxcolor/belowmincolor: color for values outsidecolorscalerange. Acceptsextend,transparent, a hex color, or a named color;timeandelevation: select along the dataset's time and vertical dimensions;format:image/png(default) orimage/jpeg;transparent: whether areas without data are transparent (defaulttrue; PNG only, JPEG is always opaque);bgcolor: background color for non-transparent maps in0xRRGGBBformat;exceptions: how errors are reported —XML(default, a ServiceExceptionReport),INIMAGE(the error is drawn into the map image), orBLANK(an empty image).
Any other dataset dimension can be selected by passing it as a query parameter named after the dimension, for example &step=1+hour for a dataset with a step dimension.
Unselected extra dimensions default to their first value.
Per the WMS 1.3.0 specification, bbox coordinates follow the axis order of the requested CRS.
For north-first CRSes like EPSG:4326 this means bbox=miny,minx,maxy,maxx (latitude first), while EPSG:3857 uses the familiar minx,miny,maxx,maxy.
For multiscale (pyramid) datasets, the service automatically renders from the overview level best matching the requested resolution, and reports the level used in the X-Multiscale-Level response header.
GetLegendGraphic
Returns a legend image for a layer, matching the styling parameters used in GetMap requests.
curl "https://compute.earthmover.io/v1/services/wms/earthmover-public/noaa-gfs-forecast/main/wms?service=WMS&version=1.3.0&request=GetLegendGraphic&layer=temperature_2m&colorscalerange=-30,40&width=400&height=100"
Parameters:
layer: the name of the variable to generate a legend for (required);styles,colorscalerange,colormap,abovemaxcolor,belowmincolor: should match the values used in the correspondingGetMaprequest;widthandheight: the image size in pixels (default 100×100);vertical: orient the colorbar vertically (defaultfalse);show_label: whether to draw the layer'slong_name [units]as the axis label (defaulttrue).
Integrating with Tools
QGIS
The service produces standard WMS 1.3.0 capabilities documents, so it can be added to QGIS as a regular WMS layer.
- Right-click on
WMS/WMTSin the Browser (left sidebar by default) and add a "New Connection". - In the URL box, use the
{base_url}for your dataset, e.g.https://compute.earthmover.io/v1/services/wms/earthmover-public/noaa-gfs-forecast/main/wms. If your service is not public, configure Basic Authentication for the connection. - Expand the connection and add any of its layers to your project.
MapLibre/Mapbox
A WMS GetMap request returns a single georeferenced image for exactly the region you ask for.
In MapLibre (or Mapbox) this maps naturally onto an image source: one GetMap request draped over the basemap at its corner coordinates.
WMS also works as a tiled raster source (a tiles URL template with the {bbox-epsg-3857} token), but this example demonstrates the single-image case.
This example drapes a single map image of 2-meter temperature over the continental United States.
Coordinate system handling
The service reprojects data from the dataset's native CRS to whatever crs you request, so the choice of request CRS is about matching the display, not the data.
MapLibre renders in Web Mercator, and an image source stretches the image linearly in mercator space between its corners — so:
- Request the image with
crs=EPSG:3857and abboxin mercator meters. - Give the image source the same four bbox corners, converted to longitude/latitude — that is the coordinate system MapLibre expects for
coordinates, regardless of the image's CRS.
Code
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Arraylake WMS Example (MapLibre)</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link href='https://unpkg.com/maplibre-gl@5.9.0/dist/maplibre-gl.css' rel='stylesheet'>
<script src='https://unpkg.com/maplibre-gl@5.9.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
zoom: 3,
center: [-95, 38],
});
map.on('style.load', () => {
// GetMap request for the continental US in EPSG:3857
// (bbox is lon -130..-60, lat 20..55 in mercator meters)
map.addSource('wms-image-source', {
'type': 'image',
'url': 'https://compute.earthmover.io/v1/services/wms/earthmover-public/noaa-gfs-forecast/main/wms?service=WMS&version=1.3.0&request=GetMap&layers=temperature_2m&styles=raster/default&crs=EPSG:3857&bbox=-14471534,2273031,-6679169,7361866&width=1024&height=669&colorscalerange=-30,40&transparent=true',
// The same corners as the bbox, in lon/lat
'coordinates': [
[-130, 55],
[-60, 55],
[-60, 20],
[-130, 20]
]
});
map.addLayer(
{
'id': 'wms-image-layer',
'type': 'raster',
'source': 'wms-image-source',
'paint': {'raster-opacity': 0.8}
}
);
});
</script>
</body>
</html>
Help! I don't see anything!
- Make sure all required parameters are set (see the
GetMapsection), and check thebboxaxis order for your CRS. - If you get a
413response, the request covers too much data at full resolution. Request a smaller area or fewer pixels, or add multiscale overviews to your dataset. - Ensure the dataset's coordinate variables have appropriate CF attributes set (see Dataset Requirements).
- If no
colorscalerangeis given and the data has novalid_min/valid_maxattributes, the color scale is autoscaled per request — setcolorscalerangeexplicitly for consistent styling.