tfields package

Subpackages

Submodules

tfields.bounding_box module

class tfields.bounding_box.Node(mesh, cuts, coord_sys=None, at_intersection='split', delta=0.0, parent=None, box=None, internal_template=None, cut_expr=None)[source]

Bases: object

This class allows to increase the performance with cuts in x,y and z direction An extension to arbitrary cuts might be possible in the future

Parameters:
  • parent – Parent node of self

  • mesh – Mesh corresponding to the node

  • cut_expr – Cut that determines the seperation in left and right node

  • cuts – List of cuts for the children nodes

Attrs:

parent (Node) remaining_cuts (dict): key specifies dimension, value the cuts that

are still not done

cut_expr (dict): part of parents remaining_cuts. The dimension defines

what is meant by left and right

Examples

>>> import tfields
>>> mesh = tfields.Mesh3D.grid((5.6, 6.2, 3),
...                            (-0.25, 0.25, 4),
...                            (-1, 1, 10))
>>> cuts = {'x': [5.7, 6.1],
...         'y': [-0.2, 0, 0.2],
...         'z': [-0.5, 0.5]}
>>> tree = tfields.bounding_box.Node(mesh,
...                                  cuts,
...                                  at_intersection='keep')
>>> leaves = tree.leaves()
>>> leaves = tfields.bounding_box.Node.sort_leaves(leaves)
>>> meshes = [leaf.mesh for leaf in leaves]
>>> templates = [leaf.template for leaf in leaves]
>>> special_leaf = tree.find_leaf([5.65, -0.21, 0])
find_leaf(point, _in_recursion=False)[source]
Returns:

Node: leaf note, containinig point None: point outside root box

Return type:

Node / None

in_box(point)[source]
is_last_cut()[source]
is_leaf()[source]
is_root()[source]
leaves()[source]

Recursive function to create a list of all leaves

Returns:

of all leaves descending from this node

Return type:

list

property root
classmethod sort_leaves(leaves_list)[source]

sorting the leaves first in x, then y, then z direction

property template

Get the global template for a leaf. This can be applied to the root mesh with the cut method to retrieve exactly this leaf mesh again.

Returns:

mesh with first scalars as an instruction on how to build

this cut (scalars point to faceIndices on mother mesh). Can be used with Mesh3D.cut

Return type:

tfields.Mesh3D

class tfields.bounding_box.Searcher(mesh, n_sections=None, delta=0.0, cut_length=None)[source]

Bases: Node

in_faces(tensors, delta=-1, assign_multiple=False)[source]
TODO-0:
  • check case of point+-delta outside box!

Examples

>>> import tfields
>>> import numpy as np
>>> mesh = tfields.Mesh3D.grid((0, 1, 2), (1, 2, 2), (2, 3, 2))
>>> tree = tfields.bounding_box.Searcher(mesh)
>>> points = tfields.Tensors([[0.5, 1, 2.1],
...                           [0.5, 0, 0],
...                           [0.5, 2, 2.1],
...                           [0.5, 1.5, 2.5]])
>>> box_res = tree.in_faces(points, delta=0.0001)
>>> usual_res = mesh.in_faces(points, delta=0.0001)
>>> assert np.array_equal(box_res, usual_res)

tfields.core module

Author: Daniel Boeckenhoff Mail: dboe@ipp.mpg.de

core of tfields library contains numpy ndarray derived bases of the tfields package

Notes

# noqa:E501 pylint:disable=line-too-long, * It could be worthwhile concidering np.li.mixins.NDArrayOperatorsMixin

class tfields.core.AbstractFields(iterable=(), /)[source]

Bases: list, AbstractObject

Extension of the list to tfields polymorphism. Allow setitem and getitem by object name.

class tfields.core.AbstractNdarray(array, **kwargs)[source]

Bases: ndarray, AbstractObject

All tensors and subclasses should derive from AbstractNdarray. AbstractNdarray implements all the inheritance specifics for np.ndarray Whene inheriting, three attributes are of interest:

__slots__

If you want to add attributes to your AbstractNdarray subclass, add the attribute name to __slots__

Type:

List(str)

__slot_defaults__

if __slot_defaults__ is None, the defaults for the attributes in __slots__ will be None other values will be treaded as defaults to the corresponding arg at the same position in the __slots__ list.

Type:

list

__slot_dtypes__

for the conversion of the args in __slots__ to numpy arrays. None values mean no conversion.

Type:

List(dtypes)

__slot_setters__

Because __slots__ and properties are mutually exclusive this is a possibility to take care of proper attribute handling. None will be passed for ‘not set’.

Type:

List(callable)

Parameters:
  • array (array-like) – input array

  • **kwargs – arguments corresponding to __slots__

property bulk

The pure ndarray version of the actual state -> nothing attached

copy(**kwargs)[source]

The standard ndarray copy does not copy slots. Correct for this.

Examples

>>> import tfields
>>> m = tfields.TensorMaps(
...     [[1,2,3], [3,3,3], [0,0,0], [5,6,7]],
...     [[1], [3], [0], [5]],
...     maps=[
...         ([[0, 1, 2], [1, 2, 3]], [21, 42]),
...         [[1]],
...         [[0, 1, 2, 3]]
...     ])
>>> mc = m.copy()
>>> mc.equal(m)
True
>>> mc is m
False
>>> mc.fields is m.fields
False
>>> mc.fields[0] is m.fields[0]
False
>>> mc.maps[3].fields[0] is m.maps[3].fields[0]
False
class tfields.core.AbstractObject[source]

Bases: Storable

Abstract base class for all tfields objects implementing polymorphisms

class tfields.core.Container(*items, labels=None)[source]

Bases: AbstractFields

Store lists of tfields objects. Save mechanisms are provided

Examples

>>> import numpy as np
>>> import tfields
>>> sphere = tfields.Mesh3D.grid(
...     (1, 1, 1),
...     (-np.pi, np.pi, 3),
...     (-np.pi / 2, np.pi / 2, 3),
...     coord_sys='spherical')
>>> sphere2 = sphere.copy() * 3
>>> c = tfields.Container([sphere, sphere2])
>>> c.save("~/tmp/spheres.npz")
>>> c1 = tfields.Container.load("~/tmp/spheres.npz")
copy()[source]

Return a shallow copy of the list.

property items

items of the container as a list

class tfields.core.Fields(*items)[source]

Bases: AbstractFields

Container for fields which should be attached to tensors with the <>.fields attribute to make them tensor fields

static to_field(field, copy=False, **kwargs)[source]
Parameters:
  • field (Tensors) –

  • copy (bool) –

  • **kwargs – passed to Tensors constructor

class tfields.core.Maps(*args, **kwargs)[source]

Bases: SortedDict, AbstractObject

Container for TensorFields sorted by dimension, i.e indexing by dimension

Parameters:
  • ( (*args) – List(TensorFields): | List(Tuple(int, TensorFields)): | TensorFields: | Tuple(Tensors, *Fields)): TODO: document

  • )

  • **kwargs – forwarded to SortedDict

TODO: further documentation

equal(other, **kwargs)[source]

Test equality with other object. :param **kwargs: passed to each item on equality check

static to_map(map_, *fields, copy=False, **kwargs)[source]
Parameters:
  • map (TensorFields) –

  • *fields (Tensors) –

  • copy (bool) –

  • **kwargs – passed to TensorFields constructor

class tfields.core.TensorFields(tensors, *fields, **kwargs)[source]

Bases: Tensors

Discrete Tensor Field

Parameters:
  • tensors (array) – base tensors

  • *fields (array) – multiple fields assigned to one base tensor. Fields themself are also of type tensor

  • **kwargs – rigid (bool): demand equal field and tensor lenght … : see tfields.Tensors

Examples

>>> import tfields
>>> from tfields import Tensors, TensorFields
>>> scalars = Tensors([0, 1, 2])
>>> vectors = Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> scalar_field = TensorFields(vectors, scalars)
>>> scalar_field.rank
1
>>> scalar_field.fields[0].rank
0
>>> vectorField = TensorFields(vectors, vectors)
>>> vectorField.fields[0].rank
1
>>> vectorField.fields[0].dim
3
>>> multiField = TensorFields(vectors, scalars, vectors)
>>> multiField.fields[0].dim
1
>>> multiField.fields[1].dim
3

Empty initialization

>>> empty_field = TensorFields([], dim=3)
>>> assert empty_field.shape == (0, 3)
>>> assert empty_field.fields == []

Directly initializing with lists or arrays

>>> vec_field_raw = tfields.TensorFields([[0, 1, 2], [3, 4, 5]],
...                                       [1, 6], [2, 7])
>>> assert len(vec_field_raw.fields) == 2

Copying

>>> cp = TensorFields(vectorField)
>>> assert vectorField.equal(cp)

Copying takes care of coord_sys

>>> cp.transform(tfields.bases.CYLINDER)
>>> cp_cyl = TensorFields(cp)
>>> assert cp_cyl.coord_sys == tfields.bases.CYLINDER

Copying with changing type

>>> tcp = TensorFields(vectorField, dtype=int)
>>> assert vectorField.equal(tcp)
>>> assert tcp.dtype == int
Raises:
  • TypeError

  • >>> import tfields

  • >>> tfields.TensorFields([1, 2, 3], [3]) # doctest – +ELLIPSIS

  • Traceback (most recent call last)

  • ...

  • ValueError – Length of base (3) should be the same as the length of all fields ([1]).

  • This error can be suppressed by setting rigid=False

  • >>> loose = tfields.TensorFields([1, 2, 3], [3], rigid=False)

  • >>> assert len(loose) != 1

coord_sys
equal(other, **kwargs)[source]

Test, whether the instance has the same content as other.

Parameters:
  • other (iterable) –

  • **kwargs – see Tensors.equal

fields
classmethod merged(*objects, **kwargs)[source]

Factory method Merges all input arguments to one object

Parameters:
  • return_templates (bool) – return the templates which can be used together with cut to retrieve the original objects

  • dim (int) –

  • **kwargs – passed to cls

Examples

>>> import numpy as np
>>> import tfields
>>> import tfields.bases

