Skip to content

Commit

Permalink
Merge pull request #83 from TimMonko/switch-to-napari-bioio
Browse files Browse the repository at this point in the history
remove aicsimageio entirely switch to napari-bioio along with bioio changes
  • Loading branch information
TimMonko authored Oct 9, 2024
2 parents dc57289 + 5e5e0c9 commit 8475511
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_and_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
files: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: true
fail_ci_if_error: false


deploy:
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ A collection of widgets intended to serve any person seeking to process microsco
pip install napari-ndev
```

The easiest way to get started with **napari-ndev** is to install all the optional dependencies (see note below) with:

```bash
pip install napari-ndev[all]
```

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

### Optional Libraries
Expand All @@ -35,7 +41,7 @@ pip install napari-ndev
pip install napari-ndev[extras]
```

**napari-ndev** can optionally use GPL-3 licensed libraries to enhance its functionality, but are not required. If you choose to install and use these optional dependencies, you must comply with the GPL-3 license terms. The main functional improvement is from `napari-aicsimageio` to properly handle metadata with the `Image Utilities` widget, but also adds support for `czi` and `lif` files. These libraries can be installed with [pip]:
**napari-ndev** can optionally use GPL-3 licensed libraries to enhance its functionality, but are not required. If you choose to install and use these optional dependencies, you must comply with the GPL-3 license terms. The main functional improvement is from `napari-bioio` to properly handle metadata with the `Image Utilities` widget, but also adds support for `czi` and `lif` files. These libraries can be installed with [pip]:

```bash
pip install napari-ndev[gpl-extras]
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/utilities/image_utilities.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# Image Utilities\n",
"\n",
"This example will describe how to manage metadata, crop, and annotate images with the Image Utilities widget. The widget can be opened from `Plugins --> neuralDev --> Image Utilities`. To crop layers in the viewer, open `Plugins --> crop region (napari_crop)`. Below, we load napari and open the Image Utilities Widget and load in a large image originally saved with the widget from a multi-scene CZI file. Note that currently no metadata populates the widget because the file was not selected with `Select Files`. Instead, the image was opened with the [`napari-aicsimageio`](https://github.com/AllenCellModeling/napari-aicsimageio) plugin; however, the metadata is saved and could normally be accessed from `viewer.layers[n].metadata['aicsimage']`.\n",
"This example will describe how to manage metadata, crop, and annotate images with the Image Utilities widget. The widget can be opened from `Plugins --> neuralDev --> Image Utilities`. To crop layers in the viewer, open `Plugins --> crop region (napari_crop)`. Below, we load napari and open the Image Utilities Widget and load in a large image originally saved with the widget from a multi-scene CZI file. Note that currently no metadata populates the widget because the file was not selected with `Select Files`. Instead, the image was opened with the [`napari-bioio`](https://github.com/TimMonko/napari-bioio) plugin; however, the metadata is saved and could normally be accessed from `viewer.layers[n].metadata['bioimage']`.\n",
"\n",
"To access metadata from any image in the viewer, press the `Selected Layer` button in the `Update Metadata from:` box. "
]
Expand Down Expand Up @@ -78,7 +78,7 @@
"viewer = napari.Viewer()\n",
"viewer.window.resize(1500, 800) # w x h\n",
"viewer.window.add_plugin_dock_widget('napari-ndev', 'Image Utilities')\n",
"viewer.open(parent / rel_path, plugin='napari-aicsimageio')\n",
"viewer.open(parent / rel_path, plugin='napari-bioio')\n",
"\n",
"nbscreenshot(viewer)"
]
Expand Down
17 changes: 5 additions & 12 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

A collection of widgets intended to serve any person seeking to process microscopy images from start to finish. The wide breadth of this plugin's scope is only made possible by the amazing libraries and plugins from the napari community, especially Robert Haase. Currently, the plugin supports the following goals:

1. **Image Utilities:** Intended for high-throuput image-labeling and management, while passing down important metadata. Allows opening image files (preferably with `napari-aicsimageio` see [Installation](installation.md)) and displaying in napari. Also reads metadata and allows customization prior to saving images and labels layers. Allows concatenation of image files and image layers for saving new images. Speeds up annotation by saving corresponding images and labels in designated folders. Also allows saving of shapes layers as labels in case shapes are being used as a region of interest.
1. **Image Utilities:** Intended for high-throuput image-labeling and management, while passing down important metadata. Allows opening image files (preferably with `napari-bioimageio` see [Installation](installation.md)) and displaying in napari. Also reads metadata and allows customization prior to saving images and labels layers. Allows concatenation of image files and image layers for saving new images. Speeds up annotation by saving corresponding images and labels in designated folders. Also allows saving of shapes layers as labels in case shapes are being used as a region of interest.
2. **Workflow Widget:** Batch pre-processing/processing images using [napari-workflows].
3. **APOC Widget:** Utilizes the excellent accelerated-pixel-and-object-classification ([apoc]) in a similar fashion to [napari-apoc], but intended for batch training and prediction with a napari widget instead of scripting.
* **Custom Feature Set Widget:** Generate a featureset to be used with the APOC widget. Also allows quick application in the napari viewer to an image layer to see all the features.
Expand All @@ -24,13 +24,13 @@ A collection of widgets intended to serve any person seeking to process microsco

### 1. Image Utilities

A quick and easy way to save annotations (a napari labels layer) and corresponding images to corresponding folders. Best if the images are opened with [napari-aicsimageio]--which can be as simple as drag and drop opening by setting the appropriate default reader for each file type in Preferences -> Plugins--in order to utilize the metadata present for saving the image-label pairs. (See [Note about bioio/AICSImageIO](#a-note-about-bioioaicsimageio))
A quick and easy way to save annotations (a napari labels layer) and corresponding images to corresponding folders. Best if the images are opened with [napari-bioio]--which can be as simple as drag and drop opening by setting the appropriate default reader for each file type in Preferences -> Plugins--in order to utilize the metadata present for saving the image-label pairs.

Quick uniform adjustments to a folder of images, saving the output. Currently supports selecting channels, slicing Z, cropping/downsampling in XY, and doing a max projection of the sliced/cropped image data. To be added: alternative projection types, slicing in T, and compatibility with non TCZYX images (but this is not a priority since [bioio] and [aicsimageio] currently always extracts images as TCZYX even if a dim is only length 1.
Quick uniform adjustments to a folder of images, saving the output. Currently supports selecting channels, slicing Z, cropping/downsampling in XY, and doing a max projection of the sliced/cropped image data. To be added: alternative projection types, slicing in T, and compatibility with non TCZYX images (but this is not a priority since [bioio] currently always extracts images as TCZYX even if a dim is only length 1.

### 2. Workflow Widget

Batch pre-processing/processing images using [napari-workflows]. Images are processed outside the napari-viewer using [aicsimageio] as both reader and writer. Prior to passing the images to napari-workflows, the user selects the correct images as the roots (inputs) and thus napari-workflows matches the processing to create the outputs. The advantage of using napari-workflows for batch processing is that it provides an incredibly flexible processing interface without writing a novel widget for small changes to processing steps like specific filters, segmentation, or measurements. Currently only intended for use with images as inputs and images as outputs from napari-workflows, though there is future potential to have other outputs possible, such as .csv measurement arrays.
Batch pre-processing/processing images using [napari-workflows]. Images are processed outside the napari-viewer using [bioio] as both reader and writer. Prior to passing the images to napari-workflows, the user selects the correct images as the roots (inputs) and thus napari-workflows matches the processing to create the outputs. The advantage of using napari-workflows for batch processing is that it provides an incredibly flexible processing interface without writing a novel widget for small changes to processing steps like specific filters, segmentation, or measurements. Currently only intended for use with images as inputs and images as outputs from napari-workflows, though there is future potential to have other outputs possible, such as .csv measurement arrays.

### 3. APOC Widget

Expand All @@ -40,18 +40,11 @@ Utilizes the excellent accelerated-pixel-and-object-classification ([apoc]) in a

Batch measurements using [scikit-image]'s [regionprops]. This can measure features of a label such as area, eccentricity, and more but also can measure various intensity metrics. Attempts to support post-processing of measurements, grouping, and more to make downstream analyses easier for users. Will be updated in the future to include [nyxus].

### A Note about bioio/AICSImageIO

[AICSImageIO] is a convenient, multi-format file reader which also has the complimentary [napari-aicsimageio] reader plugin. However, the codebase is currently being switched over to [bioio] as the package matures; bioio is a replacement for AICSImageIO and will have less issues with compatibilities.

By default, napari-aicsimageio installs all reader dependencies. Because napari-aicsimageio is not technically required for this plugin to work (you could build your own metadata for the annotation-saver) and just napari is required, the former is not an install requirement. This is to avoid using the GPL licence and to stick with BSD-3. However, you should install napari-aicsimageio if you want the smoothest operation of the widgets.

[napari-workflows]: https://github.com/haesleinhuepf/napari-workflows
[apoc]: https://github.com/haesleinhuepf/apoc
[napari-apoc]: https://github.com/haesleinhuepf/napari-accelerated-pixel-and-object-classification
[napari-aicsimageio]: https://github.com/AllenCellModeling/napari-aicsimageio
[napari-bioio]: https://github.com/TimMonko/napari-bioio
[bioio]: https://github.com/bioio-devs/bioio
[AICSImageIO]: https://allencellmodeling.github.io/aicsimageio/
[scikit-image]: https://scikit-image.org/
[regionprops]: https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops
[nyxus]: https://github.com/PolusAI/nyxus
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pip install napari-ndev
pip install napari-ndev[extras]
```

**napari-ndev** can optionally use GPL-3 licensed libraries to enhance its functionality, but are not required. If you choose to install and use these optional dependencies, you must comply with the GPL-3 license terms. The main functional improvement is from `napari-aicsimageio` to properly handle metadata with the `Image Utilities` widget. These libraries can be installed with [pip]:
**napari-ndev** can optionally use GPL-3 licensed libraries to enhance its functionality, but are not required. If you choose to install and use these optional dependencies, you must comply with the GPL-3 license terms. The main functional improvement is from `napari-bioio` to properly handle metadata with the `Image Utilities` widget. These libraries can be installed with [pip]:

```bash
pip install napari-ndev[gpl-extras]
Expand Down
14 changes: 7 additions & 7 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@ classifiers =
[options]
packages = find:
install_requires =
numpy >= 1.26 # required for python 3.12 to build
siphash24 >= 1.6
numpy >= 1.26, < 2.0 # for python 3.12 compatibility
siphash24 >= 1.6 # to prevent fallback to python's hash function
magicgui >= 0.8.3
qtpy
aicsimageio
napari[all] >= 0.4.19
magic-class
napari[all] >= 0.4.19 # for proper interaction with scaled images
apoc
pyclesperanto-prototype
dask
Expand Down Expand Up @@ -80,6 +79,7 @@ testing =
napari
pyqt5
napari-segment-blobs-and-things-with-membranes
napari-bioio @ git+https://github.com/TimMonko/napari-bioio.git@main#egg=napari-bioio

extras =
bioio-nd2
Expand All @@ -88,9 +88,9 @@ extras =
napari-simpleitk-image-processing

gpl_extras =
napari-aicsimageio
bioio-czi
bioio-czi >= 1.0.1
bioio-lif
napari-bioio @ git+https://github.com/TimMonko/napari-bioio.git@main#egg=napari-bioio

docs =
mkdocs
Expand Down
5 changes: 2 additions & 3 deletions src/napari_ndev/_tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import numpy as np
import pytest
from aicsimageio import AICSImage
from bioio import BioImage
from bioio.writers import OmeTiffWriter

Expand Down Expand Up @@ -123,7 +122,7 @@ def test_get_channel_names_CYX():

def test_get_channel_names_RGB():
file = Path(r'./src/napari_ndev/_tests/resources/RGB.tiff')
img = AICSImage(file)
img = BioImage(file)
assert get_channel_names(img) == ['red', 'green', 'blue']


Expand Down Expand Up @@ -165,7 +164,7 @@ def test_get_squeezed_dim_order_ZYX():

def test_get_squeezed_dim_order_RGB():
file = Path(r'./src/napari_ndev/_tests/resources/RGB.tiff')
img = AICSImage(file)
img = BioImage(file)
assert get_squeezed_dim_order(img) == 'YX'


Expand Down
6 changes: 3 additions & 3 deletions src/napari_ndev/_tests/widgets/test_apoc_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@ def test_update_metadata_from_file():
['/path/to/file.tif'],
)

# Mock the AICSImage class to return sample channel names
with patch('aicsimageio.AICSImage') as mock_AICSImage:
mock_AICSImage.return_value.channel_names = ['C0', 'C1', 'C2']
# Mock the BioImage class to return sample channel names
with patch('bioio.BioImage') as BioImage:
BioImage.return_value.channel_names = ['C0', 'C1', 'C2']

# Call the _update_metadata_from_file method
wdg._update_metadata_from_file()
Expand Down
30 changes: 14 additions & 16 deletions src/napari_ndev/_tests/widgets/test_utilities_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import numpy as np
import pytest
from aicsimageio import AICSImage
from bioio import BioImage

from napari_ndev.widgets._utilities_container import UtilitiesContainer

Expand Down Expand Up @@ -70,7 +70,7 @@ def test_save_shapes_as_labels(
assert expected_save_loc.exists()
assert shapes_as_labels.shape == test_image.shape
assert np.array_equal(shapes_as_labels, test_labels)
assert AICSImage(expected_save_loc).channel_names == ['Shapes']
assert BioImage(expected_save_loc).channel_names == ['Shapes']


def test_save_labels(make_napari_viewer, tmp_path: Path, test_data):
Expand All @@ -92,7 +92,7 @@ def test_save_labels(make_napari_viewer, tmp_path: Path, test_data):
expected_save_loc = tmp_path / 'Labels' / 'test.tiff'
assert expected_save_loc.exists()
assert np.array_equal(labels, test_labels)
assert AICSImage(expected_save_loc).channel_names == ['Labels']
assert BioImage(expected_save_loc).channel_names == ['Labels']


def test_save_ome_tiff(make_napari_viewer, test_data, tmp_path: Path):
Expand Down Expand Up @@ -120,7 +120,7 @@ def test_rgb_image():
path = os.path.join(
'src', 'napari_ndev', '_tests', 'resources', 'RGB.tiff'
)
img = AICSImage(path)
img = BioImage(path)
return path, img


Expand Down Expand Up @@ -149,20 +149,18 @@ def test_update_metadata_from_layer(make_napari_viewer, test_data):

assert (
'Tried to update metadata, but could only update scale'
' because layer not opened with aicsimageio'
' because layer not opened with napari-bioio'
) in container._results.value
assert container._scale_tuple.value == (1, 2, 3)

def test_open_images(make_napari_viewer, test_rgb_image):
viewer = make_napari_viewer()
container = UtilitiesContainer(viewer)

# failing tox because no napari-aicsimageio in requirements
# def test_open_images(make_napari_viewer, test_rgb_image):
# viewer = make_napari_viewer()
# container = UtilitiesContainer(viewer)

# path, _ = test_rgb_image
# container._files.value = path
# container.open_images()
path, _ = test_rgb_image
container._files.value = path
container.open_images()

# assert container._img.dims.order == "TCZYXS"
# assert container._squeezed_dims == "YX"
# assert container._channel_names.value == "['red', 'green', 'blue']"
assert container._img.dims.order == "TCZYXS"
assert container._squeezed_dims == "YX"
assert container._channel_names.value == "['red', 'green', 'blue']"
42 changes: 17 additions & 25 deletions src/napari_ndev/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
Functions
---------
get_directory_and_files : Get the directory and files in the specified directory.
get_channel_names : Get the channel names from an AICSImage or BioImage object.
get_squeezed_dim_order : Return a string containing the squeezed dimensions of the given AICSImage or BioImage object.
get_channel_names : Get the channel names from an BioImage object.
get_squeezed_dim_order : Return a string containing the squeezed dimensions of the given BioImage object.
create_id_string : Create an ID string for the given image.
check_for_missing_files : Check if the given files are missing in the specified directories.
setup_logger : Set up a logger with the specified log location.
Expand All @@ -19,7 +19,6 @@
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
from aicsimageio import AICSImage
from bioio import BioImage

__all__ = [
Expand All @@ -32,12 +31,11 @@
'setup_logger',
]

def get_Image(file: str | Path) -> AICSImage | BioImage:
def get_Image(file: str | Path) -> BioImage:
"""
Read the image file with BioImage or AICSImage.
Read the image file with BioImage.
Open the image file with BioImage, or if the file is not supported,
open it with AICSImage.
Open the image file with BioImage.
Parameters
----------
Expand All @@ -46,19 +44,13 @@ def get_Image(file: str | Path) -> AICSImage | BioImage:
Returns
-------
AICSImage or BioImage
BioImage
The image object.
"""
from bioio import BioImage
from bioio_base.exceptions import UnsupportedFileFormatError

try:
img = BioImage(file)
except UnsupportedFileFormatError:
from aicsimageio import AICSImage
img = AICSImage(file)
return img
return BioImage(file)


def get_directory_and_files(
Expand Down Expand Up @@ -122,18 +114,18 @@ def get_directory_and_files(
return directory, files


def get_channel_names(img: AICSImage | BioImage) -> list[str]:
def get_channel_names(img: BioImage) -> list[str]:
"""
Get the channel names from an AICSImage object.
Get the channel names from a BioImage object.
If the image has a dimension order that includes "S" (it is RGB),
return the default channel names ["red", "green", "blue"].
Otherwise, return the channel names from the image.
Parameters
----------
img : AICSImage or BioImage
The AICSImage object.
img : BioImage
The BioImage object.
Returns
-------
Expand All @@ -147,16 +139,16 @@ def get_channel_names(img: AICSImage | BioImage) -> list[str]:


def get_squeezed_dim_order(
img: AICSImage | BioImage,
img: BioImage,
skip_dims: list[str] | str | None = None,
) -> str:
"""
Return a string containing the squeezed dimensions of the given AICSImage object.
Return a string containing the squeezed dimensions of the given BioImage.
Parameters
----------
img : AICSImage or BioImage
The AICSImage object.
img : BioImage
The BioImage object.
skip_dims : list of str or str or None, optional
Dimensions to skip. Defaults to ["C", "S"].
Expand All @@ -173,13 +165,13 @@ def get_squeezed_dim_order(
)


def create_id_string(img: BioImage | AICSImage, identifier: str) -> str:
def create_id_string(img: BioImage, identifier: str) -> str:
"""
Create an ID string for the given image.
Parameters
----------
img : BioImage or AICSImage
img : BioImage
The image object.
identifier : str
The identifier string.
Expand Down
Loading

0 comments on commit 8475511

Please sign in to comment.