Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING CHANGE: Redesing Parameters module #136

Merged
merged 34 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
62ae8a7
add test marks
MAfarrag Jan 3, 2025
06c07d6
add a separate class for figshare `FigshareAPIClient`
MAfarrag Jan 4, 2025
74c7c63
add a separate class `FileManager`
MAfarrag Jan 4, 2025
f39d943
add a separate class `ParameterManager` and tests
MAfarrag Jan 4, 2025
cc09c99
create fig_share mark to mark the end-to-end tests that calls the fig…
MAfarrag Jan 5, 2025
8b50eec
add new design for the `Parameter` class in the parameters.py module
MAfarrag Jan 5, 2025
68d18c1
correct the coverage path in pre-commit hooks
MAfarrag Jan 5, 2025
f495983
arr hooks for notebooks and docstring
MAfarrag Jan 5, 2025
4d7c05d
add docstring and examples for the parameters.py module
MAfarrag Jan 5, 2025
5704d6d
ignore fig_share tests in ci
MAfarrag Jan 5, 2025
2497022
ignore whitespaces and ellipsis in the pre-commit hooks
MAfarrag Jan 5, 2025
ab77c23
move ignoring the whitespaces and ellipsis to the pre-commit hooks
MAfarrag Jan 5, 2025
098a276
correct the downloaded parameters path
MAfarrag Jan 5, 2025
86a3758
make the download_dir optional for the `get_parameters` method
MAfarrag Jan 5, 2025
a621c03
mock the `os.path.dirname` to return the src/Hapi in ci instead of th…
MAfarrag Jan 5, 2025
f5e907a
depend on HAPI_DATA_DIR environment variable to store the parameters
MAfarrag Jan 5, 2025
27568d4
remove the mock
MAfarrag Jan 5, 2025
ca71df6
use the `HAPI_DATA_DIR` environment variable in all methods in the `i…
MAfarrag Jan 5, 2025
a7359ba
use the `HAPI_DATA_DIR` environment variable in all methods in the `p…
MAfarrag Jan 5, 2025
e835ef2
clean
MAfarrag Jan 5, 2025
1d0a261
validate paths before reading data
MAfarrag Jan 5, 2025
0ec4ccb
solve the issue of fig_share tests were not running with other tests
MAfarrag Jan 6, 2025
39c4e7b
mock the mkdir method in the Parameter constructor method in the Test…
MAfarrag Jan 6, 2025
7cb2427
mock the integration test for the get_parameters to download only one…
MAfarrag Jan 7, 2025
bd6992a
mock the integration test for the get_parameters to download only one…
MAfarrag Jan 7, 2025
b9cca43
return the fig_share marker
MAfarrag Jan 7, 2025
65262de
add CLI for the parameters module
MAfarrag Jan 8, 2025
13299a8
correct wrong import of the descriptors module from statista
MAfarrag Jan 8, 2025
f6d471f
Merge branch 'redesign-parameters' of github.com:MAfarrag/Hapi into r…
MAfarrag Jan 8, 2025
49dd8ab
add the `HAPI_DATA_DIR` to the documentations
MAfarrag Jan 9, 2025
de09988
restrict the URL schemes allowed, to ensure that only permitted schem…
MAfarrag Jan 9, 2025
634983d
add the changes to the history file
MAfarrag Jan 9, 2025
3e73c7f
replace the `urlretrieve` with `requests` for vulnerability
MAfarrag Jan 9, 2025
e16e633
update readthedoc config with build.os
MAfarrag Jan 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/conda-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ jobs:
conda list
conda config --show-sources
conda config --show
pytest -sv -m "not plot"
pytest -sv -m "not plot" -m "not fig_share"
env:
HAPI_DATA_DIR: ${{ github.workspace }}/src/Hapi/parameters
4 changes: 3 additions & 1 deletion .github/workflows/pypi-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ jobs:

- name: Run Tests
run: |
python -m pytest -vvv --cov=src/Hapi --cov-report=xml
python -m pytest -vvv -m "not fig_share" --cov=src/Hapi --cov-report=xml
env:
HAPI_DATA_DIR: ${{ github.workspace }}/src/Hapi/parameters

- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v3
19 changes: 0 additions & 19 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,30 +161,11 @@ examples/data/Hapi.qgz
*.png
.vscode

