Commit 36309417 authored by Joel Collins's avatar Joel Collins
Browse files

Added/updated docs

parent cb441201
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ class BaseCamera(object):
        self.thread = None  #: Background thread reading frames from camera
        self.camera = None  #: Camera object

        self.lock = StrictLock(timeout=1)  #: Strict lock controlling thread access to camera hardware
        self.lock = StrictLock(timeout=1)  #: :py:class:`openflexure_microscope.lock.StrictLock`: Strict lock controlling thread access to camera hardware

        self.frame = None  #: bytes: Current frame is stored here by background thread
        self.last_access = 0  #: time: Time of last client access to the camera
+6 −2
Original line number Diff line number Diff line
@@ -5,13 +5,17 @@ from openflexure_microscope.lock import StrictLock
# TODO: Implement lock on movement
class Stage(OpenFlexureStage):
    def __init__(self, *args, **kwargs):
        self.lock = StrictLock(timeout=2)  #: Strict lock controlling thread access to camera hardware
        """
        Subclass of :py:class:`openflexure_stage.stage.OpenFlexureStage`, 
        adding an instance of :py:class:`openflexure_microscope.lock.StrictLock` to regulate access.
        """
        self.lock = StrictLock(timeout=2)  #: :py:class:`openflexure_microscope.lock.StrictLock`: Strict lock controlling thread access to camera hardware

        OpenFlexureStage.__init__(self, *args, **kwargs)
    
    def _move_rel_nobacklash(self, *args, **kwargs):
        """
        Overrides `OpenFlexureStage._move_rel_nobacklash` to acquire lock first.
        Overrides :py:function:`openflexure_stage.stage.OpenFlexureStage._move_rel_nobacklash` to acquire lock first.
        """
        with self.lock:
            OpenFlexureStage._move_rel_nobacklash(self, *args, **kwargs)
 No newline at end of file
+38 −12
Original line number Diff line number Diff line
@@ -9,19 +9,34 @@ from openflexure_microscope.utilities import entry_by_id

class TaskOrchestrator:
    def __init__(self):
        # List of tasks in the orchestrator
        self.tasks = []
        """
        Class responsible for spawning threaded tasks, and storing their returns.
        A microscope should contain exactly one instance of `TaskOrchestrator`.
        """
        self.tasks = []  #: list: List of `Task` objects

    @property
    def state(self):
        """
        Returns a list of dictionary representations of all tasks in the session.
        """
        return [task.state for task in self.tasks]

    def task_from_id(self, task_id):
    def task_from_id(self, task_id: str):
        """
        Returns a particular task object with the specified `task_id`.
        """
        return entry_by_id(task_id, self.tasks)

    def start(self, function, *args, **kwargs):
    def start(self, function: function, *args, **kwargs):
        """
        Attach and start a new long-running task, if allowed by `start_condition()`.
        Returns an instance of :py:class:`openflexure_microscope.task.Task`, which can be used to check the state
        or eventual return of the task.
    
        Args:
            function (function): The target function to run in the background
            *args, **kwargs: Arguments that will be passed to `function` at runtime.
        """
        # Create a task object
        task = Task(function, *args, **kwargs)
@@ -65,16 +80,18 @@ class TaskOrchestrator:

class Task:
    def __init__(self, task, *args, **kwargs):

        """
        Class responsible for running a task function in a thread, and handling return or errors.
        Tasks should be created by an instance of :py:class:`openflexure_microscope.task.TaskOrchestrator`.
        """
        # The task long-running method
        self.task = task
        self.args = args
        self.kwargs = kwargs
        self.task = task  #: function: Function to be called in the task thread.
        self.args = args  #: Positional arguments to be passed to the task function.
        self.kwargs = kwargs  #: Keyword arguments to be passed to the task function.

        # If task is currently running
        self._running = False
        self._running = False  #: bool: If task is currently running
        
        self.id = uuid.uuid4().hex
        self.id = uuid.uuid4().hex  #: str: Unique ID for the task

        self.state = {
            'id': self.id,
@@ -82,9 +99,12 @@ class Task:
            'return': None,
            'start_time': None,
            'end_time': None,
        }
        }  #: dict: Dictionary describing the full state of the task. `status` will be one of 'idle'', 'running', 'error', or 'success'. `return` eventually holds the return value of the task function.

    def process(self, f):
        """
        Wraps the target function to handle recording `status` and `return` to `state`.
        """
        def wrapped(*args, **kwargs):
            self.state['status'] = 'running'
            try:
@@ -98,12 +118,18 @@ class Task:
        return wrapped

    def run(self):
        """
        Records the task start and end times to `state`, and runs the task wrapped in `process`.
        """
        self.state['start_time'] = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S")
        self.process(self.task)(*self.args, **self.kwargs)
        self._running = False
        self.state['end_time'] = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S")

    def start(self):  # Start and draw
        """
        Spawns a thread, and starts `run()` in that thread.
        """
        # If not already running
        if not self._running:
            self._running = True  # Set start command