netcdf_utils module for NetCDF input¶
See also
The netcdf_utils module provides the Python layer for reading NetCDF
topography and meteorological forcing files in GeoClaw. It handles CF
attribute parsing, coordinate convention detection, unit resolution
(recognized non-contract units are converted via a scale factor; missing or
unrecognized units raise), and descriptor writing so that Fortran only needs
to open the file and read pre-validated indices.
The main classes are:
NetCDFInspector— base class; coordinate discovery, fill-value resolution, crop-bound validation.TopoInspector— topography subclass; fill-value checking within the crop region, unit enforcement.MetInspector— meteorological subclass; wind/pressure variable discovery, CF datetime decoding, unit resolution (recognized non-contract units converted, with a storm-format fallback for missing units; unrecognized units raise), and a magnitude sanity check.CFNormalizer— adds or repairs CF attributes in place without modifying data values.DescriptorWriter— writes the key=value topo descriptor lines or the&file_info/&variable_infoFortran namelist blocks for met forcing.
Documentation auto-generated from the module docstrings¶
NetCDF utilities for GeoClaw NetCDF input.
Provides inspector classes that inspect NetCDF files for coordinate metadata, unit consistency, and fill values without loading data arrays. The inspectors produce metadata dataclasses consumed by DescriptorWriter (not yet implemented — pending confirmation of Fortran topo.data parser).
Classes¶
- NetCDFInspector
Base class: opens a file, discovers coordinate variables, detects lon/lat conventions, resolves fill value, validates crop bounds.
- TopoInspector(NetCDFInspector)
Adds bathymetry-specific checks: fill values within crop region (fatal), unit verification against GEOCLAW_NETCDF_UNITS[‘topo’].
- MetInspector(NetCDFInspector)
Adds met-forcing checks: multi-variable grid/time consistency, unit verification and conversion to contract units, CF time -> seconds offset, ensemble dimension detection.
- CFNormalizer
Standalone utility: renames coordinates to CF standard names, adds/fixes standard_name / axis / units / _FillValue attributes, resolves _FillValue vs missing_value conflicts. Does not resample or reproject.
Metadata dataclasses¶
FileMetadata, TopoMetadata, MetVariableInfo, MetMetadata
- class clawpack.geoclaw.netcdf_utils.CFNormalizer(ds: Dataset)¶
Bases:
objectNormalize CF metadata in an xarray Dataset.
Performs in-memory attribute fixups: * Renames coordinate variables to CF standard names where unambiguous. * Adds
standard_name,axis, andunitsattributes to coordinatevariables if missing.
Resolves
_FillValuevsmissing_valueconflicts (CF precedence:_FillValuewins;missing_valueis promoted if_FillValueabsent; conflict triggers a warning).
Does NOT resample, reproject, or modify data values.
Parameters¶
- dsxr.Dataset
Dataset to normalise. A copy is made; the original is not modified.
Examples¶
>>> ds_norm = CFNormalizer(ds).normalize()
- normalize() Dataset¶
Apply all normalizations and return the modified dataset.
- class clawpack.geoclaw.netcdf_utils.DTopoInspector(path: str | Path, var_name: str | None = None, time_reference: str | None = None, crop_bounds: tuple[float, float, float, float] | None = None, assume_units: str | None = None)¶
Bases:
NetCDFInspectorInterrogate a NetCDF moving-topography (dtopo) file.
Required roles: longitude, latitude, time, and the deformation (dZ) variable. Beyond the base class this:
Discovers the deformation variable (by common names, else the unique 3-D data variable).
Requires time to be the variable’s slowest (first) dimension.
Validates that the time axis is uniformly spaced — the Fortran dtopo machinery reconstructs times as t0 + k*dt.
Converts the time axis to simulation seconds: numeric time values pass through unchanged; CF datetime values require an explicit time_reference and become seconds since that reference.
Parameters¶
- pathstr or Path
Path to the NetCDF file.
- var_namestr, optional
Name of the deformation variable; auto-discovered if omitted.
- time_referencestr or datetime-like, optional
Reference datetime when the file’s time axis decodes to datetimes.
- crop_boundstuple of four floats, optional
(lon_min, lon_max, lat_min, lat_max); validated against file extent.
- inspect_dtopo() DTopoMetadata¶
Fully inspect the dtopo file and return a DTopoMetadata.
Verifies deformation units (meters), records the source unit on
self.source_units, and stores ascale_factorin the metadata. A recognised non-meter unit yields a scale_factor (applied in memory byDTopography.reador by Fortran via the descriptor); a missing or unrecognised unit still raises (units are never assumed).
- class clawpack.geoclaw.netcdf_utils.DTopoMetadata(source_file: Path, x_name: str, y_name: str, time_name: str | None, lon_wrap: int | None, y_increasing: bool, dim_order: list[str], fill_value: float | None, crop_bounds: tuple[float, float, float, float] | None, var_name: str, t0: float, dt: float, mt: int, lon_wrap_offset: float = 0.0, scale_factor: float = 1.0)¶
Bases:
FileMetadataFileMetadata plus dtopo-specific fields.
The time axis is collapsed to (t0, dt) in simulation seconds: the Fortran dtopo machinery requires uniform time spacing and reconstructs times as t0 + k*dt, so Fortran never parses the file’s time variable.
- dt: float¶
- lon_wrap_offset: float = 0.0¶
- mt: int¶
- scale_factor: float = 1.0¶
- t0: float¶
- var_name: str¶
- class clawpack.geoclaw.netcdf_utils.DescriptorWriter¶
Bases:
objectWrite NetCDF descriptor metadata for GeoClaw input files.
For topo (type 4) entries the descriptor is a block of
key = valuelines written immediately after thetopo_typeline in topo.data. Fortran’sread_netcdf_descriptorparses these lines until it encounters a blank line.Usage — topo:
meta = TopoInspector(path, var_name='z').inspect_topo() with open('topo.data', 'a') as f: DescriptorWriter.write_topo_descriptor(f, meta)
Usage — met (storm file):
meta = MetInspector(path, var_map).inspect_met() with open('storm.nc', 'w') as f: f.write('netcdf\n') # format header written by caller DescriptorWriter.write_met_descriptor(f, meta)
- static write_dtopo_descriptor(f, meta: DTopoMetadata) None¶
Write the key=value descriptor block for one dtopo file.
Same format and parser contract as the topo descriptor (a blank line terminates the block), written immediately after the 9-line per-file block in dtopo.data. The time axis is carried as (t0, dt) in simulation seconds so Fortran never parses CF time.
Parameters¶
- ffile-like object
Open for writing (text mode).
- metaDTopoMetadata
Output of
DTopoInspector.inspect_dtopo().
- static write_met_descriptor(f, meta: MetMetadata) None¶
Write the
&file_info/&variable_infonamelist-style body of a GeoClaw NetCDF met/storm descriptor file.The caller is responsible for writing the
netcdfformat header line before calling this method.Parameters¶
- ffile-like object
Open for writing (text mode).
- metaMetMetadata
Output of
MetInspector.inspect_met().
- static write_topo_descriptor(f, meta: TopoMetadata) None¶
Write the key=value descriptor block for one topo file.
f should be positioned immediately after the
topo_typeline has been written. A trailing blank line is written to terminate the block for the Fortran parser.Parameters¶
- ffile-like object
Open for writing (text mode).
- metaTopoMetadata
Output of
TopoInspector.inspect_topo().
- class clawpack.geoclaw.netcdf_utils.FileMetadata(source_file: Path, x_name: str, y_name: str, time_name: str | None, lon_wrap: int | None, y_increasing: bool, dim_order: list[str], fill_value: float | None, crop_bounds: tuple[float, float, float, float] | None)¶
Bases:
objectCoordinate and convention metadata for a single NetCDF file.
- crop_bounds: tuple[float, float, float, float] | None¶
- dim_order: list[str]¶
- fill_value: float | None¶
- lon_wrap: int | None¶
- source_file: Path¶
- time_name: str | None¶
- x_name: str¶
- y_increasing: bool¶
- y_name: str¶
- class clawpack.geoclaw.netcdf_utils.MetInspector(path: str | Path, variable_map: dict[str, str] | None = None, crop_bounds: tuple[float, float, float, float] | None = None, time_reference: str | None = None, fill_action: str = 'warn', assume_units: bool = False, format_units: dict[str, str] | None = None, skip_sanity_check: bool = False)¶
Bases:
NetCDFInspectorInterrogate a NetCDF meteorological forcing file.
Additional checks beyond the base class:
Verifies that all requested variables share the same spatial grid and time axis.
Validates and (if needed) converts units to contract units via units.py.
Converts CF time to seconds from a user-provided reference offset.
Detects ensemble/member dimensions and raises if any are non-singleton.
Parameters¶
- pathstr or Path
Path to the NetCDF file.
- variable_mapdict, optional
Maps GeoClaw role strings to variable names in the file, e.g.:
{'wind_u': 'u10', 'wind_v': 'v10', 'pressure': 'msl'}
Roles not given (or the whole map, when omitted) are auto-discovered by CF
standard_namefirst, then by common variable names. An explicit entry overrides discovery for that role.- crop_boundstuple of four floats, optional
(lon_min, lon_max, lat_min, lat_max).
- time_referencestr or datetime-like, optional
Reference datetime for the time_offset calculation. The
time_offsetwritten to the descriptor will be the number of seconds between time_reference and the first time in the file. Defaults to the Unix epoch (1970-01-01T00:00:00).- fill_actionstr, optional
‘abort’ or ‘warn’. Met files may legitimately have fill values at the domain edges (Fortran handles edge fill). Default is ‘warn’.
- assume_unitsbool, optional
Explicit escape hatch for a file whose forcing variables have no
unitsattribute. When True, each variable is assumed to already be in its contract unit instead of raising. This must be set deliberately; missing units are never silently assumed.- format_unitsdict, optional
{geoclaw_role: unit_string}giving the units documented by the storm format (e.g. NWS13/OWI pressure ismbar). Used only for a variable that has nounitsattribute: the format’s documented unit is assumed and converted (e.g. mbar -> Pa). Takes precedence overassume_unitsfor the roles it covers.- skip_sanity_checkbool, optional
Skip the post-unit-resolution magnitude sanity check on pressure/wind (see
_check_magnitude). Escape hatch for exotic-but-valid files; defaults to False.
- inspect_met() MetMetadata¶
Fully inspect the met file and return a MetMetadata instance.
Roles missing from variable_map are auto-discovered (CF standard_name first, then common variable names).
- class clawpack.geoclaw.netcdf_utils.MetMetadata(source_file: Path, x_name: str, y_name: str, time_name: str | None, lon_wrap: int | None, y_increasing: bool, dim_order: list[str], fill_value: float | None, crop_bounds: tuple[float, float, float, float] | None, variables: list[MetVariableInfo], time_offset: float, fill_action: str, time_scale: float = 1.0)¶
Bases:
FileMetadataFileMetadata plus met-forcing-specific fields.
- fill_action: str¶
- time_offset: float¶
- time_scale: float = 1.0¶
- variables: list[MetVariableInfo]¶
- class clawpack.geoclaw.netcdf_utils.MetVariableInfo(var_name: str, geoclaw_role: str, source_units: str, scale_factor: float = 1.0)¶
Bases:
objectMaps one NetCDF variable to its GeoClaw role.
- geoclaw_role: str¶
- scale_factor: float = 1.0¶
- source_units: str¶
- var_name: str¶
- class clawpack.geoclaw.netcdf_utils.NetCDFInspector(path: str | Path, crop_bounds: tuple[float, float, float, float] | None = None)¶
Bases:
objectOpen a NetCDF file and inspect its coordinate metadata.
No data arrays are loaded; only coordinate values and variable attributes are accessed. Dask-lazy chunking is enabled so that any accidental downstream .compute() calls are bounded.
Parameters¶
- pathstr or Path
Path to the NetCDF file.
- crop_boundstuple of four floats, optional
(lon_min, lon_max, lat_min, lat_max) in the same convention as the file. When provided, bounds are validated against file extent.
- close() None¶
- ds: Dataset¶
- inspect(var_name: str, time_name_override: str | None = None) FileMetadata¶
Interrogate var_name and return a FileMetadata instance.
Parameters¶
- var_namestr
Name of the primary data variable (used to determine dim_order).
- time_name_overridestr, optional
Force a specific time coordinate name instead of auto-detecting.
- class clawpack.geoclaw.netcdf_utils.TopoInspector(path: str | Path, var_name: str | None = None, crop_bounds: tuple[float, float, float, float] | None = None, assume_units: str | None = None, skip_sanity_check: bool = False)¶
Bases:
NetCDFInspectorInterrogate a NetCDF bathymetry/topography file.
Additional checks beyond the base class:
Verifies the data variable’s units attribute matches the contract unit (meters). If units are convertible via units.py, records the source units in the metadata; Fortran will need a conversion factor. If units are unrecognised, raises ValueError.
Checks for fill values (NaN) within the crop region and raises ValueError — silent NaN in bathymetry is numerically fatal.
Parameters¶
- pathstr or Path
Path to the NetCDF topography file.
- var_namestr, optional
Name of the elevation/bathymetry variable (e.g.
'z','elevation'). If omitted, the variable is auto-detected by searching for known CFstandard_namevalues (surface_altitude,height_above_mean_sea_level, …) and then falling back to common names (z,elevation,topo, …). AValueErroris raised if no match is found.- crop_boundstuple of four floats, optional
(lon_min, lon_max, lat_min, lat_max).
- assume_unitsstr, optional
Explicit escape hatch for a file whose elevation variable has no
unitsattribute. When given (e.g.'m'), that unit is assumed instead of raising. This must be set deliberately by the caller; missing units are never silently assumed.- skip_sanity_checkbool, optional
Skip the post-unit-resolution magnitude sanity check (see
_check_magnitude). Escape hatch for exotic-but-valid files; defaults to False.
- inspect_topo() TopoMetadata¶
Fully inspect the topo file and return a TopoMetadata instance.
- topo_entries() list[list]¶
Return a list of ready-to-use topo entries for topofiles.
Each entry is [4, filepath, TopoMetadata]. When no wrapping is needed this returns a list of one entry. When crop_bounds straddle the file’s lon cut point, returns two entries pointing to the same file with different lon_wrap_offset and crop_bounds values.
crop_bounds on the inspector are in domain coordinates; this method converts them to file coordinates before storing in the returned metadata. Fortran can then use crop_bounds directly against file coordinate arrays before applying lon_wrap_offset.
- class clawpack.geoclaw.netcdf_utils.TopoMetadata(source_file: Path, x_name: str, y_name: str, time_name: str | None, lon_wrap: int | None, y_increasing: bool, dim_order: list[str], fill_value: float | None, crop_bounds: tuple[float, float, float, float] | None, var_name: str, source_units: str, fill_action: str, lon_wrap_offset: float = 0.0, scale_factor: float = 1.0)¶
Bases:
FileMetadataFileMetadata plus topo-specific fields.
- fill_action: str¶
- lon_wrap_offset: float = 0.0¶
- scale_factor: float = 1.0¶
- source_units: str¶
- var_name: str¶
- clawpack.geoclaw.netcdf_utils.compression_encoding(compression, chunksizes=None) dict¶
Translate a
compressionargument into an xarray encoding fragment.GeoClaw’s NetCDF writers pass a user-facing
compressionoption through here to build the per-variableencodingdict forto_netcdf. netCDF zlib compression is transparent to readers (the netCDF-C library, and hence the Fortran reader, decompresses on read) and, being chunked, keeps the file randomly accessible – unlike an externally gzipped.nc.Parameters¶
- compressionNone | bool | int | dict
None/False-> no compression (empty fragment; files stay bit-identical to the uncompressed default).True-> the recommended default, zlib level 1 with the byteshufflefilter (level 1 captures nearly all the size gain; higher levels cost CPU for little more).int-> zlib at thatcomplevel(1–9) withshuffle.dict-> used verbatim (full control, e.g.{'zlib': True, 'complevel': 4, 'shuffle': False}).
- chunksizestuple, optional
netCDF chunk shape, applied only when compression is enabled and the caller supplies it (zlib requires chunking; a per-time-slice chunk also matches how Fortran reads dtopo/met time slices). A
dictcompression that already setschunksizesis left untouched.
Returns¶
- dict
Encoding keys to merge into the variable’s
encodingentry.
- clawpack.geoclaw.netcdf_utils.suppress_netcdf4_shape_warning()¶
Silence netCDF4-python’s spurious NumPy 2.5 shape-assignment warning.
netCDF4.Variable.__setitem__reshapes the incoming array in place viadata.shape = ...(seenetCDF4/_netCDF4.pyx), which NumPy >= 2.5 now deprecates in favor ofnp.reshape. This is entirely internal to netCDF4-python (as of 1.7.4, the latest release) and not something callers can avoid, so wrapvar[:] = ...assignments in this context manager rather than letting the warning leak into test output. Safe to remove once netCDF4-python ships a fix upstream.