Commit ed4777c7 authored by Daniel Böckenhoff's avatar Daniel Böckenhoff
Browse files

tensorFields.fields is None sometimes -> fixme

parent 56cd389f
......@@ -7,3 +7,15 @@ from .lib import *
from .core import Tensors, TensorFields, TensorMaps
from .points3D import Points3D
from .mask import getMask
# methods:
from .mask import getMask # NOQA
from .lib import * # NOQA
# classes:
from .points3D import Points3D # NOQA
from .mesh3D import Mesh3D # NOQA
from .triangles3D import Triangles3D # NOQA
from .scalarField3D import ScalarField3D # NOQA
from .vectorField3D import VectorField3D # NOQA
from .planes3D import Planes3D # NOQA
......@@ -14,7 +14,6 @@ from collections import Counter
import sympy
import scipy as sp
import scipy.spatial # NOQA: F401
import scipy.stats as stats
import os
from six import string_types
import pathlib
......@@ -97,7 +96,10 @@ class AbstractNdarray(np.ndarray):
if attr not in kwargs:
kwargs[attr] = default
if dtype is not None:
kwargs[attr] = np.array(kwargs[attr], dtype=dtype)
try:
kwargs[attr] = np.array(kwargs[attr], dtype=dtype)
except Exception as err:
raise ValueError(str(attr) + str(dtype) + str(kwargs[attr]) + str(err))
def __setattr__(self, name, value):
if name in self.__slots__:
......@@ -323,12 +325,17 @@ class Tensors(AbstractNdarray):
__slot_setters__ = [tfields.bases.get_coord_system_name]
def __new__(cls, tensors, **kwargs):
dtype = kwargs.pop('dtype', np.float64)
order = kwargs.pop('order', None)
''' copy constructor '''
if issubclass(type(tensors), cls):
obj = tensors.copy()
if dtype != obj.dtype or order is not None:
obj.astype(dtype, order=order)
coordSys = kwargs.pop('coordSys', None)
if kwargs:
raise AttributeError("In copy constructor only 'coordSys' "
raise AttributeError("In copy constructor only 'dtype' and 'coordSys' "
"attribute is supported. Kwargs {kwargs} "
"are not consumed"
.format(**locals()))
......@@ -336,8 +343,6 @@ class Tensors(AbstractNdarray):
obj.transform(coordSys)
return obj
dtype = kwargs.pop('dtype', np.float64)
order = kwargs.pop('order', None)
dim = kwargs.pop('dim', None)
''' process empty inputs '''
......@@ -367,7 +372,7 @@ class Tensors(AbstractNdarray):
''' set kwargs to slots attributes '''
for attr in kwargs:
if attr not in cls._iter_slots():
raise AttributeError("Keywordargument {attr} not accepted "
raise AttributeError("Keyword argument {attr} not accepted "
"for class {cls}".format(**locals()))
setattr(obj, attr, kwargs[attr])
......@@ -740,18 +745,7 @@ class Tensors(AbstractNdarray):
Args:
moment (int): n-th moment
"""
if moment == 0:
return 0
if moment == 1: # center of mass
return np.average(self, axis=0)
elif moment == 2: # variance
return np.var(self, axis=0)
elif moment == 3 and stats: # skewness
return stats.skew(self, axis=0)
elif moment == 4 and stats: # kurtosis
return stats.kurtosis(self, axis=0)
else:
raise NotImplementedError("Moment %i not implemented." % moment)
return tfields.lib.stats.getMoment(self, moment)
def closestPoints(self, other, **kwargs):
"""
......@@ -838,14 +832,6 @@ class Tensors(AbstractNdarray):
inst = self[mask].copy()
return inst
def mapToCut(self, cutOrMeshMap, coordSys=None, atIntersection="remove"):
"""
Args:
cutOrMeshMap (cutExpression / Mesh3D with faceScalars)
"""
# in current implementation Points3D use always cut method, never MeshMap
return self.cut(cutOrMeshMap, coordSys=coordSys), None
def distances(self, other, **kwargs):
"""
Args:
......@@ -959,19 +945,110 @@ class TensorFields(Tensors):
>>> multiField.fields[1].dim
3
Copying
>>> cp = TensorFields(vectorField)
>>> assert vectorField.equal(cp)
"""
__slots__ = ['coordSys', 'fields']
def __new__(cls, tensors, *fields, **kwargs):
obj = super(TensorFields, cls).__new__(cls, tensors, **kwargs)
obj.fields = list(fields)
if fields or (issubclass(type(tensors), cls) and fields):
obj.fields = [Tensors(field) for field in fields]
return obj
def __getitem__(self, index):
"""
In addition to the usual, also slice fields
Examples:
>>> from tfields import Tensors, TensorFields
>>> import numpy as np
>>> vectors = Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> scalarField = TensorFields(vectors, [42, 21, 10.5], [1, 2, 3])
Slicing
>>> sliced = scalarField[2:]
>>> assert isinstance(sliced, TensorFields)
>>> assert isinstance(sliced.fields[0], Tensors)
>>> assert sliced.fields[0].equal([10.5])
Picking
>>> picked = scalarField[1]
>>> assert np.array_equal(picked, [0, 0, 1])
Masking
>>> masked = scalarField[[True, False, True]]
>>> assert masked.equal([[0, 0, 0], [0, -1, 0]])
>>> assert masked.fields[0].equal([42, 10.5])
>>> assert masked.fields[1].equal([1, 3])
"""
item = super(TensorFields, self).__getitem__(index)
if isinstance(item, TensorFields):
if isinstance(index, slice):
item.fields = [field.__getitem__(index) for field in item.fields]
elif isinstance(index, tuple):
item.fields = [field.__getitem__(index[0]) for field in item.fields]
else:
item.fields = [field.__getitem__(index) for field in item.fields]
return item
def __setitem__(self, index, item):
"""
In addition to the usual, also slice fields
Examples:
>>> from tfields import Tensors, TensorFields
>>> import numpy as np
>>> original = TensorFields([[0, 0, 0], [0, 0, 1], [0, -1, 0]],
... [42, 21, 10.5], [1, 2, 3])
>>> obj = TensorFields([[0, 0, 0], [0, 0, np.nan], [0, -1, 0]],
... [42, 22, 10.5], [1, -1, 3])
>>> slice_obj = obj.copy()
>>> assert not obj.equal(original)
>>> obj[1] = original[1]
>>> assert obj[:2].equal(original[:2])
>>> assert not slice_obj.equal(original)
>>> slice_obj[:] = original[:]
>>> assert slice_obj.equal(original)
"""
super(TensorFields, self).__setitem__(index, item)
if isinstance(item, TensorFields):
if isinstance(index, slice):
for i, field in enumerate(item.fields):
self.fields[i].__setitem__(index, field)
elif isinstance(index, tuple):
for i, field in enumerate(item.fields):
self.fields[i].__setitem__(index[0], field)
else:
for i, field in enumerate(item.fields):
self.fields[i].__setitem__(index, field)
def transform(self, coordSys):
super(TensorFields, self).transform(coordSys)
for field in self.fields:
field.transform(coordSys)
def equal(self, other, **kwargs):
"""
Test, whether the instance has the same content as other.
Args:
optional:
see Tensors.equal
"""
if not issubclass(type(other), Tensors):
return super(TensorFields, self).equal(other, **kwargs)
else:
with other.tmp_transform(self.coordSys):
mask = super(TensorFields, self).equal(other, **kwargs)
if issubclass(type(other), TensorFields):
for i, field in enumerate(self.fields):
mask &= field.equal(other.fields[i], **kwargs)
return mask
class TensorMaps(TensorFields):
"""
......@@ -986,21 +1063,182 @@ class TensorMaps(TensorFields):
>>> from tfields import Tensors, TensorMaps
>>> scalars = Tensors([0, 1, 2])
>>> vectors = Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0]])
>>> mesh = TensorMaps(vectors, scalars, maps=[[[0, 1, 2], [0, 1, 2]],
... [[1, 1, 1], [2, 2, 2]]])
>>> mesh.maps
array([[[0, 1, 2],
[0, 1, 2]],
<BLANKLINE>
[[1, 1, 1],
[2, 2, 2]]])
>>> maps = [TensorFields([[0, 1, 2], [0, 1, 2]], [42, 21]),
... TensorFields([[1], [2]], [-42, -21])]
>>> mesh = TensorMaps(vectors, scalars,
... maps=maps)
>>> assert isinstance(mesh.maps, list)
>>> assert len(mesh.maps) == 2
>>> print mesh.fields
>>> print mesh.maps[0].fields
"""
__slots__ = ['coordSys', 'fields', 'maps']
__slotDtypes__ = [None, None, int]
def __new__(cls, tensors, *fields, **kwargs):
maps = kwargs.pop('maps', [])
maps_cp = []
for mp in maps:
try:
mp = TensorFields(mp, dtype=int)
except Exception as err:
raise ValueError("Could not cast map {mp} to TensorFields instance."
" Error '{err}' occured."
.format(**locals()))
maps_cp.append(mp)
kwargs['maps'] = maps_cp
obj = super(TensorMaps, cls).__new__(cls, tensors, *fields, **kwargs)
return obj
def stale(self):
"""
Returns:
Mask for all vertices that are stale i.e. are not refered by maps
Examples:
>>> from tfields import Tensors, TensorMaps
>>> vectors = Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0], [4, 4, 4]])
>>> tm = TensorMaps(vectors, maps=[[[0, 1, 2], [0, 1, 2]],
... [[1, 1], [2, 2]]])
>>> assert np.array_equal(tm.stale(), [False, False, False, True])
"""
staleMask = np.full(self.shape[0], False, dtype=bool)
used = set([ind for mp in self.maps for ind in mp.flatten()])
for i in range(self.shape[0]):
if i not in used:
staleMask[i] = True
return staleMask
def cleaned(self, stale=True, duplicates=True):
"""
Args:
stale (bool): remove stale vertices
duplicates (bool): replace duplicate vertices by originals
Examples:
>>> import tfields
>>> mp1 = tfields.TensorFields([[0, 1, 2], [3, 4, 5]],
... [[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.]])
# >>> c.maps
# [array([[0, 1, 2],
# [0, 3, 4]]),
# array([[0], [0]])]
Returns:
copy of self without stale vertices and duplicat points (depending on arguments)
"""
# remove stale vertices
if stale:
stale_mask = self.stale()
else:
stale_mask = np.full(self.shape[0], False, dtype=bool)
# remove duplicates in order to not have any artificial separations
inst = self
if duplicates:
inst = self.copy()
duplicates = tfields.duplicates(self, axis=0)
for tensor_index, duplicate_index in zip(range(self.shape[0]), duplicates):
if duplicate_index != tensor_index:
stale_mask[tensor_index] = True
# redirect maps
for map_index in range(len(self.maps)):
for f in range(self.maps[map_index].shape[0]):
if tensor_index in self.maps[f]:
index = tfields.index(self.maps[map_index][f], tensor_index)
inst.maps[map_index][f][index] = duplicate_index
return inst.removed(stale_mask)
def removed(self, remove_condition):
"""
Return copy of self without vertices where remove_condition is True
Copy because self is immutable
Examples:
>>> 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=[TensorFields([[0, 1, 2], [0, 1, 3],
... [3, 4, 5], [3, 4, 1],
... [3, 4, 6]],
... [[1,2], [3,4], [5,6], [7,8], [9,0]])])
>>> m.maps[0].fields
>>> c = m.removed([True, True, True, False, False, False, False])
>>> c
TensorMaps([[ 0., 0., 0.],
[ 3., 3., 3.],
[ 4., 4., 4.],
[ 5., 5., 5.]])
>>> c.maps[0]
array([[0, 1, 2],
[0, 1, 3]])
>>> c.maps[0].fields
array([[ 5., 6.],
[ 9., 0.]])
"""
remove_condition = np.array(remove_condition)
# built instance that only contains the vaild points
inst = self[~remove_condition].copy()
delete_indices = np.arange(self.shape[0])[remove_condition]
face_keep_masks = self.to_maps_masks(~remove_condition)
for map_index, face_keep_mask in enumerate(face_keep_masks):
moveUpCounter = np.zeros(self.maps[map_index].shape, dtype=int)
# correct map:
for p in delete_indices:
moveUpCounter[self.maps[map_index] > p] -= 1
inst.maps[map_index] = (self.maps[map_index] + moveUpCounter)[face_keep_mask]
return inst
def to_maps_masks(self, mask):
"""
Examples:
>>> from tfields import TensorMaps
>>> m = TensorMaps([[1,2,3], [3,3,3], [0,0,0], [5,6,7]],
... maps=[[0, 1, 2], [1, 2, 3]])
>>> from sympy.abc import x,y,z
>>> vertexMask = m.getMask(z < 6)
>>> faceMask = m.to_maps_masks(vertexMask)
>>> faceMask
array([ True, False], dtype=bool)
Returns:
mask of faces with all vertices in mask
"""
indices = np.array(range(len(mask)))
delete_indices = indices[~mask]
delete_indices = set(delete_indices) # set speeds up everything enormously
masks = []
for map_index in range(len(self.maps)):
map_delete_mask = np.full((len(self.maps[map_index]),), False, dtype=bool)
for i, mp in enumerate(self.maps[0]):
for index in set(mp):
if index in delete_indices:
map_delete_mask[i] = True
break
masks.append(~map_delete_mask)
return masks
if __name__ == '__main__': # pragma: no cover
import doctest
doctest.testmod()
# doctest.run_docstring_examples(TensorMaps, globals())
# doctest.testmod()
# doctest.run_docstring_examples(TensorMaps.cleaned, globals())
doctest.run_docstring_examples(TensorMaps, globals())
......@@ -106,3 +106,5 @@ if __name__ == '__main__':
else:
from . import grid
from .grid import igrid
from . import stats
from .stats import mode, median, mean
......@@ -4,17 +4,9 @@
Author: Daniel Boeckenhoff
Mail: daniel.boeckenhoff@ipp.mpg.de
basic threedimensional tensor
basic threedimensional tensors
"""
import tfields
import numpy as np
import pathlib
import os
import osTools
import ioTools
import warnings
import loggingTools
logger = loggingTools.Logger(__name__)
class Points3D(tfields.Tensors):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment