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

Combined stack and tile scans

parent 2cdc20b0
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -10,11 +10,12 @@ class TileScanAPI(MicroscopeViewPlugin):

        # Get params
        name = payload.param('name')
        step_size = payload.param('step_size', default=[2000, 1500], convert=list)
        grid = payload.param('grid', default=[3, 3], convert=list)
        autofocus_dz = payload.param('autofocus_dz', default=20, convert=int)
        step_size = payload.param('step_size', default=[2000, 1500, 100], convert=list)
        grid = payload.param('grid', default=[3, 3, 5], convert=list)
        style = payload.param('style', default='raster', convert=str)
        autofocus_dz = payload.param('autofocus_dz', default=50, convert=int)

        use_video_port = payload.param('use_video_port', default=False, convert=bool)
        use_video_port = payload.param('use_video_port', default=True, convert=bool)
        resize = payload.param('size', default=None)
        if resize:
            if ('width' in resize) and ('height' in resize):
@@ -22,7 +23,7 @@ class TileScanAPI(MicroscopeViewPlugin):
            else:
                abort(404)

        bayer = payload.param('bayer', default=True, convert=bool)
        bayer = payload.param('bayer', default=False, convert=bool)
        metadata = payload.param('metadata', default={}, convert=dict)
        tags = payload.param('tags', default=[], convert=list)

@@ -32,6 +33,7 @@ class TileScanAPI(MicroscopeViewPlugin):
            basename=name,
            step_size=step_size,
            grid=grid,
            style=style,
            autofocus_dz=autofocus_dz,
            use_video_port=use_video_port,
            resize=resize,
+91 −24
Original line number Diff line number Diff line
@@ -2,12 +2,44 @@ import time
import numpy as np
from typing import Tuple
import uuid
import logging

from openflexure_microscope.camera.base import generate_basename
from openflexure_microscope.plugins import MicroscopePlugin

from .api import TileScanAPI, ZStackAPI

def construct_grid(initial, step_sizes, n_steps, style='raster'):
    """
    Given an initial position, step sizes, and number of steps,
    construct a 2-dimensional list of scan x-y positions.
    """
    arr = []

    for i in range(n_steps[0]): # x axis
        arr.append([])
        for j in range(n_steps[1]): # y axis
            # Create a coordinate array
            coord = [initial[ax] + [i, j][ax]*step_sizes[ax] for ax in range(2)]
            # Append coordinate array to position grid
            arr[i].append(tuple(coord))

    # Style modifiers
    if style == 'snake':
        for i, line in enumerate(arr):
            if i % 2 != 0:
                line.reverse()

    return arr

def flatten_grid(grid):
    """
    Convert a 3D list of scan positions into a flat list
    of sequential positions. 
    """

    grid = list(itertools.chain(*grid))
    return grid

class ScanPlugin(MicroscopePlugin):
    """
@@ -61,9 +93,10 @@ class ScanPlugin(MicroscopePlugin):
    def tile(
            self,
            basename: str = None,
            step_size: int = [2000, 1500],
            grid: list = [3, 3],
            autofocus_dz: int = 20,
            step_size: int = [2000, 1500, 100],
            grid: list = [3, 3, 5],
            style='raster',
            autofocus_dz: int = 50,
            use_video_port: bool = False,
            resize: Tuple[int, int] = None,
            bayer: bool = False,
@@ -86,17 +119,38 @@ class ScanPlugin(MicroscopePlugin):
        else:
            autofocus_enabled = False

        xdirection = 1

        with self.microscope.lock:

            for i in range(grid[0]):
                for j in range(grid[1]):
        # Construct an x-y grid (worry about z later)
        x_y_grid = construct_grid(
            initial_position, 
            step_size[:2], 
            grid[:2],
            style=style
        )

        # Now step through each point in the x-y coordinate array
        for line in x_y_grid:
            # If rastering, rather than snake (or eventually spiral)
            if style == 'raster':
                # Return focus to initial position
                logging.debug("Returning to initial z position")
                self.microscope.stage.move_abs([line[0][0], line[0][1], initial_position[2]])

            for x_y in line:
                current_position = self.microscope.stage.position
                # Move to new grid position without changing z
                logging.debug("Moving to step {}".format([x_y[0], x_y[1], current_position[2]]))
                self.microscope.stage.move_abs([x_y[0], x_y[1], current_position[2]])
                # Refocus
                if autofocus_enabled:
                    # TODO: Better autofocus
                    logging.debug("Running autofocus")
                    self.microscope.plugin.default_autofocus.autofocus(
                            range(-2 * autofocus_dz, 3 * autofocus_dz, autofocus_dz))
                        range(-3 * autofocus_dz, 4 * autofocus_dz, autofocus_dz))
                    logging.debug("Finished autofocus")
                    time.sleep(1)  # TODO: Remove

                # If we're not doing a z-stack, just capture
                if (grid[2] <= 1):
                    self.capture(
                        basename,
                        scan_id,
@@ -106,19 +160,28 @@ class ScanPlugin(MicroscopePlugin):
                        metadata=metadata,
                        tags=tags
                    )
                else:
                    logging.debug("Entering z-stack")
                    self.stack(
                        basename=basename,
                        scan_id=scan_id,
                        step_size=step_size[2],
                        steps=grid[2],
                        center=True,
                        use_video_port=use_video_port,
                        resize=resize,
                        bayer=bayer,
                        metadata=metadata,
                        tags=tags
                    )

                    if j != grid[0] - 1:
                        self.microscope.stage.move_rel([step_size[0] * xdirection, 0, 0])

                xdirection *= -1
                if i != grid[1] - 1:
                    self.microscope.stage.move_rel([256 * xdirection, step_size[1], 0])

        logging.debug("Returning to {}".format(initial_position))
        self.microscope.stage.move_abs(initial_position)

    def stack(
            self,
            basename: str = None,
            scan_id: str = None,
            step_size: int = 100,
            steps: int = 5,
            center: bool = True,
@@ -133,6 +196,7 @@ class ScanPlugin(MicroscopePlugin):
            basename = generate_basename()

        # Generate a stack ID
        if not scan_id:
            scan_id = uuid.uuid4().hex

        # Store initial position
@@ -140,12 +204,13 @@ class ScanPlugin(MicroscopePlugin):

        # Move to center scan
        if center:
            logging.debug("Moving to starting position")
            self.microscope.stage.move_rel([0, 0, int((-step_size * steps) / 2)])

        with self.microscope.lock:

            for i in range(steps):

                logging.debug("Capturing...")
                self.capture(
                    basename,
                    scan_id,
@@ -157,6 +222,8 @@ class ScanPlugin(MicroscopePlugin):
                )

                if i != steps - 1:
                    logging.debug("Moving z by {}".format(step_size))
                    self.microscope.stage.move_rel([0, 0, step_size])

            logging.debug("Returning to {}".format(initial_position))
            self.microscope.stage.move_abs(initial_position)