Source code for verde.scipygridder

# Copyright (c) 2017 The Verde Developers.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
#
# This code is part of the Fatiando a Terra project (https://www.fatiando.org)
#
"""
Gridders that use scipy.interpolate as the backend.
"""
from abc import abstractmethod
from warnings import warn

import numpy as np
from scipy.interpolate import (
    CloughTocher2DInterpolator,
    LinearNDInterpolator,
    NearestNDInterpolator,
)
from sklearn.utils.validation import check_is_fitted

from .base import BaseGridder, check_fit_input
from .coordinates import get_region


class _BaseScipyGridder(BaseGridder):
    """
    A scipy.interpolate base gridder for scalar Cartesian data.

    Used as a base class for each of the SciPy ND based interpolators.

    Attributes
    ----------
    interpolator_ : scipy interpolator class
        An instance of the corresponding scipy interpolator class.
    region_ : tuple
        The boundaries (``[W, E, S, N]``) of the data used to fit the
        interpolator. Used as the default region for the
        :meth:`~verde.ScipyGridder.grid` and
        :meth:`~verde.ScipyGridder.scatter` methods.

    """

    @abstractmethod
    def _get_interpolator(self):
        """
        Return the SciPy interpolator class and any extra keyword arguments as
        a dictionary.
        """

    def fit(self, coordinates, data, weights=None):
        """
        Fit the interpolator to the given data.

        The data region is captured and used as default for the
        :meth:`~verde._BaseScipyGridder.grid` method.

        Parameters
        ----------
        coordinates : tuple of arrays
            Arrays with the coordinates of each data point. Should be in the
            following order: (easting, northing, vertical, ...). Only easting
            and northing will be used, all subsequent coordinates will be
            ignored.
        data : array
            The data values that will be interpolated.
        weights : None or array
            Data weights are **not supported** by this interpolator and will be
            ignored. Only present for compatibility with other gridder.

        Returns
        -------
        self
            Returns this gridder instance for chaining operations.

        """
        if weights is not None:
            warn(
                "{} does not support weights and they will be ignored.".format(
                    self.__class__.__name__
                )
            )
        coordinates, data, weights = check_fit_input(coordinates, data, weights)
        easting, northing = coordinates[:2]
        self.region_ = get_region((easting, northing))
        points = np.column_stack((np.ravel(easting), np.ravel(northing)))
        interpolator_class, kwargs = self._get_interpolator()
        self.interpolator_ = interpolator_class(points, np.ravel(data), **kwargs)
        return self

    def predict(self, coordinates):
        """
        Interpolate data on the given set of points.

        Requires a fitted gridder (see :meth:`~verde._BaseScipyGridder.fit`).

        Parameters
        ----------
        coordinates : tuple of arrays
            Arrays with the coordinates of each data point. Should be in the
            following order: (easting, northing, vertical, ...). Only easting
            and northing will be used, all subsequent coordinates will be
            ignored.

        Returns
        -------
        data : array
            The data values interpolated on the given points.

        """
        check_is_fitted(self, ["interpolator_"])
        easting, northing = coordinates[:2]
        return self.interpolator_((easting, northing))


[docs]class Linear(_BaseScipyGridder): """ Piecewise linear interpolation. Provides a Verde interface to :class:`scipy.interpolate.LinearNDInterpolator`. Parameters ---------- rescale : bool If ``True``, rescale the data coordinates to [0, 1] range before interpolation. Useful when coordinates vary greatly in scale. Default is ``False``. Attributes ---------- interpolator_ : scipy interpolator class An instance of the corresponding scipy interpolator class. region_ : tuple The boundaries (``[W, E, S, N]``) of the data used to fit the interpolator. Used as the default region for the :meth:`~verde.Linear.grid` method. """ def __init__(self, rescale=False): super().__init__() self.rescale = rescale def _get_interpolator(self): """ Return the SciPy interpolator class and any extra keyword arguments as a dictionary. """ return LinearNDInterpolator, {"rescale": self.rescale}
[docs]class Cubic(_BaseScipyGridder): """ Piecewise cubic interpolation. Provides a Verde interface to :class:`scipy.interpolate.CloughTocher2DInterpolator`. Parameters ---------- rescale : bool If ``True``, rescale the data coordinates to [0, 1] range before interpolation. Useful when coordinates vary greatly in scale. Default is ``False``. Attributes ---------- interpolator_ : scipy interpolator class An instance of the corresponding scipy interpolator class. region_ : tuple The boundaries (``[W, E, S, N]``) of the data used to fit the interpolator. Used as the default region for the :meth:`~verde.Cubic.grid` method. """ def __init__(self, rescale=False): super().__init__() self.rescale = rescale def _get_interpolator(self): """ Return the SciPy interpolator class and any extra keyword arguments as a dictionary. """ return CloughTocher2DInterpolator, {"rescale": self.rescale}
[docs]class ScipyGridder(_BaseScipyGridder): """ A scipy.interpolate based gridder for scalar Cartesian data. .. warning:: The ``ScipyGridder`` class is **deprecated** and will be **removed in Verde v2.0.0**. Use :class:`~verde.KNeighbors`, :class:`~verde.Linear`, and :class:`~verde.Cubic` instead. Provides a verde gridder interface to the scipy interpolators :class:`scipy.interpolate.LinearNDInterpolator`, :class:`scipy.interpolate.NearestNDInterpolator`, and :class:`scipy.interpolate.CloughTocher2DInterpolator` (cubic). Parameters ---------- method : str The interpolation method. Either ``'linear'``, ``'nearest'``, or ``'cubic'``. extra_args : None or dict Extra keyword arguments to pass to the scipy interpolator class. See the documentation for each interpolator for a list of possible arguments. Attributes ---------- interpolator_ : scipy interpolator class An instance of the corresponding scipy interpolator class. region_ : tuple The boundaries (``[W, E, S, N]``) of the data used to fit the interpolator. Used as the default region for the :meth:`~verde.ScipyGridder.grid` and :meth:`~verde.ScipyGridder.scatter` methods. """ def __init__(self, method="cubic", extra_args=None): super().__init__() self.method = method self.extra_args = extra_args warn( "verde.ScipyGridder is deprecated and will be removed in Verde " "v2.0.0. Use the KNeighbors, Linear, and Cubic classes instead.", FutureWarning, ) def _get_interpolator(self): """ Return the SciPy interpolator class and any extra keyword arguments as a dictionary. """ classes = dict( linear=LinearNDInterpolator, nearest=NearestNDInterpolator, cubic=CloughTocher2DInterpolator, ) if self.method not in classes: raise ValueError( "Invalid interpolation method '{}'. Must be one of {}.".format( self.method, str(classes.keys()) ) ) if self.extra_args is None: kwargs = {} else: kwargs = self.extra_args return classes[self.method], kwargs