Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Daniel Boeckenhoff
tfields
Commits
554aa20d
Commit
554aa20d
authored
May 13, 2020
by
dboe
Browse files
everything works - except the copies and the tree bug
parent
0e83ff14
Changes
5
Hide whitespace changes
Inline
Side-by-side
test/test_core.py
View file @
554aa20d
...
...
@@ -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'
)
...
...
tfields/__init__.py
View file @
554aa20d
...
...
@@ -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
tfields/core.py
View file @
554aa20d
...
...
@@ -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
(
te
mplate
),
*
fields
)
if
dim
(
template
)
==
0
:
tensors
=
self
else
:
tensors
=
template
return
type
(
self
)(
Tensors
(
te
nsors
),
*
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 face
Scalar
s are none
# TODO: could allow if all face
_field
s 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 face
Scalar
s are none
# TODO: could allow if all face
_field
s 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
...
...
tfields/mesh3D.py
View file @
554aa20d
...
...
@@ -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
:
r
eturn
tfields
.
Maps
.
to_map
(
np
.
empty
((
0
,
3
)))
# empty TensorFields object
r
aise
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
.
face
Scalar
s
=
self
.
face
Scalar
s
[
~
face_delete_mask
]
self
.
face
s
.
field
s
=
self
.
face
s
.
field
s
[
~
face_delete_mask
]
def
template
(
self
,
sub_mesh
):
"""
...
...
tfields/triangles3D.py
View file @
554aa20d
...
...
@@ -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],
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment