Skip to content

Run#

Run#

hapi.run.Run #

Bases: Catchment

Run the catchment model.

The Run sub-class validates the spatial data and hands it to the Wrapper class. It is a sub-class of the Catchment class, so you need to create the Catchment object first to run the model.

Methods:

Name Description
RunHapi

Run the distributed hydrological model.

runHAPIwithLake

Run the distributed model with a lake component.

runFW1

Run the FW1 distributed model.

RunFW1withLake

Run the FW1 model with a lake component.

runLumped

Run the lumped conceptual model.

Source code in src/hapi/run.py
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 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
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
class Run(Catchment):
    """Run the catchment model.

    The Run sub-class validates the spatial data and hands it to the
    Wrapper class. It is a sub-class of the Catchment class, so you
    need to create the Catchment object first to run the model.

    Methods:
        RunHapi: Run the distributed hydrological model.
        runHAPIwithLake: Run the distributed model with a lake component.
        runFW1: Run the FW1 distributed model.
        RunFW1withLake: Run the FW1 model with a lake component.
        runLumped: Run the lumped conceptual model.
    """

    def __init__(self):
        """Initialize the Run class."""
        self.Qsim: np.ndarray | pd.DataFrame | None = None

    def RunHapi(self):
        """Run the distributed hydrological model.

        Validates that all input arrays (precipitation, evapotranspiration,
        temperature, parameters, and flow direction) have consistent
        dimensions, then executes the rainfall-runoff model via the
        Wrapper.

        The following instance attributes are set after execution:

        - ``state_variables``: 4D array (rows, cols, time, states) where
          states are [sp, wc, sm, uz, lv].
        - ``qlz``: 3D array of the lower zone discharge.
        - ``quz``: 3D array of the upper zone discharge.
        - ``qout``: 1D timeseries of discharge at the catchment outlet
          in m3/sec.
        - ``quz_routed``: 3D array of the upper zone discharge
          accumulated and routed at each time step.
        - ``qlz_translated``: 3D array of the lower zone discharge
          translated at each time step.

        Raises:
            AssertionError: If input data arrays have inconsistent
                row counts, column counts, or temporal lengths.
        """
        # input dimensions
        [fd_rows, fd_cols] = self.flow_dir_arr.shape
        assert fd_rows == self.rows and fd_cols == self.cols, (
            "all input data should have the same number of rows"
        )

        # input dimensions
        assert (
            np.shape(self.Prec)[0] == self.rows
            and np.shape(self.ET)[0] == self.rows
            and np.shape(self.Temp)[0] == self.rows
            and np.shape(self.Parameters)[0] == self.rows
        ), "all input data should have the same number of rows"
        assert (
            np.shape(self.Prec)[1] == self.cols
            and np.shape(self.ET)[1] == self.cols
            and np.shape(self.Temp)[1] == self.cols
            and np.shape(self.Parameters)[1] == self.cols
        ), "all input data should have the same number of columns"
        assert (
            np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
        ), "all meteorological input data should have the same length"

        # run the model
        Wrapper.RRMModel(self)

        print("Model Run has finished")

    def RunFloodModel(self):
        """Run the flood model.

        Runs the conceptual distributed hydrological model with
        additional validation for river geometry inputs (bankfull depth,
        river width, river roughness, and flood plain roughness).

        Raises:
            AssertionError: If meteorological input arrays, parameter
                arrays, or river geometry arrays have inconsistent
                dimensions.
        """
        # input dimensions
        [fd_rows, fd_cols] = self.flow_dir_arr.shape
        assert fd_rows == self.rows and fd_cols == self.cols, (
            "all input data should have the same number of rows"
        )

        # input dimensions
        assert (
            np.shape(self.Prec)[0] == self.rows
            and np.shape(self.ET)[0] == self.rows
            and np.shape(self.Temp)[0] == self.rows
            and np.shape(self.Parameters)[0] == self.rows
        ), "all input data should have the same number of rows"
        assert (
            np.shape(self.Prec)[1] == self.cols
            and np.shape(self.ET)[1] == self.cols
            and np.shape(self.Temp)[1] == self.cols
            and np.shape(self.Parameters)[1] == self.cols
        ), "all input data should have the same number of columns"
        assert (
            np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
        ), "all meteorological input data should have the same length"

        assert (
            np.shape(self.BankfullDepth)[0] == self.rows
            and np.shape(self.RiverWidth)[0] == self.rows
            and np.shape(self.RiverRoughness)[0] == self.rows
            and np.shape(self.FloodPlainRoughness)[0] == self.rows
        ), "all input data should have the same number of rows"
        assert (
            np.shape(self.BankfullDepth)[1] == self.cols
            and np.shape(self.RiverWidth)[1] == self.cols
            and np.shape(self.RiverRoughness)[1] == self.cols
            and np.shape(self.FloodPlainRoughness)[1] == self.cols
        ), "all input data should have the same number of columns"

        # run the model
        Wrapper.RRMModel(self)
        print("RRM has finished")
        # SV = SaintVenant()
        # SV.KinematicRaster(self)
        # print("1D model Run has finished")

    def runHAPIwithLake(self, lake: LakeType):
        """Run the distributed model with a lake component.

        Validates that all input arrays have consistent dimensions and
        that the lake meteorological data matches the simulation period,
        then executes the rainfall-runoff model with lake routing via
        the Wrapper.

        Args:
            lake: Lake object containing lake configuration and
                meteorological data. Must have a ``MeteoData`` attribute
                with shape ``(time_steps, >= 3)`` where columns are
                rain, ET, and temperature.

        Raises:
            AssertionError: If input data arrays have inconsistent
                dimensions or if the lake meteorological data length
                does not match the distributed raster data length.
        """
        # input dimensions
        [fd_rows, fd_cols] = self.flow_dir_arr.shape
        assert fd_rows == self.rows and fd_cols == self.cols, (
            "all input data should have the same number of rows and columns"
        )

        # input dimensions
        assert (
            np.shape(self.Prec)[0] == self.rows
            and np.shape(self.ET)[0] == self.rows
            and np.shape(self.Temp)[0] == self.rows
            and np.shape(self.Parameters)[0] == self.rows
        ), "all input data should have the same number of rows"
        assert (
            np.shape(self.Prec)[1] == self.cols
            and np.shape(self.ET)[1] == self.cols
            and np.shape(self.Temp)[1] == self.cols
            and np.shape(self.Parameters)[1] == self.cols
        ), "all input data should have the same number of columns"
        assert (
            np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
        ), "all meteorological input data should have the same length"

        assert np.shape(lake.MeteoData)[0] == np.shape(self.Prec)[2], (
            "Lake meteorological data has to have the same length as the distributed raster data"
        )
        assert np.shape(lake.MeteoData)[1] >= 3, (
            "Lake Meteo data has to have at least three columns of rain, ET, and Temp"
        )

        # run the model
        Wrapper.RRMWithlake(self, lake)

        print("Model Run has finished")

    def runFW1(self):
        """Run the FW1 distributed hydrological model.

        Validates that all input arrays have consistent dimensions,
        then executes the FW1 model via the Wrapper.

        The following instance attributes are set after execution:

        - ``st``: 4D array of state variables.
        - ``q_out``: 1D array of calculated discharge at the catchment
          outlet.
        - ``q_uz``: 3D array of distributed discharge for each cell.

        Raises:
            AssertionError: If input data arrays have inconsistent
                row counts, column counts, or temporal lengths.
        """
        assert (
            np.shape(self.Prec)[0] == self.rows
            and np.shape(self.ET)[0] == self.rows
            and np.shape(self.Temp)[0] == self.rows
            and np.shape(self.Parameters)[0] == self.rows
        ), "all input data should have the same number of rows"
        assert (
            np.shape(self.Prec)[1] == self.cols
            and np.shape(self.ET)[1] == self.cols
            and np.shape(self.Temp)[1] == self.cols
            and np.shape(self.Parameters)[1] == self.cols
        ), "all input data should have the same number of columns"
        assert (
            np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
        ), "all meteorological input data should have the same length"

        # run the model
        Wrapper.FW1(self)

        print("Model Run has finished")

    def RunFW1withLake(self, lake: LakeType):
        """Run the FW1 distributed model with a lake component.

        Validates that all input arrays have consistent dimensions and
        that the lake meteorological data matches the simulation period,
        then executes the FW1 model with lake routing via the Wrapper.

        Args:
            lake: Lake object containing lake configuration and
                meteorological data. Must have a ``MeteoData`` attribute
                with shape ``(time_steps, >= 3)`` where columns are
                rain, ET, and temperature.

        Note:
            The following catchment attributes should be set before
            calling this method:

            - ``prec_path``: Path to the folder containing precipitation
              rasters.
            - ``evap_path``: Path to the folder containing
              evapotranspiration rasters.
            - ``temp_path``: Path to the folder containing temperature
              rasters.
            - ``flow_acc_path``: Path to the flow accumulation raster.
            - ``flow_direction_path``: Path to the flow direction raster.
            - ``ParPath``: Path to the folder containing parameter
              rasters.
            - ``p2``: List of unoptimized parameters where ``p2[0]``
              is tfac and ``p2[1]`` is catchment area in km2.

        Raises:
            AssertionError: If input data arrays have inconsistent
                dimensions or if the lake meteorological data length
                does not match the distributed raster data length.
        """
        # input data validation

        # input dimensions
        assert (
            np.shape(self.Prec)[0] == self.rows
            and np.shape(self.ET)[0] == self.rows
            and np.shape(self.Temp)[0] == self.rows
            and np.shape(self.Parameters)[0] == self.rows
        ), "all input data should have the same number of rows"
        assert (
            np.shape(self.Prec)[1] == self.cols
            and np.shape(self.ET)[1] == self.cols
            and np.shape(self.Temp)[1] == self.cols
            and np.shape(self.Parameters)[1] == self.cols
        ), "all input data should have the same number of columns"
        assert (
            np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
        ), "all meteorological input data should have the same length"

        assert np.shape(lake.MeteoData)[0] == np.shape(self.Prec)[2], (
            "Lake meteorological data has to have the same length as the distributed raster data"
        )
        assert np.shape(lake.MeteoData)[1] >= 3, (
            "Lake Meteo data has to have at least three columns rain, ET, and Temp"
        )

        # run the model
        Wrapper.FW1Withlake(self, lake)

    def runLumped(
        self,
        Route: int = 0,
        routing_fn: Callable[..., Any] | None = None,
    ):
        """Run the lumped conceptual model.

        Executes a lumped conceptual hydrological model, optionally
        routing the generated discharge hydrograph. The simulated
        discharge is stored in ``self.Qsim`` as a pandas DataFrame
        indexed by the simulation date range.

        Args:
            Route: Flag to decide whether to route the generated
                discharge hydrograph. Use 0 for no routing or 1 to
                enable routing. Defaults to 0.
            routing_fn: Function to route the discharge hydrograph.
                If None, an empty list is used. Defaults to None.

        Note:
            The following attributes should be defined before calling
            this method:

            - ``LumpedModel``: Conceptual model containing a
              ``simulate`` method.
            - ``data``: Numpy array of meteorological data with
              columns for precipitation, evapotranspiration,
              temperature, and long-term average temperature.
            - ``Parameters``: Numpy array of conceptual model
              parameters.
            - ``CatArea``: Catchment area in km2.
            - ``conversion_factor``: Time conversion factor
              (e.g., 24 for daily).
            - ``InitialCond``: List of initial state variable
              values [sp, sm, uz, lz, wc].
            - ``Snow``: Whether to use the snow subroutine (0 or 1).
            - ``q_init``: Initial discharge value.
        """
        if routing_fn is None and Route != 0:
            raise ValueError("routing_fn must be a callable when Route != 0")
        if self.temporal_resolution.lower() == "daily":
            ind = pd.date_range(self.start, self.end, freq="D")
        else:
            ind = pd.date_range(self.start, self.end, freq="h")

        Qsim = pd.DataFrame(index=ind)

        Wrapper.Lumped(self, Route, routing_fn)
        Qsim["q"] = self.Qsim
        self.Qsim = Qsim[:]
        logger.info("Lumped model run has finished successfully")