The new object with turn out in the most frequent coordinate system if not specified explicitly

>>> vec_a = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> vec_b = tfields.Tensors([[5, 4, 1]],
...     coord_sys=tfields.bases.cylinder)
>>> vec_c = tfields.Tensors([[4, 2, 3]],
...     coord_sys=tfields.bases.cylinder)
>>> merge = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, [[2, 0, 1]])
>>> assert merge.coord_sys == 'cylinder'
>>> assert merge.equal([[0, 0, 0],
...                     [0, 0, 1],
...                     [1, -np.pi / 2, 0],
...                     [5, 4, 1],
...                     [4, 2, 3],
...                     [2, 0, 1]])

Merge also shifts the maps to still refer to the same tensors

>>> tm_a = tfields.TensorMaps(merge, maps=[[[0, 1, 2]]])
>>> tm_b = tm_a.copy()
>>> assert tm_a.coord_sys == 'cylinder'
>>> tm_merge = tfields.TensorMaps.merged(tm_a, tm_b)
>>> assert tm_merge.coord_sys == 'cylinder'
>>> assert tm_merge.maps[3].equal([[0, 1, 2],
...                               list(range(len(merge),
...                                          len(merge) + 3,
...                                          1))])
>>> obj_list = [tfields.Tensors([[1, 2, 3]],
...             coord_sys=tfields.bases.CYLINDER),
...             tfields.Tensors([[3] * 3]),
...             tfields.Tensors([[5, 1, 3]])]
>>> merge2 = tfields.Tensors.merged(
...     *obj_list, coord_sys=tfields.bases.CARTESIAN)
>>> assert merge2.equal([[-0.41614684, 0.90929743, 3.],
...                      [3, 3, 3], [5, 1, 3]], atol=1e-8)

The return_templates argument allows to retrieve a template which can be used with the cut method.

>>> merge, templates = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, return_templates=True)
>>> assert merge.cut(templates[0]).equal(vec_a)
>>> assert merge.cut(templates[1]).equal(vec_b)
>>> assert merge.cut(templates[2]).equal(vec_c)
name
property names

Retrive the names of the fields as a list

Examples

>>> import tfields
>>> s = tfields.Tensors([1,2,3], name=1.)
>>> tf = tfields.TensorFields(s, *[s]*10)
>>> assert len(tf.names) == 10
>>> assert set(tf.names) == {1.}
>>> tf.names = range(10)
>>> tf.names
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
plot(*args, **kwargs)[source]

Generic plotting method of TensorFields.

Parameters:
  • field_index – index of the field to plot (as quiver by default)

  • normalize – If True, normalize the field vectors to show only the direction

  • color – additional str argument ‘norm’ added. If color=”norm”, color with the norm.

transform_field(coord_sys, field_index=0)[source]

Transform the field to the coordinate system of choice.

NOTE: This is not yet any way generic!!! Have a look at Einsteinpy and actual status of

sympy for further implementation

class tfields.core.TensorMaps(tensors, *fields, **kwargs)[source]

Bases: TensorFields

Parameters:
  • tensors – see Tensors class

  • *fields (Tensors) – see TensorFields class

  • **kwargs

    coord_sys (‘str’): see Tensors class maps (array-like): indices indicating a connection between the

    tensors at the respective index positions

Examples

>>> import tfields
>>> scalars = tfields.Tensors([0, 1, 2])
>>> vectors = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> maps = [tfields.TensorFields([[0, 1, 2], [0, 1, 2]], [42, 21]),
...         tfields.TensorFields([[1], [2]], [-42, -21])]
>>> mesh = tfields.TensorMaps(vectors, scalars,
...                           maps=maps)
>>> assert isinstance(mesh.maps, tfields.Maps)
>>> assert len(mesh.maps) == 2
>>> assert mesh.equal(tfields.TensorFields(vectors, scalars))

Copy constructor

>>> mesh_copy = tfields.TensorMaps(mesh)

Copying takes care of coord_sys

>>> mesh_copy.transform(tfields.bases.CYLINDER)
>>> mesh_cp_cyl = tfields.TensorMaps(mesh_copy)
>>> assert mesh_cp_cyl.coord_sys == tfields.bases.CYLINDER
cleaned(stale=True, duplicates=True)[source]
Parameters:
  • stale (bool) – remove stale vertices

  • duplicates (bool) – replace duplicate vertices by originals

Examples

>>> import numpy as np
>>> import tfields
>>> mp1 = tfields.TensorFields([[0, 1, 2], [3, 4, 5]],
...                            *zip([1,2,3,4,5], [6,7,8,9,0]))
>>> mp2 = tfields.TensorFields([[0], [3]])
>>> tm = tfields.TensorMaps([[0,0,0], [1,1,1], [2,2,2], [0,0,0],
...                          [3,3,3], [4,4,4], [5,6,7]],
...                         maps=[mp1, mp2])
>>> c = tm.cleaned()
>>> assert c.equal([[0., 0., 0.],
...                 [1., 1., 1.],
...                 [2., 2., 2.],
...                 [3., 3., 3.],
...                 [4., 4., 4.]])
>>> assert np.array_equal(c.maps[3], [[0, 1, 2], [0, 3, 4]])
>>> assert np.array_equal(c.maps[1], [[0], [0]])
Returns:

copy of self without stale vertices and duplicat points (depending on arguments)

coord_sys
disjoint_map(map_dim)[source]

Find the disjoint sets of map = self.maps[map_dim] As an example, this method is interesting for splitting a mesh consisting of seperate parts

Parameters:

map_dim (int) – reference to map position used like: self.maps[map_dim]

Returns:

map description(tuple): see self.parts

Return type:

Tuple(int, List(List(int)))

Examples

>>> import tfields
>>> a = tfields.TensorMaps(
...     [[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]],
...     maps=[[[0, 1, 2], [0, 2, 3]]])
>>> b = a.copy()
>>> b[:, 0] += 2
>>> m = tfields.TensorMaps.merged(a, b)
>>> mp_description = m.disjoint_map(3)
>>> parts = m.parts(mp_description)
>>> aa, ba = parts
>>> assert aa.maps[3].equal(ba.maps[3])
>>> assert aa.equal(a)
>>> assert ba.equal(b)
equal(other, **kwargs)[source]

Test, whether the instance has the same content as other.

Parameters:
  • other (iterable) –

  • optional – see TensorFields.equal

Examples

>>> import tfields
>>> maps = [tfields.TensorFields([[1]], [42])]
>>> tm = tfields.TensorMaps(maps[0], maps=maps)

# >>> assert tm.equal(tm)

>>> cp = tm.copy()

# >>> assert tm.equal(cp)

>>> cp.maps[1].fields[0] = -42
>>> assert tm.maps[1].fields[0] == 42
>>> assert not tm.equal(cp)
fields
keep(keep_condition)[source]

Return copy of self with vertices where keep_condition is True Copy because self is immutable

Examples

>>> import numpy as np
>>> import tfields
>>> m = tfields.TensorMaps(
...     [[0,0,0], [1,1,1], [2,2,2], [0,0,0],
...      [3,3,3], [4,4,4], [5,5,5]],
...     maps=[tfields.TensorFields([[0, 1, 2], [0, 1, 3],
...                                 [3, 4, 5], [3, 4, 1],
...                                 [3, 4, 6]],
...                                 [1, 3, 5, 7, 9],
...                                 [2, 4, 6, 8, 0])])
>>> c = m.removed([True, True, True, False, False, False, False])
>>> c.equal([[0, 0, 0],
...          [3, 3, 3],
...          [4, 4, 4],
...          [5, 5, 5]])
True
>>> assert c.maps[3].equal(np.array([[0, 1, 2], [0, 1, 3]]))
>>> assert c.maps[3].fields[0].equal([5, 9])
>>> assert c.maps[3].fields[1].equal([6, 0])
maps
classmethod merged(*objects, **kwargs)[source]

Factory method Merges all input arguments to one object

Parameters:
  • return_templates (bool) – return the templates which can be used together with cut to retrieve the original objects

  • dim (int) –

  • **kwargs – passed to cls

Examples

>>> import numpy as np
>>> import tfields
>>> import tfields.bases

The new object with turn out in the most frequent coordinate system if not specified explicitly

>>> vec_a = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> vec_b = tfields.Tensors([[5, 4, 1]],
...     coord_sys=tfields.bases.cylinder)
>>> vec_c = tfields.Tensors([[4, 2, 3]],
...     coord_sys=tfields.bases.cylinder)
>>> merge = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, [[2, 0, 1]])
>>> assert merge.coord_sys == 'cylinder'
>>> assert merge.equal([[0, 0, 0],
...                     [0, 0, 1],
...                     [1, -np.pi / 2, 0],
...                     [5, 4, 1],
...                     [4, 2, 3],
...                     [2, 0, 1]])

Merge also shifts the maps to still refer to the same tensors

>>> tm_a = tfields.TensorMaps(merge, maps=[[[0, 1, 2]]])
>>> tm_b = tm_a.copy()
>>> assert tm_a.coord_sys == 'cylinder'
>>> tm_merge = tfields.TensorMaps.merged(tm_a, tm_b)
>>> assert tm_merge.coord_sys == 'cylinder'
>>> assert tm_merge.maps[3].equal([[0, 1, 2],
...                               list(range(len(merge),
...                                          len(merge) + 3,
...                                          1))])
>>> obj_list = [tfields.Tensors([[1, 2, 3]],
...             coord_sys=tfields.bases.CYLINDER),
...             tfields.Tensors([[3] * 3]),
...             tfields.Tensors([[5, 1, 3]])]
>>> merge2 = tfields.Tensors.merged(
...     *obj_list, coord_sys=tfields.bases.CARTESIAN)
>>> assert merge2.equal([[-0.41614684, 0.90929743, 3.],
...                      [3, 3, 3], [5, 1, 3]], atol=1e-8)

The return_templates argument allows to retrieve a template which can be used with the cut method.

