Skip to content

Commit

Permalink
Merge pull request #73 from CSHS-CWRA/release-0.3.0
Browse files Browse the repository at this point in the history
Release 0.3.0
  • Loading branch information
cjauvin authored Mar 11, 2021
2 parents 990ef0f + 976307e commit 165bef2
Show file tree
Hide file tree
Showing 16 changed files with 51 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .cruft.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"project_slug": "ravenpy",
"project_short_description": "A Python wrapper to setup and run the hydrologic modelling framework Raven.",
"pypi_username": "CSHS-CWRA",
"version": "0.2.3",
"version": "0.3.0",
"use_pytest": "y",
"use_pypi_deployment_with_travis": "y",
"add_pyup_badge": "y",
Expand Down
10 changes: 10 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
History
=======

0.3.0
-----

* Migration and refactoring of GIS and IO utilities (`utils.py`, `utilities/gis.py`) from RavenWPS to RavenPy.
* RavenPy can now be installed from PyPI without GIS dependencies (limited functionality).
* Hydro routing product is now supported from `geoserver.py` (a notebook has been added to demonstrate the new functions).
* New script `ravenpy aggregate-forcings-to-hrus` to aggregate NetCDF files and compute updated grid weights.
* Add the basis for a new routing emulator option (WIP).
* Add climpred verification capabilities.

0.2.3
-----

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020, Canadian Society for Hydrological Sciences
Copyright (c) 2021, Canadian Society for Hydrological Sciences

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@

# General information about the project.
project = "RavenPy"
copyright = "2020, David Huard"
copyright = "2021, David Huard"
author = "David Huard"

# The version info for the project you're documenting, acts as replacement
Expand Down
8 changes: 7 additions & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,13 @@ Then clone the Raven Test Data repo somewhere on your disk:
(ravenpy-env) $ git clone git@github.com:Ouranosinc/raven-testdata.git
You can then run the test suite by doing:
Install the pre-commit hook (to make sure that any code you contribute is properly formatted):

.. code-block:: console
(ravenpy-env) $ pre-commit install
If everything was properly installed the test suite should run successfully:

.. code-block:: console
Expand Down
2 changes: 1 addition & 1 deletion ravenpy/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@

__author__ = """David Huard"""
__email__ = "huard.david@ouranos.ca"
__version__ = "0.2.3"
__version__ = "0.3.0"
2 changes: 1 addition & 1 deletion ravenpy/utilities/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .regionalization import read_gauged_params, read_gauged_properties, regionalize