RunFW1withLake(lake: LakeType) #

Run the FW1 distributed model with a lake component.

Validates that all input arrays have consistent dimensions and that the lake meteorological data matches the simulation period, then executes the FW1 model with lake routing via the Wrapper.

Parameters:

Name Type Description Default
lake Lake

Lake object containing lake configuration and meteorological data. Must have a MeteoData attribute with shape (time_steps, >= 3) where columns are rain, ET, and temperature.

required
Note

The following catchment attributes should be set before calling this method:

  • prec_path: Path to the folder containing precipitation rasters.
  • evap_path: Path to the folder containing evapotranspiration rasters.
  • temp_path: Path to the folder containing temperature rasters.
  • flow_acc_path: Path to the flow accumulation raster.
  • flow_direction_path: Path to the flow direction raster.
  • ParPath: Path to the folder containing parameter rasters.
  • p2: List of unoptimized parameters where p2[0] is tfac and p2[1] is catchment area in km2.

Raises:

Type Description
AssertionError

If input data arrays have inconsistent dimensions or if the lake meteorological data length does not match the distributed raster data length.

Source code in src/hapi/run.py
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
def RunFW1withLake(self, lake: LakeType):
    """Run the FW1 distributed model with a lake component.

    Validates that all input arrays have consistent dimensions and
    that the lake meteorological data matches the simulation period,
    then executes the FW1 model with lake routing via the Wrapper.

    Args:
        lake: Lake object containing lake configuration and
            meteorological data. Must have a ``MeteoData`` attribute
            with shape ``(time_steps, >= 3)`` where columns are
            rain, ET, and temperature.

    Note:
        The following catchment attributes should be set before
        calling this method:

        - ``prec_path``: Path to the folder containing precipitation
          rasters.
        - ``evap_path``: Path to the folder containing
          evapotranspiration rasters.
        - ``temp_path``: Path to the folder containing temperature
          rasters.
        - ``flow_acc_path``: Path to the flow accumulation raster.
        - ``flow_direction_path``: Path to the flow direction raster.
        - ``ParPath``: Path to the folder containing parameter
          rasters.
        - ``p2``: List of unoptimized parameters where ``p2[0]``
          is tfac and ``p2[1]`` is catchment area in km2.

    Raises:
        AssertionError: If input data arrays have inconsistent
            dimensions or if the lake meteorological data length
            does not match the distributed raster data length.
    """
    # input data validation

    # input dimensions
    assert (
        np.shape(self.Prec)[0] == self.rows
        and np.shape(self.ET)[0] == self.rows
        and np.shape(self.Temp)[0] == self.rows
        and np.shape(self.Parameters)[0] == self.rows
    ), "all input data should have the same number of rows"
    assert (
        np.shape(self.Prec)[1] == self.cols
        and np.shape(self.ET)[1] == self.cols
        and np.shape(self.Temp)[1] == self.cols
        and np.shape(self.Parameters)[1] == self.cols
    ), "all input data should have the same number of columns"
    assert (
        np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
    ), "all meteorological input data should have the same length"

    assert np.shape(lake.MeteoData)[0] == np.shape(self.Prec)[2], (
        "Lake meteorological data has to have the same length as the distributed raster data"
    )
    assert np.shape(lake.MeteoData)[1] >= 3, (
        "Lake Meteo data has to have at least three columns rain, ET, and Temp"
    )

    # run the model
    Wrapper.FW1Withlake(self, lake)

RunFloodModel() #

Run the flood model.

Runs the conceptual distributed hydrological model with additional validation for river geometry inputs (bankfull depth, river width, river roughness, and flood plain roughness).

Raises:

Type Description
AssertionError

If meteorological input arrays, parameter arrays, or river geometry arrays have inconsistent dimensions.

Source code in src/hapi/run.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
def RunFloodModel(self):
    """Run the flood model.

    Runs the conceptual distributed hydrological model with
    additional validation for river geometry inputs (bankfull depth,
    river width, river roughness, and flood plain roughness).

    Raises:
        AssertionError: If meteorological input arrays, parameter
            arrays, or river geometry arrays have inconsistent
            dimensions.
    """
    # input dimensions
    [fd_rows, fd_cols] = self.flow_dir_arr.shape
    assert fd_rows == self.rows and fd_cols == self.cols, (
        "all input data should have the same number of rows"
    )

    # input dimensions
    assert (
        np.shape(self.Prec)[0] == self.rows
        and np.shape(self.ET)[0] == self.rows
        and np.shape(self.Temp)[0] == self.rows
        and np.shape(self.Parameters)[0] == self.rows
    ), "all input data should have the same number of rows"
    assert (
        np.shape(self.Prec)[1] == self.cols
        and np.shape(self.ET)[1] == self.cols
        and np.shape(self.Temp)[1] == self.cols
        and np.shape(self.Parameters)[1] == self.cols
    ), "all input data should have the same number of columns"
    assert (
        np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
    ), "all meteorological input data should have the same length"

    assert (
        np.shape(self.BankfullDepth)[0] == self.rows
        and np.shape(self.RiverWidth)[0] == self.rows
        and np.shape(self.RiverRoughness)[0] == self.rows
        and np.shape(self.FloodPlainRoughness)[0] == self.rows
    ), "all input data should have the same number of rows"
    assert (
        np.shape(self.BankfullDepth)[1] == self.cols
        and np.shape(self.RiverWidth)[1] == self.cols
        and np.shape(self.RiverRoughness)[1] == self.cols
        and np.shape(self.FloodPlainRoughness)[1] == self.cols
    ), "all input data should have the same number of columns"

    # run the model
    Wrapper.RRMModel(self)
    print("RRM has finished")

