Ejemplo n.º 1
0
def vtk_export_unstructured(filename, pos, fields):  # pragma: no cover
    """Export a field to vtk structured rectilinear grid file.

    Parameters
    ----------
    filename : :class:`str`
        Filename of the file to be saved, including the path. Note that an
        ending (.vtu) will be added to the name.
    pos : :class:`list`
        the position tuple, containing main direction and transversal
        directions
    fields : :class:`dict` or :class:`numpy.ndarray`
        Unstructured fields to be saved.
        Either a single numpy array as returned by SRF,
        or a dictionary of fields with theirs names as keys.
    """
    if not isinstance(fields, dict):
        fields = {"field": fields}
    x, y, z = pos2xyz(pos)
    if y is None:
        y = np.zeros_like(x)
    if z is None:
        z = np.zeros_like(x)
    for field in fields:
        fields[field] = fields[field].reshape(-1)
        if (len(fields[field]) != len(x) or len(fields[field]) != len(y)
                or len(fields[field]) != len(z)):
            raise ValueError("gstools.vtk_export_unstructured: " +
                             "field shape doesn't match the given mesh")
    pointsToVTK(filename, x, y, z, data=fields)
Ejemplo n.º 2
0
 def _get_iso_rad(self, pos):
     x, y, z = pos2xyz(pos, max_dim=self.dim)
     if self.do_rotation:
         x, y, z = unrotate_mesh(self.dim, self.angles, x, y, z)
     if not self.is_isotropic:
         y, z = make_isotropic(self.dim, self.anis, y, z)
     return np.linalg.norm((x, y, z)[:self.dim], axis=0)
Ejemplo n.º 3
0
def eval_func(func, pos, mesh_type="structured"):
    """
    Evaluate a function on a mesh.

    Parameters
    ----------
    func : :any:`callable`
        The function to be called. Should have the signiture f(x, [y, z])
    pos : :class:`list`
        the position tuple, containing main direction and transversal
        directions (x, [y, z])
    mesh_type : :class:`str`, optional
        'structured' / 'unstructured'

    Returns
    -------
    :class:`numpy.ndarray`
        Function values at the given points.
    """
    x, y, z, dim = pos2xyz(pos, calc_dim=True)
    if mesh_type == "structured":
        x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(dim, x, y, z)
    res = func(*[x, y, z][:dim])
    if mesh_type == "structured":
        res = reshape_field_from_unstruct_to_struct(dim, res, axis_lens)
    return res
Ejemplo n.º 4
0
def vario_estimate_unstructured(pos,
                                field,
                                bin_edges,
                                sampling_size=None,
                                sampling_seed=None):
    r"""
    Estimates the variogram on a unstructured grid.

    The algorithm calculates following equation:

    .. math::
       \gamma(r_k) = \frac{1}{2 N} \sum_{i=1}^N (z(\mathbf x_i) -
       z(\mathbf x_i'))^2, \; \mathrm{ with}

       r_k \leq \| \mathbf x_i - \mathbf x_i' \| < r_{k+1}

    Notes
    -----
    Internally uses double precision and also returns doubles.

    Parameters
    ----------
    pos : :class:`list`
        the position tuple, containing main direction and transversal
        directions
    field : :class:`numpy.ndarray`
        the spatially distributed data
    bin_edges : :class:`numpy.ndarray`
        the bins on which the variogram will be calculated
    sampling_size : :class:`int` or :any:`None`, optional
        for large input data, this method can take a long
        time to compute the variogram, therefore this argument specifies
        the number of data points to sample randomly
        Default: :any:`None`
    sampling_seed : :class:`int` or :any:`None`, optional
        seed for samples if sampling_size is given.
        Default: :any:`None`

    Returns
    -------
    :class:`tuple` of :class:`numpy.ndarray`
        the estimated variogram and the bin centers
    """
    # TODO check_mesh
    field = np.array(field, ndmin=1, dtype=np.double)
    bin_edges = np.array(bin_edges, ndmin=1, dtype=np.double)
    x, y, z, dim = pos2xyz(pos, calc_dim=True, dtype=np.double)
    bin_centres = (bin_edges[:-1] + bin_edges[1:]) / 2.0

    if sampling_size is not None and sampling_size < len(field):
        sampled_idx = np.random.RandomState(sampling_seed).choice(
            np.arange(len(field)), sampling_size, replace=False)
        field = field[sampled_idx]
        x = x[sampled_idx]
        if dim > 1:
            y = y[sampled_idx]
        if dim > 2:
            z = z[sampled_idx]

    return bin_centres, unstructured(field, bin_edges, x, y, z)
