Skip to content
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,8 @@ venv/
# pixi environments
.pixi/*
!.pixi/config.toml

# ndevio sampledata that is hosted on Zenodo
src/ndevio/sampledata/data/neocortex-3Ch.tiff
src/ndevio/sampledata/data/scratch-assay-labeled-10T-2Ch.tiff
src/ndevio/sampledata/data/neuron-4Ch_raw.tiff
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ dependencies = [
"bioio-imageio",
"zarr>=3.1.3", # tifffile's ZarrTiffStore needs set_partial_values/supports_partial_writes
"napari-plugin-manager>=0.1.7", # Renamed to PYPI from PIP for tool selection https://github.com/napari/napari-plugin-manager/pull/176
"pooch", # for downloading sample data from remote URLs
]

[project.optional-dependencies]
Expand Down Expand Up @@ -87,6 +88,9 @@ xfail_strict = true
# filterwarnings = ["error"] # recommended by PP309
log_cli_level = "INFO"
testpaths = ["tests"]
markers = [
"network: marks tests as requiring network access (deselect with '-m \"not network\"')",
]

[tool.coverage]
report.fail_under = 80
Expand Down
39 changes: 38 additions & 1 deletion src/ndevio/napari.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ display_name: ndevio
# use 'hidden' to remove plugin from napari hub search results
visibility: public
# see https://napari.org/stable/plugins/technical_references/manifest.html#fields for valid categories
# categories: []
categories: ["IO", "Dataset", "Utilities"]
contributions:
commands:
- id: ndevio.get_reader
Expand All @@ -15,6 +15,24 @@ contributions:
- id: ndevio.make_utilities_widget
python_name: ndevio.widgets:UtilitiesContainer
title: I/O Utilities
- id: ndevio.make_ndev_logo
python_name: ndevio.sampledata:ndev_logo
title: Load ndev logo
- id: ndevio.make_scratch_assay
python_name: ndevio.sampledata:scratch_assay
title: Load scratch assay data
- id: ndevio.make_neocortex
python_name: ndevio.sampledata:neocortex
title: Load neocortex data
- id: ndevio.make_neuron_raw
python_name: ndevio.sampledata:neuron_raw
title: Load raw neuron data
- id: ndevio.make_neuron_labels
python_name: ndevio.sampledata:neuron_labels
title: Load neuron labels data
- id: ndevio.make_neuron_labels_processed
python_name: ndevio.sampledata:neuron_labels_processed
title: Load processed neuron labels data
readers:
- command: ndevio.get_reader
accepts_directories: false
Expand Down Expand Up @@ -58,3 +76,22 @@ contributions:
display_name: Install BioIO Reader Plugins
- command: ndevio.make_utilities_widget
display_name: I/O Utilities
sample_data:
- command: ndevio.make_ndev_logo
display_name: ndev logo
key: ndevio.ndev_logo
- command: ndevio.make_scratch_assay
display_name: Scratch Assay Labeled (10T+2Ch) (4MB)
key: ndevio.scratch_assay
- command: ndevio.make_neocortex
display_name: Neocortex (3Ch) (2MB)
key: ndevio.neocortex
- command: ndevio.make_neuron_raw
display_name: Neuron Raw (2D+4Ch) (32MB)
key: ndevio.neuron_raw
- command: ndevio.make_neuron_labels
display_name: Neuron Labels (2D+4Ch)
key: ndevio.neuron_labels
- command: ndevio.make_neuron_labels_processed
display_name: Neuron Labels Processed (2D+4Ch)
key: ndevio.neuron_labels_processed
4 changes: 3 additions & 1 deletion src/ndevio/nimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,9 @@ def _build_single_layer_tuple(
channel_idx, n_channels
)
meta["blending"] = (
"additive" if n_channels > 1 else "translucent_no_depth"
"additive"
if channel_idx > 0 and n_channels > 1
else "translucent_no_depth"
)

# Apply per-channel overrides
Expand Down
19 changes: 19 additions & 0 deletions src/ndevio/sampledata/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Sample data for ndevio and the ndev-kit ecosystem."""

from ndevio.sampledata._sample_data import (
ndev_logo,
neocortex,
neuron_labels,
neuron_labels_processed,
neuron_raw,
scratch_assay,
)

__all__ = [
"ndev_logo",
"neocortex",
"neuron_labels",
"neuron_labels_processed",
"neuron_raw",
"scratch_assay",
]
116 changes: 116 additions & 0 deletions src/ndevio/sampledata/_sample_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""
Sample data providers for napari.

This module implements the "sample data" specification.
see: https://napari.org/stable/plugins/building_a_plugin/guides.html#sample-data
"""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

import pooch
from bioio_imageio import Reader as ImageIOReader
from bioio_ome_tiff import Reader as OmeTiffReader

from ndevio import nImage

if TYPE_CHECKING:
from napari.types import LayerDataTuple

SAMPLE_DIR = Path(__file__).parent / "data"


def ndev_logo() -> list[LayerDataTuple]:
"""Load the ndev logo image."""
return nImage(
SAMPLE_DIR / "ndev-logo.png",
reader=ImageIOReader,
).get_layer_data_tuples()


def scratch_assay() -> list[LayerDataTuple]:
"""Load scratch assay data with labeled nuclei and cytoplasm."""
scratch_assay_raw_path = pooch.retrieve(
url="doi:10.5281/zenodo.17845346/scratch-assay-labeled-10T-2Ch.tiff",
known_hash="md5:2b98c4ea18cd741a1545e59855348a2f",
fname="scratch-assay-labeled-10T-2Ch.tiff",
path=SAMPLE_DIR,
)
img = nImage(
scratch_assay_raw_path,
reader=OmeTiffReader,
)
return img.get_layer_data_tuples(
in_memory=True,
channel_types={
"H3342": "image",
"oblique": "image",
"nuclei": "labels",
"cyto": "labels",
},
channel_kwargs={
"H3342": {"colormap": "cyan"},
"oblique": {"colormap": "gray"},
},
)


def neocortex() -> list[LayerDataTuple]:
"""Load neocortex 3-channel image data."""
neocortex_raw_path = pooch.retrieve(
url="doi:10.5281/zenodo.17845346/neocortex-3Ch.tiff",
known_hash="md5:eadc3fac751052461fb2e5f3c6716afa",
fname="neocortex-3Ch.tiff",
path=SAMPLE_DIR,
)
return nImage(
neocortex_raw_path,
reader=OmeTiffReader,
).get_layer_data_tuples(in_memory=True)


def neuron_raw() -> list[LayerDataTuple]:
"""Load raw neuron 4-channel image data.

This sample is downloaded from Zenodo if not present locally.
"""
neuron_raw_path = pooch.retrieve(
url="doi:10.5281/zenodo.17845346/neuron-4Ch_raw.tiff",
known_hash="md5:5d3e42bca2085e8588b6f23cf89ba87c",
fname="neuron-4Ch_raw.tiff",
path=SAMPLE_DIR,
)
return nImage(
neuron_raw_path,
reader=OmeTiffReader,
).get_layer_data_tuples(
in_memory=True,
layer_type="image",
channel_kwargs={
"PHALL": {"colormap": "gray"},
},
)


def neuron_labels() -> list[LayerDataTuple]:
"""Load neuron labels data."""
return nImage(
SAMPLE_DIR / "neuron-4Ch_labels.tiff",
reader=OmeTiffReader,
).get_layer_data_tuples(
in_memory=True,
layer_type="labels",
)


def neuron_labels_processed() -> list[LayerDataTuple]:
"""Load processed neuron labels data."""
return nImage(
SAMPLE_DIR / "neuron-4Ch_labels_processed.tiff",
reader=OmeTiffReader,
).get_layer_data_tuples(
in_memory=True,
layer_type="labels",
)
Binary file added src/ndevio/sampledata/data/ndev-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/ndevio/sampledata/data/neuron-4Ch_labels.tiff
Binary file not shown.
Binary file not shown.
28 changes: 14 additions & 14 deletions src/ndevio/widgets/_utilities_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def _on_batch_complete(self):
self._set_batch_button_state(running=False)
self._results.value = (
"Batch concatenated files in directory."
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)

def _on_batch_error(self, ctx, exception):
Expand Down Expand Up @@ -702,7 +702,7 @@ def update_metadata_from_layer(self):
except AttributeError:
self._results.value = (
"Tried to update metadata, but no layer selected."
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)
except KeyError:
scale = selected_layer.scale
Expand All @@ -714,7 +714,7 @@ def update_metadata_from_layer(self):
self._results.value = (
"Tried to update metadata, but could only update scale"
" because layer not opened with ndevio reader."
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)

def open_images(self):
Expand Down Expand Up @@ -855,7 +855,7 @@ def _on_concat_complete(self, save_path: Path) -> None:
self._progress_bar.value = 1
self._results.value = (
f"Saved Concatenated Image: {save_path.name}"
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)

def _on_concat_error(self, exception: Exception) -> None:
Expand All @@ -865,7 +865,7 @@ def _on_concat_error(self, exception: Exception) -> None:
self._progress_bar.value = 0
self._results.value = (
f"Error concatenating files: {exception}"
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)

def _build_file_sets(self) -> list[tuple[list[Path], str]]:
Expand Down Expand Up @@ -899,7 +899,7 @@ def batch_concatenate_files(self) -> None:

if not file_sets:
self._results.value = (
f'No complete file sets found.\nAt {time.strftime("%H:%M:%S")}'
f"No complete file sets found.\nAt {time.strftime('%H:%M:%S')}"
)
return

Expand Down Expand Up @@ -974,15 +974,15 @@ def _on_scene_extracted(self, result: tuple[int, str]) -> None:
self._progress_bar.value = self._progress_bar.value + 1
self._results.value = (
f"Extracted scene {scene_idx}: {scene_name}"
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)

def _on_scenes_complete(self, scenes_list: list, _=None) -> None:
"""Handle completion of all scene extractions."""
self._progress_bar.label = ""
self._results.value = (
f"Saved extracted scenes: {scenes_list}"
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)

def _on_scene_error(self, exc: Exception) -> None:
Expand All @@ -991,7 +991,7 @@ def _on_scene_error(self, exc: Exception) -> None:
self._progress_bar.max = 1
self._progress_bar.value = 0
self._results.value = (
f'Error extracting scenes: {exc}\nAt {time.strftime("%H:%M:%S")}'
f"Error extracting scenes: {exc}\nAt {time.strftime('%H:%M:%S')}"
)

def canvas_export_figure(self) -> None:
Expand All @@ -1000,7 +1000,7 @@ def canvas_export_figure(self) -> None:
self._results.value = (
"Exporting Figure only works in 2D mode."
"\nUse Screenshot for 3D figures."
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)
return

Expand All @@ -1022,7 +1022,7 @@ def canvas_export_figure(self) -> None:
f"Exported canvas figure to Figures directory."
f"\nSaved as {save_name}"
f"\nWith scale factor of {scale}"
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)
return

Expand Down Expand Up @@ -1051,7 +1051,7 @@ def canvas_screenshot(self) -> None:
f"\nSaved as {save_name}"
f"\nWith canvas dimensions of {canvas_size}"
f"\nWith scale factor of {scale}"
f'\nAt {time.strftime("%H:%M:%S")}'
f"\nAt {time.strftime('%H:%M:%S')}"
)
return

Expand Down Expand Up @@ -1118,7 +1118,7 @@ def _on_layer_save_complete(self, result: None = None) -> None:
self._results.value = (
f"Saved {self._layer_save_type}: "
+ str(self._save_name.value)
+ f'\nAt {time.strftime("%H:%M:%S")}'
+ f"\nAt {time.strftime('%H:%M:%S')}"
)

def _on_layer_save_error(self, exc: Exception) -> None:
Expand All @@ -1127,5 +1127,5 @@ def _on_layer_save_error(self, exc: Exception) -> None:
self._progress_bar.max = 1
self._progress_bar.value = 0
self._results.value = (
f'Error saving layers: {exc}\nAt {time.strftime("%H:%M:%S")}'
f"Error saving layers: {exc}\nAt {time.strftime('%H:%M:%S')}"
)
Loading