From 33f832353306a2afd6593b728ded0cb5064dca1e Mon Sep 17 00:00:00 2001 From: Christopher Rhodes <christopher.rhodes@embl.de> Date: Fri, 27 Oct 2023 14:26:07 +0200 Subject: [PATCH] Started testing object classification from z-stack via a batch running script --- extensions/chaeo/accessors.py | 6 ++- extensions/chaeo/examples/batch_obj_cla.py | 45 ++++++++++++++++++++++ extensions/chaeo/workflows.py | 25 +++++++----- 3 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 extensions/chaeo/examples/batch_obj_cla.py diff --git a/extensions/chaeo/accessors.py b/extensions/chaeo/accessors.py index d1e9089c..b782c51b 100644 --- a/extensions/chaeo/accessors.py +++ b/extensions/chaeo/accessors.py @@ -10,12 +10,14 @@ class MonoPatchStack(InMemoryDataAccessor): """ if isinstance(data, np.ndarray): # interpret as YXZ - assert len(data.shape) == 3 + assert data.ndim == 3 self._data = np.expand_dims(data, 2) elif isinstance(data, list): # list of YX patches + nda = np.array(data) + assert nda.squeeze().ndim == 3 self._data = np.expand_dims( np.moveaxis( - np.array(data), + nda, [1, 2, 0], [0, 1, 2]), 2 diff --git a/extensions/chaeo/examples/batch_obj_cla.py b/extensions/chaeo/examples/batch_obj_cla.py new file mode 100644 index 00000000..105f8e46 --- /dev/null +++ b/extensions/chaeo/examples/batch_obj_cla.py @@ -0,0 +1,45 @@ +from pathlib import Path + +from conf.testing import output_path +from model_server.util import autonumber_new_directory, get_matching_files, loop_workflow +from extensions.chaeo.models import PatchStackObjectClassifier +from extensions.chaeo.workflows import infer_object_map_from_zstack +from extensions.ilastik.models import IlastikPixelClassifierModel + + + +if __name__ == '__main__': + where_czi = 'c:/Users/rhodes/projects/proj0004-marine-photoactivation/data/exp0038/AutoMic/20230906-163415/Selection' + where_output = autonumber_new_directory( + output_path, + 'zmask_to_automic', + ) + + px_ilp = Path.home() / 'model-server' / 'testing' / 'zmask' / 'AF405-bodies_boundaries.ilp' + ob_ilp = Path.home() / 'model-server' / 'testing' / 'zmask' / 'auto_obj_after.ilp' + + params = { + 'pxmap_threshold': 0.25, + 'pxmap_foreground_channel': 0, + 'segmentation_channel': 0, + 'patches_channel': 4, + 'zmask_filters': {'area': (1e3, 1e8)}, + } + + input_files = get_matching_files(where_czi, 'czi', coord_filter={'P': (0, 10)}, ) + + models = [ + IlastikPixelClassifierModel(params={'project_file': Path(px_ilp)}), + PatchStackObjectClassifier(params={'project_file': Path(ob_ilp)}) + ] + + loop_workflow( + input_files, + where_output, + infer_object_map_from_zstack, + models, + params, + catch_and_continue=False, + ) + + print('Finished') \ No newline at end of file diff --git a/extensions/chaeo/workflows.py b/extensions/chaeo/workflows.py index 7289c58e..3847d5e2 100644 --- a/extensions/chaeo/workflows.py +++ b/extensions/chaeo/workflows.py @@ -27,11 +27,9 @@ def get_zmask_meta( pxmap_foreground_channel: int = 0, zmask_zindex: int = None, zmask_clip: int = None, - zmask_expand_box_by: int = None, zmask_filters: Dict = None, zmask_type: str = 'boxes', - - + **kwargs, ) -> tuple: ti = Timer() stack = generate_file_accessor(Path(input_file_path)) @@ -63,7 +61,7 @@ def get_zmask_meta( stack.get_one_channel_data(segmentation_channel), mask_type=zmask_type, filters=zmask_filters, - expand_box_by=zmask_expand_box_by, + **kwargs, ) ti.click('generate_zmasks') @@ -210,7 +208,7 @@ def export_patches_from_multichannel_zstack( 'interm': interm, } -def get_object_map_from_zstack( +def infer_object_map_from_zstack( input_file_path: str, output_folder_path: str, models: List[Model], @@ -222,7 +220,7 @@ def get_object_map_from_zstack( zmask_clip: int = None, zmask_type: str = 'boxes', zmask_filters: Dict = None, - zmask_expand_box_by: int = None, + # zmask_expand_box_by: int = None, **kwargs, ) -> Dict: assert len(models) == 2 @@ -239,17 +237,19 @@ def get_object_map_from_zstack( pxmap_foreground_channel=pxmap_foreground_channel, zmask_zindex=zmask_zindex, zmask_clip=zmask_clip, - zmask_expand_box_by=zmask_expand_box_by, + # zmask_expand_box_by=zmask_expand_box_by, zmask_filters=zmask_filters, zmask_type=zmask_type, + **kwargs ) # extract patches to accessor patches_acc = get_patches_from_zmask_meta( - stack, + stack.get_one_channel_data(patches_channel), zmask_meta, rescale_clip=zmask_clip, make_3d=False, + focus_metric='max_sobel', **kwargs ) @@ -274,14 +274,21 @@ def get_object_map_from_zstack( mi = zmask_meta[ii] object_label_id = mi['info'].label result_label_map = result_acc.iat(ii) + assert (result_label_map.shape) == 2 unique_values = np.unique(result_label_map) assert len(unique_values) == 2 assert unique_values[0] == 0 - inferred_class = result_acc.iat(ii) ii_mask = object_labels_map == object_label_id object_labels_map[ii_mask] = unique_values[1] patch = patches_acc.iat(ii) + write_accessor_data_to_file( + Path(output_folder_path) / 'obj_classes_' / (fstem + '.tif'), + object_labels_map + ) + ti.click('export_object_classes') + return ti + def transfer_ecotaxa_labels_to_patch_stacks( -- GitLab