def execute(self, style, xpoints, ypoints, zpoints, mask=None, backend='vectorized'): """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, ypoints, and zpoints as arrays of x, y, and z coordinates that define a rectangular grid. Specifying 'points' treats xpoints, ypoints, and zpoints as arrays that provide coordinates at which to solve the kriging system. Specifying 'masked' treats xpoints, ypoints, and zpoints as arrays of x, y, and z 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 MxNxL 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 LxMxN grid. If style is specified as 'points', y-coordinates of specific points at which to solve kriging system. Note that in this case, xpoints, ypoints, and zpoints must have the same dimensions (i.e., L = M = N). zpoints (array-like, dim L): If style is specified as 'grid' or 'masked', z-coordinates of LxMxN grid. If style is specified as 'points', z-coordinates of specific points at which to solve kriging system. Note that in this case, xpoints, ypoints, and zpoints must have the same dimensions (i.e., L = M = N). mask (boolean array, dim LxMxN, optional): Specifies the points in the rectangular grid defined by xpoints, ypoints, zpoints 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. Default is 'vectorized'. Outputs: kvalues (numpy array, dim LxMxN or dim Nx1): Interpolated values of specified grid or at the specified set of points. If style was specified as 'masked', kvalues will be a numpy masked array. sigmasq (numpy array, dim LxMxN 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))) zpts = np.atleast_1d(np.squeeze(np.array(zpoints, copy=True))) n = self.X_ADJUSTED.shape[0] nx = xpts.size ny = ypts.size nz = zpts.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.ndim != 3: raise ValueError("Mask is not three-dimensional.") if mask.shape[0] != nz or mask.shape[1] != ny or mask.shape[ 2] != nx: if mask.shape[0] == nx and mask.shape[ 2] == nz and mask.shape[1] == ny: mask = mask.swapaxes(0, 2) else: raise ValueError( "Mask dimensions do not match specified grid dimensions." ) mask = mask.flatten() npt = nz * ny * nx grid_z, grid_y, grid_x = np.meshgrid(zpts, ypts, xpts, indexing='ij') xpts = grid_x.flatten() ypts = grid_y.flatten() zpts = grid_z.flatten() elif style == 'points': if xpts.size != ypts.size and ypts.size != zpts.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, zpts = core.adjust_for_anisotropy_3d( xpts, ypts, zpts, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) if style != 'masked': mask = np.zeros(npt, dtype='bool') xyz_points = np.concatenate( (zpts[:, np.newaxis], ypts[:, np.newaxis], xpts[:, np.newaxis]), axis=1) xyz_data = np.concatenate( (self.Z_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis], self.X_ADJUSTED[:, np.newaxis]), axis=1) bd = cdist(xyz_points, xyz_data, 'euclidean') if backend == 'vectorized': kvalues, sigmasq = self._exec_vector(a, bd, mask) elif backend == 'loop': kvalues, sigmasq = self._exec_loop(a, bd, mask) else: raise ValueError( 'Specified backend {} is not supported for 3D ordinary kriging.' .format(backend)) if style == 'masked': kvalues = np.ma.array(kvalues, mask=mask) sigmasq = np.ma.array(sigmasq, mask=mask) if style in ['masked', 'grid']: kvalues = kvalues.reshape((nz, ny, nx)) sigmasq = sigmasq.reshape((nz, ny, nx)) return kvalues, sigmasq
def __init__(self, x, y, z, val, variogram_model='linear', variogram_parameters=None, variogram_function=None, nlags=6, weight=False, anisotropy_scaling_y=1.0, anisotropy_scaling_z=1.0, anisotropy_angle_x=0.0, anisotropy_angle_y=0.0, anisotropy_angle_z=0.0, verbose=False, enable_plotting=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_ORIG = np.atleast_1d(np.squeeze(np.array(z, copy=True))) self.VALUES = np.atleast_1d(np.squeeze(np.array(val, 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.ZCENTER = (np.amax(self.Z_ORIG) + np.amin(self.Z_ORIG)) / 2.0 self.anisotropy_scaling_y = anisotropy_scaling_y self.anisotropy_scaling_z = anisotropy_scaling_z self.anisotropy_angle_x = anisotropy_angle_x self.anisotropy_angle_y = anisotropy_angle_y self.anisotropy_angle_z = anisotropy_angle_z if self.verbose: print "Adjusting data for anisotropy..." self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED = \ core.adjust_for_anisotropy_3d(np.copy(self.X_ORIG), np.copy(self.Y_ORIG), np.copy(self.Z_ORIG), self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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_3d( self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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'
def update_variogram_model(self, variogram_model, variogram_parameters=None, variogram_function=None, nlags=6, weight=False, anisotropy_scaling_y=1.0, anisotropy_scaling_z=1.0, anisotropy_angle_x=0.0, anisotropy_angle_y=0.0, anisotropy_angle_z=0.0): """Allows user to update variogram type and/or variogram model parameters.""" if anisotropy_scaling_y != self.anisotropy_scaling_y or anisotropy_scaling_z != self.anisotropy_scaling_z or \ anisotropy_angle_x != self.anisotropy_angle_x or anisotropy_angle_y != self.anisotropy_angle_y or \ anisotropy_angle_z != self.anisotropy_angle_z: if self.verbose: print "Adjusting data for anisotropy..." self.anisotropy_scaling_y = anisotropy_scaling_y self.anisotropy_scaling_z = anisotropy_scaling_z self.anisotropy_angle_x = anisotropy_angle_x self.anisotropy_angle_y = anisotropy_angle_y self.anisotropy_angle_z = anisotropy_angle_z self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED = \ core.adjust_for_anisotropy_3d(np.copy(self.X_ORIG), np.copy(self.Y_ORIG), np.copy(self.Z_ORIG), self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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_3d( self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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'
def update_variogram_model(self, variogram_model, variogram_parameters=None, variogram_function=None, nlags=6, weight=False, anisotropy_scaling_y=1.0, anisotropy_scaling_z=1.0, anisotropy_angle_x=0.0, anisotropy_angle_y=0.0, anisotropy_angle_z=0.0): """Allows user to update variogram type and/or variogram model parameters.""" if anisotropy_scaling_y != self.anisotropy_scaling_y or anisotropy_scaling_z != self.anisotropy_scaling_z or \ anisotropy_angle_x != self.anisotropy_angle_x or anisotropy_angle_y != self.anisotropy_angle_y or \ anisotropy_angle_z != self.anisotropy_angle_z: if self.verbose: print "Adjusting data for anisotropy..." self.anisotropy_scaling_y = anisotropy_scaling_y self.anisotropy_scaling_z = anisotropy_scaling_z self.anisotropy_angle_x = anisotropy_angle_x self.anisotropy_angle_y = anisotropy_angle_y self.anisotropy_angle_z = anisotropy_angle_z self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED = \ core.adjust_for_anisotropy_3d(np.copy(self.X_ORIG), np.copy(self.Y_ORIG), np.copy(self.Z_ORIG), self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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'
def execute(self, style, xpoints, ypoints, zpoints, mask=None, backend='vectorized', specified_drift_arrays=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, ypoints, and zpoints as arrays of x, y, and z coordinates that define a rectangular grid. Specifying 'points' treats xpoints, ypoints, and zpoints as arrays that provide coordinates at which to solve the kriging system. Specifying 'masked' treats xpoints, ypoints, and zpoints as arrays of x, y, and z 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 MxNxL 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 LxMxN grid. If style is specified as 'points', y-coordinates of specific points at which to solve kriging system. Note that in this case, xpoints, ypoints, and zpoints must have the same dimensions (i.e., L = M = N). zpoints (array-like, dim L): If style is specified as 'grid' or 'masked', z-coordinates of LxMxN grid. If style is specified as 'points', z-coordinates of specific points at which to solve kriging system. Note that in this case, xpoints, ypoints, and zpoints must have the same dimensions (i.e., L = M = N). mask (boolean array, dim LxMxN, optional): Specifies the points in the rectangular grid defined by xpoints, ypoints, zpoints 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. Default is 'vectorized'. 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 UniversalKriging3D 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 dim LxMxN, where L is the number of z grid-points, M is the number of y grid-points, and N is the number of x grid-points, or dim N, where N is the number of points at which to evaluate the kriging system. Outputs: kvalues (numpy array, dim LxMxN or dim N): Interpolated values of specified grid or at the specified set of points. If style was specified as 'masked', kvalues will be a numpy masked array. sigmasq (numpy array, dim LxMxN or dim N): 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))) zpts = np.atleast_1d(np.squeeze(np.array(zpoints, copy=True))) n = self.X_ADJUSTED.shape[0] n_withdrifts = n if self.regional_linear_drift: n_withdrifts += 3 if self.specified_drift: n_withdrifts += len(self.specified_drift_data_arrays) if self.functional_drift: n_withdrifts += len(self.functional_drift_terms) nx = xpts.size ny = ypts.size nz = zpts.size 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.ndim != 3: raise ValueError("Mask is not three-dimensional.") if mask.shape[0] != nz or mask.shape[1] != ny or mask.shape[2] != nx: if mask.shape[0] == nx and mask.shape[2] == nz and mask.shape[1] == ny: mask = mask.swapaxes(0, 2) else: raise ValueError("Mask dimensions do not match specified grid dimensions.") mask = mask.flatten() npt = nz * ny * nx grid_z, grid_y, grid_x = np.meshgrid(zpts, ypts, xpts, indexing='ij') xpts = grid_x.flatten() ypts = grid_y.flatten() zpts = grid_z.flatten() elif style == 'points': if xpts.size != ypts.size and ypts.size != zpts.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 < 3: raise ValueError("Dimensions of drift values array do not match specified grid dimensions.") elif spec.shape[0] != nz or spec.shape[1] != ny or spec.shape[2] != nx: if spec.shape[0] == nx and spec.shape[2] == nz and spec.shape[1] == ny: spec_drift_grids.append(np.squeeze(spec.swapaxes(0, 2))) 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: print "WARNING: Provided specified drift values, but 'specified' drift was not initialized during " \ "instantiation of UniversalKriging3D class." xpts, ypts, zpts = core.adjust_for_anisotropy_3d(xpts, ypts, zpts, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) if style != 'masked': mask = np.zeros(npt, dtype='bool') xyz_points = np.concatenate((zpts[:, np.newaxis], ypts[:, np.newaxis], xpts[:, np.newaxis]), axis=1) xyz_data = np.concatenate((self.Z_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis], self.X_ADJUSTED[:, np.newaxis]), axis=1) bd = cdist(xyz_points, xyz_data, 'euclidean') if backend == 'vectorized': kvalues, sigmasq = self._exec_vector(a, bd, xyz_points, mask, n_withdrifts, spec_drift_grids) elif backend == 'loop': kvalues, sigmasq = self._exec_loop(a, bd, xyz_points, mask, n_withdrifts, spec_drift_grids) else: raise ValueError('Specified backend {} is not supported for 3D ordinary kriging.'.format(backend)) if style == 'masked': kvalues = np.ma.array(kvalues, mask=mask) sigmasq = np.ma.array(sigmasq, mask=mask) if style in ['masked', 'grid']: kvalues = kvalues.reshape((nz, ny, nx)) sigmasq = sigmasq.reshape((nz, ny, nx)) return kvalues, sigmasq
def __init__(self, x, y, z, val, variogram_model='linear', variogram_parameters=None, variogram_function=None, nlags=6, weight=False, anisotropy_scaling_y=1.0, anisotropy_scaling_z=1.0, anisotropy_angle_x=0.0, anisotropy_angle_y=0.0, anisotropy_angle_z=0.0, drift_terms=None, specified_drift=None, functional_drift=None, verbose=False, enable_plotting=False): # Deal with mutable default argument if drift_terms is None: drift_terms = [] if specified_drift is None: specified_drift = [] if functional_drift is None: functional_drift = [] # 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_ORIG = np.atleast_1d(np.squeeze(np.array(z, copy=True))) self.VALUES = np.atleast_1d(np.squeeze(np.array(val, 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.ZCENTER = (np.amax(self.Z_ORIG) + np.amin(self.Z_ORIG))/2.0 self.anisotropy_scaling_y = anisotropy_scaling_y self.anisotropy_scaling_z = anisotropy_scaling_z self.anisotropy_angle_x = anisotropy_angle_x self.anisotropy_angle_y = anisotropy_angle_y self.anisotropy_angle_z = anisotropy_angle_z if self.verbose: print "Adjusting data for anisotropy..." self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED = \ core.adjust_for_anisotropy_3d(np.copy(self.X_ORIG), np.copy(self.Y_ORIG), np.copy(self.Z_ORIG), self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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..." # Note that the regional linear drift values will be based on the adjusted coordinate system. # Really, it doesn't actually matter which coordinate system is used here. 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 'specified' in drift_terms: if type(specified_drift) is not list: raise TypeError("Arrays for specified drift terms must be encapsulated in a list.") if len(specified_drift) == 0: raise ValueError("Must provide at least one drift-value array when using the " "'specified' drift capability.") self.specified_drift = True self.specified_drift_data_arrays = [] for term in specified_drift: specified = np.squeeze(np.array(term, copy=True)) if specified.size != self.X_ORIG.size: raise ValueError("Must specify the drift values for each data point when using the " "'specified' drift capability.") self.specified_drift_data_arrays.append(specified) else: self.specified_drift = False # The provided callable functions will be evaluated using the adjusted coordinates. if 'functional' in drift_terms: if type(functional_drift) is not list: raise TypeError("Callables for functional drift terms must be encapsulated in a list.") if len(functional_drift) == 0: raise ValueError("Must provide at least one callable object when using the " "'functional' drift capability.") self.functional_drift = True self.functional_drift_terms = functional_drift else: self.functional_drift = False
def _exec_loop(self, style, xpoints, ypoints, zpoints, mask): """Solves the kriging system by looping over all specified points. Less memory-intensive, but involves a Python-level loop.""" nx = xpoints.shape[0] ny = ypoints.shape[0] nz = zpoints.shape[0] n = self.X_ADJUSTED.shape[0] a_inv = scipy.linalg.inv(self._get_kriging_matrix(n)) if style == 'grid': kvalues = np.zeros((nz, ny, nx)) sigmasq = np.zeros((nz, ny, nx)) grid_z, grid_y, grid_x = np.meshgrid(zpoints, ypoints, xpoints, indexing='ij') grid_x, grid_y, grid_z = core.adjust_for_anisotropy_3d(grid_x, grid_y, grid_z, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) for i in range(nz): for j in range(ny): for k in range(nx): bd = np.sqrt((self.X_ADJUSTED - grid_x[i, j, k])**2 + (self.Y_ADJUSTED - grid_y[i, j, k])**2 + (self.Z_ADJUSTED - grid_z[i, j, k])**2) if np.any(np.absolute(bd) <= self.eps): zero_value = True zero_index = np.where(np.absolute(bd) <= self.eps) else: zero_value = False zero_index = None b = np.zeros((n+1, 1)) b[:n, 0] = - self.variogram_function(self.variogram_model_parameters, bd) if zero_value: b[zero_index[0], 0] = 0.0 b[n, 0] = 1.0 x = np.dot(a_inv, b) kvalues[i, j, k] = np.sum(x[:n, 0] * self.VALUES) sigmasq[i, j, k] = np.sum(x[:, 0] * -b[:, 0]) elif style == 'masked': if mask is None: raise IOError("Must specify boolean masking array.") if mask.shape[0] != nz or mask.shape[1] != ny or mask.shape[2] != nx: if mask.shape[0] == nx and mask.shape[2] == nz: mask = mask.T else: raise ValueError("Mask dimensions do not match specified grid dimensions.") kvalues = np.zeros((nz, ny, nx)) sigmasq = np.zeros((nz, ny, nx)) grid_z, grid_y, grid_x = np.meshgrid(zpoints, ypoints, xpoints, indexing='ij') grid_x, grid_y, grid_z = core.adjust_for_anisotropy_3d(grid_x, grid_y, grid_z, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) for i in range(nz): for j in range(ny): for k in range(nx): if not mask[i, j, k]: bd = np.sqrt((self.X_ADJUSTED - grid_x[i, j, k])**2 + (self.Y_ADJUSTED - grid_y[i, j, k])**2 + (self.Z_ADJUSTED - grid_z[i, j, k])**2) if np.any(np.absolute(bd) <= self.eps): zero_value = True zero_index = np.where(np.absolute(bd) <= self.eps) else: zero_value = False zero_index = None b = np.zeros((n+1, 1)) b[:n, 0] = - self.variogram_function(self.variogram_model_parameters, bd) if zero_value: b[zero_index[0], 0] = 0.0 b[n, 0] = 1.0 x = np.dot(a_inv, b) kvalues[i, j, k] = np.sum(x[:n, 0] * self.VALUES) sigmasq[i, j, k] = np.sum(x[:, 0] * -b[:, 0]) kvalues = np.ma.array(kvalues, mask=mask) sigmasq = np.ma.array(sigmasq, mask=mask) elif style == 'points': if xpoints.shape != ypoints.shape or ypoints.shape != zpoints.shape or xpoints.shape != zpoints.shape: raise ValueError("xpoints, ypoints, zpoints must have same dimensions " "when treated as listing discrete points.") kvalues = np.zeros(nx) sigmasq = np.zeros(nx) xpoints, ypoints, zpoints = core.adjust_for_anisotropy_3d(xpoints, ypoints, zpoints, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) for j in range(nx): bd = np.sqrt((self.X_ADJUSTED - xpoints[j])**2 + (self.Y_ADJUSTED - ypoints[j])**2 + (self.Z_ADJUSTED - zpoints[j])**2) if np.any(np.absolute(bd) <= self.eps): zero_value = True zero_index = np.where(np.absolute(bd) <= self.eps) else: zero_value = False zero_index = None b = np.zeros((n+1, 1)) b[:n, 0] = - self.variogram_function(self.variogram_model_parameters, bd) if zero_value: b[zero_index[0], 0] = 0.0 b[n, 0] = 1.0 x = np.dot(a_inv, b) kvalues[j] = np.sum(x[:n, 0] * self.VALUES) sigmasq[j] = np.sum(x[:, 0] * -b[:, 0]) else: raise ValueError("style argument must be 'grid', 'points', or 'masked'") return kvalues, sigmasq
def _exec_vector(self, style, xpoints, ypoints, zpoints, mask): """Solves the kriging system as a vectorized operation. This method can take a lot of memory for large grids and/or large datasets.""" nx = xpoints.shape[0] ny = ypoints.shape[0] nz = zpoints.shape[0] n = self.X_ADJUSTED.shape[0] zero_index = None zero_value = False a_inv = scipy.linalg.inv(self._get_kriging_matrix(n)) if style == 'grid': grid_z, grid_y, grid_x = np.meshgrid(zpoints, ypoints, xpoints, indexing='ij') grid_x, grid_y, grid_z = core.adjust_for_anisotropy_3d(grid_x, grid_y, grid_z, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) bd = cdist(np.concatenate((grid_z[:, :, :, np.newaxis], grid_y[:, :, :, np.newaxis], grid_x[:, :, :, np.newaxis]), axis=3).reshape((nx*ny*nz, 3)), np.concatenate((self.Z_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis], self.X_ADJUSTED[:, np.newaxis]), axis=1), 'euclidean').reshape((nz, ny, nx, n)) if np.any(np.absolute(bd) <= self.eps): zero_value = True zero_index = np.where(np.absolute(bd) <= self.eps) b = np.zeros((nz, 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], zero_index[3], 0] = 0.0 b[:, :, :, n, 0] = 1.0 x = np.dot(a_inv, b.reshape((nx*ny*nz, n+1)).T).reshape((1, n+1, nz, ny, nx)).T.swapaxes(0, 2) kvalues = np.sum(x[:, :, :, :n, 0] * self.VALUES, axis=3) sigmasq = np.sum(x[:, :, :, :, 0] * -b[:, :, :, :, 0], axis=3) elif style == 'masked': if mask is None: raise IOError("Must specify boolean masking array.") if mask.shape[0] != nz or mask.shape[1] != ny or mask.shape[2] != nx: if mask.shape[0] == nx and mask.shape[2] == nz: mask = mask.T else: raise ValueError("Mask dimensions do not match specified grid dimensions.") grid_z, grid_y, grid_x = np.meshgrid(zpoints, ypoints, xpoints, indexing='ij') grid_x, grid_y, grid_z = core.adjust_for_anisotropy_3d(grid_x, grid_y, grid_z, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) bd = cdist(np.concatenate((grid_z[:, :, :, np.newaxis], grid_x[:, :, :, np.newaxis], grid_y[:, :, :, np.newaxis]), axis=3).reshape((nx*ny*nz, 3)), np.concatenate((self.Z_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis], self.X_ADJUSTED[:, np.newaxis]), axis=1), 'euclidean').reshape((nz, ny, nx, n)) if np.any(np.absolute(bd) <= self.eps): zero_value = True zero_index = np.where(np.absolute(bd) <= self.eps) b = np.zeros((nz, 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], zero_index[3], 0] = 0.0 b[:, :, :, n, 0] = 1.0 mask_b = np.repeat(mask[:, :, :, np.newaxis, np.newaxis], n+1, axis=3) b = np.ma.array(b, mask=mask_b) x = np.dot(a_inv, b.reshape((nz*nx*ny, n+1)).T).reshape((1, n+1, nz, ny, nx)).T.swapaxes(0, 2) kvalues = np.sum(x[:, :, :, :n, 0] * self.VALUES, axis=3) sigmasq = np.sum(x[:, :, :, :, 0] * -b[:, :, :, 0], axis=3) elif style == 'points': if xpoints.shape != ypoints.shape or ypoints.shape != zpoints.shape or xpoints.shape != zpoints.shape: raise ValueError("xpoints, ypoints, zpoints must have same dimensions " "when treated as listing discrete points.") xpoints, ypoints, zpoints = core.adjust_for_anisotropy_3d(xpoints, ypoints, zpoints, self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) bd = cdist(np.concatenate((xpoints[:, np.newaxis], ypoints[:, np.newaxis], zpoints[:, np.newaxis]), axis=1), np.concatenate((self.X_ADJUSTED[:, np.newaxis], self.Y_ADJUSTED[:, np.newaxis], self.Z_ADJUSTED[:, np.newaxis]), axis=1), 'euclidean') if np.any(np.absolute(bd) <= self.eps): zero_value = True zero_index = np.where(np.absolute(bd) <= self.eps) 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.dot(a_inv, b.reshape((nx, n+1)).T).reshape((1, n+1, nx)).T kvalues = np.sum(x[:, :n, 0] * self.VALUES, axis=1) sigmasq = np.sum(x[:, :, 0] * -b[:, :, 0], axis=1) else: raise ValueError("style argument must be 'grid', 'points', or 'masked'") return kvalues, sigmasq
def __init__(self, x, y, z, val, variogram_model='linear', variogram_parameters=None, variogram_function=None, nlags=6, weight=False, anisotropy_scaling_y=1.0, anisotropy_scaling_z=1.0, anisotropy_angle_x=0.0, anisotropy_angle_y=0.0, anisotropy_angle_z=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_ORIG = np.array(z, copy=True).flatten() self.VALUES = np.array(val, 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.ZCENTER = (np.amax(self.Z_ORIG) + np.amin(self.Z_ORIG))/2.0 self.anisotropy_scaling_y = anisotropy_scaling_y self.anisotropy_scaling_z = anisotropy_scaling_z self.anisotropy_angle_x = anisotropy_angle_x self.anisotropy_angle_y = anisotropy_angle_y self.anisotropy_angle_z = anisotropy_angle_z if self.verbose: print "Adjusting data for anisotropy..." self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED = \ core.adjust_for_anisotropy_3d(np.copy(self.X_ORIG), np.copy(self.Y_ORIG), np.copy(self.Z_ORIG), self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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'
def __init__(self, x, y, z, val, variogram_model='linear', variogram_parameters=None, variogram_function=None, nlags=6, weight=False, anisotropy_scaling_y=1.0, anisotropy_scaling_z=1.0, anisotropy_angle_x=0.0, anisotropy_angle_y=0.0, anisotropy_angle_z=0.0, drift_terms=None, specified_drift=None, functional_drift=None, verbose=False, enable_plotting=False): # Deal with mutable default argument if drift_terms is None: drift_terms = [] if specified_drift is None: specified_drift = [] if functional_drift is None: functional_drift = [] # 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_ORIG = np.atleast_1d(np.squeeze(np.array(z, copy=True))) self.VALUES = np.atleast_1d(np.squeeze(np.array(val, 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.ZCENTER = (np.amax(self.Z_ORIG) + np.amin(self.Z_ORIG)) / 2.0 self.anisotropy_scaling_y = anisotropy_scaling_y self.anisotropy_scaling_z = anisotropy_scaling_z self.anisotropy_angle_x = anisotropy_angle_x self.anisotropy_angle_y = anisotropy_angle_y self.anisotropy_angle_z = anisotropy_angle_z if self.verbose: print "Adjusting data for anisotropy..." self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED = \ core.adjust_for_anisotropy_3d(np.copy(self.X_ORIG), np.copy(self.Y_ORIG), np.copy(self.Z_ORIG), self.XCENTER, self.YCENTER, self.ZCENTER, self.anisotropy_scaling_y, self.anisotropy_scaling_z, self.anisotropy_angle_x, self.anisotropy_angle_y, self.anisotropy_angle_z) 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_3d(self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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_3d( self.X_ADJUSTED, self.Y_ADJUSTED, self.Z_ADJUSTED, self.VALUES, 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..." # Note that the regional linear drift values will be based on the adjusted coordinate system. # Really, it doesn't actually matter which coordinate system is used here. 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 'specified' in drift_terms: if type(specified_drift) is not list: raise TypeError( "Arrays for specified drift terms must be encapsulated in a list." ) if len(specified_drift) == 0: raise ValueError( "Must provide at least one drift-value array when using the " "'specified' drift capability.") self.specified_drift = True self.specified_drift_data_arrays = [] for term in specified_drift: specified = np.squeeze(np.array(term, copy=True)) if specified.size != self.X_ORIG.size: raise ValueError( "Must specify the drift values for each data point when using the " "'specified' drift capability.") self.specified_drift_data_arrays.append(specified) else: self.specified_drift = False # The provided callable functions will be evaluated using the adjusted coordinates. if 'functional' in drift_terms: if type(functional_drift) is not list: raise TypeError( "Callables for functional drift terms must be encapsulated in a list." ) if len(functional_drift) == 0: raise ValueError( "Must provide at least one callable object when using the " "'functional' drift capability.") self.functional_drift = True self.functional_drift_terms = functional_drift else: self.functional_drift = False