>>> merge, templates = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, return_templates=True)
>>> assert merge.cut(templates[0]).equal(vec_a)
>>> assert merge.cut(templates[1]).equal(vec_b)
>>> assert merge.cut(templates[2]).equal(vec_c)
name
parts(*map_descriptions)[source]
Parameters:

*map_descriptions (Tuple(int, List(List(int)))) –

tuples of map_dim (int): reference to map position

used like: self.maps[map_dim]

map_indices_list (List(List(int))): each int refers

to index in a map.

Returns:

One TensorMaps or TensorMaps subclass per

map_description

Return type:

List(cls)

paths(map_dim)[source]

Find the minimal amount of graphs building the original graph with maximum of two links per node i.e.

“o—–o o—–o” ” / /” “” / /”” “o–o–o o–o 8–o”

= | + +

o o o

/ /

/ /

o o o o

where 8 is a duplicated node (one has two links and one has only one.)

Examples

>>> import tfields

Ascii figure above: >>> a = tfields.TensorMaps([[1, 0], [3, 0], [2, 2], [0, 4], [2, 4], … [4, 4], [1, 6], [3, 6], [2, 2]], … maps=[[[0, 2], [2, 4], [3, 4], [5, 4], … [1, 8], [6, 4], [6, 7], [7, 4]]])

>>> paths = a.paths(2)
>>> assert paths[0].equal([[ 1.,  0.],
...                        [ 2.,  2.],
...                        [ 2.,  4.],
...                        [ 0.,  4.]])
>>> assert paths[0].maps[4].equal([[ 0.,  1.,  2.,  3.]])
>>> assert paths[1].equal([[ 4.,  4.],
...                        [ 2.,  4.],
...                        [ 1.,  6.],
...                        [ 3.,  6.],
...                        [ 2.,  4.]])
>>> assert paths[2].equal([[ 3.,  0.],
...                        [ 2.,  2.]])

Note

The Longest path problem is a NP-hard problem.

plot(*args, **kwargs)[source]

Generic plotting method of TensorMaps.

Parameters:
  • *args – Depending on Positional arguments passed to the underlying rna.plotting.plot_tensor_map() function for arbitrary .

  • dim (int) – dimension of the plot representation (axes).

  • map (int) – index of the map to plot (default is 3).

  • edgecolor (color) – color of the edges (dim = 3)

removed(remove_condition)[source]

Return copy of self without vertices where remove_condition is True Copy because self is immutable

Examples

>>> import tfields
>>> m = tfields.TensorMaps(
...     [[0,0,0], [1,1,1], [2,2,2], [0,0,0],
...      [3,3,3], [4,4,4], [5,5,5]],
...     maps=[tfields.TensorFields([[0, 1, 2], [0, 1, 3],
...           [3, 4, 5], [3, 4, 1],
...           [3, 4, 6]],
...           [1, 3, 5, 7, 9],
...           [2, 4, 6, 8, 0])])
>>> c = m.keep([False, False, False, True, True, True, True])
>>> c.equal([[0, 0, 0],
...          [3, 3, 3],
...          [4, 4, 4],
...          [5, 5, 5]])
True
>>> assert c.maps[3].equal([[0, 1, 2], [0, 1, 3]])
>>> assert c.maps[3].fields[0].equal([5, 9])
>>> assert c.maps[3].fields[1].equal([6, 0])
stale()[source]
Returns:

Mask for all vertices that are stale i.e. are not refered by maps

Examples

>>> import numpy as np
>>> import tfields
>>> vectors = tfields.Tensors(
...     [[0, 0, 0], [0, 0, 1], [0, -1, 0], [4, 4, 4]])
>>> tm = tfields.TensorMaps(
...     vectors,
...     maps=[[[0, 1, 2], [0, 1, 2]], [[1, 1], [2, 2]]])
>>> assert np.array_equal(tm.stale(), [False, False, False, True])
class tfields.core.Tensors(tensors, **kwargs)[source]

Bases: AbstractNdarray

Set of tensors with the same basis.

Parameters:
  • tensors – np.ndarray or AbstractNdarray subclass

  • **kwargs – name: optional - custom name, can be anything

Examples

>>> import numpy as np
>>> import tfields

Initialize a scalar range

>>> scalars = tfields.Tensors([0, 1, 2])
>>> scalars.rank == 0
True

Initialize vectors

>>> vectors = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> vectors.rank == 1
True
>>> vectors.dim == 3
True
>>> assert vectors.coord_sys == 'cartesian'

Initialize the Levi-Zivita Tensor

>>> matrices = tfields.Tensors([[[0, 0, 0], [0, 0, 1], [0, -1, 0]],
...                             [[0, 0, -1], [0, 0, 0], [1, 0, 0]],
...                             [[0, 1, 0], [-1, 0, 0], [0, 0, 0]]])
>>> matrices.shape == (3, 3, 3)
True
>>> matrices.rank == 2
True
>>> matrices.dim == 3
True

Initializing in different start coordinate system

>>> cyl = tfields.Tensors([[5, np.arctan(4. / 3.), 42]],
...                       coord_sys='cylinder')
>>> assert cyl.coord_sys == 'cylinder'
>>> cyl.transform('cartesian')
>>> assert cyl.coord_sys == 'cartesian'
>>> cart = cyl
>>> assert round(cart[0, 0], 10) == 3.
>>> assert round(cart[0, 1], 10) == 4.
>>> assert cart[0, 2] == 42

Initialize with copy constructor keeps the coordinate system

>>> with vectors.tmp_transform('cylinder'):
...     vect_cyl = tfields.Tensors(vectors)
...     assert vect_cyl.coord_sys == vectors.coord_sys
>>> assert vect_cyl.coord_sys == 'cylinder'

You can demand a special dimension.

>>> _ = tfields.Tensors([[1, 2, 3]], dim=3)
>>> _ = tfields.Tensors([[1, 2, 3]], dim=2)  
Traceback (most recent call last):
    ...
ValueError: Incorrect dimension: 3 given, 2 demanded.

The dimension argument (dim) becomes necessary if you want to initialize an empty array

>>> _ = tfields.Tensors([])  
Traceback (most recent call last):
    ...
ValueError: Empty tensors need dimension parameter 'dim'.
>>> tfields.Tensors([], dim=7)
Tensors([], shape=(0, 7), dtype=float64)
closest(other, **kwargs)[source]
Parameters:
  • other (Tensors) – closest points to what? -> other

  • **kwargs – forwarded to scipy.spatial.cKDTree.query

Returns:

Indices of other points that are closest to

own points

Return type:

array shape(len(self))

Examples

>>> import tfields
>>> m = tfields.Tensors([[1,0,0], [0,1,0], [1,1,0], [0,0,1],
...                      [1,0,1]])
>>> p = tfields.Tensors([[1.1,1,0], [0,0.1,1], [1,0,1.1]])
>>> p.closest(m)
array([2, 3, 4])
contains(other)[source]

Inspired by a speed argument @ stackoverflow.com/questions/14766194/testing-whether-a-numpy-array-contains-a-given-row

Examples

>>> import tfields
>>> p = tfields.Tensors([[1,2,3], [4,5,6], [6,7,8]])
>>> p.contains([4,5,6])
True
coord_sys
cov_eig(weights=None)[source]

Calculate the covariance eigenvectors with lenghts of eigenvalues

Parameters:

weights (np.array | int | None) – index to scalars to weight with

cut(expression, coord_sys=None, return_template=False, **kwargs)[source]

Extract a part of the object according to the logic given by <expression>.

Parameters:
  • expression (sympy logical expression|tfields.TensorFields) – logical expression which will be evaluated. use symbols x, y and z. If tfields.TensorFields or subclass is given, the expression refers to a template.

  • coord_sys (str) – coord_sys to evaluate the expression in. Only active for template expression

Examples

>>> import tfields
>>> import sympy
>>> x, y, z = sympy.symbols('x y z')
>>> p = tfields.Tensors([[1., 2., 3.], [4., 5., 6.], [1, 2, -6],
...                      [-5, -5, -5], [1,0,-1], [0,1,-1]])
>>> p.cut(x > 0).equal([[1, 2, 3],
...                     [4, 5, 6],
...                     [1, 2, -6],
...                     [1, 0, -1]])
True

combinations of cuts

>>> cut_expression = (x > 0) & (z < 0)
>>> combi_cut = p.cut(cut_expression)
>>> combi_cut.equal([[1, 2, -6], [1, 0, -1]])
True

Templates can be used to speed up the repeated cuts on the same underlying tensor with the same expression but new fields. First let us cut a but request the template on return: >>> field1 = list(range(len(p))) >>> tf = tfields.TensorFields(p, field1) >>> tf_cut, template = tf.cut(cut_expression, … return_template=True)

Now repeat the cut with a new field: >>> field2 = p >>> tf.fields.append(field2) >>> tf_template_cut = tf.cut(template) >>> tf_template_cut.equal(combi_cut) True >>> tf_template_cut.fields[0].equal([2, 4]) True >>> tf_template_cut.fields[1].equal(combi_cut) True

Returns:

copy of self with cut applied [optional: template - requires <return_template> switch]

property dim

Manifold dimension

distances(other, **kwargs)[source]
Parameters:
  • other (Iterable) –

  • **kwargs – … is forwarded to scipy.spatial.distance.cdist

Examples

>>> import tfields
>>> p = tfields.Tensors.grid((0, 2, 3j),
...                          (0, 2, 3j),
...                          (0, 0, 1j))
>>> p[4,2] = 1
>>> p.distances(p)[0,0]
0.0
>>> p.distances(p)[5,1]
1.4142135623730951
>>> p.distances([[0,1,2]])[-1][0] == 3
True
dot(b, out=None)[source]

Computes the n-d dot product between self and other defined as in mathematica by summing over the last dimension. When self and b are both one-dimensional vectors, this is just the “usual” dot product; when self and b are 2D matrices, this is matrix multiplication.

Note

  • This is not the same as the numpy.dot function.

Examples

>>> import tfields
>>> import numpy as np

Scalar product by transposed dot product >>> a = tfields.Tensors([[4, 0, 4]]) >>> b = tfields.Tensors([[10, 0, 0.5]]) >>> c = a.t.dot(b) >>> assert c.equal([42]) >>> assert c.equal(np.dot(a[0], b[0])) >>> assert c.rank == 0

