Ejemplo n.º 1
0
 def grid_sample(self,
                 resolution: math.Shape,
                 size,
                 shape: math.Shape = None):
     shape = (self._shape if shape is None else shape) & resolution
     for dim in channel(self._shape):
         if dim.item_names[0] is None:
             warnings.warn(
                 f"Please provide item names for Noise dim {dim} using {dim}='x,y,z'",
                 FutureWarning)
             shape &= channel(**{dim.name: resolution.names})
     rndj = math.to_complex(random_normal(shape)) + 1j * math.to_complex(
         random_normal(shape))  # Note: there is no complex32
     with math.NUMPY:
         k = math.fftfreq(resolution) * resolution / math.tensor(
             size) * math.tensor(self.scale)  # in physical units
         k = math.vec_squared(k)
     lowest_frequency = 0.1
     weight_mask = math.to_float(k > lowest_frequency)
     # --- Compute 1/k ---
     k._native[(0, ) * len(k.shape)] = np.inf
     inv_k = 1 / k
     inv_k._native[(0, ) * len(k.shape)] = 0
     # --- Compute result ---
     fft = rndj * inv_k**self.smoothness * weight_mask
     array = math.real(math.ifft(fft))
     array /= math.std(array, dim=array.shape.non_batch)
     array -= math.mean(array, dim=array.shape.non_batch)
     array = math.to_float(array)
     return array
Ejemplo n.º 2
0
 def test_multi_dim_tensor_from_numpy(self):
     v = math.tensor(np.ones([1, 4, 3, 2]), batch('batch'), spatial('x,y'),
                     channel('vector'))
     self.assertEqual((1, 4, 3, 2), v.shape.sizes)
     v = math.tensor(np.ones([10, 4, 3, 2]), batch('batch'), spatial('x,y'),
                     channel('vector'))
     self.assertEqual((10, 4, 3, 2), v.shape.sizes)
Ejemplo n.º 3
0
    def points(self,
               points: Tensor or Number or tuple or list,
               values: Tensor or Number = None,
               radius: Tensor or float or int or None = None,
               extrapolation: math.Extrapolation = math.extrapolation.ZERO,
               color: str or Tensor or tuple or list or None = None) -> PointCloud:
        """
        Create a `phi.field.PointCloud` from the given `points`.
        The created field has no channel dimensions and all points carry the value `1`.

        Args:
            points: point locations in physical units
            values: (optional) values of the particles, defaults to 1.
            radius: (optional) size of the particles
            extrapolation: (optional) extrapolation to use, defaults to extrapolation.ZERO
            color: (optional) color used when plotting the points

        Returns:
            `phi.field.PointCloud` object
        """
        extrapolation = extrapolation if isinstance(extrapolation, math.Extrapolation) else self.boundaries[extrapolation]
        if radius is None:
            radius = math.mean(self.bounds.size) * 0.005
        # --- Parse points: tuple / list ---
        if isinstance(points, (tuple, list)):
            if len(points) == 0:  # no points
                points = math.zeros(instance(points=0), channel(vector=1))
            elif isinstance(points[0], Number):  # single point
                points = math.tensor([points], instance('points'), channel('vector'))
            else:
                points = math.tensor(points, instance('points'), channel('vector'))
        elements = Sphere(points, radius)
        if values is None:
            values = math.tensor(1.)
        return PointCloud(elements, values, extrapolation, add_overlapping=False, bounds=self.bounds, color=color)
Ejemplo n.º 4
0
def read_single_field(file: str, convert_to_backend=True) -> SampledField:
    stored = np.load(file, allow_pickle=True)
    ftype = stored['field_type']
    implemented_types = ('CenteredGrid', 'StaggeredGrid')
    if ftype in implemented_types:
        data = stored['data']
        dim_item_names = stored.get('dim_item_names',
                                    (None, ) * len(data.shape))
        data = NativeTensor(
            data,
            math.Shape(data.shape, tuple(stored['dim_names']),
                       tuple(stored['dim_types']), tuple(dim_item_names)))
        if convert_to_backend:
            data = math.tensor(data, convert=convert_to_backend)
        bounds_item_names = stored.get('bounds_item_names', (None, ) *
                                       len(stored['lower'] + stored['upper']))
        lower = math.wrap(
            stored['lower'], math.channel(vector=tuple(bounds_item_names))
        ) if stored['lower'].ndim > 0 else math.wrap(stored['lower'])
        upper = math.wrap(stored['upper'],
                          math.channel(vector=tuple(bounds_item_names)))
        extrapolation = math.extrapolation.from_dict(
            stored['extrapolation'][()])
        if ftype == 'CenteredGrid':
            return CenteredGrid(data,
                                bounds=geom.Box(lower, upper),
                                extrapolation=extrapolation)
        elif ftype == 'StaggeredGrid':
            data_ = unstack_staggered_tensor(data, extrapolation)
            return StaggeredGrid(data_,
                                 bounds=geom.Box(lower, upper),
                                 extrapolation=extrapolation)
    raise NotImplementedError(f"{ftype} not implemented ({implemented_types})")
Ejemplo n.º 5
0
 def test_np_speed_sum(self):
     print()
     np1, np2 = rnpv(64), rnpv(256)
     t1 = math.tensor(np1, batch('batch'), spatial('x, y'), channel('vector'))
     t2 = math.tensor(np2, batch('batch'), spatial('x, y'), channel('vector'))
     _assert_equally_fast(lambda: np.sum(np1), lambda: math.sum(t1, dim=t1.shape), n=10000)
     _assert_equally_fast(lambda: np.sum(np2), lambda: math.sum(t2, dim=t1.shape), n=10000)
Ejemplo n.º 6
0
 def test_stacked_get(self):
     t0 = math.ones(batch(batch=10) & spatial(x=4, y=3) & channel(vector=2))
     tensors = t0.unstack('vector')
     stacked = math.stack(tensors, channel('channel'))
     self.assertEqual(tensors, stacked.channel.unstack())
     assert tensors[0] is stacked.channel[0]
     assert tensors[1] is stacked.channel[1:2].channel.unstack()[0]
     self.assertEqual(4, len(stacked.x.unstack()))
Ejemplo n.º 7
0
def stagger(field: CenteredGrid,
            face_function: Callable,
            extrapolation: math.extrapolation.Extrapolation,
            type: type = StaggeredGrid):
    """
    Creates a new grid by evaluating `face_function` given two neighbouring cells.
    One layer of missing cells is inferred from the extrapolation.
    
    This method returns a Field of type `type` which must be either StaggeredGrid or CenteredGrid.
    When returning a StaggeredGrid, the new values are sampled at the faces of neighbouring cells.
    When returning a CenteredGrid, the new grid has the same resolution as `field`.

    Args:
      field: centered grid
      face_function: function mapping (value1: Tensor, value2: Tensor) -> center_value: Tensor
      extrapolation: extrapolation mode of the returned grid. Has no effect on the values.
      type: one of (StaggeredGrid, CenteredGrid)
      field: CenteredGrid: 
      face_function: Callable:
      extrapolation: math.extrapolation.Extrapolation: 
      type: type:  (Default value = StaggeredGrid)

    Returns:
      grid of type matching the `type` argument

    """
    all_lower = []
    all_upper = []
    if type == StaggeredGrid:
        for dim in field.shape.spatial.names:
            lo_valid, up_valid = extrapolation.valid_outer_faces(dim)
            width_lower = {dim: (int(lo_valid), int(up_valid) - 1)}
            width_upper = {
                dim: (int(lo_valid or up_valid) - 1, int(lo_valid
                                                         and up_valid))
            }
            all_lower.append(
                math.pad(field.values, width_lower, field.extrapolation))
            all_upper.append(
                math.pad(field.values, width_upper, field.extrapolation))
        all_upper = math.stack(all_upper, channel('vector'))
        all_lower = math.stack(all_lower, channel('vector'))
        values = face_function(all_lower, all_upper)
        result = StaggeredGrid(values,
                               bounds=field.bounds,
                               extrapolation=extrapolation)
        assert result.shape.spatial == field.shape.spatial
        return result
    elif type == CenteredGrid:
        left, right = math.shift(field.values, (-1, 1),
                                 padding=field.extrapolation,
                                 stack_dim=channel('vector'))
        values = face_function(left, right)
        return CenteredGrid(values,
                            bounds=field.bounds,
                            extrapolation=extrapolation)
    else:
        raise ValueError(type)
Ejemplo n.º 8
0
 def test_merge_shapes_check_item_names(self):
     s1 = channel(vector='x,y,z')
     s2 = channel(vector='r,g,b')
     try:
         math.merge_shapes(s1, s2)
         self.fail('Merging incompatible shapes did not raise an error!')
     except math.IncompatibleShapes:
         pass
     math.merge_shapes(s1, s1)
Ejemplo n.º 9
0
 def test_subshapes(self):
     s = batch(batch=10) & spatial(x=4, y=3) & channel(vector=2) & instance(points=1)
     self.assertEqual(batch(batch=10), s.batch)
     self.assertEqual(spatial(x=4, y=3), s.spatial)
     self.assertEqual(channel(vector=2), s.channel)
     self.assertEqual(instance(points=1), s.instance)
     self.assertEqual(batch(batch=10), batch(s))
     self.assertEqual(spatial(x=4, y=3), spatial(s))
     self.assertEqual(channel(vector=2), channel(s))
     self.assertEqual(instance(points=1), instance(s))
Ejemplo n.º 10
0
 def test_np_speed_op2(self):
     print()
     np1, np2 = rnpv(64), rnpv(64)
     t1 = math.tensor(np1, batch('batch'), spatial('x, y'), channel('vector'))
     t2 = math.tensor(np2, batch('batch'), spatial('x, y'), channel('vector'))
     _assert_equally_fast(lambda: np1 + np2, lambda: t1 + t2, n=10000)
     np1, np2 = rnpv(256), rnpv(256)
     t1 = math.tensor(np1, batch('batch'), spatial('x, y'), channel('vector'))
     t2 = math.tensor(np2, batch('batch'), spatial('x, y'), channel('vector'))
     _assert_equally_fast(lambda: np1 + np2, lambda: t1 + t2, n=1000)
Ejemplo n.º 11
0
 def test_tensor_as_field(self):
     t = math.random_normal(spatial(x=4, y=3), channel(vector='x,y'))
     grid = field.tensor_as_field(t)
     self.assertIsInstance(grid, CenteredGrid)
     math.assert_close(grid.dx, 1)
     math.assert_close(grid.points.x[0].y[0], 0)
     t = math.random_normal(instance(points=5), channel(vector='x,y'))
     points = field.tensor_as_field(t)
     self.assertTrue((points.elements.bounding_radius() > 0).all)
     self.assertIsInstance(points, PointCloud)
Ejemplo n.º 12
0
 def test_convert_point_cloud(self):
     loc = math.random_uniform(instance(points=4), channel(vector=2))
     val = math.random_normal(instance(points=4), channel(vector=2))
     points = PointCloud(Sphere(loc, radius=1), val)
     for backend in BACKENDS:
         converted = field.convert(points, backend)
         self.assertEqual(converted.values.default_backend, backend)
         self.assertEqual(converted.elements.center.default_backend,
                          backend)
         self.assertEqual(converted.elements.radius.default_backend,
                          backend)
