From de6f2ecd2bf838adcd2426cbc1011072aab0d883 Mon Sep 17 00:00:00 2001
From: Christopher Rhodes <christopher.rhodes@embl.de>
Date: Mon, 25 Sep 2023 12:54:30 +0200
Subject: [PATCH] Moved ilastik to its own extensions package

---
 api.py                                        |  8 +--
 extensions/__init__.py                        |  0
 extensions/examples/__init__.py               |  0
 .../examples}/ilastik3d.py                    |  0
 extensions/ilastik/__init__.py                |  0
 conf/ilastik.py => extensions/ilastik/conf.py |  0
 .../ilastik/models.py                         | 10 ++--
 extensions/ilastik/tests/__init__.py          |  0
 .../ilastik/tests}/test_ilastik.py            |  6 +-
 .../ilastik/workflows.py                      |  8 +--
 model_server/{image.py => accessors.py}       |  0
 model_server/{model.py => models.py}          |  2 +-
 model_server/session.py                       |  9 +--
 model_server/share.py                         |  5 ++
 model_server/{workflow.py => workflows.py}    |  4 +-
 simulate_automic.py                           | 55 -------------------
 tests/test_api.py                             |  2 +-
 tests/test_image.py                           |  2 +-
 tests/test_model.py                           |  4 +-
 tests/test_session.py                         |  4 +-
 tests/test_workflow.py                        |  4 +-
 21 files changed, 33 insertions(+), 90 deletions(-)
 create mode 100644 extensions/__init__.py
 create mode 100644 extensions/examples/__init__.py
 rename {examples => extensions/examples}/ilastik3d.py (100%)
 create mode 100644 extensions/ilastik/__init__.py
 rename conf/ilastik.py => extensions/ilastik/conf.py (100%)
 rename model_server/ilastik.py => extensions/ilastik/models.py (91%)
 create mode 100644 extensions/ilastik/tests/__init__.py
 rename {tests => extensions/ilastik/tests}/test_ilastik.py (96%)
 rename model_server/workflow_ilastik.py => extensions/ilastik/workflows.py (88%)
 rename model_server/{image.py => accessors.py} (100%)
 rename model_server/{model.py => models.py} (96%)
 rename model_server/{workflow.py => workflows.py} (92%)
 delete mode 100644 simulate_automic.py

diff --git a/api.py b/api.py
index abd27bbf..45ee844f 100644
--- a/api.py
+++ b/api.py
@@ -1,10 +1,10 @@
 from fastapi import FastAPI, HTTPException
 
-from model_server.ilastik import IlastikImageToImageModel, IlastikPixelClassifierModel, IlastikObjectClassifierModel
-from model_server.model import DummyImageToImageModel, ParameterExpectedError
+from extensions.ilastik.models import IlastikImageToImageModel, IlastikPixelClassifierModel, IlastikObjectClassifierModel
+from model_server.models import DummyImageToImageModel, ParameterExpectedError
 from model_server.session import Session
-from model_server.workflow import infer_image_to_image
-from model_server.workflow_ilastik import infer_px_then_ob_model
+from model_server.workflows import infer_image_to_image
+from extensions.ilastik.workflows import infer_px_then_ob_model
 
 app = FastAPI(debug=True)
 session = Session()
diff --git a/extensions/__init__.py b/extensions/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/extensions/examples/__init__.py b/extensions/examples/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/examples/ilastik3d.py b/extensions/examples/ilastik3d.py
similarity index 100%
rename from examples/ilastik3d.py
rename to extensions/examples/ilastik3d.py
diff --git a/extensions/ilastik/__init__.py b/extensions/ilastik/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/conf/ilastik.py b/extensions/ilastik/conf.py
similarity index 100%
rename from conf/ilastik.py
rename to extensions/ilastik/conf.py
diff --git a/model_server/ilastik.py b/extensions/ilastik/models.py
similarity index 91%
rename from model_server/ilastik.py
rename to extensions/ilastik/models.py
index aad0f38c..ddcb0db5 100644
--- a/model_server/ilastik.py
+++ b/extensions/ilastik/models.py
@@ -4,9 +4,9 @@ from pathlib import Path
 import numpy as np
 import vigra
 
-import conf.ilastik
-from model_server.image import GenericImageDataAccessor, InMemoryDataAccessor
-from model_server.model import ImageToImageModel, ParameterExpectedError
+import extensions.ilastik.conf
+from model_server.accessors import GenericImageDataAccessor, InMemoryDataAccessor
+from model_server.models import ImageToImageModel, ParameterExpectedError
 
 
 class IlastikImageToImageModel(ImageToImageModel):
@@ -14,7 +14,7 @@ class IlastikImageToImageModel(ImageToImageModel):
     def __init__(self, params, autoload=True):
         self.project_file = Path(params['project_file'])
         params['project_file'] = self.project_file.__str__()
-        pap = conf.ilastik.paths['project_files'] / self.project_file
+        pap = extensions.ilastik.conf.paths['project_files'] / self.project_file
         self.project_file_abspath = pap
         if not pap.exists():
             raise FileNotFoundError(f'Project file does not exist: {pap}')
