def execute(self, style, xpoints, ypoints, mask=None,
                backend='vectorized', specified_drift_arrays=None):
        """Calculates a kriged grid and the associated variance.
        Includes drift terms.

        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.

        Parameters
        ----------
        style : str
            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, shape (N,) or (N, 1)
            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, shape (M,) or (M, 1)
            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, shape (M, N), 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 : str, 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. Default is 'vectorized'.
            Note that Cython backend is not supported for UK.
        specified_drift_arrays : list of array-like objects, optional
            Specifies the drift values at the points at which the kriging
            system is to be evaluated. Required if 'specified' drift provided
            in the list of drift terms when instantiating the UniversalKriging
            class. Must be a list of arrays in the same order as the list
            provided when instantiating the kriging object. Array(s) must be
            the same dimension as the specified grid or have the same number of
            points as the specified points; i.e., the arrays either must be
            shape (M, N), where M is the number of y grid-points and N is the
            number of x grid-points, or shape (M, ) or (N, 1), where M is the
            number of  points at which to evaluate the kriging system.

        Returns
        -------
        zvalues : ndarray, shape (M, N) or (N, 1)
            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 : ndarray, shape (M, N) or (N, 1)
            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 Universal Kriging...\n")

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

        n = self.X_ADJUSTED.shape[0]
        n_withdrifts = n
        xpts = np.atleast_1d(np.squeeze(np.array(xpoints, copy=True)))
        ypts = np.atleast_1d(np.squeeze(np.array(ypoints, copy=True)))
        nx = xpts.size
        ny = ypts.size
        if self.regional_linear_drift:
            n_withdrifts += 2
        if self.point_log_drift:
            n_withdrifts += self.point_log_array.shape[0]
        if self.external_Z_drift:
            n_withdrifts += 1
        if self.specified_drift:
            n_withdrifts += len(self.specified_drift_data_arrays)
        if self.functional_drift:
            n_withdrifts += len(self.functional_drift_terms)
        a = self._get_kriging_matrix(n, n_withdrifts)

        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'")

        if specified_drift_arrays is None:
            specified_drift_arrays = []
        spec_drift_grids = []
        if self.specified_drift:
            if len(specified_drift_arrays) == 0:
                raise ValueError("Must provide drift values for kriging points "
                                 "when using 'specified' drift capability.")
            if type(specified_drift_arrays) is not list:
                raise TypeError("Arrays for specified drift terms must be "
                                "encapsulated in a list.")
            for spec in specified_drift_arrays:
                if style in ['grid', 'masked']:
                    if spec.ndim < 2:
                        raise ValueError("Dimensions of drift values array do "
                                         "not match specified grid dimensions.")
                    elif spec.shape[0] != ny or spec.shape[1] != nx:
                        if spec.shape[0] == nx and spec.shape[1] == ny:
                            spec_drift_grids.append(np.squeeze(spec.T))
                        else:
                            raise ValueError("Dimensions of drift values array "
                                             "do not match specified grid "
                                             "dimensions.")
                    else:
                        spec_drift_grids.append(np.squeeze(spec))
                elif style == 'points':
                    if spec.ndim != 1:
                        raise ValueError("Dimensions of drift values array do "
                                         "not match specified grid dimensions.")
                    elif spec.shape[0] != xpts.size:
                        raise ValueError("Number of supplied drift values in "
                                         "array do not match specified number "
                                         "of kriging points.")
                    else:
                        spec_drift_grids.append(np.squeeze(spec))
            if len(spec_drift_grids) != len(self.specified_drift_data_arrays):
                raise ValueError("Inconsistent number of specified drift "
                                 "terms supplied.")
        else:
            if len(specified_drift_arrays) != 0:
                warnings.warn("Provided specified drift values, but "
                              "'specified' drift was not initialized during "
                              "instantiation of UniversalKriging class.",
                              RuntimeWarning)

        xy_points_original = \
            np.concatenate((xpts[:, np.newaxis], ypts[:, np.newaxis]), axis=1)
        xpts, ypts = _adjust_for_anisotropy(np.vstack((xpts, ypts)).T,
                                            [self.XCENTER, self.YCENTER],
                                            [self.anisotropy_scaling],
                                            [self.anisotropy_angle]).T
        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 style != 'masked':
            mask = np.zeros(npt, dtype='bool')

        bd = cdist(xy_points,  xy_data, 'euclidean')
        if backend == 'vectorized':
            zvalues, sigmasq = self._exec_vector(a, bd, xy_points,
                                                 xy_points_original,
                                                 mask, n_withdrifts,
                                                 spec_drift_grids)
        elif backend == 'loop':
            zvalues, sigmasq = self._exec_loop(a, bd, xy_points,
                                               xy_points_original,
                                               mask, n_withdrifts,
                                               spec_drift_grids)
        else:
            raise ValueError('Specified backend {} is not supported '
                             'for 2D universal 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
Calculates a kriged grid and the associated variance.
        Includes drift terms.

        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.

        Parameters
        ----------
        style : str
            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, shape (N,) or (N, 1)
            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, shape (M,) or (M, 1)
            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, shape (M, N), 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 : str, 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. Default is 'vectorized'.
            Note that Cython backend is not supported for UK.
        specified_drift_arrays : list of array-like objects, optional
            Specifies the drift values at the points at which the kriging
            system is to be evaluated. Required if 'specified' drift provided
            in the list of drift terms when instantiating the UniversalKriging
            class. Must be a list of arrays in the same order as the list
            provided when instantiating the kriging object. Array(s) must be
            the same dimension as the specified grid or have the same number of
            points as the specified points; i.e., the arrays either must be
            shape (M, N), where M is the number of y grid-points and N is the
            number of x grid-points, or shape (M, ) or (N, 1), where M is the
            number of  points at which to evaluate the kriging system.

        Returns
        -------
        zvalues : ndarray, shape (M, N) or (N, 1)
            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 : ndarray, shape (M, N) or (N, 1)
            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.