Ejemplo n.º 13
0
 def __mul__(self, other):
     if not isinstance(other, Box):
         return NotImplemented
     lower = self._lower.vector.unstack(
         self.spatial_rank) + other._lower.vector.unstack(self.spatial_rank)
     upper = self._upper.vector.unstack(
         self.spatial_rank) + other._upper.vector.unstack(self.spatial_rank)
     names = self._upper.vector.item_names + other._upper.vector.item_names
     lower = math.stack(lower, math.channel(vector=names))
     upper = math.stack(upper, math.channel(vector=names))
     return Box(lower, upper)
Ejemplo n.º 14
0
 def test_collapsed_op2(self):
     # Collapsed + Collapsed
     a = math.zeros(channel(vector=4))
     b = math.ones(batch(batch=3))
     c = a + b
     self.assertIsInstance(c, CollapsedTensor)
     self.assertEqual(c.shape.volume, 12)
     self.assertEqual(c._inner.shape.volume, 1)
     # Collapsed + Native
     n = math.ones(channel(vector=3)) + (0, 1, 2)
     math.assert_close(n, (1, 2, 3))
Ejemplo n.º 15
0
 def test_boolean_mask_batched(self):
     for backend in BACKENDS:
         with backend:
             x = math.expand(math.range(spatial('x'), 4), batch(batch=2)) * math.tensor([1, -1])
             mask = math.tensor([[True, False, True, False], [False, True, False, False]], batch('batch'), spatial('x'))
             selected = math.boolean_mask(x, 'x', mask)
             expected_0 = math.tensor([(0, -0), (2, -2)], spatial('x'), channel('vector'))
             expected_1 = math.tensor([(1, -1)], spatial('x'), channel('vector'))
             math.assert_close(selected.batch[0], expected_0, msg=backend.name)
             math.assert_close(selected.batch[1], expected_1, msg=backend.name)
             math.assert_close(selected, x.x[mask], msg=backend.name)
Ejemplo n.º 16
0
 def test_tensor_from_tuple_of_tensor_like(self):
     native = ([1, 2, 3], math.zeros(channel(vector=3)))
     for backend in BACKENDS:
         with backend:
             tens = wrap(native, batch(stack=2), channel(vector=3))
             self.assertEqual(math.NUMPY, math.choose_backend(tens))
             self.assertEqual(
                 batch(stack=2) & channel(vector=3), tens.shape)
             tens = tensor(native, batch(stack=2), channel(vector=3))
             self.assertEqual(backend, math.choose_backend(tens))
             self.assertEqual(
                 batch(stack=2) & channel(vector=3), tens.shape)
Ejemplo n.º 17
0
 def test_stacked_native(self):
     t0 = math.ones(batch(batch=10) & spatial(x=4, y=3) & channel(vector=2))
     tensors = t0.unstack('vector')
     stacked = math.stack(tensors, channel('vector2'))
     math.assert_close(stacked, t0)
     self.assertEqual((10, 4, 3, 2), stacked.native(stacked.shape).shape)
     self.assertEqual(
         (4, 3, 2, 10),
         stacked.native(order=('x', 'y', 'vector2', 'batch')).shape)
     self.assertEqual(
         (2, 10, 3, 4),
         stacked.native(order=('vector2', 'batch', 'y', 'x')).shape
     )  # this should re-stack since only the stacked dimension position is different
Ejemplo n.º 18
0
 def test_op2_incompatible_item_names(self):
     t1 = math.random_normal(channel(vector='x,y,z'))
     t2 = math.random_normal(channel(vector='r,g,b'))
     self.assertEqual(('r', 'g', 'b'), t2.vector.item_names)
     try:
         t1 + t2
         self.fail("Tensors with incompatible item names cannot be added")
     except math.IncompatibleShapes:
         pass
     t1 + t1
     t2_ = t2 + math.random_normal(channel(vector=3))
     self.assertEqual(('r', 'g', 'b'), t2_.vector.item_names)
     t2_ = math.random_normal(channel(vector=3)) + t2
     self.assertEqual(('r', 'g', 'b'), t2_.vector.item_names)