Ejemplo n.º 5
0
def vtk_export_unstructured(filename, pos, field, fieldname="field"):
    """Export a field to vtk structured rectilinear grid file

    Parameters
    ----------
    filename : :class:`str`
        Filename of the file to be saved, including the path. Note that an
        ending (\*.vtr or \*.vtu) will be added to the name.
    pos : :class:`list`
        the position tuple, containing main direction and transversal
        directions
    field : :class:`numpy.ndarray`
        Unstructured field to be saved. As returned by SRF.
    fieldname : :class:`str`, optional
        Name of the field in the VTK file. Default: "field"
    """
    x, y, z = pos2xyz(pos)
    if y is None:
        y = np.zeros_like(x)
    if z is None:
        z = np.zeros_like(x)
    field = np.array(field).reshape(-1)
    if len(field) != len(x) or len(field) != len(y) or len(field) != len(z):
        raise ValueError("gstools.vtk_export_unstructured: " +
                         "field shape doesn't match the given mesh")
    pointsToVTK(filename, x, y, z, data={fieldname: field})
Ejemplo n.º 6
0
def set_condition(cond_pos, cond_val, max_dim=3):
    """Set the conditions for kriging.

    Parameters
    ----------
    cond_pos : :class:`list`
        the position tuple of the conditions (x, [y, z])
    cond_val : :class:`numpy.ndarray`
        the values of the conditions
    max_dim : :class:`int`, optional
        Cut of information above the given dimension. Default: 3

    Returns
    -------
    cond_pos : :class:`list`
        the error checked cond_pos
    cond_val : :class:`numpy.ndarray`
        the error checked cond_val
    """
    # convert the input for right shapes and dimension checks
    c_x, c_y, c_z = pos2xyz(cond_pos, dtype=np.double, max_dim=max_dim)
    cond_pos = xyz2pos(c_x, c_y, c_z)
    cond_val = np.array(cond_val, dtype=np.double).reshape(-1)
    if not all([len(cond_pos[i]) == len(cond_val) for i in range(max_dim)]):
        raise ValueError(
            "Please check your 'cond_pos' and 'cond_val' parameters. " +
            "The shapes do not match.")
    return cond_pos, cond_val
Ejemplo n.º 7
0
def vtk_export_structured(
    filename, pos, field, fieldname="field"
):  # pragma: no cover
    """Export a field to vtk structured rectilinear grid file.

    Parameters
    ----------
    filename : :class:`str`
        Filename of the file to be saved, including the path. Note that an
        ending (.vtr or .vtu) will be added to the name.
    pos : :class:`list`
        the position tuple, containing main direction and transversal
        directions
    field : :class:`numpy.ndarray`
        Structured field to be saved. As returned by SRF.
    fieldname : :class:`str`, optional
        Name of the field in the VTK file. Default: "field"
    """
    x, y, z = pos2xyz(pos)
    if y is None:
        y = np.array([0])
    if z is None:
        z = np.array([0])
    # need fortran order in VTK
    field = field.reshape(-1, order="F")
    if len(field) != len(x) * len(y) * len(z):
        raise ValueError(
            "gstools.vtk_export_structured: "
            + "field shape doesn't match the given mesh"
        )
    gridToVTK(filename, x, y, z, pointData={fieldname: field})
Ejemplo n.º 8
0
    def _pre_pos(self, pos, mesh_type="unstructured", make_unstruct=False):
        """
        Preprocessing positions and mesh_type.

        Parameters
        ----------
        pos : :any:`iterable`
            the position tuple, containing main direction and transversal
            directions
        mesh_type : :class:`str`
            'structured' / 'unstructured'
        make_unstruct: :class:`bool`
            State if mesh_type should be made unstructured.

        Returns
        -------
        x : :class:`numpy.ndarray`
            first components of unrotated and isotropic position vectors
        y : :class:`numpy.ndarray` or None
            analog to x
        z : :class:`numpy.ndarray` or None
            analog to x
        pos : :class:`tuple` of :class:`numpy.ndarray`
            the normalized position tuple
        mesh_type_gen : :class:`str`
            'structured' / 'unstructured' for the generator
        mesh_type_changed : :class:`bool`
            State if the mesh_type was changed.
        axis_lens : :class:`tuple` or :any:`None`
            axis lengths of the structured mesh if mesh type was changed.
        """
        x, y, z = pos2xyz(pos, max_dim=self.model.dim)
        pos = xyz2pos(x, y, z)
        mesh_type_gen = mesh_type
        # format the positional arguments of the mesh
        check_mesh(self.model.dim, x, y, z, mesh_type)
        mesh_type_changed = False
        axis_lens = None
        if (self.model.do_rotation
                or make_unstruct) and mesh_type == "structured":
            mesh_type_changed = True
            mesh_type_gen = "unstructured"
            x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(
                self.model.dim, x, y, z)
        if self.model.do_rotation:
            x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z)
        if not self.model.is_isotropic:
            y, z = make_isotropic(self.model.dim, self.model.anis, y, z)
        return x, y, z, pos, mesh_type_gen, mesh_type_changed, axis_lens
Ejemplo n.º 9
0
    def set_condition(self, cond_pos, cond_val):
        """Set the conditions for kriging.

        Parameters
        ----------
        cond_pos : :class:`list`
            the position tuple of the conditions (x, [y, z])
        cond_val : :class:`numpy.ndarray`
            the values of the conditions
        """
        self._c_x, self._c_y, self._c_z = pos2xyz(
            cond_pos, dtype=np.double, max_dim=self.model.dim
        )
        self._cond_pos = xyz2pos(self._c_x, self._c_y, self._c_z)
        self._cond_val = np.array(cond_val, dtype=np.double).reshape(-1)
Ejemplo n.º 10
0
def _vtk_unstructured_helper(pos, fields):
    if not isinstance(fields, dict):
        fields = {"field": fields}
    x, y, z = pos2xyz(pos)
    if y is None:
        y = np.zeros_like(x)
    if z is None:
        z = np.zeros_like(x)
    for field in fields:
        fields[field] = fields[field].reshape(-1)
        if (len(fields[field]) != len(x) or len(fields[field]) != len(y)
                or len(fields[field]) != len(z)):
            raise ValueError("gstools.vtk_export_unstructured: "
                             "field shape doesn't match the given mesh")
    return x, y, z, fields
Ejemplo n.º 11
0
def _vtk_structured_helper(pos, fields):
    """An internal helper to extract what is needed for the vtk rectilinear grid
    """
    if not isinstance(fields, dict):
        fields = {"field": fields}
    x, y, z = pos2xyz(pos)
    if y is None:
        y = np.array([0])
    if z is None:
        z = np.array([0])
    # need fortran order in VTK
    for field in fields:
        fields[field] = fields[field].reshape(-1, order="F")
        if len(fields[field]) != len(x) * len(y) * len(z):
            raise ValueError("gstools.vtk_export_structured: "
                             "field shape doesn't match the given mesh")
    return x, y, z, fields
Ejemplo n.º 12
0
def simple(srf):
    """Condition a given spatial random field with simple kriging.

    Parameters
    ----------
    srf : :any:`SRF`
        The spatial random field class containing all information

    Returns
    -------
    cond_field : :class:`numpy.ndarray`
        the conditioned field
    krige_field : :class:`numpy.ndarray`
        the kriged field
    err_field : :class:`numpy.ndarray`
        the error field to set the given random field to zero at the conditions
    krige_var : :class:`numpy.ndarray`
        the variance of the kriged field
    """
    if srf._value_type != "scalar":
        raise ValueError("Conditioned SRF: only scalar fields allowed.")
    krige_sk = Simple(
        model=srf.model,
        mean=srf.mean,
        cond_pos=srf.cond_pos,
        cond_val=srf.cond_val,
    )
    krige_field, krige_var = krige_sk(srf.pos, srf.mesh_type)

    # evaluate the field at the conditional points
    x, y, z = pos2xyz(srf.cond_pos, max_dim=srf.model.dim)
    if srf.model.do_rotation:
        x, y, z = unrotate_mesh(srf.model.dim, srf.model.angles, x, y, z)
    y, z = make_isotropic(srf.model.dim, srf.model.anis, y, z)
    err_data = srf.generator.__call__(x, y, z, "unstructured") + srf.mean

    err_sk = Simple(
        model=srf.model,
        mean=srf.mean,
        cond_pos=srf.cond_pos,
        cond_val=err_data,
    )
    err_field, __ = err_sk(srf.pos, srf.mesh_type)
    cond_field = srf.raw_field + krige_field - err_field + srf.mean
    info = {}
    return cond_field, krige_field, err_field, krige_var, info
Ejemplo n.º 13
0
def ordinary(srf):
    """Condition a given spatial random field with ordinary kriging.

    Parameters
    ----------
    srf : :any:`SRF`
        The spatial random field class containing all information

    Returns
    -------
    cond_field : :class:`numpy.ndarray`
        the conditioned field
    krige_field : :class:`numpy.ndarray`
        the kriged field
    err_field : :class:`numpy.ndarray`
        the error field to set the given random field to zero at the conditions
    krige_var : :class:`numpy.ndarray`
        the variance of the kriged field
    """
    krige_ok = Ordinary(model=srf.model,
                        cond_pos=srf.cond_pos,
                        cond_val=srf.cond_val)
    krige_field, krige_var = krige_ok(srf.pos, srf.mesh_type)

    # evaluate the field at the conditional points
    x, y, z = pos2xyz(srf.cond_pos, max_dim=srf.model.dim)
    if srf.model.do_rotation:
        x, y, z = unrotate_mesh(srf.model.dim, srf.model.angles, x, y, z)
    y, z = make_isotropic(srf.model.dim, srf.model.anis, y, z)
    err_data = srf.generator.__call__(x, y, z, "unstructured")

    err_ok = Ordinary(model=srf.model,
                      cond_pos=srf.cond_pos,
                      cond_val=err_data)
    err_field, __ = err_ok(srf.pos, srf.mesh_type)
    cond_field = srf.raw_field + krige_field - err_field
    info = {"mean": krige_ok.mean}
    return cond_field, krige_field, err_field, krige_var, info
Ejemplo n.º 14
0
 def _get_krige_vecs(self, pos, chunk_slice=(0, None), ext_drift=None):
     """Calculate the RHS of the kriging equation."""
     chunk_size = len(pos[0]) if chunk_slice[1] is None else chunk_slice[1]
     chunk_size -= chunk_slice[0]
     size = self.cond_no + int(self.unbiased) + self.drift_no
     res = np.empty((size, chunk_size), dtype=np.double)
     res[:self.cond_no, :] = self.model.vario_nugget(
         self._get_dists(self._krige_pos, pos, chunk_slice))
     if self.unbiased:
         res[self.cond_no, :] = 1
     # trend function need the anisotropic and rotated positions
     if not self.model.is_isotropic:
         x, y, z = pos2xyz(pos, max_dim=self.model.dim)
         y, z = make_anisotropic(self.model.dim, self.model.anis, y, z)
         if self.model.do_rotation:
             x, y, z = rotate_mesh(self.model.dim, self.model.angles, x, y,
                                   z)
         pos = xyz2pos(x, y, z, max_dim=self.model.dim)
     chunk_pos = list(pos[:self.model.dim])
     for i in range(self.model.dim):
         chunk_pos[i] = chunk_pos[i][slice(*chunk_slice)]
     for i, f in enumerate(self.drift_functions):
         res[-self.drift_no + i, :] = f(*chunk_pos)
     return res
Ejemplo n.º 15
0
    def __call__(
        self, pos, seed=np.nan, point_volumes=0.0, mesh_type="unstructured"
    ):
        """Generate the spatial random field.

        The field is saved as `self.field` and is also returned.

        Parameters
        ----------
        pos : :class:`list`
            the position tuple, containing main direction and transversal
            directions
        seed : :class:`int`, optional
            seed for RNG for reseting. Default: keep seed from generator
        point_volumes : :class:`float` or :class:`numpy.ndarray`
            If your evaluation points for the field are coming from a mesh,
            they are probably representing a certain element volume.
            This volume can be passed by `point_volumes` to apply the
            given variance upscaling. If `point_volumes` is ``0`` nothing
            is changed. Default: ``0``
        mesh_type : :class:`str`
            'structured' / 'unstructured'

        Returns
        -------
        field : :class:`numpy.ndarray`
            the SRF
        """
        # internal conversation
        x, y, z = pos2xyz(pos, max_dim=self.model.dim)
        self.pos = xyz2pos(x, y, z)
        self.mesh_type = mesh_type
        # update the model/seed in the generator if any changes were made
        self.generator.update(self.model, seed)
        # format the positional arguments of the mesh
        check_mesh(self.model.dim, x, y, z, mesh_type)
        mesh_type_changed = False
        if self.model.do_rotation:
            if mesh_type == "structured":
                mesh_type_changed = True
                mesh_type_old = mesh_type
                mesh_type = "unstructured"
                x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(
                    self.model.dim, x, y, z
                )
            x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z)
        y, z = make_isotropic(self.model.dim, self.model.anis, y, z)

        # generate the field
        self.raw_field = self.generator.__call__(x, y, z, mesh_type)

        # reshape field if we got an unstructured mesh
        if mesh_type_changed:
            mesh_type = mesh_type_old
            self.raw_field = reshape_field_from_unstruct_to_struct(
                self.model.dim, self.raw_field, axis_lens
            )

        # apply given conditions to the field
        if self.condition:
            (
                cond_field,
                krige_field,
                err_field,
                krigevar,
                info,
            ) = self.cond_func(self)
            # store everything in the class
            self.field = cond_field
            self.krige_field = krige_field
            self.err_field = err_field
            self.krige_var = krigevar
            if "mean" in info:  # ordinary krging estimates mean
                self.mean = info["mean"]
        else:
            self.field = self.raw_field + self.mean

        # upscaled variance
        if not np.isscalar(point_volumes) or not np.isclose(point_volumes, 0):
            scaled_var = self.upscaling_func(self.model, point_volumes)
            self.field -= self.mean
            self.field *= np.sqrt(scaled_var / self.model.sill)
            self.field += self.mean

        return self.field
Ejemplo n.º 16
0
    def __call__(self, pos, mesh_type="unstructured"):
        """
        Generate the ordinary kriging field.

        The field is saved as `self.field` and is also returned.

        Parameters
        ----------
        pos : :class:`list`
            the position tuple, containing main direction and transversal
            directions (x, [y, z])
        mesh_type : :class:`str`
            'structured' / 'unstructured'

        Returns
        -------
        field : :class:`numpy.ndarray`
            the kriged field
        krige_var : :class:`numpy.ndarray`
            the kriging error variance
        """
        # internal conversation
        x, y, z = pos2xyz(pos, dtype=np.double, max_dim=self.model.dim)
        c_x, c_y, c_z = pos2xyz(self.cond_pos,
                                dtype=np.double,
                                max_dim=self.model.dim)
        self.pos = xyz2pos(x, y, z)
        self.mesh_type = mesh_type
        # format the positional arguments of the mesh
        check_mesh(self.model.dim, x, y, z, mesh_type)
        mesh_type_changed = False
        if mesh_type == "structured":
            mesh_type_changed = True
            mesh_type_old = mesh_type
            mesh_type = "unstructured"
            x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(
                self.model.dim, x, y, z)
        if self.model.do_rotation:
            x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z)
            c_x, c_y, c_z = unrotate_mesh(self.model.dim, self.model.angles,
                                          c_x, c_y, c_z)
        y, z = make_isotropic(self.model.dim, self.model.anis, y, z)
        c_y, c_z = make_isotropic(self.model.dim, self.model.anis, c_y, c_z)

        # set condtions
        cond = np.concatenate((self.cond_val, [0]))
        krig_mat = inv(self._get_krig_mat((c_x, c_y, c_z), (c_x, c_y, c_z)))
        krig_vecs = self._get_vario_mat((c_x, c_y, c_z), (x, y, z), add=True)
        # generate the kriged field
        field, krige_var = krigesum(krig_mat, krig_vecs, cond)
        # calculate the estimated mean (kriging field at infinity)
        mean_est = np.concatenate((np.full_like(self.cond_val,
                                                self.model.sill), [1]))
        self.mean = np.einsum("i,ij,j", cond, krig_mat, mean_est)

        # reshape field if we got an unstructured mesh
        if mesh_type_changed:
            mesh_type = mesh_type_old
            field = reshape_field_from_unstruct_to_struct(
                self.model.dim, field, axis_lens)
            krige_var = reshape_field_from_unstruct_to_struct(
                self.model.dim, krige_var, axis_lens)
        # save the field
        self.krige_var = krige_var
        self.field = field
        return self.field, self.krige_var
