Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

NOAA’s National Bathymetric Source builds and publishes the best available high-resolution bathymetric data of U.S. waters. The program’s workflow is designed for continuous throughput, ensuring the best bathymetric data is always available to professionals and the public. This data provides depth measurements nationwide, along with vertical uncertainty estimates and information on the originating survey source. It is available in multiple formats (GeoTIFF compilations like BlueTopo and Modeling, BAG, and IHO S-102) hosted on a public S3 bucket.

This package simplifies downloading bathymetric data from NOAA and optionally assembling them into per-UTM-zone GDAL Virtual Rasters for use in GIS applications. It supports six data sources (BlueTopo, Modeling, BAG, S-102 v2.1/v2.2/v3.0).

Note: The S-102 data available through this package are for test and evaluation and should not be used for navigation. For official S-102 data, see the data available from Precision Marine Navigation.

Who this package is for

This package gives you a straightforward way to get high-resolution bathymetric data from NOAA’s National Bathymetric Source.

Point the package at your area of interest and it handles discovery, download, checksum verification, and optional mosaic assembly, ready to open in QGIS, ArcGIS, or any GDAL-compatible tool.

Common use cases include:

  • Hydrographic surveying and chart production. Access the latest compiled depths and survey source metadata.
  • Coastal and ocean modeling. Pull seamless bathymetry grids as input to storm surge, tsunami, or circulation models.
  • Marine construction and engineering. Get site-specific depth data for port design, cable routing, or dredging planning.
  • Environmental and habitat research. Combine bathymetry with other datasets to study benthic environments.
  • Education and exploration. Visualize the seafloor for teaching, outreach, or personal curiosity.

Documentation

  • User Guide — the fetch-then-build workflow, what gets created on disk, and resolution filtering.
  • Data Sources — each data source with its file format, bands, and GDAL requirements.
  • API Reference — complete reference for the Python API and CLI commands.
  • Browser UI App — a standalone UI app built on this python package.
  • About NBS — background on NOAA’s National Bathymetric Source.
  • Troubleshooting — common errors and how to fix them.
  • Quickstart Helper — draw your area of interest on a map and generate usage examples.

Installation

Install conda if you haven’t already: conda installation

Create an environment with the required packages:

conda create -n noaabathymetry_env -c conda-forge 'gdal>=3.9'
conda activate noaabathymetry_env
pip install noaabathymetry

Note: The libgdal-hdf5 package is required for BAG and S-102 data sources. If you only need BlueTopo or Modeling data, gdal>=3.4 alone is sufficient.

Quick start

After installation, you have access to a Python API and a CLI. You can use fetch for downloading tiles and mosaic for assembling them together.

See the Python API and CLI sections below to get started. You can also use the Quickstart Helper to draw your area of interest on a map and generate usage examples.

Python API

from nbs.noaabathymetry import fetch_tiles, mosaic_tiles

result = fetch_tiles('/path/to/project', geometry='area_of_interest.gpkg')
mosaic_result = mosaic_tiles('/path/to/project')

Both functions return structured result objects (FetchResult, MosaicResult) you can inspect:

result = fetch_tiles('/path/to/project', geometry='area_of_interest.gpkg')
print(f"Downloaded: {len(result.downloaded)}")
print(f"Failed: {len(result.failed)}")
print(f"Not found: {len(result.not_found)}")
print(f"Already up to date: {len(result.existing)}")

mosaic_result = mosaic_tiles('/path/to/project')
print(f"Built {len(mosaic_result.built)} UTM zone mosaics")
print(f"Skipped {len(mosaic_result.skipped)} already up-to-date zones")

CLI

The same workflow is available from the command line:

nbs fetch -d /path/to/project -g area_of_interest.gpkg
nbs mosaic -d /path/to/project

Geometry formats

The geometry parameter accepts four formats. File inputs use the CRS defined in the file. All other formats assume EPSG:4326 (WGS 84).

File — any GDAL-compatible vector file (shapefile, geopackage, GeoJSON file, etc.):

result = fetch_tiles('/path/to/project', geometry='/path/to/area_of_interest.gpkg')

Bounding boxxmin,ymin,xmax,ymax as longitude/latitude:

result = fetch_tiles('/path/to/project', geometry='-76.1,36.9,-75.9,37.1')

WKT — Well-Known Text geometry:

result = fetch_tiles('/path/to/project', geometry='POLYGON((-76.1 36.9, -75.9 36.9, -75.9 37.1, -76.1 37.1, -76.1 36.9))')

GeoJSON — geometry or Feature object:

result = fetch_tiles('/path/to/project', geometry='{"type":"Polygon","coordinates":[[[-76.1,36.9],[-75.9,36.9],[-75.9,37.1],[-76.1,37.1],[-76.1,36.9]]]}')

Other data sources

You can specify any S3-hosted source by name with the data_source parameter:

result = fetch_tiles('/path/to/project', geometry='aoi.gpkg', data_source='bag')
mosaic_result = mosaic_tiles('/path/to/project', data_source='bag')
nbs fetch -d /path/to/project -g aoi.gpkg -s modeling
nbs mosaic -d /path/to/project -s modeling

See Data Sources for details on all available sources.

User Guide

Project directory structure

After running fetch and mosaic, your project directory will contain:

/path/to/project/
├── BlueTopo_Tessellation/            # Tile scheme geopackage
│   └── BlueTopo_Tile_Scheme_*.gpkg
├── BlueTopo_Data/                    # Downloaded tile files
│   ├── tile_name.tiff
│   └── tile_name.tiff.aux.xml
├── BlueTopo_Mosaic/                  # Built mosaic files
│   ├── BlueTopo_Fetched_UTM18.vrt
│   ├── BlueTopo_Fetched_UTM18.vrt.ovr
│   ├── BlueTopo_Fetched_UTM18_hillshade.tif   # Optional (--hillshade)
│   ├── BlueTopo_Fetched_UTM19.vrt
│   └── ...
├── BlueTopo_Mosaic_3857/             # Optional (--reproject)
│   ├── BlueTopo_Fetched_UTM18.tif
│   └── ...
└── bluetopo_registry.db              # SQLite tracking database

The folder and file names change based on the data source. For example, with data_source='bag':

/path/to/project/
├── BAG_Tessellation/
│   └── Navigation_Tile_Scheme_*.gpkg
├── BAG_Data/
│   └── tile_name.bag
├── BAG_Mosaic/
│   └── BAG_Fetched_UTM18.vrt
└── bag_registry.db

S-102 sources also include a CATALOG.XML file alongside tiles and produce subdataset VRTs:

/path/to/project/
├── S102V22_Tessellation/
│   └── Navigation_Tile_Scheme_*.gpkg
├── S102V22_Data/
│   ├── CATALOG.XML
│   └── tile_name.h5
├── S102V22_Mosaic/
│   ├── S102V22_Fetched_UTM18_BathymetryCoverage.vrt
│   ├── S102V22_Fetched_UTM18_QualityOfSurvey.vrt
│   └── S102V22_Fetched_UTM18.vrt           # Combined VRT
└── s102v22_registry.db

Fetch-then-build lifecycle

The package operates in two distinct steps.

Step 1: fetch

  1. Resolves the data source — looks up the configuration for the named source.
  2. Downloads the tile scheme — fetches the latest geopackage from S3. This file defines all available tiles, their UTM zones, resolutions, and file locations.
  3. Discovers tiles — if you provide a geometry, it intersects your area of interest with the tile scheme to find overlapping tiles.
  4. Synchronizes records — compares the current tile scheme against the tracking database. If a tile has a newer delivery date, the old files are removed and the tile is queued for re-download.
  5. Downloads tiles — fetches all pending tiles from S3 in parallel with checksum verification.

Step 2: mosaic

  1. Checks prerequisites — verifies the project directory, registry database, and tile folder all exist. Checks GDAL version and driver availability.
  2. Detects missing mosaics — scans the tracking database for UTM zones that need building (newly downloaded tiles, or mosaic files deleted from disk).
  3. Builds per-UTM mosaics — creates a GDAL Virtual Raster for each UTM zone, referencing the downloaded tile files. Adds overview files (.ovr) for efficient display at multiple zoom levels.
  4. Aggregates RATs — for sources with Raster Attribute Tables (BlueTopo, Modeling, S102V22, S102V30), combines per-tile RAT data into the UTM mosaic.

Understanding FetchResult

Fetch returns a FetchResult with per-tile status lists and run metadata.

Tile statuses:

  • existing — tiles already downloaded, with verified checksum at download time, and present on disk. These are skipped.
  • downloaded — tiles successfully fetched in this run (new tiles or re-downloads after an update).
  • not_found — tiles whose files couldn’t be located on S3. This can happen temporarily when NBS is updating tiles.
  • failed — tiles where download or checksum verification failed. Each entry is a dict with tile and reason keys.

Run metadata:

  • filtered_out — tiles excluded by the resolution filter. Empty when no filter is active.
  • missing_reset — tiles previously downloaded but missing from disk.
  • available_tiles_intersecting_aoi — number of tiles with valid metadata intersecting the area of interest geometry (includes tiles already tracked).
  • new_tiles_tracked — number of tiles actually newly added to tracking in this run (tiles already in the database are not counted).
  • tile_resolution_filter — the resolution filter that was active, or None if unfiltered.

Understanding MosaicResult

Mosaic returns a MosaicResult with per-zone status lists and run metadata.

Zone statuses:

  • built — UTM zones that were built in this run. Each entry includes paths to the mosaic, overview, and optional hillshade files.
  • skipped — UTM zones already up to date, or zones with no matching tiles after resolution filtering.
  • failed — UTM zones that failed during the build. Each entry includes the zone identifier and failure reason.
  • hillshades — UTM zones where a hillshade was generated. Each entry includes the zone identifier and hillshade file path.

Run metadata:

  • missing_reset — UTM zones reset because their mosaic files were missing on disk.
  • tile_resolution_filter — the resolution filter that was active, or None if unfiltered.
  • mosaic_resolution_target — Output pixel size override that was active, or None for native resolution.

Understanding StatusResult

Status returns a StatusResult with per-tile freshness information.

Tile categories (no overlap):

  • up_to_date — tiles whose delivery datetime matches the remote and whose files exist on disk.
  • updates_available — tiles with a newer delivery datetime on S3. Each entry includes local and remote datetimes.
  • missing_from_disk — tiles whose delivery datetime matches the remote but whose files are missing from disk.
  • removed_from_nbs — tiles tracked locally that no longer appear in the remote geopackage.

Run metadata:

  • total_tracked — total number of tiles in the local database.

How geometry works

The geometry parameter controls tile discovery, not downloading. When you pass a geometry, fetch intersects it with the tile scheme and adds any overlapping tiles to a persistent tracking list in the project database. A geometry is required on the first fetch to initialize a project.

This tracking is additive. Tiles are never removed from tracking. Passing a new geometry adds new tiles without affecting previously tracked ones. All tracked tiles are downloaded and kept up to date on every fetch run, regardless of whether a geometry is provided.

On subsequent runs, passing a geometry discovers and tracks any new tiles that intersect it. This is useful both for expanding your area of interest and for picking up entirely new tiles that NBS has published since your last discovery run. Omitting the geometry still updates all previously tracked tiles, but won’t discover new ones. Re-running with your geometry periodically ensures newly published tiles in your area of interest are picked up.

Re-fetch and update behavior

Running nbs fetch again on the same project directory is safe and efficient:

  • Tiles that are already downloaded and verified are skipped.
  • The tile scheme geopackage is always re-downloaded to pick up the latest delivery information.
  • If a tile’s delivery date is newer than what’s in the database, the old files are removed and the tile is re-downloaded.
  • New tiles discovered by a new or updated geometry are added to tracking.

Running nbs mosaic again:

  • UTM zones whose mosaics are already built and up to date are skipped.
  • If you delete a mosaic file, the next nbs mosaic run will detect it’s missing and rebuild.
  • If new tiles were downloaded since the last build, only the affected UTM zones are rebuilt.

Checking for updates

Use nbs status (or status_tiles() in Python) to check if your local project has updates available on S3 without downloading anything:

from nbs.noaabathymetry import status_tiles

result = status_tiles('/path/to/project')
print(f"Updates available: {len(result.updates_available)}")
nbs status -d /path/to/project

The status check reads the remote tile scheme and compares delivery datetimes against your local database. It reports tiles that have updates, tiles missing from disk, and tiles removed from NBS. Use --verbosity verbose for per-tile detail, or --verbosity quiet to suppress all log output.

Resolution filtering

BlueTopo tiles are available at multiple resolutions (e.g. 4m, 8m, 16m). Two parameters let you control resolution.

tile_resolution_filter

Restricts which tiles are fetched or built by their native resolution. Pass one or more integer values (meters).

# Only fetch 4m and 8m tiles
result = fetch_tiles('/path/to/project', geometry='aoi.gpkg',
                     tile_resolution_filter=[4, 8])

# Only build mosaics from those tiles
mosaic_result = mosaic_tiles('/path/to/project', tile_resolution_filter=[4, 8])
nbs fetch -d /path/to/project -g aoi.gpkg --tile-resolution-filter 4 8
nbs mosaic -d /path/to/project --tile-resolution-filter 4 8

When a resolution filter is used with mosaic, the output goes to a separate directory to avoid overwriting the default mosaics:

BlueTopo_Mosaic_4m_8m/
├── BlueTopo_Fetched_UTM18_4m_8m.vrt
└── ...

mosaic_resolution_target

Forces the output mosaic pixel size to a specific value in meters. This resamples all tiles to a uniform resolution. Only applies to mosaic.

mosaic_result = mosaic_tiles('/path/to/project', mosaic_resolution_target=8)
nbs mosaic -d /path/to/project -t 8

Output directory:

BlueTopo_Mosaic_tr8m/
├── BlueTopo_Fetched_UTM18_tr8m.vrt
└── ...

Combining both

You can combine the tile filter with a resolution target:

mosaic_result = mosaic_tiles('/path/to/project',
                       tile_resolution_filter=[4, 8],
                       mosaic_resolution_target=8)

Output directory:

BlueTopo_Mosaic_4m_8m_tr8m/
├── BlueTopo_Fetched_UTM18_4m_8m_tr8m.vrt
└── ...

Note: Parameterized builds never touch the default mosaic directory. If you have both BlueTopo_Mosaic/ and BlueTopo_Mosaic_4m_8m/, mosaic will note the other directory’s existence but won’t modify it.

Web Mercator reprojection

Pass reproject=True (or --reproject on the CLI) to produce EPSG:3857 (Web Mercator) GeoTIFFs . This is useful for serving tiles through GeoServer or other web mapping platforms that require a single CRS across UTM zone boundaries.

mosaic_result = mosaic_tiles('/path/to/project', reproject=True)
nbs mosaic -d /path/to/project --reproject

The 3857 output is stored in a separate directory (e.g. BlueTopo_Mosaic_3857/) and tracked independently from the default mosaics. The output is a GeoTIFF (.tif) rather than a VRT, since the reprojection requires pixel computation. Only UTM zones with new or updated tiles are reprojected on subsequent runs.

Note: Reprojection is currently only supported for the BlueTopo data source.

This can be combined with other parameters:

# With resolution filtering
mosaic_result = mosaic_tiles('/path/to/project', tile_resolution_filter=[4, 8], reproject=True)

# With a target resolution, parallel workers, and hillshade
mosaic_result = mosaic_tiles('/path/to/project', reproject=True,
                       mosaic_resolution_target=16, workers=3, hillshade=True)
nbs mosaic -d /path/to/project --reproject -t 16 --workers 3 --hillshade

Output directories follow the same naming pattern: BlueTopo_Mosaic_4m_8m_3857/, BlueTopo_Mosaic_tr16m_3857/, etc.

Parallel processing

By default, mosaic processes UTM zones sequentially. Pass workers to build multiple zones in parallel:

result = mosaic_tiles('/path/to/project', workers=4)
nbs mosaic -d /path/to/project --workers 4

The maximum is os.cpu_count(). Each worker loads tile data into RAM independently, so memory usage scales with the number of workers. Run with the default (1 worker) first to gauge memory usage before scaling up. If a zone fails, other zones continue and the failure is reported in MosaicResult.failed.

Hillshade generation

Pass hillshade=True (or --hillshade on the CLI) to generate a hillshade GeoTIFF alongside each mosaic:

result = mosaic_tiles('/path/to/project', hillshade=True)
nbs mosaic -d /path/to/project --hillshade

This produces a _hillshade.tif Cloud Optimized GeoTIFF (COG) next to each mosaic, built from band 1 (Elevation) at 16m resolution with azimuth 315°, altitude 45°, and 4× vertical exaggeration. The COG format embeds BILINEAR overviews for efficient display.

Custom output directory

By default, mosaic creates an auto-named directory based on the build parameters (e.g. BlueTopo_Mosaic, BlueTopo_Mosaic_3857). Pass output_dir to use a custom name:

result = mosaic_tiles('/path/to/project', output_dir='my_mosaics')
nbs mosaic -d /path/to/project -o my_mosaics

Each output directory can only be used by one build configuration. If you try to use a directory that’s already in use by a different configuration (e.g. different resolution parameters), mosaic will raise an error. To reassign a directory, delete it first. The system will detect it’s gone and allow reassignment on the next run.

Debug mode

Pass debug=True (or --debug on the CLI) to generate a diagnostic report:

result = fetch_tiles('/path/to/project', geometry='aoi.gpkg', debug=True)
nbs fetch -d /path/to/project -g aoi.gpkg --debug

This writes a timestamped log file (e.g. noaabathymetry_debug_20240315_143022.log) to the project directory containing:

  1. Environment — package version, Python version, GDAL version, platform
  2. Configuration — active data source settings, file slots, gpkg field mappings
  3. Filesystem — existence and size of registry DB, tile folder, mosaic folder
  4. Database schema — column definitions for all tables
  5. Database summary — tile counts (verified, unverified, pending), UTM zone build status
  6. Tile details — per-tile anomalies (missing links, files missing on disk, unverified downloads)
  7. UTM zone details — Mosaic/OVR paths and build status per zone

The report contains only technical information and does not include credentials, environment variables, or personal data beyond the project directory path.

Data Sources

This package supports six S3-hosted data sources from the NOAA National Bathymetric Source (NBS) project that can be fetched by name.

S3 sources

These sources are fetched from NOAA’s public S3 bucket. Pass the source key as the data_source argument.

SourceFormatBandsMin GDALRATDescription
bluetopoGeoTIFFElevation, Uncertainty, Contributor3.4YesNational bathymetric compilation (public)
modelingGeoTIFFElevation, Uncertainty, Contributor3.4YesBathymetric compilation for modeling (low water datum)
bagBAG (.bag)Elevation, Uncertainty3.4NoBathymetric Attributed Grid
s102v21S-102 HDF5 (.h5)Elevation, Uncertainty3.9NoIHO S-102 v2.1 bathymetric surface
s102v22S-102 HDF5 (.h5)Elevation, Uncertainty + QualityOfSurvey3.9YesIHO S-102 v2.2 with quality subdataset
s102v30S-102 HDF5 (.h5)Elevation, Uncertainty + QualityOfBathymetryCoverage3.9YesIHO S-102 v3.0 with quality subdataset

BlueTopo

BlueTopo is a compilation of the best available public bathymetric data of U.S. waters. Created by NOAA Office of Coast Survey’s National Bathymetric Source project, it provides depth information nationwide with the vertical uncertainty tied to that depth estimate as well as information on the survey source.

It is the default and most commonly used data source.

Source key: bluetopo

File slots:

SlotGeopackage fieldFile type
geotiffGeoTIFF_Link.tiff
ratRAT_Link.tiff.aux.xml

Bands: Elevation, Uncertainty, Contributor

RAT fields (on band 3 — Contributor):

FieldTypeDescription
valueintContributor class value
countintPixel count for this class
data_assessmentintData quality assessment code
feature_least_depthfloatLeast depth of feature
significant_featuresfloatSignificant feature indicator
feature_sizefloatFeature size
coverageintCoverage flag
bathy_coverageintBathymetric coverage flag
horizontal_uncert_fixedfloatFixed horizontal uncertainty
horizontal_uncert_varfloatVariable horizontal uncertainty
vertical_uncert_fixedfloatFixed vertical uncertainty
vertical_uncert_varfloatVariable vertical uncertainty
license_namestrSource data license name
license_urlstrSource data license URL
source_survey_idstrSource survey identifier
source_institutionstrSource institution name
survey_date_startstrSurvey start date
survey_date_endstrSurvey end date

Modeling

Test-and-evaluation bathymetric compilation for coastal and ocean modeling. Uses the same file structure as BlueTopo, but data is on a low water datum instead of NAVD88/mean sea level.

Source key: modeling

File slots: Same as BlueTopo (GeoTIFF + RAT auxiliary file)

Bands: Elevation, Uncertainty, Contributor

RAT fields: Same as BlueTopo


BAG

Bathymetric Attributed Grid — a single-file format with elevation and uncertainty bands.

Source key: bag

Required GDAL drivers: BAG

File slots:

SlotGeopackage fieldFile type
fileBAG.bag

Bands: Elevation, Uncertainty

RAT: None

Note: BAG files require GDAL built with HDF5 support. Install libgdal-hdf5 via conda if the BAG driver is not available.


Note: The S-102 data available through this package are for test and evaluation and should not be used for navigation. For official S-102 data, see the data available from Precision Marine Navigation.

S102 v2.1

IHO S-102 bathymetric surface, version 2.1. Single-file HDF5 format with two bands.

Source key: s102v21

Required GDAL drivers: S102

Min GDAL version: 3.9

File slots:

SlotGeopackage fieldFile type
fileS102V21.h5

Bands: Elevation, Uncertainty

RAT: None

Requires a CATALOG.XML file downloaded from S3 (handled automatically by fetch_tiles).


S102 v2.2

IHO S-102 v2.2 with dual subdatasets: bathymetry coverage and a quality-of-survey layer. The mosaic build produces separate subdataset VRTs plus a combined VRT.

Source key: s102v22

Required GDAL drivers: S102

Min GDAL version: 3.9

File slots:

SlotGeopackage fieldFile type
fileS102V22.h5

Subdatasets:

SubdatasetBandsVRT suffix
BathymetryCoverageElevation, Uncertainty_BathymetryCoverage
QualityOfSurveyQualityOfSurvey_QualityOfSurvey

A combined VRT is also created with all three bands (Elevation, Uncertainty, QualityOfSurvey).

RAT fields (on band 3 of the combined VRT):

FieldTypeDescription
valueintQuality class value
data_assessmentintData quality assessment code
feature_least_depthfloatLeast depth of feature
significant_featuresfloatSignificant feature indicator
feature_sizefloatFeature size
feature_size_varintFeature size variance (set to 0 in mosaic)
coverageintCoverage flag
bathy_coverageintBathymetric coverage flag
horizontal_uncert_fixedfloatFixed horizontal uncertainty
horizontal_uncert_varfloatVariable horizontal uncertainty
survey_date_startstrSurvey start date
survey_date_endstrSurvey end date
source_survey_idstrSource survey identifier
source_institutionstrSource institution name
bathymetric_uncertainty_typeintUncertainty type classification (set to 0 in mosaic)

Note: feature_size_var and bathymetric_uncertainty_type are unsupported fields and are set to 0 in mosaics.


S102 v3.0

IHO S-102 v3.0 — similar to v2.2, but with a renamed quality subdataset.

Source key: s102v30

Required GDAL drivers: S102

Min GDAL version: 3.9

File slots:

SlotGeopackage fieldFile type
fileS102V30.h5

Subdatasets:

SubdatasetBandsVRT suffix
BathymetryCoverageElevation, Uncertainty_BathymetryCoverage
QualityOfBathymetryCoverageQualityOfBathymetryCoverage_QualityOfBathymetryCoverage

A combined VRT is also created with all three bands.

RAT fields (on band 3 of the combined VRT):

FieldTypeDescription
valueintQuality class value
data_assessmentintData quality assessment code
feature_least_depthfloatLeast depth of feature
significant_featuresfloatSignificant feature indicator
feature_sizefloatFeature size
feature_size_varintFeature size variance (set to 0 in mosaic)
coverageintCoverage flag
bathy_coverageintBathymetric coverage flag
horizontal_uncert_fixedfloatFixed horizontal uncertainty
horizontal_uncert_varfloatVariable horizontal uncertainty
survey_date_startstrSurvey start date
survey_date_endstrSurvey end date
source_survey_idstrSource survey identifier
source_institutionstrSource institution name
type_of_bathymetric_estimation_uncertaintyintUncertainty type classification (set to 0 in mosaic)

Note: feature_size_var and type_of_bathymetric_estimation_uncertainty are unsupported fields and are set to 0 in mosaics.

API Reference

Python API

All public functions are importable from nbs.noaabathymetry:

from nbs.noaabathymetry import fetch_tiles, mosaic_tiles, status_tiles

fetch_tiles

fetch_tiles(
    project_dir: str,
    geometry: str = None,
    data_source: str = None,
    tile_resolution_filter: list = None,
    debug: bool = False,
) -> FetchResult

Discover, download, and update NBS tiles.

Parameters

ParameterTypeDefaultDescription
project_dirstrrequiredAbsolute path to the project directory. Created if it does not exist.
geometrystr | NoneNoneGeometry input defining the area of interest. Accepts a file path, GeoJSON string, bounding box (xmin,ymin,xmax,ymax), or WKT. String inputs assume EPSG:4326. Required on the first fetch to initialize a project. Pass None on subsequent runs to skip tile discovery (useful for re-downloading existing tiles).
data_sourcestr | NoneNoneAn S3 source name (e.g. "bluetopo", "bag", "s102v30"), or None (defaults to "bluetopo").
tile_resolution_filterlist[int] | NoneNoneOnly fetch tiles at these resolutions (meters). Example: [4, 8].
debugboolFalseIf True, writes a diagnostic report to the project directory.

Returns: FetchResult

Raises

ExceptionCondition
ValueErrorproject_dir is not an absolute path.
ValueErrorgeometry path is not absolute.
ValueErrorUnknown data_source name and path is not a directory.
ValueErrorLocal directory has no tile scheme geopackage.
RuntimeErrorNo tile scheme found on S3 after retry.

Example

from nbs.noaabathymetry import fetch_tiles

result = fetch_tiles(
    '/home/user/bathymetry',
    geometry='-76.1,36.9,-75.9,37.1',
    data_source='bluetopo',
)

print(f"Tiles in AOI: {result.available_tiles_intersecting_aoi}")
print(f"Newly tracked: {result.new_tiles_tracked}")
print(f"Downloaded: {len(result.downloaded)}")
print(f"Not found on S3: {len(result.not_found)}")
print(f"Already existing: {len(result.existing)}")
for failure in result.failed:
    print(f"  Failed: {failure['tile']} - {failure['reason']}")

mosaic_tiles

mosaic_tiles(
    project_dir: str,
    data_source: str = None,
    relative_to_vrt: bool = True,
    mosaic_resolution_target: float = None,
    tile_resolution_filter: list = None,
    hillshade: bool = False,
    workers: int = None,
    reproject: bool = False,
    output_dir: str = None,
    debug: bool = False,
) -> MosaicResult

Build a per-UTM-zone mosaic from all source tiles.

Parameters

ParameterTypeDefaultDescription
project_dirstrrequiredAbsolute path to the project directory.
data_sourcestr | NoneNoneA known source name, or None (defaults to "bluetopo").
relative_to_vrtboolTrueStore referenced file paths as relative to the VRT’s directory. Set to False for absolute paths.
mosaic_resolution_targetfloat | NoneNoneForce output pixel size in meters. Must be a positive number.
tile_resolution_filterlist[int] | NoneNoneOnly include tiles at these resolutions (meters). Outputs to a separate mosaic directory.
hillshadeboolFalseIf True, generate a hillshade GeoTIFF from the elevation band.
workersint | NoneNoneNumber of parallel worker processes for building UTM zones. None or 1 = sequential. Must not exceed os.cpu_count().
reprojectboolFalseIf True, reproject to EPSG:3857 (Web Mercator) GeoTIFFs. Outputs to a separate directory.
output_dirstr | NoneNoneCustom output directory name within the project directory. Overrides the auto-generated name. Each directory can only be used by one build configuration.
debugboolFalseIf True, writes a diagnostic report to the project directory.

Returns: MosaicResult

Raises

ExceptionCondition
ValueErrorproject_dir is not an absolute path.
ValueErrorProject directory does not exist.
ValueErrorRegistry database not found (fetch_tiles must run first).
ValueErrorTile downloads folder not found (fetch_tiles must run first).
ValueErrormosaic_resolution_target is not positive.
ValueErrorworkers is not a positive integer or exceeds os.cpu_count().
ValueErrorreproject is used with a data source other than BlueTopo.
ValueErroroutput_dir contains a path separator (must be a single directory name).
RuntimeErrorGDAL version is too old for the data source.
RuntimeErrorGDAL is missing required drivers (e.g. S102, BAG).
RuntimeErrorProject was created with an incompatible internal version.
ValueErrorNo parseable tile resolutions found for a UTM zone.

Example

from nbs.noaabathymetry import mosaic_tiles

result = mosaic_tiles(
    '/home/user/bathymetry',
    data_source='bluetopo',
    mosaic_resolution_target=8,
    tile_resolution_filter=[4, 8],
)

for entry in result.built:
    print(f"Built UTM {entry['utm']}: {entry['mosaic']}")
print(f"Skipped (up to date): {len(result.skipped)}")
print(f"Missing mosaics reset: {len(result.missing_reset)}")

FetchResult

Dataclass returned by fetch_tiles.

AttributeTypeDescription
downloadedlist[str]Tile names successfully downloaded in this run.
failedlist[dict]Tiles that failed download. Each dict has tile (str) and reason (str) keys.
not_foundlist[str]Tile names whose files could not be located on S3.
existinglist[str]Tile names already downloaded, verified, and up to date.
filtered_outlist[str]Tiles excluded by the resolution filter. Empty when no filter is active.
missing_resetlist[str]Tiles previously downloaded but missing from disk.
available_tiles_intersecting_aoiintNumber of tiles with valid metadata intersecting the area of interest geometry. Includes tiles already tracked.
new_tiles_trackedintNumber of tiles actually newly added to tracking in this run. Tiles already in the database are not counted.
tile_resolution_filterlist[int] | NoneResolution filter that was active, or None if unfiltered.

Example

result = fetch_tiles('/home/user/bathymetry', geometry='aoi.gpkg')
print(result)

# FetchResult(
#     downloaded=['BlueTopo_BC25L4NW_20240315', 'BlueTopo_BC25L4NE_20240315',
#                 'BlueTopo_BC25L6SW_20240315'],
#     failed=[{'tile': 'BlueTopo_BC25L6SE_20240315',
#              'reason': 'incorrect hash for geotiff (expected=a1b2c3d4e5f6... got=9f8e7d6c5b4a...)'}],
#     not_found=['BlueTopo_BC25L8NW_20240315'],
#     existing=['BlueTopo_BC25M4NW_20240301', 'BlueTopo_BC25M4NE_20240301'],
#     filtered_out=[],
#     missing_reset=[],
#     available_tiles_intersecting_aoi=8,
#     new_tiles_tracked=6,
#     tile_resolution_filter=None
# )

MosaicResult

Dataclass returned by mosaic_tiles.

AttributeTypeDescription
builtlist[dict]UTM zones that were built. Each dict has utm (str), mosaic (str), ovr (str or None), and hillshade (str or None) keys.
skippedlist[str]UTM zone identifiers that were already up to date, or had no matching tiles after resolution filtering.
failedlist[dict]UTM zones that failed during the build. Each dict has utm (str) and reason (str) keys.
missing_resetlist[str]UTM zones reset due to mosaic files missing on disk.
hillshadeslist[dict]UTM zones where a hillshade was generated. Each dict has utm (str) and hillshade (str, absolute path) keys.
tile_resolution_filterlist[int] | NoneResolution filter that was active, or None if unfiltered.
mosaic_resolution_targetfloat | NoneOutput pixel size override that was active, or None for native resolution.

Example

result = mosaic_tiles('/home/user/bathymetry')
print(result)

# MosaicResult(
#     built=[
#         {'utm': '18', 'mosaic': '/home/user/bathymetry/BlueTopo_Mosaic/BlueTopo_Fetched_UTM18.vrt',
#          'ovr': '/home/user/bathymetry/BlueTopo_Mosaic/BlueTopo_Fetched_UTM18.vrt.ovr',
#          'hillshade': None},
#         {'utm': '19', 'mosaic': '/home/user/bathymetry/BlueTopo_Mosaic/BlueTopo_Fetched_UTM19.vrt',
#          'ovr': '/home/user/bathymetry/BlueTopo_Mosaic/BlueTopo_Fetched_UTM19.vrt.ovr',
#          'hillshade': None}
#     ],
#     skipped=['17'],
#     failed=[],
#     missing_reset=[],
#     hillshades=[],
#     tile_resolution_filter=None,
#     mosaic_resolution_target=None
# )

status_tiles

status_tiles(
    project_dir: str,
    data_source: str = None,
    verbosity: str = "normal",
) -> StatusResult

Check local project freshness against the remote tile scheme.

Parameters

ParameterTypeDefaultDescription
project_dirstrrequiredAbsolute path to the project directory.
data_sourcestr | NoneNoneA known source name, or None (defaults to "bluetopo").
verbositystr"normal"Logging verbosity: "quiet" suppresses all log output, "normal" shows UTM/resolution counts, "verbose" shows individual tiles.

Returns: StatusResult

Raises

ExceptionCondition
ValueErrorproject_dir is not an absolute path.
ValueErrorProject directory does not exist.
ValueErrorRegistry database not found (fetch_tiles must run first).
ValueErrorRate limit exceeded.
RuntimeErrorRemote tile scheme cannot be read from S3.

Example

from nbs.noaabathymetry import status_tiles

result = status_tiles('/home/user/bathymetry')

print(f"Up to date: {len(result.up_to_date)}")
print(f"Updates available: {len(result.updates_available)}")
for entry in result.updates_available:
    print(f"  {entry['tile']}: {entry['local_datetime']} -> {entry['remote_datetime']}")

StatusResult

Dataclass returned by status_tiles.

AttributeTypeDescription
up_to_datelist[dict]Tiles whose delivery datetime matches the remote and files exist on disk. Each dict has tile, utm, resolution, local_datetime, and geometry keys.
updates_availablelist[dict]Tiles with a newer delivery datetime on S3. Each dict has tile, utm, resolution, local_datetime, remote_datetime, and geometry keys.
missing_from_disklist[dict]Tiles whose delivery datetime matches the remote but files are missing from disk. Each dict has tile, utm, resolution, local_datetime, and geometry keys.
removed_from_nbslist[dict]Tiles tracked locally that no longer appear in the remote geopackage. Each dict has tile, utm, resolution, local_datetime, and geometry keys.
total_trackedintTotal number of tiles in the local database.

CLI Reference

The nbs command is installed when you pip install noaabathymetry.

nbs fetch

nbs fetch -d DIR [-g GEOMETRY] [-s SOURCE] [--tile-resolution-filter N [N ...]] [--debug] [--json]
Short formLong formDescription
-d--dir, --directoryRequired. Absolute path to the project directory.
-g--geom, --geometryGeometry input (file path, bounding box, WKT, or GeoJSON). String inputs assume EPSG:4326.
-s--source, --data-sourceData source identifier. Default: bluetopo.
--tile-resolution-filterOnly fetch tiles at these resolutions (meters). Multiple values allowed.
--debugWrite a diagnostic report to the project directory.
--jsonPrint result as JSON to stdout.
-v--versionShow version and exit.

Examples

# Discover tiles within a bounding box and download tracked tiles
nbs fetch -d /home/user/bathymetry -g "-76.1,36.9,-75.9,37.1"

# Fetch from a geopackage, only 4m and 8m tiles
nbs fetch -d /home/user/bathymetry -g /path/to/aoi.gpkg --tile-resolution-filter 4 8

# Fetch BAG data
nbs fetch -d /home/user/bathymetry -g aoi.gpkg -s bag

# Re-download/update without discovering new tiles (existing project, no geometry)
nbs fetch -d /home/user/bathymetry

nbs mosaic

nbs mosaic -d DIR [-s SOURCE] [-r BOOL] [-t RESOLUTION] [--tile-resolution-filter N [N ...]] [--hillshade] [--workers N] [--reproject] [-o OUTPUT_DIR] [--debug] [--json]
Short formLong formDescription
-d--dir, --directoryRequired. Absolute path to the project directory.
-s--source, --data-sourceData source identifier. Default: bluetopo.
-r--relative-to-vrtStore VRT file paths as relative. Default: true.
-t--mosaic-resolution-targetForce output pixel size in meters (any positive number).
--tile-resolution-filterOnly include tiles at these resolutions (meters). Multiple values allowed.
--hillshadeGenerate a hillshade GeoTIFF from the elevation band.
--workersNumber of parallel worker processes for building UTM zones.
--reprojectReproject to EPSG:3857 (Web Mercator) GeoTIFFs.
-o--output-dirCustom output directory name within the project directory.
--debugWrite a diagnostic report to the project directory.
--jsonPrint result as JSON to stdout.
-v--versionShow version and exit.

Examples

# Build mosaics from fetched BlueTopo tiles
nbs mosaic -d /home/user/bathymetry

# Build at 8m resolution target
nbs mosaic -d /home/user/bathymetry -t 8

# Build only from 4m tiles
nbs mosaic -d /home/user/bathymetry --tile-resolution-filter 4

# Build with 4 parallel workers
nbs mosaic -d /home/user/bathymetry --workers 4

# Build with hillshade generation
nbs mosaic -d /home/user/bathymetry --hillshade

# Build into a custom output directory
nbs mosaic -d /home/user/bathymetry -o my_custom_mosaics

# Build Modeling mosaics
nbs mosaic -d /home/user/bathymetry -s modeling

nbs status

nbs status -d DIR [-s SOURCE] [--verbosity quiet|normal|verbose] [--json]
Short formLong formDescription
-d--dir, --directoryRequired. Absolute path to the project directory.
-s--source, --data-sourceData source identifier. Default: bluetopo.
--verbosityLogging verbosity: quiet, normal (default), or verbose.
--jsonPrint result as JSON to stdout.

Examples

# Check for updates
nbs status -d /home/user/bathymetry

# Check with verbose tile listing
nbs status -d /home/user/bathymetry --verbosity verbose

# Quiet mode (return object only, no log output)
nbs status -d /home/user/bathymetry --verbosity quiet

# Check a different data source
nbs status -d /home/user/bathymetry -s bag

Browser UI App

NOAA Bathymetry UI is a browser-based interface for the noaabathymetry Python package. It lets you explore, download, mosaic, and export high-resolution bathymetric data from NOAA’s National Bathymetric Source. No Python environment or setup required. Just one app that bundles everything you need.

Source: GitHub

Documentation: NOAA Bathymetry UI

About NBS

The noaabathymetry package is built on data from NOAA’s National Bathymetric Source (NBS). Watch the video below to learn more about the program, or explore the links at the bottom of this page.

Learn more

Troubleshooting

“Please use an absolute path”

Full message:

Please use an absolute path for your project folder. Typically for non windows systems this means starting with ‘/’

Cause: Both fetch and mosaic require the project_dir to be an absolute path. Relative paths like ./my_project or my_project are rejected.

Fix: Use a full path:

# Wrong
result = fetch_tiles('my_project', geometry='aoi.gpkg')

# Right
result = fetch_tiles('/home/user/my_project', geometry='aoi.gpkg')

On the CLI:

nbs fetch -d /home/user/my_project -g aoi.gpkg

The same requirement applies to geometry file paths. If you pass a file path as the geometry and it contains a path separator or starts with ~, it must be absolute.


