Source code for sasktran2.util.interpolation
from __future__ import annotations
import numpy as np
[docs]
def linear_interpolating_matrix(
from_grid: np.array, to_grid: np.array, out_of_bounds_mode: str
) -> np.ndarray:
"""
Constructs an interpolating matrix that can be used to interpolate from one grid to another.
Parameters
----------
from_grid : np.array
Grid with the original values. Must be sorted in ascending order
to_grid : np.array
Grid we are going to interpolate to. Must be sorted in ascending order
out_of_bounds_mode : str
One of ["zero", "extend"], "zero" will set the result to 0 outside the bounds of the original grid,
"extend" will extend the lowest and highest values
Returns
-------
np.ndarray
A matrix such that M @ (values on from_grid) = (values on to_grid)
"""
M = np.zeros((len(to_grid), len(from_grid)))
for idx, ele in enumerate(to_grid):
if ele < from_grid[0] or ele > from_grid[-1]:
if out_of_bounds_mode == "zero":
continue
if out_of_bounds_mode == "extend":
if ele < from_grid[0]:
M[idx, 0] = 1
else:
M[idx, -1] = 1
continue
msg = f"Invalid out_of_bounds_mode {out_of_bounds_mode}"
raise ValueError(msg)
# else we are inside the grid
idx_above = np.nonzero(from_grid > ele)[0]
idx_above = len(from_grid) if len(idx_above) == 0 else idx_above[0]
interp_ele = ele
if idx_above == 0:
idx_above = 1
interp_ele = from_grid[0]
if idx_above == len(from_grid):
M[idx, idx_above - 1] = 1
else:
w = (from_grid[idx_above] - interp_ele) / (
from_grid[idx_above] - from_grid[idx_above - 1]
)
M[idx, idx_above] = 1 - w
M[idx, idx_above - 1] = w
return M