The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
An R client for any service that speaks OGC API - Environmental Data Retrieval (EDR). The spec is general, but in practice this package gets the most use against in-situ monitoring networks — stream gauges, weather stations, snow telemetry, reservoir telemetry — that expose their stations and time series through EDR.
Two known-good places to point it:
For cross-server experiments, the Met Office Labs EDR demonstrator is another useful endpoint. It is a technical demonstrator, not an operational service: availability, collections, and response details can change without notice, so do not build production workflows around it.
The goal is to take the tedious parts of EDR off your hands — URL construction, comma-separated parameter lists, WKT coordinate encoding, retries, content negotiation — and hand back something you can actually do data analysis with:
tibble (one row
per coverage × parameter × time step), via
covjson_to_tibble().sf object, via
geojson_to_sf().Install the released version from CRAN:
install.packages("edr4r")Or the development version from GitHub:
# install.packages("pak")
pak::pak("ksonda/edr4r")
# or
# install.packages("remotes")
remotes::install_github("ksonda/edr4r")For local development:
git clone https://github.com/ksonda/edr4r.git
cd edr4r
R -e 'devtools::install()'Requires R >= 4.1. The sf package is optional but
recommended (used to turn location lists and GeoJSON into spatial
objects).
Start by pointing a client at a server. The base URL is the only thing it really needs:
library(edr4r)
client <- edr_client("https://api.waterdata.usgs.gov/ogcapi/beta")
# or "https://api.wwdh.internetofwater.app"
# or "http://localhost:5005" if you're running pygeoapi locally
edr_collections(client)
#> # A tibble: N × 7
#> id title description extent_bbox crs data_queries links
#> <chr> <chr> <chr> <list> <chr> <list> <list>
#> 1 monitoring-locations Monitoring locations ... <dbl [4]> ... <chr [3]> ...
#> 2 daily-values Daily values ... <dbl [4]> ... <chr [3]> ...
#> ...The collection IDs above (monitoring-locations,
daily-values) are the ones I used as placeholders — every
server advertises its own. The first thing to do against a new service
is run edr_collections() and read the
data_queries column to see which EDR endpoints each
collection supports.
To try the non-operational Met Office demonstrator with a deliberately small request, query one terrain point rather than a forecast collection:
met <- edr_client(
"https://labs.metoffice.gov.uk/edr",
timeout = 10,
max_tries = 1
)
terrain <- edr_position(
met,
"terrain_tiles",
coords = c(-0.1276, 51.5072),
parameter_name = "Height"
)
covjson_to_tibble(terrain)This example is also exercised by a scheduled, non-blocking live smoke check; it is never run as part of CRAN checks or the regular test suite.
edr_locations() with no filters returns the full station
list as GeoJSON. If you have sf installed, it
gets promoted to an sf object automatically:
locs <- edr_locations(client, "monitoring-locations")
locs # sf POINTs with station attributes
plot(sf::st_geometry(locs))Once you know a station ID, ask for its values. The server returns
CoverageJSON; covjson_to_tibble() flattens it into one row
per (coverage × parameter × timestamp):
resp <- edr_location(
client, "daily-values",
location_id = "08313000",
datetime = "2020-01-01/2020-12-31",
parameter_name = c("discharge", "gage_height")
)
df <- covjson_to_tibble(resp)
df
#> # A tibble: 732 × 9
#> coverage_id parameter parameter_label unit datetime x y z value
#> <chr> <chr> <chr> <chr> <dttm> <dbl> <dbl> <dbl> <dbl>
#> 1 08313000 discharge Discharge ft3/s 2020-01-01 00:00:00 -109. 37.0 NA 240
#> ...To grab everything inside a rectangle, use
edr_cube():
cube <- edr_cube(
client, "daily-values",
bbox = c(-120, 39, -118, 41),
datetime = "2023-01-01/2023-03-31",
parameter_name = "discharge"
)
covjson_to_tibble(cube)For an arbitrary polygon, edr_area() takes WKT, an
sf polygon, or a matrix of (lon, lat) rows
(it’ll close the ring for you):
ring <- matrix(
c(-109, 47, -104, 47, -104, 49, -109, 49),
ncol = 2, byrow = TRUE
)
area <- edr_area(client, "monitoring-locations", coords = ring,
datetime = "2022-01-01/..")
covjson_to_tibble(area)edr_plot() is a small ggplot2 wrapper over
the tidy tibble:
edr_plot(resp) # accepts an edr_response directlyFacets by parameter (so different units don’t share a y-axis) and colours by station. Add layers or themes like any other ggplot.
It also auto-detects common non-station shapes:
edr_plot(cube) # x/y grid -> tile map
edr_plot(profile) # varying z -> vertical profile
# or force the layout
edr_plot(profile, view = "profile")
edr_plot(cube, view = "grid")edr_map() puts the stations on a leaflet basemap. Pass
data = as a named list keyed by station id (the shape
[edr_explore()] produces) and each marker gets a popup with an inline
plot and a “Download CSV” link for that station’s data — embedded as a
data: URI so the saved HTML is selfcontained:
stations <- edr_locations(client, "monitoring-locations",
bbox = c(-116, 35.5, -114, 36.5))
data_list <- list("3514" = covjson_to_tibble(resp))
m <- edr_map(stations, data = data_list, popup = "plot+csv")
edr_save_html(m, "stations.html")For a quick exploratory pass over a whole collection,
edr_explore() does the fetch + plot + map in one call:
edr_explore(
client, "daily-values",
bbox = c(-116, 35.5, -114, 36.5),
datetime = "2024-01-01/2024-03-31",
parameter_name = "discharge",
limit = 25,
file = "snapshot.html"
)Gridded coverages and vertical profiles can be mapped too.
edr_map() detects tidy CoverageJSON grids/profiles and puts
slice selectors inside the leaflet widget when there are multiple
parameters or datetimes; grids also get a z selector when
multiple vertical levels are present:
grid <- covjson_to_tibble(cube)
edr_map(grid)
profile <- covjson_to_tibble(profile_resp)
edr_map(profile)edr_explore() uses the same behavior for bulk coverage
queries. Use output = "plot" when you want a ggplot instead
of the interactive map:
edr_explore(client, "gridded-collection",
bbox = c(-120, 39, -118, 41),
method = "cube")
edr_explore(client, "profile-collection",
coords = c(-119, 40),
method = "position")
edr_explore(client, "profile-collection",
coords = c(-119, 40),
method = "position", output = "plot")Some monitoring networks use compound station IDs — colon-separated triplets are a common pattern. The client URL-encodes reserved characters for you:
edr_location(client, "station-network", "1185:CO:SNTL",
datetime = "2024-01-01/..")If the server advertises CSV, you can ask for it instead of CovJSON:
edr_location(client, "daily-values", "08313000",
datetime = "2010-01-01/..", format = "csv")And if you need to hit an endpoint the package doesn’t wrap
(instances, custom queryables, anything weird),
edr_request() is the raw escape hatch:
edr_request(client, "collections/daily-values/instances", format = "json")| Function | EDR endpoint |
|---|---|
edr_client() |
construct a client |
edr_landing() / edr_conformance() |
/, /conformance |
edr_collections() / edr_collection() |
/collections |
edr_queryables() |
/collections/{id}/queryables |
edr_locations() / edr_location() |
/collections/{id}/locations[/{loc}] |
edr_items() / edr_item() |
/collections/{id}/items[/{item}] |
edr_position() |
/collections/{id}/position |
edr_area() |
/collections/{id}/area |
edr_cube() |
/collections/{id}/cube |
edr_radius() |
/collections/{id}/radius |
edr_trajectory() |
/collections/{id}/trajectory |
edr_corridor() |
/collections/{id}/corridor |
edr_request() |
low-level escape hatch |
covjson_to_tibble() / geojson_to_sf() |
response parsers |
What a server actually supports varies. Every query verb above is in the EDR spec and supported by the client, but most servers implement only a subset. On in-situ monitoring deployments,
locations,position,cube, andareaare common;radius,trajectory, andcorridorless so. Hitting a verb the server doesn’t implement gives you an HTTP error. Check thedata_queriescolumn fromedr_collections()before you assume a query will work.
Every query verb accepts the standard EDR filters:
datetime — an ISO-8601 instant or interval. Accepts
"2020-01-01/2020-12-31", an open interval
"2020-01-01/..", or a length-2 character vector
c("2020-01-01", "2020-12-31").parameter_name — a character vector of parameter names;
sent as a comma-separated parameter-name= query. Use
edr_parameters() to discover valid names.bbox — numeric length-4
(minx, miny, maxx, maxy) or length-6 (with z).coords — for
position/area/radius/trajectory/corridor:
a WKT string, a numeric vector / 2-column matrix of lon-lat, or an
sf/sfc geometry.z, crs, limit — passed
through when supplied.... — any extra query parameter is forwarded
verbatim.MIT
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.