Esempio n. 1
0
    def execute(self, gridx, gridy):
        """Calculates a kriged grid and the associated variance.

        Inputs:
            gridx (array-like, dim Nx1): X-coordinates of NxM grid.
            gridy (array-like, dim Mx1): Y-coordinates of NxM grid.
        Outputs:
            gridz (numpy array, dim NxM): Z-values of grid.
            sigmasq (numpy array, dim NxM): Variance at grid points.
        """

        if self.verbose:
            print "Executing Ordinary Kriging...\n"

        gridx = np.array(gridx).flatten()
        gridy = np.array(gridy).flatten()
        gridded_x, gridded_y = np.meshgrid(gridx, gridy)
        gridded_x, gridded_y = core.adjust_for_anisotropy(gridded_x, gridded_y,
                                                          self.XCENTER, self.YCENTER,
                                                          self.anisotropy_scaling,
                                                          self.anisotropy_angle)
        gridz = np.zeros((gridy.shape[0], gridx.shape[0]))
        sigmasq = np.zeros((gridy.shape[0], gridx.shape[0]))
        for m in range(gridz.shape[0]):
            for n in range(gridz.shape[1]):
                z, ss = core.krige(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                   (gridded_x[m, n], gridded_y[m, n]),
                                   self.variogram_function,
                                   self.variogram_model_parameters)
                gridz[m, n] = z
                sigmasq[m, n] = ss

        return gridz, sigmasq
Esempio n. 2
0
    def test_core_adjust_for_anisotropy(self):

        x = np.array([1.0, 0.0, -1.0, 0.0])
        y = np.array([0.0, 1.0, 0.0, -1.0])
        rotated_x, rotated_y = core.adjust_for_anisotropy(
            x, y, 0.0, 0.0, 2.0, 90.0)
        self.assertTrue(np.allclose(rotated_x, np.array([0.0, -1.0, 0.0,
                                                         1.0])))
        self.assertTrue(np.allclose(rotated_y, np.array([2.0, 0.0, -2.0,
                                                         0.0])))
Esempio n. 3
0
    def execute(self, style, xpoints, ypoints, mask=None, backend='vectorized', n_closest_points=None):
        """Calculates a kriged grid and the associated variance.

        This is now the method that performs the main kriging calculation. Note that currently
        measurements (i.e., z values) are considered 'exact'. This means that, when a specified
        coordinate for interpolation is exactly the same as one of the data points, the variogram
        evaluated at the point is forced to be zero. Also, the diagonal of the kriging matrix is
        also always forced to be zero. In forcing the variogram evaluated at data points to be zero,
        we are effectively saying that there is no variance at that point (no uncertainty,
        so the value is 'exact').

        In the future, the code may include an extra 'exact_values' boolean flag that can be
        adjusted to specify whether to treat the measurements as 'exact'. Setting the flag
        to false would indicate that the variogram should not be forced to be zero at zero distance
        (i.e., when evaluated at data points). Instead, the uncertainty in the point will be
        equal to the nugget. This would mean that the diagonal of the kriging matrix would be set to
        the nugget instead of to zero.

        Inputs:
            style (string): Specifies how to treat input kriging points.
                Specifying 'grid' treats xpoints and ypoints as two arrays of
                x and y coordinates that define a rectangular grid.
                Specifying 'points' treats xpoints and ypoints as two arrays
                that provide coordinate pairs at which to solve the kriging system.
                Specifying 'masked' treats xpoints and ypoints as two arrays of
                x and y coordinates that define a rectangular grid and uses mask
                to only evaluate specific points in the grid.
            xpoints (array-like, dim N): If style is specific as 'grid' or 'masked',
                x-coordinates of MxN grid. If style is specified as 'points',
                x-coordinates of specific points at which to solve kriging system.
            ypoints (array-like, dim M): If style is specified as 'grid' or 'masked',
                y-coordinates of MxN grid. If style is specified as 'points',
                y-coordinates of specific points at which to solve kriging system.
                Note that in this case, xpoints and ypoints must have the same dimensions
                (i.e., M = N).
            mask (boolean array, dim MxN, optional): Specifies the points in the rectangular
                grid defined by xpoints and ypoints that are to be excluded in the
                kriging calculations. Must be provided if style is specified as 'masked'.
                False indicates that the point should not be masked, so the kriging system
                will be solved at the point.
                True indicates that the point should be masked, so the kriging system should
                will not be solved at the point.
            backend (string, optional): Specifies which approach to use in kriging.
                Specifying 'vectorized' will solve the entire kriging problem at once in a
                vectorized operation. This approach is faster but also can consume a
                significant amount of memory for large grids and/or large datasets.
                Specifying 'loop' will loop through each point at which the kriging system
                is to be solved. This approach is slower but also less memory-intensive.
                Specifying 'C' will utilize a loop in Cython.
                Default is 'vectorized'.
            n_closest_points (int, optional): For kriging with a moving window, specifies the number
                of nearby points to use in the calculation. This can speed up the calculation for large
                datasets, but should be used with caution. As Kitanidis notes, kriging with a moving
                window can produce unexpected oddities if the variogram model is not carefully chosen.
        Outputs:
            zvalues (numpy array, dim MxN or dim Nx1): Z-values of specified grid or at the
                specified set of points. If style was specified as 'masked', zvalues will
                be a numpy masked array.
            sigmasq (numpy array, dim MxN or dim Nx1): Variance at specified grid points or
                at the specified set of points. If style was specified as 'masked', sigmasq
                will be a numpy masked array.
        """

        if self.verbose:
            print "Executing Ordinary Kriging...\n"

        if style != 'grid' and style != 'masked' and style != 'points':
            raise ValueError("style argument must be 'grid', 'points', or 'masked'")

        xpts = np.atleast_1d(np.squeeze(np.array(xpoints, copy=True)))
        ypts = np.atleast_1d(np.squeeze(np.array(ypoints, copy=True)))
        n = self.X_ADJUSTED.shape[0]
        nx = xpts.size
        ny = ypts.size
        a = self._get_kriging_matrix(n)

        if style in ['grid', 'masked']:
            if style == 'masked':
                if mask is None:
                    raise IOError("Must specify boolean masking array when style is 'masked'.")
                if mask.shape[0] != ny or mask.shape[1] != nx:
                    if mask.shape[0] == nx and mask.shape[1] == ny:
                        mask = mask.T
                    else:
                        raise ValueError("Mask dimensions do not match specified grid dimensions.")
                mask = mask.flatten()
            npt = ny*nx
            grid_x, grid_y = np.meshgrid(xpts, ypts)
            xpts = grid_x.flatten()
            ypts = grid_y.flatten()

        elif style == 'points':
            if xpts.size != ypts.size:
                raise ValueError("xpoints and ypoints must have same dimensions "
                                 "when treated as listing discrete points.")
            npt = nx
        else:
            raise ValueError("style argument must be 'grid', 'points', or 'masked'")

        xpts, ypts = core.adjust_for_anisotropy(xpts, ypts, self.XCENTER, self.YCENTER,
                                                self.anisotropy_scaling, self.anisotropy_angle)

        if style != 'masked':
            mask = np.zeros(npt, dtype='bool')

        xy_points = np.concatenate((xpts[:, np.newaxis], ypts[:, np.newaxis]), axis=1)
        xy_data = np.concatenate((self.X_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis]), axis=1)

        if backend == 'C':
            try:
                from .lib.c*k import _c_exec_loop, _c_exec_loop_moving_window
            except ImportError:
                raise ImportError('C backend failed to load the Cython extension')
            except:
                raise RuntimeError("Unknown error in trying to load Cython extension.")

            c_pars = {key: getattr(self, key) for key in ['Z', 'eps', 'variogram_model_parameters',
                                                          'variogram_function']}
        else:
            c_pars = None

        if n_closest_points is not None:
            from scipy.spatial import cKDTree
            tree = cKDTree(xy_data)
            bd, bd_idx = tree.query(xy_points, k=n_closest_points, eps=0.0)

            if backend == 'loop':
                zvalues, sigmasq = self._exec_loop_moving_window(a, bd, mask, bd_idx)
            elif backend == 'C':
                zvalues, sigmasq = _c_exec_loop_moving_window(a, bd, mask.astype('int8'),
                                                              bd_idx, self.X_ADJUSTED.shape[0], c_pars)
            else:
                raise ValueError('Specified backend {} for a moving window is not supported.'.format(backend))
        else:
            bd = cdist(xy_points,  xy_data, 'euclidean')
            if backend == 'vectorized':
                zvalues, sigmasq = self._exec_vector(a, bd, mask)
            elif backend == 'loop':
                zvalues, sigmasq = self._exec_loop(a, bd, mask)
            elif backend == 'C':
                zvalues, sigmasq = _c_exec_loop(a, bd, mask.astype('int8'), self.X_ADJUSTED.shape[0],  c_pars)
            else:
                raise ValueError('Specified backend {} is not supported for 2D ordinary kriging.'.format(backend))

        if style == 'masked':
            zvalues = np.ma.array(zvalues, mask=mask)
            sigmasq = np.ma.array(sigmasq, mask=mask)

        if style in ['masked', 'grid']:
            zvalues = zvalues.reshape((ny, nx))
            sigmasq = sigmasq.reshape((ny, nx))

        return zvalues, sigmasq
