diff --git a/model_server/base/accessors.py b/model_server/base/accessors.py index b5da8306d3fc5dab5270bf6a22b4d628336bb943..a9366156bb6a5fcd63267cd3fb6e319d13bfbe37 100644 --- a/model_server/base/accessors.py +++ b/model_server/base/accessors.py @@ -61,6 +61,11 @@ class GenericImageDataAccessor(ABC): ) ) + def get_mip(self): + """ + Return a new accessor of maximum intensity projection (MIP) along z-axis + """ + return self.apply(lambda x: x.max(axis=self._ga('Z'), keepdims=True)) def get_mono(self, channel: int, mip: bool = False): return self.get_channels([channel], mip=mip) diff --git a/model_server/base/pipelines/roiset_obmap.py b/model_server/base/pipelines/roiset_obmap.py index 96e0339082df9f3b1fcc353793bc145fba816d8c..037fb7fc015c5646152854f5a7fa4f2258d9808d 100644 --- a/model_server/base/pipelines/roiset_obmap.py +++ b/model_server/base/pipelines/roiset_obmap.py @@ -1,6 +1,6 @@ from typing import Dict, Union -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, validator from ..accessors import GenericImageDataAccessor from .router import router @@ -51,7 +51,8 @@ class RoiSetObjectMapParams(PipelineParams): 'filters': { 'area': {'min': 1e3, 'max': 1e8} }, - 'expand_box_by': [128, 2] + 'expand_box_by': [128, 2], + 'deproject_channel': None, }) export_params: RoiSetExportParams = RoiSetExportParams() derived_channels_input_channel: Union[int, None] = Field( diff --git a/model_server/base/roiset.py b/model_server/base/roiset.py index 94fbbe400be7b47db25d54669d2b8436b062dc9c..582c517af4f4d9bfff9fb8e55d2e8b6fb8d95df7 100644 --- a/model_server/base/roiset.py +++ b/model_server/base/roiset.py @@ -62,6 +62,7 @@ class RoiSetExportParams(BaseModel): patches_2d: Union[PatchParams, None] = None annotated_zstacks: Union[AnnotatedZStackParams, None] = None object_classes: bool = False + derived_channels: bool = False def get_label_ids(acc_seg_mask: GenericImageDataAccessor, allow_3d=False, connect_3d=True) -> InMemoryDataAccessor: @@ -1091,7 +1092,7 @@ class RoiSetWithDerivedChannels(RoiSet): def __init__(self, *a, **k): self.accs_derived = [] - return super().__init__(*a, **k) + super().__init__(*a, **k) def classify_by( self, name: str, channels: list[int], diff --git a/tests/base/test_roiset_derived.py b/tests/base/test_roiset_derived.py index 49a535f0b2ff5254fb257d7716b8acd03381c4ca..52e7f6fc0a917d719262dcd0c19f3170414f2f18 100644 --- a/tests/base/test_roiset_derived.py +++ b/tests/base/test_roiset_derived.py @@ -29,6 +29,7 @@ class TestDerivedChannels(unittest.TestCase): self.seg_mask, params=RoiSetMetaParams( filters={'area': {'min': 1e3, 'max': 1e4}}, + deproject_channel=0, ) ) self.assertIsInstance(roiset, RoiSetWithDerivedChannels) diff --git a/tests/test_ilastik/test_roiset_workflow.py b/tests/test_ilastik/test_roiset_workflow.py index c02dd6d94c3b8fdfedbac432675fc1187b478f36..cec05dbdbdb1be3c97c1ed53cccf3d57984fa34c 100644 --- a/tests/test_ilastik/test_roiset_workflow.py +++ b/tests/test_ilastik/test_roiset_workflow.py @@ -60,7 +60,8 @@ class BaseTestRoiSetMonoProducts(object): 'filters': { 'area': {'min': 1e0, 'max': 1e8} }, - 'expand_box_by': [128, 2] + 'expand_box_by': [128, 2], + 'deproject_channel': 0, } def _get_models(self): # tests can either use model objects directly, or load in API via project file string