Skip to content

Commit

Permalink
Merge pull request #1246 from thewtex/point-set-io
Browse files Browse the repository at this point in the history
point set io
  • Loading branch information
thewtex authored Oct 17, 2024
2 parents 007e79a + c41eea9 commit 2bbfc74
Show file tree
Hide file tree
Showing 352 changed files with 10,210 additions and 1,673 deletions.
7 changes: 7 additions & 0 deletions include/itkWasmMeshIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <fstream>

#include "itkMeshJSON.h"
#include "itkPointSetJSON.h"
#include "cbor.h"

namespace itk
Expand Down Expand Up @@ -72,6 +73,9 @@ class WebAssemblyInterface_EXPORT WasmMeshIO: public MeshIOBase
/** Set the JSON representation of the image information. */
void SetJSON(const MeshJSON & json);

/** Set the JSON representation of the image information. */
void SetJSON(const PointSetJSON & json);

/*-------- This part of the interfaces deals with writing data ----- */

/** Writes the data to disk from the memory buffer provided. Make sure
Expand All @@ -93,6 +97,9 @@ class WebAssemblyInterface_EXPORT WasmMeshIO: public MeshIOBase
#if !defined(ITK_WRAPPING_PARSER)
/** Get the JSON representation of the mesh information. */
auto GetJSON() -> MeshJSON;

/** Get the JSON representation of the point set information. */
auto GetPointSetJSON() -> PointSetJSON;
#endif

