Skip to content

Commit

Permalink
Reapply GS-specific modifications
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidStirling committed Oct 11, 2024
1 parent 5d96dc5 commit fefde86
Show file tree
Hide file tree
Showing 13 changed files with 452 additions and 16 deletions.
3 changes: 2 additions & 1 deletion cellprofiler_core/analysis/_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,8 @@ def start_workers(cls, num=None):
# closed, the subprocess exits.
if hasattr(sys, "frozen"):
if sys.platform == "darwin":
executable = os.path.join(os.path.dirname(sys.executable), "cp")
executable = os.path.join(os.path.dirname(sys.executable),
"cellprofilerapp")
args = [executable] + aw_args
elif sys.platform.startswith("linux"):
aw_path = os.path.join(os.path.dirname(__file__), "__init__.py")
Expand Down
2 changes: 1 addition & 1 deletion cellprofiler_core/constants/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@
SUB_ALL = "All"
SUB_SOME = "Some"
FILE_SCHEME = "file:"
PASSTHROUGH_SCHEMES = ("http", "https", "ftp", "omero", "s3")
PASSTHROUGH_SCHEMES = ("http", "https", "ftp", "omero", "s3", "omero-3d")
80 changes: 78 additions & 2 deletions cellprofiler_core/image/abstract_image/file/_file_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,23 @@
import numpy
import skimage.io

import requests
from PIL import Image as PilImage
from io import BytesIO
from posixpath import join as urljoin

import cellprofiler_core.preferences
from .._abstract_image import AbstractImage
from ..._image import Image
from ....utilities.image import is_numpy_file
from ....utilities.image import is_matlab_file
from ....utilities.image import is_omero3d_path
from ....utilities.image import loadmat
from ....utilities.image import load_data_file
from ....utilities.image import generate_presigned_url
from ....constants.image import FILE_SCHEME, PASSTHROUGH_SCHEMES
from ....utilities.pathname import pathname2url, url2pathname
from ....utilities.zarr import get_zarr_reader