Esempio n. 4
0
    def update_variogram_model(self, variogram_model, variogram_parameters=None,
                               variogram_function=None, nlags=6, weight=False,
                               anisotropy_scaling=1.0, anisotropy_angle=0.0):
        """Allows user to update variogram type and/or variogram model parameters."""

        if anisotropy_scaling != self.anisotropy_scaling or \
           anisotropy_angle != self.anisotropy_angle:
            if self.verbose:
                print "Adjusting data for anisotropy..."
            self.anisotropy_scaling = anisotropy_scaling
            self.anisotropy_angle = anisotropy_angle
            self.X_ADJUSTED, self.Y_ADJUSTED = \
                core.adjust_for_anisotropy(np.copy(self.X_ORIG),
                                           np.copy(self.Y_ORIG),
                                           self.XCENTER, self.YCENTER,
                                           self.anisotropy_scaling,
                                           self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model not in self.variogram_dict.keys() and self.variogram_model != 'custom':
            raise ValueError("Specified variogram model '%s' is not supported." % variogram_model)
        elif self.variogram_model == 'custom':
            if variogram_function is None or not callable(variogram_function):
                raise ValueError("Must specify callable function for custom variogram model.")
            else:
                self.variogram_function = variogram_function
        else:
            self.variogram_function = self.variogram_dict[self.variogram_model]
        if self.verbose:
            print "Updating variogram mode..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags, weight)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            elif self.variogram_model == 'custom':
                print "Using Custom Variogram Model"
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        self.delta, self.sigma, self.epsilon = core.find_statistics(self.X_ADJUSTED, self.Y_ADJUSTED,
                                                                    self.Z, self.variogram_function,
                                                                    self.variogram_model_parameters)
        self.Q1 = core.calcQ1(self.epsilon)
        self.Q2 = core.calcQ2(self.epsilon)
        self.cR = core.calc_cR(self.Q2, self.sigma)
        if self.verbose:
            print "Q1 =", self.Q1
            print "Q2 =", self.Q2
            print "cR =", self.cR, '\n'
Esempio n. 5
0
    def __init__(self, x, y, z, variogram_model='linear', variogram_parameters=None,
                 variogram_function=None, nlags=6, weight=False, anisotropy_scaling=1.0,
                 anisotropy_angle=0.0, verbose=False, enable_plotting=False,
                 enable_statistics=False):

        # Code assumes 1D input arrays. Ensures that any extraneous dimensions
        # don't get in the way. Copies are created to avoid any problems with
        # referencing the original passed arguments.
        self.X_ORIG = np.atleast_1d(np.squeeze(np.array(x, copy=True)))
        self.Y_ORIG = np.atleast_1d(np.squeeze(np.array(y, copy=True)))
        self.Z = np.atleast_1d(np.squeeze(np.array(z, copy=True)))

        self.verbose = verbose
        self.enable_plotting = enable_plotting
        if self.enable_plotting and self.verbose:
            print "Plotting Enabled\n"

        self.XCENTER = (np.amax(self.X_ORIG) + np.amin(self.X_ORIG))/2.0
        self.YCENTER = (np.amax(self.Y_ORIG) + np.amin(self.Y_ORIG))/2.0
        self.anisotropy_scaling = anisotropy_scaling
        self.anisotropy_angle = anisotropy_angle
        if self.verbose:
            print "Adjusting data for anisotropy..."
        self.X_ADJUSTED, self.Y_ADJUSTED = \
            core.adjust_for_anisotropy(np.copy(self.X_ORIG), np.copy(self.Y_ORIG),
                                       self.XCENTER, self.YCENTER,
                                       self.anisotropy_scaling, self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model not in self.variogram_dict.keys() and self.variogram_model != 'custom':
            raise ValueError("Specified variogram model '%s' is not supported." % variogram_model)
        elif self.variogram_model == 'custom':
            if variogram_function is None or not callable(variogram_function):
                raise ValueError("Must specify callable function for custom variogram model.")
            else:
                self.variogram_function = variogram_function
        else:
            self.variogram_function = self.variogram_dict[self.variogram_model]
        if self.verbose:
            print "Initializing variogram model..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags, weight)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            elif self.variogram_model == 'custom':
                print "Using Custom Variogram Model"
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        if enable_statistics:
            self.delta, self.sigma, self.epsilon = core.find_statistics(self.X_ADJUSTED, self.Y_ADJUSTED,
                                                                        self.Z, self.variogram_function,
                                                                        self.variogram_model_parameters)
            self.Q1 = core.calcQ1(self.epsilon)
            self.Q2 = core.calcQ2(self.epsilon)
            self.cR = core.calc_cR(self.Q2, self.sigma)
            if self.verbose:
                print "Q1 =", self.Q1
                print "Q2 =", self.Q2
                print "cR =", self.cR, '\n'
        else:
            self.delta, self.sigma, self.epsilon, self.Q1, self.Q2, self.cR = [None]*6
Esempio n. 6
0
    def execute(self,
                style,
                xpoints,
                ypoints,
                mask=None,
                backend='vectorized',
                n_closest_points=None):
        """Calculates a kriged grid and the associated variance.

        This is now the method that performs the main kriging calculation. Note that currently
        measurements (i.e., z values) are considered 'exact'. This means that, when a specified
        coordinate for interpolation is exactly the same as one of the data points, the variogram
        evaluated at the point is forced to be zero. Also, the diagonal of the kriging matrix is
        also always forced to be zero. In forcing the variogram evaluated at data points to be zero,
        we are effectively saying that there is no variance at that point (no uncertainty,
        so the value is 'exact').

        In the future, the code may include an extra 'exact_values' boolean flag that can be
        adjusted to specify whether to treat the measurements as 'exact'. Setting the flag
        to false would indicate that the variogram should not be forced to be zero at zero distance
        (i.e., when evaluated at data points). Instead, the uncertainty in the point will be
        equal to the nugget. This would mean that the diagonal of the kriging matrix would be set to
        the nugget instead of to zero.

        Inputs:
            style (string): Specifies how to treat input kriging points.
                Specifying 'grid' treats xpoints and ypoints as two arrays of
                x and y coordinates that define a rectangular grid.
                Specifying 'points' treats xpoints and ypoints as two arrays
                that provide coordinate pairs at which to solve the kriging system.
                Specifying 'masked' treats xpoints and ypoints as two arrays of
                x and y coordinates that define a rectangular grid and uses mask
                to only evaluate specific points in the grid.
            xpoints (array-like, dim N): If style is specific as 'grid' or 'masked',
                x-coordinates of MxN grid. If style is specified as 'points',
                x-coordinates of specific points at which to solve kriging system.
            ypoints (array-like, dim M): If style is specified as 'grid' or 'masked',
                y-coordinates of MxN grid. If style is specified as 'points',
                y-coordinates of specific points at which to solve kriging system.
                Note that in this case, xpoints and ypoints must have the same dimensions
                (i.e., M = N).
            mask (boolean array, dim MxN, optional): Specifies the points in the rectangular
                grid defined by xpoints and ypoints that are to be excluded in the
                kriging calculations. Must be provided if style is specified as 'masked'.
                False indicates that the point should not be masked, so the kriging system
                will be solved at the point.
                True indicates that the point should be masked, so the kriging system should
                will not be solved at the point.
            backend (string, optional): Specifies which approach to use in kriging.
                Specifying 'vectorized' will solve the entire kriging problem at once in a
                vectorized operation. This approach is faster but also can consume a
                significant amount of memory for large grids and/or large datasets.
                Specifying 'loop' will loop through each point at which the kriging system
                is to be solved. This approach is slower but also less memory-intensive.
                Specifying 'C' will utilize a loop in Cython.
                Default is 'vectorized'.
            n_closest_points (int, optional): For kriging with a moving window, specifies the number
                of nearby points to use in the calculation. This can speed up the calculation for large
                datasets, but should be used with caution. As Kitanidis notes, kriging with a moving
                window can produce unexpected oddities if the variogram model is not carefully chosen.
        Outputs:
            zvalues (numpy array, dim MxN or dim Nx1): Z-values of specified grid or at the
                specified set of points. If style was specified as 'masked', zvalues will
                be a numpy masked array.
            sigmasq (numpy array, dim MxN or dim Nx1): Variance at specified grid points or
                at the specified set of points. If style was specified as 'masked', sigmasq
                will be a numpy masked array.
        """

        if self.verbose:
            print "Executing Ordinary Kriging...\n"

        if style != 'grid' and style != 'masked' and style != 'points':
            raise ValueError(
                "style argument must be 'grid', 'points', or 'masked'")

        xpts = np.atleast_1d(np.squeeze(np.array(xpoints, copy=True)))
        ypts = np.atleast_1d(np.squeeze(np.array(ypoints, copy=True)))
        n = self.X_ADJUSTED.shape[0]
        nx = xpts.size
        ny = ypts.size
        a = self._get_kriging_matrix(n)

        if style in ['grid', 'masked']:
            if style == 'masked':
                if mask is None:
                    raise IOError(
                        "Must specify boolean masking array when style is 'masked'."
                    )
                if mask.shape[0] != ny or mask.shape[1] != nx:
                    if mask.shape[0] == nx and mask.shape[1] == ny:
                        mask = mask.T
                    else:
                        raise ValueError(
                            "Mask dimensions do not match specified grid dimensions."
                        )
                mask = mask.flatten()
            npt = ny * nx
            grid_x, grid_y = np.meshgrid(xpts, ypts)
            xpts = grid_x.flatten()
            ypts = grid_y.flatten()

        elif style == 'points':
            if xpts.size != ypts.size:
                raise ValueError(
                    "xpoints and ypoints must have same dimensions "
                    "when treated as listing discrete points.")
            npt = nx
        else:
            raise ValueError(
                "style argument must be 'grid', 'points', or 'masked'")

        xpts, ypts = core.adjust_for_anisotropy(xpts, ypts, self.XCENTER,
                                                self.YCENTER,
                                                self.anisotropy_scaling,
                                                self.anisotropy_angle)

        if style != 'masked':
            mask = np.zeros(npt, dtype='bool')

        xy_points = np.concatenate((xpts[:, np.newaxis], ypts[:, np.newaxis]),
                                   axis=1)
        xy_data = np.concatenate(
            (self.X_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis]),
            axis=1)

        if backend == 'C':
            try:
                from .lib.c*k import _c_exec_loop, _c_exec_loop_moving_window
            except ImportError:
                raise ImportError(
                    'C backend failed to load the Cython extension')
            except:
                raise RuntimeError(
                    "Unknown error in trying to load Cython extension.")

            c_pars = {
                key: getattr(self, key)
                for key in [
                    'Z', 'eps', 'variogram_model_parameters',
                    'variogram_function'
                ]
            }
        else:
            c_pars = None

        if n_closest_points is not None:
            from scipy.spatial import cKDTree
            tree = cKDTree(xy_data)
            bd, bd_idx = tree.query(xy_points, k=n_closest_points, eps=0.0)

            if backend == 'loop':
                zvalues, sigmasq = self._exec_loop_moving_window(
                    a, bd, mask, bd_idx)
            elif backend == 'C':
                zvalues, sigmasq = _c_exec_loop_moving_window(
                    a, bd, mask.astype('int8'), bd_idx,
                    self.X_ADJUSTED.shape[0], c_pars)
            else:
                raise ValueError(
                    'Specified backend {} for a moving window is not supported.'
                    .format(backend))
        else:
            bd = cdist(xy_points, xy_data, 'euclidean')
            if backend == 'vectorized':
                zvalues, sigmasq = self._exec_vector(a, bd, mask)
            elif backend == 'loop':
                zvalues, sigmasq = self._exec_loop(a, bd, mask)
            elif backend == 'C':
                zvalues, sigmasq = _c_exec_loop(a, bd, mask.astype('int8'),
                                                self.X_ADJUSTED.shape[0],
                                                c_pars)
            else:
                raise ValueError(
                    'Specified backend {} is not supported for 2D ordinary kriging.'
                    .format(backend))

        if style == 'masked':
            zvalues = np.ma.array(zvalues, mask=mask)
            sigmasq = np.ma.array(sigmasq, mask=mask)

        if style in ['masked', 'grid']:
            zvalues = zvalues.reshape((ny, nx))
            sigmasq = sigmasq.reshape((ny, nx))

        return zvalues, sigmasq
Esempio n. 7
0
    def update_variogram_model(self,
                               variogram_model,
                               variogram_parameters=None,
                               variogram_function=None,
                               nlags=6,
                               weight=False,
                               anisotropy_scaling=1.0,
                               anisotropy_angle=0.0):
        """Allows user to update variogram type and/or variogram model parameters."""

        if anisotropy_scaling != self.anisotropy_scaling or \
           anisotropy_angle != self.anisotropy_angle:
            if self.verbose:
                print "Adjusting data for anisotropy..."
            self.anisotropy_scaling = anisotropy_scaling
            self.anisotropy_angle = anisotropy_angle
            self.X_ADJUSTED, self.Y_ADJUSTED = \
                core.adjust_for_anisotropy(np.copy(self.X_ORIG),
                                           np.copy(self.Y_ORIG),
                                           self.XCENTER, self.YCENTER,
                                           self.anisotropy_scaling,
                                           self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model not in self.variogram_dict.keys(
        ) and self.variogram_model != 'custom':
            raise ValueError(
                "Specified variogram model '%s' is not supported." %
                variogram_model)
        elif self.variogram_model == 'custom':
            if variogram_function is None or not callable(variogram_function):
                raise ValueError(
                    "Must specify callable function for custom variogram model."
                )
            else:
                self.variogram_function = variogram_function
        else:
            self.variogram_function = self.variogram_dict[self.variogram_model]
        if self.verbose:
            print "Updating variogram mode..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags, weight)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            elif self.variogram_model == 'custom':
                print "Using Custom Variogram Model"
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        self.delta, self.sigma, self.epsilon = core.find_statistics(
            self.X_ADJUSTED, self.Y_ADJUSTED, self.Z, self.variogram_function,
            self.variogram_model_parameters)
        self.Q1 = core.calcQ1(self.epsilon)
        self.Q2 = core.calcQ2(self.epsilon)
        self.cR = core.calc_cR(self.Q2, self.sigma)
        if self.verbose:
            print "Q1 =", self.Q1
            print "Q2 =", self.Q2
            print "cR =", self.cR, '\n'
Esempio n. 8
0
    def __init__(self,
                 x,
                 y,
                 z,
                 variogram_model='linear',
                 variogram_parameters=None,
                 variogram_function=None,
                 nlags=6,
                 weight=False,
                 anisotropy_scaling=1.0,
                 anisotropy_angle=0.0,
                 verbose=False,
                 enable_plotting=False,
                 enable_statistics=False):

        # Code assumes 1D input arrays. Ensures that any extraneous dimensions
        # don't get in the way. Copies are created to avoid any problems with
        # referencing the original passed arguments.
        self.X_ORIG = np.atleast_1d(np.squeeze(np.array(x, copy=True)))
        self.Y_ORIG = np.atleast_1d(np.squeeze(np.array(y, copy=True)))
        self.Z = np.atleast_1d(np.squeeze(np.array(z, copy=True)))

        self.verbose = verbose
        self.enable_plotting = enable_plotting
        if self.enable_plotting and self.verbose:
            print "Plotting Enabled\n"

        self.XCENTER = (np.amax(self.X_ORIG) + np.amin(self.X_ORIG)) / 2.0
        self.YCENTER = (np.amax(self.Y_ORIG) + np.amin(self.Y_ORIG)) / 2.0
        self.anisotropy_scaling = anisotropy_scaling
        self.anisotropy_angle = anisotropy_angle
        if self.verbose:
            print "Adjusting data for anisotropy..."
        self.X_ADJUSTED, self.Y_ADJUSTED = \
            core.adjust_for_anisotropy(np.copy(self.X_ORIG), np.copy(self.Y_ORIG),
                                       self.XCENTER, self.YCENTER,
                                       self.anisotropy_scaling, self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model not in self.variogram_dict.keys(
        ) and self.variogram_model != 'custom':
            raise ValueError(
                "Specified variogram model '%s' is not supported." %
                variogram_model)
        elif self.variogram_model == 'custom':
            if variogram_function is None or not callable(variogram_function):
                raise ValueError(
                    "Must specify callable function for custom variogram model."
                )
            else:
                self.variogram_function = variogram_function
        else:
            self.variogram_function = self.variogram_dict[self.variogram_model]
        if self.verbose:
            print "Initializing variogram model..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags, weight)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            elif self.variogram_model == 'custom':
                print "Using Custom Variogram Model"
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        if enable_statistics:
            self.delta, self.sigma, self.epsilon = core.find_statistics(
                self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                self.variogram_function, self.variogram_model_parameters)
            self.Q1 = core.calcQ1(self.epsilon)
            self.Q2 = core.calcQ2(self.epsilon)
            self.cR = core.calc_cR(self.Q2, self.sigma)
            if self.verbose:
                print "Q1 =", self.Q1
                print "Q2 =", self.Q2
                print "cR =", self.cR, '\n'
        else:
            self.delta, self.sigma, self.epsilon, self.Q1, self.Q2, self.cR = [
                None
            ] * 6
Esempio n. 9
0
    def update_variogram_model(self, variogram_model,
                               variogram_parameters=None,
                               nlags=6, anisotropy_scaling=1.0,
                               anisotropy_angle=0.0):
        """Allows user to update variogram type and/or variogram model parameters."""

        if anisotropy_scaling != self.anisotropy_scaling or \
           anisotropy_angle != self.anisotropy_angle:
            if self.verbose:
                print "Adjusting data for anisotropy..."
            self.anisotropy_scaling = anisotropy_scaling
            self.anisotropy_angle = anisotropy_angle
            self.X_ADJUSTED, self.Y_ADJUSTED = \
                core.adjust_for_anisotropy(np.copy(self.X_ORIG),
                                           np.copy(self.Y_ORIG),
                                           self.XCENTER, self.YCENTER,
                                           self.anisotropy_scaling,
                                           self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model == 'linear':
            self.variogram_function = variogram_models.linear_variogram_model
        if self.variogram_model == 'power':
            self.variogram_function = variogram_models.power_variogram_model
        if self.variogram_model == 'gaussian':
            self.variogram_function = variogram_models.gaussian_variogram_model
        if self.variogram_model == 'spherical':
            self.variogram_function = variogram_models.spherical_variogram_model
        if self.variogram_model == 'exponential':
            self.variogram_function = variogram_models.exponential_variogram_model
        if self.verbose:
            print "Updating variogram mode..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        self.delta, self.sigma, self.epsilon = core.find_statistics(self.X_ADJUSTED,
                                                                    self.Y_ADJUSTED,
                                                                    self.Z,
                                                                    self.variogram_function,
                                                                    self.variogram_model_parameters)
        self.Q1 = core.calcQ1(self.epsilon)
        self.Q2 = core.calcQ2(self.epsilon)
        self.cR = core.calc_cR(self.Q2, self.sigma)
        if self.verbose:
            print "Q1 =", self.Q1
            print "Q2 =", self.Q2
            print "cR =", self.cR, '\n'
Esempio n. 10
0
    def __init__(self, x, y, z, variogram_model='linear',
                 variogram_parameters=None, nlags=6,
                 anisotropy_scaling=1.0, anisotropy_angle=0.0,
                 verbose=False, enable_plotting=False):

        # Code assumes 1D input arrays. Ensures that this is the case.
        self.X_ORIG = np.array(x).flatten()
        self.Y_ORIG = np.array(y).flatten()
        self.Z = np.array(z).flatten()

        self.verbose = verbose
        self.enable_plotting = enable_plotting
        if self.enable_plotting and self.verbose:
            print "Plotting Enabled\n"

        self.XCENTER = (np.amax(self.X_ORIG) + np.amin(self.X_ORIG))/2.0
        self.YCENTER = (np.amax(self.Y_ORIG) + np.amin(self.Y_ORIG))/2.0
        self.anisotropy_scaling = anisotropy_scaling
        self.anisotropy_angle = anisotropy_angle
        if self.verbose:
            print "Adjusting data for anisotropy..."
        self.X_ADJUSTED, self.Y_ADJUSTED = \
            core.adjust_for_anisotropy(np.copy(self.X_ORIG), np.copy(self.Y_ORIG),
                                       self.XCENTER, self.YCENTER,
                                       self.anisotropy_scaling, self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model == 'linear':
            self.variogram_function = variogram_models.linear_variogram_model
        if self.variogram_model == 'power':
            self.variogram_function = variogram_models.power_variogram_model
        if self.variogram_model == 'gaussian':
            self.variogram_function = variogram_models.gaussian_variogram_model
        if self.variogram_model == 'spherical':
            self.variogram_function = variogram_models.spherical_variogram_model
        if self.variogram_model == 'exponential':
            self.variogram_function = variogram_models.exponential_variogram_model
        if self.verbose:
            print "Initializing variogram model..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        self.delta, self.sigma, self.epsilon = core.find_statistics(self.X_ADJUSTED,
                                                                    self.Y_ADJUSTED,
                                                                    self.Z,
                                                                    self.variogram_function,
                                                                    self.variogram_model_parameters)
        self.Q1 = core.calcQ1(self.epsilon)
        self.Q2 = core.calcQ2(self.epsilon)
        self.cR = core.calc_cR(self.Q2, self.sigma)
        if self.verbose:
            print "Q1 =", self.Q1
            print "Q2 =", self.Q2
            print "cR =", self.cR, '\n'
Esempio n. 11
0
    def __init__(self, x, y, z, variogram_model='linear',
                 variogram_parameters=None, nlags=6,
                 anisotropy_scaling=1.0, anisotropy_angle=0.0,
                 drift_terms=[None], point_drift=None, external_drift=None,
                 external_drift_x=None, external_drift_y=None,
                 external_drift_xspacing=None, external_drift_yspacing=None,
                 verbose=False, enable_plotting=False):

        # Code assumes 1D input arrays. Ensures that this is the case.
        self.X_ORIG = np.array(x).flatten()
        self.Y_ORIG = np.array(y).flatten()
        self.Z = np.array(z).flatten()

        self.verbose = verbose
        self.enable_plotting = enable_plotting
        if self.enable_plotting and self.verbose:
            print "Plotting Enabled\n"

        self.XCENTER = (np.amax(self.X_ORIG) + np.amin(self.X_ORIG))/2.0
        self.YCENTER = (np.amax(self.Y_ORIG) + np.amin(self.Y_ORIG))/2.0
        self.anisotropy_scaling = anisotropy_scaling
        self.anisotropy_angle = anisotropy_angle
        if self.verbose:
            print "Adjusting data for anisotropy..."
        self.X_ADJUSTED, self.Y_ADJUSTED = \
            core.adjust_for_anisotropy(np.copy(self.X_ORIG), np.copy(self.Y_ORIG),
                                       self.XCENTER, self.YCENTER,
                                       self.anisotropy_scaling, self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model == 'linear':
            self.variogram_function = variogram_models.linear_variogram_model
        if self.variogram_model == 'power':
            self.variogram_function = variogram_models.power_variogram_model
        if self.variogram_model == 'gaussian':
            self.variogram_function = variogram_models.gaussian_variogram_model
        if self.variogram_model == 'spherical':
            self.variogram_function = variogram_models.spherical_variogram_model
        if self.variogram_model == 'exponential':
            self.variogram_function = variogram_models.exponential_variogram_model
        if self.verbose:
            print "Initializing variogram model..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2]
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        self.delta, self.sigma, self.epsilon = core.find_statistics(self.X_ADJUSTED,
                                                                    self.Y_ADJUSTED,
                                                                    self.Z,
                                                                    self.variogram_function,
                                                                    self.variogram_model_parameters)
        self.Q1 = core.calcQ1(self.epsilon)
        self.Q2 = core.calcQ2(self.epsilon)
        self.cR = core.calc_cR(self.Q2, self.sigma)
        if self.verbose:
            print "Q1 =", self.Q1
            print "Q2 =", self.Q2
            print "cR =", self.cR, '\n'

        if self.verbose:
            print "Initializing drift terms..."

        if 'regional_linear' in drift_terms:
            self.regional_linear_drift = True
            if self.verbose:
                print "Implementing regional linear drift."
        else:
            self.regional_linear_drift = False

        if 'external_Z' in drift_terms:
            if external_drift is None:
                raise ValueError("Must specify external Z drift terms.")
            if external_drift_x is None or external_drift_y is None:
                raise ValueError("Must specify coordinates of external Z drift terms.")
            self.external_Z_drift = True
            self.external_Z_array = np.array(external_drift)
            self.external_Z_array_x = np.array(external_drift_x).flatten()
            self.external_Z_array_y = np.array(external_drift_y).flatten()
            if np.unique(self.external_Z_array_x[1:] - self.external_Z_array_x[:-1]).size != 1:
                if external_drift_xspacing is None:
                    raise ValueError("X-coordinate spacing is not constant. "
                                     "Must provide X-coordinate grid size.")
                else:
                    self.external_Z_array_x_spacing = np.array(external_drift_xspacing).flatten()
            else:
                self.external_Z_array_x_spacing = np.zeros(self.external_Z_array_x.shape)
                self.external_Z_array_x_spacing.fill(
                    np.unique(self.external_Z_array_x[1:] - self.external_Z_array_x[:-1])[0])
            if np.unique(self.external_Z_array_y[1:] - self.external_Z_array_y[:-1]).size != 1:
                if external_drift_yspacing is None:
                    raise ValueError("Y-coordinate spacing is not constant. "
                                     "Must provide Y-coordinate grid size.")
                else:
                    self.external_Z_array_y_spacing = np.array(external_drift_yspacing).flatten()
            else:
                self.external_Z_array_y_spacing = np.zeros(self.external_Z_array_y.shape)
                self.external_Z_array_y_spacing.fill(
                    np.unique(self.external_Z_array_y[1:] - self.external_Z_array_y[:-1])[0])
            self.z_scalars = self._calculate_data_point_zscalars(self.X_ORIG,
                                                                 self.Y_ORIG)
            if self.verbose:
                print "Implementing external Z drift."
        else:
            self.external_Z_drift = False

        if 'point_log' in drift_terms:
            if point_drift is None:
                raise ValueError("Must specify location(s) and strength(s) of point drift terms.")
            self.point_log_drift = True
            self.point_log_array = np.atleast_2d(np.array(point_drift))
            if self.verbose:
                print "Implementing external point-logarithmic drift; " \
                      "number of points =", self.point_log_array.shape[0], '\n'
        else:
            self.point_log_drift = False
Esempio n. 12
0
    def execute(self, style, xpoints, ypoints, mask=None):
        """Calculates a kriged grid and the associated variance.

        This is now the method that performs the main kriging calculation. Note that currently
        measurements (i.e., z values) are considered 'exact'. This means that, when a specified
        coordinate for interpolation is exactly the same as one of the data points, the variogram
        evaluated at the point is forced to be zero. Also, the diagonal of the kriging matrix is
        also always forced to be zero. In forcing the variogram evaluated at data points to be zero,
        we are effectively saying that there is no variance at that point (no uncertainty,
        so the value is 'exact').

        In the future, the code may include an extra 'exact_values' boolean flag that can be
        adjusted to specify whether to treat the measurements as 'exact'. Setting the flag
        to false would indicate that the variogram should not be forced to be zero at zero distance
        (i.e., when evaluated at data points). Instead, the uncertainty in the point will be
        equal to the nugget. This would mean that the diagonal of the kriging matrix would be set to
        the nugget instead of to zero.

        Inputs:
            style (string): Specifies how to treat input kriging points.
                Specifying 'grid' treats xpoints and ypoints as two arrays of
                x and y coordinates that define a rectangular grid.
                Specifying 'points' treats xpoints and ypoints as two arrays
                that provide coordinate pairs at which to solve the kriging system.
                Specifying 'masked' treats xpoints and ypoints as two arrays of
                x and y coordinates that define a rectangular grid and uses mask
                to only evaluate specific points in the grid.
            xpoints (array-like, dim Nx1): If style is specific as 'grid' or 'masked',
                x-coordinates of MxN grid. If style is specified as 'points',
                x-coordinates of specific points at which to solve kriging system.
            ypoints (array-like, dim Mx1): If style is specified as 'grid' or 'masked',
                y-coordinates of MxN grid. If style is specified as 'points',
                y-coordinates of specific points at which to solve kriging system.
                Note that in this case, xpoints and ypoints must have the same dimensions
                (i.e., M = N).
            mask (boolean array, dim MxN, optional): Specifies the points in the rectangular
                grid defined by xpoints and ypoints that are to be excluded in the
                kriging calculations. Must be provided if style is specified as 'masked'.
                False indicates that the point should not be masked, so that the kriging system
                is solved at the point; True indicates that the point should be masked,
                so that the kriging system is not solved at the point.
        Outputs:
            zvalues (numpy array, dim MxN or dim Nx1): Z-values of specified grid or at the
                specified set of points. If style was specified as 'masked', zvalues will
                be a numpy masked array.
            sigmasq (numpy array, dim MxN or dim Nx1): Variance at specified grid points or
                at the specified set of points. If style was specified as 'masked', sigmasq
                will be a numpy masked array.
        """

        if self.verbose:
            print "Executing Ordinary Kriging...\n"

        xpoints = np.array(xpoints, copy=True).flatten()
        ypoints = np.array(ypoints, copy=True).flatten()
        nx = xpoints.shape[0]
        ny = ypoints.shape[0]
        n = self.X_ADJUSTED.shape[0]
        zero_index = None
        if np.any(xpoints == self.X_ORIG) and np.any(ypoints == self.Y_ORIG):
            zero_value = True
        else:
            zero_value = False

        if style == 'grid':
            grid_x, grid_y = np.meshgrid(xpoints, ypoints)
            grid_x, grid_y = core.adjust_for_anisotropy(
                grid_x, grid_y, self.XCENTER, self.YCENTER,
                self.anisotropy_scaling, self.anisotropy_angle)

            x1, x2 = np.meshgrid(self.X_ADJUSTED, self.X_ADJUSTED)
            y1, y2 = np.meshgrid(self.Y_ADJUSTED, self.Y_ADJUSTED)
            d = np.sqrt((x1 - x2)**2 + (y1 - y2)**2)
            a = np.zeros((ny, nx, n + 1, n + 1))
            a[:, :, :n, :n] = -self.variogram_function(
                self.variogram_model_parameters, d)
            index_grid = np.indices((ny, nx, n + 1, n + 1))
            a[index_grid[2] == index_grid[3]] = 0.0
            a[:, :, n, :] = 1.0
            a[:, :, :, n] = 1.0
            a[:, :, n, n] = 0.0

            grid_x_3d = np.repeat(grid_x[:, :, np.newaxis], n, axis=2)
            grid_y_3d = np.repeat(grid_y[:, :, np.newaxis], n, axis=2)
            data_x_3d = np.repeat(np.repeat(self.X_ADJUSTED[np.newaxis,
                                                            np.newaxis, :],
                                            ny,
                                            axis=0),
                                  nx,
                                  axis=1)
            data_y_3d = np.repeat(np.repeat(self.Y_ADJUSTED[np.newaxis,
                                                            np.newaxis, :],
                                            ny,
                                            axis=0),
                                  nx,
                                  axis=1)
            bd = np.sqrt((data_x_3d - grid_x_3d)**2 +
                         (data_y_3d - grid_y_3d)**2)
            if zero_value:
                zero_index = np.where(bd == 0.0)
            b = np.zeros((ny, nx, n + 1, 1))
            b[:, :, :n, 0] = -self.variogram_function(
                self.variogram_model_parameters, bd)
            if zero_value:
                b[zero_index[0], zero_index[1], zero_index[2], 0] = 0.0
            b[:, :, n, 0] = 1.0

            x = np.linalg.solve(a, b)
            zvalues = np.sum(x[:, :, :n, 0] * self.Z, axis=2)
            sigmasq = np.sum(x[:, :, :, 0] * -b[:, :, :, 0], axis=2)

        elif style == 'masked':
            if mask is None:
                raise IOError("Must specify boolean masking array.")
            if mask.shape[0] != ny or mask.shape[1] != nx:
                if mask.shape[0] == nx and mask.shape[1] == ny:
                    mask = mask.T
                else:
                    raise ValueError(
                        "Mask dimensions do not match specified grid dimensions."
                    )

            grid_x, grid_y = np.meshgrid(xpoints, ypoints)
            grid_x, grid_y = core.adjust_for_anisotropy(
                grid_x, grid_y, self.XCENTER, self.YCENTER,
                self.anisotropy_scaling, self.anisotropy_angle)

            x1, x2 = np.meshgrid(self.X_ADJUSTED, self.X_ADJUSTED)
            y1, y2 = np.meshgrid(self.Y_ADJUSTED, self.Y_ADJUSTED)
            d = np.sqrt((x1 - x2)**2 + (y1 - y2)**2)
            a = np.zeros((ny, nx, n + 1, n + 1))
            a[:, :, :n, :n] = -self.variogram_function(
                self.variogram_model_parameters, d)
            index_grid = np.indices((ny, nx, n + 1, n + 1))
            a[index_grid[2] == index_grid[3]] = 0.0
            a[:, :, n, :] = 1.0
            a[:, :, :, n] = 1.0
            a[:, :, n, n] = 0.0
            mask_a = np.repeat(np.repeat(mask[:, :, np.newaxis, np.newaxis],
                                         n + 1,
                                         axis=2),
                               n + 1,
                               axis=3)
            a = np.ma.array(a, mask=mask_a)

            grid_x_3d = np.repeat(grid_x[:, :, np.newaxis], n, axis=2)
            grid_y_3d = np.repeat(grid_y[:, :, np.newaxis], n, axis=2)
            data_x_3d = np.repeat(np.repeat(self.X_ADJUSTED[np.newaxis,
                                                            np.newaxis, :],
                                            ny,
                                            axis=0),
                                  nx,
                                  axis=1)
            data_y_3d = np.repeat(np.repeat(self.Y_ADJUSTED[np.newaxis,
                                                            np.newaxis, :],
                                            ny,
                                            axis=0),
                                  nx,
                                  axis=1)
            bd = np.sqrt((data_x_3d - grid_x_3d)**2 +
                         (data_y_3d - grid_y_3d)**2)
            if zero_value:
                zero_index = np.where(bd == 0.0)
            b = np.zeros((ny, nx, n + 1, 1))
            b[:, :, :n, 0] = -self.variogram_function(
                self.variogram_model_parameters, bd)
            if zero_value:
                b[zero_index[0], zero_index[1], zero_index[2], 0] = 0.0
            b[:, :, n, 0] = 1.0
            mask_b = np.repeat(mask[:, :, np.newaxis, np.newaxis],
                               n + 1,
                               axis=2)
            b = np.ma.array(b, mask=mask_b)

            x = np.linalg.solve(a, b)
            zvalues = np.sum(x[:, :, :n, 0] * self.Z, axis=2)
            sigmasq = np.sum(x[:, :, :, 0] * -b[:, :, :, 0], axis=2)

        elif style == 'points':
            if xpoints.shape != ypoints.shape:
                raise ValueError(
                    "xpoints and ypoints must have same dimensions "
                    "when treated as listing discrete points.")

            xpoints, ypoints = core.adjust_for_anisotropy(
                xpoints, ypoints, self.XCENTER, self.YCENTER,
                self.anisotropy_scaling, self.anisotropy_angle)

            x1, x2 = np.meshgrid(self.X_ADJUSTED, self.X_ADJUSTED)
            y1, y2 = np.meshgrid(self.Y_ADJUSTED, self.Y_ADJUSTED)
            d = np.sqrt((x1 - x2)**2 + (y1 - y2)**2)
            a = np.zeros((nx, n + 1, n + 1))
            a[:, :n, :n] = -self.variogram_function(
                self.variogram_model_parameters, d)
            index_grid = np.indices((nx, n + 1, n + 1))
            a[index_grid[1] == index_grid[2]] = 0.0
            a[:, n, :] = 1.0
            a[:, :, n] = 1.0
            a[:, n, n] = 0.0

            x_vals = np.repeat(xpoints[:, np.newaxis], n, axis=1)
            y_vals = np.repeat(ypoints[:, np.newaxis], n, axis=1)
            x_data = np.repeat(self.X_ADJUSTED[np.newaxis, :], nx, axis=0)
            y_data = np.repeat(self.Y_ADJUSTED[np.newaxis, :], nx, axis=0)
            bd = np.sqrt((x_data - x_vals)**2 + (y_data - y_vals)**2)
            if zero_value:
                zero_index = np.where(bd == 0.0)
            b = np.zeros((nx, n + 1, 1))
            b[:, :n, 0] = -self.variogram_function(
                self.variogram_model_parameters, bd)
            if zero_value:
                b[zero_index[0], zero_index[1], 0] = 0.0
            b[:, n, 0] = 1.0

            x = np.linalg.solve(a, b)
            zvalues = np.sum(x[:, :n, 0] * self.Z, axis=1)
            sigmasq = np.sum(x[:, :, 0] * -b[:, :, 0], axis=1)

        else:
            raise ValueError(
                "style argument must be 'grid', 'points', or 'masked'")

        return zvalues, sigmasq
Esempio n. 13
0
    def __init__(self,
                 x,
                 y,
                 z,
                 variogram_model='linear',
                 variogram_parameters=None,
                 nlags=6,
                 weight=False,
                 anisotropy_scaling=1.0,
                 anisotropy_angle=0.0,
                 verbose=False,
                 enable_plotting=False):

        # Code assumes 1D input arrays. Ensures that this is the case.
        # Copies are created to avoid any problems with referencing
        # the original passed arguments.
        self.X_ORIG = np.array(x, copy=True).flatten()
        self.Y_ORIG = np.array(y, copy=True).flatten()
        self.Z = np.array(z, copy=True).flatten()

        self.verbose = verbose
        self.enable_plotting = enable_plotting
        if self.enable_plotting and self.verbose:
            print "Plotting Enabled\n"

        self.XCENTER = (np.amax(self.X_ORIG) + np.amin(self.X_ORIG)) / 2.0
        self.YCENTER = (np.amax(self.Y_ORIG) + np.amin(self.Y_ORIG)) / 2.0
        self.anisotropy_scaling = anisotropy_scaling
        self.anisotropy_angle = anisotropy_angle
        if self.verbose:
            print "Adjusting data for anisotropy..."
        self.X_ADJUSTED, self.Y_ADJUSTED = \
            core.adjust_for_anisotropy(np.copy(self.X_ORIG), np.copy(self.Y_ORIG),
                                       self.XCENTER, self.YCENTER,
                                       self.anisotropy_scaling, self.anisotropy_angle)

        self.variogram_model = variogram_model
        if self.variogram_model == 'linear':
            self.variogram_function = variogram_models.linear_variogram_model
        elif self.variogram_model == 'power':
            self.variogram_function = variogram_models.power_variogram_model
        elif self.variogram_model == 'gaussian':
            self.variogram_function = variogram_models.gaussian_variogram_model
        elif self.variogram_model == 'spherical':
            self.variogram_function = variogram_models.spherical_variogram_model
        elif self.variogram_model == 'exponential':
            self.variogram_function = variogram_models.exponential_variogram_model
        else:
            raise ValueError(
                "Specified variogram model '%s' is not supported." %
                variogram_model)
        if self.verbose:
            print "Initializing variogram model..."
        self.lags, self.semivariance, self.variogram_model_parameters = \
            core.initialize_variogram_model(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z,
                                            self.variogram_model, variogram_parameters,
                                            self.variogram_function, nlags, weight)
        if self.verbose:
            if self.variogram_model == 'linear':
                print "Using '%s' Variogram Model" % 'linear'
                print "Slope:", self.variogram_model_parameters[0]
                print "Nugget:", self.variogram_model_parameters[1], '\n'
            elif self.variogram_model == 'power':
                print "Using '%s' Variogram Model" % 'power'
                print "Scale:", self.variogram_model_parameters[0]
                print "Exponent:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
            else:
                print "Using '%s' Variogram Model" % self.variogram_model
                print "Sill:", self.variogram_model_parameters[0]
                print "Range:", self.variogram_model_parameters[1]
                print "Nugget:", self.variogram_model_parameters[2], '\n'
        if self.enable_plotting:
            self.display_variogram_model()

        if self.verbose:
            print "Calculating statistics on variogram model fit..."
        self.delta, self.sigma, self.epsilon = core.find_statistics(
            self.X_ADJUSTED, self.Y_ADJUSTED, self.Z, self.variogram_function,
            self.variogram_model_parameters)
        self.Q1 = core.calcQ1(self.epsilon)
        self.Q2 = core.calcQ2(self.epsilon)
        self.cR = core.calc_cR(self.Q2, self.sigma)
        if self.verbose:
            print "Q1 =", self.Q1
            print "Q2 =", self.Q2
            print "cR =", self.cR, '\n'