ows4R icon indicating copy to clipboard operation
ows4R copied to clipboard

Extend DescribeFeatureType methods to support multiple typeNames

Open maelle opened this issue 2 years ago • 9 comments

  • Could one get all feature types at once? At the moment it seems one can only get the feature type per feature, but a request like https://geo.vliz.be/geoserver/Dataportal/wfs?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0 actually exists.
  • From that URL above some layers are "complexType" and some are "element". Could that help guessing the output format? In that case the one that are "elements" are the one sf::st_read() (that's used in ows4R) returns a data.frame.

The context is that I'm wondering how we could get more info on what we're going to get before using getFeatures() itself.

Thanks in advance!

maelle avatar Mar 11 '22 13:03 maelle

I think I misread what the element vs complexType are, however I'm still wondering whether the metadata could help one see what's geographical (sf) vs not (data.frame).

maelle avatar Mar 11 '22 13:03 maelle

DescribeFeatureType should target 0..* cardinality for typeNames , as part of the WFS spec, so in principle we should be able to implement it. Possibly the same for GetFeatures, but i can't work on it immediatly. In general DescribeFeatureType and GetFeature are not used on more than one typeNames, although it is possible in the standard model.

You can get information of feature type before doing Get Feature, you do it when finding/accessing a feature type where a DescribeFeatureType operation is done when triggering getDescription() method.

For example

wfs <- WFSClient$new("https://www.fao.org/fishery/geoserver/wfs", "2.0.0", logger = "INFO")
fao_areas <- wfs$capabilities$findFeatureTypeByName("fifao:FAO_MAJOR")
fao_areas_desc <- fao_areas$getDescription(pretty = T)

eblondel avatar Mar 11 '22 13:03 eblondel

Thank you!

Oh right and if none of the types is "geometry" then one can conclude it'll be a data.frame, correct?

maelle avatar Mar 11 '22 13:03 maelle

Yes ows4R behaves like that. You can publish (in particular in Geoserver) geometryless data through WFS protocol, ows4R will retrieve a data.frame instead of a sf object.

eblondel avatar Mar 11 '22 13:03 eblondel

You can still filter over the properties you want to be part of the output with the WFS propertyName parameter. See below an exampe where I skip the geometry:

fao_areas_data = fao_areas$getFeatures(propertyName = "F_CODE,F_LEVEL")

eblondel avatar Mar 11 '22 13:03 eblondel

Thanks!

Is this "type guessing before download" something that should happen in ows4R (like getTitle() there could be getRType() or so) or in EMODnetWFS?

maelle avatar Mar 11 '22 13:03 maelle

The type is the R type already. The guessing is done in https://github.com/eblondel/ows4R/blob/master/R/WFSFeatureTypeElement.R#L119. For backward compatibility reasons, I can't really change the method now so getType will give the R type, but if you need the WFS type, I can add a method getNativeType or something similar

fao_areas_desc <- fao_areas$getDescription(pretty = F) will give you the raw list of WFSFeatureTypeElement from which you can apply the getType. The above with pretty = T is just a convenience to get tabular view over the feature type definition

eblondel avatar Mar 11 '22 13:03 eblondel

I think by type I meant layer type actually. I.e. knowing in advance when we do getFeatures(), if the resulting thing will be a data.frame or a sf. Sorry for getting this mixed up.

maelle avatar Mar 11 '22 13:03 maelle

Example:

library("EMODnetWFS")
wfs <- emodnet_init_wfs_client(
    service = "biology_occurrence_data"
)
#> Loading ISO 19139 XML schemas...
#> Loading ISO 19115 codelists...
#> Loading IANA mime types...
#> No encoding supplied: defaulting to UTF-8.
#> ✓ WFS client created succesfully
#> ℹ Service: 'http://geo.vliz.be/geoserver/Dataportal/wfs'
#> ℹ Version: '2.0.0'

layers <- emodnet_get_wfs_info(wfs)[["layer_name"]]

is_geom <- function(layer_name, wfs) {
    layer <- wfs$capabilities$findFeatureTypeByName(sprintf("Dataportal:%s", layer_name)) 
    geom <- any(layer$getDescription(pretty = T)$type == "geometry")
    tibble::tibble(
        layer = layer_name,
        geom = geom
    )
} 

layers_info <- purrr::map_df(layers, is_geom, wfs = wfs)
knitr::kable(layers_info)
layer geom
abiotic_observations TRUE
biotic_observations TRUE
eurobis-obisenv_basic FALSE
eurobis-obisenv_count FALSE
eurobis-obisenv_full TRUE
eurobis-obisenv TRUE
eurobis_grid_15m-obisenv TRUE
eurobis_grid_1d-obisenv TRUE
eurobis_grid_30m-obisenv TRUE
eurobis_grid_6m-obisenv TRUE
eurobis_points-obisenv TRUE
iucn_grid TRUE
abiotic_observations_count FALSE
biotic_observations_count FALSE
categories FALSE
categories_get_by_datatype FALSE
datafiches_get_by_datasource_and_dataorigin_and_datatype FALSE
dataorigin_get_by_datasource_and_datatype FALSE
dataportal_get_observations_where TRUE
dataproviders_get_by_datatype FALSE
datasets FALSE
eurobis TRUE
geoobjects TRUE
geoobjects_get_by_name FALSE
parameters FALSE
parameters_get_by_name_and_category FALSE
taxa FALSE

Created on 2022-03-11 by the reprex package (v2.0.1)

maelle avatar Mar 11 '22 13:03 maelle