class FileImage(AbstractImage):
Expand All @@ -35,6 +42,8 @@ def __init__(
channel=None,
volume=False,
spacing=None,
z=None,
t=None,
):
"""
:param name: Name of image to be provided
Expand Down Expand Up @@ -84,6 +93,8 @@ def __init__(
self.__index = index
self.__volume = volume
self.__spacing = spacing
self.z_index = z if z is not None else 0
self.t_index = t if t is not None else 0
self.scale = None

@property
Expand Down Expand Up @@ -176,6 +187,8 @@ def cache_file(self):
)
finally:
os.close(tempfd)
elif url.lower().endswith('.zarr'):
self.__cached_file = url
else:
from bioformats.formatreader import get_image_reader

Expand All @@ -185,6 +198,8 @@ def cache_file(self):
return True

def get_full_name(self):
if is_omero3d_path(self.__url):
return self.get_url()
self.cache_file()
if self.__is_cached:
return self.__cached_file
Expand All @@ -203,8 +218,12 @@ def get_md5_hash(self, measurements):
#
# Cache the MD5 hash on the image reader
#
if is_matlab_file(self.__filename) or is_numpy_file(self.__filename):
if (is_matlab_file(self.__filename) or
is_numpy_file(self.__filename) or
is_omero3d_path(self.get_url())):
rdr = None
elif self.get_url().endswith('.zarr'):
rdr = get_zarr_reader(None, url=self.get_url())
else:
from bioformats.formatreader import get_image_reader

Expand Down Expand Up @@ -273,6 +292,8 @@ def __set_image(self):
url = self.get_url()
if url.lower().startswith("omero:"):
rdr = get_image_reader(self.get_name(), url=url)
elif url.lower().endswith('.zarr'):
rdr = get_zarr_reader(self.get_name(), url=url)
else:
rdr = get_image_reader(self.get_name(), url=self.get_url())
if numpy.isscalar(self.index) or self.index is None:
Expand All @@ -283,6 +304,8 @@ def __set_image(self):
rescale=self.rescale if isinstance(self.rescale, bool) else False,
wants_max_intensity=True,
channel_names=channel_names,
z=self.z_index,
t=self.t_index,
)
else:
# It's a stack
Expand All @@ -305,6 +328,8 @@ def __set_image(self):
rescale=self.rescale if isinstance(self.rescale, bool) else False,
wants_max_intensity=True,
channel_names=channel_names,
z=self.z_index,
t=self.t_index,
)
stack.append(img)
img = numpy.dstack(stack)
Expand All @@ -330,10 +355,61 @@ def provide_image(self, image_set):

def __set_image_volume(self):
pathname = url2pathname(self.get_url())

print("Using pathname: {} for url {}".format(pathname, self.get_url()))
# Volume loading is currently limited to tiffs/numpy files only
if is_numpy_file(self.__filename):
data = numpy.load(pathname)
elif is_omero3d_path(self.__url):
scheme = 'omero-3d:'
url = self.__url.split(scheme)[1]
parsed_url = urllib.parse.urlparse(url)
query_params = urllib.parse.parse_qs(parsed_url.query)
zmin = int(query_params['zmin'][0])
zmax = int(query_params['zmax'][0])
width = int(query_params['width'][0])
height = int(query_params['height'][0])
image_id = query_params['imageid'][0]
channel = query_params['c'][0]
stack = numpy.ndarray((zmax - zmin + 1, height, width))
for i in range(zmin, zmax + 1):
path = urljoin('/tile', image_id, str(i), channel, '0')
url = urllib.parse.urlunparse((
parsed_url.scheme,
parsed_url.netloc,
path,
'',
parsed_url.query,
''
))
print("Requesting URL: {}".format(url))
timeout = 2
response = None
while timeout < 500:
try:
response = requests.get(url, timeout=timeout)
except Exception:
print('Get %s with timeout %s sec failed' % (
url, timeout))
timeout = timeout**2
else:
break
if response is None:
raise Exception('Failed to retrieve data from URL')
image_bytes = BytesIO(response.content)
image = PilImage.open(image_bytes)
stack[i - zmin, :, :] = image
data = stack
elif pathname.endswith('.zarr'):
rdr = get_zarr_reader(self.get_name(), url=self.get_url())
data = rdr.read(
c=self.channel,
series=self.series,
index=None,
rescale=False,
wants_max_intensity=False,
z=None,
t=self.t_index,
)
else:
data = imageio.volread(pathname)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class ColorImage(URLImage):
"""Provide a color image, tripling a monochrome plane if needed"""

def __init__(
self, name, url, series, index, rescale=True, volume=False, spacing=None
self, name, url, series, index, rescale=True, volume=False, spacing=None, z=None, t=None,
):
URLImage.__init__(
self,
Expand All @@ -18,6 +18,8 @@ def __init__(
index=index,
volume=volume,
spacing=spacing,
z=z,
t=t,
)

def provide_image(self, image_set):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class MaskImage(MonochromeImage):
"""Provide a boolean image, converting nonzero to True, zero to False if needed"""

def __init__(self, name, url, series, index, channel, volume=False, spacing=None):
def __init__(self, name, url, series, index, channel, volume=False, spacing=None, z=None, t=None):
MonochromeImage.__init__(
self,
name,
Expand All @@ -15,6 +15,8 @@ def __init__(self, name, url, series, index, channel, volume=False, spacing=None
channel=channel,
volume=volume,
spacing=spacing,
z=z,
t=t,
)

def provide_image(self, image_set):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def __init__(
rescale=True,
volume=False,
spacing=None,
z=None,
t=None,
):
URLImage.__init__(
self,
Expand All @@ -27,6 +29,8 @@ def __init__(
channel=channel,
volume=volume,
spacing=spacing,
z=z,
t=t,
)

def provide_image(self, image_set):
Expand Down
12 changes: 11 additions & 1 deletion cellprofiler_core/image/abstract_image/file/url/_url_image.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os
from .....utilities.pathname import url2pathname

from .....utilities.image import is_omero3d_path

from .._file_image import FileImage


Expand All @@ -17,6 +19,8 @@ def __init__(
channel=None,
volume=False,
spacing=None,
z=None,
t=None,
):
if url.lower().startswith("file:"):
path = url2pathname(url)
Expand All @@ -25,11 +29,17 @@ def __init__(
pathname = ""
filename = url
super(URLImage, self).__init__(
name, pathname, filename, rescale, series, index, channel, volume, spacing
name, pathname, filename, rescale, series, index, channel, volume, spacing, z=z, t=t,
)
self.url = url

def get_url(self):
if is_omero3d_path(self.url):
print("OMERO-3D URL: {}".format(self.url))
url = self.url.split("omero-3d:")[1]
if url is not None:
return url
return self.url
if self.cache_file():
return super(URLImage, self).get_url()
return self.url
27 changes: 27 additions & 0 deletions cellprofiler_core/modules/loaddata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,33 @@ def fetch_provider(self, name, measurements, is_image_name=True):
frame = measurements["Image", frame_feature]
else:
frame = None
if url.endswith('.zarr'):
# Zarrs need czt indexing rather than just index.
c, z, t = None, None, None

if measurements.has_feature("Image", f"Channel_{name}"):
c = measurements["Image", f"Channel_{name}"]
elif measurements.has_feature("Image", "Metadata_C"):
c = measurements["Image", "Metadata_C"]
if measurements.has_feature("Image", f"Z_{name}"):
z = measurements["Image", f"Z_{name}"]
elif measurements.has_feature("Image", "Metadata_Z"):
z = measurements["Image", "Metadata_Z"]
if measurements.has_feature("Image", f"T_{name}"):
t = measurements["Image", f"T_{name}"]
elif measurements.has_feature("Image", "Metadata_T"):
t = measurements["Image", "Metadata_T"]
return FileImage(
name,
path,
filename,
rescale=self.rescale.value and is_image_name,
series=series,
index=frame,
z=z,
channel=c,
t=t,
)
return FileImage(
name,
path,
Expand Down
8 changes: 6 additions & 2 deletions cellprofiler_core/modules/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ def msg(url):
from bioformats.formatreader import get_omexml_metadata
from typing import Optional, Any, Callable
from dataclasses import dataclass
from cellprofiler_core.utilities.zarr import get_zarr_metadata

@dataclass
class ui_context:
Expand Down Expand Up @@ -1173,6 +1174,7 @@ def update_all_urls():
for i, url in enumerate(urls):
try:
if not pbar_context.update_callback(pbar_context.dlg, i, url):

break
if group.filter_choice == F_FILTERED_IMAGES:
match = group.filter.evaluate(
Expand All @@ -1186,7 +1188,10 @@ def update_all_urls():
continue
metadata = filelist.get_metadata(url)
if metadata is None:
metadata = get_omexml_metadata(url=url)
if url.lower().endswith('.zarr'):
metadata = get_zarr_metadata(url=url)
else:
metadata = get_omexml_metadata(url=url)
filelist.add_metadata(url, metadata)
except Exception as e:
import logging
Expand All @@ -1199,7 +1204,6 @@ def update_all_urls():
pbar_context.err_callback(errmsg)

update_all_urls()

group.metadata_autoextracted.value = True

def on_activated(self, workspace):
Expand Down
Loading

0 comments on commit fefde86

Please sign in to comment.