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

Merge branch 'build-2024.10.01' into 'staging'

Build 2024.10.01

See merge request !63
parents 5851da53 534066f0
No related branches found
No related tags found
2 merge requests!65Release 2024.10.01,!63Build 2024.10.01
...@@ -954,7 +954,7 @@ class RoiSet(object): ...@@ -954,7 +954,7 @@ class RoiSet(object):
return interm return interm
def serialize(self, where: Path, prefix='') -> dict: def serialize(self, where: Path, prefix='roiset') -> dict:
""" """
Export the minimal information needed to recreate RoiSet object, i.e. CSV data file and tight patch masks Export the minimal information needed to recreate RoiSet object, i.e. CSV data file and tight patch masks
:param where: path of directory in which to write files :param where: path of directory in which to write files
......
import json import json
import os import os
import unittest import unittest
from math import floor
from multiprocessing import Process from multiprocessing import Process
from pathlib import Path from pathlib import Path
from shutil import copyfile from shutil import copyfile
import numpy as np
import requests import requests
from urllib3 import Retry from urllib3 import Retry
from ..base.accessors import GenericImageDataAccessor, InMemoryDataAccessor
from ..base.models import SemanticSegmentationModel, InstanceSegmentationModel
from ..base.accessors import generate_file_accessor from ..base.accessors import generate_file_accessor
class TestServerBaseClass(unittest.TestCase): class TestServerBaseClass(unittest.TestCase):
...@@ -77,9 +82,21 @@ def setup_test_data(): ...@@ -77,9 +82,21 @@ def setup_test_data():
:return: :return:
meta (dict) of test data and paths meta (dict) of test data and paths
""" """
def _winpath(f):
if not isinstance(f, str):
return f
p = f.split('/')
if len(p) > 1:
p[1] = p[1] + ':'
return '\\'.join(p[1:])
else:
return f
# places to look for test data # places to look for test data
data_paths = [ data_paths = [
os.environ.get('UNITTEST_DATA_ROOT'), os.environ.get('UNITTEST_DATA_ROOT'),
_winpath(os.environ.get('UNITTEST_DATA_ROOT')),
Path.home() / 'model_server' / 'testing', Path.home() / 'model_server' / 'testing',
os.getcwd(), os.getcwd(),
] ]
...@@ -100,8 +117,7 @@ def setup_test_data(): ...@@ -100,8 +117,7 @@ def setup_test_data():
raise Exception('Could not find test data, try setting environmental variable UNITTEST_DATA_ROOT.') raise Exception('Could not find test data, try setting environmental variable UNITTEST_DATA_ROOT.')
meta['root'] = Path(root) meta['root'] = Path(root)
op_ev = os.environ.get('UNITTEST_OUTPUT', (meta['root'] / 'test_output')) meta['output_path'] = meta['root'] / 'test_output'
meta['output_path'] = Path(op_ev)
meta['output_path'].mkdir(parents=True, exist_ok=True) meta['output_path'].mkdir(parents=True, exist_ok=True)
# resolve relative paths # resolve relative paths
...@@ -117,4 +133,49 @@ def setup_test_data(): ...@@ -117,4 +133,49 @@ def setup_test_data():
return meta return meta
# object containing test data paths and metadata, for import into unittest modules # object containing test data paths and metadata, for import into unittest modules
meta = setup_test_data() meta = setup_test_data()
\ No newline at end of file
class DummySemanticSegmentationModel(SemanticSegmentationModel):
model_id = 'dummy_make_white_square'
def load(self):
return True
def infer(self, img: GenericImageDataAccessor) -> (GenericImageDataAccessor, dict):
super().infer(img)
w = img.shape_dict['X']
h = img.shape_dict['Y']
result = np.zeros([h, w], dtype='uint8')
result[floor(0.25 * h) : floor(0.75 * h), floor(0.25 * w) : floor(0.75 * w)] = 255
return InMemoryDataAccessor(data=result), {'success': True}
def label_pixel_class(
self, img: GenericImageDataAccessor, **kwargs) -> GenericImageDataAccessor:
mask, _ = self.infer(img)
return mask
class DummyInstanceSegmentationModel(InstanceSegmentationModel):
model_id = 'dummy_pass_input_mask'
def load(self):
return True
def infer(
self, img: GenericImageDataAccessor, mask: GenericImageDataAccessor
) -> (GenericImageDataAccessor, dict):
return img.__class__(
(mask.data / mask.data.max()).astype('uint16')
)
def label_instance_class(
self, img: GenericImageDataAccessor, mask: GenericImageDataAccessor, **kwargs
) -> GenericImageDataAccessor:
"""
Returns a trivial segmentation, i.e. the input mask with value 1
"""
super(DummyInstanceSegmentationModel, self).label_instance_class(img, mask, **kwargs)
return self.infer(img, mask)
...@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" ...@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "model_server" name = "model_server"
license = {file = "LICENSE"} license = {file = "LICENSE"}
version = "2024.09.30" version = "2024.10.01"
authors = [ authors = [
{ name="Christopher Rhodes", email="christopher.rhodes@embl.de" }, { name="Christopher Rhodes", email="christopher.rhodes@embl.de" },
] ]
......
...@@ -8,7 +8,7 @@ import model_server.conf.testing as conf ...@@ -8,7 +8,7 @@ import model_server.conf.testing as conf
from model_server.base.accessors import InMemoryDataAccessor from model_server.base.accessors import InMemoryDataAccessor
from model_server.base.api import app from model_server.base.api import app
from model_server.base.session import session from model_server.base.session import session
from tests.base.test_model import DummyInstanceSegmentationModel, DummySemanticSegmentationModel from model_server.conf.testing import DummySemanticSegmentationModel, DummyInstanceSegmentationModel
czifile = conf.meta['image_files']['czifile'] czifile = conf.meta['image_files']['czifile']
......
from math import floor
import unittest import unittest
import numpy as np
import model_server.conf.testing as conf import model_server.conf.testing as conf
from model_server.base.accessors import CziImageFileAccessor, GenericImageDataAccessor, InMemoryDataAccessor from model_server.conf.testing import DummySemanticSegmentationModel, DummyInstanceSegmentationModel
from model_server.base.models import CouldNotLoadModelError, InstanceSegmentationModel, SemanticSegmentationModel, BinaryThresholdSegmentationModel from model_server.base.accessors import CziImageFileAccessor
from model_server.base.models import CouldNotLoadModelError, BinaryThresholdSegmentationModel
czifile = conf.meta['image_files']['czifile'] czifile = conf.meta['image_files']['czifile']
class DummySemanticSegmentationModel(SemanticSegmentationModel):
model_id = 'dummy_make_white_square'
def load(self):
return True
def infer(self, img: GenericImageDataAccessor) -> (GenericImageDataAccessor, dict):
super().infer(img)
w = img.shape_dict['X']
h = img.shape_dict['Y']
result = np.zeros([h, w], dtype='uint8')
result[floor(0.25 * h) : floor(0.75 * h), floor(0.25 * w) : floor(0.75 * w)] = 255
return InMemoryDataAccessor(data=result), {'success': True}
def label_pixel_class(
self, img: GenericImageDataAccessor, **kwargs) -> GenericImageDataAccessor:
mask, _ = self.infer(img)
return mask
class DummyInstanceSegmentationModel(InstanceSegmentationModel):
model_id = 'dummy_pass_input_mask'
def load(self):
return True
def infer(
self, img: GenericImageDataAccessor, mask: GenericImageDataAccessor
) -> (GenericImageDataAccessor, dict):
return img.__class__(
(mask.data / mask.data.max()).astype('uint16')
)
def label_instance_class(
self, img: GenericImageDataAccessor, mask: GenericImageDataAccessor, **kwargs
) -> GenericImageDataAccessor:
"""
Returns a trivial segmentation, i.e. the input mask with value 1
"""
super(DummyInstanceSegmentationModel, self).label_instance_class(img, mask, **kwargs)
return self.infer(img, mask)
class TestCziImageFileAccess(unittest.TestCase): class TestCziImageFileAccess(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
......
...@@ -4,7 +4,7 @@ from model_server.base.accessors import generate_file_accessor, write_accessor_d ...@@ -4,7 +4,7 @@ from model_server.base.accessors import generate_file_accessor, write_accessor_d
from model_server.base.pipelines import router, segment, segment_zproj from model_server.base.pipelines import router, segment, segment_zproj
import model_server.conf.testing as conf import model_server.conf.testing as conf
from tests.base.test_model import DummySemanticSegmentationModel from model_server.conf.testing import DummySemanticSegmentationModel
czifile = conf.meta['image_files']['czifile'] czifile = conf.meta['image_files']['czifile']
zstack = conf.meta['image_files']['tifffile'] zstack = conf.meta['image_files']['tifffile']
......
...@@ -11,7 +11,7 @@ from model_server.base.roiset import filter_df_overlap_bbox, filter_df_overlap_s ...@@ -11,7 +11,7 @@ from model_server.base.roiset import filter_df_overlap_bbox, filter_df_overlap_s
from model_server.base.roiset import RoiSet from model_server.base.roiset import RoiSet
from model_server.base.accessors import generate_file_accessor, InMemoryDataAccessor, write_accessor_data_to_file, PatchStack from model_server.base.accessors import generate_file_accessor, InMemoryDataAccessor, write_accessor_data_to_file, PatchStack
import model_server.conf.testing as conf import model_server.conf.testing as conf
from tests.base.test_model import DummyInstanceSegmentationModel from model_server.conf.testing import DummyInstanceSegmentationModel
data = conf.meta['image_files'] data = conf.meta['image_files']
output_path = conf.meta['output_path'] output_path = conf.meta['output_path']
......
...@@ -7,7 +7,7 @@ from model_server.base.roiset import RoiSetWithDerivedChannelsExportParams, RoiS ...@@ -7,7 +7,7 @@ from model_server.base.roiset import RoiSetWithDerivedChannelsExportParams, RoiS
from model_server.base.roiset import RoiSetWithDerivedChannels from model_server.base.roiset import RoiSetWithDerivedChannels
from model_server.base.accessors import generate_file_accessor, PatchStack from model_server.base.accessors import generate_file_accessor, PatchStack
import model_server.conf.testing as conf import model_server.conf.testing as conf
from tests.base.test_model import DummyInstanceSegmentationModel from model_server.conf.testing import DummyInstanceSegmentationModel
data = conf.meta['image_files'] data = conf.meta['image_files']
params = conf.meta['roiset'] params = conf.meta['roiset']
......
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