Skip to content

Commit

Permalink
Merge pull request #1265 from nschloe/separate-int-data
Browse files Browse the repository at this point in the history
Separate int data
  • Loading branch information
nschloe authored Jan 20, 2022
2 parents 36ddfc7 + 1986272 commit 3e6bdf5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 70 deletions.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = meshio
version = 5.2.4
version = 5.2.5
author = Nico Schlömer et al.
author_email = nico.schloemer@gmail.com
description = I/O for many mesh formats
Expand Down
114 changes: 52 additions & 62 deletions src/meshio/_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ def read(cls, path_or_buf, file_format=None):
warn("meshio.Mesh.read is deprecated, use meshio.read instead")
return read(path_or_buf, file_format)

def sets_to_int_data(self):
def cell_sets_to_data(self):
# If possible, convert cell sets to integer cell data. This is possible if all
# cells appear exactly in one group.
default_value = -1
Expand Down Expand Up @@ -341,8 +341,10 @@ def sets_to_int_data(self):
self.cell_data[data_name] = intfun
self.cell_sets = {}

def point_sets_to_data(self):
# now for the point sets
# Go for -1 as the default value. (NaN is not int.)
default_value = -1
if len(self.point_sets) > 0:
intfun = np.full(len(self.points), default_value, dtype=int)
for i, cc in enumerate(self.point_sets.values()):
Expand All @@ -358,73 +360,61 @@ def sets_to_int_data(self):
self.point_data[data_name] = intfun
self.point_sets = {}

def int_data_to_sets(self, keys: list[str] | None = None):
"""Convert all int data to {point,cell}_sets, where possible."""
rm_keys = []
for key, data in self.cell_data.items():
if keys is not None:
if key not in keys:
continue

# handle all int and uint data
if not all(v.dtype.kind in ["i", "u"] for v in data):
continue

rm_keys.append(key)

# this call can be rather expensive
tags = np.unique(np.concatenate(data))

# try and get the names by splitting the key along "-" (this is how
# sets_to_int_data() forms the key)
names = key.split("-")
# remove duplicates and preserve order
# <https://stackoverflow.com/a/7961390/353337>:
names = list(dict.fromkeys(names))
if len(names) != len(tags):
# alternative names
names = [f"set-{key}-{tag}" for tag in tags]

# TODO there's probably a better way besides np.where, something from
# np.unique or np.sort
for name, tag in zip(names, tags):
self.cell_sets[name] = [np.where(d == tag)[0] for d in data]
# This used to be int_data_to_sets(), converting _all_ cell and point data.
# This is not useful in many cases, as one usually only wants one
# particular data array (e.g., "MaterialIDs") converted to sets.
def cell_data_to_sets(self, key: str):
"""Convert point_data to cell_sets."""
data = self.cell_data[key]

# handle all int and uint data
if not all(v.dtype.kind in ["i", "u"] for v in data):
raise RuntimeError(f"cell_data['{key}'] is not int data.")

tags = np.unique(np.concatenate(data))

# try and get the names by splitting the key along "-" (this is how
# sets_to_int_data() forms the key)
names = key.split("-")
# remove duplicates and preserve order
# <https://stackoverflow.com/a/7961390/353337>:
names = list(dict.fromkeys(names))
if len(names) != len(tags):
# alternative names
names = [f"set-{key}-{tag}" for tag in tags]

# TODO there's probably a better way besides np.where, something from
# np.unique or np.sort
for name, tag in zip(names, tags):
self.cell_sets[name] = [np.where(d == tag)[0] for d in data]

# remove the cell data
for key in rm_keys:
del self.cell_data[key]

# now point data
rm_keys = []
for key, data in self.point_data.items():
if keys is not None:
if key not in keys:
continue
del self.cell_data[key]

# handle all int and uint data
if not all(v.dtype.kind in ["i", "u"] for v in data):
continue
def point_data_to_sets(self, key: str):
"""Convert point_data to point_sets."""
data = self.point_data[key]