Ejemplo n.º 17
0
    def __call__(
        self,
        pos,
        seed=np.nan,
        force_moments=False,
        point_volumes=0.0,
        mesh_type="unstructured",
    ):
        """Generate the spatial random field.

        Parameters
        ----------
        pos : :class:`list`
            the position tuple, containing main direction and transversal
            directions
        seed : :class:`int`, optional
            seed for RNG for reseting. Default: keep seed from generator
        force_moments : :class:`bool`
            Force the generator to exactly match mean and variance.
            Default: ``False``
        point_volumes : :class:`float` or :class:`numpy.ndarray`
            If your evaluation points for the field are coming from a mesh,
            they are probably representing a certain element volume.
            This volumes can be passed by `point_volumes` to apply the
            given variance upscaling. If `point_volumes` is ``0`` nothing
            is changed. Default: ``0``
        mesh_type : :class:`str`
            'structured' / 'unstructured'

        Returns
        -------
        field : :class:`numpy.ndarray`
            the SRF
        """
        # internal conversation
        x, y, z = pos2xyz(pos)
        # update the model/seed in the generator if any changes were made
        self.generator.update(self.model, seed)
        # format the positional arguments of the mesh
        check_mesh(self.model.dim, x, y, z, mesh_type)
        mesh_type_changed = False
        if self.do_rotation:
            if mesh_type == "structured":
                mesh_type_changed = True
                mesh_type_old = mesh_type
                mesh_type = "unstructured"
                x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(
                    self.model.dim, x, y, z)
            x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z)
        y, z = make_isotropic(self.model.dim, self.model.anis, y, z)
        x, y, z = reshape_input(x, y, z, mesh_type)

        # generate the field
        field = self.generator.__call__(x, y, z)

        # reshape field if we got an unstructured mesh
        if mesh_type_changed:
            mesh_type = mesh_type_old
            field = reshape_field_from_unstruct_to_struct(
                self.model.dim, field, axis_lens)

        # force variance and mean to be exactly as given (if wanted)
        if force_moments:
            var_in = np.var(field)
            mean_in = np.mean(field)
            rescale = np.sqrt(self.model.sill / var_in)
            field = rescale * (field - mean_in)

        # upscaled variance
        scaled_var = self.upscaling_func(self.model, point_volumes)

        # rescale and shift the field to the mean
        self.field = np.sqrt(scaled_var / self.model.sill) * field + self.mean

        return self.field
