Exemplo n.º 1
0
def interpolate2d(x, y, z, points, mode='linear', bounds_error=False):
    """Fundamental 2D interpolation routine

    :param x: 1D array of x-coordinates of the mesh on which to interpolate
    :type x: numpy.ndarray

    :param y: 1D array of y-coordinates of the mesh on which to interpolate
    :type y: numpy.ndarray

    :param z: 2D array of values for each x, y pair
    :type z: numpy.ndarry

    :param points: Nx2 array of coordinates where interpolated values are
        sought
    :type points: numpy.narray

    :param mode: Determines the interpolation order.
        Options are:

            * 'constant' - piecewise constant nearest neighbour interpolation
            * 'linear' - bilinear interpolation using the four
              nearest neighbours (default)

    :type mode: str

    :param bounds_error: If True (default) a BoundsError exception
          will be raised when interpolated values are requested
          outside the domain of the input data. If False, nan
          is returned for those values
    :type bounds_error: bool

    :returns: 1D array with same length as points with interpolated values

    :raises: Exception, BoundsError (see note about bounds_error)

    ..notes::
        Input coordinates x and y are assumed to be monotonically increasing,
        but need not be equidistantly spaced. No such assumption regarding
        ordering of points is made.

        z is assumed to have dimension M x N, where M = len(x) and N = len(y).
        In other words it is assumed that the x values follow the first
        (vertical) axis downwards and y values the second (horizontal) axis
        from left to right.

        If this routine is to be used for interpolation of raster grids where
        data is typically organised with longitudes (x) going from left to
        right and latitudes (y) from left to right then user
        interpolate_raster in this module
    """

    # Input checks
    validate_mode(mode)
    x, y, z, xi, eta = validate_inputs(
        x=x, y=y, z=z, points=points, bounds_error=bounds_error)

    # Identify elements that are outside interpolation domain or NaN
    outside = (xi < x[0]) + (eta < y[0]) + (xi > x[-1]) + (eta > y[-1])
    outside += numpy.isnan(xi) + numpy.isnan(eta)

    inside = -outside
    xi = xi[inside]
    eta = eta[inside]

    # Find upper neighbours for each interpolation point
    idx = numpy.searchsorted(x, xi, side='left')
    idy = numpy.searchsorted(y, eta, side='left')

    # Internal check (index == 0 is OK)
    if len(idx) > 0 or len(idy) > 0:
        if (max(idx) >= len(x)) or (max(idy) >= len(y)):
            msg = (
                'Interpolation point outside domain. '
                'This should never happen. '
                'Please email [email protected]')
            raise InaSAFEError(msg)

    # Get the four neighbours for each interpolation point
    x0 = x[idx - 1]
    x1 = x[idx]
    y0 = y[idy - 1]
    y1 = y[idy]

    z00 = z[idx - 1, idy - 1]
    z01 = z[idx - 1, idy]
    z10 = z[idx, idy - 1]
    z11 = z[idx, idy]

    # Coefficients for weighting between lower and upper bounds
    old_set = numpy.seterr(invalid='ignore')  # Suppress warnings
    alpha = (xi - x0) / (x1 - x0)
    beta = (eta - y0) / (y1 - y0)
    numpy.seterr(**old_set)  # Restore

    if mode == 'linear':
        # Bilinear interpolation formula
        dx = z10 - z00
        dy = z01 - z00
        z = z00 + alpha * dx + beta * dy + alpha * beta * (z11 - dx - dy - z00)
    else:
        # Piecewise constant (as verified in input_check)

        # Set up masks for the quadrants
        left = alpha < 0.5
        right = -left
        lower = beta < 0.5
        upper = -lower

        lower_left = lower * left
        lower_right = lower * right
        upper_left = upper * left

        # Initialise result array with all elements set to upper right
        z = z11

        # Then set the other quadrants
        z[lower_left] = z00[lower_left]
        z[lower_right] = z10[lower_right]
        z[upper_left] = z01[upper_left]

    # Self test
    if len(z) > 0:
        mz = numpy.nanmax(z)
        mZ = numpy.nanmax(z)
        # noinspection PyStringFormat
        msg = ('Internal check failed. Max interpolated value %.15f '
               'exceeds max grid value %.15f ' % (mz, mZ))
        if not(numpy.isnan(mz) or numpy.isnan(mZ)):
            if not mz <= mZ:
                raise InaSAFEError(msg)

    # Populate result with interpolated values for points inside domain
    # and NaN for values outside
    r = numpy.zeros(len(points))
    r[inside] = z
    r[outside] = numpy.nan

    return r