RunHapi() #

Run the distributed hydrological model.

Validates that all input arrays (precipitation, evapotranspiration, temperature, parameters, and flow direction) have consistent dimensions, then executes the rainfall-runoff model via the Wrapper.

The following instance attributes are set after execution:

  • state_variables: 4D array (rows, cols, time, states) where states are [sp, wc, sm, uz, lv].
  • qlz: 3D array of the lower zone discharge.
  • quz: 3D array of the upper zone discharge.
  • qout: 1D timeseries of discharge at the catchment outlet in m3/sec.
  • quz_routed: 3D array of the upper zone discharge accumulated and routed at each time step.
  • qlz_translated: 3D array of the lower zone discharge translated at each time step.

Raises:

Type Description
AssertionError

If input data arrays have inconsistent row counts, column counts, or temporal lengths.

Source code in src/hapi/run.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def RunHapi(self):
    """Run the distributed hydrological model.

    Validates that all input arrays (precipitation, evapotranspiration,
    temperature, parameters, and flow direction) have consistent
    dimensions, then executes the rainfall-runoff model via the
    Wrapper.

    The following instance attributes are set after execution:

    - ``state_variables``: 4D array (rows, cols, time, states) where
      states are [sp, wc, sm, uz, lv].
    - ``qlz``: 3D array of the lower zone discharge.
    - ``quz``: 3D array of the upper zone discharge.
    - ``qout``: 1D timeseries of discharge at the catchment outlet
      in m3/sec.
    - ``quz_routed``: 3D array of the upper zone discharge
      accumulated and routed at each time step.
    - ``qlz_translated``: 3D array of the lower zone discharge
      translated at each time step.

    Raises:
        AssertionError: If input data arrays have inconsistent
            row counts, column counts, or temporal lengths.
    """
    # input dimensions
    [fd_rows, fd_cols] = self.flow_dir_arr.shape
    assert fd_rows == self.rows and fd_cols == self.cols, (
        "all input data should have the same number of rows"
    )

    # input dimensions
    assert (
        np.shape(self.Prec)[0] == self.rows
        and np.shape(self.ET)[0] == self.rows
        and np.shape(self.Temp)[0] == self.rows
        and np.shape(self.Parameters)[0] == self.rows
    ), "all input data should have the same number of rows"
    assert (
        np.shape(self.Prec)[1] == self.cols
        and np.shape(self.ET)[1] == self.cols
        and np.shape(self.Temp)[1] == self.cols
        and np.shape(self.Parameters)[1] == self.cols
    ), "all input data should have the same number of columns"
    assert (
        np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
    ), "all meteorological input data should have the same length"

    # run the model
    Wrapper.RRMModel(self)

    print("Model Run has finished")