To get the angle between a and b you now just need >>> angle = np.arccos(c)

Matrix vector multiplication >>> a = tfields.Tensors([[[1, 20, 0], [2, 18, 1], [1, 5, 10]]]) >>> b = tfields.Tensors([[1, 2, 3]]) >>> c = a.dot(b) >>> assert c.equal([[41,41,41]])

TODO: generalize dot product to inner

# Matrix matrix multiplication can not be done like this. It requires # >>> a = tfields.Tensors([[[1, 8], [2, 4]]]) # >>> b = tfields.Tensors([[[1, 2], [1/2, 1/4]]]) # >>> c = a.dot(b) # >>> c # >>> assert c.equal([[[5, 4], [4, 5]]])

TODO: handle types, fields and maps (which fields etc to choose for the output?)

epsilon_neighbourhood(epsilon)[source]
Returns:

indices for those sets of points that lie within epsilon around the other

Examples

Create mesh grid with one extra point that will have 8 neighbours within epsilon >>> import tfields >>> p = tfields.Tensors.grid((0, 1, 2j), … (0, 1, 2j), … (0, 1, 2j)) >>> p = tfields.Tensors.merged(p, [[0.5, 0.5, 0.5]]) >>> [len(en) for en in p.epsilon_neighbourhood(0.9)] [2, 2, 2, 2, 2, 2, 2, 2, 9]

equal(other, rtol=None, atol=None, equal_nan=False, return_bool=True)[source]

Evaluate, whether the instance has the same content as other.

Parameters:
  • optional – rtol (float) atol (float) equal_nan (bool)

  • numpy.isclose (see) –

evalf(expression=None, coord_sys=None)[source]
Parameters:
  • expression (sympy logical expression) –

  • coord_sys (str) – coord_sys to evalfuate the expression in.

Returns:

mask of dtype bool with lenght of number of points in

self. This array is True, where expression evalfuates True.

Return type:

np.ndarray

Examples

>>> import tfields
>>> import numpy as np
>>> import sympy
>>> x, y, z = sympy.symbols('x y z')
>>> p = tfields.Tensors([[1., 2., 3.], [4., 5., 6.], [1, 2, -6],
...                      [-5, -5, -5], [1,0,-1], [0,1,-1]])
>>> np.array_equal(p.evalf(x > 0),
...                [True, True, True, False, True, False])
True
>>> np.array_equal(p.evalf(x >= 0),
...                [True, True, True, False, True, True])
True

And combination

>>> np.array_equal(p.evalf((x > 0) & (y < 3)),
...                [True, False, True, False, True, False])
True

Or combination

>>> np.array_equal(p.evalf((x > 0) | (y > 3)),
...                [True, True, True, False, True, False])
True
classmethod grid(*base_vectors, **kwargs)[source]
Parameters:
  • *base_vectors (Iterable) – base coordinates. The amount of base vectors defines the dimension

  • **kwargs

    iter_order (list): order in which the iteration will be done.

    Frequency rises with position in list. default is [0, 1, 2] iteration will be done like:

    for v0 in base_vectors[iter_order[0]]:
    for v1 in base_vectors[iter_order[1]]:
    for v2 in base_vectors[iter_order[2]]:

    coords0.append(locals()[‘v%i’ % iter_order[0]]) coords1.append(locals()[‘v%i’ % iter_order[1]]) coords2.append(locals()[‘v%i’ % iter_order[2]])

Examples

Initilaize using the mgrid notation

>>> import numpy as np
>>> import tfields
>>> mgrid = tfields.Tensors.grid((0, 1, 2j), (3, 4, 2j), (6, 7, 2j))
>>> mgrid.equal([[0, 3, 6],
...              [0, 3, 7],
...              [0, 4, 6],
...              [0, 4, 7],
...              [1, 3, 6],
...              [1, 3, 7],
...              [1, 4, 6],
...              [1, 4, 7]])
True

Lists or arrays are accepted also. Furthermore, the iteration order can be changed

>>> lins = tfields.Tensors.grid(
...     np.linspace(3, 4, 2), np.linspace(0, 1, 2),
...     np.linspace(6, 7, 2), iter_order=[1, 0, 2])
>>> lins.equal([[3, 0, 6],
...             [3, 0, 7],
...             [4, 0, 6],
...             [4, 0, 7],
...             [3, 1, 6],
...             [3, 1, 7],
...             [4, 1, 6],
...             [4, 1, 7]])
True
>>> lins2 = tfields.Tensors.grid(np.linspace(0, 1, 2),
...                              np.linspace(3, 4, 2),
...                              np.linspace(6, 7, 2),
...                              iter_order=[2, 0, 1])
>>> lins2.equal([[0, 3, 6],
...              [0, 4, 6],
...              [1, 3, 6],
...              [1, 4, 6],
...              [0, 3, 7],
...              [0, 4, 7],
...              [1, 3, 7],
...              [1, 4, 7]])
True

When given the coord_sys argument, the grid is performed in the given coorinate system:

>>> lins3 = tfields.Tensors.grid(np.linspace(4, 9, 2),
...                              np.linspace(np.pi/2, np.pi/2, 1),
...                              np.linspace(4, 4, 1),
...                              iter_order=[2, 0, 1],
...                              coord_sys=tfields.bases.CYLINDER)
>>> assert lins3.coord_sys == 'cylinder'
>>> lins3.transform('cartesian')
>>> assert np.array_equal(lins3[:, 1], [4, 9])
index(tensor, **kwargs)[source]
Parameters:

tensor

Returns:

index of tensor occuring

Return type:

int

indices(tensor, rtol=None, atol=None)[source]
Returns:

indices of tensor occuring

Return type:

list of int

Examples

Rank 1 Tensors

>>> import tfields
>>> p = tfields.Tensors([[1,2,3], [4,5,6], [6,7,8], [4,5,6],
...                      [4.1, 5, 6]])
>>> p.indices([4,5,6])
array([1, 3])
>>> p.indices([4,5,6.1], rtol=1e-5, atol=1e-1)
array([1, 3, 4])

Rank 0 Tensors

>>> p = tfields.Tensors([2, 3, 6, 3.01])
>>> p.indices(3)
array([1])
>>> p.indices(3, rtol=1e-5, atol=1e-1)
array([1, 3])
main_axes(weights=None)[source]
Returns:

Main Axes eigen-vectors

classmethod merged(*objects, **kwargs)[source]

Factory method Merges all input arguments to one object

Parameters:
  • return_templates (bool) – return the templates which can be used together with cut to retrieve the original objects

  • dim (int) –

  • **kwargs – passed to cls

Examples

>>> import numpy as np
>>> import tfields
>>> import tfields.bases

The new object with turn out in the most frequent coordinate system if not specified explicitly

>>> vec_a = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> vec_b = tfields.Tensors([[5, 4, 1]],
...     coord_sys=tfields.bases.cylinder)
>>> vec_c = tfields.Tensors([[4, 2, 3]],
...     coord_sys=tfields.bases.cylinder)
>>> merge = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, [[2, 0, 1]])
>>> assert merge.coord_sys == 'cylinder'
>>> assert merge.equal([[0, 0, 0],
...                     [0, 0, 1],
...                     [1, -np.pi / 2, 0],
...                     [5, 4, 1],
...                     [4, 2, 3],
...                     [2, 0, 1]])

Merge also shifts the maps to still refer to the same tensors

>>> tm_a = tfields.TensorMaps(merge, maps=[[[0, 1, 2]]])
>>> tm_b = tm_a.copy()
>>> assert tm_a.coord_sys == 'cylinder'
>>> tm_merge = tfields.TensorMaps.merged(tm_a, tm_b)
>>> assert tm_merge.coord_sys == 'cylinder'
>>> assert tm_merge.maps[3].equal([[0, 1, 2],
...                               list(range(len(merge),
...                                          len(merge) + 3,
...                                          1))])
>>> obj_list = [tfields.Tensors([[1, 2, 3]],
...             coord_sys=tfields.bases.CYLINDER),
...             tfields.Tensors([[3] * 3]),
...             tfields.Tensors([[5, 1, 3]])]
>>> merge2 = tfields.Tensors.merged(
...     *obj_list, coord_sys=tfields.bases.CARTESIAN)
>>> assert merge2.equal([[-0.41614684, 0.90929743, 3.],
...                      [3, 3, 3], [5, 1, 3]], atol=1e-8)

The return_templates argument allows to retrieve a template which can be used with the cut method.

>>> merge, templates = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, return_templates=True)
>>> assert merge.cut(templates[0]).equal(vec_a)
>>> assert merge.cut(templates[1]).equal(vec_b)
>>> assert merge.cut(templates[2]).equal(vec_c)
min_dists(other=None, **kwargs)[source]
Parameters:
  • other (array | None) – if None: closest distance to self

  • **kwargs

    memory_saving (bool): for very large array comparisons

    default False

    … rest is forwarded to scipy.spatial.distance.cdist

Returns:

minimal distances of self to other

Return type:

np.array

Examples

>>> import tfields
>>> import numpy as np
>>> p = tfields.Tensors.grid((0, 2, 3),
...                          (0, 2, 3),
...                          (0, 0, 1))
>>> p[4,2] = 1
>>> dMin = p.min_dists()
>>> expected = [1] * 9
>>> expected[4] = np.sqrt(2)
>>> np.array_equal(dMin, expected)
True
>>> dMin2 = p.min_dists(memory_saving=True)
>>> bool((dMin2 == dMin).all())
True
mirror(coordinate, condition=None)[source]

Reflect/Mirror the entries meeting <condition> at <coordinate> = 0

Parameters:

coordinate (int) – coordinate index

Examples

>>> import tfields
>>> p = tfields.Tensors([[1., 2., 3.], [4., 5., 6.], [1, 2, -6]])
>>> p.mirror(1)
>>> assert p.equal([[1, -2, 3], [4, -5,  6], [1, -2, -6]])

multiple coordinates can be mirrored at the same time i.e. a point mirrorion would be

>>> p = tfields.Tensors([[1., 2., 3.], [4., 5., 6.], [1, 2, -6]])
>>> p.mirror([0,2])
>>> assert p.equal([[-1, 2, -3], [-4, 5, -6], [-1, 2., 6.]])

You can give a condition as mask or as str. The mirroring will only be applied to the points meeting the condition.

>>> import sympy
>>> x, y, z = sympy.symbols('x y z')
>>> p.mirror([0, 2], y > 3)
>>> p.equal([[-1, 2, -3], [4, 5, 6], [-1, 2, 6]])
True
moment(moment, weights=None)[source]
Returns:

Moments of the distribution.

Parameters:

moment (int) – n-th moment

Examples

>>> import tfields

Skalars

>>> t = tfields.Tensors(range(1, 6))
>>> assert t.moment(1) == 0
>>> assert t.moment(1, weights=[-2, -1, 20, 1, 2]) == 0.5
>>> assert t.moment(2, weights=[0.25, 1, 17.5, 1, 0.25]) == 0.2

Vectors

>>> t = tfields.Tensors(list(zip(range(1, 6), range(1, 6))))
>>> assert tfields.Tensors([0.5, 0.5]).equal(
...     t.moment(1, weights=[-2, -1, 20, 1, 2]))
>>> assert tfields.Tensors([1. , 0.5]).equal(
...     t.moment(1, weights=list(zip([-2, -1, 10, 1, 2],
...                                  [-2, -1, 20, 1, 2]))))
name
norm(ord=None, axis=None, keepdims=False)[source]

Calculate the norm up to rank 2

Parameters:
  • axis (See numpy.linal.norm except redefinition in) –

  • axis – by default omitting first axis

Examples

>>> import tfields
>>> a = tfields.Tensors([[1, 0, 0]])
>>> assert a.norm().equal([1])
normalized(*args, **kwargs)[source]

Return the self / norm(self)

Parameters:

to (forwarded) – meth:norm

Examples

>>> import tfields
>>> a = tfields.Tensors([[1, 4, 3]])
>>> assert not a.norm().equal([1])
>>> a = a.normalized()
>>> assert a.norm().equal([1])
>>> a = tfields.Tensors([[1, 0, 0],
...                      [0, 2, 0],
...                      [0, 0, 3]])
>>> assert a.norm().equal([1, 2, 3])
>>> a = a.normalized()
>>> assert a.equal([
...     [1, 0, 0],
...     [0, 1, 0],
...     [0, 0, 1],
... ])
>>> assert a.norm().equal([1, 1, 1])
plot(*args, **kwargs)[source]

Generic plotting method of Tensors.

Forwarding to rna.plotting.plot_tensor

property rank

Tensor rank

property t

Same as self.T but for tensor dimension only. Keeping the order of stacked tensors.

Examples

>>> import tfields
>>> a = tfields.Tensors([[[1,2,3,4],[5,6,7,8]]])
>>> assert a.t.equal([a[0].T])
tmp_transform(coord_sys)[source]

Temporarily change the coord_sys to another coord_sys and change it back at exit This method is for cleaner code only. No speed improvements go with this.

Parameters:

transform (see) –

Examples

>>> import tfields
>>> p = tfields.Tensors([[1,2,3]], coord_sys=tfields.bases.SPHERICAL)
>>> with p.tmp_transform(tfields.bases.CYLINDER):
...     assert p.coord_sys == tfields.bases.CYLINDER
>>> assert p.coord_sys == tfields.bases.SPHERICAL
to_segment(segment, num_segments, coordinate, periodicity=6.283185307179586, offset=0.0, coord_sys=None)[source]

For circular (close into themself after <periodicity>) coordinates at index <coordinate> assume <num_segments> segments and transform all values to segment number <segment>

Parameters:
  • segment (int) – segment index (starting at 0)

  • num_segments (int) – number of segments

  • coordinate (int) – coordinate index

  • periodicity (float) – after what lenght, the coordiante repeats

  • offset (float) – offset in the mapping

  • coord_sys (str or sympy.CoordinateSystem) – in which coord sys the transformation should be done

Examples

>>> import tfields
>>> import numpy as np
>>> pStart = tfields.Points3D([[6, 2 * np.pi, 1],
...                            [6, 2 * np.pi / 5 * 3, 1]],
...                           coord_sys='cylinder')
>>> p = tfields.Points3D(pStart)
>>> p.to_segment(0, 5, 1, offset=-2 * np.pi / 10)
>>> assert np.array_equal(p[:, 1], [0, 0])
>>> p2 = tfields.Points3D(pStart)
>>> p2.to_segment(1, 5, 1, offset=-2 * np.pi / 10)
>>> assert np.array_equal(np.round(p2[:, 1], 4), [1.2566] * 2)
transform(coord_sys, **kwargs)[source]
Parameters:

coord_sys (str) –

Examples

>>> import numpy as np
>>> import tfields

CARTESIAN to SPHERICAL >>> t = tfields.Tensors([[1, 2, 2], [1, 0, 0], [0, 0, -1], … [0, 0, 1], [0, 0, 0]]) >>> t.transform(‘spherical’)

r

>>> assert t[0, 0] == 3

phi

>>> assert t[1, 1] == 0.
>>> assert t[2, 1] == 0.

theta is 0 at (0, 0, 1) and pi / 2 at (0, 0, -1)

>>> assert round(t[1, 2], 10) == round(0, 10)
>>> assert t[2, 2] == -np.pi / 2
>>> assert t[3, 2] == np.pi / 2

theta is defined 0 for R == 0

>>> assert t[4, 0] == 0.
>>> assert t[4, 2] == 0.

CARTESIAN to CYLINDER

>>> tCart = tfields.Tensors([[3, 4, 42], [1, 0, 0], [0, 1, -1],
...                          [-1, 0, 1], [0, 0, 0]])
>>> t_cyl = tCart.copy()
>>> t_cyl.transform('cylinder')
>>> assert t_cyl.coord_sys == 'cylinder'

R

>>> assert t_cyl[0, 0] == 5
>>> assert t_cyl[1, 0] == 1
>>> assert t_cyl[2, 0] == 1
>>> assert t_cyl[4, 0] == 0

Phi

>>> assert round(t_cyl[0, 1], 10) == round(np.arctan(4. / 3), 10)
>>> assert t_cyl[1, 1] == 0
>>> assert round(t_cyl[2, 1], 10) == round(np.pi / 2, 10)
>>> assert t_cyl[1, 1] == 0

Z

>>> assert t_cyl[0, 2] == 42
>>> assert t_cyl[2, 2] == -1
>>> t_cyl.transform('cartesian')
>>> assert t_cyl.coord_sys == 'cartesian'
>>> assert round(t_cyl[0, 0], 10) == 3
tfields.core.as_fields(fields)[source]

Setter for TensorFields.fields Copies input .. rubric:: Examples

>>> import tfields
>>> scalars = tfields.Tensors([0, 1, 2])
>>> vectors = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> maps = [tfields.TensorFields([[0, 1, 2], [0, 1, 2]]),
...         tfields.TensorFields([[1], [2]], [-42, -21])]
>>> mesh = tfields.TensorMaps(vectors, scalars,
...                           maps=maps)
>>> mesh.maps[3].fields = [[42, 21]]
>>> assert len(mesh.maps[3].fields) == 1
>>> assert mesh.maps[3].fields[0].equal([42, 21])
tfields.core.as_maps(maps)[source]

Setter for TensorMaps.maps Copies input

tfields.core.dim(tensor)[source]

Manifold dimension

tfields.core.rank(tensor)[source]

Tensor rank

tfields.mask module

Author: Daniel Boeckenhoff Mail: daniel.boeckenhoff@ipp.mpg.de

part of tfields library contains interaction methods for sympy and numpy

tfields.mask.evalf(array, cut_expression=None, coords=None)[source]

Linking sympy and numpy by retrieving a mask according to the cut_expression

Parameters:
  • array (numpy ndarray) –

  • cut_expression (sympy logical expression) –

  • coord_sys (str) – coord_sys to evalfuate the expression in.

Returns:

mask which is True, where cut_expression evalfuates True.

Return type:

np.array

Examples

>>> import sympy
>>> import numpy as np
>>> import tfields
>>> x, y, z = sympy.symbols('x y z')
>>> a = np.array([[1., 2., 3.], [4., 5., 6.], [1, 2, -6],
...               [-5, -5, -5], [1,0,-1], [0,1,-1]])
>>> assert np.array_equal(
...     tfields.evalf(a, x > 0),
...     np.array([ True, True, True, False, True, False]))

And combination >>> assert np.array_equal( … tfields.evalf(a, (x > 0) & (y < 3)), … np.array([True, False, True, False, True, False]))

Or combination >>> assert np.array_equal( … tfields.evalf(a, (x > 0) | (y > 3)), … np.array([True, True, True, False, True, False]))

If array of other shape than (?, 3) is given, the coords need to be specified >>> a0, a1 = sympy.symbols(‘a0 a1’) >>> assert np.array_equal( … tfields.evalf([[0., 1.], [-1, 3]], a1 > 2, coords=[a0, a1]), … np.array([False, True], dtype=bool))

>= is taken care of >>> assert np.array_equal( … tfields.evalf(a, x >= 0), … np.array([ True, True, True, False, True, True]))

tfields.mesh_3d module

Author: Daniel Boeckenhoff Mail: daniel.boeckenhoff@ipp.mpg.de

Triangulated mesh class and methods

class tfields.mesh_3d.Mesh3D(tensors, *fields, **kwargs)[source]

Bases: TensorMaps

Points3D child used as vertices combined with faces to build a geometrical mesh of triangles .. rubric:: Examples

>>> import tfields
>>> import numpy as np
>>> m = tfields.Mesh3D([[1,2,3], [3,3,3], [0,0,0], [5,6,7]], faces=[[0, 1, 2], [1, 2, 3]])
>>> m.equal([[1, 2, 3],
...          [3, 3, 3],
...          [0, 0, 0],
...          [5, 6, 7]])
True
>>> np.array_equal(m.faces, [[0, 1, 2], [1, 2, 3]])
True

