Skip to content

Commit fd4d5fe

Browse files
committed
test(mesh-io): python read and write point set wasi tests
1 parent 04c79b0 commit fd4d5fe

29 files changed

+666
-9
lines changed

packages/core/python/itkwasm/itkwasm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from .interface_types import InterfaceTypes
66
from .image import Image, ImageType, ImageRegion
7-
from .pointset import PointSet, PointSetType
7+
from .point_set import PointSet, PointSetType
88
from .mesh import Mesh, MeshType
99
from .transform import Transform, TransformType, TransformParameterizations
1010
from .polydata import PolyData, PolyDataType

packages/core/python/itkwasm/itkwasm/interface_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class InterfaceTypes(str, Enum):
77
BinaryStream = "BinaryStream"
88
Image = "Image"
99
Mesh = "Mesh"
10+
PointSet = "PointSet"
1011
PolyData = "PolyData"
1112
Transform = "Transform"
1213
JsonCompatible = "JsonCompatible"

packages/core/python/itkwasm/itkwasm/pipeline.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .binary_file import BinaryFile
2323
from .image import Image
2424
from .mesh import Mesh
25+
from .point_set import PointSet
2526
from .polydata import PolyData
2627
from .json_compatible import JsonCompatible
2728
from .int_types import IntTypes
@@ -277,6 +278,27 @@ def run(
277278
"cellData": f"data:application/vnd.itk.address,0:{cell_data_ptr}",
278279
}
279280
ri.set_input_json(mesh_json, index)
281+
elif input_.type == InterfaceTypes.PointSet:
282+
point_set = input_.data
283+
if point_set.numberOfPoints:
284+
pv = array_like_to_bytes(point_set.points)
285+
else:
286+
pv = bytes([])
287+
points_ptr = ri.set_input_array(pv, index, 0)
288+
if point_set.numberOfPointPixels:
289+
pdv = array_like_to_bytes(point_set.pointData)
290+
else:
291+
pdv = bytes([])
292+
point_data_ptr = ri.set_input_array(pdv, index, 1)
293+
point_set_json = {
294+
"pointSetType": asdict(point_set.pointSetType),
295+
"name": point_set.name,
296+
"numberOfPoints": point_set.numberOfPoints,
297+
"points": f"data:application/vnd.itk.address,0:{points_ptr}",
298+
"numberOfPointPixels": point_set.numberOfPointPixels,
299+
"pointData": f"data:application/vnd.itk.address,0:{point_data_ptr}",
300+
}
301+
ri.set_input_json(point_set_json, index)
280302
elif input_.type == InterfaceTypes.PolyData:
281303
polydata = input_.data
282304
if polydata.numberOfPoints:
@@ -442,6 +464,31 @@ def run(
442464
mesh.cellData = buffer_to_numpy_array(mesh.meshType.cellPixelComponentType, bytes([]))
443465

444466
output_data = PipelineOutput(InterfaceTypes.Mesh, mesh)
467+
elif output.type == InterfaceTypes.PointSet:
468+
point_set_json = ri.get_output_json(index)
469+
point_set = PointSet(**point_set_json)
470+
471+
if point_set.numberOfPoints > 0:
472+
data_ptr = ri.get_output_array_address(0, index, 0)
473+
data_size = ri.get_output_array_size(0, index, 0)
474+
point_set.points = buffer_to_numpy_array(
475+
point_set.pointSetType.pointComponentType,
476+
ri.wasmtime_lift(data_ptr, data_size),
477+
)
478+
else:
479+
point_set.points = buffer_to_numpy_array(point_set.pointSetType.pointComponentType, bytes([]))
480+
481+
if point_set.numberOfPointPixels > 0:
482+
data_ptr = ri.get_output_array_address(0, index, 1)
483+
data_size = ri.get_output_array_size(0, index, 1)
484+
point_set.pointData = buffer_to_numpy_array(
485+
point_set.pointSetType.pointPixelComponentType,
486+
ri.wasmtime_lift(data_ptr, data_size),
487+
)
488+
else:
489+
point_set.pointData = buffer_to_numpy_array(point_set.pointSetType.pointPixelComponentType, bytes([]))
490+
491+
output_data = PipelineOutput(InterfaceTypes.PointSet, point_set)
445492
elif output.type == InterfaceTypes.PolyData:
446493
polydata_json = ri.get_output_json(index)
447494
polydata = PolyData(**polydata_json)

packages/core/python/itkwasm/itkwasm/pyodide.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Optional
33

44
from .image import Image, ImageType
5-
from .pointset import PointSet, PointSetType
5+
from .point_set import PointSet, PointSetType
66
from .mesh import Mesh, MeshType
77
from .polydata import PolyData, PolyDataType
88
from .binary_file import BinaryFile

packages/mesh-io/python/itkwasm-mesh-io-emscripten/itkwasm_mesh_io_emscripten/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from .read_mesh_async import read_mesh_async
44
from .write_mesh_async import write_mesh_async
55

6+
from .read_point_set_async import read_point_set_async
7+
from .write_point_set_async import write_point_set_async
8+
69
from .byu_read_mesh_async import byu_read_mesh_async
710
from .byu_write_mesh_async import byu_write_mesh_async
811
from .free_surfer_ascii_read_mesh_async import free_surfer_ascii_read_mesh_async
@@ -24,4 +27,15 @@
2427
from .wasm_zstd_read_mesh_async import wasm_zstd_read_mesh_async
2528
from .wasm_zstd_write_mesh_async import wasm_zstd_write_mesh_async
2629

30+
from .obj_read_mesh_async import obj_read_mesh_async
31+
from .obj_write_mesh_async import obj_write_mesh_async
32+
from .off_read_mesh_async import off_read_mesh_async
33+
from .off_write_mesh_async import off_write_mesh_async
34+
from .vtk_poly_data_read_mesh_async import vtk_poly_data_read_mesh_async
35+
from .vtk_poly_data_write_mesh_async import vtk_poly_data_write_mesh_async
36+
from .wasm_read_mesh_async import wasm_read_mesh_async
37+
from .wasm_write_mesh_async import wasm_write_mesh_async
38+
from .wasm_zstd_read_mesh_async import wasm_zstd_read_mesh_async
39+
from .wasm_zstd_write_mesh_async import wasm_zstd_write_mesh_async
40+
2741
from ._version import __version__

packages/mesh-io/python/itkwasm-mesh-io-emscripten/itkwasm_mesh_io_emscripten/extension_to_mesh_io.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,4 @@
1212
('.iwm', 'wasm'),
1313
('.iwm.cbor', 'wasm'),
1414
('.iwm.cbor.zst', 'wasmZstd'),
15-
('.bmp', 'bmp'),
1615
])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from collections import OrderedDict
2+
3+
extension_to_point_set_io = OrderedDict([
4+
('.vtk', 'vtkPolyData'),
5+
('.obj', 'obj'),
6+
('.off', 'off'),
7+
('.iwm', 'wasm'),
8+
('.iwm.cbor', 'wasm'),
9+
('.iwm.cbor.zst', 'wasmZstd'),
10+
])
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
point_set_io_index = [
2+
'vtk_poly_data',
3+
'obj',
4+
'off',
5+
'wasm',
6+
'wasm_zstd',
7+
]
8+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import os
2+
from typing import Optional, Union
3+
from pathlib import Path
4+
5+
from itkwasm import (
6+
PointSet,
7+
BinaryFile,
8+
)
9+
10+
from .js_package import js_package
11+
12+
from itkwasm.pyodide import (
13+
to_js,
14+
to_py,
15+
js_resources
16+
)
17+
18+
from .extension_to_point_set_io import extension_to_point_set_io
19+
from .point_set_io_index import point_set_io_index
20+
21+
async def read_point_set_async(
22+
serialized_point_set: os.PathLike,
23+
information_only: bool = False,
24+
) -> PointSet:
25+
"""Read an point set file format and convert it to the ITK-Wasm file format.
26+
27+
:param serialized_point_set: Input point set serialized in the file format
28+
:type serialized_point_set: os.PathLike
29+
30+
:param information_only: Only read point set metadata -- do not read pixel data.
31+
:type information_only: bool
32+
33+
:return: Output point set
34+
:rtype: PointSet
35+
"""
36+
js_module = await js_package.js_module
37+
web_worker = js_resources.web_worker
38+
39+
kwargs = {}
40+
if information_only:
41+
kwargs["informationOnly"] = to_js(information_only)
42+
43+
extension = ''.join(Path(serialized_point_set).suffixes)
44+
45+
io = None
46+
if extension in extension_to_point_set_io:
47+
func = f"{extension_to_point_set_io[extension]}ReadPointSet"
48+
io = getattr(js_module, func)
49+
else:
50+
for ioname in point_set_io_index:
51+
func = f"{ioname}ReadPointSet"
52+
io = getattr(js_module, func)
53+
outputs = await io(to_js(BinaryFile(serialized_point_set)), webWorker=web_worker, noCopy=True, **kwargs)
54+
outputs_object_map = outputs.as_object_map()
55+
web_worker = outputs_object_map['webWorker']
56+
js_resources.web_worker = web_worker
57+
could_read = to_py(outputs_object_map['couldRead'])
58+
if could_read:
59+
point_set = to_py(outputs_object_map['point_set'])
60+
return point_set
61+
62+
if io is None:
63+
raise RuntimeError(f"Could not find an point_set reader for {extension}")
64+
65+
outputs = await io(to_js(BinaryFile(serialized_point_set)), webWorker=web_worker, noCopy=True, **kwargs)
66+
outputs_object_map = outputs.as_object_map()
67+
web_worker = outputs_object_map['webWorker']
68+
could_read = to_py(outputs_object_map['couldRead'])
69+
70+
if not could_read:
71+
raise RuntimeError(f"Could not read {serialized_point_set}")
72+
73+
js_resources.web_worker = web_worker
74+
75+
point_set = to_py(outputs_object_map['point_set'])
76+
77+
return point_set
78+
79+
async def pointsetread_async(
80+
serialized_point_set: os.PathLike,
81+
information_only: bool = False,
82+
) -> PointSet:
83+
return await read_point_set_async(serialized_point_set, information_only=information_only)
84+
85+
pointsetread_async.__doc__ = f"""{read_point_set_async.__doc__}
86+
Alias for read_point_set_async.
87+
"""

0 commit comments

Comments
 (0)