"examples/Hydrodynamic models/test_case/inputs/gauges/discharge_long_ts/Statistical analysis results/Figures/F-444222.png"
"examples/Hydrodynamic models/test_case/inputs/gauges/discharge_long_ts/Statistical analysis results/Figures/F-888555.png"
"examples/Hydrodynamic models/test_case/inputs/gauges/discharge_long_ts/Statistical analysis results/Figures/F-999666.png"
examples/Hydrodynamic models/test_case/resultsMetricsHM_Q_Obs.geojson
examples/Hydrodynamic models/test_case/resultsMetricsHM_Q_Obs.geojson.csv
examples/Hydrodynamic models/test_case/resultsMetricsHM_Q_RRM.geojson
examples/Hydrodynamic models/test_case/resultsMetricsHM_Q_RRM.geojson.csv
examples/Hydrodynamic models/test_case/resultsMetricsHM_WL_Obs.geojson
examples/Hydrodynamic models/test_case/resultsMetricsHM_WL_Obs.geojson.csv
examples/Hydrodynamic models/test_case/resultsMetricsRRM_Q_Obs.geojson
examples/Hydrodynamic models/test_case/resultsMetricsRRM_Q_Obs.geojson.csv
Hapi/java_functions.py
*History*
Hapi/parameters/*.tif
*.bin
*.cue
examples/hydrological-model/data/distributed_model/calibration/LB - tot.txt
/examples/Hydrological model/data/meteo_data/meteodata_prepared/temp-rename-example/*.tif
examples/Hydrodynamic models/test_case/results/q/right_results/*
examples/Hydrodynamic models/test_case/results/h/right_results/*
examples/Hydrodynamic models/test_case/results/USbnd/right_results/*
examples/Hydrodynamic models/test_case/results/q/New folder/*
examples/Hydrodynamic models/test_case/results/h/New folder/*
examples/Hydrodynamic models/test_case/results/USbnd/New folder/*
tests/mo/*
/tests/rrm/data/test_results/extract_parameter/01_TT.tif
/tests/rrm/data/test_results/extract_parameter/02_RFCF.tif
Expand Down
19 changes: 18 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,24 @@ repos:
hooks:
- id: pytest-check
name: pytest-check
entry: pytest -vvv --cov=Hapi --cov-report term-missing
entry: pytest -vvv --cov=src/Hapi --cov-report term-missing -m "not fig_share"
language: system
pass_filenames: false
always_run: true

- repo: local
hooks:
- id: examples-notebook-check
name: nbval
entry: pytest --nbval
language: system
files: \.ipynb$

- repo: local
hooks:
- id: doctest
name: doctest
entry: pytest --doctest-modules
args: ["--doctest-glob=*.rst", "-o", "doctest_optionflags=NORMALIZE_WHITESPACE ELLIPSIS"]
language: system
files: ^src/.*\.py$
12 changes: 7 additions & 5 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
# Required
version: 2

conda:
environment: docs/environment.yml
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
#Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml

build:
os: "ubuntu-22.04"
tools:
python: "mambaforge-22.9"

conda:
environment: docs/environment.yml

# Optionally build your docs in additional formats such as PDF and ePub
formats: all
10 changes: 9 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,12 @@ Dev
- move the main packge files inside src directory
- move the hydrodymanic model to separate repo (serapis)
- move the plot module to the cleopatra package
- replace the setup.py by pyproject.toml
- replace the setup.py by pyproject.toml

Parameters
----------
- remove the parameters from the package and retrieve them with the parameter package.
- Redesign the parameters module to separate the responsibility of each class (`Parameter`, `ParameterManager`,
`FileManager`, `FigshareAPIClient`).
- Add CLI to download the parameters from the FigShare server (`list-parameter-names`, `download-parameter-set`,
`download-parameters`).
2 changes: 1 addition & 1 deletion docs/Hydrological model/DistributedModel_calib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ After preparing all the meteorological, GIS inputs required for the model, and E
from Hapi.calibration import Calibration
import Hapi.rrm.hbv_bergestrom92 as HBV

import statista.metrics as metrics
import statista.descriptors as metrics

Path = Comp + "/data/distributed/coello"
PrecPath = Path + "/prec"
Expand Down
6 changes: 3 additions & 3 deletions docs/Hydrological model/Lumped_run.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ To run the HBV lumped model inside Hapi you need to prepare the meteorological i

Run.runLumped(Coello, Route, RoutingFn)

to calculate some metrics for the quality assessment of the calculate discharge the `statista.metrics` contains some
to calculate some metrics for the quality assessment of the calculate discharge the `statista.descriptors` contains some
metrics like `rmse`, `nse`, `kge` and `wb` , you need to load it, a measured time series of doscharge for the same
period of the simulation is also needed for the comparison.

all methods in `statista.metrics` takes two numpy arrays of the same length and return real number.
all methods in `statista.descriptors` takes two numpy arrays of the same length and return real number.

.. code-block:: py
:linenos:
import statista.metrics as metrics
import statista.descriptors as metrics

Metrics = dict()
Qobs = Coello.QGauges['q']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"import Hapi.rrm.hbv_bergestrom92 as HBV\n",
"\n",
"from Hapi.rrm.distparameters import DistParameters as DP\n",
"import statista.metrics as PC"
"import statista.descriptors as PC"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

### Modules
import datetime as dt

import matplotlib
import numpy as np
import pandas as pd

matplotlib.use("TkAgg")
import random
import statista.metrics as metrics

import statista.descriptors as metrics
from deap import algorithms, base, creator, tools

import Hapi.rrm.hbv_bergestrom92 as HBVLumped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import numpy as np
import pandas as pd
import statista.metrics as metrics
import statista.descriptors as metrics

import Hapi.rrm.hbv_bergestrom92 as HBVLumped
from Hapi.calibration import Calibration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import datetime as dt

import matplotlib

matplotlib.use("TkAgg")
import statista.metrics as metrics
import statista.descriptors as metrics

import Hapi.rrm.hbv_bergestrom92 as HBVLumped
from Hapi.catchment import Catchment
Expand Down
2 changes: 1 addition & 1 deletion examples/hydrological-model/coello-lumped-model-run.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import matplotlib

matplotlib.use("TkAgg")
import statista.metrics as PC
import statista.descriptors as PC

import Hapi.rrm.hbv_bergestrom92 as HBVLumped
from Hapi.catchment import Catchment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import numpy as np
from osgeo import gdal
from statista.metrics import rmse
from statista.descriptors import rmse

import Hapi.rrm.hbv_bergestrom92 as HBV
from Hapi.calibration import Calibration
Expand Down
17 changes: 15 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,33 @@ max-line-length = 88
max-complexity = 18
select = "B,C,E,F,W,T4"

[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88


[tool.pytest.ini_options]
markers = [
"vfs: mark a test as a virtual file system.",
"slow: mark test as slow.",
"fast: mark test as fast.",
"plot: test plotting function optional package (deselect with '-m \"not plot\"')"
"plot: test plotting function optional package (deselect with '-m \"not plot\"')",
"e2e: end-to-end test (deselect with '-m \"not e2e\"')",
"mock: mock test (deselect with '-m \"not mock\"')",
"integration: mock test (deselect with '-m \"not integration\"')",
"fig_share: mock test (deselect with '-m \"not fig_share\"')"
]


[build-system]
requires = [
"setuptools>=61",
"wheel",
# "tomli>=1.1.0",
]
build-backend = "setuptools.build_meta"

[project.scripts]
download-parameters = "Hapi.parameters.parameters:main"
download-parameter-set = "Hapi.parameters.parameters:main"
list-parameter-names = "Hapi.parameters.parameters:main"
55 changes: 38 additions & 17 deletions src/Hapi/inputs.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""Rainfall-runoff Inputs."""
from typing import Union
from pathlib import Path

import datetime as dt
import os
from pathlib import Path
from typing import Union

import pandas as pd
from geopandas import GeoDataFrame
from pyramids.dataset import Dataset
from pyramids.datacube import Datacube

import Hapi
from pyramids.dataset import Dataset

PARAMETERS_LIST = [
"01_tt",
Expand Down Expand Up @@ -61,7 +61,7 @@ def __init__(self, src: str):
self.source_dem = src

def prepare_inputs(
self, input_folder: Union[str, Path], output_folder: Union[str, Path]
self, inputs_dir: Union[str, Path], outputs_dir: Union[str, Path]
):
"""prepareInputs.

Expand All @@ -71,10 +71,10 @@ def prepare_inputs(

Parameters
----------
input_folder: [str/Path]
inputs_dir: [str/Path]
path of the folder of the rasters you want to adjust their no of rows, columns and resolution (alignment)
like a source raster.
output_folder: [str]
outputs_dir: [str]
name to create a folder to store resulted rasters.

Example
Expand All @@ -91,15 +91,18 @@ def prepare_inputs(
>>> In = Inputs(dem_path)
>>> Inputs.prepare_inputs(evap_in_path, f"{output_path}/evap")
"""
if not isinstance(output_folder, str):
if not isinstance(outputs_dir, str):
print("output_folder input should be string type")

mask = Dataset.read_file(self.source_dem)
cube = Datacube.read_multiple_files(input_folder, with_order=False)
if not Path(inputs_dir).exists():
raise FileNotFoundError(f"{inputs_dir} does not exist")

cube = Datacube.read_multiple_files(inputs_dir, with_order=False)
cube.open_datacube()
cube.align(mask)
cube.crop(mask, inplace=True)
path = [f"{output_folder}/{file.split('/')[-1]}" for file in cube.files]
path = [f"{outputs_dir}/{file.split('/')[-1]}" for file in cube.files]
cube.to_file(path)

@staticmethod
Expand All @@ -125,15 +128,22 @@ def extract_parameters_boundaries(basin: GeoDataFrame):
["tt", "sfcf","cfmax","cwh","cfr","fc","beta",
"lp","k0","k1","k2","uzl","perc", "maxbas"]
"""
parameters_path = f"{os.path.dirname(Hapi.__file__)}/parameters"
data_dir = Inputs._check_data_dir()
max_dir = data_dir / "max"
min_dir = data_dir / "min"
file_path = data_dir / f"max/{PARAMETERS_LIST[0]}.tif"

dataset = Dataset.read_file(f"{parameters_path}/max/{PARAMETERS_LIST[0]}.tif")
if not file_path.exists() or not max_dir.exists() or not min_dir.exists():
raise FileNotFoundError(f"check the following files{file_path}, {max_dir}, {min_dir} does not exist")

dataset = Dataset.read_file(str(file_path))
basin = basin.to_crs(crs=dataset.crs)

# max values
ub = list()
for i in range(len(PARAMETERS_LIST)):
dataset = Dataset.read_file(
f"{parameters_path}/max/{PARAMETERS_LIST[i]}.tif"
f"{data_dir}/max/{PARAMETERS_LIST[i]}.tif"
)
vals = dataset.stats(mask=basin)
ub.append(vals.loc[vals.index[0], "max"])
Expand All @@ -142,7 +152,7 @@ def extract_parameters_boundaries(basin: GeoDataFrame):
lb = list()
for i in range(len(PARAMETERS_LIST)):
dataset = Dataset.read_file(
f"{parameters_path}/min/{PARAMETERS_LIST[i]}.tif"
f"{data_dir}/min/{PARAMETERS_LIST[i]}.tif"
)
vals = dataset.stats(mask=basin)
lb.append(vals.loc[vals.index[0], "min"])
Expand Down Expand Up @@ -197,8 +207,8 @@ def extract_parameters(
"lp","k0","k1","k2","uzl","perc", "maxbas",'K_muskingum',
'x_muskingum']
"""
parameters_path = os.path.dirname(Hapi.__file__)
parameters_path = f"{parameters_path}/parameters/{scenario}"
data_dir = self._check_data_dir()
parameters_path = data_dir / scenario

if not as_raster:
dataset = Dataset.read_file(f"{parameters_path}/{PARAMETERS_LIST[0]}.tif")
Expand Down Expand Up @@ -356,3 +366,14 @@ def rename_files(
os.rename(
f"{path}/{df.loc[i, 'files']}", f"{path}/{df.loc[i, 'new_names']}"
)

@staticmethod
def _check_data_dir() -> Path:
data_dir = os.getenv("HAPI_DATA_DIR")
if data_dir is None:
raise ValueError("HAPI_DATA_DIR environment variable is not set")
else:
data_dir = Path(data_dir)
if not data_dir.exists():
raise FileNotFoundError(f"{data_dir} does not exist")
return data_dir
13 changes: 0 additions & 13 deletions src/Hapi/parameters/download_parameters.py

This file was deleted.

Loading
Loading