conversion to points only >>> tfields.Points3D(m).equal([[1, 2, 3], … [3, 3, 3], … [0, 0, 0], … [5, 6, 7]]) True

Empty instances >>> m = tfields.Mesh3D([]);

going from Mesh3D to Triangles3D instance is easy and will be cached. >>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], faces=[[0, 1, 2]]); >>> assert m.triangles().equal(tfields.Triangles3D([[ 1., 0., 0.], … [ 0., 1., 0.], … [ 0., 0., 0.]]))

a list of scalars is assigned to each face >>> mScalar = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], … faces=([[0, 1, 2]], [.5])); >>> np.array_equal(mScalar.faces.fields, [[ 0.5]]) True

adding together two meshes: >>> m2 = tfields.Mesh3D([[1,0,0],[2,0,0],[0,3,0]], … faces=([[0,1,2]], [.7])) >>> msum = tfields.Mesh3D.merged(mScalar, m2) >>> msum.equal([[ 1., 0., 0.], … [ 0., 1., 0.], … [ 0., 0., 0.], … [ 1., 0., 0.], … [ 2., 0., 0.], … [ 0., 3., 0.]]) True >>> assert np.array_equal(msum.faces, [[0, 1, 2], [3, 4, 5]])

Saving and reading >>> from tempfile import NamedTemporaryFile >>> outFile = NamedTemporaryFile(suffix=’.npz’) >>> m.save(outFile.name) >>> _ = outFile.seek(0) >>> m1 = tfields.Mesh3D.load(outFile.name, allow_pickle=True) >>> bool(np.all(m == m1)) True >>> assert np.array_equal(m1.faces, np.array([[0, 1, 2]]))

centroids()[source]
coord_sys
cut(*args, **kwargs)[source]

cut method for Mesh3D. :param expression:

sympy locical expression: Sympy expression that defines planes

in 3D

Mesh3D: A mesh3D will be interpreted as a template, i.e. a

fast instruction of how to cut the triangles. It is the second part of the tuple, returned by a previous cut with a sympy locial expression with ‘return_template=True’. We use the vertices and maps of the Mesh as the skelleton of the returned mesh. The fields are mapped according to indices in the template.maps[i].fields.

Parameters:
  • coord_sys (coordinate system to cut in) –

  • at_intersection (str) –

    instruction on what to do, when a cut will intersect a triangle. Options: ‘remove’ (Default) - remove the faces that are on the edge

    ’keep’ - keep the faces that are on the edge ‘split’ - Create new triangles that make up the old one.

  • return_template (bool) – If True: return the template to redo the same cut fast

Examples

define the cut >>> import numpy as np >>> import tfields >>> from sympy.abc import x,y,z >>> cut_expr = x > 1.5

>>> m = tfields.Mesh3D.grid((0, 3, 4),
...                         (0, 3, 4),
...                         (0, 0, 1))
>>> m.fields.append(tfields.Tensors(np.linspace(0, len(m) - 1,
...                                             len(m))))
>>> m.maps[3].fields.append(
...     tfields.Tensors(np.linspace(0,
...                                 len(m.maps[3]) - 1,
...                                 len(m.maps[3]))))
>>> mNew = m.cut(cut_expr)
>>> len(mNew)
8
>>> mNew.nfaces()
6
>>> float(mNew[:, 0].min())
2.0

Cutting with the ‘keep’ option will leave triangles on the edge untouched: >>> m_keep = m.cut(cut_expr, at_intersection=’keep’) >>> float(m_keep[:, 0].min()) 1.0 >>> m_keep.nfaces() 12

Cutting with the ‘split’ option will create new triangles on the edge: >>> m_split = m.cut(cut_expr, at_intersection=’split’) >>> float(m_split[:, 0].min()) 1.5 >>> len(m_split) 15 >>> m_split.nfaces() 15

Cut with ‘return_template=True’ will return the exact same mesh but additionally an instruction to conduct the exact same cut fast (template) >>> m_split_2, template = m.cut(cut_expr, at_intersection=’split’, … return_template=True) >>> m_split_template = m.cut(template) >>> assert m_split.equal(m_split_2, equal_nan=True) >>> assert m_split.equal(m_split_template, equal_nan=True) >>> assert len(template.fields) == 1 >>> assert len(m_split.fields) == 1 >>> assert len(m_split_template.fields) == 1 >>> assert m_split.fields[0].equal( … list(range(8, 16)) + [np.nan] * 7, equal_nan=True) >>> assert m_split_template.fields[0].equal( … list(range(8, 16)) + [np.nan] * 7, equal_nan=True)

This seems irrelevant at first but consider, the map field or the tensor field changes: >>> m_altered_fields = m.copy() >>> m_altered_fields[0] += 42 >>> assert not m_split.equal(m_altered_fields.cut(template)) >>> assert tfields.Tensors(m_split).equal( … m_altered_fields.cut(template)) >>> assert tfields.Tensors(m_split.maps[3]).equal( … m_altered_fields.cut(template).maps[3])

The cut expression may be a sympy.BooleanFunction: >>> cut_expr_bool_fun = (x > 1.5) & (y < 1.5) & (y >0.2) & (z > -0.5) >>> m_split_bool = m.cut(cut_expr_bool_fun, … at_intersection=’split’)

Returns:

copy of cut mesh * optional: template

disjoint_parts(return_template=False)[source]
Returns:

disjoint_parts(List(cls)), templates(List(cls))

>>> import tfields
>>> a = tfields.Mesh3D(
...     [[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]],
...     maps=[[[0, 1, 2], [0, 2, 3]]])
>>> b = a.copy()
>>> b[:, 0] += 2
>>> m = tfields.Mesh3D.merged(a, b)
>>> parts = m.disjoint_parts()
>>> aa, ba = parts
>>> assert aa.maps[3].equal(ba.maps[3])
>>> assert aa.equal(a)
>>> assert ba.equal(b)

property faces
fields
classmethod grid(*base_vectors, **kwargs)[source]

Construct ‘cuboid’ along base_vectors .. rubric:: Examples

Building symmetric geometries were never as easy:

Approximated sphere with radius 1, translated in y by 2 units >>> import numpy as np >>> import tfields >>> sphere = tfields.Mesh3D.grid((1, 1, 1), … (-np.pi, np.pi, 12), … (-np.pi / 2, np.pi / 2, 12), … coord_sys=’spherical’) >>> sphere.transform(‘cartesian’) >>> sphere[:, 1] += 2

Oktaeder >>> oktaeder = tfields.Mesh3D.grid((1, 1, 1), … (-np.pi, np.pi, 5), … (-np.pi / 2, np.pi / 2, 3), … coord_sys=’spherical’) >>> oktaeder.transform(‘cartesian’)

Cube with edge length of 2 units >>> cube = tfields.Mesh3D.grid((-1, 1, 2), … (-1, 1, 2), … (-5, -3, 2))

Cylinder >>> cylinder = tfields.Mesh3D.grid((1, 1, 1), … (-np.pi, np.pi, 12), … (-5, 3, 12), … coord_sys=’cylinder’) >>> cylinder.transform(‘cartesian’)

in_faces(points, delta, **kwargs)[source]

Check whether points lie within triangles with Barycentric Technique see Triangles3D.in_triangles. If multiple requests are done on huge meshes, this can be hugely optimized by requesting the property self.tree or setting it to self.tree = <saved tree> before calling in_faces.

maps
name
nfaces()[source]
classmethod plane(*base_vectors, **kwargs)[source]

Alternative constructor for creating a plane from :param *base_vectors: see grid constructors in core. One base_vector has

to be one-dimensional

Parameters:

**kwargs – forwarded to __new__

planes()[source]
project(tensor_field, delta=None, merge_functions=None, point_face_assignment=None, return_point_face_assignment=False)[source]

Project the points of the tensor_field to a copy of the mesh and set the face values accord to the field to the maps field. If no field is present in tensor_field, the number of points in a mesh is counted.

Parameters:
  • tensor_field (Tensors | TensorFields) –

  • delta (float | None) – forwarded to Mesh3D.in_faces

  • merge_functions (callable) – if multiple Tensors lie in the same face, they are mapped with the merge_function to one value

  • point_face_assignment (np.array, dtype=int) – array assigning each point to a face. Each entry position corresponds to a point of the tensor, each entry value is the index of the assigned face

  • return_point_face_assignment (bool) – if true, return the point_face_assignment

Examples

>>> import tfields
>>> import numpy as np
>>> mp = tfields.TensorFields([[0,1,2],[2,3,0],[3,2,5],[5,4,3]],
...                           [1, 2, 3, 4])
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [1,1,0], [0,1,0], [0,2,0], [1,2,0]],
...                     maps=[mp])
>>> points = tfields.Tensors([[0.5, 0.2, 0.0],
...                           [0.5, 0.02, 0.0],
...                           [0.5, 0.8, 0.0],
...                           [0.5, 0.8, 0.1]])  # not contained

Projecting points onto the mesh gives the count >>> m_points = m.project(points, delta=0.01) >>> list(m_points.maps[3].fields[0]) [2, 1, 0, 0]

TensorFields with arbitrary size are projected, combinging the fields automatically >>> fields = [tfields.Tensors([1,3,42, -1]), … tfields.Tensors([[0,1,2], [2,3,4], [3,4,5], [-1] * 3]), … tfields.Tensors([[[0, 0]] * 2, … [[2, 2]] * 2, … [[3, 3]] * 2, … [[9, 9]] * 2])] >>> tf = tfields.TensorFields(points, *fields) >>> m_tf = m.project(tf, delta=0.01) >>> assert m_tf.maps[3].fields[0].equal([2, 42, np.nan, np.nan], equal_nan=True) >>> assert m_tf.maps[3].fields[1].equal([[1, 2, 3], … [3, 4, 5], … [np.nan] * 3, … [np.nan] * 3], … equal_nan=True) >>> assert m_tf.maps[3].fields[2].equal([[[1, 1]] * 2, … [[3, 3]] * 2, … [[np.nan, np.nan]] * 2, … [[np.nan, np.nan]] * 2], … equal_nan=True)

