Protocols#
Run does not import Catchment, and Catchment does not inherit from anything in the run
layer. What connects them is stated here: the run layer owns the interfaces, and Catchment
satisfies them structurally.
That is dependency inversion, and it buys two checkable things. hapi.run and hapi.wrapper
carry no runtime dependency on the concrete class, so the arrow between the modules points the
other way. And the requirement is checked by mypy, where it used to live in prose in each
method's docstring — prose does not fail CI.
CatchmentLike is deliberately builder-shaped: its fields really are optional, because a
half-built catchment is a legitimate state. Narrowing it into a run
(see Runs) is where the optionality is resolved.
CatchmentLike#
hapi.protocols.CatchmentLike
#
Bases: Protocol
A catchment under assembly: the period is settled, the inputs may not be.
Every field but period is optional, because that is the truth about a builder -- and it
is why an entry point narrows before it runs anything, rather than dereferencing these.
Attributes:
| Name | Type | Description |
|---|---|---|
period |
SimulationPeriod
|
The span the model covers. Settled at construction, so never |
meteo |
MeteoInputs | None
|
The three driver cubes, once assigned. |
flow_network |
FlowNetwork | None
|
The routing network and grid, once assigned. |
parameters |
ParameterSet | None
|
The parameter set, once |
model_setup |
ConceptualModelSetup | None
|
The conceptual model, once |
data |
ndarray | None
|
The lumped driver record, once |
river_geometry |
RiverGeometry | None
|
The hydraulic rasters, once |
flow_path_length_arr |
ndarray | None
|
The flow-path-length raster, once read. |
routing_method |
str
|
Which routing the parameter set was calibrated for. |
results |
SimulationResults | None
|
Where a run's output lands. |
Source code in src/hapi/protocols.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
SupportsQsim#
hapi.protocols.SupportsQsim
#
Bases: CatchmentLike, Protocol
A catchment that also has somewhere for a lumped hydrograph to land.
Attributes:
| Name | Type | Description |
|---|---|---|
Qsim |
Any
|
Where |
Source code in src/hapi/protocols.py
66 67 68 69 70 71 72 73 | |
SpatialDistribution#
hapi.protocols.SpatialDistribution
#
Bases: Protocol
What a calibration needs of the thing that maps a flat vector onto the model's grid.
The optimiser searches over a flat vector; the model runs on a (rows, cols, n) array. A
spatial-distribution object is what converts one into the other, and
:class:hapi.rrm.parameters.Parameters is the implementation that ships here.
The calibration entry points used to type this argument Callable[..., Any], which was
doubly wrong: a calibration never calls it, and what it actually does is read four members
off it. So the annotation described a function while the code used an object, and mypy had
nothing to check the four accesses against.
Attributes:
| Name | Type | Description |
|---|---|---|
Function |
Callable[..., Any]
|
The distribution strategy, chosen by |
Par3d |
ndarray
|
The |
no_parameters |
int
|
Parameters per cell. Strides the Muskingum K/X pairs out of the trial vector when the constraints are built. |
no_elem |
int
|
Cells inside the domain. Sizes the two inequality constraints per cell. |
Source code in src/hapi/protocols.py
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |