Commit f89789a0 authored by dboe's avatar dboe
Browse files

everything works - except the copies and the tree bug

parent 1394faa0
......@@ -21,15 +21,15 @@ class Base_Check(object):
self.demand_equal(reloaded)
# def test_implicit_copy(self):
# copy = type(self._inst)(self._inst)
# self.demand_equal(copy)
# # self.assertIsNot(self._inst, copy)
# def test_explicit_copy(self):
# copy = self._inst.copy()
# self.demand_equal(copy)
# self.assertIsNot(self._inst, copy)
def test_implicit_copy(self):
copy = type(self._inst)(self._inst)
self.demand_equal(copy)
# self.assertIsNot(self._inst, copy)
def test_explicit_copy(self):
copy = self._inst.copy()
self.demand_equal(copy)
self.assertIsNot(self._inst, copy)
def test_save_npz(self):
out_file = NamedTemporaryFile(suffix='.npz')
......
......@@ -18,7 +18,6 @@ from .lib import * # NOQA
# classes:
from .points3D import Points3D # NOQA
from .mesh3D import Mesh3D # NOQA
from .mesh3D import fields_to_scalars, scalars_to_fields
from .triangles3D import Triangles3D # NOQA
from .planes3D import Planes3D # NOQA
from .bounding_box import Node
......@@ -558,7 +558,11 @@ class AbstractNdarray(np.ndarray, AbstractObject):
>>> import tfields
>>> m = tfields.TensorMaps(
... [[1,2,3], [3,3,3], [0,0,0], [5,6,7]],
... maps=[[[0, 1, 2], [1, 2, 3]], [[1]], [[0, 1, 2, 3]]])
... maps=[
... ([[0, 1, 2], [1, 2, 3]], [21, 42]),
... [[1]],
... [[0, 1, 2, 3]]
... ])
>>> mc = m.copy()
>>> mc.equal(m)
True
......@@ -1430,9 +1434,13 @@ class Tensors(AbstractNdarray):
points, extending the object it should cut. This becomes relevant for
Mesh3D when adding vertices at the edge of the cut is necessary.
"""
# TODO: in merged return np.empty() for tensors to save space.
# use tensors only when adding. I think this function already suits the
# needs
# Redirect fields
fields = []
if template.fields:
if template.fields and issubclass(type(self), TensorFields):
template_field = np.array(template.fields[0])
if len(self) > 0:
'''
......@@ -1449,11 +1457,11 @@ class Tensors(AbstractNdarray):
projected_field = field[template_field]
projected_field[nan_mask] = np.nan # correction for nan
fields.append(projected_field)
if dim(template) == 0:
tensors = self
else:
tensors = template
return type(self)(Tensors(template), *fields)
if dim(template) == 0:
tensors = self
else:
tensors = template
return type(self)(Tensors(tensors), *fields)
def cut(self, expression, coord_sys=None, return_template=False, **kwargs):
"""
......@@ -1934,7 +1942,7 @@ class TensorFields(Tensors):
def merged(cls, *objects, **kwargs):
if not all([isinstance(o, cls) for o in objects]):
types = [type(o) for o in objects]
# TODO: could allow if all faceScalars are none
# TODO: could allow if all face_fields are none
raise TypeError(
"Merge constructor only accepts {cls} instances."
"Got objects of types {types} instead.".format(**locals())
......@@ -2151,7 +2159,14 @@ class Maps(sortedcontainers.SortedDict, AbstractObject):
super().__init__(arg_tuple_list, **kwargs)
@staticmethod
def to_map(mp, *fields, copy=False):
def to_map(mp, *fields, copy=False, **kwargs):
"""
Args:
mp (TensorFields)
*fields (Tensors)
copy (bool)
**kwargs: passed to TensorFields constructor
"""
if not copy:
if isinstance(mp, TensorFields) and not fields:
if not np.issubdtype(mp.dtype, np.integer):
......@@ -2159,7 +2174,7 @@ class Maps(sortedcontainers.SortedDict, AbstractObject):
else:
copy = True
if copy: # not else, because in case of wrong mp type we initialize
mp = TensorFields(mp, *fields, dtype=int)
mp = TensorFields(mp, *fields, dtype=int, **kwargs)
if not mp.rank == 1:
raise ValueError(
"Incorrect map rank {mp.rank}".format(**locals())
......@@ -2216,11 +2231,9 @@ class TensorMaps(TensorFields):
... tfields.TensorFields([[1], [2]], [-42, -21])]
>>> mesh = tfields.TensorMaps(vectors, scalars,
... maps=maps)
>>> assert isinstance(mesh.maps, list)
>>> assert isinstance(mesh.maps, tfields.Maps)
>>> assert len(mesh.maps) == 2
>>> assert mesh.equal(tfields.TensorFields(vectors, scalars))
>>> assert mesh.maps[3].fields[0].equal(maps[3].fields[0])
Copy constructor
......@@ -2344,7 +2357,7 @@ class TensorMaps(TensorFields):
@classmethod
def merged(cls, *objects, **kwargs):
if not all([isinstance(o, cls) for o in objects]):
# TODO: could allow if all faceScalars are none
# TODO: could allow if all face_fields are none
raise TypeError(
"Merge constructor only accepts {cls} instances.".format(
**locals()
......@@ -2486,7 +2499,7 @@ class TensorMaps(TensorFields):
Examples:
>>> import tfields
>>> maps = [tfields.TensorFields([[1]], [42])]
>>> tm = tfields.TensorMaps(maps[3], maps=maps)
>>> tm = tfields.TensorMaps(maps[0], maps=maps)
# >>> assert tm.equal(tm)
......@@ -2612,21 +2625,6 @@ class TensorMaps(TensorFields):
"""
remove_condition = np.array(remove_condition)
# # build 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_dim, face_keep_mask in enumerate(face_keep_masks):
# move_up_counter = np.zeros(self.maps[map_dim].shape, dtype=int)
# # correct map:
# for p in delete_indices:
# move_up_counter[self.maps[map_dim] > p] -= 1
# inst.maps[map_dim] = (self.maps[map_dim]
# + move_up_counter)[face_keep_mask]
# return inst
return self[~remove_condition]
def keep(self, keep_condition):
......@@ -2658,44 +2656,6 @@ class TensorMaps(TensorFields):
keep_condition = np.array(keep_condition)
return self[keep_condition]
def to_maps_masks(self, mask):
"""
Examples:
>>> from tfields import TensorMaps
>>> import numpy as np
>>> m = TensorMaps([[1,2,3], [3,3,3], [0,0,0], [5,6,7]],
... maps=[[[0, 1, 2], [1, 2, 3]],
... [[0], [3]]])
>>> from sympy.abc import x,y,z
>>> vertexMask = m.evalf(z < 6)
>>> faceMask = m.to_maps_masks(vertexMask)
>>> assert np.array_equal(faceMask, [[True, False], [True, False]])
>>> index_face_mask = m.to_maps_masks(0)
>>> assert np.array_equal(index_face_mask,
... [[False, False], [True, False]])
Returns:
masks of maps with all vertices in mask
"""
indices = np.array(range(len(self)))
keep_indices = indices[mask]
if isinstance(keep_indices, int):
keep_indices = np.array([keep_indices])
delete_indices = set(indices.flat).difference(set(keep_indices.flat))
masks = []
for map_dim in self.maps:
map_delete_mask = np.full(
(len(self.maps[map_dim]),), False, dtype=bool
)
for i, mp in enumerate(self.maps[map_dim]):
for index in mp:
if index in delete_indices:
map_delete_mask[i] = True
break
masks.append(~map_delete_mask)
return masks
def parts(self, *map_descriptions):
"""
Args:
......@@ -2748,7 +2708,7 @@ class TensorMaps(TensorFields):
>>> b[:, 0] += 2
>>> m = tfields.TensorMaps.merged(a, b)
>>> mp_description = m.disjoint_map(0)
>>> mp_description = m.disjoint_map(3)
>>> parts = m.parts(mp_description)
>>> aa, ba = parts
>>> assert aa.maps[3].equal(ba.maps[3])
......@@ -2787,12 +2747,12 @@ class TensorMaps(TensorFields):
... maps=[[[0, 2], [2, 4], [3, 4], [5, 4],
... [1, 8], [6, 4], [6, 7], [7, 4]]])
>>> paths = a.paths(0)
>>> paths = a.paths(2)
>>> assert paths[0].equal([[ 1., 0.],
... [ 2., 2.],
... [ 2., 4.],
... [ 0., 4.]])
>>> assert paths[0].maps[0].equal([[ 0., 1., 2., 3.]])
>>> assert paths[0].maps[4].equal([[ 0., 1., 2., 3.]])
>>> assert paths[1].equal([[ 4., 4.],
... [ 2., 4.],
... [ 1., 6.],
......@@ -2885,7 +2845,8 @@ class TensorMaps(TensorFields):
chain.extend(edge[1:])
node = edge[-1]
path = path[chain]
path.maps[0] = tfields.TensorFields([sorted(chain)])
path_map = Maps.to_map([sorted(chain)])
path.maps[dim(path_map)] = path_map
sorted_paths.append(path)
paths = sorted_paths
......
......@@ -129,24 +129,6 @@ def _intersect(triangle, plane, vertices_rejected):
return new_points
def scalars_to_fields(scalars):
scalars = np.array(scalars)
if len(scalars.shape) == 1:
return [tfields.Tensors(scalars)]
return [tfields.Tensors(fs) for fs in scalars]
def fields_to_scalars(fields):
return np.array(fields)
def faces_to_maps(faces, *fields):
# TODO: replace by Maps.to_maps or so
return tfields.Maps(
tfields.TensorFields(faces, *fields, dtype=int, dim=3)
)
class Mesh3D(tfields.TensorMaps):
# pylint: disable=R0904
"""
......@@ -180,13 +162,14 @@ class Mesh3D(tfields.TensorMaps):
... [ 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]], faceScalars=[.5]);
>>> np.array_equal(mScalar.faceScalars, [[ 0.5]])
>>> 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]], faceScalars=[.7])
... faces=([[0,1,2]], [.7]))
>>> msum = tfields.Mesh3D.merged(mScalar, m2)
>>> msum.equal([[ 1., 0., 0.],
... [ 0., 1., 0.],
......@@ -211,19 +194,13 @@ class Mesh3D(tfields.TensorMaps):
def __new__(cls, tensors, *fields, **kwargs):
if not issubclass(type(tensors), Mesh3D):
kwargs['dim'] = 3
faces = kwargs.pop('faces', None)
faceScalars = kwargs.pop('faceScalars', [])
maps = kwargs.pop('maps', None)
if maps is not None and faces is not None:
if 'maps' in kwargs and 'faces' in kwargs:
raise ValueError("Conflicting options maps and faces")
if maps is not None:
kwargs['maps'] = maps
if len(faceScalars) > 0:
map_fields = scalars_to_fields(faceScalars)
else:
map_fields = []
if faces is not None:
kwargs['maps'] = [(faces,) + tuple(map_fields)]
faces = kwargs.pop('faces', None)
if not faces: # None or []
faces = np.empty((0, 3))
maps = kwargs.pop('maps', [faces])
kwargs['maps'] = maps
obj = super(Mesh3D, cls).__new__(cls, tensors, *fields, **kwargs)
if len(obj.maps) > 1:
raise ValueError("Mesh3D only allows one map")
......@@ -244,7 +221,7 @@ class Mesh3D(tfields.TensorMaps):
path = path.replace('.obj', '')
directory, name = os.path.split(path)
if not (self.faceScalars.size == 0 or map_index is None):
if map_index is not None:
scalars = self.maps[3].fields[map_index]
min_scalar = scalars[~np.isnan(scalars)].min()
max_scalar = scalars[~np.isnan(scalars)].max()
......@@ -494,24 +471,13 @@ class Mesh3D(tfields.TensorMaps):
if self.maps:
return self.maps[3]
else:
return tfields.Maps.to_map(np.empty((0, 3))) # empty TensorFields object
raise AttributeError("No faces found. Bug - please report")
@faces.setter
def faces(self, faces):
self.maps = tfields.Maps() # circumvent the copy constructor
mp = tfields.Maps.to_map(faces)
mp = tfields.Maps.to_map(faces, dim=3)
self.maps[tfields.dim(mp)] = mp
@property
def faceScalars(self):
# TODO: BAD NAME
return fields_to_scalars(self.maps[3].fields)
@faceScalars.setter
def faceScalars(self, scalars):
# TODO: BAD NAME
self.maps[3].fields = scalars_to_fields(scalars)
@cached_property()
def _triangles(self):
"""
......@@ -610,7 +576,7 @@ class Mesh3D(tfields.TensorMaps):
"""
face_delete_mask = np.array(face_delete_mask, dtype=bool)
self.faces = self.faces[~face_delete_mask]
self.faceScalars = self.faceScalars[~face_delete_mask]
self.faces.fields = self.faces.fields[~face_delete_mask]
def template(self, sub_mesh):
"""
......
......@@ -136,17 +136,6 @@ class Triangles3D(tfields.TensorFields):
.format(len(obj)))
return obj
@property
def triangleScalars(self):
"""
Deprecated scalars implementation
"""
return tfields.fields_to_scalars(self.fields)
@triangleScalars.setter
def triangleScalars(self, scalars):
self.fields = tfields.scalars_to_fields(scalars)
def evalf(self, expression=None, coord_sys=None):
"""
Triangle3D implementation
......@@ -185,10 +174,9 @@ class Triangles3D(tfields.TensorFields):
>>> assert tc.equal(tfields.Triangles3D([[ 5., -5., -5.],
... [ 1., 0., -1.],
... [ 0., 1., -1.]]))
>>> assert np.array_equal(tc.triangleScalars, [])
>>> t.fields.append(tfields.Tensors([1,2,3]))
>>> tc2 = t.cut(x >= 0)
>>> assert np.array_equal(tc2.triangleScalars, np.array([[2.]]))
>>> assert np.array_equal(tc2.fields[-1], np.array([2.]))
"""
# mask = self.evalf(expression, coord_sys=coord_sys)
......@@ -407,12 +395,15 @@ class Triangles3D(tfields.TensorFields):
>>> m2 = tfields.Mesh3D([[0,0,0], [2,0,0], [0,2,0], [0,0,2]],
... faces=[[0, 1, 2], [0, 2, 3]]);
>>> assert np.array_equal(m2.triangles()._baricentric(np.array([0.2, 0.2, 0]),
... delta=2.),
... [[0.1, 0.1, 0.0],
... [0.1, 0.0, 0.1]])
>>> assert np.array_equal(
... m2.triangles()._baricentric(np.array([0.2, 0.2, 0]),
... delta=2.),
... [[0.1, 0.1, 0.0],
... [0.1, 0.0, 0.1]])
if point lies in the plane, return np.nan, else inf for w if delta
is exactly 0.
if point lies in the plane, return np.nan, else inf for w if delta is exactly 0.
>>> baric = m2.triangles()._baricentric(np.array([0.2, 0.2, 0]),
... delta=0.),
>>> baric_expected = np.array([[0.1, 0.1, np.nan],
......
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