Returning the calculated point_face_assignment can speed up multiple results >>> m_tf, point_face_assignment = m.project(tf, delta=0.01, … return_point_face_assignment=True) >>> m_tf_fast = m.project(tf, delta=0.01, point_face_assignment=point_face_assignment) >>> assert m_tf.equal(m_tf_fast, equal_nan=True)

remove_faces(face_delete_mask)[source]

Remove faces where face_delete_mask is True

template(sub_mesh)[source]

‘Manual’ way to build a template that can be used with self.cut :returns:

template (see cut), can be used as template to retrieve

sub_mesh from self instance

Return type:

Mesh3D

Examples

>>> import tfields
>>> from sympy.abc import y
>>> mp = tfields.TensorFields([[0,1,2],[2,3,0],[3,2,5],[5,4,3]],
...                           [1, 2, 3, 4])
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [1,1,0], [0,1,0], [0,2,0], [1,2,0]],
...                     maps=[mp])
>>> m_cut = m.cut(y < 1.5, at_intersection='split')
>>> template = m.template(m_cut)
>>> assert m_cut.equal(m.cut(template))
property tree

Cached property to retrieve a bounding_box Searcher. This searcher can hugely optimize ‘in_faces’ searches

Examples

>>> import numpy as np
>>> import tfields
>>> mesh = tfields.Mesh3D.grid((0, 1, 3), (1, 2, 3), (2, 3, 3))
>>> _ = mesh.tree
>>> assert hasattr(mesh, '_cache')
>>> assert 'mesh_tree' in mesh._cache
>>> face_indices = mesh.in_faces(tfields.Points3D([[0.2, 1.2, 2.0]]),
...                      0.00001)

You might want to know the number of points per face >>> unique, counts = np.unique(face_indices, return_counts=True) >>> dict(zip(unique, counts)) # one point on triangle number 16 {16: 1}

triangles()[source]

Cached method to retrieve the triangles, belonging to this mesh .. rubric:: Examples

>>> import tfields
>>> mesh = tfields.Mesh3D.grid((0, 1, 3), (1, 2, 3), (2, 3, 3))
>>> assert mesh.triangles() is mesh.triangles()

tfields.planes_3d module

Author: Daniel Boeckenhoff Mail: daniel.boeckenhoff@ipp.mpg.de

part of tfields library

class tfields.planes_3d.Planes3D(tensors, *fields, **kwargs)[source]

Bases: TensorFields

Point-NormVector representaion of planes

Examples

>>> import tfields
>>> points = [[0, 1, 0]]
>>> norms = [[0, 0, 1]]
>>> plane = tfields.Planes3D(points, norms)
>>> plane.symbolic()[0]
Plane(Point3D(0, 1, 0), (0, 0, 1))
coord_sys
fields
name
plot(**kwargs)[source]

forward to Mesh3D plotting

symbolic()[source]
Returns:

list with sympy.Plane objects

Return type:

list

tfields.points_3d module

Author: Daniel Boeckenhoff Mail: daniel.boeckenhoff@ipp.mpg.de

basic threedimensional tensors

class tfields.points_3d.Points3D(tensors, **kwargs)[source]

Bases: Tensors

Points3D is a general class for 3D Point operations and storage. Points are stored in np.arrays of shape (len, 3). Thus the three coordinates of the Points stay close.

Parameters:
  • constructor (points3DInstance -> copy) –

  • [points3DInstance1

  • points3DInstance2

  • treated (...] -> coord_sys are correctly) –

  • coordinates (list of) –

Kwargs:
coord_sys (str):

Use tfields.bases.CARTESIAN -> x, y, z Use tfields.bases.CYLINDER -> r, phi, z Use tfields.bases.SPHERICAL -> r, phi, theta

Examples

Initializing with 3 vectors >>> import tfields >>> import numpy as np >>> p1 = tfields.Points3D([[1., 2., 3.], [4., 5., 6.], [1, 2, -6]]) >>> assert p1.equal([[1., 2., 3.], … [4., 5., 6.], … [1., 2., -6.]])

Initializing with list of coordinates >>> p2 = tfields.Points3D(np.array([[1., 2., 3., 4, 5,], … [4., 5., 6., 7, 8], … [1, 2, -6, -1, 0]]).T) >>> assert p2.equal( … [[ 1., 4., 1.], … [ 2., 5., 2.], … [ 3., 6., -6.], … [ 4., 7., -1.], … [ 5., 8., 0.]], atol=1e-8) >>> p2.transform(tfields.bases.CYLINDER) >>> assert p2.equal( … [[ 4.12310563, 1.32581766, 1.], … [ 5.38516481, 1.19028995, 2.], … [ 6.70820393, 1.10714872, -6.], … [ 8.06225775, 1.05165021, -1.], … [ 9.43398113, 1.01219701, 0.]], atol=1e-8)

Copy constructor with one instance preserves coord_sys of instance >>> assert tfields.Points3D(p2).coord_sys == p2.coord_sys

Unless you specify other: >>> assert tfields.Points3D(p2, … coord_sys=tfields.bases.CARTESIAN).equal( … [[ 1., 4., 1.], … [ 2., 5., 2.], … [ 3., 6., -6.], … [ 4., 7., -1.], … [ 5., 8., 0.]], atol=1e-8)

Copy constructor with many instances chooses majority of coordinates systems to avoid much transformation >>> assert tfields.Points3D.merged(p1, p2, p1).equal( … [[ 1., 2., 3.], … [ 4., 5., 6.], … [ 1., 2., -6.], … [ 1., 4., 1.], … [ 2., 5., 2.], … [ 3., 6., -6.], … [ 4., 7., -1.], … [ 5., 8., 0.], … [ 1., 2., 3.], … [ 4., 5., 6.], … [ 1., 2., -6.]], atol=1e-8) >>> p1.transform(tfields.bases.CYLINDER)

… unless specified other. Here it is specified >>> assert tfields.Points3D.merged( … p1, p2, coord_sys=tfields.bases.CYLINDER).equal( … [[ 2.23606798, 1.10714872, 3. ], … [ 6.40312424, 0.89605538, 6. ], … [ 2.23606798, 1.10714872, -6. ], … [ 4.12310563, 1.32581766, 1. ], … [ 5.38516481, 1.19028995, 2. ], … [ 6.70820393, 1.10714872, -6. ], … [ 8.06225775, 1.05165021, -1. ], … [ 9.43398113, 1.01219701, 0. ]], atol=1e-8)

Shape is always (…, 3) >>> p = tfields.Points3D([[1., 2., 3.], [4., 5., 6.], … [1, 2, -6], [-5, -5, -5], [1,0,-1], [0,1,-1]]) >>> p.shape (6, 3)

Empty array will create an ndarray of the form (0, 3) >>> tfields.Points3D([]) Points3D([], shape=(0, 3), dtype=float64)

Use it as np.ndarrays -> masking etc. is inherited >>> mask = np.array([True, False, True, False, False, True]) >>> mp = p[mask].copy()

Copy constructor >>> assert mp.equal( … [[ 1., 2., 3.], … [ 1., 2., -6.], … [ 0., 1., -1.]]) >>> assert tfields.Points3D(mp).equal( … [[ 1., 2., 3.], … [ 1., 2., -6.], … [ 0., 1., -1.]])

Coordinate system is implemented. Default is cartesian >>> p_cart = p.copy() >>> p.transform(tfields.bases.CYLINDER) >>> assert p.equal( … tfields.Points3D([[2.236, 1.107, 3.], … [6.403, 0.896, 6.], … [2.236, 1.107, -6.], … [7.071, -2.356, -5.], … [1. , 0. , -1.], … [1. , 1.571, -1.]], … coord_sys=tfields.bases.CYLINDER), … atol=1e-3) >>> p.transform(tfields.bases.CARTESIAN) >>> assert p.equal(p_cart, atol=1e-15)

balls(radius, spacing=(5, 3))[source]
Parameters:
  • radius (float) – radius of spheres

  • spacing (tuple of int) – n_phi, n_theta

Returns:

Builds a sphere around each point with a resolution

defined by spacing and given radius

Return type:

tfields.Mesh3D

coord_sys
name

tfields.tensor_grid module

Implementaiton of TensorGrid class

class tfields.tensor_grid.TensorGrid(tensors, *fields, **kwargs)[source]

Bases: TensorFields

A Tensor Grid is a TensorField which is aware of it’s grid nature, which is order of iteration (iter-order) over the base vectors (base_vectors).

Parameters:
  • *base_vectors (tuple) – indices of the axes which should be iterated

  • **kwargs – num (np.array): same as np.linspace ‘num’ iter_order (np.array): index order of building the grid. further: see TensorFields class

base_num_tuples()[source]

Returns the grid style base_vectors + num tuples

base_vectors
change_iter_order(iter_order)[source]

Transform the iter order

coord_sys
classmethod empty(*base_vectors, **kwargs)[source]

Build the grid (implicitly) from base vectors

explicit()[source]

Build the grid explicitly (e.g. after changing base_vector, iter_order or init with empty)

fields
classmethod grid(*base_vectors, tensors=None, fields=None, **kwargs)[source]

Build the grid (explicitly) from base vectors

Parameters:
  • args (explicit) – see __new__

  • **kwargs – see TensorFields

is_empty()[source]

Check if the object is an implicit grid (base points are empty but base_vectors and iter order can be used to build the explicit grid’s base points).

iter_order
classmethod merged(*objects, **kwargs)[source]

Factory method Merges all input arguments to one object

Parameters:
  • return_templates (bool) – return the templates which can be used together with cut to retrieve the original objects

  • dim (int) –

  • **kwargs – passed to cls

Examples

>>> import numpy as np
>>> import tfields
>>> import tfields.bases

The new object with turn out in the most frequent coordinate system if not specified explicitly

