Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bacc0e2
adding scripts
MikeLippincott Feb 20, 2025
58aaf4d
Update `labels_dir` parameter to include default (#19)
jenna-tomkinson Feb 14, 2025
43cec57
Add Synapse download enhancement to test real data (#33)
d33bs Apr 10, 2025
7501e0b
Enable downstream GitHub Actions runs to check out properly (#35)
d33bs Apr 25, 2025
301afcd
Add `nviz` CLI (#36)
d33bs Apr 28, 2025
df85609
Bump astral-sh/setup-uv from 5 to 6 (#39)
dependabot[bot] Apr 29, 2025
1bde834
Bump pyvista/setup-headless-display-action from 3 to 4 (#38)
dependabot[bot] Apr 29, 2025
2920812
Move to `macos-14` for pre-commit checks within GH Actions (#40)
d33bs May 2, 2025
8c55e77
Add `path_report` capability to help observe file and directory chall…
d33bs May 20, 2025
b2580dc
Update numpy requirement from <2.3 to <2.4 (#46)
dependabot[bot] Jun 24, 2025
0b22013
Fix Linux CI (#50)
d33bs Jul 31, 2025
55cb0d5
Fix docs builds with linux headless config (#41)
d33bs Aug 4, 2025
ad4a6a3
Add software DOI for reference (#48)
d33bs Aug 4, 2025
52e4623
Bump pyvista/setup-headless-display-action from 3 to 4 (#52)
dependabot[bot] Aug 5, 2025
cc1c404
Bump astral-sh/setup-uv from 5 to 6 (#53)
dependabot[bot] Aug 5, 2025
8aff886
Update pre-commit-lite conditions (#44)
d33bs Aug 6, 2025
5fe8b57
Update GH Actions ubuntu (#43)
d33bs Aug 6, 2025
7cc044c
Bump actions/checkout from 4 to 5 (#54)
dependabot[bot] Aug 12, 2025
c1b7452
Update dependabot to group Python updates together (#25)
d33bs Aug 18, 2025
1c10aab
Add Almanack to pre-commit checks (#47)
d33bs Aug 18, 2025
2ebb137
remove git remote newline and avoid lint (#56)
d33bs Sep 13, 2025
14392cd
Merge remote-tracking branch 'upstream/main'
MikeLippincott Sep 29, 2025
7991f02
applying fix
MikeLippincott Sep 29, 2025
a2e7788
redo the uv lock
MikeLippincott Sep 30, 2025
6793099
Update tests/test_image.py
MikeLippincott Nov 4, 2025
5ce1a86
Update src/nviz/image.py
MikeLippincott Nov 4, 2025
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
37 changes: 36 additions & 1 deletion src/nviz/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,44 @@
from typing import Dict, List, Optional, Tuple, Union

import numpy as np
import skimage
import tifffile as tiff
import zarr
from ome_zarr.io import parse_url as zarr_parse_url
from ome_zarr.writer import write_image as zarr_write_image

from .image_meta import extract_z_slice_number_from_filename, generate_ome_xml

def read_zstack_image(tiff_file_path):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding tests for this new function which otherwise is only implicitly checked.

"""
Read a z-stack image from a TIFF file and ensure it is in uint16 format.

Parameters
----------
tiff_file_path : str
Path to the TIFF file.

Returns
-------
np.ndarray
The processed z-stack image.
"""
img = tiff.imread(tiff_file_path)

if len(img.shape) > 5:
# determine if any of the dimensions is size of 1?
img = np.squeeze(img)

if img.dtype != np.uint16:
if img.dtype in [np.float32, np.float64]:
# For float images, first rescale to 0-1 range, then convert
img = skimage.exposure.rescale_intensity(img, out_range=(0, 1))
img = skimage.img_as_uint(img)
else:
# For other integer types
img = skimage.img_as_uint(img)

return img.astype(np.uint16)

def image_set_to_arrays(
image_dir: str,
Expand Down Expand Up @@ -55,7 +86,7 @@ def image_set_to_arrays(
"images": {
channel_map.get(filename_code, filename_code): np.stack(
[
tiff.imread(tiff_file.path).astype(np.uint16)
read_zstack_image(tiff_file.path).astype(np.uint16)
for tiff_file in sorted(
files,
key=lambda x: extract_z_slice_number_from_filename(x.name),
Expand Down Expand Up @@ -286,12 +317,16 @@ def tiff_to_ometiff( # noqa: PLR0913

# Collect image data
for channel, stack in frame_zstacks["images"].items():
dim = len(stack.shape)
images_data.append(stack)
channel_names.append(channel)

# Collect label data
if label_dir:
for compartment_name, stack in frame_zstacks["labels"].items():
if len(stack.shape) != dim:
if len(stack.shape) == 3:
stack = np.expand_dims(stack, axis=0)
labels_data.append(stack)
label_names.append(compartment_name)

Expand Down
2 changes: 1 addition & 1 deletion src/nviz/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def view_ometiff_with_napari(

if not headless:
# Start the Napari event loop
napari.run()
napari.run(force=True)
else:
logger.warning(
"Running view in headless mode and returning a napari viewer object."
Expand Down
3 changes: 3 additions & 0 deletions tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ def test_tiff_to_ometiff(
metadata = tif.ome_metadata
assert metadata is not None

assert tif.shape > 3 # Ensure there are multiple dimensions
assert tif.shape == 4 # includes channel names :)

# Parse the OME-XML metadata
root = ET.fromstring(metadata)
channels = root.find(
Expand Down
Loading
Loading