Source code for holypipette.devices.manipulator.microscope

'''
A microscope is a manipulator with a single axis.
With methods to take a stack of images, autofocus, etc.

TODO:
* a umanager class that autoconfigures with umanager config file
* steps for stack acquisition?
'''
from holypipette.devices.manipulator import *
import time
import warnings
try:
    import cv2
except:
    warnings.warn('OpenCV not available')

__all__ = ['Microscope']

[docs]class Microscope(Manipulator): ''' A microscope Z axis, obtained here from an axis of a Manipulator. ''' def __init__(self, dev, axis): ''' Parameters ---------- dev : underlying device axis : axis index ''' Manipulator.__init__(self) self.dev = dev self.axis = axis self.up_direction = None # Up direction, must be provided or calculated self.floor_Z = None # This is the Z coordinate of the coverslip # Motor range in um; by default +- one meter self.min = -1e6 # This could replace floor_Z self.max = 1e6
[docs] def position(self): ''' Current position Returns ------- The current position of the device axis in um. ''' return self.dev.position(self.axis)
[docs] def absolute_move(self, x): ''' Moves the device axis to position x in um. Parameters ---------- x : target position in um. ''' self.dev.absolute_move(x, self.axis) self.sleep(.05)
[docs] def relative_move(self, x): ''' Moves the device axis by relative amount x in um. Parameters ---------- x : position shift in um. ''' self.dev.relative_move(x, self.axis) self.sleep(.05)
[docs] def step_move(self, distance): self.dev.step_move(distance, self.axis)
[docs] def stop(self): """ Stop current movements. """ self.dev.stop(self.axis)
[docs] def wait_until_still(self): """ Waits for the motors to stop. """ self.dev.wait_until_still([self.axis]) self.sleep(.05)
[docs] def stack(self, camera, z, preprocessing=lambda img:img, save = None, pause = 0.3): ''' Take a stack of images at the positions given in the z list Parameters ---------- camera : a camera, eg with a snap() method z : A list of z positions preprocessing : a function that processes the images (optional) save : saves images to disk if True pause : pause in second after each movement ''' position = self.position() images = [] current_z = position for k,zi in enumerate(z): #self.absolute_move(zi) self.relative_move(zi-current_z) current_z = zi self.wait_until_still() # We wait a little bit because there might be mechanical oscillations time.sleep(pause) # also make sure the camera is in sync img = preprocessing(camera.snap()) images.append(img) if save is not None: cv2.imwrite('./screenshots/'+save+'{}.jpg'.format(k), img) self.absolute_move(position) self.wait_until_still() return images
[docs] def save_configuration(self): ''' Outputs configuration in a dictionary. ''' config = {'up_direction' : self.up_direction, 'floor_Z' : self.floor_Z} return config
[docs] def load_configuration(self, config): ''' Loads configuration from dictionary config. Variables not present in the dictionary are untouched. ''' self.up_direction = config.get('up_direction', self.up_direction)
#self.floor_Z = config.get('floor_Z', self.floor_Z)