Spatial interpolation#

Grid interpolation#

For enhanced visuals, hyoga supports interpolating and remasking model output onto a different (usually higher-resolution) topography. This produces an image which deviates somewhat from the model results, but with detail potentially improving readability.

A necessary first step in many cases is to compute the bedrock deformation due to isostatic adjustment. If the dataset was produced by a model including bedrock deformation, there will be a systematic offset between the model bedrock topography and the new topography onto which data are interpolated.

Warning

Assigning isostasy is not strictly necessary for interpolation to succeed, but omitting it would produce errors in the new ice mask. Of course, it can be safely omitted if the model run does not include isostasy.

In this case, we compute the bedrock deformation by comparing bedrock altitude in the dataset with bedrock altitude in the initial state:

ds = hyoga.open.example('pism.alps.out.2d.nc')
ds = ds.hyoga.assign_isostasy(hyoga.open.example('pism.alps.in.boot.nc'))

The method assign_isostasy() assigns a new variable (standard name bedrock_altitude_change_due_to_isostatic_adjustment). Next we run interp() which interpolates all variables, and recalculates an ice mask based on the new topographies, corrected for bedrock depression in this case. This uses yet another demo file, which contains high-resolution topographic data over a small part of the model domain.

ds = ds.hyoga.interp(hyoga.open.example('pism.alps.vis.refined.nc'))

The new dataset can be plotted in the same way as any other hyoga dataset, only with a much higher resolution.

ds.hyoga.plot.bedrock_altitude(center=False)
ds.hyoga.plot.surface_velocity(vmin=1e1, vmax=1e3)
ds.hyoga.plot.surface_altitude_contours()
ds.hyoga.plot.ice_margin(edgecolor='0.25')
ds.hyoga.plot.scale_bar()
../_images/refining-3.png

Profile interpolation#

Profile interpolation aggregates variables with two horizontal dimensions (and possibly more dimensions) along a profile curve (or surface) defined by a sequence of (x, y) points. Let us draw a linear cross-section across the example dataset and plot this line on a map.

# prepare a linear profile
import numpy as np
x = np.linspace(250e3, 450e3, 21)
y = np.linspace(5200e3, 5000e3, 21)
points = list(zip(x, y))

# plot profile line on a map
ds = hyoga.open.example('pism.alps.out.2d.nc')
ds.hyoga.plot.bedrock_altitude(center=False)
ds.hyoga.plot.ice_margin(facecolor='tab:blue')
plt.plot(x, y, color='tab:red', marker='x')
../_images/refining-4.png

The accessor method profile() can be used to linearly interpolate the gridded dataset onto these coordinates, producing a new dataset where the x and y coordinates are swapped for a new coordinate d, for the distance along the profile.

profile = ds.hyoga.profile(points)
profile.hyoga.getvar('bedrock_altitude').plot(color='0.25')
profile.hyoga.getvar('surface_altitude').plot(color='C0')
../_images/refining-5.png

An additional interval keyword can be passed to control the horizontal resolution of the new profile dataset. This is particularly useful if the sequence of points is not regularly spaced.

# prepare three subplots
fig, axes = plt.subplots(nrows=3, sharex=True, sharey=True)

# 10, 3, and 1 km resolutions
for ax, interval in zip(axes, [10e3, 3e3, 1e3]):
    profile = ds.hyoga.profile(points, interval=interval)
    profile.hyoga.getvar('bedrock_altitude').plot(ax=ax, color='0.25')
    profile.hyoga.getvar('surface_altitude').plot(ax=ax, color='C0')

# remove duplicate labels
for ax in axes[:2]:
    ax.set_xlabel('')
for ax in axes[::2]:
    ax.set_ylabel('')
../_images/refining-6.png

The sequence of points in the above example does not have to form a straight line. Besides, it can also be provided as a numpy.ndarray, a geopandas.GeoDataFrame, or a path to a vector file containing a single, linestring geometry. Here is a more advanced example using a custom shapefile provided in the example data.

#!/usr/bin/env python
# Copyright (c) 2022, Julien Seguinot (juseg.github.io)
# GNU General Public License v3.0+ (https://www.gnu.org/licenses/gpl-3.0.txt)

"""
Profile interpolation
=====================

Demonstrate interpolating two-dimensional model output onto a one-dimensional
profile defined by x and y coordinates inside a shapefile.
"""

import matplotlib.pyplot as plt
import hyoga

# initialize figure
fig, (ax, pfax) = plt.subplots(ncols=2, gridspec_kw=dict(width_ratios=(1, 2)))

# open demo data
with hyoga.open.example('pism.alps.out.2d.nc') as ds:

    # plot 2D model output
    ds.hyoga.plot.bedrock_altitude(ax=ax, center=False)
    ds.hyoga.plot.ice_margin(ax=ax, edgecolor='tab:blue', linewidths=1)
    ds.hyoga.plot.ice_margin(ax=ax, facecolor='tab:blue')

    # interpolate along profile
    ds = ds.hyoga.profile(hyoga.open.example('profile.rhine.shp'))

    # plot profile line in map view
    ax.plot(ds.x, ds.y, color='w', dashes=(2, 1))
    ax.plot(ds.x[0], ds.y[0], 'wo')

    # plot bedrock and surface profiles
    ds.hyoga.getvar('bedrock_altitude').plot(ax=pfax, color='0.25')
    ds.hyoga.getvar('surface_altitude').plot(ax=pfax, color='tab:blue')

# set map axes properties
ax.set_xlim(425e3, 575e3)
ax.set_ylim(5000e3, 5400e3)
ax.set_title('map view')

# set profile axes properties
pfax.set_title('profile view')
pfax.yaxis.set_label_position("right")
pfax.yaxis.tick_right()

# show
plt.show()
../_images/plot_profile_altitudes.png