From 33164ac352bdc956db749f7829686df34d71acdc Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:38:06 +0100 Subject: [PATCH 1/9] Safe import of _table.py --- napari_skimage_regionprops/_table.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/napari_skimage_regionprops/_table.py b/napari_skimage_regionprops/_table.py index 3dfc3d6..15d5255 100644 --- a/napari_skimage_regionprops/_table.py +++ b/napari_skimage_regionprops/_table.py @@ -1,9 +1,16 @@ import time -import napari +try: + import napari + from qtpy.QtCore import QTimer + from qtpy.QtWidgets import QTableWidget, QHBoxLayout, QTableWidgetItem, QWidget, QGridLayout, QPushButton, QFileDialog +except ModuleNotFoundError as e: + import warnings + warnings.warn(str(e)) + class QWidget: + pass + from pandas import DataFrame -from qtpy.QtCore import QTimer -from qtpy.QtWidgets import QTableWidget, QHBoxLayout, QTableWidgetItem, QWidget, QGridLayout, QPushButton, QFileDialog from napari_tools_menu import register_function import pandas as pd @@ -16,7 +23,7 @@ class TableWidget(QWidget): The table widget represents a table inside napari. Tables are just views on `properties` of `layers`. """ - def __init__(self, layer: napari.layers.Layer, viewer:napari.Viewer = None): + def __init__(self, layer: "napari.layers.Layer", viewer: "napari.Viewer" = None): super().__init__() self._layer = layer @@ -235,7 +242,7 @@ def append_content(self, table: Union[dict, DataFrame], how: str = 'outer'): @register_function(menu="Measurement > Show table (nsr)") -def add_table(labels_layer: napari.layers.Layer, viewer:napari.Viewer) -> TableWidget: +def add_table(labels_layer: "napari.layers.Layer", viewer: "napari.Viewer") -> TableWidget: """ Add a table to a viewer and return the table widget. The table will show the `properties` of the given layer. """ @@ -251,7 +258,7 @@ def add_table(labels_layer: napari.layers.Layer, viewer:napari.Viewer) -> TableW return dock_widget -def get_table(labels_layer: napari.layers.Layer, viewer:napari.Viewer) -> TableWidget: +def get_table(labels_layer: "napari.layers.Layer", viewer: "napari.Viewer") -> TableWidget: """ Searches inside a viewer for a given table and returns it. If it cannot find it, it will return None. @@ -274,4 +281,4 @@ def _determine_frame_column(table): for c in candidates: if c in table.keys(): return c - return None \ No newline at end of file + return None From 64a4f116be5ddeb33c843e1a08fdefc4f5872242 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:40:01 +0100 Subject: [PATCH 2/9] Safe import of _regionprops.py --- napari_skimage_regionprops/_regionprops.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/napari_skimage_regionprops/_regionprops.py b/napari_skimage_regionprops/_regionprops.py index 8b7a6eb..2051d2c 100644 --- a/napari_skimage_regionprops/_regionprops.py +++ b/napari_skimage_regionprops/_regionprops.py @@ -2,13 +2,17 @@ import numpy as np import pandas -from napari import Viewer +try: + from napari import Viewer + import napari +except ModuleNotFoundError as e: + warnings.warn(str(e)) + from napari_tools_menu import register_function -import napari import math from ._all_frames import analyze_all_frames -def regionprops(image_layer : napari.layers.Layer, labels_layer: napari.layers.Labels, size : bool = True, intensity : bool = True, perimeter : bool = False, shape : bool = False, position : bool = False, moments : bool = False, napari_viewer : Viewer = None): +def regionprops(image_layer: "napari.layers.Layer", labels_layer: "napari.layers.Labels", size : bool = True, intensity : bool = True, perimeter : bool = False, shape : bool = False, position : bool = False, moments : bool = False, napari_viewer : Viewer = None): warnings.warn("napari_skimage_regionprops.regionprops is deprecated. Use regionprops_table instead.") image_data = None if image_layer is not None: @@ -17,7 +21,7 @@ def regionprops(image_layer : napari.layers.Layer, labels_layer: napari.layers.L regionprops_table(image_data, labels_layer.data, size, intensity, perimeter, shape, position, moments, napari_viewer) @register_function(menu="Measurement > 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 : Viewer = None) -> "pandas.DataFrame": +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 : Viewer = None) -> "pandas.DataFrame": """ Adds a table widget to a given napari viewer with quantitative analysis results derived from an image-label pair. """ From f8c88685bf7267acb8b6da4fdc76ba9db760c514 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:40:58 +0100 Subject: [PATCH 3/9] Delayed napari import in _all_frames.py --- napari_skimage_regionprops/_all_frames.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/napari_skimage_regionprops/_all_frames.py b/napari_skimage_regionprops/_all_frames.py index 27da9a0..05a8d57 100644 --- a/napari_skimage_regionprops/_all_frames.py +++ b/napari_skimage_regionprops/_all_frames.py @@ -1,5 +1,3 @@ - -import napari from toolz import curry from typing import Callable from functools import wraps @@ -10,6 +8,7 @@ @curry def analyze_all_frames(function: Callable) -> Callable: + import napari from napari_workflows._workflow import _get_layer_from_data @wraps(function) From 479bf5c5af0e72821f46e59bb8dceae0841e5cd6 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:45:25 +0100 Subject: [PATCH 4/9] Add try/except blocks for napari-related imports --- napari_skimage_regionprops/_all_frames.py | 7 ++++++- napari_skimage_regionprops/_load_csv.py | 10 ++++++++-- napari_skimage_regionprops/_regionprops.py | 5 ++--- napari_skimage_regionprops/_utilities.py | 20 +++++++++++++------- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/napari_skimage_regionprops/_all_frames.py b/napari_skimage_regionprops/_all_frames.py index 05a8d57..ed5578c 100644 --- a/napari_skimage_regionprops/_all_frames.py +++ b/napari_skimage_regionprops/_all_frames.py @@ -6,9 +6,14 @@ import pandas as pd from ._utilities import isimage +try: + import napari +except ModuleNotFoundError as e: + import warnings + warnings.warn(str(e)) + @curry def analyze_all_frames(function: Callable) -> Callable: - import napari from napari_workflows._workflow import _get_layer_from_data @wraps(function) diff --git a/napari_skimage_regionprops/_load_csv.py b/napari_skimage_regionprops/_load_csv.py index 3247b79..62a16c8 100644 --- a/napari_skimage_regionprops/_load_csv.py +++ b/napari_skimage_regionprops/_load_csv.py @@ -1,9 +1,15 @@ -import napari import numpy as np from napari_tools_menu import register_function +try: + import napari +except ModuleNotFoundError as e: + import warnings + warnings.warn(str(e)) + + @register_function(menu="Measurement > Load from CSV (nsr)") -def load_csv(csv_filename:"magicgui.types.PathLike", labels_layer:napari.layers.Labels, viewer:napari.Viewer=None): +def load_csv(csv_filename:"magicgui.types.PathLike", labels_layer: "napari.layers.Labels", viewer: "napari.Viewer" = None): """Save contents of a CSV file into a given layer's properties""" import pandas as pd # load region properties from csv file diff --git a/napari_skimage_regionprops/_regionprops.py b/napari_skimage_regionprops/_regionprops.py index 2051d2c..5ce0872 100644 --- a/napari_skimage_regionprops/_regionprops.py +++ b/napari_skimage_regionprops/_regionprops.py @@ -3,7 +3,6 @@ import numpy as np import pandas try: - from napari import Viewer import napari except ModuleNotFoundError as e: warnings.warn(str(e)) @@ -12,7 +11,7 @@ import math from ._all_frames import analyze_all_frames -def regionprops(image_layer: "napari.layers.Layer", labels_layer: "napari.layers.Labels", size : bool = True, intensity : bool = True, perimeter : bool = False, shape : bool = False, position : bool = False, moments : bool = False, napari_viewer : Viewer = None): +def regionprops(image_layer: "napari.layers.Layer", labels_layer: "napari.layers.Labels", size : bool = True, intensity : bool = True, perimeter : bool = False, shape : bool = False, position : bool = False, moments : bool = False, napari_viewer : "napari.Viewer" = None): warnings.warn("napari_skimage_regionprops.regionprops is deprecated. Use regionprops_table instead.") image_data = None if image_layer is not None: @@ -21,7 +20,7 @@ def regionprops(image_layer: "napari.layers.Layer", labels_layer: "napari.layers regionprops_table(image_data, labels_layer.data, size, intensity, perimeter, shape, position, moments, napari_viewer) @register_function(menu="Measurement > 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 : Viewer = None) -> "pandas.DataFrame": +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": """ Adds a table widget to a given napari viewer with quantitative analysis results derived from an image-label pair. """ diff --git a/napari_skimage_regionprops/_utilities.py b/napari_skimage_regionprops/_utilities.py index 45f9244..108862f 100644 --- a/napari_skimage_regionprops/_utilities.py +++ b/napari_skimage_regionprops/_utilities.py @@ -1,18 +1,24 @@ import numpy as np -from napari_plugin_engine import napari_hook_implementation -from napari.types import ImageData -from napari import Viewer +try: + from napari_plugin_engine import napari_hook_implementation + from napari.types import ImageData + from napari import Viewer + from napari.layers import Image, Labels, Layer + from typing_extensions import Annotated + LayerInput = Annotated[Layer, {"label": "Image"}] +except ModuleNotFoundError as e: + import warnings + warnings.warn(str(e)) + from napari_tools_menu import register_function -from typing_extensions import Annotated -from napari.layers import Image, Labels, Layer -LayerInput = Annotated[Layer, {"label": "Image"}] + @napari_hook_implementation def napari_experimental_provide_function(): return [duplicate_current_frame] @register_function(menu="Utilities > Duplicate current timepoint (nsr)") -def duplicate_current_frame(layer : LayerInput, napari_viewer : Viewer, axis : int = 0) -> Layer: +def duplicate_current_frame(layer : "LayerInput", napari_viewer: "Viewer", axis : int = 0) -> "Layer": image = layer.data current_dim_value = napari_viewer.dims.current_step[axis] new_image = np.take(image, current_dim_value, axis) From d0c3af4530a8f5a536e5591af5fbd7ddd031c1e0 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Thu, 26 Jan 2023 08:35:55 +0100 Subject: [PATCH 5/9] Update napari-tools-menu requirement to >=0.1.18 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 619db33..a8c2dd1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ numpy scikit-image napari pandas -napari-tools-menu>=0.1.11 +napari-tools-menu>=0.1.18 napari-workflows imageio!=2.22.1 From c140301650db7b2f1651c3ec0592edf65cd7fbe0 Mon Sep 17 00:00:00 2001 From: Robert Haase Date: Sun, 29 Jan 2023 09:51:58 +0100 Subject: [PATCH 6/9] update links to be more precise --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c86068c..af94660 100644 --- a/README.md +++ b/README.md @@ -84,9 +84,9 @@ The user can select categories of features for feature extraction in the user in * extent * feret_diameter_max * local_centroid - * roundness as defined for 2D labels [by ImageJ](https://imagej.nih.gov/ij/docs/menus/analyze.html) - * circularity as defined for 2D labels [by ImageJ](https://imagej.nih.gov/ij/docs/menus/analyze.html) - * aspect_ratio as defined for 2D labels [by ImageJ](https://imagej.nih.gov/ij/docs/menus/analyze.html) + * roundness as defined for 2D labels [by ImageJ](https://imagej.nih.gov/ij/docs/menus/analyze.html#set) + * circularity as defined for 2D labels [by ImageJ](https://imagej.nih.gov/ij/docs/menus/analyze.html#set) + * aspect_ratio as defined for 2D labels [by ImageJ](https://imagej.nih.gov/ij/docs/menus/analyze.html#set) * position: * centroid * bbox From 53305dd7426a13356f88ff95942d0850ff8819e4 Mon Sep 17 00:00:00 2001 From: Robert Haase Date: Sun, 29 Jan 2023 10:01:55 +0100 Subject: [PATCH 7/9] fix crashes when clicking menu --- napari_skimage_regionprops/_utilities.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/napari_skimage_regionprops/_utilities.py b/napari_skimage_regionprops/_utilities.py index 108862f..7355bbd 100644 --- a/napari_skimage_regionprops/_utilities.py +++ b/napari_skimage_regionprops/_utilities.py @@ -2,13 +2,14 @@ try: from napari_plugin_engine import napari_hook_implementation from napari.types import ImageData - from napari import Viewer + import napari from napari.layers import Image, Labels, Layer from typing_extensions import Annotated LayerInput = Annotated[Layer, {"label": "Image"}] except ModuleNotFoundError as e: import warnings warnings.warn(str(e)) + LayerInput = None from napari_tools_menu import register_function @@ -18,7 +19,7 @@ def napari_experimental_provide_function(): return [duplicate_current_frame] @register_function(menu="Utilities > Duplicate current timepoint (nsr)") -def duplicate_current_frame(layer : "LayerInput", napari_viewer: "Viewer", axis : int = 0) -> "Layer": +def duplicate_current_frame(layer : LayerInput, napari_viewer: "napari.Viewer", axis : int = 0) -> "napari.layers.Layer": image = layer.data current_dim_value = napari_viewer.dims.current_step[axis] new_image = np.take(image, current_dim_value, axis) From 8378380f47f2303bffcfbadb24b5b9366044d159 Mon Sep 17 00:00:00 2001 From: Robert Haase Date: Sun, 29 Jan 2023 10:04:28 +0100 Subject: [PATCH 8/9] removed unnecessary imports --- napari_skimage_regionprops/_table.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/napari_skimage_regionprops/_table.py b/napari_skimage_regionprops/_table.py index 503bd1a..e221886 100644 --- a/napari_skimage_regionprops/_table.py +++ b/napari_skimage_regionprops/_table.py @@ -1,5 +1,3 @@ -import time - try: import napari from qtpy.QtCore import QTimer From b0075a6add126eb1bedcebaeea81faee826013c4 Mon Sep 17 00:00:00 2001 From: Robert Haase Date: Sun, 29 Jan 2023 10:07:37 +0100 Subject: [PATCH 9/9] bump version --- napari_skimage_regionprops/__init__.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/napari_skimage_regionprops/__init__.py b/napari_skimage_regionprops/__init__.py index 82e7957..0ac158f 100644 --- a/napari_skimage_regionprops/__init__.py +++ b/napari_skimage_regionprops/__init__.py @@ -8,7 +8,7 @@ try: from ._version import version as __version__ except ImportError: - __version__ = "0.7.0" + __version__ = "0.8.0" @napari_hook_implementation diff --git a/setup.py b/setup.py index 811d112..f59577c 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ def read(fname): packages=find_packages(), python_requires='>=3.8', install_requires=requirements, - version='0.7.0', + version='0.8.0', #use_scm_version=use_scm, setup_requires=['setuptools_scm'], classifiers=[