A demonstration of connecting Erddap to Leaflet-Velocity maps
See here for an online demonstration.
See here for example with time dimension control.
To include the code in your own website, you will need to first add the Leaflet.js mapping library, Leaflet-Velocity and then include errdapToLeafletVelocity, e.g.:
<script src="https://irishmarineinstitute.github.io/erddap-leaflet-velocity-demo/erddapToLeafletVelocity.js"></src>
L.erddapVelocityLayer({
erddapBaseUrl: 'https://erddap.marine.ie',
datasetID: 'IMI_Model_Stats',
uParameter: 'sea_surface_x_velocity',
vParameter: 'sea_surface_y_velocity',
minLat: 48.5,
maxLat: 58.5,
minLon: -17.0,
maxLon: -2.0,
refTime: '2019-12-15T00:00:00Z',
strideLon: 10,
strideLat: 10,
minVelocity: 0,
maxVelocity: 1}).addTo('map');
Once you have added the erddapToLeafletVelocity.js script to your webpages, you can use the erddapToLeafletVelocity function or the L.erddapVelocityLayer function with the following inputs:
- erddapBaseUrl
String
: The base URL of the Errdap server to be called - e.g. 'http://erddap.marine.ie' - datasetID
String
: The dataset name to be accessed from the Erddap server - 'e.g. IMI_Model_Stats' - uParameter
String
: The eastwards velocity parameter name to be accessed from the Erddap dataset - e.g. 'sea_surface_x_velocity' - vParameter
String
: The northwards velocity parameter name to be accessed from the Erddap dataset - e.g. 'sea_surface_x_velocity' - minLat
Number
: The southernmost latitude to be accessed from the Erddap dataset - maxLat
Number
: The northernmost latitude to be accessed from the Erddap dataset - minLon
Number
: The westernmost longitude to be accessed from the Erddap dataset - maxLon
Number
: The easternmost longitude to be accessed from the Erddap dataset - refTime
String
: The dateTime for the data to be returned from Erddap - strideLon
Number
: The Erddap stride to use on the grid for the longitude axis as an integer value - strideLat
Number
: The Erddap stride to use on the grid for the latitude axis as an integer value - minVelocity
Number
: The minimum velocity to use on the Leaflet Velocity display - maxVelocity
Number
: The maximum velocity to use on the Leaflet Velocity display - mapID
String
: The Leaflet map ID to add the velocity layer to
Leaflet-Velocity expects input in the form of a JSON object conforming to the output of Grib2JSON. Some of the fields are documented below:
- Header
- dx The grid spacing on the x-axis in degrees
- dy The grid spacing on the y-axis in degrees
- la1 The northernmost latitutde of the grid
- la2 The southernmost latittude of the grid
- lo1 The westernmost longitude of the grid
- lo2 The easternmost longitude of the grid
- nx The number of grid points on the x axis
- ny The number of grid points on the y-axis
- parameterCategory Use the integer 2
- parameterNumber Use the integer 2 for the x-axis speed and the integer 3 for the y axis speed
- parameterNumberName A plain text label for the parameter
- parameterUnit The units of measure for the parameter
- refTime The date and time for this parameter and grid combination
- Data
- A one-dimensional array of the parameter's data values for this point in time on the grid. Data are west-to-east across the grid, repeating north-to-south down the grid
The following should allow you to build the expected output from any Erddap instance, using a griddap enabled dataset. Contains input from @abkfenris.
const erddapBaseUrl = 'https://erddap.marine.ie';
const datasetID = 'IMI_Model_Stats';
const uParameter = 'sea_surface_x_velocity';
const vParameter = 'sea_surface_y_velocity';
const minLat = 48.5;
const maxLat = 58.5;
const minLon = -17.0;
const maxLon = -2.0;
const refTime = '2019-12-15T00:00:00Z';
const strideLon = 20;
const strideLat = 20;
function jsonp(url) {
return new Promise(function(resolve, reject) {
let script = document.createElement('script')
const name = "_jsonp_" + Math.round(100000 * Math.random());
//url formatting
if (url.match(/\?/)) url += "&.jsonp="+name
else url += "?.jsonp="+name
script.src = url;
window[name] = function(data) {
resolve(data);
document.body.removeChild(script);
delete window[name];
}
document.body.appendChild(script);
});
}
jsonp(erddapBaseUrl
+ '/erddap/griddap/'
+ datasetID
+ '.json?'
+ uParameter + '[(' + refTime + '):1:(' + refTime + ')][(' + String(minLat) + '):' + String(strideLat) + ':(' + String(maxLat) + ')][(' + String(minLon) + '):'+ String(strideLon) +':(' + String(maxLon) + ')],'
+ vParameter + '[(' + refTime + '):1:(' + refTime + ')][(' + String(minLat) + '):' + String(strideLat)+ ':(' + String(maxLat) + ')][(' + String(minLon) + '):' + String(strideLon) + ':(' + String(maxLon) + ')]')
.then(
data => [{
'header':{
'la1': Math.max(...Array.from([...new Set(data.table.rows.map(x => x[1]))])),
'la2': Math.min(...Array.from([...new Set(data.table.rows.map(x => x[1]))])),
'lo1': Math.min(...Array.from([...new Set(data.table.rows.map(x => x[2]))])),
'lo2': Math.max(...Array.from([...new Set(data.table.rows.map(x => x[2]))])),
'dx': (Math.max(...Array.from([...new Set(data.table.rows.map(x => x[2]))])) - Math.min(...Array.from([...new Set(data.table.rows.map(x => x[2]))]))) / ([...new Set(data.table.rows.map(x => x[2]))].length - 1),
'dy': (Math.max(...Array.from([...new Set(data.table.rows.map(x => x[1]))])) - Math.min(...Array.from([...new Set(data.table.rows.map(x => x[1]))]))) / ([...new Set(data.table.rows.map(x => x[1]))].length - 1),
'nx': [...new Set(data.table.rows.map(x => x[2]))].length,
'ny': [...new Set(data.table.rows.map(x => x[1]))].length,
'parameterCategory': 2,
'parameterNumber': 2,
'parameterUnit': 'm.s-1',
'parameterNumberName': data.table.columnNames[3],
'refTime': refTime.replace('T', ' ').replace('Z','')
},
'data': data.table.rows.sort((a,b) => b[1]-a[1]).map(x => x[3])
},{
'header':{
'la1': Math.max(...Array.from([...new Set(data.table.rows.map(x => x[1]))])),
'la2': Math.min(...Array.from([...new Set(data.table.rows.map(x => x[1]))])),
'lo1': Math.min(...Array.from([...new Set(data.table.rows.map(x => x[2]))])),
'lo2': Math.max(...Array.from([...new Set(data.table.rows.map(x => x[2]))])),
'dx': (Math.max(...Array.from([...new Set(data.table.rows.map(x => x[2]))])) - Math.min(...Array.from([...new Set(data.table.rows.map(x => x[2]))]))) / ([...new Set(data.table.rows.map(x => x[2]))].length - 1),
'dy': (Math.max(...Array.from([...new Set(data.table.rows.map(x => x[1]))])) - Math.min(...Array.from([...new Set(data.table.rows.map(x => x[1]))]))) / ([...new Set(data.table.rows.map(x => x[1]))].length - 1),
'nx': [...new Set(data.table.rows.map(x => x[2]))].length,
'ny': [...new Set(data.table.rows.map(x => x[1]))].length,
'parameterCategory': 2,
'parameterNumber': 3,
'parameterUnit': 'm.s-1',
'parameterNumberName': data.table.columnNames[4],
'refTime': refTime.replace('T', ' ').replace('Z','')
},
'data': data.table.rows.sort((a,b) => b[1]-a[1]).map(x => x[4])
}]
)