rm_keys.append(key)
# handle all int and uint data
if not all(v.dtype.kind in ["i", "u"] for v in data):
raise RuntimeError(f"point_data['{key}'] is not int data.")

# this call can be rather expensive
tags = np.unique(data)
tags = np.unique(data)

# try and get the names by splitting the key along "-" (this is how
# sets_to_int_data() forms the key
names = key.split("-")
# remove duplicates and preserve order
# <https://stackoverflow.com/a/7961390/353337>:
names = list(dict.fromkeys(names))
if len(names) != len(tags):
# alternative names
names = [f"set{tag}" for tag in tags]
# try and get the names by splitting the key along "-" (this is how
# sets_to_int_data() forms the key
names = key.split("-")
# remove duplicates and preserve order
# <https://stackoverflow.com/a/7961390/353337>:
names = list(dict.fromkeys(names))
if len(names) != len(tags):
# alternative names
names = [f"set-key-{tag}" for tag in tags]

# TODO there's probably a better way besides np.where, something from
# np.unique or np.sort
for name, tag in zip(names, tags):
self.point_sets[name] = np.where(data == tag)[0]
# TODO there's probably a better way besides np.where, something from
# np.unique or np.sort
for name, tag in zip(names, tags):
self.point_sets[name] = np.where(data == tag)[0]

# remove the cell data
for key in rm_keys:
del self.point_data[key]
del self.point_data[key]
16 changes: 9 additions & 7 deletions tests/test_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ def test_sets_to_int_data():
mesh = helpers.add_point_sets(mesh)
mesh = helpers.add_cell_sets(mesh)

mesh.sets_to_int_data()
mesh.point_sets_to_data()
mesh.cell_sets_to_data()

assert mesh.cell_sets == {}
assert_equal(mesh.cell_data, {"grain0-grain1": [[0, 0, 1, 1, 1]]})
Expand All @@ -39,7 +40,8 @@ def test_sets_to_int_data():
assert_equal(mesh.point_data, {"fixed-loose": [0, 0, 0, 1, 1, 1, 1]})

# now back to set data
mesh.int_data_to_sets()
mesh.cell_data_to_sets("grain0-grain1")
mesh.point_data_to_sets("fixed-loose")

assert mesh.cell_data == {}
assert_equal(mesh.cell_sets, {"grain0": [[0, 1]], "grain1": [[2, 3, 4]]})
Expand All @@ -56,7 +58,7 @@ def test_sets_to_int_data_warning():
cell_sets={"tag": [[0]]},
)
with pytest.warns(UserWarning):
mesh.sets_to_int_data()
mesh.cell_sets_to_data()
assert np.all(mesh.cell_data["tag"] == np.array([[0, -1]]))

mesh = meshio.Mesh(
Expand All @@ -65,7 +67,7 @@ def test_sets_to_int_data_warning():
point_sets={"tag": [[0, 1, 3]]},
)
with pytest.warns(UserWarning):
mesh.sets_to_int_data()
mesh.point_sets_to_data()

assert np.all(mesh.point_data["tag"] == np.array([[0, 0, -1, 0]]))

Expand All @@ -74,7 +76,7 @@ def test_int_data_to_sets():
mesh = helpers.tri_mesh
mesh.cell_data = {"grain0-grain1": [np.array([0, 1])]}

mesh.int_data_to_sets()
mesh.cell_data_to_sets("grain0-grain1")

assert_equal(mesh.cell_sets, {"grain0": [[0]], "grain1": [[1]]})

Expand All @@ -92,8 +94,8 @@ def test_gh_1165():
},
)

mesh.sets_to_int_data()
mesh.int_data_to_sets()
mesh.cell_sets_to_data()
mesh.cell_data_to_sets("test-sets")

assert_equal(mesh.cell_sets, {"test": [[], [1]], "sets": [[0, 1], [0, 2, 3]]})

Expand Down

0 comments on commit 3e6bdf5

Please sign in to comment.