-
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(compare-images): add python bindings
- Loading branch information
Showing
26 changed files
with
749 additions
and
0 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
packages/compare-images/python/itkwasm-compare-images-emscripten/README.md
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,23 @@ | ||
# itkwasm-compare-images-emscripten | ||
|
||
[![PyPI version](https://badge.fury.io/py/itkwasm-compare-images-emscripten.svg)](https://badge.fury.io/py/itkwasm-compare-images-emscripten) | ||
|
||
Read files and images related to compare-images file format. Emscripten implementation. | ||
|
||
This package provides the Emscripten WebAssembly implementation. It is usually not called directly. Please use the [`itkwasm-compare-images`](https://pypi.org/project/itkwasm-compare-images/) instead. | ||
|
||
|
||
## Installation | ||
|
||
```sh | ||
import micropip | ||
await micropip.install('itkwasm-compare-images-emscripten') | ||
``` | ||
|
||
## Development | ||
|
||
```sh | ||
pip install hatch | ||
hatch run download-pyodide | ||
hatch run test | ||
``` |
5 changes: 5 additions & 0 deletions
5
...es/python/itkwasm-compare-images-emscripten/itkwasm_compare_images_emscripten/__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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"""itkwasm-compare-images-emscripten: Read files and images related to compare-images file format. Emscripten implementation.""" | ||
|
||
from .compare_double_images_async import compare_double_images_async | ||
|
||
from ._version import __version__ |
1 change: 1 addition & 0 deletions
1
...es/python/itkwasm-compare-images-emscripten/itkwasm_compare_images_emscripten/_version.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 @@ | ||
__version__ = "1.0.0" |
86 changes: 86 additions & 0 deletions
86
...ompare-images-emscripten/itkwasm_compare_images_emscripten/compare_double_images_async.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,86 @@ | ||
# Generated file. Do not edit. | ||
|
||
from pathlib import Path | ||
import os | ||
from typing import Dict, Tuple, Optional, List, Any | ||
|
||
from .js_package import js_package | ||
|
||
from itkwasm.pyodide import ( | ||
to_js, | ||
to_py, | ||
js_resources | ||
) | ||
from itkwasm import ( | ||
InterfaceTypes, | ||
Image, | ||
) | ||
|
||
async def compare_double_images_async( | ||
test_image: Image, | ||
baseline_images: List[Image] = [], | ||
difference_threshold: float = 0, | ||
radius_tolerance: int = 0, | ||
number_of_pixels_tolerance: int = 0, | ||
ignore_boundary_pixels: bool = False, | ||
) -> Tuple[Dict, Image, Image]: | ||
"""Compare double pixel type images with a tolerance for regression testing. | ||
:param test_image: The input test image | ||
:type test_image: Image | ||
:param baseline_images: Baseline images compare against | ||
:type baseline_images: Image | ||
:param difference_threshold: Intensity difference for pixels to be considered different. | ||
:type difference_threshold: float | ||
:param radius_tolerance: Radius of the neighborhood around a pixel to search for similar intensity values. | ||
:type radius_tolerance: int | ||
:param number_of_pixels_tolerance: Number of pixels that can be different before the test fails. | ||
:type number_of_pixels_tolerance: int | ||
:param ignore_boundary_pixels: Ignore boundary pixels. Useful when resampling may have introduced difference pixel values along the image edge. | ||
:type ignore_boundary_pixels: bool | ||
:return: Metrics for the baseline with the fewest number of pixels outside the tolerances. | ||
:rtype: Dict | ||
:return: Absolute difference image | ||
:rtype: Image | ||
:return: Unsigned char, 2D difference image for rendering | ||
:rtype: Image | ||
""" | ||
js_module = await js_package.js_module | ||
web_worker = js_resources.web_worker | ||
|
||
kwargs = {} | ||
if baseline_images is not None: | ||
kwargs["baselineImages"] = to_js(baseline_images) | ||
if difference_threshold: | ||
kwargs["differenceThreshold"] = to_js(difference_threshold) | ||
if radius_tolerance: | ||
kwargs["radiusTolerance"] = to_js(radius_tolerance) | ||
if number_of_pixels_tolerance: | ||
kwargs["numberOfPixelsTolerance"] = to_js(number_of_pixels_tolerance) | ||
if ignore_boundary_pixels: | ||
kwargs["ignoreBoundaryPixels"] = to_js(ignore_boundary_pixels) | ||
|
||
outputs = await js_module.compareDoubleImages(web_worker, to_js(test_image), **kwargs) | ||
|
||
output_web_worker = None | ||
output_list = [] | ||
outputs_object_map = outputs.as_object_map() | ||
for output_name in outputs.object_keys(): | ||
if output_name == 'webWorker': | ||
output_web_worker = outputs_object_map[output_name] | ||
else: | ||
output_list.append(to_py(outputs_object_map[output_name])) | ||
|
||
js_resources.web_worker = output_web_worker | ||
|
||
if len(output_list) == 1: | ||
return output_list[0] | ||
return tuple(output_list) |
6 changes: 6 additions & 0 deletions
6
.../python/itkwasm-compare-images-emscripten/itkwasm_compare_images_emscripten/js_package.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,6 @@ | ||
from itkwasm.pyodide import JsPackageConfig, JsPackage | ||
|
||
from ._version import __version__ | ||
|
||
default_config = JsPackageConfig(f"https://cdn.jsdelivr.net/npm/@itk-wasm/compare-images@{__version__}/dist/bundles/compare-images.js") | ||
js_package = JsPackage(default_config) |
72 changes: 72 additions & 0 deletions
72
packages/compare-images/python/itkwasm-compare-images-emscripten/pyproject.toml
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,72 @@ | ||
[build-system] | ||
requires = ["hatchling", "hatch-vcs"] | ||
build-backend = "hatchling.build" | ||
|
||
[project] | ||
name = "itkwasm-compare-images-emscripten" | ||
readme = "README.md" | ||
license = "Apache-2.0" | ||
dynamic = ["version", "description"] | ||
classifiers = [ | ||
"License :: OSI Approved :: Apache Software License", | ||
"Programming Language :: Python", | ||
"Programming Language :: C++", | ||
"Environment :: WebAssembly", | ||
"Environment :: WebAssembly :: Emscripten", | ||
"Environment :: WebAssembly :: WASI", | ||
"Development Status :: 3 - Alpha", | ||
"Intended Audience :: Developers", | ||
"Intended Audience :: Science/Research", | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.7", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
] | ||
keywords = [ | ||
"itkwasm", | ||
"webassembly", | ||
"emscripten", | ||
] | ||
|
||
requires-python = ">=3.7" | ||
dependencies = [ | ||
"itkwasm >= 1.0.b105", | ||
] | ||
|
||
[tool.hatch.version] | ||
path = "itkwasm_compare_images_emscripten/_version.py" | ||
|
||
[tool.hatch.envs.default] | ||
dependencies = [ | ||
"pytest", | ||
"pytest-pyodide", | ||
] | ||
|
||
[project.urls] | ||
Home = "https://github.com/InsightSoftwareConsortium/itk-wasm" | ||
Source = "https://github.com/InsightSoftwareConsortium/itk-wasm" | ||
|
||
[tool.hatch.envs.default.scripts] | ||
test = [ | ||
"hatch build -t wheel", | ||
"pytest --dist-dir=./dist --rt=chrome", | ||
] | ||
download-pyodide = [ | ||
"curl -L https://github.com/pyodide/pyodide/releases/download/0.23.1/pyodide-0.23.1.tar.bz2 -o pyodide.tar.bz2", | ||
"tar xjf pyodide.tar.bz2", | ||
"rm -rf dist pyodide.tar.bz2", | ||
"mv pyodide dist", | ||
] | ||
serve = [ | ||
"hatch build -t wheel", | ||
'echo "\nVisit http://localhost:8877/console.html\n"', | ||
"python -m http.server --directory=./dist 8877", | ||
] | ||
|
||
|
||
[tool.hatch.build] | ||
exclude = [ | ||
"/examples", | ||
] |
20 changes: 20 additions & 0 deletions
20
...mpare-images/python/itkwasm-compare-images-emscripten/test/test_itkwasm_compare_images.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,20 @@ | ||
import pytest | ||
import sys | ||
|
||
if sys.version_info < (3,10): | ||
pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) | ||
|
||
from pytest_pyodide import run_in_pyodide | ||
|
||
from itkwasm_compare_images_emscripten import __version__ as test_package_version | ||
|
||
@pytest.fixture | ||
def package_wheel(): | ||
return f"itkwasm_compare_images_emscripten-{test_package_version}-py3-none-any.whl" | ||
|
||
@run_in_pyodide(packages=['micropip']) | ||
async def test_example(selenium, package_wheel): | ||
import micropip | ||
await micropip.install(package_wheel) | ||
|
||
# Write your test code here |
26 changes: 26 additions & 0 deletions
26
packages/compare-images/python/itkwasm-compare-images-wasi/README.md
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,26 @@ | ||
# itkwasm-compare-images-wasi | ||
|
||
[![PyPI version](https://badge.fury.io/py/itkwasm-compare-images-wasi.svg)](https://badge.fury.io/py/itkwasm-compare-images-wasi) | ||
|
||
Read files and images related to compare-images file format. WASI implementation. | ||
|
||
This package provides the WASI WebAssembly implementation. It is usually not called directly. Please use [`itkwasm-compare-images`](https://pypi.org/project/itkwasm-compare-images/) instead. | ||
|
||
|
||
## Installation | ||
|
||
```sh | ||
pip install itkwasm-compare-images-wasi | ||
``` | ||
|
||
## Development | ||
|
||
```sh | ||
pip install pytest | ||
pip install -e . | ||
pytest | ||
|
||
# or | ||
pip install hatch | ||
hatch run test | ||
``` |
5 changes: 5 additions & 0 deletions
5
...compare-images/python/itkwasm-compare-images-wasi/itkwasm_compare_images_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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"""itkwasm-compare-images-wasi: Read files and images related to compare-images file format. WASI implementation.""" | ||
|
||
from .compare_double_images import compare_double_images | ||
|
||
from ._version import __version__ |
1 change: 1 addition & 0 deletions
1
...compare-images/python/itkwasm-compare-images-wasi/itkwasm_compare_images_wasi/_version.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 @@ | ||
__version__ = "1.0.0" |
112 changes: 112 additions & 0 deletions
112
...s/python/itkwasm-compare-images-wasi/itkwasm_compare_images_wasi/compare_double_images.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,112 @@ | ||
# Generated file. Do not edit. | ||
|
||
from pathlib import Path, PurePosixPath | ||
import os | ||
from typing import Dict, Tuple, Optional, List, Any | ||
|
||
from importlib_resources import files as file_resources | ||
|
||
_pipeline = None | ||
|
||
from itkwasm import ( | ||
InterfaceTypes, | ||
PipelineOutput, | ||
PipelineInput, | ||
Pipeline, | ||
Image, | ||
) | ||
|
||
def compare_double_images( | ||
test_image: Image, | ||
baseline_images: List[Image] = [], | ||
difference_threshold: float = 0, | ||
radius_tolerance: int = 0, | ||
number_of_pixels_tolerance: int = 0, | ||
ignore_boundary_pixels: bool = False, | ||
) -> Tuple[Dict, Image, Image]: | ||
"""Compare double pixel type images with a tolerance for regression testing. | ||
:param test_image: The input test image | ||
:type test_image: Image | ||
:param baseline_images: Baseline images compare against | ||
:type baseline_images: Image | ||
:param difference_threshold: Intensity difference for pixels to be considered different. | ||
:type difference_threshold: float | ||
:param radius_tolerance: Radius of the neighborhood around a pixel to search for similar intensity values. | ||
:type radius_tolerance: int | ||
:param number_of_pixels_tolerance: Number of pixels that can be different before the test fails. | ||
:type number_of_pixels_tolerance: int | ||
:param ignore_boundary_pixels: Ignore boundary pixels. Useful when resampling may have introduced difference pixel values along the image edge. | ||
:type ignore_boundary_pixels: bool | ||
:return: Metrics for the baseline with the fewest number of pixels outside the tolerances. | ||
:rtype: Dict | ||
:return: Absolute difference image | ||
:rtype: Image | ||
:return: Unsigned char, 2D difference image for rendering | ||
:rtype: Image | ||
""" | ||
global _pipeline | ||
if _pipeline is None: | ||
_pipeline = Pipeline(file_resources('itkwasm_compare_images_wasi').joinpath(Path('wasm_modules') / Path('compare-double-images.wasi.wasm'))) | ||
|
||
pipeline_outputs: List[PipelineOutput] = [ | ||
PipelineOutput(InterfaceTypes.JsonObject), | ||
PipelineOutput(InterfaceTypes.Image), | ||
PipelineOutput(InterfaceTypes.Image), | ||
] | ||
|
||
pipeline_inputs: List[PipelineInput] = [ | ||
PipelineInput(InterfaceTypes.Image, test_image), | ||
] | ||
|
||
args: List[str] = ['--memory-io',] | ||
# Inputs | ||
args.append('0') | ||
# Outputs | ||
args.append('0') | ||
args.append('1') | ||
args.append('2') | ||
# Options | ||
if len(baseline_images) > 1: | ||
if len(baseline_images) < 1: | ||
raise ValueError('"baseline-images" option must have a length > 1') | ||
|
||
args.append('--baseline-images') | ||
for value in baseline_images: | ||
input_count_string = str(len(pipeline_inputs)) | ||
pipeline_inputs.push(PipelineInput(InterfaceTypes.Image, value)) | ||
args.append(input_count_string) | ||
|
||
if difference_threshold: | ||
args.append('--difference-threshold') | ||
args.append(str(difference_threshold)) | ||
|
||
if radius_tolerance: | ||
args.append('--radius-tolerance') | ||
args.append(str(radius_tolerance)) | ||
|
||
if number_of_pixels_tolerance: | ||
args.append('--number-of-pixels-tolerance') | ||
args.append(str(number_of_pixels_tolerance)) | ||
|
||
if ignore_boundary_pixels: | ||
args.append('--ignore-boundary-pixels') | ||
|
||
|
||
outputs = _pipeline.run(args, pipeline_outputs, pipeline_inputs) | ||
|
||
result = ( | ||
outputs[0].data, | ||
outputs[1].data, | ||
outputs[2].data, | ||
) | ||
return result | ||
|
Binary file added
BIN
+1.52 MB
...pare-images-wasi/itkwasm_compare_images_wasi/wasm_modules/compare-double-images.wasi.wasm
Binary file not shown.
Oops, something went wrong.