>>> vec_a = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> vec_b = tfields.Tensors([[5, 4, 1]],
...     coord_sys=tfields.bases.cylinder)
>>> vec_c = tfields.Tensors([[4, 2, 3]],
...     coord_sys=tfields.bases.cylinder)
>>> merge = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, [[2, 0, 1]])
>>> assert merge.coord_sys == 'cylinder'
>>> assert merge.equal([[0, 0, 0],
...                     [0, 0, 1],
...                     [1, -np.pi / 2, 0],
...                     [5, 4, 1],
...                     [4, 2, 3],
...                     [2, 0, 1]])

Merge also shifts the maps to still refer to the same tensors

>>> tm_a = tfields.TensorMaps(merge, maps=[[[0, 1, 2]]])
>>> tm_b = tm_a.copy()
>>> assert tm_a.coord_sys == 'cylinder'
>>> tm_merge = tfields.TensorMaps.merged(tm_a, tm_b)
>>> assert tm_merge.coord_sys == 'cylinder'
>>> assert tm_merge.maps[3].equal([[0, 1, 2],
...                               list(range(len(merge),
...                                          len(merge) + 3,
...                                          1))])
>>> obj_list = [tfields.Tensors([[1, 2, 3]],
...             coord_sys=tfields.bases.CYLINDER),
...             tfields.Tensors([[3] * 3]),
...             tfields.Tensors([[5, 1, 3]])]
>>> merge2 = tfields.Tensors.merged(
...     *obj_list, coord_sys=tfields.bases.CARTESIAN)
>>> assert merge2.equal([[-0.41614684, 0.90929743, 3.],
...                      [3, 3, 3], [5, 1, 3]], atol=1e-8)

The return_templates argument allows to retrieve a template which can be used with the cut method.

>>> merge, templates = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, return_templates=True)
>>> assert merge.cut(templates[0]).equal(vec_a)
>>> assert merge.cut(templates[1]).equal(vec_b)
>>> assert merge.cut(templates[2]).equal(vec_c)
name
num
property rank

Tensor rank

tfields.triangles_3d module

Author: Daniel Boeckenhoff Mail: daniel.boeckenhoff@ipp.mpg.de

part of tfields library

class tfields.triangles_3d.Triangles3D(tensors, *fields, **kwargs)[source]

Bases: TensorFields

Points3D child restricted to n * 3 Points. Three Points always group together to one triangle.

Parameters:
  • tensors (Iterable | tfields.TensorFields) –

  • *fields (Iterable | tfields.Tensors) – Fields with the same length as tensors

  • **kwargs – passed to base class

see :class:`~tfields.TensorFields`

Examples

>>> import tfields
>>> t = tfields.Triangles3D([[1,2,3], [3,3,3], [0,0,0]])

You can add fields to each triangle

>>> t = tfields.Triangles3D(t, tfields.Tensors([42]))
>>> assert t.fields[0].equal([42])
areas(transform=None)[source]

Calculate area with “heron’s formula”

Parameters:

transform (np.ndarray) – optional transformation matrix The triangle points are transformed with transform if given before calclulating the area

Examples

>>> import numpy as np
>>> import tfields
>>> m = tfields.Mesh3D([[1,0,0], [0,0,1], [0,0,0]],
...                    faces=[[0, 1, 2]])
>>> assert np.allclose(m.triangles().areas(), np.array([0.5]))
>>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [0,0,1]],
...                    faces=[[0, 1, 2], [1, 2, 3]])
>>> assert np.allclose(m.triangles().areas(), np.array([0.5, 0.5]))
>>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [1,1,0], [0,0,1], [1,0,1]],
...                    faces=[[0, 1, 2], [0, 3, 4]])
>>> assert np.allclose(m.triangles().areas(), np.array([0.5, 0.5]))
centroids()[source]
Returns:

_centroids()

Examples

>>> import tfields
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
...                    faces=[[0, 1, 3],[0, 2, 3],[1,2,4], [1, 3, 4]]);
>>> assert m.triangles().centroids().equal(
...     [[1./3, 1./3, 0.],
...      [-1./3, 1./3, 0.],
...      [0., 0., 1./3],
...      [1./3, 1./3, 1./3]])
circumcenters()[source]

Semi baricentric method to calculate circumcenter points of the triangles

Examples

>>> import numpy as np
>>> import tfields
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
...                    faces=[[0, 1, 3],[0, 2, 3],[1,2,4], [1, 3, 4]]);
>>> assert np.allclose(
...     m.triangles().circumcenters(),
...     [[0.5, 0.5, 0.0],
...      [-0.5, 0.5, 0.0],
...      [0.0, 0.0, 0.0],
...      [1.0 / 3, 1.0 / 3, 1.0 / 3]])
coord_sys
corners()[source]
Returns:

three np.arrays with corner points of triangles

cut(expression, coord_sys=None)[source]

Default cut method for Triangles3D

Examples

>>> import sympy
>>> import numpy as np
>>> import tfields
>>> x, y, z = sympy.symbols('x y z')
>>> t = tfields.Triangles3D([[1., 2., 3.], [-4., 5., 6.], [1, 2, -6],
...                          [5, -5, -5], [1, 0, -1], [0, 1, -1],
...                          [-5, -5, -5], [1, 0, -1], [0, 1, -1]])
>>> tc = t.cut(x >= 0)
>>> assert tc.equal(tfields.Triangles3D([[ 5., -5., -5.],
...                                      [ 1.,  0., -1.],
...                                      [ 0.,  1., -1.]]))
>>> t.fields.append(tfields.Tensors([1,2,3]))
>>> tc2 = t.cut(x >= 0)
>>> assert np.array_equal(tc2.fields[-1], np.array([2.]))
edges()[source]

Retrieve two of the three edge vectors

Returns:

vectors ab and ac, where a, b, c are corners (see

self.corners)

Return type:

two np.ndarrays

evalf(expression=None, coord_sys=None)[source]

Triangle3D implementation

Examples

>>> from sympy.abc import x
>>> import numpy as np
>>> import tfields
>>> t = tfields.Triangles3D([[1., 2., 3.], [-4., 5., 6.], [1, 2, -6],
...                          [5, -5, -5], [1,0,-1], [0,1,-1],
...                          [-5, -5, -5], [1,0,-1], [0,1,-1]])
>>> mask = t.evalf(x >= 0)
>>> assert np.array_equal(t[mask],
...                       tfields.Triangles3D([[ 5., -5., -5.],
...                                            [ 1.,  0., -1.],
...                                            [ 0.,  1., -1.]]))
Returns:

mask which is True, where expression evaluates True

Return type:

np.array

fields
in_triangles(tensors, delta: Optional[float] = 0.0, assign_multiple: bool = False) Union[List[List[int]], array][source]

Barycentric method to obtain, which tensors are containes in any of the triangles

Parameters:
  • tensors (Points3D instance) –

  • optional

  • delta

    float: Normal distance to a triangle, that the points

    are concidered to be contained in the triangle.

    None: Find the minimum distance. Default is 0.

  • assign_multiple – If True, one point may belong to multiple triangles at the same time. In the other case the first occurence will be True the other False

Returns:

[index(or indices if assign_multiple) of triangle for point in tensors]

Return type:

list

classmethod merged(*objects, **kwargs)[source]

Factory method Merges all input arguments to one object

Parameters:
  • return_templates (bool) – return the templates which can be used together with cut to retrieve the original objects

  • dim (int) –

  • **kwargs – passed to cls

Examples

>>> import numpy as np
>>> import tfields
>>> import tfields.bases

The new object with turn out in the most frequent coordinate system if not specified explicitly

>>> vec_a = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> vec_b = tfields.Tensors([[5, 4, 1]],
...     coord_sys=tfields.bases.cylinder)
>>> vec_c = tfields.Tensors([[4, 2, 3]],
...     coord_sys=tfields.bases.cylinder)
>>> merge = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, [[2, 0, 1]])
>>> assert merge.coord_sys == 'cylinder'
>>> assert merge.equal([[0, 0, 0],
...                     [0, 0, 1],
...                     [1, -np.pi / 2, 0],
...                     [5, 4, 1],
...                     [4, 2, 3],
...                     [2, 0, 1]])

Merge also shifts the maps to still refer to the same tensors

>>> tm_a = tfields.TensorMaps(merge, maps=[[[0, 1, 2]]])
>>> tm_b = tm_a.copy()
>>> assert tm_a.coord_sys == 'cylinder'
>>> tm_merge = tfields.TensorMaps.merged(tm_a, tm_b)
>>> assert tm_merge.coord_sys == 'cylinder'
>>> assert tm_merge.maps[3].equal([[0, 1, 2],
...                               list(range(len(merge),
...                                          len(merge) + 3,
...                                          1))])
>>> obj_list = [tfields.Tensors([[1, 2, 3]],
...             coord_sys=tfields.bases.CYLINDER),
...             tfields.Tensors([[3] * 3]),
...             tfields.Tensors([[5, 1, 3]])]
>>> merge2 = tfields.Tensors.merged(
...     *obj_list, coord_sys=tfields.bases.CARTESIAN)
>>> assert merge2.equal([[-0.41614684, 0.90929743, 3.],
...                      [3, 3, 3], [5, 1, 3]], atol=1e-8)

The return_templates argument allows to retrieve a template which can be used with the cut method.

>>> merge, templates = tfields.Tensors.merged(
...     vec_a, vec_b, vec_c, return_templates=True)
>>> assert merge.cut(templates[0]).equal(vec_a)
>>> assert merge.cut(templates[1]).equal(vec_b)
>>> assert merge.cut(templates[2]).equal(vec_c)
mesh()[source]
Returns:

tfields.Mesh3D

name
norms()[source]

Examples

>>> import numpy as np
>>> import tfields
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
...                    faces=[[0, 1, 3],[0, 2, 3],[1,2,4], [1, 3, 4]]);
>>> assert np.allclose(m.triangles().norms(),
...                    [[0.0, 0.0, 1.0],
...                     [0.0, 0.0, -1.0],
...                     [0.0, 1.0, 0.0],
...                     [0.57735027] * 3],
...                    atol=1e-8)
ntriangles()[source]
Returns:

number of triangles

Return type:

int

Module contents

Top-level package of tfields. TODO: proper documentation, also in dough.