Skip to content

Replace parameter vectors with structured objects #143

Description

@MAfarrag
  • Replace all unstructured positional parameter vectors (e.g. p, p2, v, St) used in HBV variants and routines with typed, named objects using Python's dataclasses or Pydantic models.

In HBV models like hbv.py, hbv_lake.py, etc., model routines use:

def step_run(p, p2, v, St):
    ltt = p[0]
    utt = p[1]
    ttm = p[2]
    ...

These are flat list or np.ndarray objects with up to 20+ parameters. Access relies on fixed ordering, which is error-prone and hard to understand.

What To Introduce

  • Define new structured classes like this:
  1. @DataClass Option (preferred for performance & simplicity):
from dataclasses import dataclass
from typing import List

@dataclass
class HBVParameters:
    ltt: float
    utt: float
    ttm: float
    cfmax: float
    fc: float
    ecorr: float
    etf: float
    lp: float
    k: float
    k1: float
    alpha: float
    beta: float
    cwh: float
    cfr: float
    c_flux: float
    perc: float
    rfcf: float
    sfcf: float
    maxbas: int

@dataclass
class SimulationConstants:
    tfac: float
    area: float

@dataclass
class Forcing:
    prec: float
    temp: float
    evap: float
    ll_temp: float

@dataclass
class HBVState:
    sp: float
    sm: float
    uz: float
    lz: float
    wc: float
  • In all routines across hbv*.py, replace:
Old New
p[i] params.name
p2[0], p2[1] constants.tfac, constants.area
v[0], v[1], etc. forcing.prec, forcing.temp, ...
St[0], St[1], etc. state.sp, state.sm, ...
  • before
def step_run(p, p2, v, St):
    ltt = p[0]
    tfac = p2[0]
    prec = v[0]
    sm = St[1]
    ...
  • after
def step_run(self, params: HBVParameters, constants: SimulationConstants, 
             forcing: Forcing, state: HBVState):
    rf, sf = self.precipitation(forcing.temp, params.ltt, params.utt, forcing.prec, 
                                 params.rfcf, params.sfcf)
    ...

Refactoring strategy

1 - Define HBVParameters, SimulationConstants, Forcing, HBVState in a new module:

src/Hapi/models/schemas.py

2- Update step_run() signatures across:

  • hbv.py, hbv_lake.py, hbvold.py, hbvlumped.py, hbv_bergestrom92.py

Example:

def step_run(self, params: HBVParameters, constants: SimulationConstants,
             forcing: Forcing, state: HBVState) -> Tuple[float, HBVState]:

3- Update downstream calls in wrappers/calibration code:

  • Replace any array slicing into params/state with object instantiation.

4- Optionally, implement from_vector() static methods on HBVParameters, etc.:

@staticmethod
def from_vector(vec: List[float]) -> "HBVParameters":
    return HBVParameters(*vec[:19])

Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions