Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transform io python #1277

Merged
merged 22 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dcf4098
fix(itkwasm): interface type is TransformList instead of Transform
thewtex Nov 21, 2024
bdbbc2f
chore(itkwasm): bump version to 1.0b181
thewtex Nov 21, 2024
4120317
test(transform-io): wasi format tests
thewtex Nov 21, 2024
78d1395
test(itkwasm): bump pyodide to 0.26.4
thewtex Nov 21, 2024
95f6087
fix(itkwasm): add WasiConfig args for wasmtime 27.0.0
thewtex Nov 21, 2024
94adbbe
chore(itkwasm): bump version to 1.0b182
thewtex Nov 21, 2024
d630f1c
fix(itkwasm): dask is only a testing dependency
thewtex Nov 21, 2024
db91709
chore(itkwasm): bump version to 1.0b183
thewtex Nov 21, 2024
a4516fd
feat(itkwasm): add pipeline TransformList support
thewtex Nov 21, 2024
781430e
build(itkwasm): bump wasmtime dep to 27.0.1
thewtex Nov 21, 2024
5f7da32
chore(itkwasm): bump version to 1.0b184
thewtex Nov 21, 2024
83ca16b
test(transform-io): wasi format tests
thewtex Nov 22, 2024
7ca5ca7
chore(bindgen): bump itkwasm to 1.0.b184, Python to 3.9-3.13
thewtex Nov 22, 2024
c0d7605
feat(transform-io): add wasi read_transform, write_transform
thewtex Nov 23, 2024
4d20cc8
feat(itkwasm): pyodide support for Transform
thewtex Nov 25, 2024
b2ad922
chore(itkwasm): bump version to 1.0b185
thewtex Nov 25, 2024
2ffc2ca
test(transform-io): emscripten hdf5 read write tests
thewtex Nov 23, 2024
395beb7
feat(transform-io): emscripten read_transform_async, write_transform_…
thewtex Nov 25, 2024
0d7641c
feat(transform-io): dispatch read and write functions
thewtex Nov 26, 2024
f9be400
ci(python-wasm): add transform-io
thewtex Nov 26, 2024
cbe3dc0
build(transform-io): update pyproject.toml from license to license-ex…
thewtex Nov 26, 2024
e72fc66
build(transform-io): add dist/ folders to .gitignore
thewtex Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-wasm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
matrix:
os: [ubuntu-22.04, windows-2022, macos-14]
python-minor-version: [11, 12]
package: [compress-stringify, compare-images, dicom, mesh-io, image-io, downsample]
package: [compress-stringify, compare-images, dicom, mesh-io, image-io, transform-io, downsample]

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion packages/core/python/itkwasm/itkwasm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""itkwasm: Python interface to itk-wasm WebAssembly modules."""

__version__ = "1.0b180"
__version__ = "1.0b185"

from .interface_types import InterfaceTypes
from .image import Image, ImageType, ImageRegion
Expand Down
2 changes: 1 addition & 1 deletion packages/core/python/itkwasm/itkwasm/interface_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class InterfaceTypes(str, Enum):
Mesh = "Mesh"
PointSet = "PointSet"
PolyData = "PolyData"
Transform = "Transform"
TransformList = "TransformList"
JsonCompatible = "JsonCompatible"
54 changes: 53 additions & 1 deletion packages/core/python/itkwasm/itkwasm/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .binary_file import BinaryFile
from .image import Image
from .mesh import Mesh
from .transform import Transform
from .point_set import PointSet
from .polydata import PolyData
from .json_compatible import JsonCompatible
Expand All @@ -45,6 +46,8 @@
WasiConfig,
Linker,
WasmtimeError,
DirPerms,
FilePerms
)

# Get the value of the ITKWASM_CACHE_DIR environment variable
Expand Down Expand Up @@ -83,7 +86,7 @@ def __init__(
wasi_config.argv = args

for preopen in preopen_directories:
wasi_config.preopen_dir(preopen, preopen)
wasi_config.preopen_dir(preopen, preopen, DirPerms.READ_WRITE, FilePerms.READ_WRITE)

store.set_wasi(wasi_config)

Expand Down Expand Up @@ -299,6 +302,34 @@ def run(
"pointData": f"data:application/vnd.itk.address,0:{point_data_ptr}",
}
ri.set_input_json(point_set_json, index)
elif input_.type == InterfaceTypes.TransformList:
transform_list = input_.data
transform_list_json = []
for idx, transform in enumerate(transform_list):
if transform.numberOfFixedParameters:
fpv = array_like_to_bytes(transform.fixedParameters)
else:
fpv = bytes([])
fixed_parameters_ptr = ri.set_input_array(fpv, index, idx * 2)
fixed_parameters = f"data:application/vnd.itk.address,0:{fixed_parameters_ptr}"
if transform.numberOfParameters:
pv = array_like_to_bytes(transform.parameters)
else:
pv = bytes([])
parameters_ptr = ri.set_input_array(pv, index, idx * 2 + 1)
parameters = f"data:application/vnd.itk.address,0:{parameters_ptr}"
transform_json = {
"transformType": asdict(transform.transformType),
"numberOfFixedParameters": transform.numberOfFixedParameters,
"numberOfParameters": transform.numberOfParameters,
"name": transform.name,
"inputSpaceName": transform.inputSpaceName,
"outputSpaceName": transform.outputSpaceName,
"fixedParameters": fixed_parameters,
"parameters": parameters,
}
transform_list_json.append(transform_json)
ri.set_input_json(transform_list_json, index)
elif input_.type == InterfaceTypes.PolyData:
polydata = input_.data
if polydata.numberOfPoints:
Expand Down Expand Up @@ -489,6 +520,27 @@ def run(
point_set.pointData = buffer_to_numpy_array(point_set.pointSetType.pointPixelComponentType, bytes([]))

output_data = PipelineOutput(InterfaceTypes.PointSet, point_set)
elif output.type == InterfaceTypes.TransformList:
transform_list_json = ri.get_output_json(index)
transform_list = []
for idx, transform_json in enumerate(transform_list_json):
transform = Transform(**transform_json)
if transform.numberOfFixedParameters > 0:
data_ptr = ri.get_output_array_address(0, index, idx * 2)
data_size = ri.get_output_array_size(0, index, idx * 2)
transform.fixedParameters = buffer_to_numpy_array(
transform.transformType.parametersValueType,
ri.wasmtime_lift(data_ptr, data_size),
)
if transform.numberOfParameters > 0:
data_ptr = ri.get_output_array_address(0, index, idx * 2 + 1)
data_size = ri.get_output_array_size(0, index, idx * 2 + 1)
transform.parameters = buffer_to_numpy_array(
transform.transformType.parametersValueType,
ri.wasmtime_lift(data_ptr, data_size),
)
transform_list.append(transform)
output_data = PipelineOutput(InterfaceTypes.TransformList, transform_list)
elif output.type == InterfaceTypes.PolyData:
polydata_json = ri.get_output_json(index)
polydata = PolyData(**polydata_json)
Expand Down
22 changes: 22 additions & 0 deletions packages/core/python/itkwasm/itkwasm/pyodide.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .point_set import PointSet, PointSetType
from .mesh import Mesh, MeshType
from .polydata import PolyData, PolyDataType
from .transform import Transform, TransformType
from .binary_file import BinaryFile
from .binary_stream import BinaryStream
from .text_file import TextFile
Expand Down Expand Up @@ -147,6 +148,20 @@ def to_py(js_proxy):
if polydata_dict["cellData"] is not None:
polydata_dict["cellData"] = buffer_to_numpy_array(cell_pixel_component_type, polydata_dict["cellData"])
return PolyData(**polydata_dict)
elif hasattr(js_proxy, "transformType"):
transform_dict = js_proxy.to_py()
transform_type = TransformType(**transform_dict["transformType"])
transform_dict["transformType"] = transform_type
parameters_value_type = transform_type.parametersValueType
if transform_dict["fixedParameters"] is not None:
transform_dict["fixedParameters"] = buffer_to_numpy_array(
parameters_value_type, transform_dict["fixedParameters"]
)
if transform_dict["parameters"] is not None:
transform_dict["parameters"] = buffer_to_numpy_array(
parameters_value_type, transform_dict["parameters"]
)
return Transform(**transform_dict)
elif hasattr(js_proxy, "path") and hasattr(js_proxy, "data") and isinstance(js_proxy.data, str):
with open(js_proxy.path, "w") as fp:
fp.write(js_proxy.data)
Expand Down Expand Up @@ -222,6 +237,13 @@ def to_js(py, **kwargs):
if polydata_dict["cellData"] is not None:
polydata_dict["cellData"] = polydata_dict["cellData"].ravel()
return pyodide.ffi.to_js(polydata_dict, dict_converter=js.Object.fromEntries)
elif isinstance(py, Transform):
transform_dict = asdict(py)
if transform_dict["fixedParameters"] is not None:
transform_dict["fixedParameters"] = transform_dict["fixedParameters"].ravel()
if transform_dict["parameters"] is not None:
transform_dict["parameters"] = transform_dict["parameters"].ravel()
return pyodide.ffi.to_js(transform_dict, dict_converter=js.Object.fromEntries)
elif isinstance(py, TextStream):
text_stream_dict = asdict(py)
return pyodide.ffi.to_js(text_stream_dict, dict_converter=js.Object.fromEntries)
Expand Down
5 changes: 4 additions & 1 deletion packages/core/python/itkwasm/itkwasm/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from numpy import ndarray as ArrayLike
import numpy as np

from .float_types import FloatTypes

class TransformParameterizations(str, Enum):
Composite = "Composite"
Identity = "Identity"
Expand Down Expand Up @@ -40,9 +42,10 @@ class TransformParameterizations(str, Enum):

@dataclass
class TransformType:
transformParameterization: TransformParameterizations = TransformParameterizations.Identity
parametersValueType: FloatTypes = FloatTypes.Float64
inputDimension: int = 3
outputDimension: int = 3
transformParameterization: TransformParameterizations = TransformParameterizations.Identity

@dataclass
class Transform:
Expand Down
63 changes: 31 additions & 32 deletions packages/core/python/itkwasm/pixi.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading