Skip to contents

ocean3d is an R package for three-dimensional marine spatial analysis of species ranges, fisheries, and depth-stratified oceanographic data. It grew out of work on sharks, rays, and chimaeras, with the functions generalising to any marine taxon or spatial layer.

The three-dimensional marine environment poses a unique challenge for spatial analyses. Most conventional GIS workflows represent space as a two-dimensional plane. This abstraction fails to capture the range of depths and vertical overlap of marine habitat. Fisheries also operate at different depths depending on gear type and target species, creating depth-specific patterns of threat exposure that require analysis in 3D volume rather than 2D planes to quantify. ocean3d provides documented workflows and reusable functions for:

  • extracting values from depth-stratified oceanographic rasters within user-defined geographic areas and depth windows;
  • characterising the abiotic habitat (e.g., temperature, dissolved oxygen) of marine species using IUCN Red List ranges and World Ocean Atlas 2023 climatologies;
  • calculating three-dimensional overlap between species distributions, fisheries effort, and other spatial layers;
  • producing depth-aware maps and depth-profile plots of species ranges, environmental conditions, and cumulative fishing pressure.

How it works

In order to represent the 3D space in the ocean, we use a stacked-raster approach built on terra. We call this the Spatial Voxel Model, with the class SpatVoxel. Using this SpatVoxel, we can represent any number of spatial phenomena in the ocean, including species distributions, fishing effort, and oceanographic variables.

Diagram that represents the multi-depth spatial voxel model
Diagram that represents the multi-depth spatial voxel model

This package includes functions for converting common vector representations to the SpatVoxel class 3D representation. One example operation enabled by ocean3d is to take an existing vector and observed depth range, and have it match with a pre-existing SpatVoxel.

Converting species range vector into SpatVoxel
Converting species range vector into SpatVoxel

ocean3d uses two representations for 3D geometry: A SpatEnvelope stores one continuous [depth_min, depth_max] interval per cell; a SpatVoxel (shown above) stores a value at each of a set of depth levels, so it can hold a variable and interior gaps. SpatEnvelope is useful for representing discrete 3D geometry (ex. species ranges with defined boundaries for area and depth). In contrast, SpatVoxel is ideal for representing continuous values (ex. species distribution models with probabilities of occurrence, rather than presence and absences). SpatVoxel can also represent overhangs, holes, etc. in 3D space since it contains a value for every depth, rather than a depth range.

This package includes utilities for working with commonly used datasets in marine habitat spatial analyses, including IUCN Red List, World Ocean Atlas, GEBCO, Copernicus Marine, and Global Fishing Watch.

Installation

You can install the development version of ocean3d from GitHub with:

# install.packages("devtools")
devtools::install_github("Marine-Biodiversity-Conservation-Lab/ocean3d")

Function overview

Create a raster covering extent of multiple spatial inputs

  • create_study_raster() — build an empty study-area SpatRaster covering the combined extent of one or more spatial inputs.

3D representations

  • as_voxel() — wrap a multi-depth SpatRaster (or a list of single-depth ones) as a validated SpatVoxel, ordered shallow to deep with {variable}_depth={value} layer names.
  • as_envelope() — define a 3D envelope with two rasters, with depth_min and depth_max corresponding to the minimum and maximum depths present in given cell.

Conversion between 3D representations

  • vect_to_envelope() — rasterize a single species range or fishery footprint onto the study grid and attach per-cell depth_min / depth_max, returning a SpatEnvelope.
  • envelope_to_voxel() — expand an envelope onto a set of depth levels.
  • voxel_to_envelope() — collapse a voxel to the envelope bounding it, using a predicate on the cell values. Lossy: interior gaps are filled.

3D spatial query

Three functions ask how a SpatEnvelope or SpatVoxel relates to another object in 3D. The other object can be a 3D object or a 2D one: a SpatRaster footprint or polygons (SpatVector, sf). A 2D object restricts the domain horizontally and without restricting the depths.

  • intersect_3d(x, y) — the shared 3D space between the two inputs. Returns an envelope with the shared depth interval or a presence voxel, depending on inputs.
  • intersects_3d(x, y) — whether inputs share any 3D space, cell by cell: TRUE, FALSE (both present but disjoint, or only one present), or NA (neither present).
  • mask(x, mask) — terra::mask() made depth-aware. Keeps the values of x where the mask domain reaches that cell at that depth.

3D volume

Both dispatch on the 3D representation, so they take either a SpatEnvelope or a SpatVoxel. A voxel’s volume sums the slab each occupied depth level stands for, so interior gaps cost volume instead of being filled in. Given one of each, the envelope is discretized onto the voxel’s depth levels.

  • volume() — total 3D volume (km³) of a rasterized domain.
  • calc_volume_overlap() — per-cell depth intervals and volumes for two rasterized domains and their intersection (returns a 9-layer stack). Built on intersect_3d().

Environmental extraction to areas

  • extract_to_area() — crop a SpatVoxel to an area polygon and select layers within a depth range.

See vignette("ocean3d") for the full workflow, from a range polygon through to a vertical profile of the values inside it.

Environmental extraction to point observations

  • extract_to_point() — the general engine: match observation points (data frame, tibble, sf POINT, matrix, or named list) against one or more NetCDF files, snapping to the nearest longitude, latitude, time and depth cell. Returns the input with the extracted values appended, structure preserved.
  • extract2d() — for variables with no depth dimension.
  • extract3d_nearest() — the valid, non-missing depth layer closest to each observation’s depth, so a cell below the seabed does not silently return NA.
  • extract3d_surface() / extract3d_bottom() — the first available depth layer, or the deepest non-missing one at that cell.
  • extract3d_all() — nearest, surface and bottom in one pass, as three columns.

Common spatial dataset utilities

IUCN Red List API utilities

Add an IUCN Red List API key to access species-assessment functions. Sign up and acquire your API key at https://api.iucnredlist.org/:

usethis::edit_r_environ()
# Add the following line to the .Renviron file
# IUCN_REDLIST_KEY="your_iucn_api_key_here"
  • fetch_species_assessments() — query the IUCN Red List API for taxonomy, Red List category, and depth limits, by SIS ID, scientific name, or comprehensive group code.
  • fill_missing_depths() — fix swapped upper/lower depth values and fill missing values from genus-level means.

GEBCO Bathymetry

World Ocean Atlas 2023 utilities

  • woa_download() — download WOA 2023 NetCDF files (temperature, salinity, dissolved oxygen, oxygen saturation, AOU, nitrate, phosphate, silicate, density) at 0.25°, 1°, or 5° resolution, with caching.
  • woa_load_nc() — load a WOA NetCDF and select a statistical field (e.g., objectively analyzed climatology), returning a SpatRaster with the package’s standard {variable}_depth={value} layer names.
  • woa_cache_dir() / woa_cache_clear() — manage the persistent WOA download cache.

Global Fishing Watch (fisheries effort)

  • gfw_effort_to_raster() — turn the long-format apparent-fishing-hours tibble from gfwr::gfw_ais_fishing_hours() into a multi-layer SpatRaster, one layer per gear (or other grouping). Extending that into 3D uses the general converters — as_envelope() and envelope_to_voxel() — driven by a gear-to-depth-band lookup. Those operating-depth priors are analysis assumptions rather than package data, so they live in the gfw-fishing-effort-3d article.

Contributing

Contributions are welcome. ocean3d is being actively built out from a set of lab analyses into a general, tested package, and there is plenty of well-scoped work available. Start with:

  • CONTRIBUTING.md — development setup, data requirements, the branching/coordination workflow, and coding conventions.
  • SPEC.md — the roadmap; every planned function with its priority and source. Unchecked items are up for grabs.
  • Code of Conduct.

New contributors: the “Known rough edges / good first issues” section of CONTRIBUTING.md lists concrete starting points.

Acknowledgements

Thank you to the people that have inspired and collaborated on this work!

David Ruiz-García, Rachel Aitchison, Wade VanderWright, Amanda Arnold, Dr. Samm Sherman, Dr. Alifa Haque, Prof Nicholas K. Dulvy.

Citation

Jay H. Matsushiba, David Ruiz-García, Rachel M. Aitchison, Wade J. VanderWright, C. Samantha Sherman, Alifa Bintha Haque, Nicholas K. Dulvy. ocean3d: An R Package for Three-Dimensional Spatial Analyses of Marine Habitat.