protected:
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/core/python/itkwasm/itkwasm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""itkwasm: Python interface to itk-wasm WebAssembly modules."""

__version__ = "1.0b178"
__version__ = "1.0b179"

from .interface_types import InterfaceTypes
from .image import Image, ImageType, ImageRegion
from .pointset import PointSet, PointSetType
from .point_set import PointSet, PointSetType
from .mesh import Mesh, MeshType
from .transform import Transform, TransformType, TransformParameterizations
from .polydata import PolyData, PolyDataType
Expand Down
1 change: 1 addition & 0 deletions packages/core/python/itkwasm/itkwasm/interface_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class InterfaceTypes(str, Enum):
BinaryStream = "BinaryStream"
Image = "Image"
Mesh = "Mesh"
PointSet = "PointSet"
PolyData = "PolyData"
Transform = "Transform"
JsonCompatible = "JsonCompatible"
47 changes: 47 additions & 0 deletions 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 .point_set import PointSet
from .polydata import PolyData
from .json_compatible import JsonCompatible
from .int_types import IntTypes
Expand Down Expand Up @@ -277,6 +278,27 @@ def run(
"cellData": f"data:application/vnd.itk.address,0:{cell_data_ptr}",
}
ri.set_input_json(mesh_json, index)
elif input_.type == InterfaceTypes.PointSet:
point_set = input_.data
if point_set.numberOfPoints:
pv = array_like_to_bytes(point_set.points)
else:
pv = bytes([])
points_ptr = ri.set_input_array(pv, index, 0)
if point_set.numberOfPointPixels:
pdv = array_like_to_bytes(point_set.pointData)
else:
pdv = bytes([])
point_data_ptr = ri.set_input_array(pdv, index, 1)
point_set_json = {
"pointSetType": asdict(point_set.pointSetType),
"name": point_set.name,
"numberOfPoints": point_set.numberOfPoints,
"points": f"data:application/vnd.itk.address,0:{points_ptr}",
"numberOfPointPixels": point_set.numberOfPointPixels,
"pointData": f"data:application/vnd.itk.address,0:{point_data_ptr}",
}
ri.set_input_json(point_set_json, index)
elif input_.type == InterfaceTypes.PolyData:
polydata = input_.data
if polydata.numberOfPoints:
Expand Down Expand Up @@ -442,6 +464,31 @@ def run(
mesh.cellData = buffer_to_numpy_array(mesh.meshType.cellPixelComponentType, bytes([]))

output_data = PipelineOutput(InterfaceTypes.Mesh, mesh)
elif output.type == InterfaceTypes.PointSet:
point_set_json = ri.get_output_json(index)
point_set = PointSet(**point_set_json)

if point_set.numberOfPoints > 0:
data_ptr = ri.get_output_array_address(0, index, 0)
data_size = ri.get_output_array_size(0, index, 0)
point_set.points = buffer_to_numpy_array(
point_set.pointSetType.pointComponentType,
ri.wasmtime_lift(data_ptr, data_size),
)
else:
point_set.points = buffer_to_numpy_array(point_set.pointSetType.pointComponentType, bytes([]))

if point_set.numberOfPointPixels > 0:
data_ptr = ri.get_output_array_address(0, index, 1)
data_size = ri.get_output_array_size(0, index, 1)
point_set.pointData = buffer_to_numpy_array(
point_set.pointSetType.pointPixelComponentType,
ri.wasmtime_lift(data_ptr, data_size),
)
else:
point_set.pointData = buffer_to_numpy_array(point_set.pointSetType.pointPixelComponentType, bytes([]))

output_data = PipelineOutput(InterfaceTypes.PointSet, point_set)
elif output.type == InterfaceTypes.PolyData:
polydata_json = ri.get_output_json(index)
polydata = PolyData(**polydata_json)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/python/itkwasm/itkwasm/pyodide.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Optional

from .image import Image, ImageType
from .pointset import PointSet, PointSetType
from .point_set import PointSet, PointSetType
from .mesh import Mesh, MeshType
from .polydata import PolyData, PolyDataType
from .binary_file import BinaryFile
Expand Down
3 changes: 2 additions & 1 deletion packages/core/python/itkwasm/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies = [
"itk>=5.4.0",
"pytest >=2.7.3",
"pytest-pyodide",
"pyodide-py",
"dask[array]",
"test_accelerator @ {root:uri}/test/test-accelerator",
]
Expand All @@ -57,7 +58,7 @@ test = [
"pytest --dist-dir=./dist --rt=chrome",
]
download-pyodide = [
"curl -L https://github.com/pyodide/pyodide/releases/download/0.25.1/pyodide-0.25.1.tar.bz2 -o pyodide.tar.bz2",
"curl -L https://github.com/pyodide/pyodide/releases/download/0.26.2/pyodide-0.26.2.tar.bz2 -o pyodide.tar.bz2",
"tar xjf pyodide.tar.bz2",
"rm -rf dist pyodide.tar.bz2",
"mv pyodide dist",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/typescript/itk-wasm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "itk-wasm",
"version": "1.0.0-b.178",
"version": "1.0.0-b.179",
"packageManager": "[email protected]",
"description": "High-performance spatial analysis in a web browser, Node.js, and reproducible execution across programming languages and hardware architectures.",
"type": "module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const interfaceJsonTypeToInterfaceType = new Map([
['OUTPUT_IMAGE', 'Image'],
['INPUT_MESH', 'Mesh'],
['OUTPUT_MESH', 'Mesh'],
['INPUT_POINT_SET', 'PointSet'],
['OUTPUT_POINT_SET', 'PointSet'],
['INPUT_POLYDATA', 'PolyData'],
['OUTPUT_POLYDATA', 'PolyData'],
['INPUT_TRANSFORM', 'Transform'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const interfaceJsonTypeToPythonType = new Map([
['OUTPUT_IMAGE', 'Image'],
['INPUT_MESH', 'Mesh'],
['OUTPUT_MESH', 'Mesh'],
['INPUT_POINT_SET', 'PointSet'],
['OUTPUT_POINT_SET', 'PointSet'],
['INPUT_POLYDATA', 'PolyData'],
['OUTPUT_POLYDATA', 'PolyData'],
['INPUT_TRANSFORM', 'Transform'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const demoSupportedInputTypes = new Set([
'BOOL',
'INPUT_JSON',
'INPUT_IMAGE',
'INPUT_MESH'
'INPUT_MESH',
'INPUT_POINT_SET'
])
const demoSupportedOutputTypes = new Set([
'OUTPUT_TEXT_FILE',
Expand All @@ -20,7 +21,8 @@ const demoSupportedOutputTypes = new Set([
'OUTPUT_BINARY_STREAM',
'OUTPUT_JSON',
'OUTPUT_IMAGE',
'OUTPUT_MESH'
'OUTPUT_MESH',
'OUTPUT_POINT_SET'
])

function allDemoTypesSupported(interfaceJson) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
import camelCase from '../../camel-case.js'
import snakeCase from '../../snake-case.js'

function inputParametersDemoHtml (functionName, prefix, indent, parameter, required, useCamelCase) {
function inputParametersDemoHtml(
functionName,
prefix,
indent,
parameter,
required,
useCamelCase
) {
let result = ''
const description = parameter.description.replaceAll('"', '&quot;')
const requiredAttr = required ? 'required ' : ''
const label = useCamelCase ? camelCase(parameter.name) : snakeCase(parameter.name)
const label = useCamelCase
? camelCase(parameter.name)
: snakeCase(parameter.name)
const tooltipContent = `content="Use the Upload button to provide the ${label}"`
const parameterType = parameter.type.split(' ')[0].split(':')[0]
switch (parameterType) {
case 'INPUT_TEXT_FILE':
case 'INPUT_TEXT_STREAM': {
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><sl-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></sl-details></sl-tooltip>\n`
const multiple = parameter.itemsExpectedMax > 1 ? 'multiple ' : ''
result += `${prefix}${indent}<label for="${parameter.name}-file"><sl-button name="${parameter.name}-file-button" variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sp-button></label><input type="file" ${multiple} name="${parameter.name}-file" style="display: none"/>\n`
result += '<br /><br />\n'
}
case 'INPUT_TEXT_STREAM':
{
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><sl-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></sl-details></sl-tooltip>\n`
const multiple = parameter.itemsExpectedMax > 1 ? 'multiple ' : ''
result += `${prefix}${indent}<label for="${parameter.name}-file"><sl-button name="${parameter.name}-file-button" variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sp-button></label><input type="file" ${multiple} name="${parameter.name}-file" style="display: none"/>\n`
result += '<br /><br />\n'
}
break
case 'INPUT_BINARY_FILE':
case 'INPUT_BINARY_STREAM': {
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><sl-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></sl-details></sl-tooltip>\n`
const multiple = parameter.itemsExpectedMax > 1 ? 'multiple ' : ''
result += `${prefix}${indent}<label for="${parameter.name}-file"><sl-button name="${parameter.name}-file-button" ${requiredAttr}variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sl-button></label><input type="file" ${multiple} name="${parameter.name}-file" style="display: none"/>\n`
result += '<br /><br />\n'
}
case 'INPUT_BINARY_STREAM':
{
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><sl-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></sl-details></sl-tooltip>\n`
const multiple = parameter.itemsExpectedMax > 1 ? 'multiple ' : ''
result += `${prefix}${indent}<label for="${parameter.name}-file"><sl-button name="${parameter.name}-file-button" ${requiredAttr}variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sl-button></label><input type="file" ${multiple} name="${parameter.name}-file" style="display: none"/>\n`
result += '<br /><br />\n'
}
break
case 'TEXT':
case 'OUTPUT_TEXT_FILE':
Expand All @@ -32,28 +43,30 @@ function inputParametersDemoHtml (functionName, prefix, indent, parameter, requi
break
case 'INT':
case 'UINT':
case 'FLOAT': {
const typeName = parameter.itemsExpectedMax > 1 ? "text" : "number"
let constraints = ''
if (parameter.itemsExpected !== 1) {
constraints = ''
} else if (parameterType === 'INT') {
constraints = 'step="1" '
} else if (parameterType === 'UINT') {
constraints = 'min="0" step="1" '
} else if (parameterType === 'FLOAT') {
constraints = 'step="any" '
case 'FLOAT':
{
const typeName = parameter.itemsExpectedMax > 1 ? 'text' : 'number'
let constraints = ''
if (parameter.itemsExpected !== 1) {
constraints = ''
} else if (parameterType === 'INT') {
constraints = 'step="1" '
} else if (parameterType === 'UINT') {
constraints = 'min="0" step="1" '
} else if (parameterType === 'FLOAT') {
constraints = 'step="any" '
}
result += `${prefix}${indent}<sl-input ${requiredAttr}name="${parameter.name}" type="${typeName}" value="${parameter.default}" ${constraints}label="${label}" help-text="${description}"></sl-input>\n`
result += '<br />\n'
}
result += `${prefix}${indent}<sl-input ${requiredAttr}name="${parameter.name}" type="${typeName}" value="${parameter.default}" ${constraints}label="${label}" help-text="${description}"></sl-input>\n`
result += '<br />\n'
}
break
case 'BOOL':
result += `${prefix}${indent}<sl-checkbox name="${parameter.name}">${label} - <i>${description}</i></sl-checkbox>\n`
result += '<br /><br />\n'
break
case 'INPUT_JSON':
case 'INPUT_MESH':
case 'INPUT_POINT_SET':
result += `${prefix}${indent}<label for="${parameter.name}-file"><sl-button name="${parameter.name}-file-button" variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sp-button></label><input type="file" name="${parameter.name}-file" style="display: none"/>\n`
result += `${prefix}${indent}<sl-tooltip ${tooltipContent}><sl-details id="${functionName}-${parameter.name}-details" summary="${label}: ${description}" disabled></sl-details></sl-tooltip>\n`
result += '<br /><br />\n'
Expand Down
Loading

0 comments on commit 2bbfc74

Please sign in to comment.