Skip to content
Snippets Groups Projects
Commit 87b32bfe authored by Christopher Randolph Rhodes's avatar Christopher Randolph Rhodes
Browse files

Moved PatchStack to base.accessors

parent b54bfadd
No related branches found
No related tags found
No related merge requests found
......@@ -8,6 +8,7 @@ from skimage.io import imread
import czifile
import tifffile
from extensions.chaeo.accessors import InvalidDataForPatchStackError
from model_server.base.process import is_mask
class GenericImageDataAccessor(ABC):
......@@ -234,4 +235,68 @@ class InvalidAxisKey(Error):
pass
class InvalidDataShape(Error):
pass
\ No newline at end of file
pass
class PatchStack(InMemoryDataAccessor):
def __init__(self, data):
"""
A sequence of n (generally) color 3D images of the same size
:param data: either a list of np.ndarrays of size YXCZ, or np.ndarray of size PYXCZ
"""
if isinstance(data, list): # list of YXCZ patches
n = len(data)
yxcz_shape = np.array([e.shape for e in data]).max(axis=0)
nda = np.zeros(
(n, *yxcz_shape), dtype=data[0].dtype
)
for i in range(0, len(data)):
s = tuple([slice(0, c) for c in data[i].shape])
nda[i][s] = data[i]
elif isinstance(data, np.ndarray) and len(data.shape) == 5: # interpret as PYXCZ
nda = data
else:
raise InvalidDataForPatchStackError(f'Cannot create accessor from {type(data)}')
assert nda.ndim == 5
self._data = nda
def iat(self, i):
return self.data[i, :, :, :, :]
def iat_yxcz(self, i):
return self.iat(i)
@property
def count(self):
return self.shape_dict['P']
@property
def shape_dict(self):
return dict(zip(('P', 'Y', 'X', 'C', 'Z'), self.data.shape))
def get_list(self):
n = self.nz
return [self.data[:, :, 0, zi] for zi in range(0, n)]
@property
def pyxcz(self):
return self.data
@property
def pczyx(self):
return np.moveaxis(
self.data,
[0, 3, 4, 1, 2],
[0, 1, 2, 3, 4]
)
@property
def shape(self):
return self.data.shape
@property
def shape_dict(self):
return dict(zip(('P', 'Y', 'X', 'C', 'Z'), self.data.shape))
......@@ -17,7 +17,8 @@ from model_server.base.accessors import GenericImageDataAccessor, InMemoryDataAc
from model_server.base.models import InstanceSegmentationModel
from model_server.base.process import pad, rescale, resample_to_8bit, make_rgb
from base.annotators import draw_box_on_patch, draw_contours_on_patch, draw_boxes_on_3d_image
from model_server.extensions.chaeo.accessors import write_patch_to_file, PatchStack
from model_server.extensions.chaeo.accessors import write_patch_to_file
from base.accessors import PatchStack
from base.process import mask_largest_object
......
......@@ -7,67 +7,6 @@ from tifffile import imwrite
from base.process import make_rgb
from model_server.base.accessors import generate_file_accessor, InMemoryDataAccessor
class MonoPatchStack(InMemoryDataAccessor):
def __init__(self, data):
"""
A sequence of n monochrome images of the same size
:param data: either np.ndarray of dimensions YXn, or a list of np.ndarrays of size YX
"""
if isinstance(data, np.ndarray):
if data.ndim == 3: # interpret as YXZ
self._data = np.expand_dims(data, 2)
elif data.ndim == 4: # interpret as a copy another patch stack
self._data = data
else:
raise InvalidDataForPatchStackError()
elif isinstance(data, list): # list of YX patches
if len(data) == 0:
self._data = np.ndarray([0, 0, 0, 0], dtype='uin9')
elif len(data) == 1:
self._data = np.expand_dims(
np.array(
data[0].squeeze()
),
(2, 3)
)
else:
nda = np.array(data).squeeze()
assert nda.ndim == 3
self._data = np.expand_dims(
np.moveaxis(
nda,
[1, 2, 0],
[0, 1, 2]),
2
)
else:
raise InvalidDataForPatchStackError(f'Cannot create accessor from {type(data)}')
def make_tczyx(self):
assert self.chroma == 1
tyx = np.moveaxis(
self.data[:, :, 0, :], # YX(C)Z
[2, 0, 1],
[0, 1, 2]
)
return np.expand_dims(tyx, (1, 2))
@property
def count(self):
return self.nz
def iat(self, i):
return self.data[:, :, 0, i]
def iat_yxcz(self, i):
return np.expand_dims(self.iat(i), (2, 3))
def get_list(self):
n = self.nz
return [self.data[:, :, 0, zi] for zi in range(0, n)]
class MonoPatchStackFromFile(MonoPatchStack):
def __init__(self, fpath):
......@@ -81,70 +20,6 @@ class MonoPatchStackFromFile(MonoPatchStack):
return self.file_acc.fpath
class PatchStack(InMemoryDataAccessor):
def __init__(self, data):
"""
A sequence of n (generally) color 3D images of the same size
:param data: either a list of np.ndarrays of size YXCZ, or np.ndarray of size PYXCZ
"""
if isinstance(data, list): # list of YXCZ patches
n = len(data)
yxcz_shape = np.array([e.shape for e in data]).max(axis=0)
nda = np.zeros(
(n, *yxcz_shape), dtype=data[0].dtype
)
for i in range(0, len(data)):
s = tuple([slice(0, c) for c in data[i].shape])
nda[i][s] = data[i]
elif isinstance(data, np.ndarray) and len(data.shape) == 5: # interpret as PYXCZ
nda = data
else:
raise InvalidDataForPatchStackError(f'Cannot create accessor from {type(data)}')
assert nda.ndim == 5
self._data = nda
def iat(self, i):
return self.data[i, :, :, :, :]
def iat_yxcz(self, i):
return self.iat(i)
@property
def count(self):
return self.shape_dict['P']
@property
def shape_dict(self):
return dict(zip(('P', 'Y', 'X', 'C', 'Z'), self.data.shape))
def get_list(self):
n = self.nz
return [self.data[:, :, 0, zi] for zi in range(0, n)]
@property
def pyxcz(self):
return self.data
@property
def pczyx(self):
return np.moveaxis(
self.data,
[0, 3, 4, 1, 2],
[0, 1, 2, 3, 4]
)
@property
def shape(self):
return self.data.shape
@property
def shape_dict(self):
return dict(zip(('P', 'Y', 'X', 'C', 'Z'), self.data.shape))
def write_patch_to_file(where, fname, yxcz):
ext = fname.split('.')[-1].upper()
where.mkdir(parents=True, exist_ok=True)
......
......@@ -3,8 +3,8 @@ import unittest
import numpy as np
from model_server.conf.testing import monozstackmask
from model_server.extensions.chaeo.accessors import MonoPatchStackFromFile, PatchStack
from model_server.extensions.chaeo.accessors import MonoPatchStackFromFile
from base.accessors import PatchStack
class TestMultipositionCziImageFileAccess(unittest.TestCase):
......
......@@ -5,7 +5,7 @@ import numpy as np
import vigra
import model_server.extensions.ilastik.conf
from extensions.chaeo.accessors import PatchStack
from base.accessors import PatchStack
from model_server.base.accessors import GenericImageDataAccessor, InMemoryDataAccessor
from model_server.base.models import Model, ImageToImageModel, InstanceSegmentationModel, InvalidInputImageError, ParameterExpectedError, SemanticSegmentationModel
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment