Bathymetry¶
The XBeachBathy class handles bathymetry data processing for XBeach simulations. It provides powerful capabilities for interpolating source data onto the model grid, extending the domain offshore, and handling coordinate system transformations.
Why a Bathymetry Abstraction?¶
Bathymetry data rarely comes in the exact format XBeach needs:
- Different CRS — Source data may be in WGS84 while the grid uses a projected CRS
- Different resolution — Source data resolution may not match the model grid
- Insufficient extent — Nearshore surveys often don't extend far enough offshore
- Missing data — Gaps in coverage need interpolation
XBeachBathy addresses all these challenges automatically.
Basic Usage¶
from rompy_xbeach.data.bathy import XBeachBathy
from rompy_xbeach.source import SourceGeotiff
# Define the bathymetry source
source = SourceGeotiff(filename="bathymetry.tif")
# Create the bathymetry object
bathy = XBeachBathy(
source=source,
posdwn=False, # Depths are negative (below sea level)
)
# Generate XBeach files
xfile, yfile, depfile, grid = bathy.get(
destdir=Path("./run"),
grid=grid,
)
Source Types¶
XBeachBathy accepts any source object that provides gridded data with CRS information. Common choices for bathymetry:
| Source | Best For |
|---|---|
SourceGeotiff |
GeoTIFF raster files (most common) |
SourceXYZ |
XYZ point cloud / survey data |
SourceCRSFile |
NetCDF, Zarr, or other xarray-compatible files |
SourceCRSDataset |
Existing xarray Dataset objects |
from rompy_xbeach.source import SourceGeotiff, SourceXYZ
# GeoTIFF (simplest - CRS embedded in file)
source = SourceGeotiff(filename="bathymetry.tif")
# XYZ point data (requires gridding)
source = SourceXYZ(
filename="survey.xyz",
crs="EPSG:4326",
res=0.0005,
)
For detailed documentation on all source types and their parameters, see Sources.
Interpolation¶
How It Works¶
- Source data is opened with CRS information
- Data is reprojected to the grid CRS if needed
- Regular grid interpolation maps source data to model grid points
- Missing values are handled according to settings
Interpolator Configuration¶
The interpolator is configurable through an interface that allows different interpolation backends. Currently, a scipy-based interpolator is available, but the interface can be extended to support other interpolation methods if needed.
from rompy_xbeach.interpolate import RegularGridInterpolator
interpolator = RegularGridInterpolator(
kwargs=dict(
method="linear", # Interpolation method
fill_value=None, # Extrapolation handling
),
)
bathy = XBeachBathy(
source=source,
interpolator=interpolator,
)
The RegularGridInterpolator uses scipy.interpolate.RegularGridInterpolator under the hood. Available methods:
| Method | Description |
|---|---|
"linear" |
Bilinear interpolation (default) |
"nearest" |
Nearest neighbour |
"cubic" |
Cubic interpolation |
Handling Missing Data¶
bathy = XBeachBathy(
source=source,
interpolate_na=True, # Interpolate NaN values (default)
# interpolate_na=False # Keep NaN values
)
Depth Convention¶
XBeach supports both depth conventions via the posdwn parameter:
posdwn=True— Positive down: depths below sea level are positive valuesposdwn=False— Negative down: depths below sea level are negative values
The posdwn parameter in XBeachBathy should match your source data convention:
# Source has negative depths (below sea level = negative)
bathy = XBeachBathy(source=source, posdwn=False)
# Source has positive depths (below sea level = positive)
bathy = XBeachBathy(source=source, posdwn=True)
This setting is also written to params.txt so XBeach interprets the bathymetry correctly.
Check Your Convention
Incorrect posdwn setting will invert your bathymetry, placing deep water at the coast.
Offshore Extension¶
Nearshore surveys often don't extend far enough offshore for wave modelling. XBeachBathy can automatically extend the bathymetry seaward.
Linear Extension¶
Extends the offshore boundary with a constant slope until reaching a target depth:
from rompy_xbeach.data.bathy import SeawardExtensionLinear
extension = SeawardExtensionLinear(
depth=25, # Target depth (m)
slope=0.1, # Slope of extension (rise/run)
)
bathy = XBeachBathy(
source=source,
extension=extension,
)
The extension:
- Takes the depth at the offshore boundary
- Extends seaward with the specified slope
- Stops when reaching the target depth
- Adds new grid rows to accommodate the extension
# Gentler slope = longer extension
extension = SeawardExtensionLinear(depth=25, slope=0.02)
# Steeper slope = shorter extension
extension = SeawardExtensionLinear(depth=25, slope=0.2)
Grid Modification¶
When extension is applied, the grid is modified:
# Original grid
print(f"Original shape: {grid.shape}") # (230, 220)
# After extension
xfile, yfile, depfile, extended_grid = bathy.get(destdir, grid)
print(f"Extended shape: {extended_grid.shape}") # (280, 220)
The returned extended_grid has additional rows for the offshore extension.
Lateral Extension¶
Extend the grid laterally (alongshore) by replicating edge values:
bathy = XBeachBathy(
source=source,
left=10, # Extend left boundary by 10 cells
right=10, # Extend right boundary by 10 cells
)
This is useful when:
- Source data doesn't fully cover the alongshore extent
- You want buffer zones at lateral boundaries
Combined Extension¶
Offshore and lateral extensions can be combined:
bathy = XBeachBathy(
source=source,
extension=SeawardExtensionLinear(depth=25, slope=0.02),
left=10,
right=10,
)
Output Files¶
The get() method generates three XBeach input files:
| File | Description |
|---|---|
x.txt |
X-coordinates of grid points |
y.txt |
Y-coordinates of grid points |
dep.txt |
Depth values at grid points |
xfile, yfile, depfile, grid = bathy.get(destdir, grid)
print(xfile) # Path to x.txt
print(yfile) # Path to y.txt
print(depfile) # Path to dep.txt
Reading Output Data¶
Use the xarray accessor to read generated files:
import xarray as xr
# Read bathymetry into xarray Dataset
dset = xr.Dataset.xbeach.from_xbeach(depfile, grid)
# Plot
dset.xbeach.plot_model_bathy(grid, posdwn=False)
CRS Handling¶
Automatic Reprojection¶
Source data is automatically reprojected to match the grid CRS:
# Source in WGS84
source = SourceGeotiff(filename="bathy_wgs84.tif") # EPSG:4326
# Grid in projected CRS
grid = RegularGrid(
ori=GeoPoint(x=115.5, y=-32.6, crs="EPSG:4326"),
crs="EPSG:28350", # MGA Zone 50
# ...
)
# Bathymetry is automatically reprojected
bathy = XBeachBathy(source=source)
bathy.get(destdir, grid) # Handles CRS transformation
Mixed CRS Scenarios¶
| Source CRS | Grid CRS | Handling |
|---|---|---|
| WGS84 | Projected | Auto-reproject source to grid CRS |
| Projected | Same projected | Direct interpolation |
| Projected A | Projected B | Auto-reproject source to grid CRS |
Integration with Config¶
from rompy_xbeach.config import Config
config = Config(
grid=grid,
bathy=XBeachBathy(
source=SourceGeotiff(filename="bathymetry.tif"),
posdwn=False,
extension=SeawardExtensionLinear(depth=25, slope=0.1),
),
# ...
)
When Config is called, it:
- Generates bathymetry files via
bathy.get() - Updates grid parameters if extension was applied
- Includes file paths in
params.txt
Example: Complete Workflow¶
from pathlib import Path
from rompy_xbeach.grid import RegularGrid, GeoPoint
from rompy_xbeach.data.bathy import XBeachBathy, SeawardExtensionLinear
from rompy_xbeach.source import SourceGeotiff
from rompy_xbeach.interpolate import RegularGridInterpolator
# 1. Define the grid
grid = RegularGrid(
ori=GeoPoint(x=115.594239, y=-32.641104, crs="EPSG:4326"),
alfa=347.0,
dx=10, dy=15,
nx=230, ny=220,
crs="EPSG:28350",
)
# 2. Configure bathymetry with extension
bathy = XBeachBathy(
source=SourceGeotiff(filename="bathymetry.tif"),
posdwn=False,
interpolator=RegularGridInterpolator(
kwargs=dict(method="linear", fill_value=None)
),
extension=SeawardExtensionLinear(depth=25, slope=0.05),
left=5,
right=5,
)
# 3. Generate files
destdir = Path("./xbeach_run")
destdir.mkdir(exist_ok=True)
xfile, yfile, depfile, extended_grid = bathy.get(destdir, grid)
# 4. Verify
print(f"Original grid: {grid.shape}")
print(f"Extended grid: {extended_grid.shape}")
print(f"Files created: {list(destdir.glob('*.txt'))}")
# 5. Visualise
import xarray as xr
dset = xr.Dataset.xbeach.from_xbeach(depfile, extended_grid)
dset.xbeach.plot_model_bathy(extended_grid, posdwn=False)
Troubleshooting¶
Inverted Bathymetry¶
Symptom: Deep water appears at the coast, shallow water offshore.
Cause: Incorrect posdwn setting or grid orientation.
Fix:
Missing Data at Boundaries¶
Symptom: NaN values at grid edges.
Cause: Source data doesn't fully cover the grid extent.
Fix:
# Use lateral extension
bathy = XBeachBathy(source=source, left=10, right=10)
# Or use extrapolation in interpolator
interpolator = RegularGridInterpolator(
kwargs=dict(method="nearest", fill_value=None)
)
CRS Mismatch Errors¶
Symptom: Interpolation produces unexpected results or errors.
Cause: Source CRS not correctly specified.
Fix:
# Explicitly set source CRS
source = SourceCRSDataset(
uri="bathymetry.nc",
crs="EPSG:4326", # Specify explicitly
)
See Also¶
- Grid — Grid definition and CRS handling
- Examples: Bathymetry Demo — Interactive notebook with detailed examples