@@ -53,7 +53,7 @@ class IlastikPixelClassifierModel(IlastikImageToImageModel):
 
     @staticmethod
     def get_workflow():
-        from ilastik.workflows.pixelClassification import PixelClassificationWorkflow
+        from ilastik.workflows import PixelClassificationWorkflow
         return PixelClassificationWorkflow
 
     def infer(self, input_img: GenericImageDataAccessor) -> (np.ndarray, dict):
diff --git a/extensions/ilastik/tests/__init__.py b/extensions/ilastik/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/test_ilastik.py b/extensions/ilastik/tests/test_ilastik.py
similarity index 96%
rename from tests/test_ilastik.py
rename to extensions/ilastik/tests/test_ilastik.py
index 747de17a..f8ec7e9e 100644
--- a/tests/test_ilastik.py
+++ b/extensions/ilastik/tests/test_ilastik.py
@@ -4,9 +4,9 @@ import unittest
 import numpy as np
 
 import conf.testing
-from model_server.image import CziImageFileAccessor, InMemoryDataAccessor, write_accessor_data_to_file
-from model_server.ilastik import IlastikObjectClassifierModel, IlastikPixelClassifierModel
-from model_server.workflow import infer_image_to_image
+from model_server.accessors import CziImageFileAccessor, InMemoryDataAccessor, write_accessor_data_to_file
+from extensions.ilastik.models import IlastikObjectClassifierModel, IlastikPixelClassifierModel
+from model_server.workflows import infer_image_to_image
 from tests.test_api import TestServerBaseClass
 
 class TestIlastikPixelClassification(unittest.TestCase):