Exemplo n.º 2
0
def interpolate2d(x, y, z, points, mode='linear', bounds_error=False):
    """Fundamental 2D interpolation routine

    :param x: 1D array of x-coordinates of the mesh on which to interpolate
    :type x: numpy.ndarray

    :param y: 1D array of y-coordinates of the mesh on which to interpolate
    :type y: numpy.ndarray

    :param z: 2D array of values for each x, y pair
    :type z: numpy.ndarry

    :param points: Nx2 array of coordinates where interpolated values are
        sought
    :type points: numpy.narray

    :param mode: Determines the interpolation order.
        Options are:

            * 'constant' - piecewise constant nearest neighbour interpolation
            * 'linear' - bilinear interpolation using the four
              nearest neighbours (default)

    :type mode: str

    :param bounds_error: If True (default) a BoundsError exception
          will be raised when interpolated values are requested
          outside the domain of the input data. If False, nan
          is returned for those values
    :type bounds_error: bool

    :returns: 1D array with same length as points with interpolated values

    :raises: Exception, BoundsError (see note about bounds_error)

    ..notes::
        Input coordinates x and y are assumed to be monotonically increasing,
        but need not be equidistantly spaced. No such assumption regarding
        ordering of points is made.

        z is assumed to have dimension M x N, where M = len(x) and N = len(y).
        In other words it is assumed that the x values follow the first
        (vertical) axis downwards and y values the second (horizontal) axis
        from left to right.

        If this routine is to be used for interpolation of raster grids where
        data is typically organised with longitudes (x) going from left to
        right and latitudes (y) from left to right then user
        interpolate_raster in this module
    """

    # Input checks
    validate_mode(mode)
    x, y, z, xi, eta = validate_inputs(
        x=x, y=y, z=z, points=points, bounds_error=bounds_error)

    # Identify elements that are outside interpolation domain or NaN
    outside = (xi < x[0]) + (eta < y[0]) + (xi > x[-1]) + (eta > y[-1])
    outside += numpy.isnan(xi) + numpy.isnan(eta)

    inside = -outside
    xi = xi[inside]
    eta = eta[inside]

    # Find upper neighbours for each interpolation point
    idx = numpy.searchsorted(x, xi, side='left')
    idy = numpy.searchsorted(y, eta, side='left')

    # Internal check (index == 0 is OK)
    if len(idx) > 0 or len(idy) > 0:
        if (max(idx) >= len(x)) or (max(idy) >= len(y)):
            msg = (
                'Interpolation point outside domain. '
                'This should never happen. '
                'Please email [email protected]')
            raise InaSAFEError(msg)

    # Get the four neighbours for each interpolation point
    x0 = x[idx - 1]
    x1 = x[idx]
    y0 = y[idy - 1]
    y1 = y[idy]

    z00 = z[idx - 1, idy - 1]
    z01 = z[idx - 1, idy]
    z10 = z[idx, idy - 1]
    z11 = z[idx, idy]

    # Coefficients for weighting between lower and upper bounds
    old_set = numpy.seterr(invalid='ignore')  # Suppress warnings
    alpha = (xi - x0) / (x1 - x0)
    beta = (eta - y0) / (y1 - y0)
    numpy.seterr(**old_set)  # Restore

    if mode == 'linear':
        # Bilinear interpolation formula
        dx = z10 - z00
        dy = z01 - z00
        z = z00 + alpha * dx + beta * dy + alpha * beta * (z11 - dx - dy - z00)
    else:
        # Piecewise constant (as verified in input_check)

        # Set up masks for the quadrants
        left = alpha < 0.5
        right = -left
        lower = beta < 0.5
        upper = -lower

        lower_left = lower * left
        lower_right = lower * right
        upper_left = upper * left

        # Initialise result array with all elements set to upper right
        z = z11

        # Then set the other quadrants
        z[lower_left] = z00[lower_left]
        z[lower_right] = z10[lower_right]
        z[upper_left] = z01[upper_left]

    # Self test
    if len(z) > 0:
        mz = numpy.nanmax(z)
        mZ = numpy.nanmax(z)
        # noinspection PyStringFormat
        msg = ('Internal check failed. Max interpolated value %.15f '
               'exceeds max grid value %.15f ' % (mz, mZ))
        if not(numpy.isnan(mz) or numpy.isnan(mZ)):
            if not mz <= mZ:
                raise InaSAFEError(msg)

    # Populate result with interpolated values for points inside domain
    # and NaN for values outside
    r = numpy.zeros(len(points))
    r[inside] = z
    r[outside] = numpy.nan

    return r
Exemplo n.º 3
0
def interpolate1d(x, z, points, mode='linear', bounds_error=False):
    """Fundamental 1D interpolation routine.

    :param x: 1D array of x-coordinates on which to interpolate
    :type x: numpy.ndarray

    :param z: 1D array of values for each x
    :type z: numpy.ndarray

    :param points: 1D array of coordinates where interpolated values are sought
    :type points: numpy.ndarray

    :param mode: Determines the interpolation order.
        Options are:

            * 'constant' - piecewise constant nearest neighbour interpolation
            * 'linear' - bilinear interpolation using the two nearest \
              neighbours (default)

    :type mode: str

    :param bounds_error: Flag to indicate whether an exception will be raised
        when interpolated values are requested outside the domain of the
        input data. If False, nan is returned for those values.
    :type bounds_error: bool

    :returns: 1D array with same length as points with interpolated values
    :rtype: numpy.ndarry

    :raises: RuntimeError

    ..note::
        Input coordinates x are assumed to be monotonically increasing,
        but need not be equidistantly spaced.

        z is assumed to have dimension M where M = len(x).
    """

    # Input checks
    validate_mode(mode)
    #pylint: disable=W0632
    x, z, xi = validate_inputs(x=x,
                               z=z,
                               points=points,
                               bounds_error=bounds_error)
    #pylint: enable=W0632

    # Identify elements that are outside interpolation domain or NaN
    outside = (xi < x[0]) + (xi > x[-1])
    outside += numpy.isnan(xi)

    inside = -outside
    xi = xi[inside]

    # Find upper neighbours for each interpolation point
    idx = numpy.searchsorted(x, xi, side='left')

    # Internal check (index == 0 is OK)
    msg = ('Interpolation point outside domain. This should never happen. '
           'Please email [email protected]')
    if len(idx) > 0:
        if not max(idx) < len(x):
            raise RuntimeError(msg)

    # Get the two neighbours for each interpolation point
    x0 = x[idx - 1]
    x1 = x[idx]

    z0 = z[idx - 1]
    z1 = z[idx]

    # Coefficient for weighting between lower and upper bounds
    alpha = (xi - x0) / (x1 - x0)

    if mode == 'linear':
        # Bilinear interpolation formula
        dx = z1 - z0
        zeta = z0 + alpha * dx
    else:
        # Piecewise constant (as verified in input_check)

        # Set up masks for the quadrants
        left = alpha < 0.5

        # Initialise result array with all elements set to right neighbour
        zeta = z1

        # Then set the left neigbours
        zeta[left] = z0[left]

    # Self test
    if len(zeta) > 0:
        mzeta = numpy.nanmax(zeta)
        mz = numpy.nanmax(z)
        # noinspection PyStringFormat
        msg = ('Internal check failed. Max interpolated value %.15f '
               'exceeds max grid value %.15f ' % (mzeta, mz))
        if not (numpy.isnan(mzeta) or numpy.isnan(mz)):
            if not mzeta <= mz:
                raise RuntimeError(msg)

    # Populate result with interpolated values for points inside domain
    # and NaN for values outside
    r = numpy.zeros(len(points))
    r[inside] = zeta
    r[outside] = numpy.nan

    return r
Exemplo n.º 4
0
def interpolate1d(x, z, points, mode='linear', bounds_error=False):
    """Fundamental 1D interpolation routine.

    :param x: 1D array of x-coordinates on which to interpolate
    :type x: numpy.ndarray

    :param z: 1D array of values for each x
    :type z: numpy.ndarray

    :param points: 1D array of coordinates where interpolated values are sought
    :type points: numpy.ndarray

    :param mode: Determines the interpolation order.
        Options are:

            * 'constant' - piecewise constant nearest neighbour interpolation
            * 'linear' - bilinear interpolation using the two nearest \
              neighbours (default)

    :type mode: str

    :param bounds_error: Flag to indicate whether an exception will be raised
        when interpolated values are requested outside the domain of the
        input data. If False, nan is returned for those values.
    :type bounds_error: bool

    :returns: 1D array with same length as points with interpolated values
    :rtype: numpy.ndarry

    :raises: RuntimeError

    ..note::
        Input coordinates x are assumed to be monotonically increasing,
        but need not be equidistantly spaced.

        z is assumed to have dimension M where M = len(x).
    """

    # Input checks
    validate_mode(mode)
    x, z, xi = validate_inputs(
        x=x, z=z, points=points, bounds_error=bounds_error)

    # Identify elements that are outside interpolation domain or NaN
    outside = (xi < x[0]) + (xi > x[-1])
    outside += numpy.isnan(xi)

    inside = -outside
    xi = xi[inside]

    # Find upper neighbours for each interpolation point
    idx = numpy.searchsorted(x, xi, side='left')

    # Internal check (index == 0 is OK)
    msg = ('Interpolation point outside domain. This should never happen. '
           'Please email [email protected]')
    if len(idx) > 0:
        if not max(idx) < len(x):
            raise RuntimeError(msg)

    # Get the two neighbours for each interpolation point
    x0 = x[idx - 1]
    x1 = x[idx]

    z0 = z[idx - 1]
    z1 = z[idx]

    # Coefficient for weighting between lower and upper bounds
    alpha = (xi - x0) / (x1 - x0)

    if mode == 'linear':
        # Bilinear interpolation formula
        dx = z1 - z0
        zeta = z0 + alpha * dx
    else:
        # Piecewise constant (as verified in input_check)

        # Set up masks for the quadrants
        left = alpha < 0.5

        # Initialise result array with all elements set to right neighbour
        zeta = z1

        # Then set the left neigbours
        zeta[left] = z0[left]

    # Self test
    if len(zeta) > 0:
        mzeta = numpy.nanmax(zeta)
        mz = numpy.nanmax(z)
        # noinspection PyStringFormat
        msg = ('Internal check failed. Max interpolated value %.15f '
               'exceeds max grid value %.15f ' % (mzeta, mz))
        if not(numpy.isnan(mzeta) or numpy.isnan(mz)):
            if not mzeta <= mz:
                raise RuntimeError(msg)

    # Populate result with interpolated values for points inside domain
    # and NaN for values outside
    r = numpy.zeros(len(points))
    r[inside] = zeta
    r[outside] = numpy.nan

    return r