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