Loading openflexure_microscope/api/app.py +28 −49 Original line number Diff line number Diff line Loading @@ -16,25 +16,18 @@ from flask_cors import CORS from openflexure_microscope.api.exceptions import JSONExceptionHandler from openflexure_microscope.api.utilities import list_routes from openflexure_microscope import Microscope from openflexure_microscope.camera.capture import build_captures_from_exif from openflexure_microscope.config import settings_file_path, JSONEncoder from openflexure_microscope.config import ( settings_file_path, JSONEncoder, USER_PLUGINS_PATH, ) from openflexure_microscope.api.v1 import blueprints from openflexure_microscope.api import v2 # Import device modules # NB this will eventually be handled by the RC file, so you can choose what device # class should be attached. try: from openflexure_microscope.camera.pi import PiCameraStreamer except ImportError: logging.warning("Unable to import PiCameraStreamer") from openflexure_microscope.camera.mock import MockStreamer from openflexure_microscope.stage.sanga import SangaStage from openflexure_microscope.stage.mock import MockStage from openflexure_microscope.common.labthings import LabThing from openflexure_microscope.common.labthings.plugins import find_plugins from openflexure_microscope.api.microscope import default_microscope as api_microscope # Handle logging is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "") Loading @@ -54,7 +47,7 @@ else: ) rotating_logfile = logging.handlers.RotatingFileHandler( DEFAULT_LOGFILE, maxBytes=1000000, backupCount=7 DEFAULT_LOGFILE, maxBytes=1_000_000, backupCount=7 ) error_handlers = [rotating_logfile, logging.StreamHandler()] Loading @@ -65,39 +58,6 @@ else: root.setLevel(logging.getLogger("gunicorn.error").level) # Create a dummy microscope object, with no hardware attachments api_microscope = Microscope() # Initialise camera logging.debug("Creating camera object...") try: api_camera = PiCameraStreamer() except Exception as e: logging.error(e) logging.warning("No valid camera hardware found. Falling back to mock camera!") api_camera = MockStreamer() # Initialise stage logging.debug("Creating stage object...") try: api_stage = SangaStage() except Exception as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() # Attach devices to microscope logging.debug("Attaching devices to microscope...") api_microscope.attach(api_camera, api_stage) # Restore loaded capture array to camera object logging.debug("Restoring captures...") api_microscope.camera.images = build_captures_from_exif( api_microscope.camera.paths["default"] ) logging.debug("Microscope successfully attached!") # Generate API URI based on version from filename def uri(suffix, api_version, base=None): Loading @@ -121,6 +81,10 @@ CORS(app, resources=r"*") # Make errors more API friendly handler = JSONExceptionHandler(app) # Attach lab devices labthing = LabThing(app) labthing.register_device(api_microscope, "openflexure_microscope") # WEBAPP ROUTES # Base routes Loading Loading @@ -176,6 +140,21 @@ v2_actions_blueprint = v2.blueprints.actions.construct_blueprint(api_microscope) app.register_blueprint(v2_actions_blueprint, url_prefix=uri("/actions", "v2")) plugins = find_plugins(USER_PLUGINS_PATH) print(plugins.__plugins__) for plugin_obj in plugins.__plugins__: for plugin_view_id, plugin_view in plugin_obj.views.items(): # Add route to the plugins blueprint app.add_url_rule( "/new-plugins" + plugin_view["rule"], view_func=plugin_view["view"].as_view( f"{plugin_obj._name_python_safe}_{plugin_view_id}" ), **plugin_view["kwargs"], ) @app.route("/routes") def routes(): """ Loading openflexure_microscope/api/microscope.py 0 → 100644 +48 −0 Original line number Diff line number Diff line from openflexure_microscope import Microscope from openflexure_microscope.camera.capture import build_captures_from_exif import logging # Import device modules # NB this will eventually be handled by the RC file, so you can choose what device # class should be attached. try: from openflexure_microscope.camera.pi import PiCameraStreamer except ImportError: logging.warning("Unable to import PiCameraStreamer") from openflexure_microscope.camera.mock import MockStreamer from openflexure_microscope.stage.sanga import SangaStage from openflexure_microscope.stage.mock import MockStage default_microscope = Microscope() # Initialise camera logging.debug("Creating camera object...") try: api_camera = PiCameraStreamer() except Exception as e: logging.error(e) logging.warning("No valid camera hardware found. Falling back to mock camera!") api_camera = MockStreamer() # Initialise stage logging.debug("Creating stage object...") try: api_stage = SangaStage() except Exception as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() # Attach devices to microscope logging.debug("Attaching devices to microscope...") default_microscope.attach(api_camera, api_stage) # Restore loaded capture array to camera object logging.debug("Restoring captures...") default_microscope.camera.images = build_captures_from_exif( default_microscope.camera.paths["default"] ) logging.debug("Microscope successfully attached!") openflexure_microscope/common/__init__.py +1 −0 Original line number Diff line number Diff line from . import tasks, labthings openflexure_microscope/common/labthings/__init__.py 0 → 100644 +37 −0 Original line number Diff line number Diff line from flask import current_app, _app_ctx_stack EXTENSION_NAME = "flask-lab" class LabThing(object): def __init__(self, app=None): self.app = app self.devices = {} if app is not None: self.init_app(app) def init_app(self, app): app.teardown_appcontext(self.teardown) app.extensions = getattr(app, "extensions", {}) app.extensions[EXTENSION_NAME] = self def teardown(self, exception): print(f"Tearing down devices: {self.devices}") def register_device(self, device_object, device_name: str): self.devices[device_name] = device_object def find_device(device_name): app = current_app if not app: return None pylot_instance = app.extensions[EXTENSION_NAME] if device_name in pylot_instance.devices: return pylot_instance.devices[device_name] else: return None openflexure_microscope/common/labthings/fields.py 0 → 100644 +0 −0 Empty file added. Loading
openflexure_microscope/api/app.py +28 −49 Original line number Diff line number Diff line Loading @@ -16,25 +16,18 @@ from flask_cors import CORS from openflexure_microscope.api.exceptions import JSONExceptionHandler from openflexure_microscope.api.utilities import list_routes from openflexure_microscope import Microscope from openflexure_microscope.camera.capture import build_captures_from_exif from openflexure_microscope.config import settings_file_path, JSONEncoder from openflexure_microscope.config import ( settings_file_path, JSONEncoder, USER_PLUGINS_PATH, ) from openflexure_microscope.api.v1 import blueprints from openflexure_microscope.api import v2 # Import device modules # NB this will eventually be handled by the RC file, so you can choose what device # class should be attached. try: from openflexure_microscope.camera.pi import PiCameraStreamer except ImportError: logging.warning("Unable to import PiCameraStreamer") from openflexure_microscope.camera.mock import MockStreamer from openflexure_microscope.stage.sanga import SangaStage from openflexure_microscope.stage.mock import MockStage from openflexure_microscope.common.labthings import LabThing from openflexure_microscope.common.labthings.plugins import find_plugins from openflexure_microscope.api.microscope import default_microscope as api_microscope # Handle logging is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "") Loading @@ -54,7 +47,7 @@ else: ) rotating_logfile = logging.handlers.RotatingFileHandler( DEFAULT_LOGFILE, maxBytes=1000000, backupCount=7 DEFAULT_LOGFILE, maxBytes=1_000_000, backupCount=7 ) error_handlers = [rotating_logfile, logging.StreamHandler()] Loading @@ -65,39 +58,6 @@ else: root.setLevel(logging.getLogger("gunicorn.error").level) # Create a dummy microscope object, with no hardware attachments api_microscope = Microscope() # Initialise camera logging.debug("Creating camera object...") try: api_camera = PiCameraStreamer() except Exception as e: logging.error(e) logging.warning("No valid camera hardware found. Falling back to mock camera!") api_camera = MockStreamer() # Initialise stage logging.debug("Creating stage object...") try: api_stage = SangaStage() except Exception as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() # Attach devices to microscope logging.debug("Attaching devices to microscope...") api_microscope.attach(api_camera, api_stage) # Restore loaded capture array to camera object logging.debug("Restoring captures...") api_microscope.camera.images = build_captures_from_exif( api_microscope.camera.paths["default"] ) logging.debug("Microscope successfully attached!") # Generate API URI based on version from filename def uri(suffix, api_version, base=None): Loading @@ -121,6 +81,10 @@ CORS(app, resources=r"*") # Make errors more API friendly handler = JSONExceptionHandler(app) # Attach lab devices labthing = LabThing(app) labthing.register_device(api_microscope, "openflexure_microscope") # WEBAPP ROUTES # Base routes Loading Loading @@ -176,6 +140,21 @@ v2_actions_blueprint = v2.blueprints.actions.construct_blueprint(api_microscope) app.register_blueprint(v2_actions_blueprint, url_prefix=uri("/actions", "v2")) plugins = find_plugins(USER_PLUGINS_PATH) print(plugins.__plugins__) for plugin_obj in plugins.__plugins__: for plugin_view_id, plugin_view in plugin_obj.views.items(): # Add route to the plugins blueprint app.add_url_rule( "/new-plugins" + plugin_view["rule"], view_func=plugin_view["view"].as_view( f"{plugin_obj._name_python_safe}_{plugin_view_id}" ), **plugin_view["kwargs"], ) @app.route("/routes") def routes(): """ Loading
openflexure_microscope/api/microscope.py 0 → 100644 +48 −0 Original line number Diff line number Diff line from openflexure_microscope import Microscope from openflexure_microscope.camera.capture import build_captures_from_exif import logging # Import device modules # NB this will eventually be handled by the RC file, so you can choose what device # class should be attached. try: from openflexure_microscope.camera.pi import PiCameraStreamer except ImportError: logging.warning("Unable to import PiCameraStreamer") from openflexure_microscope.camera.mock import MockStreamer from openflexure_microscope.stage.sanga import SangaStage from openflexure_microscope.stage.mock import MockStage default_microscope = Microscope() # Initialise camera logging.debug("Creating camera object...") try: api_camera = PiCameraStreamer() except Exception as e: logging.error(e) logging.warning("No valid camera hardware found. Falling back to mock camera!") api_camera = MockStreamer() # Initialise stage logging.debug("Creating stage object...") try: api_stage = SangaStage() except Exception as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() # Attach devices to microscope logging.debug("Attaching devices to microscope...") default_microscope.attach(api_camera, api_stage) # Restore loaded capture array to camera object logging.debug("Restoring captures...") default_microscope.camera.images = build_captures_from_exif( default_microscope.camera.paths["default"] ) logging.debug("Microscope successfully attached!")
openflexure_microscope/common/__init__.py +1 −0 Original line number Diff line number Diff line from . import tasks, labthings
openflexure_microscope/common/labthings/__init__.py 0 → 100644 +37 −0 Original line number Diff line number Diff line from flask import current_app, _app_ctx_stack EXTENSION_NAME = "flask-lab" class LabThing(object): def __init__(self, app=None): self.app = app self.devices = {} if app is not None: self.init_app(app) def init_app(self, app): app.teardown_appcontext(self.teardown) app.extensions = getattr(app, "extensions", {}) app.extensions[EXTENSION_NAME] = self def teardown(self, exception): print(f"Tearing down devices: {self.devices}") def register_device(self, device_object, device_name: str): self.devices[device_name] = device_object def find_device(device_name): app = current_app if not app: return None pylot_instance = app.extensions[EXTENSION_NAME] if device_name in pylot_instance.devices: return pylot_instance.devices[device_name] else: return None