-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(mesh-io): add wasi read_mesh, write_mesh
- Loading branch information
Showing
6 changed files
with
209 additions
and
2 deletions.
There are no files selected for viewing
5 changes: 3 additions & 2 deletions
5
packages/mesh-io/python/itkwasm-mesh-io-wasi/itkwasm_mesh_io_wasi/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
packages/mesh-io/python/itkwasm-mesh-io-wasi/itkwasm_mesh_io_wasi/extension_to_mesh_io.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from collections import OrderedDict | ||
|
||
extension_to_mesh_io = OrderedDict([ | ||
('.vtk', 'vtk_poly_data'), | ||
('.byu', 'byu'), | ||
('.fsa', 'free_surfer_ascii'), | ||
('.fsb', 'free_surfer_binary'), | ||
('.obj', 'obj'), | ||
('.off', 'off'), | ||
('.stl', 'stl'), | ||
('.swc', 'swc'), | ||
('.iwm', 'wasm'), | ||
('.iwm.cbor', 'wasm'), | ||
('.iwm.cbor.zst', 'wasm_zstd'), | ||
('.bmp', 'bmp'), | ||
]) |
13 changes: 13 additions & 0 deletions
13
packages/mesh-io/python/itkwasm-mesh-io-wasi/itkwasm_mesh_io_wasi/mesh_io_index.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
mesh_io_index = [ | ||
'vtk_poly_data', | ||
'byu', | ||
'free_surfer_ascii', | ||
'free_surfer_binary', | ||
'obj', | ||
'off', | ||
'stl', | ||
'swc', | ||
'wasm', | ||
'wasm_zstd', | ||
] | ||
|
61 changes: 61 additions & 0 deletions
61
packages/mesh-io/python/itkwasm-mesh-io-wasi/itkwasm_mesh_io_wasi/read_mesh.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import os | ||
import importlib | ||
from pathlib import Path | ||
|
||
from itkwasm import Mesh | ||
|
||
from .extension_to_mesh_io import extension_to_mesh_io | ||
from .mesh_io_index import mesh_io_index | ||
|
||
def read_mesh( | ||
serialized_mesh: os.PathLike, | ||
information_only: bool = False, | ||
) -> Mesh: | ||
"""Read an mesh file format and convert it to the itk-wasm file format. | ||
:param serialized_mesh: Input mesh serialized in the file format | ||
:type serialized_mesh: os.PathLike | ||
:param information_only: Only read mesh metadata -- do not read pixel data. | ||
:type information_only: bool | ||
:return: Output mesh | ||
:rtype: Mesh | ||
""" | ||
extension = ''.join(Path(serialized_mesh).suffixes) | ||
|
||
io = None | ||
if extension in extension_to_mesh_io: | ||
func = f"{extension_to_mesh_io[extension]}_read_mesh" | ||
mod_name = f"itkwasm_mesh_io_wasi.{func}" | ||
mod = importlib.import_module(mod_name) | ||
io = getattr(mod, func) | ||
else: | ||
for ioname in mesh_io_index: | ||
func = f"{ioname}_read_mesh" | ||
mod_name = f"itkwasm_mesh_io_wasi.{func}" | ||
mod = importlib.import_module(mod_name) | ||
io = getattr(mod, func) | ||
could_read, mesh = io(serialized_mesh, information_only=information_only) | ||
if could_read: | ||
return mesh | ||
|
||
if io is None: | ||
raise RuntimeError(f"Could not find an mesh reader for {extension}") | ||
|
||
could_read, mesh = io(serialized_mesh, information_only=information_only) | ||
if not could_read: | ||
raise RuntimeError(f"Could not read {serialized_mesh}") | ||
|
||
return mesh | ||
|
||
|
||
def meshread( | ||
serialized_mesh: os.PathLike, | ||
information_only: bool = False, | ||
) -> Mesh: | ||
return read_mesh(serialized_mesh, information_only=information_only) | ||
|
||
meshread.__doc__ = f"""{read_mesh.__doc__} | ||
Alias for read_mesh. | ||
""" |
68 changes: 68 additions & 0 deletions
68
packages/mesh-io/python/itkwasm-mesh-io-wasi/itkwasm_mesh_io_wasi/write_mesh.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import os | ||
import importlib | ||
from pathlib import Path | ||
|
||
from itkwasm import Mesh, PixelTypes, IntTypes, FloatTypes | ||
|
||
from .extension_to_mesh_io import extension_to_mesh_io | ||
from .mesh_io_index import mesh_io_index | ||
|
||
def write_mesh( | ||
mesh: Mesh, | ||
serialized_mesh: os.PathLike, | ||
information_only: bool = False, | ||
use_compression: bool = False, | ||
) -> None: | ||
"""Write an itk-wasm Mesh to an mesh file format. | ||
:param mesh: Input mesh | ||
:type mesh: Mesh | ||
:param serialized_mesh: Output mesh serialized in the file format. | ||
:type serialized_mesh: str | ||
:param information_only: Only write mesh metadata -- do not write pixel data. | ||
:type information_only: bool | ||
:param use_compression: Use compression in the written file | ||
:type use_compression: bool | ||
:param serialized_mesh: Input mesh serialized in the file format | ||
:type serialized_mesh: os.PathLike | ||
""" | ||
extension = ''.join(Path(serialized_mesh).suffixes) | ||
|
||
io = None | ||
if extension in extension_to_mesh_io: | ||
func = f"{extension_to_mesh_io[extension]}_write_mesh" | ||
mod_name = f"itkwasm_mesh_io_wasi.{func}" | ||
mod = importlib.import_module(mod_name) | ||
io = getattr(mod, func) | ||
else: | ||
for ioname in mesh_io_index: | ||
func = f"{ioname}_write_mesh" | ||
mod_name = f"itkwasm_mesh_io_wasi.{func}" | ||
mod = importlib.import_module(mod_name) | ||
io = getattr(mod, func) | ||
could_write = io(mesh, serialized_mesh, information_only=information_only, use_compression=use_compression) | ||
if could_write: | ||
return | ||
|
||
if io is None: | ||
raise RuntimeError(f"Could not find an mesh writer for {extension}") | ||
|
||
could_write = io(mesh, serialized_mesh, information_only=information_only, use_compression=use_compression) | ||
if not could_write: | ||
raise RuntimeError(f"Could not write {serialized_mesh}") | ||
|
||
def meshwrite( | ||
mesh: Mesh, | ||
serialized_mesh: os.PathLike, | ||
information_only: bool = False, | ||
use_compression: bool = False, | ||
) -> None: | ||
return write_mesh(mesh, serialized_mesh, information_only=information_only, use_compression=use_compression) | ||
|
||
meshwrite.__doc__ = f"""{write_mesh.__doc__} | ||
Alias for write_mesh. | ||
""" |
48 changes: 48 additions & 0 deletions
48
packages/mesh-io/python/itkwasm-mesh-io-wasi/tests/test_read_write_mesh.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from itkwasm import IntTypes, FloatTypes | ||
import numpy as np | ||
|
||
from itkwasm_mesh_io_wasi import read_mesh, meshread, write_mesh, meshwrite | ||
|
||
from .common import test_input_path, test_output_path | ||
|
||
test_input_file_path = test_input_path / "cow.vtk" | ||
test_output_file_path = test_output_path / "read-write-cow.vtk" | ||
|
||
def verify_mesh(mesh): | ||
assert mesh.meshType.dimension == 3 | ||
assert mesh.meshType.pointComponentType == FloatTypes.Float32 | ||
assert mesh.meshType.pointPixelComponentType == IntTypes.Int8 | ||
assert mesh.numberOfPoints == 2903 | ||
assert np.allclose(mesh.points[0],3.71636) | ||
assert np.allclose(mesh.points[1],2.34339) | ||
assert mesh.numberOfCells == 3263 | ||
assert mesh.cellBufferSize == 18856 | ||
assert mesh.cells[0] == 4 | ||
assert mesh.cells[1] == 4 | ||
assert mesh.cells[2] == 250 | ||
|
||
def test_read_mesh(): | ||
mesh = read_mesh(test_input_file_path) | ||
verify_mesh(mesh) | ||
|
||
def test_meshread(): | ||
mesh = meshread(test_input_file_path) | ||
verify_mesh(mesh) | ||
|
||
def test_write_mesh(): | ||
mesh = read_mesh(test_input_file_path) | ||
|
||
use_compression = False | ||
write_mesh(mesh, test_output_file_path, use_compression=use_compression) | ||
|
||
mesh = read_mesh(test_output_file_path) | ||
verify_mesh(mesh) | ||
|
||
def test_meshwrite(): | ||
mesh = meshread(test_input_file_path) | ||
|
||
use_compression = False | ||
meshwrite(mesh, test_output_file_path, use_compression=use_compression) | ||
|
||
mesh = meshread(test_output_file_path) | ||
verify_mesh(mesh) |