Skip to content

Commit

Permalink
Only rescale points for older napari versions (#33)
Browse files Browse the repository at this point in the history
napari v0.5 includes a fix to handle expected combinations of point size
and layer scale. Previously, we worked around that issue by rescaling
the point sizes ourselves. After this PR, we only do that for older
versions of napari. The check is cached to avoid spamming the logs.

Alternatively, we could require `napari>=0.5` in `setup.cfg`. I decided
to support both versions for now, since v0.5 is quite new and comes with
a few of its own new bugs.

This was tested manually by installing v0.4.19 and v0.5.2 of napari and
visually inspecting the resulting point sizes.
  • Loading branch information
andy-sweet authored Sep 4, 2024
1 parent 5cdf633 commit e397320
Showing 1 changed file with 45 additions and 8 deletions.
53 changes: 45 additions & 8 deletions src/napari_cryoet_data_portal/_open_widget.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from dataclasses import dataclass
from functools import lru_cache
from typing import TYPE_CHECKING, Generator, Optional, Tuple

import numpy as np
from cryoet_data_portal import Annotation, Client, Tomogram
from npe2.types import FullLayerData
from qtpy.QtCore import Qt
from qtpy.QtWidgets import (
Expand All @@ -14,7 +16,6 @@
QVBoxLayout,
QWidget,
)
from cryoet_data_portal import Annotation, Client, Tomogram

from napari_cryoet_data_portal._logging import logger
from napari_cryoet_data_portal._progress_widget import ProgressWidget
Expand Down Expand Up @@ -139,8 +140,11 @@ def _loadTomogram(
# A single client is not thread safe, so we need a new instance for each query.
client = Client(self._uri)
annotations = Annotation.find(
client,
[Annotation.tomogram_voxel_spacing_id == tomogram.tomogram_voxel_spacing_id],
client,
[
Annotation.tomogram_voxel_spacing_id
== tomogram.tomogram_voxel_spacing_id
],
)

for annotation in annotations:
Expand All @@ -164,7 +168,9 @@ def _onLayerLoaded(self, layer_data: FullLayerData) -> None:
raise AssertionError(f"Unexpected {layer_type=}")


def _handle_image_at_resolution(layer_data: FullLayerData, resolution: Resolution) -> FullLayerData:
def _handle_image_at_resolution(
layer_data: FullLayerData, resolution: Resolution
) -> FullLayerData:
data, attrs, layer_type = layer_data
# Skip indexing for multi-resolution to avoid adding any
# unnecessary nodes to the dask compute graph.
Expand All @@ -191,11 +197,42 @@ def _handle_image_at_resolution(layer_data: FullLayerData, resolution: Resolutio
return data, attrs, layer_type


def _handle_points_at_scale(layer_data: FullLayerData, image_scale: Tuple[float, float, float]) -> FullLayerData:
def _handle_points_at_scale(
layer_data: FullLayerData, image_scale: Tuple[float, float, float]
) -> FullLayerData:
data, attrs, layer_type = layer_data
# Inherit scale from full resolution image, so that points are visually
# aligned with the image.
attrs["scale"] = image_scale
# Scaling points also changes the size, so adjust accordingly.
attrs["size"] /= np.mean(image_scale)
return data, attrs, layer_type
# Scaling points also changes the size in some version of napari, so adjust accordingly.
if _is_napari_version_less_than("0.5"):
attrs["size"] /= np.mean(image_scale)
return data, attrs, layer_type


@lru_cache(maxsize=None)
def _is_napari_version_less_than(version: str) -> bool:
try:
import napari
except ImportError:
logger.warn("Failed to import napari")
return False
try:
from packaging.version import InvalidVersion, Version
except ImportError:
logger.warn("Failed to import packaging")
return False
try:
actual_version = Version(napari.__version__)
except InvalidVersion:
logger.warn(
"Failed to parse actual napari version from %s ",
napari.__version__,
)
return False
try:
target_version = Version(version)
except InvalidVersion:
logger.warn("Failed to parse target napari version from %s", version)
return False
return actual_version < target_version

0 comments on commit e397320

Please sign in to comment.