diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
index 3874e8e32..b2a0c1458 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/run-tests.yml
@@ -24,7 +24,7 @@ jobs:
- workflow-multi
- graphics-mpl
container:
- - ghcr.io/oggm/untested_base:20211114
+ - ghcr.io/oggm/untested_base:20220320
- ghcr.io/oggm/untested_base:py3.7
- ghcr.io/oggm/untested_base:py3.9
include:
diff --git a/docs/api.rst b/docs/api.rst
index 7be1e17f0..675e7faeb 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -288,9 +288,9 @@ Users usually don't have to care about *where* the data is located.
fdem = gdir.get_filepath('dem')
fdem
- import xarray as xr
+ import rioxarray as rioxr
@savefig plot_gdir_dem.png width=80%
- xr.open_rasterio(fdem).plot(cmap='terrain');
+ rioxr.open_rasterio(fdem).plot(cmap='terrain');
This persistence on disk allows for example to continue a workflow that has
been previously interrupted. Initialising a GlacierDirectory from a non-empty
diff --git a/docs/cloud.rst b/docs/cloud.rst
index 8860d85a2..8c85133d0 100644
--- a/docs/cloud.rst
+++ b/docs/cloud.rst
@@ -18,6 +18,8 @@ link below to get you started!
.. image:: https://img.shields.io/badge/Launch-OGGM%20tutorials-579ACA.svg?style=popout&logo=data:image/png;base64,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
:target: https://mybinder.org/v2/gh/OGGM/binder/stable?urlpath=git-pull?repo=https://github.com/OGGM/tutorials%26amp%3Bbranch=master%26amp%3Burlpath=lab/tree/tutorials/notebooks/welcome.ipynb%3Fautodecode
+
+
If you are new to the Jupyter Notebooks or to JupyterLab, you will probably
find this `introduction to interactive notebooks`_ quite useful.
diff --git a/docs/installing-oggm.rst b/docs/installing-oggm.rst
index 833b1482e..4fa182aa8 100644
--- a/docs/installing-oggm.rst
+++ b/docs/installing-oggm.rst
@@ -64,6 +64,7 @@ GIS tools:
- shapely
- pyproj
- rasterio
+ - rioxarray
- geopandas
Testing:
@@ -113,7 +114,7 @@ window, type::
conda create --name oggm_env python=3.X
-where ``3.X`` is the Python version shipped with conda (currently 3.8).
+where ``3.X`` is the Python version shipped with conda (currently 3.9).
You can of course use any other name for your environment.
Don't forget to activate it before going on::
@@ -124,15 +125,20 @@ Don't forget to activate it before going on::
.. _environment: https://conda.io/projects/conda/en/latest/user-guide/concepts/environments.html
-Feeling adventurous? Try mamba (optional)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In a hurry? Try mamba (optional)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The conda package manager has recently been criticized for being slow (it *is*
-quite slow to be honest). A new, faster tool is now available to replace conda: `mamba `_.
-Mamba is a drop-in replacement for all conda commands.
-If you feel like it, install mamba in your conda environment (``conda install -c conda-forge mamba``)
+The conda package manager has been criticized for being slow (it *is*
+quite slow to be honest). A new, faster tool is now available
+to replace conda: `mamba `_. Mamba is a drop-in
+replacement for all conda commands. If you feel like it, install mamba in your conda
+environment (``conda install -c conda-forge mamba``)
and replace all occurrences of ``conda`` with ``mamba`` in the instructions below.
+*Note March 2022: soon, conda will use mamba per default. See
+`this post `_
+for more info.*
+
Install dependencies
~~~~~~~~~~~~~~~~~~~~
@@ -272,6 +278,11 @@ If everything worked fine, you should see something like::
You can safely ignore deprecation warnings and other messages (if any),
as long as the tests end without errors.
+.. important::
+
+ The tests (without the ``--run-slow`` option) should run in 5 to 10 minutes.
+ If this takes too long, this may be an indiv
+
This runs a minimal suite of tests. If you want to run the entire test suite
(including graphics and slow running tests), type::
@@ -303,7 +314,7 @@ environment from the following ``environment.yml`` file used to work::
channels:
- conda-forge
dependencies:
- - python=3.8
+ - python=3.9
- jupyter
- jupyterlab
- numpy
@@ -324,6 +335,7 @@ environment from the following ``environment.yml`` file used to work::
- cartopy
- geopandas
- rasterio
+ - rioxarray
- seaborn
- pytables
- salem
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 8115e0782..1ce8d6ed7 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -13,6 +13,7 @@ scikit-image
configobj
joblib
xarray
+rioxarray
progressbar2
pytest
tables
diff --git a/oggm/core/centerlines.py b/oggm/core/centerlines.py
index 0dd09b70c..4a3a6e0ab 100644
--- a/oggm/core/centerlines.py
+++ b/oggm/core/centerlines.py
@@ -19,7 +19,7 @@
import copy
from itertools import groupby
from collections import Counter
-from distutils.version import LooseVersion
+from packaging.version import Version
# External libs
import numpy as np
@@ -28,9 +28,8 @@
import scipy.signal
import shapely.geometry as shpg
from scipy.interpolate import RegularGridInterpolator
-from scipy.ndimage.filters import gaussian_filter1d
-from scipy.ndimage.morphology import distance_transform_edt
-from scipy.ndimage.measurements import label, find_objects
+from scipy.ndimage import (gaussian_filter1d, distance_transform_edt,
+ label, find_objects)
# Optional libs
try:
@@ -1326,7 +1325,10 @@ def _point_width(normals, point, centerline, poly, poly_no_nunataks):
# Make sure we are always returning a MultiLineString for later
line = line.intersection(poly)
if line.type == 'LineString':
- line = shpg.MultiLineString([line])
+ try:
+ line = shpg.MultiLineString([line])
+ except shapely.errors.EmptyPartError:
+ return np.NaN, shpg.MultiLineString()
elif line.type == 'MultiLineString':
pass # nothing to be done
elif line.type == 'GeometryCollection':
@@ -1605,7 +1607,7 @@ def catchment_intersections(gdir):
to_crs=gdir.grid.proj, inplace=True)
except TypeError:
# from_crs not available yet
- if LooseVersion(gpd.__version__) >= LooseVersion('0.7.0'):
+ if Version(gpd.__version__) >= Version('0.7.0'):
raise ImportError('You have installed geopandas v0.7 or higher. '
'Please also update salem for compatibility.')
gdfc.crs = gdir.grid
diff --git a/oggm/core/gis.py b/oggm/core/gis.py
index 59905b49b..8ef1f4048 100644
--- a/oggm/core/gis.py
+++ b/oggm/core/gis.py
@@ -6,7 +6,7 @@
import os
import logging
import warnings
-from distutils.version import LooseVersion
+from packaging.version import Version
from functools import partial
# External libs
@@ -16,9 +16,7 @@
import xarray as xr
import shapely.geometry as shpg
import scipy.signal
-from scipy.ndimage.measurements import label
-from scipy.ndimage import binary_erosion
-from scipy.ndimage.morphology import distance_transform_edt
+from scipy.ndimage import label, distance_transform_edt, binary_erosion
from scipy.interpolate import griddata
from scipy import optimize as optimization
@@ -358,7 +356,7 @@ def _get_nodata(rio_ds):
if len(dem_list) == 1:
dem_dss = [rasterio.open(dem_list[0])] # if one tile, just open it
dem_data = rasterio.band(dem_dss[0], 1)
- if LooseVersion(rasterio.__version__) >= LooseVersion('1.0'):
+ if Version(rasterio.__version__) >= Version('1.0'):
src_transform = dem_dss[0].transform
else:
src_transform = dem_dss[0].affine
diff --git a/oggm/shop/gcm_climate.py b/oggm/shop/gcm_climate.py
index 71cc8b265..e89c75240 100644
--- a/oggm/shop/gcm_climate.py
+++ b/oggm/shop/gcm_climate.py
@@ -1,7 +1,7 @@
"""Climate data pre-processing"""
# Built ins
import logging
-from distutils.version import LooseVersion
+from packaging.version import Version
import warnings
# External libs
@@ -209,7 +209,7 @@ def process_cesm_data(gdir, filesuffix='', fpath_temp=None, fpath_precc=None,
fpath_precl = cfg.PATHS['cesm_precl_file']
# read the files
- if LooseVersion(xr.__version__) < LooseVersion('0.11'):
+ if Version(xr.__version__) < Version('0.11'):
raise ImportError('This task needs xarray v0.11 or newer to run.')
tempds = xr.open_dataset(fpath_temp)
diff --git a/oggm/tests/__init__.py b/oggm/tests/__init__.py
index 69cf284e0..c0cdc7af0 100644
--- a/oggm/tests/__init__.py
+++ b/oggm/tests/__init__.py
@@ -1,5 +1,5 @@
import os
-from distutils.version import LooseVersion
+from packaging.version import Version
import pytest
import matplotlib.ft2font
@@ -12,7 +12,7 @@
# Matplotlib version changes plots, too
HAS_MPL_FOR_TESTS = False
-if LooseVersion(matplotlib.__version__) >= LooseVersion('2'):
+if Version(matplotlib.__version__) >= Version('2'):
HAS_MPL_FOR_TESTS = True
BASELINE_DIR = os.path.join(cfg.CACHE_DIR,
'oggm-sample-data-%s' % SAMPLE_DATA_COMMIT,
diff --git a/oggm/tests/test_prepro.py b/oggm/tests/test_prepro.py
index c33cae46b..799a6ffeb 100644
--- a/oggm/tests/test_prepro.py
+++ b/oggm/tests/test_prepro.py
@@ -1,7 +1,7 @@
import unittest
import os
import shutil
-from distutils.version import LooseVersion
+from packaging.version import Version
import pytest
import warnings
@@ -301,8 +301,8 @@ def test_glacier_masks(self):
with pytest.raises(RuntimeError):
gis.glacier_masks(gdir)
- @pytest.mark.skipif((LooseVersion(rasterio.__version__) <
- LooseVersion('1.0')),
+ @pytest.mark.skipif((Version(rasterio.__version__) <
+ Version('1.0')),
reason='requires rasterio >= 1.0')
def test_simple_glacier_masks(self):
@@ -357,8 +357,8 @@ def test_simple_glacier_masks(self):
assert dft.sum()[0] == 1000
assert utils.rmsd(dft['ref'], dft['oggm']) < 5
- @pytest.mark.skipif((LooseVersion(rasterio.__version__) <
- LooseVersion('1.0')),
+ @pytest.mark.skipif((Version(rasterio.__version__) <
+ Version('1.0')),
reason='requires rasterio >= 1.0')
def test_glacier_masks_other_glacier(self):
@@ -390,8 +390,8 @@ def test_glacier_masks_other_glacier(self):
np.testing.assert_allclose(dfh['Zmax'], entity.Zmax, atol=20)
np.testing.assert_allclose(dfh['Zmin'], entity.Zmin, atol=20)
- @pytest.mark.skipif((LooseVersion(rasterio.__version__) <
- LooseVersion('1.0')),
+ @pytest.mark.skipif((Version(rasterio.__version__) <
+ Version('1.0')),
reason='requires rasterio >= 1.0')
def test_rasterio_glacier_masks(self):
@@ -3086,7 +3086,7 @@ def test_find_calving_full_fl(self):
df = inversion.find_inversion_calving(gdir)
assert df['calving_flux'] > 2
- assert df['calving_rate_myr'] > 500
+ assert df['calving_rate_myr'] > 450
assert df['calving_mu_star'] == 0
# Test that new MB equal flux
diff --git a/oggm/tests/test_shop.py b/oggm/tests/test_shop.py
index 4a0f518bb..f86893dc5 100644
--- a/oggm/tests/test_shop.py
+++ b/oggm/tests/test_shop.py
@@ -7,6 +7,7 @@
import oggm
import xarray as xr
+import rioxarray as rioxr
import numpy as np
import pandas as pd
from oggm import utils
@@ -66,9 +67,9 @@ def test_repro_to_glacier(self, class_case_dir, monkeypatch):
gis.rasterio_to_gdir(gdir, region_files['ALA']['vy'], 'its_live_vy',
resampling='bilinear')
- with xr.open_rasterio(gdir.get_filepath('its_live_vx')) as da:
+ with rioxr.open_rasterio(gdir.get_filepath('its_live_vx')) as da:
_vx = da.where(mask).data.squeeze()
- with xr.open_rasterio(gdir.get_filepath('its_live_vy')) as da:
+ with rioxr.open_rasterio(gdir.get_filepath('its_live_vy')) as da:
_vy = da.where(mask).data.squeeze()
_vel = np.sqrt(_vx**2 + _vy**2)
@@ -552,7 +553,7 @@ def test_add_consensus(self, class_case_dir, monkeypatch):
with xr.open_dataset(gdir.get_filepath('gridded_data')) as ds:
mine = ds.consensus_ice_thickness
- with xr.open_rasterio(gdir.get_filepath('consensus')) as ds:
+ with rioxr.open_rasterio(gdir.get_filepath('consensus')) as ds:
ref = ds.isel(band=0)
# Check area
diff --git a/oggm/tests/test_utils.py b/oggm/tests/test_utils.py
index 77c6fdff5..8ee7a6550 100644
--- a/oggm/tests/test_utils.py
+++ b/oggm/tests/test_utils.py
@@ -1653,10 +1653,9 @@ def prepare_verify_test(self, valid_size=True, valid_crc32=True,
file_sha256 = file_sha256.digest()
data = utils.get_dl_verify_data('cluster.klima.uni-bremen.de')
- s = pd.Series({'size': file_size, 'sha256': file_sha256},
- name='test.txt')
- data = data.append(s)
- cfg.DATA['dl_verify_data_test.com'] = data
+ s = pd.DataFrame({'size': file_size, 'sha256': file_sha256},
+ index=['test.txt'])
+ cfg.DATA['dl_verify_data_test.com'] = pd.concat([data, s])
return 'https://test.com/test.txt'
diff --git a/oggm/utils/_funcs.py b/oggm/utils/_funcs.py
index 66869a4e5..1b33663b4 100644
--- a/oggm/utils/_funcs.py
+++ b/oggm/utils/_funcs.py
@@ -8,12 +8,12 @@
import logging
import warnings
import shutil
-from distutils.version import LooseVersion
+from packaging.version import Version
# External libs
import pandas as pd
import numpy as np
-from scipy.ndimage import filters
+from scipy.ndimage import convolve1d
try:
from scipy.signal.windows import gaussian
except AttributeError:
@@ -268,7 +268,7 @@ def smooth1d(array, window_size=None, kernel='gaussian'):
else:
raise NotImplementedError('Kernel: ' + kernel)
kernel = kernel / np.asarray(kernel).sum()
- return filters.convolve1d(array, kernel, mode='mirror')
+ return convolve1d(array, kernel, mode='mirror')
def line_interpol(line, dx):
@@ -375,7 +375,7 @@ def clip_scalar(value, vmin, vmax):
return vmin if value < vmin else vmax if value > vmax else value
-if LooseVersion(np.__version__) < LooseVersion('1.17'):
+if Version(np.__version__) < Version('1.17'):
clip_array = np.clip
else:
# TODO: reassess this when https://github.com/numpy/numpy/issues/14281
@@ -509,7 +509,7 @@ def polygon_intersections(gdf):
'{}.'.format(line.type))
line = gpd.GeoDataFrame([[i, j, line]],
columns=out_cols)
- out = out.append(line)
+ out = pd.concat([out, line])
return out