Ejemplo n.º 18
0
def vario_estimate_unstructured(
    pos,
    field,
    bin_edges,
    sampling_size=None,
    sampling_seed=None,
    estimator="matheron",
):
    r"""
    Estimates the variogram on a unstructured grid.

    The algorithm calculates following equation:

    .. math::
       \gamma(r_k) = \frac{1}{2 N(r_k)} \sum_{i=1}^{N(r_k)} (z(\mathbf x_i) -
       z(\mathbf x_i'))^2 \; ,

    with :math:`r_k \leq \| \mathbf x_i - \mathbf x_i' \| < r_{k+1}` being the bins.

    Or if the estimator "cressie" was chosen:

    .. math::
       \gamma(r_k) = \frac{\left(\frac{1}{N(r_k)} \sum_{i=1}^{N(r_k)}
       \left|z(\mathbf x_i) - z(\mathbf x_i')\right|^{0.5}\right)^4}
       {0.457 + 0.494 / N(r_k) + 0.045 / N^2(r_k)} \; ,

    with :math:`r_k \leq \| \mathbf x_i - \mathbf x_i' \| < r_{k+1}` being the bins.
    The Cressie estimator is more robust to outliers.

    Notes
    -----
    Internally uses double precision and also returns doubles.

    Parameters
    ----------
    pos : :class:`list`
        the position tuple, containing main direction and transversal
        directions
    field : :class:`numpy.ndarray`
        the spatially distributed data
    bin_edges : :class:`numpy.ndarray`
        the bins on which the variogram will be calculated
    sampling_size : :class:`int` or :any:`None`, optional
        for large input data, this method can take a long
        time to compute the variogram, therefore this argument specifies
        the number of data points to sample randomly
        Default: :any:`None`
    sampling_seed : :class:`int` or :any:`None`, optional
        seed for samples if sampling_size is given.
        Default: :any:`None`
    estimator : :class:`str`, optional
        the estimator function, possible choices:

            * "matheron": the standard method of moments of Matheron
            * "cressie": an estimator more robust to outliers

        Default: "matheron"

    Returns
    -------
    :class:`tuple` of :class:`numpy.ndarray`
        the estimated variogram and the bin centers
    """
    # TODO check_mesh
    field = np.array(field, ndmin=1, dtype=np.double)
    bin_edges = np.array(bin_edges, ndmin=1, dtype=np.double)
    x, y, z, dim = pos2xyz(pos, calc_dim=True, dtype=np.double)
    bin_centres = (bin_edges[:-1] + bin_edges[1:]) / 2.0

    if sampling_size is not None and sampling_size < len(field):
        sampled_idx = np.random.RandomState(sampling_seed).choice(
            np.arange(len(field)), sampling_size, replace=False)
        field = field[sampled_idx]
        x = x[sampled_idx]
        if dim > 1:
            y = y[sampled_idx]
        if dim > 2:
            z = z[sampled_idx]

    cython_estimator = _set_estimator(estimator)

    return (
        bin_centres,
        unstructured(field,
                     bin_edges,
                     x,
                     y,
                     z,
                     estimator_type=cython_estimator),
    )
Ejemplo n.º 19
0
    def __call__(self, pos, mesh_type="unstructured"):
        """
        Generate the simple kriging field.

        The field is saved as `self.field` and is also returned.

        Parameters
        ----------
        pos : :class:`list`
            the position tuple, containing main direction and transversal
            directions (x, [y, z])
        mesh_type : :class:`str`
            'structured' / 'unstructured'

        Returns
        -------
        field : :class:`numpy.ndarray`
            the kriged field
        krige_var : :class:`numpy.ndarray`
            the kriging error variance
        """
        # internal conversation
        x, y, z = pos2xyz(pos, dtype=np.double, max_dim=self.model.dim)
        c_x, c_y, c_z = pos2xyz(self.cond_pos,
                                dtype=np.double,
                                max_dim=self.model.dim)
        self.pos = xyz2pos(x, y, z)
        self.mesh_type = mesh_type
        # format the positional arguments of the mesh
        check_mesh(self.model.dim, x, y, z, mesh_type)
        mesh_type_changed = False
        if mesh_type == "structured":
            mesh_type_changed = True
            mesh_type_old = mesh_type
            mesh_type = "unstructured"
            x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(
                self.model.dim, x, y, z)
        if self.model.do_rotation:
            x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z)
            c_x, c_y, c_z = unrotate_mesh(self.model.dim, self.model.angles,
                                          c_x, c_y, c_z)
        y, z = make_isotropic(self.model.dim, self.model.anis, y, z)
        c_y, c_z = make_isotropic(self.model.dim, self.model.anis, c_y, c_z)

        # set condtions to zero mean
        cond = self.cond_val - self.mean
        krig_mat = inv(self._get_cov_mat((c_x, c_y, c_z), (c_x, c_y, c_z)))
        krig_vecs = self._get_cov_mat((c_x, c_y, c_z), (x, y, z))
        # generate the kriged field
        field, krige_var = krigesum(krig_mat, krig_vecs, cond)

        # reshape field if we got an unstructured mesh
        if mesh_type_changed:
            mesh_type = mesh_type_old
            field = reshape_field_from_unstruct_to_struct(
                self.model.dim, field, axis_lens)
            krige_var = reshape_field_from_unstruct_to_struct(
                self.model.dim, krige_var, axis_lens)
        # calculate the kriging error
        self.krige_var = self.model.sill - krige_var
        # add the given mean
        self.field = field + self.mean
        return self.field, self.krige_var