Source code for verde.base.utils

"""
Utility functions for building gridders and checking arguments.
"""
import numpy as np


def check_data(data):
    """
    Check the *data* argument and make sure it's a tuple.
    If the data is a single array, return it as a tuple with a single element.

    This is the default format accepted and used by all gridders and processing
    functions.

    Examples
    --------

    >>> check_data([1, 2, 3])
    ([1, 2, 3],)
    >>> check_data(([1, 2], [3, 4]))
    ([1, 2], [3, 4])
    """
    if not isinstance(data, tuple):
        data = (data,)
    return data


def check_coordinates(coordinates):
    """
    Check that the given coordinate arrays are what we expect them to be.
    Should be a tuple with arrays of the same shape.
    """
    shapes = [coord.shape for coord in coordinates]
    if not all(shape == shapes[0] for shape in shapes):
        raise ValueError(
            "Coordinate arrays must have the same shape. Coordinate shapes: {}".format(
                shapes
            )
        )
    return coordinates


[docs]def check_fit_input(coordinates, data, weights, unpack=True): """ Validate the inputs to the fit method of gridders. Checks that the coordinates, data, and weights (if given) all have the same shape. Weights arrays are raveled. Parameters ---------- coordinates : tuple of arrays Arrays with the coordinates of each data point. Should be in the following order: (easting, northing, vertical, ...). data : array or tuple of arrays The data values of each data point. Data can have more than one component. In such cases, data should be a tuple of arrays. weights : None or array If not None, then the weights assigned to each data point. Typically, this should be 1 over the data uncertainty squared. If the data has multiple components, the weights have the same number of components. unpack : bool If False, data and weights will be tuples always. If they are single arrays, then they will be returned as a 1-element tuple. If True, will unpack the tuples if there is only 1 array in each. Returns ------- validated_inputs The validated inputs in the same order. If weights are given, will ravel the array before returning. """ data = check_data(data) weights = check_data(weights) coordinates = check_coordinates(coordinates) if any(i.shape != coordinates[0].shape for i in data): raise ValueError( "Data arrays must have the same shape {} as coordinates. Data shapes: {}.".format( coordinates[0].shape, [i.shape for i in data] ) ) if any(w is not None for w in weights): if len(weights) != len(data): raise ValueError( "Number of data '{}' and weights '{}' must be equal.".format( len(data), len(weights) ) ) if any(i.size != j.size for i in weights for j in data): raise ValueError("Weights must have the same size as the data array.") weights = tuple(i.ravel() for i in weights) else: weights = tuple([None] * len(data)) if unpack: if len(weights) == 1: weights = weights[0] if len(data) == 1: data = data[0] return coordinates, data, weights
[docs]def n_1d_arrays(arrays, n): """ Get the first n elements from a tuple/list, convert to arrays, and ravel. Use this function to make sure that coordinate and data arrays are ready for building Jacobian matrices and least-squares fitting. Parameters ---------- arrays : tuple of arrays The arrays. Can be lists or anything that can be converted to a numpy array (including numpy arrays). n : int How many arrays to return. Returns ------- 1darrays : tuple of arrays The converted 1D numpy arrays. Examples -------- >>> import numpy as np >>> arrays = [np.arange(4).reshape(2, 2)]*3 >>> n_1d_arrays(arrays, n=2) (array([0, 1, 2, 3]), array([0, 1, 2, 3])) """ return tuple(np.atleast_1d(i).ravel() for i in arrays[:n])