Skip to contents

EMODnetWCS provides functionalitly for downloading coverage data from EMODnet WCS services as terra <spatRaster> class objects. It also allows subsetting along coverage dimensions as well as requesting specific bands for download.

For more details on extracting metadata to inform valid subsetting of coverages, please refer to the Getting metadata about Services & Coverages article in the EMODnetWCS online documentation.

The first step to downloading coverages is to initiate a connection with on of the EMODnet WCS servers.

library(EMODnetWCS)
#> Loading ISO 19139 XML schemas...
#> Loading ISO 19115 codelists...
wcs <- emdn_init_wcs_client(service = "biology")
#>  WCS client created succesfully
#>  Service: <https://geo.vliz.be/geoserver/Emodnetbio/wcs>
#>  Service: "2.0.1"

You can get a list of available coverages from the service with emdn_get_coverage_ids()

coverage_ids <- emdn_get_coverage_ids(wcs)
coverage_ids
#>  [1] "Emodnetbio__ratio_large_to_small_19582016_L1_err"
#>  [2] "Emodnetbio__aca_spp_19582016_L1"                 
#>  [3] "Emodnetbio__cal_fin_19582016_L1_err"             
#>  [4] "Emodnetbio__cal_hel_19582016_L1_err"             
#>  [5] "Emodnetbio__met_luc_19582016_L1_err"             
#>  [6] "Emodnetbio__oit_spp_19582016_L1_err"             
#>  [7] "Emodnetbio__tem_lon_19582016_L1_err"             
#>  [8] "Emodnetbio__chli_19582016_L1_err"                
#>  [9] "Emodnetbio__tot_lar_19582016_L1_err"             
#> [10] "Emodnetbio__tot_sma_19582016_L1_err"

Let’s focus on the Calanus finmarchicus

coverage_id <- coverage_ids[3]
coverage_id
#> [1] "Emodnetbio__cal_fin_19582016_L1_err"

Subset using a bounding box

While downloading full coverages for most services will work, it may take a long time depending on the size of the coverage so it’s often a good idea to focus on areas of interest and use bounding boxes to subset requests.

So let’s also create a subsetting bbox of an area of interest, the southern North Sea.

We can first check the bounding box of the full coverage to ensure the subset bounding box lies within.

cov_summary <- emdn_get_coverage_summaries(
    wcs,
    coverage_id
)[[1]]
    
emdn_get_bbox(cov_summary)
#> Loading required package: sf
#> Linking to GEOS 3.10.2, GDAL 3.4.2, PROJ 8.2.1; sf_use_s2() is TRUE
#>   xmin   ymin   xmax   ymax 
#> -75.05  34.95  20.05  75.05

We can then create a bounding ensuring it lies within the coverage’s bounding box.

bbox <- c(xmin = 1.5, 
          ymin = 53,
          xmax = 6.5, 
          ymax = 58)

Now we are ready to download the coverage and provide the bounding box we created to the bbox argument.

cov_1 <- emdn_get_coverage(wcs,
                  coverage_id = coverage_id,
                  bbox = bbox)
#> ── Downloading coverage "Emodnetbio__cal_fin_19582016_L1_err" ──────────────────
#> <GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"
#> 
#>  Coverage "Emodnetbio__cal_fin_19582016_L1_err" downloaded succesfully as a
#> terra <SpatRaster>

cov_1
#> class       : SpatRaster 
#> dimensions  : 50, 49, 2  (nrow, ncol, nlyr)
#> resolution  : 0.1, 0.1  (x, y)
#> extent      : 1.55, 6.45, 53.05, 58.05  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : Emodnetbio__cal_fin_19582016_L1_err_2016-11-16T00_00_00_53,1.5,58,6.5.tif 
#> names       : Emodnetbio__cal~53,1.5,58,6.5_1, Emodnetbio__cal~53,1.5,58,6.5_2
terra::plot(cov_1)
#> Warning in .get_breaks(Z, length(out$cols), "eqint", out$range): probable
#> complete loss of accuracy in modulus

#> Warning in .get_breaks(Z, length(out$cols), "eqint", out$range): probable
#> complete loss of accuracy in modulus

The raster returned from the server includes the nil value (which technically encodes NA) as a number.

You can access nil values for each band from a summary object using emdn_get_band_nil_values()

emdn_get_band_nil_values(cov_summary)
#> Relative abundance     Relative error 
#>        9.96921e+36        9.96921e+36

If you wish to encode nil values as NA during coverage download, you can use argument nil_values_as_na.

cov_nil_to_na <- emdn_get_coverage(wcs,
                  coverage_id = coverage_id,
                  bbox = bbox,
                  nil_values_as_na = TRUE)
#> ── Downloading coverage "Emodnetbio__cal_fin_19582016_L1_err" ──────────────────
#> <GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"
#> 
#>  Coverage "Emodnetbio__cal_fin_19582016_L1_err" downloaded succesfully as a
#> terra <SpatRaster>
#>  nil values 9.96920996838687e+36 converted to NA on all bands.

cov_nil_to_na
#> class       : SpatRaster 
#> dimensions  : 50, 49, 2  (nrow, ncol, nlyr)
#> resolution  : 0.1, 0.1  (x, y)
#> extent      : 1.55, 6.45, 53.05, 58.05  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : memory 
#> names       : Emodnetbio__cal~53,1.5,58,6.5_1, Emodnetbio__cal~53,1.5,58,6.5_2 
#> min values  :                      -0.0473766,                    0.0004004543 
#> max values  :                       0.6265208,                    0.0039839428
terra::plot(cov_nil_to_na)

Now, nil values are encode as NA and plotting is much more informative as the range of values within the raster is now constrained to valid values of interest.

Subset using a bounding box and specific timepoints

If a coverage has additional dimensions to the two geographic ones (x/long & y/lat) then the last point on that dimension is always returned if none are specified through the request.

Coverage Emodnetbio__cal_fin_19582016_L1_err indeed has a temporal extent:

emdn_get_dimension_types(cov_summary)
#> [1] "geographic" "geographic" "temporal"

so our previous request returned only the last timepoint of the coverage:

However we can request specific timepoints. First, let’s get a list of all available timepoints.

temp_coefs <- emdn_get_coverage_dim_coefs(
    wcs = wcs,
    coverage_ids = coverage_id,
    type = "temporal")

Next, let’s select the first 3 available timepoints.

timepoints <- head(temp_coefs[[1]], 3)
timepoints
#> [1] "1958-02-16T00:00:00" "1958-05-16T00:00:00" "1958-08-16T00:00:00"

We can request the specific timepoints by supplying our vector of timepoints to the time argument.

cov_2 <- emdn_get_coverage(wcs,
                  coverage_id = coverage_id,
                  bbox = bbox,
                  time = timepoints,
                  nil_values_as_na = TRUE)
#> ── Downloading coverage "Emodnetbio__cal_fin_19582016_L1_err" ──────────────────
#> <GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"<GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"<GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"
#> 
#>  Coverage "Emodnetbio__cal_fin_19582016_L1_err" downloaded succesfully as a
#> terra <SpatRaster> Stack
#>  nil values 9.96920996838687e+36 converted to NA on all bands.
cov_2
#> class       : SpatRaster 
#> dimensions  : 50, 49, 6  (nrow, ncol, nlyr)
#> resolution  : 0.1, 0.1  (x, y)
#> extent      : 1.55, 6.45, 53.05, 58.05  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : memory 
#> names       : Emodn~6.5_1,  Emodn~6.5_2, Emodn~6.5_1,  Emodn~6.5_2, Emodn~6.5_1,  Emodn~6.5_2 
#> min values  :  0.03297495, 0.0007284791,  -0.4147479, 0.0003826013, -0.08314963, 5.374558e-05 
#> max values  :  2.14260626, 0.0124995606,   2.8409283, 0.0090929186,  1.95963264, 9.205581e-03

Note that this returns a <SpatRaster> Stack instead of a single <SpatRaster>.

terra::plot(cov_2)

A similar approach is used for specifying points in the vertical dimension, using argument elevation where appropriate.

Subset a specific band

We can also request specific bands from a coverage.

First let’s check the available bands in our coverage.

emdn_get_band_descriptions(cov_summary)
#> [1] "Relative abundance" "Relative error"    
#> attr(,"uom")
#> [1] "W.m-2.Sr-1" "W.m-2.Sr-1"

To download a specifc band we use the argument rangesubset:

emdn_get_coverage(wcs, 
                  coverage_id = coverage_id,
                  bbox = bbox,
                  rangesubset = "Relative error",
                  nil_values_as_na = TRUE) %>% 
    terra::plot()
#> ── Downloading coverage "Emodnetbio__cal_fin_19582016_L1_err" ──────────────────
#> <GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"
#> 
#>  Coverage "Emodnetbio__cal_fin_19582016_L1_err" downloaded succesfully as a
#> terra <SpatRaster>
#>  nil values 9.96920996838687e+36 converted to NA on all bands.

Specify an output filename

When downloading data, underlying package ows4R uses the in-built WCSCoverageFilenameHandler() function for generating appropriate filenames from the parameters supplied to the request.

However, it is possible to override this as well as the location the file is written to by supplying a file path to argument filename.

emdn_get_coverage(wcs, 
                  coverage_id = coverage_id,
                  bbox = bbox,
                  rangesubset = "Relative error",
                  filename = "cal-fin_rel-error.tif")
#> ── Downloading coverage "Emodnetbio__cal_fin_19582016_L1_err" ──────────────────
#> <GMLEnvelope>
#> ....|-- lowerCorner: 53 1.5 "1958-02-16T00:00:00"
#> ....|-- upperCorner: 58 6.5 "2016-11-16T00:00:00"
#> 
#>  Coverage "Emodnetbio__cal_fin_19582016_L1_err" downloaded succesfully as a
#> terra <SpatRaster>
#> class       : SpatRaster 
#> dimensions  : 50, 49, 1  (nrow, ncol, nlyr)
#> resolution  : 0.1, 0.1  (x, y)
#> extent      : 1.55, 6.45, 53.05, 58.05  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source      : cal-fin_rel-error.tif 
#> name        : cal-fin_rel-error