Skip to contents

The share is the catalogue

There is no manifest file to maintain. build_catalogue() walks \\ABMI-DATA2\science\spatial_data, parses the readme stored beside each dataset, and assembles a table from what it finds. Documenting a dataset means editing its readme; nothing has to be registered anywhere, and the catalogue cannot drift from the data.

Folders follow the ISO 19115 topic categories and readmes follow the ABMI spatial metadata template, both documented in the geospatial catalog and management guide.

A folder is catalogued as a layer when it holds a readme written to the dataset template. Theme folders carry a shorter Category/Description/Examples readme and are reported by list_themes() instead. Datasets sit at whatever depth a theme needs, so each layer has both a short name (fab_dem) and a full id (elevation/fab_dem).

The one folder no scan looks at is top-level _temp, the share’s scratch area. Work in progress, staging copies, and exports live there, so its contents are neither catalogued as layers nor counted against the share by check_metadata() — a layer only becomes discoverable once it is filed under a theme.

Pointing at the share

spatial_root() reports where the catalogue reads from and errors if the share is unreachable.

spatial_root()
#> [1] "//ABMI-DATA2/science/spatial_data"

To work from a mirror, a mapped drive, or a local copy, set an option or an environment variable:

options(sciSpatialR.spatial_root = "D:/spatial_data")
Sys.setenv(SCISPATIALR_SPATIAL_ROOT = "D:/spatial_data")

Browsing

Start with the themes, which show the topic categories and how much sits under each:

12 themes, 18 layers catalogued

 theme                            description                                        n_layers
 elevation                        Height above or below sea level.                   5
 inlandWaters                     Inland water features, drainage systems, and thei… 4
 imageryBaseMapsEarthCover        Base maps.                                         3
 biota                            Flora and/or fauna in natural environments.        2
 location                         Positional information and services.               2
 boundaries                       Legal land descriptions.                           1
 transportation                   Means and aids for conveying persons and/or goods. 1
 climatologyMeteorologyAtmosphere Processes and phenomena of the atmosphere.         0
 economy                          Economic activities, conditions, and employment.   0
 environment                      Environmental resources, protection, and conserva… 0
 farming                          Rearing of animals and/or cultivation of plants.   0
 geoscientificInformation         Information pertaining to earth sciences.          0

Every ISO 19115 topic category appears, including the ones nothing is filed under yet, so the empty folders read as available rather than missing. A theme folder with no readme of its own would still appear, with no description, so an undocumented theme stays visible rather than dropping out of the listing. _temp is the exception, and is absent: it is scratch space rather than a topic category.

The returned table carries an examples column as well, too long to tabulate but useful when deciding where a new dataset belongs.

Then list the layers:

