Components
Project files
- hydrobricks.load_project(source: str | Path | dict, base_dir: str | Path | None = None, setup: bool = True) Project[source]
Build a ready-to-run model setup from a YAML project file (or dict).
The configuration is validated as a whole before anything is built: unknown keys (with ‘did you mean’ suggestions), missing files, missing CSV columns, wrong types and unknown model or parameter names are all reported together in a single
ConfigurationError.- Parameters:
source – Path to a YAML project file, or an equivalent (already parsed) mapping.
base_dir – Directory used to resolve the relative paths in the configuration. Defaults to the project file directory (or the current working directory when
sourceis a dict).setup – Whether to
setup()the model over the full simulation span (default). PassFalsewhen something must happen between the model construction and its setup — e.g. configuring recordings for auxiliary observations — then callProject.setup()yourself.
- Returns:
The wired
(model, forcing, parameters, observations, periods)bundle.- Return type:
- class hydrobricks.Project(model: Model, forcing: Forcing, parameters: ParameterSet, observations: DischargeObservations | None, periods: Periods, config: dict, path: Path | None = None, output_dir: Path | None = None, hydro_units: HydroUnits | None = None, catchment: Any | None = None)[source]
Bases:
objectThe wired-up objects built from a project file by
load_project().- model
The model instance, already
setup()over the full simulation span (with the project spin-up). Callrun()ormodel.run(...).
- parameters
The generated
ParameterSet, with the values from the project file applied. If the file does not value every parameter, set the remaining ones before running.
- observations
The loaded observed discharge, or
Nonewhen the project file has noobservationssection.
- periods
The
Periods(calibration / validation / simulation and spin-up policy) declared in the project file.
- config
The raw configuration mapping the project was built from.
- Type:
dict
- path
The project file path, or
Nonewhen built from a dict.- Type:
pathlib.Path | None
- output_dir
The resolved output directory the model writes to.
- Type:
pathlib.Path | None
- hydro_units
The
HydroUnits(loaded or delineated).- Type:
Catchment
- class hydrobricks.Catchment(outline: str | Path | None = None, land_cover_types: list[str] | None = None, land_cover_names: list[str] | None = None, hydro_units_data: pd.DataFrame | None = None)[source]
Bases:
objectCreation of catchment-related data
- Parameters:
outline – Path to the outline of the catchment.
land_cover_types – The land cover types of the catchment.
land_cover_names – The land cover names of the catchment.
hydro_units_data – The hydro units data of the catchment.
- area
The area of the catchment.
- Type:
float
- crs
The crs of the catchment outline.
- Type:
str
- outline
The outline of the catchment.
- Type:
shapely.geometry.Polygon
- dem
The DEM of the catchment [m].
- Type:
rasterio.DatasetReader
- dem_data
The masked DEM data of the catchment.
- Type:
np.ndarray
- slope
The slope map of the catchment [degrees].
- Type:
np.ndarray
- aspect
The aspect map of the catchment.
- Type:
np.ndarray
- map_unit_ids
The unit ids as a numpy array matching the DEM extent.
- Type:
np.ndarray
- hydro_units
The hydro units of the catchment.
- Type:
- static calculate_cast_shadows(*args, **kwargs) numpy.ndarray[source]
Call the calculate_cast_shadows method of the PotentialSolarRadiation class.
- calculate_connectivity(*args, **kwargs) pandas.DataFrame[source]
Call the calculate_connectivity method of the Connectivity class.
- calculate_daily_potential_radiation(*args, **kwargs) None[source]
Call the calculate_daily_potential_radiation method of the PotentialSolarRadiation class.
- calculate_slope_aspect() None[source]
Call the calculate_slope_aspect method of the Topography class.
- close() None[source]
Close all open resources (DEM dataset and MemoryFiles).
Called automatically when using the catchment as a context manager, or can be called manually to explicitly release resources.
Examples
Using as context manager (recommended):
>>> with Catchment(outline='boundary.shp') as catchment: ... catchment.extract_dem('dem.tif')
Manual cleanup:
>>> catchment = Catchment(outline='boundary.shp') >>> try: ... catchment.extract_dem('dem.tif') ... finally: ... catchment.close()
- property connectivity: Any
Lazy-loaded connectivity module.
- Returns:
Connectivity processor for the catchment, loaded on first access.
- Return type:
- create_dem_pixel_geometry(i: int, j: int) shapely.geometry.Polygon[source]
Create a shapely geometry of the DEM pixel.
- Parameters:
i – The row of the pixel.
j – The column of the pixel.
- Return type:
The shapely geometry of the pixel.
- create_elevation_bands(*args, **kwargs) None[source]
Call the create_elevation_bands method of the Discretization class.
- property discretization: Any
Lazy-loaded discretization module.
- Returns:
Discretization processor for the catchment, loaded on first access.
- Return type:
- discretize_by(*args, **kwargs) None[source]
Call the discretize_by method of the Discretization class.
- extract_attribute_raster(raster_path: str | Path, attr_name: str, resample_to_dem_resolution: bool = True, resampling: str = 'average', replace_nans_by_zeros: bool = True, reproject_crs: bool = False) bool[source]
Extract spatial attributes (raster) for the catchment.
- Parameters:
raster_path – Path of the raster file containing the attribute data.
attr_name – Name of the attribute to store in self.attributes dictionary.
resample_to_dem_resolution – If True, resample the attribute raster to DEM resolution. Default: True
resampling – Resampling method to use when resample_to_dem_resolution is True. Options: ‘nearest’, ‘bilinear’, ‘cubic’, ‘cubic_spline’, ‘lanczos’, ‘average’, ‘mode’, ‘gauss’, ‘max’, ‘min’, ‘med’, ‘q1’, ‘q3’, ‘sum’, ‘rms’ Default: ‘average’
replace_nans_by_zeros – If True, replace NaN values with zero in the output raster. Default: True
reproject_crs – If True, the raster is warped onto the DEM grid even when its CRS differs from the catchment CRS (the raster is not required to match the catchment CRS and is not masked by the outline beforehand). Use this for datasets provided in a different CRS, e.g. ESA WorldCover (EPSG:4326) against a projected DEM. Implies resampling onto the DEM grid. Default: False
- Returns:
True if extraction was successful, False otherwise.
- Return type:
bool
- Raises:
FileNotFoundError – If the raster file does not exist.
ValueError – If the resampling method is not recognized.
- extract_dem(raster_path: str | Path) bool[source]
Extract the DEM data for the catchment. Does not handle change in coordinates.
- Parameters:
raster_path – Path of the DEM raster file.
- Returns:
True if extraction was successful, False otherwise.
- Return type:
bool
- Raises:
FileNotFoundError – If the raster file does not exist.
- extract_land_cover_from_raster(*args, **kwargs) None[source]
Extract land-cover fractions from a categorical raster (e.g. ESA WorldCover).
Call the
extract_from_rastermethod of the CatchmentLandCover class.
- extract_land_cover_from_shapefile(*args, **kwargs) None[source]
Extract land-cover fractions from a vector dataset (e.g. swissTLMRegio).
Call the
extract_from_shapefilemethod of the CatchmentLandCover class.
- extract_unit_mean_lat_lon(mask_unit: numpy.ndarray) tuple[float, float][source]
Extract the mean latitude and longitude for a hydro unit.
Calculates the mean coordinates of pixels within a unit mask and converts them from the catchment CRS to latitude/longitude (EPSG:4326).
- Parameters:
mask_unit – Boolean mask array identifying the cells of the hydro unit.
- Returns:
Tuple of (mean_latitude, mean_longitude) in degrees.
- Return type:
tuple[float, float]
- get_attribute_raster_x_resolution(attr_name: str = 'dem') float[source]
Get the given attribute raster x resolution.
- Parameters:
attr_name – Name of the attribute.
- Return type:
The attribute raster x resolution.
- get_attribute_raster_y_resolution(attr_name: str = 'dem') float[source]
Get the given attribute raster y resolution.
- Parameters:
attr_name – Name of the attribute.
- Return type:
The attribute raster y resolution.
- get_dem_mean_lat_lon() tuple[float, float][source]
Get the mean latitude and longitude of the DEM extent.
Calculates the central coordinates of the catchment DEM and converts them from the catchment CRS to latitude/longitude (EPSG:4326).
- Returns:
Tuple of (mean_latitude, mean_longitude) in degrees.
- Return type:
tuple[float, float]
- get_hillshade(*args, **kwargs) numpy.ndarray[source]
Call the get_hillshade method of the Topography class.
- get_hydro_unit_count() int[source]
Get the number of hydro units.
- Return type:
The number of hydro units.
- get_hydro_units_attributes() HydroUnits[source]
Extract the hydro units attributes.
- Return type:
The hydro units attributes.
- get_hydro_units_elevations() numpy.ndarray[source]
Get the elevation of the hydro units.
- Return type:
The elevation of the hydro units.
- static get_solar_azimuth_to_north(*args, **kwargs) float | np.ndarray[source]
Call the get_solar_azimuth_to_north method of the PotentialSolarRadiation class.
- static get_solar_azimuth_to_south(*args, **kwargs) numpy.ndarray[source]
Call the get_solar_azimuth_to_south method of the PotentialSolarRadiation class.
- static get_solar_declination_rad(*args, **kwargs) float[source]
Call the get_solar_declination_rad method of the PotentialSolarRadiation class.
- static get_solar_hour_angle_limit(*args, **kwargs) float | np.ndarray[source]
Call the get_solar_hour_angle_limit method of the PotentialSolarRadiation class.
- static get_solar_zenith(*args, **kwargs) float | np.ndarray[source]
Call the get_solar_zenith method of the PotentialSolarRadiation class.
- initialize_area_from_land_cover_change(land_cover_name: str, land_cover_change: pandas.DataFrame) None[source]
Initialize the HydroUnits cover area from a land cover change object.
Must be called before
Model.setup(): it updates the land cover fractions that the model reads at build time. Calling it afterwards changes the hydro units’ settings but does not propagate to an already-built model.- Parameters:
land_cover_name – The name of the land cover to initialize.
land_cover_change – The land cover change dataframe.
- initialize_land_cover_fractions() None[source]
Initialize land cover fractions for all hydro units.
Sets up the initial fractional areas for each land cover type within each hydro unit based on the available land cover data.
- property land_cover: Any
Lazy-loaded land-cover extraction module.
- Returns:
Land-cover extraction processor for the catchment, loaded on first access.
- Return type:
- load_hydro_units_from_csv(path: str | Path) None[source]
Load hydro units from a csv file.
- Parameters:
path – Path to the csv file.
- load_mean_annual_radiation_raster(*args, **kwargs) None[source]
Call the load_mean_annual_radiation_raster method of the PotentialSolarRadiation class.
- load_unit_ids_from_raster(path: str, filename: str = 'unit_ids.tif') None[source]
Load hydro units from a raster file.
- Parameters:
path – Path to the directory containing the raster file. If the path is a file, it will be used as the full path.
filename – Name of the raster file. Default is ‘unit_ids.tif’.
- mask_dem(shapefile: gpd.GeoDataFrame, nodata: float = -9999, all_touched: bool = True) np.ndarray[source]
Rasterize vector geometries onto the DEM grid.
Masks the catchment DEM with the geometries of
shapefile(which must be in the catchment CRS): cells covered by a geometry keep their DEM value, cells outside getnodata. Used to derive per-cell presence masks from polygons (e.g. land cover, glacier extent, sub-catchments).- Parameters:
shapefile – GeoDataFrame of geometries, expressed in the catchment CRS.
nodata – Value assigned to cells outside the geometries. Default: -9999.
all_touched – If True (default), every cell touched by a geometry is included; if False, only cells whose centre falls within a geometry.
- Returns:
2D array over the DEM grid holding the DEM value where a geometry is present and
nodataelsewhere.- Return type:
np.ndarray
- resample_dem_and_calculate_slope_aspect(*args, **kwargs) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray][source]
Call the resample_dem_and_calculate_slope_aspect method of the Topography class.
- save_hydro_units_to_csv(path: str | Path) None[source]
Save the hydro units to a csv file.
- Parameters:
path – Path to the output file.
- save_unit_ids_raster(output_path: str | Path, output_filename: str = 'unit_ids.tif') None[source]
Save the unit ids raster to a file.
- Parameters:
output_path – Path to the output file.
output_filename – Name of the output file. Default is ‘unit_ids.tif’.
- property solar_radiation: Any
Lazy-loaded solar radiation module.
- Returns:
Solar radiation processor for the catchment, loaded on first access.
- Return type:
- property topography: Any
Lazy-loaded topography analysis module.
- Returns:
Topography processor for the catchment, loaded on first access.
- Return type:
HydroUnits
- class hydrobricks.HydroUnits(land_cover_types: list[str] | None = None, land_cover_names: list[str] | None = None, data: pd.DataFrame | None = None)[source]
Bases:
objectClass for the hydro units
- Parameters:
land_cover_types – List of land cover types. Default: [‘open’]
land_cover_names – List of land cover names. Default: [‘open’]
data – DataFrame containing the hydro units data.
- land_cover_types
List of land cover types. Default: [‘open’]
- Type:
list[str]
- land_cover_names
List of land cover names. Default: [‘open’]
- Type:
list[str]
- hydro_units
Dataframe containing the hydro units data.
- Type:
pd.DataFrame
- FRACTION_PREFIX: ClassVar[str] = 'fraction-'
- GENERIC_COVER_ALIASES = ('open', 'ground', 'generic', 'generic_land_cover')
Generic (soil-bearing) land cover aliases. ‘open’ is the canonical name; the others are accepted for backward compatibility. The generic cover absorbs the residual area when other land cover fractions change.
- add_land_cover(name: str, cover_type: str = 'generic_land_cover') None[source]
Register a new land cover on the hydro units.
Appends the land cover (name + type) and adds its
fraction-<name>column, initialized to 0.0 for every hydro unit. Existing fractions are left untouched, so the generic soil cover keeps absorbing the residual area until the new cover’s fractions are set (e.g. viainitialize_from_land_cover_change).- Parameters:
name – The name of the land cover to add.
cover_type – The land cover type identifier (e.g. ‘glacier’, ‘forest’, ‘open’). Default: ‘generic_land_cover’.
- Raises:
DataError – If a land cover with the same name already exists.
- add_property(column_tuple: tuple[str, str], values: numpy.ndarray, set_first: bool = False) None[source]
Add a property to the hydro units.
Adds a new column to the hydro_units DataFrame with the specified property name, unit, and values. Can optionally insert as the first column.
- Parameters:
column_tuple – Tuple containing (property_name, unit_string). Example: (‘elevation’, ‘m’)
values – Numpy array containing the property values for each hydro unit.
set_first – If True, the property is added as the first column. Default: False
- Raises:
ValueError – If values length doesn’t match the number of hydro units.
- check_land_cover_fractions_not_empty() None[source]
Check that the land cover fractions are not empty.
Validates that all land cover fractions have been defined. If there is a single land cover type (e.g. ‘open’), automatically sets it to 1.0 for all hydro units.
- Raises:
ValueError – If any land cover fraction contains NaN values (when multiple land cover types exist).
- get_generic_cover_name() str[source]
Return the generic soil land cover name (the one that absorbs residual area).
Picks the land cover whose name or type is a generic alias (‘open’, ‘ground’, …). Falls back to the first land cover if none is explicitly generic.
- get_hydro_unit_count() int[source]
Get the number of hydro units.
- Return type:
Number of hydro units.
- has(prop: str) bool[source]
Check if the hydro units have a given property.
- Parameters:
prop – The property name to check. Should match a column name in the hydro_units DataFrame.
- Returns:
True if the property is present, False otherwise.
- Return type:
bool
- initialize_from_land_cover_change(land_cover_name: str, land_cover_change: pandas.DataFrame) None[source]
Initialize the hydro units from the first values of a land cover change dataframe.
Updates the land cover fractions for specified hydro units based on a land cover change dataframe. Automatically adjusts the generic soil land cover fraction (‘open’, or its ‘ground’ alias) to maintain conservation.
Must be called before
Model.setup(): the fractions set here become the model’s initial extent, captured at build time. Calling it afterwards updates the settings but does not propagate to an already-built model.- Parameters:
land_cover_name – The name of the land cover to initialize.
land_cover_change – The land cover change dataframe with columns ‘hydro_unit’ and area values.
- Raises:
ValueError – If computed land cover fraction is not in the range [0, 1].
- initialize_land_cover_fractions() None[source]
Initialize land cover fractions with default values.
Sets the generic soil land cover fraction (‘open’, or its ‘ground’ alias) to 1.0 and all other land cover types to 0.0 for all hydro units. Used as a starting point before applying specific land cover changes.
- load_from_csv(path: str | Path, column_elevation: str | None = None, column_area: str | None = None, columns_areas: dict[str, str] | None = None, other_columns: dict[str, str] | None = None) None[source]
Read hydro units properties from CSV file. The file must contain two header rows. The first row contains the column names and the second row contains the units. The file must contain at minimum the units area.
- Parameters:
path – Path to the CSV file containing hydro units data.
column_elevation – Column name containing the elevation values. If None, looks for ‘elevation’ column. Default: None
column_area – Column name containing the total area values. If None, looks for ‘area’ column. Default: None
columns_areas – Dictionary mapping land cover names to area column names. Cannot be used with column_area. Default: None
other_columns – Dictionary mapping property names to column names in the CSV file. Example: {‘slope’: ‘Slope’, ‘aspect’: ‘Aspect’} Default: None
- Raises:
FileNotFoundError – If the CSV file does not exist.
ValueError – If required columns are missing or are inconsistent.
- populate_bounded_instance() None[source]
Populate the SettingsBasin instance from current hydro units data.
Updates the internal SettingsBasin object with current hydro unit properties, sorted by elevation in descending order. Includes land cover fractions and all custom properties.
- save_as(path: str) None[source]
Create a file containing the hydro unit properties. Such a file can be used in the command-line version of hydrobricks.
Saves hydro units and land cover information to a netCDF4 file with proper dimensions and variable attributes.
- Parameters:
path – Path of the file to create.
- Raises:
ImportError – If netcdf4 is not installed.
- save_to_csv(path: str | Path) None[source]
Save the hydro units to a csv file.
Exports the hydro units DataFrame to a CSV file with multi-level header containing both property names and units.
- Parameters:
path – Path to the output file.
- Raises:
ValueError – If no hydro units data is available.
- set_connectivity(connectivity: pd.DataFrame | Path | str) None[source]
Set the connectivity of the hydro units.
Configures how water flows between hydro units by setting lateral connections with specified ratios. Can accept connectivity data as a DataFrame or load from file.
- Parameters:
connectivity – File or Dataframe containing the connectivity information as generated by catchment.calculate_connectivity().
- Raises:
TypeError – If connectivity is not a DataFrame or valid file path.
ValueError – If connectivity DataFrame is missing required columns or has invalid values.
ParameterSet
- class hydrobricks.ParameterSet[source]
Bases:
objectClass for the parameter sets
- add_aliases(parameter_name: str, aliases: list[str] | str) None[source]
Add aliases to a parameter.
- Parameters:
parameter_name – The name of the parameter with the related component (e.g., snowpack:degree_day_factor).
aliases – Aliases to the parameter name, such as names used in other implementations (e.g., kgl, an). Aliases must be unique.
- add_data_parameter(name: str, value: float | list[float] | None = None, min_val: float | list[float] | None = None, max_val: float | list[float] | None = None, unit: str | None = None) None[source]
Add a parameter related to the data.
- Parameters:
name – The name of the parameter.
value – The parameter value.
min_val – Minimum value allowed for the parameter.
max_val – Maximum value allowed for the parameter.
unit – The unit of the parameter.
- property allow_changing: list[str]
Get the list of parameters to assess during calibration.
- Returns:
List of parameter names that are allowed to change.
- Return type:
list[str]
- are_valid() bool[source]
Check if all the parameters are defined and have a value. Alias of is_valid.
- Returns:
True if all parameters are defined and have a value, False otherwise.
- Return type:
bool
- change_range(parameter: str, min_val: float | None = None, max_val: float | None = None) None[source]
Change the value range of a parameter.
Only the bounds that are provided are changed; passing
None(the default) leaves that bound untouched. This allows raising a lower bound without having to restate the maximum.- Parameters:
parameter – Name (or alias) of the parameter
min_val – New minimum value, or None to keep the current minimum.
max_val – New maximum value, or None to keep the current maximum.
- constraints_satisfied() bool[source]
Check if the constraints between parameters are satisfied.
- Returns:
True if constraints are satisfied, False otherwise.
- Return type:
bool
- define_constraint(parameter_1: str, operator: str, parameter_2: str) None[source]
Defines a constraint between 2 parameters (e.g., paramA > paramB)
- Parameters:
parameter_1 – The name of the first parameter.
operator – The operator (e.g. ‘<=’).
parameter_2 – The name of the second parameter.
Examples
parameter_set.define_constraint(‘paramA’, ‘>=’, ‘paramB’)
- define_parameter(component: str, name: str, unit: str | None = None, aliases: str | list[str] | None = None, min_val: float | list[float] | None = None, max_val: float | list[float] | None = None, default: float | list[float] | None = None, mandatory: bool = True) None[source]
Define a parameter by setting its properties.
- Parameters:
component – The component (brick) name to which the parameter refer (e.g., snowpack, glacier, surface_runoff). It can be a string of a list of components when the parameter is shared between components (e.g., melt_factor in the temperature index method).
name – The name of the parameter in the C++ code of hydrobricks (e.g., degree_day_factor, response_factor).
unit – The unit of the parameter.
aliases – Aliases to the parameter name, such as names used in other implementations (e.g., kgl, an). Aliases must be unique.
min_val – Minimum value allowed for the parameter.
max_val – Maximum value allowed for the parameter.
default – The parameter default value.
mandatory – If the parameter needs to be defined or if it can silently use the default value.
- generate_parameters(land_cover_types: list[str], land_cover_names: list[str], options: dict, structure: dict)[source]
Generate a parameters object for the provided model options and structure.
- Parameters:
land_cover_types – The land cover types.
land_cover_names – The land cover names.
options – The model options.
structure – The model structure.
- get(name: str) float[source]
Get the value of a parameter by name.
- Parameters:
name – The name of the parameter.
- Returns:
The parameter value.
- Return type:
float
- get_for_spotpy() list[spotpy.parameter][source]
Get the parameters to assess ready to be used in spotpy.
- Return type:
A list of the parameters as spotpy objects.
- get_model_parameters() pandas.DataFrame[source]
Get the model-only parameters (excluding data-related parameters).
- Returns:
DataFrame containing model parameters only.
- Return type:
pd.DataFrame
- get_transform(name: str) ParameterTransform | None[source]
Return the transform attached to a parameter, or None.
- Parameters:
name – The name or one of the aliases of the parameter.
- Returns:
The transform if one is set, otherwise None. Parameters without a transform (or unknown names) return None.
- Return type:
ParameterTransform | None
- get_transformed(name: str) float[source]
Get the transformed value of a parameter by name.
Returns the parameter value mapped through its transform (if any). If the parameter has no transform, the real value is returned unchanged.
- Parameters:
name – The name of the parameter.
- Returns:
The transformed parameter value.
- Return type:
float
- get_undefined() list[str][source]
Get the undefined parameters.
- Returns:
List of the undefined parameter names.
- Return type:
list[str]
- has(name: str) bool[source]
Check if a parameter exists.
- Parameters:
name – The name of the parameter.
- Returns:
True if found, False otherwise.
- Return type:
bool
- is_for_forcing(parameter_name: str) bool[source]
Check if the parameter relates to forcing data.
- Parameters:
parameter_name – The name of the parameter.
- Returns:
True if relates to forcing data, False otherwise.
- Return type:
bool
- is_valid() bool[source]
Check if all the parameters are defined and have a value.
- Returns:
True if all parameters are defined and have a value, False otherwise.
- Return type:
bool
- list_constraints() None[source]
List the constraints currently defined.
Prints all defined parameter constraints to the console.
- needs_random_forcing() bool[source]
Check if one of the parameters to assess involves the meteorological data.
- Return type:
True if one of the parameters to assess involves the meteorological data.
- range_satisfied() bool[source]
Check if the parameter value ranges are satisfied.
- Returns:
True if ranges are satisfied, False otherwise.
- Return type:
bool
- remove_constraint(parameter_1: str, operator: str, parameter_2: str) None[source]
Removes a constraint between 2 parameters (e.g., paramA > paramB)
- Parameters:
parameter_1 – The name of the first parameter.
operator – The operator (e.g. ‘<=’).
parameter_2 – The name of the second parameter.
Examples
parameter_set.remove_constraint(‘paramA’, ‘>=’, ‘paramB’)
- save_as(directory: str, name: str, file_type: str = 'both')[source]
Create a configuration file containing the parameter values.
Such a file can be used when using the command-line version of hydrobricks. It contains the model parameter values.
- Parameters:
directory – The directory to write the file.
name – The name of the generated file.
file_type – The type of file to generate: ‘json’, ‘yaml’, or ‘both’.
- set_prior(parameter: str, prior: spotpy.parameter) None[source]
Set a prior distribution for a parameter.
Assigns a prior probability distribution to a parameter for use in Bayesian calibration methods.
- Parameters:
parameter – Name (or alias) of the parameter
prior – The prior distribution (instance of spotpy.parameter)
- Raises:
ImportError – If spotpy is not installed.
- set_random_values(parameters: list[str]) pandas.DataFrame[source]
Set the provided parameter to random values.
Randomly assigns values to specified parameters within their defined ranges. Iterates until all constraints are satisfied.
- Parameters:
parameters – The name or alias of the parameters to set to random values. Example: [‘kr’, ‘A’]
- Returns:
A dataframe with the assigned parameter values.
- Return type:
pd.DataFrame
- Raises:
ValueError – If parameter constraints cannot be satisfied after 1000 iterations.
- set_transform(parameter: str, to_transformed: Callable[[float], float], to_real: Callable[[float], float]) None[source]
Attach a transform between the real and transformed values of a parameter.
The real value (used by the C++ engine and stored in the parameter set) and the transformed value (used for optimisation or to express the parameter in its original formulation) are related by the two provided functions. Either representation can be set; the other is derived. Both functions must be monotonic.
- Parameters:
parameter – Name (or alias) of the parameter.
to_transformed – Function mapping the real value to the transformed value.
to_real – Function mapping the transformed value back to the real value.
- Raises:
ConfigurationError – If the parameter is list-valued (transforms are not supported for lists).
- set_values(values: dict, check_range: bool = True, allow_adapt: bool = False, transformed: bool = False) None[source]
Set the parameter values.
- Parameters:
values – The values must be provided as a dictionary with the parameter name with the related component or one of its aliases as the key. Example: {‘k’: 32, ‘A’: 300} or {‘slow_reservoir:capacity’: 300}
check_range – Check that the parameter value falls into the allowed range.
allow_adapt – Allow the parameter values to be adapted to enforce defined constraints (e.g.: min, max).
transformed – If True, the provided values are in transformed space and are mapped back to the real value (using each parameter’s transform) before being stored. Parameters without a transform are treated as real values. The range check and storage always operate on the real value.
Forcing
- class hydrobricks.Forcing(spatial_entity: HydroUnits | Catchment)[source]
Bases:
objectClass for managing forcing (meteorological) data for hydrological models.
- class Variable(value)[source]
Bases:
StrEnumEnumeration of supported meteorological variables.
- P = 'p'
- PET = 'pet'
- PRESSURE = 'pressure'
- RH = 'rh'
- RH_MAX = 'rh_max'
- RH_MIN = 'rh_min'
- R_NET = 'r_net'
- R_SOLAR = 'r_solar'
- SD = 'sd'
- T = 't'
- T_DEW_POINT = 't_dew_point'
- T_MAX = 't_max'
- T_MIN = 't_min'
- WIND = 'wind'
- apply_operations(parameters: ParameterSet | None = None, apply_to_all: bool = True) None[source]
Apply the pre-defined operations.
Executes all spatialization, correction, and PET computation operations that were previously defined. Operations are applied in a fixed order: 1. Prior corrections 2. Station data spatialization 3. Gridded data spatialization 4. PET computation
- Parameters:
parameters – The parameter object instance. Required if operations reference parameters using the ‘param:’ prefix.
apply_to_all – If True, the operations will be applied to all variables. If False, the operations will only be applied to the variables related to parameters defined in the parameters.allow_changing list. This is useful to avoid re-applying, during the calibration phase, operations that have already been applied previously. Default: True
- Raises:
ValueError – If operations reference parameters but no parameter object is provided.
- compute_pet(method: str, use: list[str], lat: float | None = None, **kwargs: Any) None[source]
Define a PET computation operation using the pyet library. The PET is computed for all hydro units.
The operation is stored and applied later (deferred execution). The
methodis validated immediately.- Parameters:
method – Name of the method to use. Possible values are those provided in the table from the pyet documentation: https://pypi.org/project/pyet/. The method name or the pyet function name can be used.
use – List of the meteorological variables to use to compute the PET. Only the variables listed here will be used. The variables must be named according to the pyet naming convention (see the pyet API documentation: https://pyet.readthedocs.io/en/latest/api/index.html) and must be available (loaded in the forcing) and spatialized. Example: use=[‘t’, ‘tmin’, ‘tmax’, ‘lat’, ‘elevation’]
lat – Latitude of the catchment (degrees). If not provided, the latitude computed for each hydro unit is used.
**kwargs – Additional function-specific options passed through to the pyet function (see the pyet documentation).
- Raises:
DependencyError – If pyet is not installed.
ForcingError – If the PET method is not recognized.
- correct_station_data(variable: str, method: str = 'multiplicative', correction_factor: float | str | None = None) None[source]
Define a prior correction operation to apply to station forcing data.
The operation is stored and applied later (deferred execution). The
variableandmethodare validated immediately so mistakes are reported at the call site.- Parameters:
variable – Name or alias of the variable to correct (e.g. ‘precipitation’, ‘p’).
method – Correction method: ‘multiplicative’ (default) or ‘additive’.
correction_factor – Value of the correction factor (to add or multiply). A
'param:<name>'string can be given to have the value taken from the parameter set at calibration time.
- Raises:
ForcingError – If the variable/method is not recognized or
correction_factoris missing.
Examples
>>> forcing.correct_station_data( ... variable='temperature', ... method='additive', ... correction_factor=0.5 # Add 0.5 degrees ... )
- get_total_precipitation() float[source]
Calculate the catchment-average total precipitation.
Computes the weighted average precipitation across all hydro units based on their areas.
- Returns:
Total precipitation in mm (or original units if data is in different units).
- Return type:
float
- get_variable_enum(variable: str) Variable[source]
Match a variable name string to the corresponding Variable enum value.
- Parameters:
variable – Variable name or alias (e.g., ‘precipitation’, ‘precip’, ‘p’, ‘P’).
- Returns:
The corresponding Variable enum value.
- Return type:
- Raises:
ValueError – If the variable name is not recognized.
Examples
>>> forcing = Forcing(hydro_units) >>> var = forcing.get_variable_enum('precip') >>> var == Forcing.Variable.P True
- is_initialized() bool[source]
Check if the forcing has been initialized.
- Returns:
True if the forcing has been initialized, False otherwise.
- Return type:
bool
- load_from(path: str | Path) None[source]
Load data from a netCDF file created using save_as().
Reads a previously saved netCDF file containing spatialized forcing data and loads it into the Forcing object’s data2D structure.
- Parameters:
path – Path of the file to read.
- Raises:
ImportError – If netcdf4 is not installed.
ValueError – If the hydro units in the file don’t match the Forcing object’s hydro units.
Notes
The loaded data will have the same structure as if it was created through spatialization operations. The Forcing object will be marked as initialized after successful loading.
- load_station_data_from_csv(path: str | Path, column_time: str, time_format: str, content: dict[str, str] | None = None) None[source]
Read 1D time series data from CSV file for a single station.
- Parameters:
path – Path to the CSV file containing station data.
column_time – Column name containing the time values.
time_format – Format string for parsing time values (e.g., ‘%Y-%m-%d’).
content – Dictionary mapping variable names/aliases to CSV column names. Example: {‘precipitation’: ‘Precipitation (mm)’, ‘temperature’: ‘Temp (C)’} Default: None
- Raises:
FileNotFoundError – If the CSV file does not exist.
KeyError – If required columns are not found in the CSV file.
Examples
>>> forcing.load_station_data_from_csv( ... 'weather.csv', ... 'Date', ... '%Y-%m-%d', ... {'precipitation': 'P (mm)', 'temperature': 'T (C)'} ... )
- save_as(path: str | Path, max_compression: bool = False) None[source]
Create a netCDF file with the forcing data.
Saves the 2D spatialized forcing data to a netCDF4 file with the structure suitable for later loading with load_from().
- Parameters:
path – Path of the file to create.
max_compression – Option to allow maximum compression for data in file. When True, uses compression with least_significant_digit=3 for better storage efficiency. Default: False
- Raises:
ImportError – If netcdf4 is not installed.
Notes
If apply_operations() has not been called, it will be called automatically before saving to ensure data is properly spatialized.
- spatialize_from_gridded_data(variable: str, method: str = 'default', path: str | Path | None = None, file_pattern: str | None = None, data_crs: int | None = None, var_name: str | None = None, dim_time: str | None = None, dim_x: str | None = None, dim_y: str | None = None, raster_hydro_units: str | Path | None = None, apply_data_gradient: bool | None = None, gradient_type: str | None = None) None[source]
Define a spatialization operation from gridded data to all hydro units.
The operation is stored and applied later (deferred execution). The
variableandmethodare validated immediately.- Parameters:
variable – Name or alias of the variable to spatialize.
method – Name of the method to use. Currently only ‘regrid_from_netcdf’ (the ‘default’).
path – Path to the file containing the data or to a folder containing multiple files.
file_pattern – Pattern of the files to read. If None, the path is considered a single file.
data_crs – CRS (as EPSG id) of the data file. If None, the CRS is read from the file.
var_name – Name of the variable to read in the netCDF file.
dim_time – Name of the time dimension (default ‘time’).
dim_x – Name of the x dimension (default ‘x’).
dim_y – Name of the y dimension (default ‘y’).
raster_hydro_units – Path to a raster containing the hydro unit ids used for the spatialization.
apply_data_gradient – If True, elevation-based gradients are retrieved from the data and applied to the hydro units (e.g. for temperature and precipitation). If None, the default depends on the variable (True for temperature and precipitation, False otherwise). Requires the Forcing to be built from a Catchment with a single DEM.
gradient_type – ‘additive’ or ‘multiplicative’. If None, a per-variable default is used.
- Raises:
ForcingError – If the variable or method is not recognized.
- spatialize_from_station_data(variable: str, method: str = 'default', ref_elevation: float | str | None = None, gradient: float | list | str | None = None, gradient_1: float | list | str | None = None, gradient_2: float | list | str | None = None, elevation_threshold: float | str | None = None) None[source]
Define a spatialization operation from station data to all hydro units.
The operation is stored and applied later (deferred execution). The
variableandmethodare validated immediately. Any of the numeric options may be given as a'param:<name>'string to be resolved from the parameter set at calibration time.- Parameters:
variable – Name or alias of the variable to spatialize (e.g. ‘temperature’, ‘t’).
method –
Name of the method to use:
’default’: pick a sensible method for the variable (additive gradient for temperature, multiplicative for precipitation, constant for PET).
’constant’: the same value is used for every hydro unit.
’additive_elevation_gradient’: additive elevation gradient, constant or one value per month. Uses ‘ref_elevation’ and ‘gradient’.
’multiplicative_elevation_gradient’: multiplicative elevation gradient, constant or one value per month. Uses ‘ref_elevation’ and ‘gradient’.
’multiplicative_elevation_threshold_gradients’: as above but with a gradient below and above an elevation threshold. Uses ‘ref_elevation’, ‘gradient’, ‘gradient_2’ and ‘elevation_threshold’.
ref_elevation – Reference (station) elevation. Required for the gradient methods.
gradient – Gradient of the variable per 100 m (e.g. °C/100 m). Either a single value or a list of 12 monthly values.
gradient_1 – Alias of
gradient(used ifgradientis not provided).gradient_2 – Gradient per 100 m for the units above
elevation_threshold(threshold method only).elevation_threshold – Threshold elevation to switch from
gradienttogradient_2.
- Raises:
ForcingError – If the variable or method is not recognized.
Discharge observations
- class hydrobricks.DischargeObservations(start_date: str | pd.Timestamp | datetime | Period | Periods, end_date: str | pd.Timestamp | datetime | None = None)[source]
Bases:
TimeSeries1DObserved discharge time series (the primary calibration signal).
- compute_reference_metric(metric: str, start_date: str | None = None, end_date: str | None = None, with_exclusion: bool = False, mean_discharge: bool = False, all_combinations: bool = False, n_evals: int = 100) float[source]
Compute a reference for the provided metric (goodness of fit) by block bootstrapping the observed series n_evals times (100 times by default), evaluating the bootstrapped series using the provided metric and computing the mean of the results.
- Parameters:
metric – The abbreviation of the function as defined in HydroErr (https://hydroerr.readthedocs.io/en/stable/list_of_metrics.html) Examples: ‘nse’, ‘kge_2012’, ‘rmse’, etc.
start_date – Start date string for period of interest (format: ‘YYYY-MM-DD’). If None, uses full time series. Default: None
end_date – End date string for period of interest (format: ‘YYYY-MM-DD’). If None, uses full time series. Default: None
with_exclusion – If True, avoid using the same year’s data for the same position in the bootstrapped sample, ensuring no self-selection for specific years. Default: False
mean_discharge – If True, computes the average on the discharge directly rather than on the result of the HydroErr function. Default: False
all_combinations – If True uses all combinations possible for the bootstrapping. If False, randomly samples n_evals combinations. Default: False
n_evals – Number of random evaluations to perform (ignored if all_combinations=True). Default: 100
- Returns:
The mean value of n_evals realizations of the selected metric.
- Return type:
float
- Raises:
DataError – If there is only one year of data (insufficient for block bootstrapping).
ValueError – If metric is not recognized or if time series setup is invalid.
Examples
>>> obs = DischargeObservations('2000-01-01', '2010-12-31') >>> obs.load_from_csv('data.csv', 'date', '%Y-%m-%d', {'discharge': 'Q'}) >>> ref_metric = obs.compute_reference_metric('nse', n_evals=100)
- load_from_csv(path: str | Path, column_time: str, time_format: str, content: dict[str, str], start_date: str | pd.Timestamp | datetime | None = None, end_date: str | pd.Timestamp | datetime | None = None) None[source]
Read discharge observations from a CSV file.
Restricted by default to
[start_date, end_date]as given to the constructor, so the loaded series already matches the simulation period (no manual pre-slicing needed). Passstart_date/end_datehere to load a different range instead (e.g. to deliberately load a period wider than the constructor’s, for testing).- Parameters:
path – Path to the CSV file containing the discharge data.
column_time – Column name containing the time values.
time_format – Format string for parsing time values (e.g., ‘%Y-%m-%d’).
content – Dictionary mapping variable names/enums to column names in the CSV. Example: {‘discharge’: ‘Discharge (mm/d)’}
start_date – Overrides the constructor’s
start_date/end_datefor this load.end_date – Overrides the constructor’s
start_date/end_datefor this load.
- Raises:
FileNotFoundError – If the specified file does not exist.
KeyError – If required columns are not found in the CSV file.
Examples
>>> obs = DischargeObservations('2000-01-01', '2010-12-31') >>> obs.load_from_csv('data.csv', 'date', '%Y-%m-%d', {'discharge': 'Q'})
Periods
- class hydrobricks.Period(start: str | datetime | pd.Timestamp, end: str | datetime | pd.Timestamp, name: str | None = None)[source]
Bases:
objectA named, inclusive date range (e.g. the calibration period).
- Parameters:
start – Period bounds (inclusive), as
'YYYY-MM-DD'strings, datetimes or Timestamps.end – Period bounds (inclusive), as
'YYYY-MM-DD'strings, datetimes or Timestamps.name – Optional label (e.g.
'calibration'), used in tables and error messages.
- property bounds: tuple[str, str]
The period bounds as
('YYYY-MM-DD', 'YYYY-MM-DD')strings.
- classmethod coerce(value: Period | tuple | list, name: str | None = None) Period[source]
Build a Period from a Period or a
(start, end)pair.
- mask(time: pd.DatetimeIndex | pd.Series) np.ndarray[source]
Boolean mask selecting the period on the given time axis.
- property n_days: int
The number of days in the (inclusive) period.
- class hydrobricks.Periods(calibration: Period | tuple | list | None = None, validation: Period | tuple | list | None = None, simulation: Period | tuple | list | None = None, spinup: int | str = '4y')[source]
Bases:
objectThe canonical modelling periods and the spin-up policy.
Groups the calibration period, the validation period and the simulation span, so a single object can drive the model setup, the calibration and the per-period evaluation (split-sample testing).
- Parameters:
calibration – The calibration period, as a
Periodor(start, end)pair.validation – The validation period. Optional.
simulation – The simulation span. Defaults to the union span of the other periods (earliest start to latest end).
spinup – The spin-up policy applied to a model set up over one of these periods: the first years/days of the period are replayed (unlogged) to initialize the states before the run restarts at the period start. Either a number of days (int) or a string like
'4y'(default: 4 years). A spin-up longer than a period is clamped to that period (i.e. the whole period is replayed once).
Examples
>>> periods = Periods( ... calibration=('1981-01-01', '2000-12-31'), ... validation=('2001-01-01', '2020-12-31'), ... spinup='4y', ... ) >>> periods.calibration.bounds ('1981-01-01', '2000-12-31')
- hydrobricks.evaluate_periods(model: Model, observations: DischargeObservations | np.ndarray, periods: Periods, metrics: Iterable[str] = ('kge_2012',)) pd.DataFrame[source]
Evaluate a simulation on each declared period (split-sample table).
The model must have been run over a span covering the periods (typically the full span,
periods.simulation); each metric is then computed on the date slice of every defined period. This is the recommended validation workflow: calibrate on the calibration period, re-run the best parameters over the full span, and read the calibration/validation scores from this table.- Parameters:
model – A model that has been
setup()andrun().observations – The observed discharge: a
DischargeObservations(sliced by its own dates) or an array aligned with the simulated series.periods – The periods to evaluate on.
metrics – HydroErr metric names (e.g.
'nse','kge_2012').
- Return type:
A DataFrame with one row per period and one column per metric.
Results
- class hydrobricks.Results(filename: str)[source]
Bases:
objectClass for the detailed results of a model run. This class is used to read the results of a model run (from a netCDF file) and to provide methods to extract the results.
- get_hydro_units_structure_ids() numpy.ndarray[source]
Get the model-structure id used by each hydro unit.
Units sharing the same subsurface use the same structure; an exclusive land cover (e.g. a lake) places a unit on a different structure variant. Useful to identify which units a given (possibly NaN-omitted) component applies to.
- Returns:
Structure id per hydro unit (1D array, defaults to 1).
- Return type:
np.ndarray
- get_hydro_units_values(component: str, start_date: str | None = None, end_date: str | None = None) numpy.ndarray[source]
Get the values of a component at the hydro units.
Retrieves time series or snapshot data for a specific model component distributed across hydro units. Supports optional temporal slicing.
- Parameters:
component – The name of the component (e.g., ‘snowpack’, ‘soil_moisture’). Use list_hydro_units_components() to see available options.
start_date – The start date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns full time series from the beginning. Default: None
end_date – The end date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns up to end of time series. Default: None
- Returns:
Values of the component at the hydro units. Shape: (n_timesteps, n_hydro_units) for time series, or (n_hydro_units,) for single date if only start_date provided.
- Return type:
np.ndarray
- Raises:
ValueError – If the component is not found in the results.
KeyError – If date selection fails or dates are not in the time series.
- get_land_cover_areas(land_cover: str, start_date: str | None = None, end_date: str | None = None) numpy.ndarray[source]
Get the areas of a land cover across the hydro units.
Calculates the spatial distribution of a specific land cover type across hydro units over time by multiplying the land cover fractions with the hydro unit areas. Supports optional temporal slicing (matching the behaviour of get_hydro_units_values).
- Parameters:
land_cover – The name of the land cover type (e.g., ‘glacier’, ‘ground’, ‘forest’).
start_date – The start date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns the full time series. Default: None
end_date – The end date of the period to extract (format: ‘YYYY-MM-DD’). If None (with start_date set), returns a single-date snapshot. Default: None
- Returns:
Areas of the land cover across the hydro units (2D array: units × time), or (units,) for a single date. Units match the hydro unit area units (typically m² or km²).
- Return type:
np.ndarray
- Raises:
ValueError – If the land cover is not found in the results.
IndexError – If labels_land_cover is None or empty.
- get_mean_hydro_units_values(land_cover: str, component: str, start_date: str | None = None, end_date: str | None = None) numpy.ndarray[source]
Get the mean values of a component across the hydro units weighted by land cover area.
Computes area-weighted average of a component for a specific land cover type, accounting for spatial variation in land cover distribution across hydro units.
- Parameters:
land_cover – The name of the land cover type to weight by (e.g., ‘glacier’, ‘ground’, ‘forest’).
component – The name of the component (e.g., ‘snowpack’, ‘soil_moisture’). Use list_hydro_units_components() to see available options.
start_date – The start date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns full time series. Default: None
end_date – The end date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns up to end of time series. Default: None
- Returns:
Weighted mean values of the component across the hydro units (1D time series). Weights are based on the land cover area in each hydro unit.
- Return type:
np.ndarray
- Raises:
ValueError – If the land cover or component is not found in the results.
- get_mean_swe(start_date: str | None = None, end_date: str | None = None) numpy.ndarray[source]
Get the mean snow water equivalent (SWE) across the hydro units weighted by land cover.
Computes the catchment-wide average snow water equivalent by aggregating SWE values across all land cover types and hydro units, weighted by their respective areas.
- Parameters:
start_date – The start date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns full time series. Default: None
end_date – The end date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns up to end of time series. Default: None
- Returns:
Mean SWE across the hydro units (1D time series, units: mm water equivalent). A scalar for a single date.
- Return type:
np.ndarray
Notes
Land covers without a snowpack (e.g. open water) contribute zero SWE over their area, diluting the average as expected.
- get_time_array(start_date: str, end_date: str) numpy.ndarray[source]
Get the time array.
Extracts the time coordinates from the results dataset for a specified date range. Useful for creating time-aligned arrays for plotting or analysis.
- Parameters:
start_date – The start date of the period to extract (format: ‘YYYY-MM-DD’).
end_date – The end date of the period to extract (format: ‘YYYY-MM-DD’).
- Returns:
Array of time values (typically datetime64) for the specified period.
- Return type:
np.ndarray
- Raises:
KeyError – If dates are not found in the results time coordinates.
- get_total_swe(start_date: str | None = None, end_date: str | None = None) numpy.ndarray[source]
Get the total snow water equivalent (SWE) per hydro unit, aggregated across land covers.
SWE is stored per land cover. For each hydro unit this combines the per-land-cover snowpack into a single unit-average SWE depth, weighted by the land cover areas within the unit. Unlike get_mean_swe(), the hydro unit dimension is preserved (no catchment-wide averaging).
- Parameters:
start_date – The start date of the period to extract (format: ‘YYYY-MM-DD’). If None, returns full time series. Default: None
end_date – The end date of the period to extract (format: ‘YYYY-MM-DD’). If None (with start_date set), returns a single-date snapshot. Default: None
- Returns:
Total SWE per hydro unit (2D array: units × time, units: mm water equivalent), or (units,) for a single date.
- Return type:
np.ndarray
Notes
Land covers without a snowpack (e.g. open water) contribute zero SWE over their area, diluting the per-unit average as expected.
- list_hydro_units_components() None[source]
Print a list of the distributed (hydro unit level) components.
Displays all component names that have values distributed across individual hydro units. These are typically state variables like snowpack, soil moisture, or groundwater storage.
- list_sub_basin_components() None[source]
Print a list of the aggregated (sub-basin level) components.
Displays all component names that have aggregated values at the sub-basin level. These are typically fluxes or flows that are summed across the entire catchment (e.g., total runoff, evapotranspiration).
TimeSeries
StructureGraph
- class hydrobricks.structure.StructureGraph(nodes: list[Node], edges: list[Edge], *, structure_id: int = 1, n_structures: int = 1, model_name: str | None = None, solver: str | None = None)[source]
Bases:
objectThe structure graph of one model structure variant.
- classmethod from_settings(structures: list[dict], structure_id: int = 1, *, model_name: str | None = None, solver: str | None = None, with_forcing: bool = True) StructureGraph[source]
Build the graph from the C++
SettingsModel.get_structure()export.- Parameters:
structures – The list of structure-variant dicts returned by
get_structure().structure_id – Which structure variant to build (default 1, the primary). Models with glacier/lake covers have several variants.
model_name – Optional metadata shown in the summary.
solver – Optional metadata shown in the summary.
with_forcing – Add forcing sources (precipitation, pet, …) as nodes feeding the components that consume them.
- plot(path: str | None = None, fmt: str = 'png', view: bool = False, legend: bool = True, nodesep: float = 0.5, ranksep: float = 0.7, dpi: int = 200)[source]
Render the structure as a directed graph with Graphviz.
- Parameters:
path – Output file path without extension (e.g.
'structure'). If None, the rendered graph object is returned without writing a file.fmt – Output format (e.g. ‘png’, ‘pdf’, ‘svg’). Vector formats (‘pdf’, ‘svg’) are resolution-independent and give the sharpest result.
view – Open the rendered file with the default viewer.
legend – Add a legend describing the node and flux styles (default True).
nodesep – Graphviz spacing (inches) between nodes in a rank and between ranks; larger values give the diagram more breathing room.
ranksep – Graphviz spacing (inches) between nodes in a rank and between ranks; larger values give the diagram more breathing room.
dpi – Raster (e.g. PNG) resolution in dots per inch; raise it for a crisper image. Ignored for vector formats.
- Return type:
The
graphviz.Digraphobject.- Raises:
DependencyError – If the optional
graphvizpackage is not installed.
- to_dot(legend: bool = True, nodesep: float = 0.5, ranksep: float = 0.7, dpi: int = 200) str[source]
Return the graph as a Graphviz DOT string (no dependency required).
nodesep/ranksepset the Graphviz spacing (inches) between nodes in a rank and between ranks; larger values give the diagram more breathing room.dpisets the raster (e.g. PNG) resolution; it is ignored for vector formats.
Trainer
- class hydrobricks.trainer.SpotpySetup(model: Model | list[Model] | None = None, params: ParameterSet | None = None, forcing: Forcing | list[Forcing] | None = None, discharge: DischargeObservations | list[DischargeObservations] | None = None, warmup: int | None = None, obj_func: str | Callable[[np.ndarray, np.ndarray], float] | None = None, dump_outputs: bool = False, dump_forcing: bool = False, dump_dir: str = '', setup_factory: Callable[[], tuple] | None = None, extra_observations: list[AuxiliaryObservation] | None = None, combine: str = 'weighted', discharge_weight: float = 1.0, normalize: bool = True, periods: Periods | None = None)[source]
Bases:
objectSetup class for SPOTPY optimization framework integration.
- classmethod from_factory(setup_factory: Callable[[], tuple], params: ParameterSet, **kwargs: Any) SpotpySetup[source]
Create a picklable setup for parallel calibration.
The
setup_factoryis called once in each worker process to (re)build the model, forcing, and observations; the result is cached and reused across that worker’s evaluations. This avoids pickling the C++-backed objects, which is required for SPOTPYparallel='mpc'/'mpi'(and in particular on Windows, where workers are spawned, not forked).- Parameters:
setup_factory – Picklable callable taking no arguments and returning a
(model, forcing, obs)tuple (each a single instance or a list). Must be a top-level/module-level function (lambdas and closures cannot be pickled by the standard backends).params – ParameterSet defining the model parameters to calibrate. Must itself be picklable (plain hydrobricks ParameterSet instances are).
**kwargs – Forwarded to
SpotpySetup(warmup,obj_func,dump_outputs,dump_forcing,dump_dir).
- Returns:
A setup that builds its models lazily and can be pickled to workers.
- Return type:
- objectivefunction(simulation: list[np.ndarray], evaluation: list[np.ndarray], params: spotpy.parameter | None = None) float | list[float][source]
- parameters() Any[source]
Generate random parameter sets that satisfy constraints.
- Returns:
SPOTPY parameter object with valid random parameter values.
- Return type:
Any
- Raises:
RuntimeError – If unable to generate valid parameters after 1000 attempts.
- simulation(x: spotpy.parameter) list[np.ndarray] | None[source]
Run model simulation with given parameter set.
- Parameters:
x – SPOTPY parameter object containing parameter values.
- Returns:
List of simulated discharge time series (one per model), or None if simulation failed or constraints were violated.
- Return type:
list[np.ndarray] | None
- hydrobricks.trainer.calibrate(spot_setup: SpotpySetup, algorithm: str, repetitions: int, dbname: str | None = None, dbformat: str = 'ram', parallel: str = 'seq', save_sim: bool = True, n_workers: int | None = None, sample_kwargs: dict[str, Any] | None = None, **algorithm_kwargs: Any) Any[source]
Run a SPOTPY calibration, optionally across multiple processes.
Thin convenience wrapper around the SPOTPY algorithm classes that validates the requested parallel backend before sampling. For
parallel='mpc'thespot_setupmust have been built withSpotpySetup.from_factory()so that models can be rebuilt in each worker process.- Parameters:
spot_setup – The configured
SpotpySetup.algorithm – Name of the SPOTPY algorithm (e.g.
'mc','lhs','sceua','dream'), resolved fromspotpy.algorithms.repetitions – Number of repetitions passed to
sampler.sample().dbname – SPOTPY database name (passed through to the algorithm).
dbformat – SPOTPY database format (
'ram','csv', …). Default:'ram'.parallel – SPOTPY parallel backend:
'seq'(default),'mpc'(multiprocessing, requires thepathospackage),'mpi'(requiresmpi4py), or'umpc'. Note that not all algorithms parallelize well: independent samplers (mc,lhs,rope) anddreambenefit most, whereas SCE-UA is largely sequential.save_sim – Whether SPOTPY stores the simulated series. Default: True.
n_workers – Number of worker processes for
parallel='mpc'/'umpc'. Defaults to None, i.e. all logical CPUs. Ignored for'seq'and'mpi'(the MPI process count is set by the MPI launcher, e.g.mpiexec -n).sample_kwargs – Extra keyword arguments forwarded to
sampler.sample(). Needed by some algorithms; e.g. the multi-objectiveNSGAII(used for the glacier mass-balance'pareto'mode) requires{'n_obj': 2}and accepts'n_pop'. Default: None.**algorithm_kwargs – Extra keyword arguments forwarded to the SPOTPY algorithm constructor.
- Return type:
The SPOTPY sampler instance (call
sampler.getdata()for results).
- hydrobricks.trainer.calibrate_from_factory(setup_factory: Callable[[], tuple], algorithm: str, repetitions: int, allow_changing: list[str] | None = None, warmup: int | None = None, obj_func: str | Callable[[np.ndarray, np.ndarray], float] | None = None, dump_outputs: bool = False, dump_forcing: bool = False, dump_dir: str = '', dbname: str | None = None, dbformat: str = 'ram', parallel: str = 'seq', save_sim: bool = True, n_workers: int | None = None, sample_kwargs: dict[str, Any] | None = None, extra_observations: list[AuxiliaryObservation] | None = None, combine: str = 'weighted', discharge_weight: float = 1.0, normalize: bool = True, periods: Periods | None = None, **algorithm_kwargs: Any) Any[source]
Build a calibration setup from a single factory and run it (parallel-ready).
This is the simplest way to run a calibration, including in parallel: provide one factory that builds everything, and this function assembles the (picklable)
SpotpySetupand runs the sampler. It removes the boilerplate of extracting the parameters, callingSpotpySetup.from_factory(), and thencalibrate()separately.For
parallel='mpc'/'mpi'the factory is shipped to each worker process to rebuild the model there, so it must be a top-level (module-level) function — not a lambda or closure — and the call must be guarded byif __name__ == '__main__':(required on platforms that spawn workers, such as Windows).- Parameters:
setup_factory – Callable taking no arguments and returning a
(model, parameters, forcing, discharge)tuple. Called once in the main process (to obtain the parameters and build the local setup) and once in each worker (to rebuild the model). Must be picklable for parallel runs.algorithm – Name of the SPOTPY algorithm (e.g.
'mc','lhs','sceua').repetitions – Number of repetitions passed to
sampler.sample().allow_changing – Optional list of parameter names/aliases to calibrate. If given, it overrides any
parameters.allow_changingset inside the factory.warmup – Forwarded to
SpotpySetup. Withperiods, the factory must set the model up overperiods.calibration(typically withspinup=periods.spinup) andwarmupmust be left unset.obj_func – Forwarded to
SpotpySetup. Withperiods, the factory must set the model up overperiods.calibration(typically withspinup=periods.spinup) andwarmupmust be left unset.dump_outputs – Forwarded to
SpotpySetup. Withperiods, the factory must set the model up overperiods.calibration(typically withspinup=periods.spinup) andwarmupmust be left unset.dump_forcing – Forwarded to
SpotpySetup. Withperiods, the factory must set the model up overperiods.calibration(typically withspinup=periods.spinup) andwarmupmust be left unset.dump_dir – Forwarded to
SpotpySetup. Withperiods, the factory must set the model up overperiods.calibration(typically withspinup=periods.spinup) andwarmupmust be left unset.periods – Forwarded to
SpotpySetup. Withperiods, the factory must set the model up overperiods.calibration(typically withspinup=periods.spinup) andwarmupmust be left unset.extra_observations – Forwarded to
SpotpySetupto calibrate (also) on auxiliary signals such as glacier mass balance.extra_observationsare light, picklable objects, so they are passed directly rather than rebuilt by the factory.normalize(default True) combines the weighted terms as benchmark skill scores so a discharge KGE/NSE and an auxiliary RMSE share a comparable range.combine – Forwarded to
SpotpySetupto calibrate (also) on auxiliary signals such as glacier mass balance.extra_observationsare light, picklable objects, so they are passed directly rather than rebuilt by the factory.normalize(default True) combines the weighted terms as benchmark skill scores so a discharge KGE/NSE and an auxiliary RMSE share a comparable range.discharge_weight – Forwarded to
SpotpySetupto calibrate (also) on auxiliary signals such as glacier mass balance.extra_observationsare light, picklable objects, so they are passed directly rather than rebuilt by the factory.normalize(default True) combines the weighted terms as benchmark skill scores so a discharge KGE/NSE and an auxiliary RMSE share a comparable range.normalize – Forwarded to
SpotpySetupto calibrate (also) on auxiliary signals such as glacier mass balance.extra_observationsare light, picklable objects, so they are passed directly rather than rebuilt by the factory.normalize(default True) combines the weighted terms as benchmark skill scores so a discharge KGE/NSE and an auxiliary RMSE share a comparable range.dbname – Forwarded to
calibrate().dbformat – Forwarded to
calibrate().parallel – Forwarded to
calibrate().save_sim – Forwarded to
calibrate().n_workers – Forwarded to
calibrate().sample_kwargs – Forwarded to
calibrate().**algorithm_kwargs – Extra sampler options, forwarded to
calibrate()as well.
- Return type:
The SPOTPY sampler instance (call
sampler.getdata()for results).
- hydrobricks.trainer.get_best(sampler: Any, parameters: ParameterSet | None = None) dict[str, Any][source]
Return the best parameter set and its score (skill space, higher is better).
Convenience over
get_results()for single-objective calibrations: it selects the run with the highest skill (after undoing any optimizer sign flip), so the reported score is the true metric value — a KGE of 0.7 is0.7, not-0.7.- Parameters:
sampler – The sampler returned by
calibrate()/calibrate_from_factory().parameters – The ParameterSet that was calibrated. The stored parameter values are in the optimizer’s transformed space; the returned
'parameters'are mapped back to real values via each parameter’s transform, so they can be passed straight toParameterSet.set_values(...). Parameters without a transform are unchanged. This argument is optional:calibrate()stashes the calibrated ParameterSet on the sampler, so the back-transform happens automatically. Pass it only to override that stashed set (e.g. an unpickled sampler that lost it).
- Returns:
{'score': float, 'parameters': {name: value}, 'index': int}whereindexis the row insampler.getdata().- Return type:
dict
- Raises:
ConfigurationError – For a multi-objective (
combine='pareto') calibration, where a single best run is not defined — useget_results()and select a point on the Pareto front instead.
- hydrobricks.trainer.get_results(sampler: Any, parameters: ParameterSet | None = None) Any[source]
Return the calibration results as a DataFrame, scores in skill space.
SPOTPY stores the objective exactly as it was handed to the optimizer, which is the negated skill for minimizing algorithms (SCE-UA, NSGA-II, PADDS). This helper flips it back so every score column is a skill where higher is always better, regardless of the algorithm — e.g. a KGE of 0.7 reads as 0.7, never -0.7. (Error metrics such as
rmseare negated by the skill convention, so a smaller error shows as a larger, less-negative score.)- Parameters:
sampler – The sampler returned by
calibrate()/calibrate_from_factory().parameters – The ParameterSet that was calibrated. SPOTPY samples — and therefore the stored
parcolumns — are in the optimizer’s transformed space; each parameter column is mapped back to its real value using that parameter’s transform, so the returned values match what the model actually used. Parameters without a transform are left unchanged. This argument is optional:calibrate()stashes the calibrated ParameterSet on the sampler, so the back-transform happens automatically. Pass it only to override that stashed set (e.g. an unpickled sampler that lost it).
- Returns:
One row per evaluated parameter set, with the calibrated parameter columns (the SPOTPY
parprefix stripped) and ascorecolumn — orscore1,score2, … for a multi-objective (combine='pareto') calibration. The simulated series are not included.- Return type:
pandas.DataFrame
Evaluation (auxiliary observations)
Model-evaluation data: the observed signals a model is compared against.
This subpackage holds the reference series used to evaluate and calibrate a model
(as opposed to the meteorological forcing, which is model input and lives in
forcing.py):
DischargeObservations— the primary signal (observed discharge).AuxiliaryObservation— base class for additional signals.GlacierMassBalanceObservations— observed glacier mass balance.SnowCoverObservations— observed snow cover fraction (e.g. MODIS).
It also exposes evaluate(), the HydroErr-based goodness-of-fit helper.
- class hydrobricks.evaluation.AuxiliaryObservation[source]
Bases:
objectBase class for an auxiliary calibration/evaluation signal.
Besides the primary discharge, a model can be evaluated against additional observed signals — glacier mass balance, snow cover, … Each such signal is represented by a subclass that knows how to provide the observed values and to compute the matching simulated values from a run model. The two are returned as aligned value vectors (
observed()andsimulated(model)must have the same length and ordering), which keeps the contract agnostic to whether the signal is a time series or a set of per-period / per-band / per-(date, unit) targets.A signal also carries how it should be used during calibration:
mode='objective'contributes aweight-scaled goodness-of-fit (metric) term to the combined objective;mode='constraint'acts as a behavioural pass/fail filter — a run is rejected when the mean absolute error exceedstolerance(absolute, in the signal’s units) or, alternatively,relative_tolerancetimes the mean absolute observed value. Exactly one of the two must be set.
- metric
HydroErr metric name used for the objective term (default
'rmse').- Type:
str
- weight
Weight of this term in the combined
'weighted'score (default 1.0).- Type:
float
- mode
'objective'or'constraint'(default'objective').- Type:
str
- tolerance
Maximum allowed mean absolute error for
'constraint'mode, in the signal’s units. Mutually exclusive withrelative_tolerance.- Type:
float or None
- relative_tolerance
Maximum allowed mean absolute error for
'constraint'mode, expressed as a fraction of the mean absolute observed value (e.g.0.1for 10%). Mutually exclusive withtolerance.- Type:
float or None
- requires_recording
Whether computing the simulated values needs recorded series, either via
record_all=Trueor by recording the specific items returned byrequired_recordings()(default True).- Type:
bool
- configure_recording(model: Model) None[source]
Enable, on
model, the recordings this signal needs.Call this before
model.setup()as a targeted alternative to creating the model withrecord_all=True.
- required_recordings(model: Model) RecordingRequest[source]
Return the specific stores/fluxes this signal needs recorded.
Default: an empty request. Subclasses that read recorded series should override this so the model can record only what is needed, instead of
record_all=True.modelis provided to resolve names (e.g. the glacier land covers) from the model configuration.
- restrict_to_period(start: str | pd.Timestamp | None, end: str | pd.Timestamp | None) None[source]
Restrict the observations to
[start, end](default: no-op).
- simulated(model: Model) np.ndarray[source]
Return the simulated values matching
observed(), from a run model.The model must already have been run (and recorded, if
requires_recording). The returned array must align 1:1 withobserved(); entries that cannot be evaluated should be NaN.
- class hydrobricks.evaluation.RecordingRequest(brick_states: list[tuple[str, str]]=<factory>, process_outputs: list[tuple[str, str, str]]=<factory>, fractions: bool = False)[source]
Bases:
objectThe specific stores/fluxes an auxiliary observation needs recorded.
Used as a lightweight alternative to
record_all: an observation declares exactly which series it reads from a run model, so only those are logged.- brick_states
(brick_name, item)pairs, e.g.("glacier_snowpack", "snow_content"). Logged label:"{brick}:{item}".- Type:
list[tuple[str, str]]
- process_outputs
(brick_name, process_name, item)triples, e.g.("glacier", "melt", "output"). Logged label:"{brick}:{process}:{item}".- Type:
list[tuple[str, str, str]]
- fractions
Whether the time-varying land-cover fractions must be recorded.
- Type:
bool
- class hydrobricks.evaluation.GlacierMassBalanceObservations(metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None)[source]
Bases:
AuxiliaryObservationObserved glacier mass balance, used as an auxiliary calibration signal.
The observations are stored as a flat list of targets, each a single scalar value with its observation period and (optionally) its elevation band. The matching simulated values are produced by
simulated(), in the same order, so the two can be compared directly.- Parameters:
metric – Calibration configuration, see
AuxiliaryObservation.weight – Calibration configuration, see
AuxiliaryObservation.mode – Calibration configuration, see
AuxiliaryObservation.tolerance – Calibration configuration, see
AuxiliaryObservation.relative_tolerance – Calibration configuration, see
AuxiliaryObservation.
- targets
One entry per scalar observation, with keys
t0,t1(period bounds,pd.Timestamp),value(mm w.e.),balance_type, andband_lo/band_hi(m a.s.l., orNonefor a whole-glacier observation).- Type:
list[dict]
- granularity
'whole'or'elevationbins'.- Type:
str
- classmethod from_csv(path: str | Path, value_col: str | int, balance_type: str = 'annual', *, date_start_col: str | int | None = None, date_end_col: str | int | None = None, year_col: str | int | None = None, hydro_year_start: str | int = 'October', band_lo_col: str | int | None = None, band_hi_col: str | int | None = None, band_area_col: str | int | None = None, value_unit: str = 'mm_we', area_unit: str = 'km2', date_format: str | None = None, glacier_id_col: str | int | None = None, glacier_id: str | None = None, start_date: str | pd.Timestamp | None = None, end_date: str | pd.Timestamp | None = None, skiprows: int = 0, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None, **read_csv_kwargs: Any) GlacierMassBalanceObservations[source]
Load observed glacier mass balance from a generic CSV file.
Each row is one observed balance for
balance_type. The observation period is given either by explicitdate_start_col/date_end_col, or derived from ayear_colusing ahydro_year_startmonth (the period runs from the 1st of that month of the year to the day before it a year later — e.g. October → Oct 1 to Sep 30 of the next year; January → the calendar year). Provideband_*columns to load per-elevation-band balances. Call once per balance type for files with several (winter/summer/annual) value columns, or usefrom_glamos().- Parameters:
path – Path to the CSV file.
value_col – Column (name or 0-based index) holding the mass-balance value.
balance_type – What
value_colrepresents:'annual','winter'or'summer'(used only as a label).date_start_col – Columns with the period start/end dates (explicit-period mode).
date_end_col – Columns with the period start/end dates (explicit-period mode).
year_col – Alternative to explicit dates: a year column and the month the hydrological year starts (name or 1-12).
hydro_year_start – Alternative to explicit dates: a year column and the month the hydrological year starts (name or 1-12).
band_lo_col – Columns with the elevation-band bounds [m] and area, for per-band data.
band_hi_col – Columns with the elevation-band bounds [m] and area, for per-band data.
band_area_col – Columns with the elevation-band bounds [m] and area, for per-band data.
value_unit – Units of the value (
'mm_we'or'm_we') and band area ('km2'or'm2'); normalized to mm w.e. and m2.area_unit – Units of the value (
'mm_we'or'm_we') and band area ('km2'or'm2'); normalized to mm w.e. and m2.date_format – Optional explicit date format; otherwise dates are inferred.
glacier_id_col – Optional column and value to filter a single glacier from a multi-glacier file.
glacier_id – Optional column and value to filter a single glacier from a multi-glacier file.
start_date – Keep only observations whose period lies fully within this range.
end_date – Keep only observations whose period lies fully within this range.
skiprows – Rows to skip at the top of the file (metadata header).
metric – Calibration configuration (see the class docstring).
weight – Calibration configuration (see the class docstring).
mode – Calibration configuration (see the class docstring).
tolerance – Calibration configuration (see the class docstring).
relative_tolerance – Calibration configuration (see the class docstring).
**read_csv_kwargs – Extra keyword arguments forwarded to
pandas.read_csv.
- Return type:
The populated observations object.
- classmethod from_glamos(path: str | Path, kind: str = 'whole', glacier_id: str | None = None, balance_types: tuple[str, ...] | list[str] = ('annual',), start_date: str | pd.Timestamp | None = None, end_date: str | pd.Timestamp | None = None, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None) GlacierMassBalanceObservations[source]
Load a GLAMOS “fixdate” mass-balance CSV file (preset over the CSV reader).
Handles the GLAMOS file layout (metadata/citation header rows, a
date_startshort-name header row, then a units row). The observation periods are taken from the per-row dates, so the hydrological year of the data is respected without any extra configuration.- Parameters:
path – Path to the GLAMOS CSV file.
kind –
'whole'for the whole-glacier file (one value per period) or'elevationbins'for the per-elevation-bin file.glacier_id – If given, keep only the rows of this glacier id (e.g.
'B43-03').balance_types – Which balances to use among
'annual'(Ba),'winter'(Bw) and'summer'(Bs).start_date – Keep only observations whose period lies fully within this range.
end_date – Keep only observations whose period lies fully within this range.
metric – Calibration configuration (see the class docstring).
weight – Calibration configuration (see the class docstring).
mode – Calibration configuration (see the class docstring).
tolerance – Calibration configuration (see the class docstring).
relative_tolerance – Calibration configuration (see the class docstring).
- Return type:
The populated observations object.
- required_recordings(model: Model) RecordingRequest[source]
The glacier series needed by
simulated()for each glacier cover.For each glacier land cover this records the snowpack snow content, the ice melt output, and (once) the land-cover fractions — the exact inputs of the flux-based surface balance. A targeted alternative to
record_all=True.
- restrict_to_period(start: str | pd.Timestamp | None, end: str | pd.Timestamp | None) None[source]
Keep only targets whose period lies fully within
[start, end].
- simulated(model: Model) np.ndarray[source]
Compute the simulated glacier mass balance matching each observation.
For each target the flux-based surface balance
B_i = ΔS_i − Σ M_ice,iis evaluated per glacier hydro unit over the target’s period, then aggregated (area-weighted by the model’s time-varying glacier area) to the target’s granularity — over all glacierized units for a whole-glacier target, or over the units whose elevation lies in the band for an elevation-bin target.The glacier snowpack, ice melt and land-cover fractions must have been recorded in memory — either with
record_all=Trueor by recording the specific items (seerequired_recordings(), applied viaconfigure_recording(model)beforemodel.setup()).- Returns:
Simulated mass balance [mm w.e.], aligned 1:1 with
observed(). Entries are NaN where the period falls outside the simulation or where no glacier area is available.- Return type:
np.ndarray
- property values: numpy.ndarray
Alias of
observed()(observed values [mm w.e.]).
- class hydrobricks.evaluation.SnowCoverObservations(swe_full: float = 100.0, land_covers: list[str] | None = None, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None)[source]
Bases:
AuxiliaryObservationObserved snow cover fraction, used as an auxiliary calibration signal.
The observations are stored as a flat list of targets, each a single per-(hydro unit, date) fraction. The matching simulated values are produced by
simulated(), in the same order, so the two can be compared directly (RMSE by default).- Parameters:
swe_full – SWE [mm w.e.] at which a hydro unit is considered fully snow-covered, i.e. the threshold of the linear SWE→fraction depletion curve. Default: 100.0.
land_covers – Names of the land covers whose snowpacks contribute to the snow cover (e.g.
['ground']to ignore glacier snow). Default:None(all land covers of the model).metric – Calibration configuration, see
AuxiliaryObservation.weight – Calibration configuration, see
AuxiliaryObservation.mode – Calibration configuration, see
AuxiliaryObservation.tolerance – Calibration configuration, see
AuxiliaryObservation.relative_tolerance – Calibration configuration, see
AuxiliaryObservation.
- targets
One entry per observed fraction, with keys
t(date,pd.Timestamp),unit_id(int) andvalue(fraction in [0, 1]).- Type:
list[dict]
- classmethod from_csv(path: str | Path, *, date_col: str | int, unit_col: str | int, value_col: str | int, value_scale: float = 1.0, valid_min: float | None = None, valid_max: float | None = None, date_format: str | None = None, start_date: str | pd.Timestamp | None = None, end_date: str | pd.Timestamp | None = None, skiprows: int = 0, swe_full: float = 100.0, land_covers: list[str] | None = None, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None, **read_csv_kwargs: Any) SnowCoverObservations[source]
Load pre-aggregated per-hydro-unit snow cover from a long-format CSV.
Each row is one observed snow cover fraction for a given hydro unit and date.
- Parameters:
path – Path to the CSV file.
date_col – Columns (name or 0-based index) holding the observation date, the hydro unit id, and the snow cover value.
unit_col – Columns (name or 0-based index) holding the observation date, the hydro unit id, and the snow cover value.
value_col – Columns (name or 0-based index) holding the observation date, the hydro unit id, and the snow cover value.
value_scale – Factor applied to the value column to obtain a fraction in [0, 1] (e.g.
0.01for a 0-100 % cover). Default: 1.0.valid_min – Keep only raw values within
[valid_min, valid_max](applied beforevalue_scale); values outside are dropped. Use to filter quality/error codes (e.g.valid_max=100for a 0-100 % product).valid_max – Keep only raw values within
[valid_min, valid_max](applied beforevalue_scale); values outside are dropped. Use to filter quality/error codes (e.g.valid_max=100for a 0-100 % product).date_format – Optional explicit date format; otherwise dates are inferred.
start_date – Keep only observations whose date lies within this range.
end_date – Keep only observations whose date lies within this range.
skiprows – Rows to skip at the top of the file (metadata header).
swe_full – Configuration (see the class docstring).
land_covers – Configuration (see the class docstring).
metric – Configuration (see the class docstring).
weight – Configuration (see the class docstring).
mode – Configuration (see the class docstring).
tolerance – Configuration (see the class docstring).
relative_tolerance – Configuration (see the class docstring).
**read_csv_kwargs – Extra keyword arguments forwarded to
pandas.read_csv.
- Return type:
The populated observations object.
- classmethod from_hdf5(path: str | Path, raster_hydro_units: str | Path, hydro_units: Any | None = None, *, var_name: str | None = None, file_pattern: str | None = None, data_crs: int | None = None, dim_time: str = 'time', dim_x: str = 'x', dim_y: str = 'y', value_scale: float = 1.0, nodata: float | None = None, valid_min: float | None = None, valid_max: float | None = None, min_valid_ratio: float = 0.5, start_date: str | pd.Timestamp | None = None, end_date: str | pd.Timestamp | None = None, swe_full: float = 100.0, land_covers: list[str] | None = None, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None, engine: str | None = None, group: str | None = None, cache_dir: str | Path | None = None) SnowCoverObservations[source]
Load and aggregate a snow-cover HDF5 stack per hydro unit.
Same as
from_netcdf()but reads HDF5 files:enginedefaults to'h5netcdf'when available, falling back to'netcdf4'(which reads NetCDF4/HDF5). For data that stores its variable in an HDF5 group, passgroup. Quality/error codes are filtered withvalid_min/valid_max(e.g.valid_max=100to drop MODIS codes above 100 %). See_from_stack()for the full parameter description.
- classmethod from_modis(path: str | Path, raster_hydro_units: str | Path, hydro_units: Any | None = None, *, variable: str = 'NDSI_Snow_Cover', file_pattern: str = '*.hdf', date_regex: str = 'A(\\d{7})', date_format: str = '%Y%j', date_parser: Any | None = None, value_scale: float = 0.01, valid_min: float | None = 0.0, valid_max: float | None = 100.0, nodata: float | None = None, min_valid_ratio: float = 0.5, resampling: str = 'nearest', engine: str = 'netcdf4', start_date: str | pd.Timestamp | None = None, end_date: str | pd.Timestamp | None = None, swe_full: float = 100.0, land_covers: list[str] | None = None, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None, cache_dir: str | Path | None = None) SnowCoverObservations[source]
Load MODIS (HDF-EOS) daily snow-cover tiles, aggregated per hydro unit.
Reads HDF-EOS grid products such as MOD10A1 / MYD10A1 (NDSI snow cover). Each file holds one date’s tile; the date is parsed from the file name, tiles sharing a date are mosaicked, and the data are reprojected from the MODIS sinusoidal grid (read from the file’s
StructMetadata) to the hydro-unit raster’s CRS before aggregating. The defaultvalid_min=0/valid_max=100drop the product’s quality/error codes (200=missing, 250=cloud, 255=fill, …), andvalue_scale=0.01converts the 0-100 % NDSI snow cover to a fraction.Reading the HDF-EOS files uses xarray’s
netcdf4engine (the bundlednetCDF4reads HDF4-EOS); no separate HDF4/GDAL build is required.- Parameters:
path – Folder of tiles (with
file_pattern) or a single file.raster_hydro_units – The hydro-unit id raster and (optionally) the units to aggregate; see
_from_stack().hydro_units – The hydro-unit id raster and (optionally) the units to aggregate; see
_from_stack().variable – Data field to read (default
'NDSI_Snow_Cover').file_pattern – Glob of the tile files (default
'*.hdf').date_regex – Parse the date from the file name:
date_regex’s first group is parsed withdate_format(defaults match MODISA%Y%jtokens, e.g.A2025361).date_format – Parse the date from the file name:
date_regex’s first group is parsed withdate_format(defaults match MODISA%Y%jtokens, e.g.A2025361).date_parser – Optional callable
(filename) -> pd.Timestampoverriding the regex.value_scale – Aggregation/filtering options; see
_from_stack().valid_min – Aggregation/filtering options; see
_from_stack().valid_max – Aggregation/filtering options; see
_from_stack().nodata – Aggregation/filtering options; see
_from_stack().min_valid_ratio – Aggregation/filtering options; see
_from_stack().resampling – Resampling for the reprojection to the hydro-unit grid (a
rasterio.enums.Resamplingname, default'nearest').engine – xarray engine used to read the files (default
'netcdf4').start_date – Configuration; see
_from_stack()and the class docstring.end_date – Configuration; see
_from_stack()and the class docstring.swe_full – Configuration; see
_from_stack()and the class docstring.land_covers – Configuration; see
_from_stack()and the class docstring.metric – Calibration-signal configuration; see the class docstring.
weight – Calibration-signal configuration; see the class docstring.
mode – Calibration-signal configuration; see the class docstring.
tolerance – Calibration-signal configuration; see the class docstring.
relative_tolerance – Calibration-signal configuration; see the class docstring.
cache_dir – If given, the aggregated per-(unit, date) fractions are cached there as a CSV named
snow_cover_<hash>.csv. The hash is built from the hydro-unit id raster (the discretization), the aggregation options and a signature of the input tiles, so caches never mix across discretizations or settings. On a later call with the same inputs the CSV is loaded directly (skipping the slow tile reading); otherwise it is written after aggregating. Default:None(no caching).
- Return type:
The populated observations object.
- classmethod from_netcdf(path: str | Path, raster_hydro_units: str | Path, hydro_units: Any | None = None, *, var_name: str | None = None, file_pattern: str | None = None, data_crs: int | None = None, dim_time: str = 'time', dim_x: str = 'x', dim_y: str = 'y', value_scale: float = 1.0, nodata: float | None = None, valid_min: float | None = None, valid_max: float | None = None, min_valid_ratio: float = 0.5, start_date: str | pd.Timestamp | None = None, end_date: str | pd.Timestamp | None = None, swe_full: float = 100.0, land_covers: list[str] | None = None, metric: str = 'rmse', weight: float = 1.0, mode: str = 'objective', tolerance: float | None = None, relative_tolerance: float | None = None, engine: str | None = None, group: str | None = None, cache_dir: str | Path | None = None) SnowCoverObservations[source]
Load and aggregate a snow-cover NetCDF stack per hydro unit.
See
_from_stack()for the full parameter description. This is the netCDF variant; for HDF5 inputs usefrom_hdf5().
- required_recordings(model: Model) RecordingRequest[source]
The snowpack series needed by
simulated().For each contributing land cover this records the snowpack snow content and (once) the land-cover fractions, the inputs of the SWE-to-fraction transform. A targeted alternative to
record_all=True.
- restrict_to_period(start: str | pd.Timestamp | None, end: str | pd.Timestamp | None) None[source]
Keep only targets whose date lies within
[start, end].
- simulated(model: Model) np.ndarray[source]
Compute the simulated snow cover fraction matching each observation.
For each land cover the recorded snowpack SWE is turned into a per-unit cover fraction (linear depletion curve, see
_swe_to_fraction()), then combined across land covers as a land-cover-fraction-weighted mean. The result is then read per target at its (hydro unit, date).The snowpack snow content and the land-cover fractions must have been recorded in memory — either with
record_all=Trueor by recording the specific items (seerequired_recordings(), applied viaconfigure_recording(model)beforemodel.setup()).- Returns:
Simulated snow cover fraction [0, 1], aligned 1:1 with
observed(). Entries are NaN where the date falls outside the simulation or the unit is absent.- Return type:
np.ndarray
- to_csv(path: str | Path) None[source]
Save the per-(hydro unit, date) observations to a long-format CSV.
The file has
date,unit_idandvaluecolumns and can be read back withfrom_csv()(it is also the format used by the raster loaders’ cache).
- property values: numpy.ndarray
Alias of
observed()(observed fractions [0, 1]).