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

base.accessors method to make patch mask from file

parent 87b32bfe
No related branches found
No related tags found
No related merge requests found
...@@ -185,6 +185,14 @@ class CziImageFileAccessor(GenericImageFileAccessor): ...@@ -185,6 +185,14 @@ class CziImageFileAccessor(GenericImageFileAccessor):
def write_accessor_data_to_file(fpath: Path, accessor: GenericImageDataAccessor, mkdir=True) -> bool: def write_accessor_data_to_file(fpath: Path, accessor: GenericImageDataAccessor, mkdir=True) -> bool:
"""
Export an image accessor to file.
:param fpath: complete path including filename and extension
:param accessor: image accessor to be written
:param mkdir: create any needed subdirectories in fpath if True
:return: True
"""
if mkdir: if mkdir:
fpath.parent.mkdir(parents=True, exist_ok=True) fpath.parent.mkdir(parents=True, exist_ok=True)
try: try:
...@@ -207,6 +215,10 @@ def write_accessor_data_to_file(fpath: Path, accessor: GenericImageDataAccessor, ...@@ -207,6 +215,10 @@ def write_accessor_data_to_file(fpath: Path, accessor: GenericImageDataAccessor,
def generate_file_accessor(fpath): def generate_file_accessor(fpath):
"""
Given an image file path, return an image accessor, assuming the file is a supported format and represents
a single position array, which may be single or multi-channel, single plane or z-stack.
"""
if str(fpath).upper().endswith('.TIF') or str(fpath).upper().endswith('.TIFF'): if str(fpath).upper().endswith('.TIF') or str(fpath).upper().endswith('.TIFF'):
return TifSingleSeriesFileAccessor(fpath) return TifSingleSeriesFileAccessor(fpath)
elif str(fpath).upper().endswith('.CZI'): elif str(fpath).upper().endswith('.CZI'):
...@@ -216,27 +228,6 @@ def generate_file_accessor(fpath): ...@@ -216,27 +228,6 @@ def generate_file_accessor(fpath):
else: else:
raise FileAccessorError(f'Could not match a file accessor with {fpath}') raise FileAccessorError(f'Could not match a file accessor with {fpath}')
class Error(Exception):
pass
class FileAccessorError(Error):
pass
class FileNotFoundError(Error):
pass
class DataShapeError(Error):
pass
class FileWriteError(Error):
pass
class InvalidAxisKey(Error):
pass
class InvalidDataShape(Error):
pass
class PatchStack(InMemoryDataAccessor): class PatchStack(InMemoryDataAccessor):
...@@ -293,6 +284,7 @@ class PatchStack(InMemoryDataAccessor): ...@@ -293,6 +284,7 @@ class PatchStack(InMemoryDataAccessor):
[0, 3, 4, 1, 2], [0, 3, 4, 1, 2],
[0, 1, 2, 3, 4] [0, 1, 2, 3, 4]
) )
@property @property
def shape(self): def shape(self):
return self.data.shape return self.data.shape
...@@ -300,3 +292,41 @@ class PatchStack(InMemoryDataAccessor): ...@@ -300,3 +292,41 @@ class PatchStack(InMemoryDataAccessor):
@property @property
def shape_dict(self): def shape_dict(self):
return dict(zip(('P', 'Y', 'X', 'C', 'Z'), self.data.shape)) return dict(zip(('P', 'Y', 'X', 'C', 'Z'), self.data.shape))
def make_patch_stack_from_file(fpath): # interpret z-dimension as patch position
if not Path(fpath).exists():
raise FileNotFoundError(f'Could not find {fpath}')
pyxc = np.moveaxis(
generate_file_accessor(fpath).data, # yxcz
[0, 1, 2, 3],
[1, 2, 3, 0]
)
pyxcz = np.expand_dims(pyxc, axis=3)
return PatchStack(pyxcz)
class Error(Exception):
pass
class FileAccessorError(Error):
pass
class FileNotFoundError(Error):
pass
class DataShapeError(Error):
pass
class FileWriteError(Error):
pass
class InvalidAxisKey(Error):
pass
class InvalidDataShape(Error):
pass
from pathlib import Path
import numpy as np import numpy as np
from skimage.io import imsave from skimage.io import imsave
from tifffile import imwrite from tifffile import imwrite
from base.process import make_rgb from base.process import make_rgb
from model_server.base.accessors import generate_file_accessor, InMemoryDataAccessor
class MonoPatchStackFromFile(MonoPatchStack):
def __init__(self, fpath):
if not Path(fpath).exists():
raise FileNotFoundError(f'Could not find {fpath}')
self.file_acc = generate_file_accessor(fpath)
super().__init__(self.file_acc.data[:, :, 0, :])
@property
def fpath(self):
return self.file_acc.fpath
# TODO: move this as method in base.accessors
def write_patch_to_file(where, fname, yxcz): def write_patch_to_file(where, fname, yxcz):
ext = fname.split('.')[-1].upper() ext = fname.split('.')[-1].upper()
where.mkdir(parents=True, exist_ok=True) where.mkdir(parents=True, exist_ok=True)
...@@ -52,7 +38,4 @@ class Error(Exception): ...@@ -52,7 +38,4 @@ class Error(Exception):
class InvalidDataForPatchStackError(Error): class InvalidDataForPatchStackError(Error):
pass pass
class FileNotFoundError(Error):
pass
...@@ -5,16 +5,15 @@ import h5py ...@@ -5,16 +5,15 @@ import h5py
import numpy as np import numpy as np
import skimage import skimage
from model_server.extensions.chaeo.accessors import MonoPatchStackFromFile from model_server.extensions.chaeo.accessors import PatchStack
def generate_ilastik_object_classifier( def generate_ilastik_object_classifier(
template_ilp: Path, template_ilp: Path,
target_ilp: Path, target_ilp: Path,
raw_stack: MonoPatchStackFromFile, raw_stack: PatchStack,
mask_stack: MonoPatchStackFromFile, mask_stack: PatchStack,
label_stack: MonoPatchStackFromFile, label_stack: PatchStack,
label_names: list, label_names: list,
lane: int = 0, lane: int = 0,
allow_multiple_objects=True, allow_multiple_objects=True,
......
...@@ -3,8 +3,7 @@ import unittest ...@@ -3,8 +3,7 @@ import unittest
import numpy as np import numpy as np
from model_server.conf.testing import monozstackmask from model_server.conf.testing import monozstackmask
from model_server.extensions.chaeo.accessors import MonoPatchStackFromFile from base.accessors import PatchStack, make_patch_stack_from_file, FileNotFoundError
from base.accessors import PatchStack
class TestMultipositionCziImageFileAccess(unittest.TestCase): class TestMultipositionCziImageFileAccess(unittest.TestCase):
...@@ -36,16 +35,15 @@ class TestMultipositionCziImageFileAccess(unittest.TestCase): ...@@ -36,16 +35,15 @@ class TestMultipositionCziImageFileAccess(unittest.TestCase):
w = monozstackmask['w'] w = monozstackmask['w']
c = monozstackmask['c'] c = monozstackmask['c']
n = monozstackmask['z'] n = monozstackmask['z']
acc = MonoPatchStackFromFile(monozstackmask['path'])
acc = make_patch_stack_from_file(monozstackmask['path'])
self.assertEqual(acc.hw, (h, w)) self.assertEqual(acc.hw, (h, w))
self.assertEqual(acc.count, n) self.assertEqual(acc.count, n)
self.assertEqual(acc.make_tczyx().shape, (n, c, 1, h, w)) self.assertEqual(acc.pyxcz.shape, (n, h, w, c, 1))
self.assertEqual(acc.fpath, monozstackmask['path'])
def test_raises_filenotfound(self): def test_raises_filenotfound(self):
from model_server.extensions.chaeo.accessors import FileNotFoundError
with self.assertRaises(FileNotFoundError): with self.assertRaises(FileNotFoundError):
acc = MonoPatchStackFromFile('c:/fake/file/name.tif') acc = make_patch_stack_from_file('c:/fake/file/name.tif')
def test_make_3d_patch_stack_from_nonuniform_list(self): def test_make_3d_patch_stack_from_nonuniform_list(self):
w = 256 w = 256
......
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