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-hdf5package is required for BAG and S-102 data sources. If you only need BlueTopo or Modeling data,gdal>=3.4alone 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 box — xmin,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
- Resolves the data source — looks up the configuration for the named source.
- Downloads the tile scheme — fetches the latest geopackage from S3. This file defines all available tiles, their UTM zones, resolutions, and file locations.
- Discovers tiles — if you provide a geometry, it intersects your area of interest with the tile scheme to find overlapping tiles.
- 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.
- Downloads tiles — fetches all pending tiles from S3 in parallel with checksum verification.
Step 2: mosaic
- Checks prerequisites — verifies the project directory, registry database, and tile folder all exist. Checks GDAL version and driver availability.
- Detects missing mosaics — scans the tracking database for UTM zones that need building (newly downloaded tiles, or mosaic files deleted from disk).
- 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. - 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
tileandreasonkeys.
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
Noneif 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
Noneif unfiltered. - mosaic_resolution_target — Output pixel size override that was active, or
Nonefor 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 mosaicrun 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/andBlueTopo_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:
- Environment — package version, Python version, GDAL version, platform
- Configuration — active data source settings, file slots, gpkg field mappings
- Filesystem — existence and size of registry DB, tile folder, mosaic folder
- Database schema — column definitions for all tables
- Database summary — tile counts (verified, unverified, pending), UTM zone build status
- Tile details — per-tile anomalies (missing links, files missing on disk, unverified downloads)
- 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.
| Source | Format | Bands | Min GDAL | RAT | Description |
|---|---|---|---|---|---|
bluetopo | GeoTIFF | Elevation, Uncertainty, Contributor | 3.4 | Yes | National bathymetric compilation (public) |
modeling | GeoTIFF | Elevation, Uncertainty, Contributor | 3.4 | Yes | Bathymetric compilation for modeling (low water datum) |
bag | BAG (.bag) | Elevation, Uncertainty | 3.4 | No | Bathymetric Attributed Grid |
s102v21 | S-102 HDF5 (.h5) | Elevation, Uncertainty | 3.9 | No | IHO S-102 v2.1 bathymetric surface |
s102v22 | S-102 HDF5 (.h5) | Elevation, Uncertainty + QualityOfSurvey | 3.9 | Yes | IHO S-102 v2.2 with quality subdataset |
s102v30 | S-102 HDF5 (.h5) | Elevation, Uncertainty + QualityOfBathymetryCoverage | 3.9 | Yes | IHO 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:
| Slot | Geopackage field | File type |
|---|---|---|
geotiff | GeoTIFF_Link | .tiff |
rat | RAT_Link | .tiff.aux.xml |
Bands: Elevation, Uncertainty, Contributor
RAT fields (on band 3 — Contributor):
| Field | Type | Description |
|---|---|---|
value | int | Contributor class value |
count | int | Pixel count for this class |
data_assessment | int | Data quality assessment code |
feature_least_depth | float | Least depth of feature |
significant_features | float | Significant feature indicator |
feature_size | float | Feature size |
coverage | int | Coverage flag |
bathy_coverage | int | Bathymetric coverage flag |
horizontal_uncert_fixed | float | Fixed horizontal uncertainty |
horizontal_uncert_var | float | Variable horizontal uncertainty |
vertical_uncert_fixed | float | Fixed vertical uncertainty |
vertical_uncert_var | float | Variable vertical uncertainty |
license_name | str | Source data license name |
license_url | str | Source data license URL |
source_survey_id | str | Source survey identifier |
source_institution | str | Source institution name |
survey_date_start | str | Survey start date |
survey_date_end | str | Survey 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:
| Slot | Geopackage field | File type |
|---|---|---|
file | BAG | .bag |
Bands: Elevation, Uncertainty
RAT: None
Note: BAG files require GDAL built with HDF5 support. Install
libgdal-hdf5via 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:
| Slot | Geopackage field | File type |
|---|---|---|
file | S102V21 | .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:
| Slot | Geopackage field | File type |
|---|---|---|
file | S102V22 | .h5 |
Subdatasets:
| Subdataset | Bands | VRT suffix |
|---|---|---|
| BathymetryCoverage | Elevation, Uncertainty | _BathymetryCoverage |
| QualityOfSurvey | QualityOfSurvey | _QualityOfSurvey |
A combined VRT is also created with all three bands (Elevation, Uncertainty, QualityOfSurvey).
RAT fields (on band 3 of the combined VRT):
| Field | Type | Description |
|---|---|---|
value | int | Quality class value |
data_assessment | int | Data quality assessment code |
feature_least_depth | float | Least depth of feature |
significant_features | float | Significant feature indicator |
feature_size | float | Feature size |
feature_size_var | int | Feature size variance (set to 0 in mosaic) |
coverage | int | Coverage flag |
bathy_coverage | int | Bathymetric coverage flag |
horizontal_uncert_fixed | float | Fixed horizontal uncertainty |
horizontal_uncert_var | float | Variable horizontal uncertainty |
survey_date_start | str | Survey start date |
survey_date_end | str | Survey end date |
source_survey_id | str | Source survey identifier |
source_institution | str | Source institution name |
bathymetric_uncertainty_type | int | Uncertainty type classification (set to 0 in mosaic) |
Note:
feature_size_varandbathymetric_uncertainty_typeare 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:
| Slot | Geopackage field | File type |
|---|---|---|
file | S102V30 | .h5 |
Subdatasets:
| Subdataset | Bands | VRT suffix |
|---|---|---|
| BathymetryCoverage | Elevation, Uncertainty | _BathymetryCoverage |
| QualityOfBathymetryCoverage | QualityOfBathymetryCoverage | _QualityOfBathymetryCoverage |
A combined VRT is also created with all three bands.
RAT fields (on band 3 of the combined VRT):
| Field | Type | Description |
|---|---|---|
value | int | Quality class value |
data_assessment | int | Data quality assessment code |
feature_least_depth | float | Least depth of feature |
significant_features | float | Significant feature indicator |
feature_size | float | Feature size |
feature_size_var | int | Feature size variance (set to 0 in mosaic) |
coverage | int | Coverage flag |
bathy_coverage | int | Bathymetric coverage flag |
horizontal_uncert_fixed | float | Fixed horizontal uncertainty |
horizontal_uncert_var | float | Variable horizontal uncertainty |
survey_date_start | str | Survey start date |
survey_date_end | str | Survey end date |
source_survey_id | str | Source survey identifier |
source_institution | str | Source institution name |
type_of_bathymetric_estimation_uncertainty | int | Uncertainty type classification (set to 0 in mosaic) |
Note:
feature_size_varandtype_of_bathymetric_estimation_uncertaintyare 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
| Parameter | Type | Default | Description |
|---|---|---|---|
project_dir | str | required | Absolute path to the project directory. Created if it does not exist. |
geometry | str | None | None | Geometry 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_source | str | None | None | An S3 source name (e.g. "bluetopo", "bag", "s102v30"), or None (defaults to "bluetopo"). |
tile_resolution_filter | list[int] | None | None | Only fetch tiles at these resolutions (meters). Example: [4, 8]. |
debug | bool | False | If True, writes a diagnostic report to the project directory. |
Returns: FetchResult
Raises
| Exception | Condition |
|---|---|
ValueError | project_dir is not an absolute path. |
ValueError | geometry path is not absolute. |
ValueError | Unknown data_source name and path is not a directory. |
ValueError | Local directory has no tile scheme geopackage. |
RuntimeError | No 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
| Parameter | Type | Default | Description |
|---|---|---|---|
project_dir | str | required | Absolute path to the project directory. |
data_source | str | None | None | A known source name, or None (defaults to "bluetopo"). |
relative_to_vrt | bool | True | Store referenced file paths as relative to the VRT’s directory. Set to False for absolute paths. |
mosaic_resolution_target | float | None | None | Force output pixel size in meters. Must be a positive number. |
tile_resolution_filter | list[int] | None | None | Only include tiles at these resolutions (meters). Outputs to a separate mosaic directory. |
hillshade | bool | False | If True, generate a hillshade GeoTIFF from the elevation band. |
workers | int | None | None | Number of parallel worker processes for building UTM zones. None or 1 = sequential. Must not exceed os.cpu_count(). |
reproject | bool | False | If True, reproject to EPSG:3857 (Web Mercator) GeoTIFFs. Outputs to a separate directory. |
output_dir | str | None | None | Custom output directory name within the project directory. Overrides the auto-generated name. Each directory can only be used by one build configuration. |
debug | bool | False | If True, writes a diagnostic report to the project directory. |
Returns: MosaicResult
Raises
| Exception | Condition |
|---|---|
ValueError | project_dir is not an absolute path. |
ValueError | Project directory does not exist. |
ValueError | Registry database not found (fetch_tiles must run first). |
ValueError | Tile downloads folder not found (fetch_tiles must run first). |
ValueError | mosaic_resolution_target is not positive. |
ValueError | workers is not a positive integer or exceeds os.cpu_count(). |
ValueError | reproject is used with a data source other than BlueTopo. |
ValueError | output_dir contains a path separator (must be a single directory name). |
RuntimeError | GDAL version is too old for the data source. |
RuntimeError | GDAL is missing required drivers (e.g. S102, BAG). |
RuntimeError | Project was created with an incompatible internal version. |
ValueError | No 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.
| Attribute | Type | Description |
|---|---|---|
downloaded | list[str] | Tile names successfully downloaded in this run. |
failed | list[dict] | Tiles that failed download. Each dict has tile (str) and reason (str) keys. |
not_found | list[str] | Tile names whose files could not be located on S3. |
existing | list[str] | Tile names already downloaded, verified, and up to date. |
filtered_out | list[str] | Tiles excluded by the resolution filter. Empty when no filter is active. |
missing_reset | list[str] | Tiles previously downloaded but missing from disk. |
available_tiles_intersecting_aoi | int | Number of tiles with valid metadata intersecting the area of interest geometry. Includes tiles already tracked. |
new_tiles_tracked | int | Number of tiles actually newly added to tracking in this run. Tiles already in the database are not counted. |
tile_resolution_filter | list[int] | None | Resolution 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.
| Attribute | Type | Description |
|---|---|---|
built | list[dict] | UTM zones that were built. Each dict has utm (str), mosaic (str), ovr (str or None), and hillshade (str or None) keys. |
skipped | list[str] | UTM zone identifiers that were already up to date, or had no matching tiles after resolution filtering. |
failed | list[dict] | UTM zones that failed during the build. Each dict has utm (str) and reason (str) keys. |
missing_reset | list[str] | UTM zones reset due to mosaic files missing on disk. |
hillshades | list[dict] | UTM zones where a hillshade was generated. Each dict has utm (str) and hillshade (str, absolute path) keys. |
tile_resolution_filter | list[int] | None | Resolution filter that was active, or None if unfiltered. |
mosaic_resolution_target | float | None | Output 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
| Parameter | Type | Default | Description |
|---|---|---|---|
project_dir | str | required | Absolute path to the project directory. |
data_source | str | None | None | A known source name, or None (defaults to "bluetopo"). |
verbosity | str | "normal" | Logging verbosity: "quiet" suppresses all log output, "normal" shows UTM/resolution counts, "verbose" shows individual tiles. |
Returns: StatusResult
Raises
| Exception | Condition |
|---|---|
ValueError | project_dir is not an absolute path. |
ValueError | Project directory does not exist. |
ValueError | Registry database not found (fetch_tiles must run first). |
ValueError | Rate limit exceeded. |
RuntimeError | Remote 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.
| Attribute | Type | Description |
|---|---|---|
up_to_date | list[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_available | list[dict] | Tiles with a newer delivery datetime on S3. Each dict has tile, utm, resolution, local_datetime, remote_datetime, and geometry keys. |
missing_from_disk | list[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_nbs | list[dict] | Tiles tracked locally that no longer appear in the remote geopackage. Each dict has tile, utm, resolution, local_datetime, and geometry keys. |
total_tracked | int | Total 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 form | Long form | Description |
|---|---|---|
-d | --dir, --directory | Required. Absolute path to the project directory. |
-g | --geom, --geometry | Geometry input (file path, bounding box, WKT, or GeoJSON). String inputs assume EPSG:4326. |
-s | --source, --data-source | Data source identifier. Default: bluetopo. |
--tile-resolution-filter | Only fetch tiles at these resolutions (meters). Multiple values allowed. | |
--debug | Write a diagnostic report to the project directory. | |
--json | Print result as JSON to stdout. | |
-v | --version | Show 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 form | Long form | Description |
|---|---|---|
-d | --dir, --directory | Required. Absolute path to the project directory. |
-s | --source, --data-source | Data source identifier. Default: bluetopo. |
-r | --relative-to-vrt | Store VRT file paths as relative. Default: true. |
-t | --mosaic-resolution-target | Force output pixel size in meters (any positive number). |
--tile-resolution-filter | Only include tiles at these resolutions (meters). Multiple values allowed. | |
--hillshade | Generate a hillshade GeoTIFF from the elevation band. | |
--workers | Number of parallel worker processes for building UTM zones. | |
--reproject | Reproject to EPSG:3857 (Web Mercator) GeoTIFFs. | |
-o | --output-dir | Custom output directory name within the project directory. |
--debug | Write a diagnostic report to the project directory. | |
--json | Print result as JSON to stdout. | |
-v | --version | Show 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 form | Long form | Description |
|---|---|---|
-d | --dir, --directory | Required. Absolute path to the project directory. |
-s | --source, --data-source | Data source identifier. Default: bluetopo. |
--verbosity | Logging verbosity: quiet, normal (default), or verbose. | |
--json | Print 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
- National Bathymetric Source
- BlueTopo
- G. A. Rice, Wyllie, K., Gallagher, B., and Geleg, P., “The National Bathymetric Source”, OCEANS 2023 - MTS/IEEE U.S. Gulf Coast. Biloxi, MS, pp. 1-7, 2023.
- noaabathymetry Python package
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_sourceargument 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.