“fetch must be run at least once prior to mosaic”

Full message:

SQLite database not found. Confirm correct folder. Note: fetch must be run at least once prior to mosaic

Cause: Mosaic could not find the registry database (<source>_registry.db) in the project directory. This happens when:

  • Fetch was never run on this directory.
  • You’re pointing mosaic at the wrong directory.
  • The data_source argument doesn’t match what was used with fetch (each source has its own database).

Fix: Run fetch first, then mosaic with the same directory and data source:

fetch_tiles('/path/to/project', geometry='aoi.gpkg', data_source='bag')
mosaic_tiles('/path/to/project', data_source='bag')

GDAL version too old

Full message:

Please update GDAL to >=3.9 to run mosaic. Some users have encountered issues with conda’s installation of GDAL 3.4. Try more recent versions of GDAL if you also encounter issues in your conda environment.

Cause: The installed GDAL version is older than what the data source requires. S-102 sources (s102v21, s102v22, s102v30) need GDAL 3.9+. BlueTopo, Modeling, and BAG need GDAL 3.4+.

Fix: Update GDAL in your conda environment:

conda install -c conda-forge 'gdal>=3.9'

Note: Some conda environments have had issues with GDAL 3.4 specifically. If you encounter unexpected errors even with GDAL 3.4 installed, try upgrading to a newer version.


Missing GDAL drivers (S102, BAG)

Full message:

GDAL is missing required driver(s) for S102V22: S102. Reinstall GDAL with HDF5 support to use this data source.

Cause: The GDAL installation doesn’t include the S102 or BAG driver. These drivers require HDF5 support, which isn’t always included in default GDAL builds.

Fix: Install the HDF5-enabled GDAL package:

conda install -c conda-forge libgdal-hdf5

To verify drivers are available:

from osgeo import gdal
print(gdal.GetDriverByName('BAG'))    # Should not be None
print(gdal.GetDriverByName('S102'))   # Should not be None

S3 temporarily unavailable / tiles not found

Console output:

No geometry found in BlueTopo/…, retrying in 5 seconds…

or

* Some tiles we wanted to fetch were not found in the S3 bucket. * The NBS may be actively updating the tiles in question. * You can rerun fetch at a later time to download these tiles.

Cause: The NBS S3 bucket is temporarily unavailable, or tiles are being updated. When fetching the tile scheme geopackage or XML catalog, the package retries once after 5 seconds. For individual tiles, links from the geopackage may temporarily point to files being replaced.

Fix: Wait and rerun fetch. If the problem persists across multiple runs over several hours, contact the NBS team at ocs.nbs@noaa.gov.

Tiles that couldn’t be found are reported in FetchResult.not_found:

result = fetch_tiles('/path/to/project', geometry='aoi.gpkg')
if result.not_found:
    print(f"{len(result.not_found)} tiles not found, try again later")

Checksum verification failures

Console output:

N tiles failed checksum verification: [‘tile_A’, ‘tile_B’] Please contact the NBS if this issue does not fix itself on subsequent runs.

Cause: The SHA-256 hash of a downloaded file doesn’t match the expected checksum from the tile scheme. This can happen due to:

  • Interrupted download (network issues)
  • Tile being actively updated on S3
  • Corrupted file

Fix: Rerun fetch. The failed tiles will be re-downloaded. If the issue persists, contact the NBS team at ocs.nbs@noaa.gov.


“Please close all files and attempt again”

Full message:

Failed to download tile scheme. Possibly due to conflict with an open existing file. Please close all files and attempt again

Cause: The tile scheme geopackage, XML catalog, or tile files cannot be written because another process has them locked. This is most common on Windows when:

  • QGIS has the mosaic or geopackage file open
  • Another Python process is using the database
  • A file explorer preview pane has the file locked

Fix: Close the file in the other application and retry. On Windows, check Task Manager for processes that might have file locks.


Stale mosaic directories

Console output:

Note: 2 other mosaic director(ies) exist that may contain stale data: BlueTopo_Mosaic/ BlueTopo_Mosaic_4m_8m/

Cause: This is an informational warning, not an error. When running mosaic with resolution parameters (--tile-resolution-filter or --mosaic-resolution-target), the output goes to a parameterized directory (e.g. BlueTopo_Mosaic_tr8m/). If other mosaic directories exist from previous builds with different parameters, the package notes them.

What to do: This warning is safe to ignore. The other directories are not modified. If you no longer need them, you can delete them manually. Deleting the default BlueTopo_Mosaic/ directory will cause the next default mosaic run to rebuild it from scratch.


Parallel worker failures

Console output:

2 zone(s) failed: utm18, utm19

Cause: When using --workers N, individual UTM zones can fail while others succeed. Common causes include insufficient RAM (each worker loads tile data independently), disk space exhaustion, or GDAL errors on specific tile combinations.

Fix: Check your system’s available memory. Each worker can consume significant RAM depending on the number and size of tiles in the UTM zone. Run with the default (no --workers flag) first to gauge memory usage for a single zone, then scale up. Failed zones can be retried by running mosaic again. Only the failed zones will be rebuilt.

result = mosaic_tiles('/path/to/project', workers=4)
for failure in result.failed:
    print(f"UTM {failure['utm']} failed: {failure['reason']}")

Overview failed to create

Full message:

Overview failed to create for utmXX. Please try again. If error persists, please contact NBS.

Cause: GDAL failed to create the .ovr overview file for a UTM zone mosaic. This can happen due to disk space issues, file permission problems, or GDAL bugs.

Fix: Check that you have sufficient disk space and write permissions. Retry the build. If the error persists, run with --debug and share the diagnostic report with the NBS team.

Quickstart Helper

Draw your area of interest on the map below to generate usage examples.

Use the draw tools on the left side of the map to draw a rectangle or polygon.