18 layers in 7 themes

 id                                                              title                                         year resolution_m data_type
 biota/natural_regions/natural_regions_subregions_of_alberta     Natural Regions and Subregions of Alberta     2022      NA      vector
 biota/vegetation/grassland_inventory                            Grassland Inventory for Alberta, Manitoba, a… 2024   30.00      raster
 boundaries/administrativeBoundaries/alberta                     AB2020_provincial_boundary                    2023      NA      vector
 elevation/fab_dem                                               FABDEM – Forest And Buildings Removed Copern… 2018  100.00      raster
 elevation/geomorpho90                                           Alberta Geomorphometric Layers (Geomorpho90m) 2023   90.00      raster
 elevation/nrcan_mrdem_dsm                                       Medium Resolution Digital Elevation Model (M… 2006   30.00      raster
 elevation/nrcan_mrdem_dtm                                       Medium Resolution Digital Elevation Model (M… 2006   30.00      raster
 elevation/nrcan_mrdem_dtm_hillshade                             Medium Resolution Digital Elevation Model (M… 2006   30.00      raster
 imageryBaseMapsEarthCover/landsat_summer_mean_indices_2000_2024 Landsat Time Series - Alberta Mean Spectral … 2024   30.00      raster
 imageryBaseMapsEarthCover/modis_land_cover_dynamics_2001_2023   MODIS Annual Land Cover Dynamics (MCD12Q2) -… 2023  500.00      raster
 imageryBaseMapsEarthCover/scanfi_v1.2                           SCANFI: Spatialized Canadian National Forest… 2020   30.00      raster
 inlandWaters/dynamicSurfaceWaterMaps                            Dynamic Surface Water Maps of Canada from 19… 2023      NA      raster
 inlandWaters/hydrologically adjusted elevations                 Height Above Nearest Drainage (HAND) - Hydro… 2024   92.77      raster
 inlandWaters/streams/archydro2                                  Alberta ArcHydro Phase 2 Data                 1996  100.00      vector
 inlandWaters/topographic_wetness_index                          Topographic Wetness Index (TWI)               2024   92.77      raster
 location/referenceGrids/GRID1SQKM_AB2020_gdb                    GRID1SQKM_AB2020                                NA 1000.00      <NA>
 location/referenceGrids/GRID1SQKM_AB2020_raster                 GRID1SQKM_AB2020_raster                       2026 1000.00      raster
 transportation/government_of_alberta_access_layers              Access and Facility Roads - Alberta           2023      NA      vector

Nothing under _temp is listed, documented or not — the Sentinel-2 composites staged there are invisible to the catalogue until they are filed under a theme.

Or narrow the listing to one theme:

list_layers(theme = "elevation")
5 layers in 1 theme

 id                                  title                                         year resolution_m data_type
 elevation/fab_dem                   FABDEM – Forest And Buildings Removed Copern… 2018 100          raster
 elevation/geomorpho90               Alberta Geomorphometric Layers (Geomorpho90m) 2023  90          raster
 elevation/nrcan_mrdem_dsm           Medium Resolution Digital Elevation Model (M… 2006  30          raster
 elevation/nrcan_mrdem_dtm           Medium Resolution Digital Elevation Model (M… 2006  30          raster
 elevation/nrcan_mrdem_dtm_hillshade Medium Resolution Digital Elevation Model (M… 2006  30          raster

list_layers() prints a summary and returns the manifest invisibly. Assign it, or pass verbose = FALSE, to work with the full table — one row per layer, carrying the parsed template fields alongside n_files, size_mb, data_type, path, and readme.

cat_df <- list_layers(verbose = FALSE)
dim(cat_df)
#> [1] 18 40

Forty columns is too wide to print whole; a few of them give the shape of the table:

cat_df[1:5, c("name", "theme", "year", "resolution_m",
              "n_files", "size_mb", "data_type")]
                                   name      theme year resolution_m n_files size_mb data_type
1 natural_regions_subregions_of_alberta      biota 2022           NA       1    11.2    vector
2                   grassland_inventory      biota 2024           30       3 30110.4    raster
3                               alberta boundaries 2023           NA       1     0.4    vector
4                               fab_dem  elevation 2018          100       1 11272.9    raster
5                           geomorpho90  elevation 2023           90       1 11197.9    raster

The full set of fields — the parsed template alongside the columns the file scan adds:

names(cat_df)
 [1] "id"                 "name"               "theme"              "sub_theme"          "title"              "topic_category"
 [7] "keywords"           "year"               "resolution"         "resolution_m"       "xmin"               "xmax"
[13] "ymin"               "ymax"               "crs"                "crs_name"           "datum"              "vertical_crs"
[19] "publication_date"   "start_date"         "end_date"           "format"             "size"               "use_constraints"
[25] "access_constraints" "contact_name"       "contact_email"      "doi"                "online_resource"    "metadata_date"
[31] "abstract"           "purpose"            "credits"            "lineage"            "citation"           "n_files"
[37] "size_mb"            "data_type"          "path"               "readme"

The catalogue as it stands

The table below is a frozen scan of the share, rendered when this vignette was built. It is what list_layers(verbose = FALSE) returns, narrowed to the columns worth tabulating — run the call yourself for the live version and the other thirty-odd columns.

The spatial data catalogue, scanned 2026-08-16.
theme name title year res (m) type size (MB)
biota natural_regions_subregions_of_alberta Natural Regions and Subregions of Alberta 2022 vector 11.2
biota grassland_inventory Grassland Inventory for Alberta, Manitoba, and Saskatchewan (2023) 2024 30.00 raster 30,110.4
boundaries alberta AB2020_provincial_boundary 2023 vector 0.4
elevation fab_dem FABDEM – Forest And Buildings Removed Copernicus Global DEM (30 m) 2018 100.00 raster 11,272.9
elevation geomorpho90 Alberta Geomorphometric Layers (Geomorpho90m) 2023 90.00 raster 11,197.9
elevation nrcan_mrdem_dsm Medium Resolution Digital Elevation Model (MRDEM) - DSM Cloud Optimized GeoTIFF (COG) 2006 30.00 raster 56,895.8
elevation nrcan_mrdem_dtm Medium Resolution Digital Elevation Model (MRDEM) - DTM Cloud Optimized GeoTIFF (COG) 2006 30.00 raster 57,503.7
elevation nrcan_mrdem_dtm_hillshade Medium Resolution Digital Elevation Model (MRDEM) - DTM Hillshade Cloud Optimized GeoTIFF (COG) 2006 30.00 raster 13,648.1
imageryBaseMapsEarthCover landsat_summer_mean_indices_2000_2024 Landsat Time Series - Alberta Mean Spectral Indices (2000-2024) 2024 30.00 raster 2,772,122.1
imageryBaseMapsEarthCover modis_land_cover_dynamics_2001_2023 MODIS Annual Land Cover Dynamics (MCD12Q2) - 500m Phenology 2023 500.00 raster 2,529.0
imageryBaseMapsEarthCover scanfi_v1.2 SCANFI: Spatialized Canadian National Forest Inventory 2020 30.00 raster 34,349.8
inlandWaters dynamicSurfaceWaterMaps Dynamic Surface Water Maps of Canada from 1984-2023 Landsat Satellite Imagery 2023 raster 21,796.5
inlandWaters hydrologically adjusted elevations Height Above Nearest Drainage (HAND) - Hydrologically Adjusted Elevations 2024 92.77 raster 239.0
inlandWaters archydro2 Alberta ArcHydro Phase 2 Data 1996 100.00 vector 680.3
inlandWaters topographic_wetness_index Topographic Wetness Index (TWI) 2024 92.77 raster 1,193.0
location GRID1SQKM_AB2020_gdb GRID1SQKM_AB2020 1,000.00 322.8
location GRID1SQKM_AB2020_raster GRID1SQKM_AB2020_raster 2026 1,000.00 raster 0.0
transportation government_of_alberta_access_layers Access and Facility Roads - Alberta 2023 vector 1,399.7

Blank cells are fields the readme leaves unfilled, which is what keeps a layer out of the matching find_layer() filter.

Finding a layer

find_layer() searches by what a layer is rather than where it lives. keyword matches the folder name, title, keywords, topic category, and abstract:

find_layer(keyword = "elevation")
10 layers in 4 themes

 id                                                            title                                         year resolution_m data_type
 biota/natural_regions/natural_regions_subregions_of_alberta   Natural Regions and Subregions of Alberta     2022     NA       vector
 elevation/fab_dem                                             FABDEM – Forest And Buildings Removed Copern… 2018 100.00       raster
 elevation/geomorpho90                                         Alberta Geomorphometric Layers (Geomorpho90m) 2023  90.00       raster
 elevation/nrcan_mrdem_dsm                                     Medium Resolution Digital Elevation Model (M… 2006  30.00       raster
 elevation/nrcan_mrdem_dtm                                     Medium Resolution Digital Elevation Model (M… 2006  30.00       raster
 elevation/nrcan_mrdem_dtm_hillshade                           Medium Resolution Digital Elevation Model (M… 2006  30.00       raster
 imageryBaseMapsEarthCover/modis_land_cover_dynamics_2001_2023 MODIS Annual Land Cover Dynamics (MCD12Q2) -… 2023 500.00       raster
 inlandWaters/hydrologically adjusted elevations               Height Above Nearest Drainage (HAND) - Hydro… 2024  92.77       raster
 inlandWaters/streams/archydro2                                Alberta ArcHydro Phase 2 Data                 1996 100.00       vector
 inlandWaters/topographic_wetness_index                        Topographic Wetness Index (TWI)               2024  92.77       raster

Note the first hit: a layer filed under biota matched on its abstract, which is the point of searching metadata rather than folder names.

Filters combine, and each takes either a single value or a c(min, max) range:

find_layer(year = c(2020, 2024))
find_layer(resolution = c(0, 120))
find_layer(extent = c(-120, -110, 49, 60))   # decimal degrees
find_layer(theme = "elevation", resolution = 30)

A filter narrows to layers known to match. Resolution, year, and extent come from the readme, so a layer whose readme leaves the field blank is excluded rather than guessed at — check_metadata() will show you which readmes are keeping a layer out.

Loading a layer

get_layer() reads the data with terra, returning a SpatRaster or a SpatVector depending on the format:

twi <- get_layer("topographic_wetness_index")
nsr <- get_layer("natural_regions_subregions_of_alberta")

Pass return_path = TRUE when you want the file rather than the object — to hand it to another tool, or to open it with your own arguments:

get_layer("fab_dem", return_path = TRUE)
#> [1] "//ABMI-DATA2/science/spatial_data/elevation/fab_dem/fab_dem_us_canada.tif"

Some folders hold several datasets. layer_files() shows what is there, and file picks one:

layer_files("grassland_inventory")
#> [1] ".../alberta_grassland_classification_2023.tif"
#> [2] ".../manitoba_grassland_classification_2023.tif"
#> [3] ".../saskatchewan_grassland_classification_2023.tif.tif"

get_layer("grassland_inventory", file = "alberta")

Asking for a multi-file layer without file is an error that lists the candidates, so you never silently get the wrong raster. Shapefile sidecars (.dbf, .shx, .prj) are hidden; pass all = TRUE to see every file in the folder.

Short names work when unambiguous. If two themes hold a folder of the same name, use the full id:

get_layer("elevation/fab_dem")

Reading the metadata

layer_meta() prints a layer’s provenance, licence, and contact details, and returns the parsed fields invisibly:

layer_meta("fab_dem")
<sciSpatialR metadata>
  file: //ABMI-DATA2/science/spatial_data/elevation/fab_dem/readme.txt
  Title       FABDEM – Forest And Buildings Removed Copernicus Global DEM…
  Abstract    FABDEM is a global, bare-earth digital elevation model deri…
  Purpose     To provide a globally consistent, near–bare-earth digital e…
  Topic       geoscientificInformation
  Keywords    digital elevation model, DEM, bare-earth, terrain, topograp…
  Resolution  3.23 arc-seconds (~100 m at the equator)
  Published   2022-01-01
  Start       2010-01-01
  End         2018-12-31
  Lineage     FABDEM was derived from the Copernicus GLO-30 Digital Eleva…
  Format      GeoTIFF
  Size        Global dataset; size varies by tile (1° × 1° tiles grouped …
  Use         Creative Commons Attribution–NonCommercial–ShareAlike 4.0 I…
  Access      None. Data is publicly available subject to license terms.
  Contact     Laurence Hawker
  DOI         10.1088/1748-9326/ac4d4f
  Source      https://doi.org/10.1088/1748-9326/ac4d4f
  Updated     2026-01-23

Values are truncated for display only; the returned object holds them in full. Fields the readme left blank are omitted from the printout — here Credits and Email, which check_metadata() reports below.

Every Label: value line in the readme is captured, not just the template fields, so anything a readme records is reachable. Labels become snake_case keys, and sub-fields indented under a parent are prefixed with it:

md <- layer_meta("fab_dem", print = FALSE)
md$use_constraints
md$extent_west_bounding_coordinate
md$temporal_extent_start_date

read_metadata() does the same for a readme you name by path, and as_metadata_row() flattens the result to a one-row data.frame with the numeric fields coerced — resolution to metres, bounding coordinates to decimal degrees, dates to a year:

md <- read_metadata("path/to/readme.txt")
as_metadata_row(md)

Unfilled template placeholders ([Data Title]) and non-values ("Not Specified") are returned as NA rather than as text, so a copied-but-unedited readme reads as missing rather than documented.

Auditing the metadata

check_metadata() scores every layer against the required template fields and lists the data folders that have no readme at all:

26 layers audited, 8 with no readme

 id                                                      n_missing complete missing
 …here/climate_na/fab_dem_us_canada_int/Normal_1991_2020 NA        0.000    readme
 …yAtmosphere/climate_na/fab_dem_us_canada_int/Year_2000 NA        0.000    readme
 inlandWaters/streams/archydro2_merged                   NA        0.000    readme
 biota/vegetation/grassland_inventory                     8        0.579    purpose, xmin, xmax, ymin, ymax, use_constra…
 boundaries/administrativeBoundaries/alberta              7        0.632    abstract, credits, resolution, use_constrain…
 imageryBaseMapsEarthCover/scanfi_v1.2                    6        0.684    purpose, xmin, xmax, ymin, ymax, lineage
 elevation/fab_dem                                        2        0.895    credits, contact_email
 elevation/nrcan_mrdem_dsm                                1        0.947    access_constraints
 elevation/geomorpho90                                    0        1.000

(Abridged; folders with no readme sort first, then the least complete readmes.) Rows with missing = "readme" are folders holding spatial data that the catalogue cannot see at all — they are the first thing to fix. Deep ids are trimmed from the front when printed, since the last segment is what distinguishes one from another; the returned table holds them in full.

Nothing under _temp is audited either, so staging exports are not counted as undocumented data. The audit stays a list of real gaps.

Use detail = TRUE for one row per missing field, which is easier to tabulate:

check_metadata(detail = TRUE)
check_metadata(theme = "elevation", detail = TRUE)
5 missing fields across 4 layers

 id                                  theme     field
 elevation/fab_dem                   elevation credits
 elevation/fab_dem                   elevation contact_email
 elevation/nrcan_mrdem_dsm           elevation access_constraints
 elevation/nrcan_mrdem_dtm           elevation access_constraints
 elevation/nrcan_mrdem_dtm_hillshade elevation access_constraints

Both forms print the compact view above. Pass verbose = FALSE for the plain data.frame instead — every column, and the missing list in full rather than truncated to the width of the printout:

gaps <- check_metadata(verbose = FALSE)
gaps$missing[gaps$id == "biota/vegetation/grassland_inventory"]
#> [1] "purpose, xmin, xmax, ymin, ymax, use_constraints, access_constraints, contact_email"

Caching

Scanning a network share is the slow step, so the manifest is built once per session and reused. After editing a readme or adding data, rescan:

build_catalogue(refresh = TRUE)

build_catalogue(files = FALSE) skips the file inventory for a faster, metadata-only scan; n_files, size_mb, and data_type are then NA. Any argument accepted by build_catalogue() can be passed through the query functions:

list_layers(root = "D:/spatial_data", refresh = TRUE)

Adding a field to the template

Readmes are parsed generically rather than against a fixed schema, so a field you add to the template is readable immediately, with no change to the package. Every Label: value line is captured, and a sub-field indented under a parent label is namespaced by it. Given this block:

Coordinate Reference System:
    Name: NAD83 / Alberta 10-TM (Forest)
    Authority Code: EPSG:3400
    Datum: North American Datum 1983
    Projection: Transverse Mercator
    Vertical CRS: CGVD2013

every part is reachable at once:

md <- layer_meta("some_layer", print = FALSE)
md$coordinate_reference_system_authority_code
#> [1] "EPSG:3400"
md$coordinate_reference_system_projection
#> [1] "Transverse Mercator"

What is not automatic is becoming a column of the manifest, and so a filter in find_layer(). That takes one edit: add the parsed key to .meta_field_map in R/metadata.R. Adding it to .meta_required in the same file makes check_metadata() count it towards completeness. R/catalogue.R builds its columns from that map and needs no change.