Surface#

class hydromodpy.spatial.Surface(name, values, support=None)[source]#

Bases: object

One raster-like surface plus its optional spatial support.

Parameters#

namestr

Human-readable surface name (for example "surface_topo" or "substratum").

valuesAny

2D array-like values of the surface.

supportRasterSupport | None

Optional spatial support describing where this 2D array is located in space. The values remain usable without it, but any georeferenced use case should attach one.

param name:

type name:

str

param values:

type values:

Any

param support:

type support:

RasterSupport | None

classmethod from_geographic_dem(dem_values, *, support=None, name='surface_topo')[source]#

Build one surface from explicit DEM values.

This constructor does not read from CatchmentDelineation directly. The caller must provide: - the already-extracted DEM values, - and, when available, the matching RasterSupport.

Parameters:
Return type:

Surface

as_array()[source]#

Return the surface values as a float NumPy array.

This is the canonical internal representation used by all numerical operations in this module.

Return type:

ndarray

assert_support_matches_values()[source]#

Ensure the internal array shape is consistent with attached support.

This is intentionally lightweight and only validates local coherence. Pairwise domain consistency between two surfaces is handled by assert_same_geographic_domain.

Return type:

None

assert_same_geographic_domain(other, *, atol=1e-09)[source]#

Validate that two surfaces are defined on the exact same geographic domain.

The check is delegated to RasterSupport.assert_same_geographic_domain and also verifies that each surface values-array is coherent with its own support dimensions.

Parameters:
Return type:

None

resample_to_shape(nrows, ncols, *, resampling='bilinear', nodata=None, name=None)[source]#

Return one new surface re-discretized to (nrows, ncols).

Geographic extent and CRS are preserved; only raster resolution changes.

Parameters:
Return type:

Surface

shifted_down_by(offset, *, name='substratum')[source]#

Return a new surface shifted downward by one constant offset.

The returned surface: - keeps the same raster support as the current one, - uses a new 2D array equal to self - offset, - leaves a NODATA cell AT the sentinel instead of shifting it.

The sentinel must not move. The support is shared by reference, so it keeps advertising the same nodata value, and every consumer recognises a no-data cell by exact equality with it (surface_sampling, the discretization guard, the zonal statistics). Shifting -9999 to -9999 - offset silently turns the sentinel into an ordinary elevation: it is then interpolated as if it were terrain, and a mesh cell whose stencil straddles the mask edge inherits a bottom dragged toward it. Such a cell has no idomain signature either, because the top of that same cell is clean: it stays active and carries a column kilometres thick, with the transmissivity and the storage that go with it.

Return type:

Surface

Parameters:

Example#

If self stores the topography and offset=50, the returned surface is topography - 50 on every cell carrying data.

param offset:

type offset:

float

param name:

type name:

str

flat_like(value, *, name='substratum', min_gap=1.0)[source]#

Return a flat (constant-elevation) substratum below this surface.

The returned surface is value on every cell whose top sits strictly above value + min_gap. Where the top drops to or below that level the cell has no aquifer (basement outcrop, or a NODATA sentinel left by a watershed-masked / out-of-DEM cell): the bottom is clamped to top - min_gap so the column stays a thin degenerate cell that the mesh masks out, instead of inverting (bottom above top). This mirrors shifted_down_by on those cells, so a flat substratum behaves like a constant thickness there and never trips the strict-ordering guard.

Return type:

Surface

Parameters:

Example#

If value=20 and the terrain is 56..83 m, every cell gets a flat bottom at 20 m. A NODATA cell (top -9999) is clamped to -10000.

param value:

type value:

float

param name:

type name:

str

param min_gap:

type min_gap:

float

assert_strictly_below(upper_surface)[source]#

Validate that this surface is strictly lower than upper_surface.

Return type:

None

Parameters:

upper_surface (Surface)

Validation rules#

  • both surfaces must have the same 2D shape,

  • only finite overlapping cells are checked,

  • at every checked cell, self < upper_surface must hold.

A ValueError is raised when: - shapes are incompatible, - there is no finite overlap, - or at least one cell violates the strict ordering.

param upper_surface:

type upper_surface:

Surface

Parameters: