Loading openflexure_microscope/api/app.py +8 −6 Original line number Diff line number Diff line Loading @@ -13,7 +13,8 @@ from openflexure_microscope.api.utilities import list_routes from openflexure_microscope import Microscope from openflexure_microscope.camera.pi import StreamingCamera from openflexure_microscope.stage.openflexure import Stage from openflexure_microscope.stage.sanga import SangaStage from openflexure_microscope.stage.mock import MockStage import atexit import logging Loading Loading @@ -71,11 +72,12 @@ def attach_microscope(): logging.debug("Creating stage object...") try: api_stage = Stage("/dev/ttyUSB0") except SerialException as e: api_camera.close() raise e else: api_stage = SangaStage() except (SerialException, OSError) as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() finally: logging.debug("Attaching devices to microscope...") api_microscope.attach( api_camera, Loading openflexure_microscope/api/exceptions.py +2 −2 Original line number Diff line number Diff line from flask import jsonify from flask import jsonify, escape from werkzeug.exceptions import default_exceptions from werkzeug.exceptions import HTTPException Loading @@ -21,7 +21,7 @@ class JSONExceptionHandler(object): response = { 'status_code': status_code, 'message': message 'message': escape(message) } return jsonify(response), status_code Loading openflexure_microscope/microscope.py +7 −20 Original line number Diff line number Diff line Loading @@ -163,26 +163,10 @@ class Microscope(object): dict: Dictionary containing position data, and :py:attr:`openflexure_microscope.camera.base.BaseCamera.state` """ state = { 'camera': {}, 'stage': {}, 'plugin': {} 'camera': self.camera.state, 'stage': self.stage.state, 'plugin': self.plugin.state } # Add stage position if self.stage: # If stage exists, populate with real values position = self.stage.position else: # Else, zero position = [0, 0, 0] state['stage']['position'] = { 'x': position[0], 'y': position[1], 'z': position[2], } # Add camera state state['camera'] = self.camera.state return state def write_config(self, config: dict): Loading Loading @@ -216,7 +200,10 @@ class Microscope(object): # If attached to a stage if self.stage: if hasattr(self.stage.backlash, 'tolist'): backlash = self.stage.backlash.tolist() else: backlash = self.stage.backlash else: backlash = [0, 0, 0] Loading openflexure_microscope/plugins/loader.py +6 −1 Original line number Diff line number Diff line Loading @@ -131,11 +131,16 @@ class PluginMount(object): self.plugins = [] print("Creating plugin mount") @property def state(self): return [m[0] for m in self.members] @property def members(self): ignores = ['state', 'members', 'attach'] plugin_array = [] for obj_name in dir(self): if not obj_name == "plugins" and not obj_name[:2] == '__': if not obj_name in ignores and not obj_name[:2] == '__': obj = getattr(self, obj_name) if isinstance(obj, MicroscopePlugin): plugin_members = [member for member in inspect.getmembers(obj) if not member[0][:2] == '__'] Loading openflexure_microscope/stage/base.py 0 → 100644 +58 −0 Original line number Diff line number Diff line from abc import ABCMeta, abstractmethod from openflexure_microscope.lock import StrictLock class BaseStage(metaclass=ABCMeta): def __init__(self): self.lock = StrictLock(timeout=5) #: :py:class:`openflexure_microscope.lock.StrictLock`: Strict lock controlling thread access to camera hardware @property @abstractmethod def state(self): """The general state dictionary of the board. Should at least contain 'position', and 'board' keys. Note: A None/Null value for 'board' will disable stage movement in the OpenFlexure eV client software, """ pass @property @abstractmethod def n_axes(self): """The number of axes this stage has.""" pass @property @abstractmethod def position(self): """The current position, as a list""" pass @property @abstractmethod def backlash(self): """Get the distance used for backlash compensation.""" pass @backlash.setter @abstractmethod def backlash(self): """Set the distance used for backlash compensation.""" pass @abstractmethod def move_rel(self, displacement, backlash=True): """Make a relative move, optionally correcting for backlash. displacement: integer or array/list of 3 integers backlash: (default: True) whether to correct for backlash. """ pass @abstractmethod def move_abs(self, final, **kwargs): """Make an absolute move to a position""" pass @abstractmethod def close(self): """Cleanly close communication with the stage""" pass Loading
openflexure_microscope/api/app.py +8 −6 Original line number Diff line number Diff line Loading @@ -13,7 +13,8 @@ from openflexure_microscope.api.utilities import list_routes from openflexure_microscope import Microscope from openflexure_microscope.camera.pi import StreamingCamera from openflexure_microscope.stage.openflexure import Stage from openflexure_microscope.stage.sanga import SangaStage from openflexure_microscope.stage.mock import MockStage import atexit import logging Loading Loading @@ -71,11 +72,12 @@ def attach_microscope(): logging.debug("Creating stage object...") try: api_stage = Stage("/dev/ttyUSB0") except SerialException as e: api_camera.close() raise e else: api_stage = SangaStage() except (SerialException, OSError) as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() finally: logging.debug("Attaching devices to microscope...") api_microscope.attach( api_camera, Loading
openflexure_microscope/api/exceptions.py +2 −2 Original line number Diff line number Diff line from flask import jsonify from flask import jsonify, escape from werkzeug.exceptions import default_exceptions from werkzeug.exceptions import HTTPException Loading @@ -21,7 +21,7 @@ class JSONExceptionHandler(object): response = { 'status_code': status_code, 'message': message 'message': escape(message) } return jsonify(response), status_code Loading
openflexure_microscope/microscope.py +7 −20 Original line number Diff line number Diff line Loading @@ -163,26 +163,10 @@ class Microscope(object): dict: Dictionary containing position data, and :py:attr:`openflexure_microscope.camera.base.BaseCamera.state` """ state = { 'camera': {}, 'stage': {}, 'plugin': {} 'camera': self.camera.state, 'stage': self.stage.state, 'plugin': self.plugin.state } # Add stage position if self.stage: # If stage exists, populate with real values position = self.stage.position else: # Else, zero position = [0, 0, 0] state['stage']['position'] = { 'x': position[0], 'y': position[1], 'z': position[2], } # Add camera state state['camera'] = self.camera.state return state def write_config(self, config: dict): Loading Loading @@ -216,7 +200,10 @@ class Microscope(object): # If attached to a stage if self.stage: if hasattr(self.stage.backlash, 'tolist'): backlash = self.stage.backlash.tolist() else: backlash = self.stage.backlash else: backlash = [0, 0, 0] Loading
openflexure_microscope/plugins/loader.py +6 −1 Original line number Diff line number Diff line Loading @@ -131,11 +131,16 @@ class PluginMount(object): self.plugins = [] print("Creating plugin mount") @property def state(self): return [m[0] for m in self.members] @property def members(self): ignores = ['state', 'members', 'attach'] plugin_array = [] for obj_name in dir(self): if not obj_name == "plugins" and not obj_name[:2] == '__': if not obj_name in ignores and not obj_name[:2] == '__': obj = getattr(self, obj_name) if isinstance(obj, MicroscopePlugin): plugin_members = [member for member in inspect.getmembers(obj) if not member[0][:2] == '__'] Loading
openflexure_microscope/stage/base.py 0 → 100644 +58 −0 Original line number Diff line number Diff line from abc import ABCMeta, abstractmethod from openflexure_microscope.lock import StrictLock class BaseStage(metaclass=ABCMeta): def __init__(self): self.lock = StrictLock(timeout=5) #: :py:class:`openflexure_microscope.lock.StrictLock`: Strict lock controlling thread access to camera hardware @property @abstractmethod def state(self): """The general state dictionary of the board. Should at least contain 'position', and 'board' keys. Note: A None/Null value for 'board' will disable stage movement in the OpenFlexure eV client software, """ pass @property @abstractmethod def n_axes(self): """The number of axes this stage has.""" pass @property @abstractmethod def position(self): """The current position, as a list""" pass @property @abstractmethod def backlash(self): """Get the distance used for backlash compensation.""" pass @backlash.setter @abstractmethod def backlash(self): """Set the distance used for backlash compensation.""" pass @abstractmethod def move_rel(self, displacement, backlash=True): """Make a relative move, optionally correcting for backlash. displacement: integer or array/list of 3 integers backlash: (default: True) whether to correct for backlash. """ pass @abstractmethod def move_abs(self, final, **kwargs): """Make an absolute move to a position""" pass @abstractmethod def close(self): """Cleanly close communication with the stage""" pass