diff --git a/model_server/workflow_ilastik.py b/extensions/ilastik/workflows.py
similarity index 88%
rename from model_server/workflow_ilastik.py
rename to extensions/ilastik/workflows.py
index db412bb4..45763ad7 100644
--- a/model_server/workflow_ilastik.py
+++ b/extensions/ilastik/workflows.py
@@ -2,13 +2,11 @@
 Implementation of image analysis work behind API endpoints, without knowledge of persistent data in server session.
 """
 from pathlib import Path
-from time import perf_counter
 from typing import Dict
 
-from model_server.ilastik import IlastikPixelClassifierModel, IlastikObjectClassifierModel
-from model_server.image import generate_file_accessor, write_accessor_data_to_file
-from model_server.model import Model
-from model_server.workflow import Timer
+from extensions.ilastik.models import IlastikPixelClassifierModel, IlastikObjectClassifierModel
+from model_server.accessors import generate_file_accessor, write_accessor_data_to_file
+from model_server.workflows import Timer
 
 from pydantic import BaseModel
 
diff --git a/model_server/image.py b/model_server/accessors.py
similarity index 100%
rename from model_server/image.py
rename to model_server/accessors.py
diff --git a/model_server/model.py b/model_server/models.py
similarity index 96%
rename from model_server/model.py
rename to model_server/models.py
index a2d75c7b..4285b49c 100644
--- a/model_server/model.py
+++ b/model_server/models.py
@@ -4,7 +4,7 @@ import os
 
 import numpy as np
 
-from model_server.image import GenericImageDataAccessor, InMemoryDataAccessor
+from model_server.accessors import GenericImageDataAccessor, InMemoryDataAccessor
 
 
 class Model(ABC):
diff --git a/model_server/session.py b/model_server/session.py
index eb82d1b6..3d5db0bc 100644
--- a/model_server/session.py
+++ b/model_server/session.py
@@ -6,9 +6,9 @@ from time import strftime, localtime
 from typing import Dict
 
 import conf.defaults
-from model_server.model import Model
+from model_server.models import Model
 from model_server.share import SharedImageDirectory
-from model_server.workflow import WorkflowRunRecord
+from model_server.workflows import WorkflowRunRecord
 
 def create_manifest_json():
     pass
@@ -17,9 +17,6 @@ class Session(object):
     """
     Singleton class for a server session that persists data between API calls
     """
-    # inbound = SharedImageDirectory(conf.defaults.paths['inbound_images'])
-    # outbound = SharedImageDirectory(conf.defaults.paths['outbound_images'])
-    # where_records = conf.defaults.paths['logs']
 
     def __new__(cls):
         if not hasattr(cls, 'instance'):
@@ -31,8 +28,6 @@ class Session(object):
         self.models = {} # model_id : model object
         self.manifest = [] # paths to data as well as other metadata from each inference run
         self.paths = self.make_paths(root)
-        # self.session_id = self.create_session_id(self.paths['logs'])
-        # self.session_id = self.create_session_id(self.paths)
         self.session_log = self.paths['logs'] / f'session.log'
         self.log_event('Initialized session')
         self.manifest_json = self.paths['logs'] / f'manifest.json'
diff --git a/model_server/share.py b/model_server/share.py
index e270dea6..fad2b2f0 100644
--- a/model_server/share.py
+++ b/model_server/share.py
@@ -1,3 +1,8 @@
+"""
+Classes that manage data sharing between server and outside processes.  Currently just a directory on a shared
+filesystem; but may expand to include data transfer over API, shared memory objects, etc.
+"""
+
 import os
 import pathlib
 
diff --git a/model_server/workflow.py b/model_server/workflows.py
similarity index 92%
rename from model_server/workflow.py
rename to model_server/workflows.py
index 7c09bc46..c81d2afd 100644
--- a/model_server/workflow.py
+++ b/model_server/workflows.py
@@ -5,8 +5,8 @@ from pathlib import Path
 from time import perf_counter
 from typing import Dict
 
-from model_server.image import generate_file_accessor, write_accessor_data_to_file
-from model_server.model import Model
+from model_server.accessors import generate_file_accessor, write_accessor_data_to_file
+from model_server.models import Model
 
 from pydantic import BaseModel
 
diff --git a/simulate_automic.py b/simulate_automic.py
deleted file mode 100644
index 94e042c8..00000000
--- a/simulate_automic.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from multiprocessing import Process
-import os
-import requests
-import unittest
-
-import uvicorn
-
-import conf.server
-
-# run server in subprocess
-
-host = '127.0.0.1'
-port = 5000
-server_process = Process(
-    target=uvicorn.run,
-    args=('api:app', ),
-    kwargs={'host': host, 'port': port, 'log_level': 'debug'},
-    daemon=True
-)
-uri = f'http://{host}:{port}/'
-server_process.start()
-
-# configure and validate folders etc.
-paths = conf.server.paths
-paths['automic_watch_folder'] = paths['images']['inbound']
-paths['test_source_files'] = ''
-
-# load models by API
-
-# prompt user start AutoMic loop
-
-# move files from one folder to another
-def copy_one_input_image_files(copy=True):
-    pattern = ''
-    os.listdir(paths['test_source_files'])
-
-    # order by increaseing alpha order?  timestamp?
-
-
-    if copy:
-        # copy image from test source files to automic watch folder
-    else:
-        # move them
-
-    # recursive repeat until nothign is left
-
-# point to server session logs
-
-
-# shut down server
-server_process.terminate()
-
-
-# do something with the data?
-
diff --git a/tests/test_api.py b/tests/test_api.py
index 40ecfd29..778c378f 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -4,7 +4,7 @@ import requests
 import unittest
 
 from conf.testing import czifile
-from model_server.model import DummyImageToImageModel
+from model_server.models import DummyImageToImageModel
 
 class TestServerBaseClass(unittest.TestCase):
     def setUp(self) -> None:
diff --git a/tests/test_image.py b/tests/test_image.py
index 6c085b6c..3d590990 100644
--- a/tests/test_image.py
+++ b/tests/test_image.py
@@ -3,7 +3,7 @@ import unittest
 import numpy as np
 
 from conf.testing import czifile, output_path
-from model_server.image import CziImageFileAccessor, DataShapeError, InMemoryDataAccessor, write_accessor_data_to_file
+from model_server.accessors import CziImageFileAccessor, DataShapeError, InMemoryDataAccessor, write_accessor_data_to_file
 
 class TestCziImageFileAccess(unittest.TestCase):
 
diff --git a/tests/test_model.py b/tests/test_model.py
index a265cbe4..661aeadf 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -1,7 +1,7 @@
 import unittest
 from conf.testing import czifile
-from model_server.image import CziImageFileAccessor
-from model_server.model import DummyImageToImageModel, CouldNotLoadModelError
+from model_server.accessors import CziImageFileAccessor
+from model_server.models import DummyImageToImageModel, CouldNotLoadModelError
 
 class TestCziImageFileAccess(unittest.TestCase):
     def setUp(self) -> None:
diff --git a/tests/test_session.py b/tests/test_session.py
index a03e1ad1..fd4b79c9 100644
--- a/tests/test_session.py
+++ b/tests/test_session.py
@@ -1,5 +1,5 @@
 import unittest
-from model_server.model import DummyImageToImageModel
+from model_server.models import DummyImageToImageModel
 from model_server.session import Session
 
 class TestGetSessionObject(unittest.TestCase):
@@ -38,7 +38,7 @@ class TestGetSessionObject(unittest.TestCase):
 
     def test_session_records_workflow(self):
         import json
-        from model_server.workflow import WorkflowRunRecord
+        from model_server.workflows import WorkflowRunRecord
         sesh = Session()
         di = WorkflowRunRecord(
             model_id='test_model',
diff --git a/tests/test_workflow.py b/tests/test_workflow.py
index 6bc8d56d..2cab499d 100644
--- a/tests/test_workflow.py
+++ b/tests/test_workflow.py
@@ -1,8 +1,8 @@
 import unittest
 
 from conf.testing import czifile, output_path
-from model_server.model import DummyImageToImageModel
-from model_server.workflow import infer_image_to_image
+from model_server.models import DummyImageToImageModel
+from model_server.workflows import infer_image_to_image
 
 
 class TestGetSessionObject(unittest.TestCase):
-- 
GitLab