Commit 06041647 authored by Daniel Böckenhoff (Laptop)'s avatar Daniel Böckenhoff (Laptop)
Browse files

core especially __getitem__ for TensorMaps

parent 8b71fffa
...@@ -1186,17 +1186,17 @@ class TensorFields(Tensors): ...@@ -1186,17 +1186,17 @@ class TensorFields(Tensors):
>>> assert masked.fields[0].equal([42, 10.5]) >>> assert masked.fields[0].equal([42, 10.5])
>>> assert masked.fields[1].equal([1, 3]) >>> assert masked.fields[1].equal([1, 3])
Iteration
>>> _ = [point for point in scalarField]
""" """
item = super(TensorFields, self).__getitem__(index) item = super(TensorFields, self).__getitem__(index)
try: try:
if issubclass(type(item), TensorFields): if issubclass(type(item), TensorFields):
if isinstance(index, tuple): if isinstance(index, tuple):
index = index[0] index = index[0]
if isinstance(index, slice): if item.fields:
item.fields = [field.__getitem__(index) for field in item.fields] item.fields = [field.__getitem__(index) for field in item.fields]
else:
if item.fields:
item.fields = [field.__getitem__(index) for field in item.fields]
except IndexError as err: except IndexError as err:
warnings.warn("Index error occured for field.__getitem__. Error " warnings.warn("Index error occured for field.__getitem__. Error "
"message: {err}".format(**locals())) "message: {err}".format(**locals()))
...@@ -1330,6 +1330,86 @@ class TensorMaps(TensorFields): ...@@ -1330,6 +1330,86 @@ class TensorMaps(TensorFields):
obj.maps = maps obj.maps = maps
return obj return obj
def __getitem__(self, index):
"""
In addition to the usual, also slice fields
Examples:
>>> import tfields
>>> import numpy as np
>>> vectors = tfields.Tensors([[0, 0, 0], [0, 0, 1], [0, -1, 0],
... [1, 1, 1], [-1, -1, -1]])
>>> maps=[tfields.TensorFields([[0, 1, 2], [0, 1, 3], [2, 3, 4]],
... [[1, 2], [3, 4], [5, 6]]),
... tfields.TensorFields([[0], [1], [2], [3], [4]])]
>>> mesh = tfields.TensorMaps(vectors,
... [42, 21, 10.5, 1, 1],
... [1, 2, 3, 3, 3],
... maps=maps)
Slicing
>>> sliced = mesh[2:]
>>> assert isinstance(sliced, tfields.TensorMaps)
>>> assert isinstance(sliced.fields[0], tfields.Tensors)
>>> assert isinstance(sliced.maps[0], tfields.TensorFields)
>>> assert sliced.fields[0].equal([10.5, 1, 1])
>>> assert sliced.maps[0].equal([[0, 1, 2]])
>>> assert sliced.maps[0].fields[0].equal([[5, 6]])
Picking
>>> picked = mesh[1]
>>> assert np.array_equal(picked, [0, 0, 1])
>>> assert np.array_equal(picked.maps[0], np.empty((0, 3)))
>>> assert np.array_equal(picked.maps[1], [[0]])
Masking
>>> masked = mesh[[True, False, True, True, True]]
>>> assert masked.equal([[0, 0, 0], [0, -1, 0], [1, 1, 1], [-1, -1, -1]])
>>> assert masked.fields[0].equal([42, 10.5, 1, 1])
>>> assert masked.fields[1].equal([1, 3, 3, 3])
>>> assert masked.maps[0].equal([[1, 2, 3]])
>>> assert masked.maps[1].equal([[0], [1], [2], [3]])
Iteration
>>> _ = [vertex for vertex in mesh]
"""
item = super(TensorMaps, self).__getitem__(index)
try:
if issubclass(type(item), TensorMaps):
item.maps = [mp.copy() for mp in item.maps]
if isinstance(index, tuple):
index = index[0]
if item.maps:
indices = np.array(range(len(self)))
keep_indices = indices[index]
if isinstance(keep_indices, int):
keep_indices = [keep_indices]
delete_indices = set(indices).difference(set(keep_indices))
# correct all maps that contain deleted indices
for mp_idx in range(len(self.maps)):
# build mask, where the map should be deleted
map_delete_mask = np.full((len(self.maps[mp_idx]),), False, dtype=bool)
for i, mp in enumerate(self.maps[mp_idx]):
for index in mp:
if index in delete_indices:
map_delete_mask[i] = True
break
map_mask = ~map_delete_mask
# build the correction counters
move_up_counter = np.zeros(self.maps[mp_idx].shape, dtype=int)
for p in delete_indices:
move_up_counter[self.maps[mp_idx] > p] -= 1
item.maps[mp_idx] = (self.maps[mp_idx] + move_up_counter)[map_mask]
except IndexError as err:
warnings.warn("Index error occured for field.__getitem__. Error "
"message: {err}".format(**locals()))
return item
@classmethod @classmethod
def merged(cls, *objects, **kwargs): def merged(cls, *objects, **kwargs):
if not all([isinstance(o, cls) for o in objects]): if not all([isinstance(o, cls) for o in objects]):
...@@ -1345,12 +1425,12 @@ class TensorMaps(TensorFields): ...@@ -1345,12 +1425,12 @@ class TensorMaps(TensorFields):
for map_field in o.maps: for map_field in o.maps:
map_field = map_field + cum_tensor_lengths[i] map_field = map_field + cum_tensor_lengths[i]
try: try:
map_index = dims.index(map_field.dim) mp_idx = dims.index(map_field.dim)
except ValueError: except ValueError:
maps.append(map_field) maps.append(map_field)
dims.append(map_field.dim) dims.append(map_field.dim)
else: else:
maps[map_index] = TensorFields.merged(maps[map_index], map_field) maps[mp_idx] = TensorFields.merged(maps[mp_idx], map_field)
kwargs['maps'] = maps kwargs['maps'] = maps
obj = super(TensorMaps, cls).merged(*objects, **kwargs) obj = super(TensorMaps, cls).merged(*objects, **kwargs)
...@@ -1424,16 +1504,14 @@ class TensorMaps(TensorFields): ...@@ -1424,16 +1504,14 @@ class TensorMaps(TensorFields):
... [3,3,3], [4,4,4], [5,6,7]], ... [3,3,3], [4,4,4], [5,6,7]],
... maps=[mp1, mp2]) ... maps=[mp1, mp2])
# >>> c = tm.cleaned() >>> c = tm.cleaned()
# >>> assert c.equal([[0., 0., 0.], >>> assert c.equal([[0., 0., 0.],
# ... [1., 1., 1.], ... [1., 1., 1.],
# ... [2., 2., 2.], ... [2., 2., 2.],
# ... [3., 3., 3.], ... [3., 3., 3.],
# ... [4., 4., 4.]]) ... [4., 4., 4.]])
# >>> c.maps >>> assert np.array_equal(c.maps[0], [[0, 1, 2], [0, 3, 4]])
# [array([[0, 1, 2], >>> assert np.array_equal(c.maps[1], [[0], [0]])
# [0, 3, 4]]),
# array([[0], [0]])]
Returns: Returns:
...@@ -1453,11 +1531,11 @@ class TensorMaps(TensorFields): ...@@ -1453,11 +1531,11 @@ class TensorMaps(TensorFields):
if duplicate_index != tensor_index: if duplicate_index != tensor_index:
stale_mask[tensor_index] = True stale_mask[tensor_index] = True
# redirect maps # redirect maps
for map_index in range(len(self.maps)): for mp_idx in range(len(self.maps)):
for f in range(self.maps[map_index].shape[0]): for f in range(len(self.maps[mp_idx])):
if tensor_index in self.maps[f]: if tensor_index in self.maps[mp_idx][f]:
index = tfields.index(self.maps[map_index][f], tensor_index) index = tfields.index(self.maps[mp_idx][f], tensor_index)
inst.maps[map_index][f][index] = duplicate_index inst.maps[mp_idx][f][index] = duplicate_index
return inst.removed(stale_mask) return inst.removed(stale_mask)
...@@ -1475,7 +1553,7 @@ class TensorMaps(TensorFields): ...@@ -1475,7 +1553,7 @@ class TensorMaps(TensorFields):
... [3, 4, 6]], ... [3, 4, 6]],
... [1, 3, 5, 7, 9], ... [1, 3, 5, 7, 9],
... [2, 4, 6, 8, 0])]) ... [2, 4, 6, 8, 0])])
>>> c = m.removed([True, True, True, False, False, False, False]) >>> c = m.keep([False, False, False, True, True, True, True])
>>> c.equal([[0, 0, 0], >>> c.equal([[0, 0, 0],
... [3, 3, 3], ... [3, 3, 3],
... [4, 4, 4], ... [4, 4, 4],
...@@ -1489,20 +1567,51 @@ class TensorMaps(TensorFields): ...@@ -1489,20 +1567,51 @@ class TensorMaps(TensorFields):
""" """
remove_condition = np.array(remove_condition) remove_condition = np.array(remove_condition)
# built instance that only contains the vaild points # # built instance that only contains the vaild points
inst = self[~remove_condition].copy() # inst = self[~remove_condition].copy()
delete_indices = np.arange(self.shape[0])[remove_condition] # delete_indices = np.arange(self.shape[0])[remove_condition]
face_keep_masks = self.to_maps_masks(~remove_condition) # face_keep_masks = self.to_maps_masks(~remove_condition)
for map_index, face_keep_mask in enumerate(face_keep_masks): # for mp_idx, face_keep_mask in enumerate(face_keep_masks):
moveUpCounter = np.zeros(self.maps[map_index].shape, dtype=int) # move_up_counter = np.zeros(self.maps[mp_idx].shape, dtype=int)
# correct map: # # correct map:
for p in delete_indices: # for p in delete_indices:
moveUpCounter[self.maps[map_index] > p] -= 1 # move_up_counter[self.maps[mp_idx] > p] -= 1
inst.maps[map_index] = (self.maps[map_index] + moveUpCounter)[face_keep_mask] # inst.maps[mp_idx] = (self.maps[mp_idx] + move_up_counter)[face_keep_mask]
return inst # return inst
return self[~remove_condition]
def keep(self, keep_condition):
"""
Return copy of self with vertices where keep_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.removed([True, True, True, False, False, False, False])
>>> c.equal([[0, 0, 0],
... [3, 3, 3],
... [4, 4, 4],
... [5, 5, 5]])
True
>>> c.maps[0]
TensorFields([[0, 1, 2],
[0, 1, 3]])
>>> assert c.maps[0].fields[0].equal([5, 9])
>>> assert c.maps[0].fields[1].equal([6, 0])
"""
keep_condition = np.array(keep_condition)
return self[keep_condition]
def to_maps_masks(self, mask): def to_maps_masks(self, mask):
""" """
...@@ -1510,24 +1619,30 @@ class TensorMaps(TensorFields): ...@@ -1510,24 +1619,30 @@ class TensorMaps(TensorFields):
>>> from tfields import TensorMaps >>> from tfields import TensorMaps
>>> import numpy as np >>> import numpy as np
>>> m = TensorMaps([[1,2,3], [3,3,3], [0,0,0], [5,6,7]], >>> m = TensorMaps([[1,2,3], [3,3,3], [0,0,0], [5,6,7]],
... maps=[[[0, 1, 2], [1, 2, 3]]]) ... maps=[[[0, 1, 2], [1, 2, 3]],
... [[0], [3]]])
>>> from sympy.abc import x,y,z >>> from sympy.abc import x,y,z
>>> vertexMask = m.evalf(z < 6) >>> vertexMask = m.evalf(z < 6)
>>> faceMask = m.to_maps_masks(vertexMask) >>> faceMask = m.to_maps_masks(vertexMask)
>>> assert np.array_equal(faceMask, [[True, False]]) >>> 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: Returns:
mask of faces with all vertices in mask masks of maps with all vertices in mask
""" """
indices = np.array(range(len(self)))
indices = np.array(range(len(mask))) keep_indices = indices[mask]
delete_indices = indices[~mask] if isinstance(keep_indices, int):
delete_indices = set(delete_indices) # set speeds up everything enormously keep_indices = [keep_indices]
delete_indices = set(indices).difference(set(keep_indices))
# delete_indices = indices[~mask]
# delete_indices = set(delete_indices) # set speeds up everything enormously
masks = [] masks = []
for map_index in range(len(self.maps)): for mp_idx in range(len(self.maps)):
map_delete_mask = np.full((len(self.maps[map_index]),), False, dtype=bool) map_delete_mask = np.full((len(self.maps[mp_idx]),), False, dtype=bool)
for i, mp in enumerate(self.maps[map_index]): for i, mp in enumerate(self.maps[mp_idx]):
for index in mp: for index in mp:
if index in delete_indices: if index in delete_indices:
map_delete_mask[i] = True map_delete_mask[i] = True
...@@ -1539,6 +1654,10 @@ class TensorMaps(TensorFields): ...@@ -1539,6 +1654,10 @@ class TensorMaps(TensorFields):
if __name__ == '__main__': # pragma: no cover if __name__ == '__main__': # pragma: no cover
import doctest import doctest
doctest.testmod() doctest.testmod()
# doctest.run_docstring_examples(TensorFields.__getitem__, globals())
# doctest.run_docstring_examples(TensorMaps.__getitem__, globals())
# doctest.run_docstring_examples(TensorMaps.keep, globals())
# doctest.run_docstring_examples(TensorMaps.to_maps_masks, globals())
# doctest.run_docstring_examples(TensorMaps, globals()) # doctest.run_docstring_examples(TensorMaps, globals())
# doctest.run_docstring_examples(TensorFields, globals()) # doctest.run_docstring_examples(TensorFields, globals())
# doctest.run_docstring_examples(AbstractNdarray.copy, globals()) # doctest.run_docstring_examples(AbstractNdarray.copy, globals())
......
...@@ -119,7 +119,7 @@ class Mesh3D(tfields.TensorMaps): ...@@ -119,7 +119,7 @@ class Mesh3D(tfields.TensorMaps):
raise ValueError("Conflicting options maps and faces") raise ValueError("Conflicting options maps and faces")
if maps is not None: if maps is not None:
kwargs['maps'] = maps kwargs['maps'] = maps
if faceScalars: if len(faceScalars) > 0:
map_fields = scalars_to_fields(faceScalars) map_fields = scalars_to_fields(faceScalars)
else: else:
map_fields = [] map_fields = []
...@@ -133,6 +133,61 @@ class Mesh3D(tfields.TensorMaps): ...@@ -133,6 +133,61 @@ class Mesh3D(tfields.TensorMaps):
raise ValueError("Face dimension should be 3") raise ValueError("Face dimension should be 3")
return obj return obj
@classmethod
def plane(cls, *base_vectors, **kwargs):
vertices = tfields.Tensors.grid(*base_vectors)
fix_coord = None
for coord in range(3):
if len(base_vectors[coord]) > 1:
continue
if len(base_vectors[coord]) == 0:
continue
fix_coord = coord
var_coords = list(range(3))
var_coords.pop(var_coords.index(fix_coord))
faces = []
base0, base1 = base_vectors[var_coords[0]], base_vectors[var_coords[1]]
for i1 in range(len(base1) - 1):
for i0 in range(len(base0) - 1):
idx_top_left = len(base1) * (i0 + 0) + (i1 + 0)
idx_top_right = len(base1) * (i0 + 0) + (i1 + 1)
idx_bot_left = len(base1) * (i0 + 1) + (i1 + 0)
idx_bot_right = len(base1) * (i0 + 1) + (i1 + 1)
faces.append([idx_top_left, idx_top_right, idx_bot_left])
faces.append([idx_top_right, idx_bot_left, idx_bot_right])
inst = cls.__new__(cls, vertices, faces=faces, **kwargs)
return inst
@classmethod
def grid(cls, *base_vectors, **kwargs):
if not len(base_vectors) == 3:
raise AttributeError("3 base_vectors vectors required")
indices = [0, -1]
coords = range(3)
baseLengthsAbove1 = [len(b) > 1 for b in base_vectors]
# if one plane is given: rearrange indices and coords
if not all(baseLengthsAbove1):
indices = [0]
for i, b in enumerate(baseLengthsAbove1):
if not b:
coords = [i]
break
base_vectors = list(base_vectors)
planes = []
for ind in indices:
for coord in coords:
basePart = base_vectors[:]
basePart[coord] = np.array([base_vectors[coord][ind]],
dtype=float)
planes.append(cls.plane(*basePart))
inst = cls.merged(*planes, **kwargs)
return inst
@property @property
def faces(self): def faces(self):
return maps_to_faces(self.maps) return maps_to_faces(self.maps)
...@@ -330,108 +385,6 @@ class Mesh3D(tfields.TensorMaps): ...@@ -330,108 +385,6 @@ class Mesh3D(tfields.TensorMaps):
return ~faceDeleteMask return ~faceDeleteMask
def getRemovedVertices(self, vertexDeleteMask):
"""
Return copy of self without vertices where vertexDeleteMask is True
Copy because self is immutable
Examples:
>>> m = tfields.Mesh3D([[0,0,0], [1,1,1], [2,2,2], [0,0,0],
... [3,3,3], [4,4,4], [5,5,5]],
... [[0, 1, 2], [0, 1, 3], [3, 4, 5], [3, 4, 1],
... [3, 4, 6]],
... faceScalars=[[1,2], [3,4], [5,6], [7,8], [9,0]])
>>> c = m.getRemovedVertices([True, True, True, False, False,
... False, False])
>>> c
Mesh3D([[ 0., 0., 0.],
[ 3., 3., 3.],
[ 4., 4., 4.],
[ 5., 5., 5.]])
>>> c.faces
array([[0, 1, 2],
[0, 1, 3]])
>>> c.faceScalars
array([[ 5., 6.],
[ 9., 0.]])
"""
log = logger.new()
vertexDeleteMask = np.array(vertexDeleteMask)
log.verbose("Remove {0} vertices.".format(vertexDeleteMask.sum()))
# built instance that only contains the vaild points
inst = self[~vertexDeleteMask].copy()
moveUpCounter = np.zeros(self.faces.shape, dtype=int)
# correct faces:
deleteIndices = np.arange(len(self))[vertexDeleteMask]
for p in deleteIndices:
moveUpCounter[self.faces > p] -= 1
faceKeepMask = self.getFaceMask(~vertexDeleteMask)
inst.faces = (self.faces + moveUpCounter)[faceKeepMask]
inst.faceScalars = self.faceScalars[faceKeepMask]
return inst
def cleaned(self, stale=True, duplicates=True):
"""
Args:
stale (bool): remove stale vertices
duplicates (bool): replace duplicate vertices by originals
Examples:
>>> m = tfields.Mesh3D([[0,0,0], [1,1,1], [2,2,2], [0,0,0],
... [3,3,3], [4,4,4], [5,6,7]],
... [[0, 1, 2], [3, 4, 5]],
... faceScalars=[[1,2,3,4,5], [6,7,8,9,0]])
>>> c = m.clean()
>>> c
Mesh3D([[ 0., 0., 0.],
[ 1., 1., 1.],
[ 2., 2., 2.],
[ 3., 3., 3.],
[ 4., 4., 4.]])
>>> c.faces
array([[0, 1, 2],
[0, 3, 4]])
Returns:
copy of self without stale vertices and duplicat points
"""
log = logger.new()
log.verbose("Cleaning up.")
# remove stale vertices
if stale:
vertexDeleteMask = self.staleVertices()
else:
vertexDeleteMask = 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()
log.verbose("Finding Duplicates")
dups = tfields.duplicates(self, axis=0)
for i, dupi in zip(range(self.shape[0]), dups):
if dupi != i:
log.verbose("Found Duplicate point @ index {0}".format(i))
vertexDeleteMask[i] = True
# redirect faces
log.verbose("Run trough all faces to let it point to the"
"original")
for f in range(self.nfaces()):
if i in self.faces[f]:
index = tfields.index(self.faces[f], i)
inst.faces[f][index] = dupi
return inst.getRemovedVertices(vertexDeleteMask)
def clean(self, *args, **kwargs):
"""
Deprecated
"""
warnings.warn("Name clean is deprecated. take cleaned instead", DeprecationWarning)
return self.cleaned(*args, **kwargs)
def getScalarMap(self, mask): def getScalarMap(self, mask):
""" """
Return copy of self without vertices where mask is True Return copy of self without vertices where mask is True
...@@ -568,7 +521,7 @@ class Mesh3D(tfields.TensorMaps): ...@@ -568,7 +521,7 @@ class Mesh3D(tfields.TensorMaps):
else False else False
for i in faceIndices] for i in faceIndices]
mesh.removeFaces(faceDeleteMask) mesh.removeFaces(faceDeleteMask)
mesh = mesh.getRemovedVertices(mesh.staleVertices()) mesh = mesh.cleaned(duplicates=False)
parts.append(mesh) parts.append(mesh)
return parts return parts
...@@ -628,7 +581,7 @@ class Mesh3D(tfields.TensorMaps): ...@@ -628,7 +581,7 @@ class Mesh3D(tfields.TensorMaps):
>>> base = [np.linspace(0, 1, 10), >>> base = [np.linspace(0, 1, 10),
... np.linspace(0, 1, 10), ... np.linspace(0, 1, 10),
... np.linspace(0, 1, 10)] ... np.linspace(0, 1, 10)]
>>> mesh = tfields.Mesh3D.createMeshGrid(*base).cleaned() >>> mesh = tfields.Mesh3D.grid(*base).cleaned()
Some small mistake occured in the test. Check that. Some small mistake occured in the test. Check that.
# Select the first face as a seedFace # Select the first face as a seedFace
...@@ -688,7 +641,7 @@ class Mesh3D(tfields.TensorMaps): ...@@ -688,7 +641,7 @@ class Mesh3D(tfields.TensorMaps):
>>> base = [np.linspace(0, 1, 2), >>> base = [np.linspace(0, 1, 2),
... np.linspace(0, 1, 4), ... np.linspace(0, 1, 4),
... np.linspace(0, 1, 4)] ... np.linspace(0, 1, 4)]
>>> mesh = tfields.Mesh3D.createMeshGrid(*base).cleaned() >>> mesh = tfields.Mesh3D.grid(*base).cleaned()
Select the first face as a seedFace Select the first face as a seedFace
>>> faceGroups = mesh.getSides([[1,0,0],[0,1,0],[0,0,1]]) >>> faceGroups = mesh.getSides([[1,0,0],[0,1,0],[0,0,1]])
...@@ -903,9 +856,9 @@ class Mesh3D(tfields.TensorMaps): ...@@ -903,9 +856,9 @@ class Mesh3D(tfields.TensorMaps):
return self.copy(), self.copy() return self.copy(), self.copy()
# mask for points that do not fulfill the cut expression # mask for points that do not fulfill the cut expression
mask = self.evalf(expression, coordSys=coordSys) mask = self.evalf(expression)
# remove the points # remove the points
inst = self.getRemovedVertices(~mask) inst = self[mask].copy()
scalarMap = self.getScalarMap(mask) scalarMap = self.getScalarMap(mask)
scalarMap = scalarMap.reshape((-1, 1)).astype(float) scalarMap = scalarMap.reshape((-1, 1)).astype(float)
...@@ -1057,9 +1010,10 @@ class Mesh3D(tfields.TensorMaps): ...@@ -1057,9 +1010,10 @@ class Mesh3D(tfields.TensorMaps):
>>> from sympy.abc import x,y,z >>> from sympy.abc import x,y,z
>>> cutExpr = x > 1.5 >>> cutExpr = x > 1.5
>>> m = tfields.Mesh3D.createMeshGrid(np.linspace(0,3,4), >>> m = tfields.Mesh3D.grid((0,3,4),
... np.linspace(0,3,4), ... (0,3,4),
... np.linspace(0, 0, 1), faceScalars=np.linspace(4, 8, 18)) ... (0, 0, 1))
>>> m.faceScalars = np.linspace(4, 8, 18)
>>> mNew = m.cut(cutExpr) >>> mNew = m.cut(cutExpr)
>>> len(mNew) >>> len(mNew)
8 8
...@@ -1085,7 +1039,7 @@ class Mesh3D(tfields.TensorMaps): ...@@ -1085,7 +1039,7 @@ class Mesh3D(tfields.TensorMaps):
copy of cut mesh copy of cut mesh
""" """
with self.tmp_transform(coordSys): with self.tmp_transform(coordSys or self.coordSys):
if isinstance(expression, Mesh3D): if isinstance(expression, Mesh3D):
obj = self._cut_template(expression) obj = self._cut_template(expression)
else: else:
......