Skip to content

Commit 809b30e

Browse files
authored
Better thickness distribution tasks (#465)
* Better thickness distribution tasks * Update defaults * Update sample-data commit * update tests * Update tolerance for graphics and fix windows test * Add what's new
1 parent 051d0aa commit 809b30e

10 files changed

+491
-144
lines changed

docs/whats-new.rst

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ Breaking changes
3535
By `Fabien Maussion <https://github.com/fmaussion>`_.
3636
- RGI version 4 isn't supported anymore (:issue:`142`).
3737
By `Fabien Maussion <https://github.com/fmaussion>`_.
38+
- Rework of the 2d interpolation tasks for ice thickness in the context of
39+
`ITMIX2 <http://oggm.org/2018/05/21/g2ti/>`_. The new interpolation
40+
are better, but not backwards compatible. Aside of me I don't think
41+
anybody was using them (:pull:`465`).
42+
By `Fabien Maussion <https://github.com/fmaussion>`_.
3843

3944
Enhancements
4045
~~~~~~~~~~~~

oggm/core/gis.py

+100-1
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,25 @@
1414
60(221), 537-552. http://doi.org/10.3189/2014JoG13J176
1515
"""
1616
# Built ins
17-
import os
1817
import logging
1918
import json
19+
import warnings
2020
from functools import partial
2121
from distutils.version import LooseVersion
2222
# External libs
23+
import netCDF4
2324
import salem
2425
import pyproj
2526
import numpy as np
2627
import shapely.ops
28+
import pandas as pd
2729
import geopandas as gpd
2830
import skimage.draw as skdraw
2931
import shapely.geometry as shpg
3032
import scipy.signal
3133
from scipy.ndimage.measurements import label
34+
from scipy.ndimage import binary_erosion
35+
from scipy.ndimage.morphology import distance_transform_edt
3236
from scipy.interpolate import griddata
3337
import rasterio
3438
from rasterio.warp import reproject, Resampling
@@ -742,3 +746,98 @@ def proj(x, y):
742746
nc.max_h_glacier = np.max(dem_on_g)
743747
nc.min_h_glacier = np.min(dem_on_g)
744748
nc.close()
749+
750+
751+
@entity_task(log, writes=['gridded_data'])
752+
def interpolation_masks(gdir):
753+
"""Computes the glacier exterior masks taking ice divides into account.
754+
755+
This is useful for distributed ice thickness. The masks are added to the
756+
gridded data file. For convenience we also add a slope mask.
757+
758+
Parameters
759+
----------
760+
gdir : :py:class:`oggm.GlacierDirectory`
761+
where to write the data
762+
"""
763+
764+
# Variables
765+
grids_file = gdir.get_filepath('gridded_data')
766+
with netCDF4.Dataset(grids_file) as nc:
767+
topo_smoothed = nc.variables['topo_smoothed'][:]
768+
glacier_mask = nc.variables['glacier_mask'][:]
769+
770+
# Glacier exterior including nunataks
771+
erode = binary_erosion(glacier_mask)
772+
glacier_ext = glacier_mask ^ erode
773+
glacier_ext = np.where(glacier_mask == 1, glacier_ext, 0)
774+
775+
# Intersects between glaciers
776+
gdfi = gpd.GeoDataFrame(columns=['geometry'])
777+
if gdir.has_file('intersects'):
778+
# read and transform to grid
779+
gdf = gpd.read_file(gdir.get_filepath('intersects'))
780+
salem.transform_geopandas(gdf, gdir.grid, inplace=True)
781+
gdfi = pd.concat([gdfi, gdf[['geometry']]])
782+
783+
# Ice divide mask
784+
# Probably not the fastest way to do this, but it works
785+
dist = np.array([])
786+
jj, ii = np.where(glacier_ext)
787+
for j, i in zip(jj, ii):
788+
dist = np.append(dist, np.min(gdfi.distance(shpg.Point(i, j))))
789+
790+
with warnings.catch_warnings():
791+
warnings.filterwarnings("ignore", category=RuntimeWarning)
792+
pok = np.where(dist <= 1)
793+
glacier_ext_intersect = glacier_ext * 0
794+
glacier_ext_intersect[jj[pok], ii[pok]] = 1
795+
796+
# Distance from border mask - Scipy does the job
797+
dx = gdir.grid.dx
798+
dis_from_border = 1 + glacier_ext_intersect - glacier_ext
799+
dis_from_border = distance_transform_edt(dis_from_border) * dx
800+
801+
# Slope
802+
sy, sx = np.gradient(topo_smoothed, dx, dx)
803+
slope = np.arctan(np.sqrt(sy**2 + sx**2))
804+
slope = np.clip(slope, np.deg2rad(cfg.PARAMS['min_slope']*4), np.pi/2.)
805+
slope = 1 / slope**(cfg.N / (cfg.N+2))
806+
807+
with netCDF4.Dataset(grids_file, 'a') as nc:
808+
809+
vn = 'glacier_ext_erosion'
810+
if vn in nc.variables:
811+
v = nc.variables[vn]
812+
else:
813+
v = nc.createVariable(vn, 'i1', ('y', 'x', ))
814+
v.units = '-'
815+
v.long_name = 'Glacier exterior with binary erosion method'
816+
v[:] = glacier_ext
817+
818+
vn = 'ice_divides'
819+
if vn in nc.variables:
820+
v = nc.variables[vn]
821+
else:
822+
v = nc.createVariable(vn, 'i1', ('y', 'x', ))
823+
v.units = '-'
824+
v.long_name = 'Glacier ice divides'
825+
v[:] = glacier_ext_intersect
826+
827+
vn = 'slope_factor'
828+
if vn in nc.variables:
829+
v = nc.variables[vn]
830+
else:
831+
v = nc.createVariable(vn, 'f4', ('y', 'x', ))
832+
v.units = '-'
833+
v.long_name = 'Slope factor as defined in Farinotti et al 2009'
834+
v[:] = slope
835+
836+
vn = 'dis_from_border'
837+
if vn in nc.variables:
838+
v = nc.variables[vn]
839+
else:
840+
v = nc.createVariable(vn, 'f4', ('y', 'x', ))
841+
v.units = 'm'
842+
v.long_name = 'Distance from border'
843+
v[:] = dis_from_border

0 commit comments

Comments
 (0)