Source code for src.nviz.view
"""
Utilities for viewing n-dimensional data
"""
import logging
from typing import Optional
import napari
import tifffile as tiff
import xmltodict
import zarr
logger = logging.getLogger(__name__)
[docs]
def view_zarr_with_napari(
zarr_dir: str, scaling_values: tuple, headless: bool = False
) -> Optional[napari.Viewer]:
"""
View a Zarr file created with nviz through napari.
Args:
zarr_dir (str):
The path to the Zarr file.
scaling_values (tuple):
The scaling values for the image.
headless (bool):
Whether to run in headless mode
(where we don't run napari and hand
back the viewer object instead).
Returns:
Optional[napari.Viewer]]:
The napari viewer object if not headless,
otherwise None.
"""
# Check Zarr file structure
frame_zarr = zarr.open(zarr_dir, mode="r")
# Visualize with napari, start in 3d mode
viewer = napari.Viewer(ndisplay=3)
# Iterate through each channel in the Zarr file
for channel_name in sorted(frame_zarr["images"].keys(), reverse=True):
viewer.add_image(
frame_zarr["images"][channel_name]["0"][:],
name=channel_name,
scale=scaling_values,
)
# Iterate through each compartment in the Zarr file and add labels to Napari
if "labels" in frame_zarr:
for label_name in sorted(frame_zarr["labels"].keys(), reverse=True):
viewer.add_labels(
frame_zarr["labels"][label_name]["0"][:],
name=f"{label_name} (label)",
scale=scaling_values,
)
if not headless:
# Start the Napari event loop
napari.run()
else:
logger.warning(
"Running view in headless mode and returning a napari viewer object."
)
# otherwise return the viewer
return viewer
[docs]
def view_ometiff_with_napari(
ometiff_path: str, scaling_values: tuple, headless: bool = False
) -> Optional[napari.Viewer]:
"""
View a OME-TIFF file created with nviz through napari.
Args:
ometiff_path (str):
The path to the OME-TIFF file.
scaling_values (tuple):
The scaling values for the image.
headless (bool):
Whether to run in headless mode
(where we don't run napari and hand
back the viewer object instead).
Returns:
Optional[napari.Viewer]]:
The napari viewer object if not headless,
otherwise None.
"""
# Visualize with napari, start in 3d mode
viewer = napari.Viewer(ndisplay=3)
# Read and add layers from the combined OME-TIFF file
with tiff.TiffFile(ometiff_path) as tif:
combined_data = tif.asarray()
metadata = xmltodict.parse(tif.ome_metadata)
channel_names = [
channel["@Name"]
for channel in metadata["OME"]["Image"]["Pixels"]["Channel"]
]
# First, add image layers
for i, (channel_data, channel_name) in enumerate(
zip(combined_data, channel_names)
):
if "(labels)" not in channel_name:
viewer.add_image(
channel_data,
name=channel_name,
scale=scaling_values,
)
# Then, add label layers
for i, (channel_data, channel_name) in enumerate(
zip(combined_data, channel_names)
):
if "(labels)" in channel_name:
viewer.add_labels(
channel_data,
name=channel_name,
scale=scaling_values,
)
if not headless:
# Start the Napari event loop
napari.run()
else:
logger.warning(
"Running view in headless mode and returning a napari viewer object."
)
# otherwise return the viewer
return viewer