Ejemplo n.º 19
0
 def test_expand_copy_item_names(self):
     a = math.zeros(channel(vector=2))
     try:
         math.expand(a, channel(vector=3))
         self.fail()
     except IncompatibleShapes:
         pass
     b = math.expand(a, channel(vector='x,y'))
     self.assertEqual(('x', 'y'), b.vector.item_names)
     try:
         math.expand(b, channel(vector='a,b'))
         self.fail()
     except IncompatibleShapes:
         pass
Ejemplo n.º 20
0
def tensor_as_field(t: Tensor):
    """
    Interpret a `Tensor` as a `CenteredGrid` or `PointCloud` depending on its dimensions.

    Unlike the `CenteredGrid` constructor, this function will have the values sampled at integer points for each spatial dimension.

    Args:
        t: `Tensor` with either `spatial` or `instance` dimensions.

    Returns:
        `CenteredGrid` or `PointCloud`
    """
    if spatial(t):
        assert not instance(
            t
        ), f"Cannot interpret tensor as Field because it has both spatial and instance dimensions: {t.shape}"
        bounds = Box(-0.5, math.wrap(spatial(t), channel('vector')) - 0.5)
        return CenteredGrid(t, 0, bounds=bounds)
    if instance(t):
        assert not spatial(
            t
        ), f"Cannot interpret tensor as Field because it has both spatial and instance dimensions: {t.shape}"
        assert 'vector' in t.shape, f"Cannot interpret tensor as PointCloud because it has not vector dimension."
        point_count = instance(t).volume
        bounds = data_bounds(t)
        radius = math.vec_length(
            bounds.size) / (1 + point_count**(1 / t.vector.size))
        return PointCloud(Sphere(t, radius=radius))
Ejemplo n.º 21
0
 def test_meshgrid_names(self):
     shape = spatial(x=2) & channel(vector='x')
     indices = list(shape.meshgrid(names=True))
     self.assertEqual([
         dict(x=0, vector='x'),
         dict(x=1, vector='x'),
     ], indices)
Ejemplo n.º 22
0
 def test_dimension_types(self):
     v = math.ones(batch(batch=10) & spatial(x=4, y=3) & channel(vector=2))
     self.assertEqual(v.x.index, 1)
     self.assertEqual(v.x.name, 'x')
     self.assertEqual(('batch', 'spatial', 'spatial', 'channel'), v.shape.types)
     b = v.x.as_batch()
     self.assertEqual(('batch', 'batch', 'spatial', 'channel'), b.shape.types)
Ejemplo n.º 23
0
    def vector_grid(self,
                    value: Field or Tensor or Number or Geometry or callable = 0.,
                    type: type = CenteredGrid,
                    extrapolation: math.Extrapolation or str = 'vector') -> CenteredGrid or StaggeredGrid:
        """
        Creates a vector grid matching the resolution and bounds of the domain.
        The grid is created from the given `value` which must be one of the following:
        
        * Number (int, float, complex or zero-dimensional tensor): all grid values will be equal to `value`. This has a near-zero memory footprint.
        * Field: the given value is resampled to the grid cells of this Domain.
        * Tensor with spatial dimensions matcing the domain resolution: grid values will equal `value`.
        * Geometry: grid values are determined from the volume overlap between grid cells and geometry. Non-overlapping = 0, fully enclosed grid cell = 1.
        * function(location: Tensor) returning one of the above.
        
        The returned grid will have a vector dimension with size equal to the rank of the domain.

        Args:
          value: constant, Field, Tensor or function specifying the grid values
          type: class of Grid to create, must be either CenteredGrid or StaggeredGrid
          extrapolation: (optional) grid extrapolation, defaults to Domain.boundaries['vector']

        Returns:
          Grid of specified type
        """
        extrapolation = extrapolation if isinstance(extrapolation, math.Extrapolation) else self.boundaries[extrapolation]
        result = type(value, resolution=self.resolution, bounds=self.bounds, extrapolation=extrapolation)
        if result.shape.channel_rank == 0:
            result = result.with_values(math.expand(result.values, channel(vector=self.rank)))
        else:
            assert result.shape.get_size('vector') == self.rank
        return result
