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

Proof of principle napari workflows mock #504

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
185 changes: 103 additions & 82 deletions poetry.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ scikit-image = { version = ">=0.19", optional = true }
napari-segment-blobs-and-things-with-membranes = { version = "^0.3.3", optional = true }
napari-workflows = { version = "^0.2.8", optional = true }
napari-skimage-regionprops = { version = "^0.8.1", optional = true }
napari-skimage-regionprops-mock = { file="tests/data/napari_workflows/mock_package/dist/napari_skimage_regionprops_mock-9.9.9-py3-none-any.whl", optional = true }
napari-tools-menu = { version = "^0.1.19", optional = true }
cellpose = { version = "~2.2", optional = true }
torch = { version = "<=2.0.0", optional = true }

[tool.poetry.extras]
fractal-tasks = ["Pillow", "imageio-ffmpeg", "scikit-image", "llvmlite", "napari-segment-blobs-and-things-with-membranes", "napari-workflows", "napari-skimage-regionprops", "napari-tools-menu", "cellpose", "torch"]
fractal-tasks = ["Pillow", "imageio-ffmpeg", "scikit-image", "llvmlite", "napari-segment-blobs-and-things-with-membranes", "napari-workflows", "napari-skimage-regionprops", "napari-skimage-regionprops-mock", "napari-tools-menu", "cellpose", "torch"]

[tool.poetry.group.dev]
optional = true
Expand Down
82 changes: 82 additions & 0 deletions tests/data/napari_workflows/mock_package/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
.napari_cache

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask instance folder
instance/

# Sphinx documentation
docs/_build/

# MkDocs documentation
/site/

# PyBuilder
target/

# IPython Notebook
.ipynb_checkpoints

# pyenv
.python-version

# OS
.DS_Store

# written by setuptools_scm
*/_version.py
/.idea/
/venv/
test.csv
34 changes: 34 additions & 0 deletions tests/data/napari_workflows/mock_package/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
This folder is a mock of the original
https://github.com/haesleinhuepf/napari-skimage-regionprops/ package. The
original copyright notice is reported below:

-------------------------------------------------------------------------------


Copyright (c) 2021, Robert Haase, Physics of Life, TU Dresden
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of napari-skimage-regionprops nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6 changes: 6 additions & 0 deletions tests/data/napari_workflows/mock_package/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include requirements.txt

recursive-exclude * __pycache__
recursive-exclude demo *
recursive-exclude images *
recursive-exclude * *.py[co]
4 changes: 4 additions & 0 deletions tests/data/napari_workflows/mock_package/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Build command:
```
poetry run python -m build --wheel
```
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import logging

from napari_plugin_engine import napari_hook_implementation

from ._regionprops import regionprops_table # , regionprops_table_all_frames

logging.critical(
"WARNING: THIS IS A MOCK OF THE ACTUAL "
"'napari_skimage_regionprops' PACKAGE"
)


@napari_hook_implementation
def napari_experimental_provide_function():
return [regionprops_table]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import warnings

import numpy as np
import pandas

try:
import napari
except Exception as e:
warnings.warn(str(e))

from napari_tools_menu import register_function


@register_function(menu="Measurement tables > Regionprops (scikit-image, nsr)")
def regionprops_table(
image: "napari.types.ImageData",
labels: "napari.types.LabelsData",
size: bool = True,
intensity: bool = True,
perimeter: bool = False,
shape: bool = False,
position: bool = False,
moments: bool = False,
napari_viewer: "napari.Viewer" = None,
) -> "pandas.DataFrame":
"""
MOCK OF THE ORIGINAL FUNCTION
"""

num_labels = len(np.unique(labels))
int_values = np.arange(num_labels)
float_values = np.arange(num_labels) + 0.5
table = dict(
label=int_values,
area=float_values,
bbox_area=float_values,
equivalent_diameter=float_values,
convex_area=float_values,
)
df = pandas.DataFrame(table)
return df
5 changes: 5 additions & 0 deletions tests/data/napari_workflows/mock_package/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
napari-plugin-engine>=0.1.4
numpy
pandas
napari-tools-menu>=0.1.19
napari-workflows
34 changes: 34 additions & 0 deletions tests/data/napari_workflows/mock_package/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import codecs
import os

from setuptools import setup


def read(fname):
file_path = os.path.join(os.path.dirname(__file__), fname)
return codecs.open(file_path, encoding="utf-8").read()


# Add your dependencies in requirements.txt
# Note: you can add test-specific requirements in tox.ini
requirements = []
with open("requirements.txt") as f:
for line in f:
stripped = line.split("#")[0].strip()
if len(stripped) > 0:
requirements.append(stripped)