gis_error_message = (
gis_import_error_message = (
"`{}` requires installation of the RavenPy GIS libraries. These can be installed using the"
" `pip install ravenpy[gis]` recipe or via Anaconda (`conda env -n ravenpy-env -f environment.yml`)"
" from the RavenPy repository source files."
Expand Down
4 changes: 2 additions & 2 deletions ravenpy/utilities/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

import numpy as np

from . import gis_error_message
from . import gis_import_error_message

try:
import rasterio
from osgeo.gdal import Dataset, DEMProcessing
from shapely.geometry import GeometryCollection, MultiPolygon, Polygon, shape
except (ImportError, ModuleNotFoundError) as e:
msg = gis_error_message.format(Path(__file__).stem)
msg = gis_import_error_message.format(Path(__file__).stem)
raise ImportError(msg) from e

from ravenpy.utilities.geo import generic_raster_clip
Expand Down
4 changes: 2 additions & 2 deletions ravenpy/utilities/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pathlib import Path
from typing import Any, List, Sequence, Tuple, Union

from . import gis_error_message
from . import gis_import_error_message

try:
import fiona
Expand All @@ -17,7 +17,7 @@
from pyproj.exceptions import CRSError
from shapely.geometry import GeometryCollection, MultiPolygon, Point, shape
except (ImportError, ModuleNotFoundError) as e:
msg = gis_error_message.format(Path(__file__).stem)
msg = gis_import_error_message.format(Path(__file__).stem)
raise ImportError(msg) from e

import ravenpy.utilities.io as io
Expand Down
8 changes: 3 additions & 5 deletions ravenpy/utilities/forecasting.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@
import xarray as xr
from climpred import HindcastEnsemble

from . import gis_import_error_message

try:
import rioxarray
from clisops.core import subset
except (ImportError, ModuleNotFoundError) as e:
msg = (
f"`{Path(__file__).stem}` requires installation of the RavenPy GIS libraries. These can be installed using the"
" `pip install ravenpy[gis]` recipe or via Anaconda (`conda env -n ravenpy-env -f environment.yml`)"
" from the RavenPy repository source files."
)
msg = gis_import_error_message.format(Path(__file__).stem)
raise ImportError(msg) from e

from ravenpy.models import get_model
Expand Down
4 changes: 2 additions & 2 deletions ravenpy/utilities/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pathlib import Path
from typing import List, Union

from . import gis_error_message
from . import gis_import_error_message

try:
import fiona
Expand All @@ -26,7 +26,7 @@
)
from shapely.ops import transform
except (ImportError, ModuleNotFoundError) as e:
msg = gis_error_message.format(Path(__file__).stem)
msg = gis_import_error_message.format(Path(__file__).stem)
raise ImportError(msg) from e

RASTERIO_TIFF_COMPRESSION = "lzw"
Expand Down
8 changes: 3 additions & 5 deletions ravenpy/utilities/geoserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

from requests import Request

from . import gis_import_error_message

try:
import fiona
import pandas as pd
Expand All @@ -24,11 +26,7 @@
from owslib.wfs import WebFeatureService
from shapely.geometry import Point, shape
except (ImportError, ModuleNotFoundError) as e:
msg = (
f"`{Path(__file__).stem}` requires installation of the RavenPy GIS libraries. These can be installed using the"
" `pip install ravenpy[gis]` recipe or via Anaconda (`conda env -n ravenpy-env -f environment.yml`)"
" from the RavenPy repository source files."
)
msg = gis_import_error_message.format(Path(__file__).stem)
raise ImportError(msg) from e

# Do not remove the trailing / otherwise `urljoin` will remove the geoserver path.
Expand Down
4 changes: 2 additions & 2 deletions ravenpy/utilities/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
from re import search
from typing import Iterable, List, Optional, Sequence, Union

from . import gis_error_message
from . import gis_import_error_message

try:
import fiona
import rasterio
from pyproj import CRS
from shapely.geometry import shape
except (ImportError, ModuleNotFoundError) as e:
msg = gis_error_message.format(Path(__file__).stem)
msg = gis_import_error_message.format(Path(__file__).stem)
raise ImportError(msg) from e

LOGGER = logging.getLogger("RavenPy")
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.2.3
current_version = 0.3.0
commit = False
tag = False

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def run(self):
gis=gis_requirements,
),
url="https://github.com/CSHS-CWRA/ravenpy",
version="0.2.3",
version="0.3.0",
zip_safe=False,
cmdclass={
"install": create_external_deps_install_class(install),
Expand Down
25 changes: 13 additions & 12 deletions tests/test_geo_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,18 @@ def test_gdal_slope_not_projected(self, tmp_path):
# Slope values are high due to data values using Geographic CRS
def test_dem_properties(self):
dem_properties = self.analysis.dem_prop(self.raster_file)
np.testing.assert_almost_equal(dem_properties["aspect"], 10.9119033)
np.testing.assert_almost_equal(dem_properties["elevation"], 79.0341721)
np.testing.assert_almost_equal(dem_properties["slope"], 64.4365427)
np.testing.assert_almost_equal(dem_properties["aspect"], 10.911, 3)
np.testing.assert_almost_equal(dem_properties["elevation"], 79.0341, 4)
np.testing.assert_almost_equal(dem_properties["slope"], 64.43654, 5)

with self.fiona.open(self.geojson_file) as gj:
feature = next(iter(gj))
geom = self.sgeo.shape(feature["geometry"])

region_dem_properties = self.analysis.dem_prop(self.raster_file, geom=geom)
np.testing.assert_almost_equal(region_dem_properties["aspect"], 280.6814208)
np.testing.assert_almost_equal(region_dem_properties["elevation"], 145.8899082)
np.testing.assert_almost_equal(region_dem_properties["slope"], 61.2650882)
np.testing.assert_almost_equal(region_dem_properties["aspect"], 280.681, 3)
np.testing.assert_almost_equal(region_dem_properties["elevation"], 145.8899, 4)
np.testing.assert_almost_equal(region_dem_properties["slope"], 61.26508, 5)

# Slope values are high due to data values using Geographic CRS
def test_geom_properties(self):
Expand Down Expand Up @@ -243,17 +243,18 @@ def test_raster_warp(self, tmp_path):
self.raster_file, output=reproj_file, target_crs="EPSG:3348"
)

# EPSG:3348 is a very general transformation; Some tolerance should be allowed.
with self.rasterio.open(reproj_file) as gt:
assert gt.crs.to_epsg() == 3348
np.testing.assert_almost_equal(gt.bounds.left, -2077535.25979486)
np.testing.assert_almost_equal(gt.bounds.right, 15591620.75098695)
np.testing.assert_almost_equal(gt.bounds.bottom, -4167898.76317739)
np.testing.assert_almost_equal(gt.bounds.top, 5817014.91999878)
np.testing.assert_allclose(gt.bounds.left, -2077535, atol=3)
np.testing.assert_allclose(gt.bounds.right, 15591620, atol=3)
np.testing.assert_allclose(gt.bounds.bottom, -4167898, atol=3)
np.testing.assert_allclose(gt.bounds.top, 5817014, atol=3)

data = gt.read(1) # read band 1 (red)
assert data.min() == 0
assert data.max() == 255
np.testing.assert_almost_equal(data.mean(), 60.7291936)
np.testing.assert_almost_equal(data.mean(), 60.729, 3)

def test_warped_raster_slope(self, tmp_path):
reproj_file = tempfile.NamedTemporaryFile(
Expand All @@ -278,7 +279,7 @@ def test_warped_raster_aspect(self, tmp_path):
aspect_grid = self.analysis.gdal_aspect_analysis(reproj_file)

np.testing.assert_almost_equal(
self.analysis.circular_mean_aspect(aspect_grid), 7.7805879
self.analysis.circular_mean_aspect(aspect_grid), 7.780, decimal=3
)

def test_raster_clip(self, tmp_path):
Expand Down

0 comments on commit 165bef2

Please sign in to comment.