Ejemplo n.º 24
0
 def test_indexing(self):
     s = batch(batch=10) & spatial(x=4, y=3) & channel(vector=2)
     self.assertEqual(batch(batch=10), s[0:1])
     self.assertEqual(batch(batch=10), s[[0]])
     self.assertEqual(spatial(x=4, y=3), s[1:3])
     self.assertEqual(spatial(x=4), s['x'])
     self.assertEqual(spatial(x=4, y=3), s['x, y'])
Ejemplo n.º 25
0
 def test_stacked_shapes(self):
     t0 = math.ones(batch(batch=10) & spatial(x=4, y=3) & channel(vector=2))
     for dim in t0.shape.names:
         tensors = t0.unstack(dim)
         stacked = math.stack(tensors, t0.shape[dim].with_sizes([None]))
         self.assertEqual(set(t0.shape.names), set(stacked.shape.names))
         self.assertEqual(t0.shape.volume, stacked.shape.volume)
Ejemplo n.º 26
0
 def test_iterate_layout(self):
     a = [dict(a=1), dict(b=2)]
     t = math.layout(a, channel('outer,dict'))
     total = []
     for d in t:
         total.append(d)
     self.assertEqual(total, [1, 2])
Ejemplo n.º 27
0
 def test_layout_dict_conflict(self):
     a = [dict(a=1), dict(b=2)]
     t = math.layout(a, channel('outer,dict'))
     self.assertEqual(None, t.shape.get_item_names('dict'))
     self.assertEqual(a, t.native())
     self.assertEqual([1, 2], t.dict[0].native())
     self.assertEqual(2, t.dict[0].outer[1].native())
Ejemplo n.º 28
0
 def __init__(self,
              center: Tensor = None,
              radius: float or Tensor = None,
              **center_: float or Tensor):
     """
     Args:
         center: Sphere center as `Tensor` with `vector` dimension.
             The spatial dimension order should be specified in the `vector` dimension via item names.
         radius: Sphere radius as `float` or `Tensor`
         **center_: Specifies center when the `center` argument is not given. Center position by dimension, e.g. `x=0.5, y=0.2`.
     """
     if center is not None:
         if not isinstance(center, Tensor):
             warnings.warn(
                 f"constructor Sphere({type(center)}) is deprecated. Use Sphere(Tensor) or Sphere(**center_) instead.",
                 DeprecationWarning)
             self._center = wrap(center)
         else:
             self._center = center
         assert 'vector' in self._center.shape, f"Sphere.center must have a 'vector' dimension. Use the syntax x=0.5."
     else:
         self._center = math.wrap(
             tuple(center_.values()),
             math.channel(vector=tuple(center_.keys())))
         # self._center = wrap(math.spatial(**center_), math.channel('vector'))
     assert radius is not None, "radius must be specified."
     self._radius = wrap(radius)
Ejemplo n.º 29
0
 def test_slice_centered_grid(self):
     g = CenteredGrid(Noise(batch(batch=10), channel(vector=2)), x=10, y=20)
     s1 = g[{'vector': 0, 'batch': 1, 'x': 1}]
     s2 = g.vector[0].batch[1].x[1]
     self.assertIsInstance(s1, CenteredGrid)
     self.assertEqual(s1.bounds, Box[1:2, 0:20])
     field.assert_close(s1, s2)
Ejemplo n.º 30
0
 def test_flip_item_names(self):
     t = math.zeros(spatial(x=4, y=3), channel(vector='x,y'))
     self.assertEqual(('x', 'y'), t.vector.item_names)
     t_ = t.vector.flip()
     self.assertEqual(('y', 'x'), t_.vector.item_names)
     t_ = t.vector[::-1]
     self.assertEqual(('y', 'x'), t_.vector.item_names)