def eval_func( func_val, pos, dim, mesh_type="unstructured", value_type="scalar", broadcast=False, ): """ Evaluate a function on a mesh. Parameters ---------- func_val : :any:`callable` or :class:`float` or :any:`None` Function to be called or single value to be filled. Should have the signiture f(x, [y, z, ...]) in case of callable. In case of a float, the field will be filled with a single value and in case of None, this value will be set to 0. pos : :class:`list` The position tuple, containing main direction and transversal directions (x, [y, z, ...]). dim : :class:`int` The spatial dimension. mesh_type : :class:`str`, optional 'structured' / 'unstructured' Default: 'unstructured' value_type : :class:`str`, optional Value type of the field. Either "scalar" or "vector". The default is "scalar". broadcast : :class:`bool`, optional Whether to return a single value, if a single value was given. Default: False Returns ------- :class:`numpy.ndarray` Function values at the given points. """ # care about scalar inputs func_val = 0 if func_val is None else func_val if broadcast and not callable(func_val) and np.size(func_val) == 1: return np.array(func_val, dtype=np.double).item() if not callable(func_val): func_val = _func_from_single_val(func_val, dim, value_type=value_type) # care about mesh and function call if mesh_type != "unstructured": pos, shape = format_struct_pos_dim(pos, dim) pos = generate_grid(pos) else: pos = np.array(pos, dtype=np.double).reshape(dim, -1) shape = np.shape(pos[0]) # prepend dimension if we have a vector field if value_type == "vector": shape = (dim,) + shape return np.reshape(func_val(*pos), shape)
def pos(self, pos): if self.mesh_type == "unstructured": self._pos = np.asarray(pos, dtype=np.double).reshape(self.dim, -1) self._field_shape = np.shape(self._pos[0]) else: self._pos, self._field_shape = format_struct_pos_dim(pos, self.dim) # prepend dimension if we have a vector field if self.value_type == "vector": self._field_shape = (self.dim,) + self._field_shape if self.latlon: raise ValueError("Field: Vector fields not allowed for latlon")
def pre_pos(self, pos, mesh_type="unstructured"): """ Preprocessing positions and mesh_type. Parameters ---------- pos : :any:`iterable` the position tuple, containing main direction and transversal directions mesh_type : :class:`str`, optional 'structured' / 'unstructured' Default: `"unstructured"` Returns ------- iso_pos : (d, n), :class:`numpy.ndarray` the isometrized position tuple shape : :class:`tuple` Shape of the resulting field. """ # save mesh-type self.mesh_type = mesh_type # save pos tuple if mesh_type != "unstructured": pos, shape = format_struct_pos_dim(pos, self.model.dim) self.pos = pos pos = gen_mesh(pos) else: pos = np.array(pos, dtype=np.double).reshape(self.model.dim, -1) self.pos = pos shape = np.shape(pos[0]) # prepend dimension if we have a vector field if self.value_type == "vector": shape = (self.model.dim, ) + shape # return isometrized pos tuple and resulting field shape return self.model.isometrize(pos), shape
def standard_bins( pos=None, dim=2, latlon=False, mesh_type="unstructured", bin_no=None, max_dist=None, ): r""" Get standard binning. Parameters ---------- pos : :class:`list`, optional the position tuple, containing either the point coordinates (x, y, ...) or the axes descriptions (for mesh_type='structured') dim : :class:`int`, optional Field dimension. latlon : :class:`bool`, optional Whether the data is representing 2D fields on earths surface described by latitude and longitude. When using this, the estimator will use great-circle distance for variogram estimation. Note, that only an isotropic variogram can be estimated and a ValueError will be raised, if a direction was specified. Bin edges need to be given in radians in this case. Default: False mesh_type : :class:`str`, optional 'structured' / 'unstructured', indicates whether the pos tuple describes the axis or the point coordinates. Default: `'unstructured'` bin_no: :class:`int`, optional number of bins to create. If None is given, will be determined by Sturges' rule from the number of points. Default: None max_dist: :class:`float`, optional Cut of length for the bins. If None is given, it will be set to one third of the box-diameter from the given points. Default: None Returns ------- :class:`numpy.ndarray` The generated bin edges. Notes ----- Internally uses double precision and also returns doubles. """ dim = 2 if latlon else int(dim) if bin_no is None or max_dist is None: if pos is None: raise ValueError("standard_bins: no pos tuple given.") if mesh_type != "unstructured": pos = generate_grid(format_struct_pos_dim(pos, dim)[0]) else: pos = np.asarray(pos, dtype=np.double).reshape(dim, -1) pos = latlon2pos(pos) if latlon else pos pnt_cnt = len(pos[0]) box = [] for axis in pos: box.append([np.min(axis), np.max(axis)]) box = np.asarray(box) diam = np.linalg.norm(box[:, 0] - box[:, 1]) # convert diameter to great-circle distance if using latlon diam = chordal_to_great_circle(diam) if latlon else diam bin_no = _sturges(pnt_cnt) if bin_no is None else int(bin_no) max_dist = diam / 3 if max_dist is None else float(max_dist) return np.linspace(0, max_dist, num=bin_no + 1, dtype=np.double)