__init__() #

Initialize the Run class.

Source code in src/hapi/run.py
40
41
42
def __init__(self):
    """Initialize the Run class."""
    self.Qsim: np.ndarray | pd.DataFrame | None = None

runFW1() #

Run the FW1 distributed hydrological model.

Validates that all input arrays have consistent dimensions, then executes the FW1 model via the Wrapper.

The following instance attributes are set after execution:

  • st: 4D array of state variables.
  • q_out: 1D array of calculated discharge at the catchment outlet.
  • q_uz: 3D array of distributed discharge for each cell.

Raises:

Type Description
AssertionError

If input data arrays have inconsistent row counts, column counts, or temporal lengths.

Source code in src/hapi/run.py
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
def runFW1(self):
    """Run the FW1 distributed hydrological model.

    Validates that all input arrays have consistent dimensions,
    then executes the FW1 model via the Wrapper.

    The following instance attributes are set after execution:

    - ``st``: 4D array of state variables.
    - ``q_out``: 1D array of calculated discharge at the catchment
      outlet.
    - ``q_uz``: 3D array of distributed discharge for each cell.

    Raises:
        AssertionError: If input data arrays have inconsistent
            row counts, column counts, or temporal lengths.
    """
    assert (
        np.shape(self.Prec)[0] == self.rows
        and np.shape(self.ET)[0] == self.rows
        and np.shape(self.Temp)[0] == self.rows
        and np.shape(self.Parameters)[0] == self.rows
    ), "all input data should have the same number of rows"
    assert (
        np.shape(self.Prec)[1] == self.cols
        and np.shape(self.ET)[1] == self.cols
        and np.shape(self.Temp)[1] == self.cols
        and np.shape(self.Parameters)[1] == self.cols
    ), "all input data should have the same number of columns"
    assert (
        np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
    ), "all meteorological input data should have the same length"

    # run the model
    Wrapper.FW1(self)

    print("Model Run has finished")

runHAPIwithLake(lake: LakeType) #

Run the distributed model with a lake component.

Validates that all input arrays have consistent dimensions and that the lake meteorological data matches the simulation period, then executes the rainfall-runoff model with lake routing via the Wrapper.

Parameters:

Name Type Description Default
lake Lake

Lake object containing lake configuration and meteorological data. Must have a MeteoData attribute with shape (time_steps, >= 3) where columns are rain, ET, and temperature.

required

Raises:

Type Description
AssertionError

If input data arrays have inconsistent dimensions or if the lake meteorological data length does not match the distributed raster data length.

Source code in src/hapi/run.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
def runHAPIwithLake(self, lake: LakeType):
    """Run the distributed model with a lake component.

    Validates that all input arrays have consistent dimensions and
    that the lake meteorological data matches the simulation period,
    then executes the rainfall-runoff model with lake routing via
    the Wrapper.

    Args:
        lake: Lake object containing lake configuration and
            meteorological data. Must have a ``MeteoData`` attribute
            with shape ``(time_steps, >= 3)`` where columns are
            rain, ET, and temperature.

    Raises:
        AssertionError: If input data arrays have inconsistent
            dimensions or if the lake meteorological data length
            does not match the distributed raster data length.
    """
    # input dimensions
    [fd_rows, fd_cols] = self.flow_dir_arr.shape
    assert fd_rows == self.rows and fd_cols == self.cols, (
        "all input data should have the same number of rows and columns"
    )

    # input dimensions
    assert (
        np.shape(self.Prec)[0] == self.rows
        and np.shape(self.ET)[0] == self.rows
        and np.shape(self.Temp)[0] == self.rows
        and np.shape(self.Parameters)[0] == self.rows
    ), "all input data should have the same number of rows"
    assert (
        np.shape(self.Prec)[1] == self.cols
        and np.shape(self.ET)[1] == self.cols
        and np.shape(self.Temp)[1] == self.cols
        and np.shape(self.Parameters)[1] == self.cols
    ), "all input data should have the same number of columns"
    assert (
        np.shape(self.Prec)[2] == np.shape(self.ET)[2] == np.shape(self.Temp)[2]
    ), "all meteorological input data should have the same length"

    assert np.shape(lake.MeteoData)[0] == np.shape(self.Prec)[2], (
        "Lake meteorological data has to have the same length as the distributed raster data"
    )
    assert np.shape(lake.MeteoData)[1] >= 3, (
        "Lake Meteo data has to have at least three columns of rain, ET, and Temp"
    )

    # run the model
    Wrapper.RRMWithlake(self, lake)

    print("Model Run has finished")

runLumped(Route: int = 0, routing_fn: Callable[..., Any] | None = None) #

Run the lumped conceptual model.

Executes a lumped conceptual hydrological model, optionally routing the generated discharge hydrograph. The simulated discharge is stored in self.Qsim as a pandas DataFrame indexed by the simulation date range.

Parameters:

Name Type Description Default
Route int

Flag to decide whether to route the generated discharge hydrograph. Use 0 for no routing or 1 to enable routing. Defaults to 0.

0
routing_fn Callable[..., Any] | None

Function to route the discharge hydrograph. If None, an empty list is used. Defaults to None.

None
Note

The following attributes should be defined before calling this method:

  • LumpedModel: Conceptual model containing a simulate method.
  • data: Numpy array of meteorological data with columns for precipitation, evapotranspiration, temperature, and long-term average temperature.
  • Parameters: Numpy array of conceptual model parameters.
  • CatArea: Catchment area in km2.
  • conversion_factor: Time conversion factor (e.g., 24 for daily).
  • InitialCond: List of initial state variable values [sp, sm, uz, lz, wc].
  • Snow: Whether to use the snow subroutine (0 or 1).
  • q_init: Initial discharge value.
Source code in src/hapi/run.py
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
def runLumped(
    self,
    Route: int = 0,
    routing_fn: Callable[..., Any] | None = None,
):
    """Run the lumped conceptual model.

    Executes a lumped conceptual hydrological model, optionally
    routing the generated discharge hydrograph. The simulated
    discharge is stored in ``self.Qsim`` as a pandas DataFrame
    indexed by the simulation date range.

    Args:
        Route: Flag to decide whether to route the generated
            discharge hydrograph. Use 0 for no routing or 1 to
            enable routing. Defaults to 0.
        routing_fn: Function to route the discharge hydrograph.
            If None, an empty list is used. Defaults to None.

    Note:
        The following attributes should be defined before calling
        this method:

        - ``LumpedModel``: Conceptual model containing a
          ``simulate`` method.
        - ``data``: Numpy array of meteorological data with
          columns for precipitation, evapotranspiration,
          temperature, and long-term average temperature.
        - ``Parameters``: Numpy array of conceptual model
          parameters.
        - ``CatArea``: Catchment area in km2.
        - ``conversion_factor``: Time conversion factor
          (e.g., 24 for daily).
        - ``InitialCond``: List of initial state variable
          values [sp, sm, uz, lz, wc].
        - ``Snow``: Whether to use the snow subroutine (0 or 1).
        - ``q_init``: Initial discharge value.
    """
    if routing_fn is None and Route != 0:
        raise ValueError("routing_fn must be a callable when Route != 0")
    if self.temporal_resolution.lower() == "daily":
        ind = pd.date_range(self.start, self.end, freq="D")
    else:
        ind = pd.date_range(self.start, self.end, freq="h")

    Qsim = pd.DataFrame(index=ind)

    Wrapper.Lumped(self, Route, routing_fn)
    Qsim["q"] = self.Qsim
    self.Qsim = Qsim[:]
    logger.info("Lumped model run has finished successfully")