setup(
name="napari-skimage-regionprops-mock",
author="Marcelo Zoccoler, Robert Haase",
author_email="[email protected]",
license="BSD-3",
description='MOCK OF "A regionprops table widget plugin for napari"',
python_requires=">=3.8",
install_requires=requirements,
version="9.9.9",
setup_requires=["setuptools_scm"],
)
12 changes: 12 additions & 0 deletions tests/data/napari_workflows/wf_4_mock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
!!python/object:napari_workflows._workflow.Workflow
_tasks:
regionprops_DAPI: !!python/tuple
- !!python/name:napari_skimage_regionprops_mock._regionprops.regionprops_table ''
- dapi_img
- dapi_label_img
- true
- false
- false
- false
- false
- false
111 changes: 82 additions & 29 deletions tests/tasks/test_workflows_napari_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
napari_workflows_wrapper,
)

try:
import napari_skimage_regionprops_mock

has_napari_skimage_regionprops_mock = True
print(napari_skimage_regionprops_mock)
except ModuleNotFoundError:
has_napari_skimage_regionprops_mock = False


def test_napari_workflow(
tmp_path: Path,
Expand Down Expand Up @@ -365,35 +373,6 @@ def test_relabeling(
)
debug(metadata)

# Re-run with overwrite=True
for component in metadata["image"]:
napari_workflows_wrapper(
input_paths=[str(zarr_path)],
output_path=str(zarr_path),
metadata=metadata,
component=component,
input_specs=input_specs,
output_specs=output_specs,
workflow_file=workflow_file,
input_ROI_table="FOV_ROI_table",
overwrite=True,
)

# Re-run with overwrite=False
with pytest.raises(OverwriteNotAllowedError):
for component in metadata["image"]:
napari_workflows_wrapper(
input_paths=[str(zarr_path)],
output_path=str(zarr_path),
metadata=metadata,
component=component,
input_specs=input_specs,
output_specs=output_specs,
workflow_file=workflow_file,
input_ROI_table="FOV_ROI_table",
overwrite=False,
)

# Check output
image_zarr = Path(zarr_path / metadata["image"][0])
validate_labels_and_measurements(
Expand Down Expand Up @@ -781,3 +760,77 @@ def test_napari_workflow_CYX_wrong_dimensions(
level=2,
)
debug(e.value)


@pytest.mark.skipif(
not has_napari_skimage_regionprops_mock,
reason="napari_skimage_regionprops_mock not available",
)
def test_napari_workflow_mock(
tmp_path: Path,
testdata_path: Path,
zenodo_zarr: list[str],
zenodo_zarr_metadata: list[dict[str, Any]],
):

# Init
zarr_path = tmp_path / "tmp_out/"
metadata = prepare_3D_zarr(
str(zarr_path), zenodo_zarr, zenodo_zarr_metadata
)
debug(zarr_path)
debug(metadata)

# Prepare parameters for first napari-workflows task (labeling)
workflow_file = str(testdata_path / "napari_workflows/wf_1.yaml")
input_specs: dict[str, NapariWorkflowsInput] = {
"input": {"type": "image", "channel": {"wavelength_id": "A01_C01"}}, # type: ignore # noqa
}
output_specs: dict[str, NapariWorkflowsOutput] = {
"Result of Expand labels (scikit-image, nsbatwm)": { # type: ignore # noqa
"type": "label",
"label_name": "label_DAPI",
},
}

# Run once
for component in metadata["image"]:
napari_workflows_wrapper(
input_paths=[str(zarr_path)],
output_path=str(zarr_path),
metadata=metadata,
component=component,
input_specs=input_specs,
output_specs=output_specs,
workflow_file=workflow_file,
input_ROI_table="FOV_ROI_table",
level=2,
)
debug(metadata)

# Prepare parameters for second napari-workflows task (measurement)
workflow_file = str(testdata_path / "napari_workflows/wf_4_mock.yaml")
input_specs = {
"dapi_img": {"type": "image", "channel": {"wavelength_id": "A01_C01"}}, # type: ignore # noqa
"dapi_label_img": {"type": "label", "label_name": "label_DAPI"}, # type: ignore # noqa
}
output_specs = {
"regionprops_DAPI": { # type: ignore # noqa
"type": "dataframe",
"table_name": "regionprops_DAPI",
},
}

# Run once
for component in metadata["image"]:
napari_workflows_wrapper(
input_paths=[str(zarr_path)],
output_path=str(zarr_path),
metadata=metadata,
component=component,
input_specs=input_specs,
output_specs=output_specs,
workflow_file=workflow_file,
input_ROI_table="FOV_ROI_table",
)
debug(metadata)