Source code for Cameras.PylablibInterfaceClassDef

# -*- coding: utf-8 -*-

"""
Define class interface of PyLabLib general driver for most of cameras
"""

import numpy as np

from .CameraClassDef import CameraClass

try : 
    from pylablib.devices.interface.camera import ICamera
    from pylablib.core.devio.comm_backend import DeviceError as pllDeviceError
    pylablibDriverInstalled = True
except :
    print('ERROR ! : Tried to load pylablib driver, but it is not installed')
    pylablibDriverInstalled = False


[docs] class PylablibInterfaceClass(CameraClass) : """Parent class for all camera driver classes using pylablib. Used as an interface through ICamera (IROICamera, IExposureCamera + Trigger) interface of pylablib """
[docs] def __init__(self, cameraNumber, triggerMode=0, exposurems=1, gaindB=1, camROI=None, loadDefault = False) : """Initialize the Camera object Args: cameraNumber (int) : index of camera in camerasConfigs list Keyword Args: triggerMode=0 (int) : 0 for hardware/external, 1 for software/internal exposurems=1. (float) : Exposition duration (exposure) in ms. gaindB=0. (float) : hardware gain of the camera in dB. camROI=None (None or [int]*4) : Camera region of interest to read from sensor [x offset , y offset , x size , y size ] (binning is not implemented) loadDefault = True (bool): Decide if default values from cameraConfigs should be set at creation Return: PylablibInterfaceClass camera object """ super().__init__(cameraNumber, triggerMode=triggerMode, exposurems=exposurems, gaindB=gaindB, camROI=camROI, loadDefault=loadDefault) #check if pylablib driver installed, if no return self.cameraDriverInstalled = pylablibDriverInstalled if not(self.cameraDriverInstalled) : print('ERROR ! : pylablib driver is not installed') return # here is the main camera object that will be used to access camera via driver : replaced in children classes self.pylablibCamera = ICamera()
[docs] def __del__(self) : """Delete the Camera object by calling close function Close the Camera and free memory""" if self.pylablibCamera.is_opened() : self.pylablibCamera.stop_acquisition() self.pylablibCamera.close() del(self.pylablibCamera) super().__del__() #ALWAYS call at end of any child class del
[docs] def setTriggerMode(self, triggerMode): """Set the trigger mode Args: triggerMode (int) : 0 for hardware/external, 1 for software/internal """ raise NotImplementedError('Funtion SetTriggerMode not defined')
[docs] def sendSoftwareTrigger(self): """Send a software trigger to the camera to start an exposure""" raise NotImplementedError('Funtion sendSoftwareTrigger not defined')
[docs] def setExposurems(self, exposurems) : """Set the duration of the exposition Args: exposurems (float) : Exposition duration (exposure) in ms. """ self.exposurems = 1e3*self.pylablibCamera.set_exposure(exposurems*1e-3)
[docs] def setGaindB(self, gaindB) : """Set the hardware gain of camera readout Args: gaindB (float) : hardware gain of the camera in dB. """ raise NotImplementedError('Function setGaindB not defined')
[docs] def roundCamROI(self, ROI=None) : """Rounding of ROI values to closest possible one according to camera rules Keyword Args: ROI ( None or [int]*4) : [ x offset, y offset, x size, y size], if None, set to [0, 0, max Width, max height] Return: Camera ROI ([int]*4) : [x offset, y offset, x size, y size] """ xlims,ylims = self.pylablibCamera.get_roi_limits() rules = [xlims[2], ylims[2], xlims[3], ylims[3]] # x offset step, y offset step, x size step, y size step self.wpxmax = xlims[1] self.hpxmax = ylims[1] if ROI is not None: def rounding(a) : val, step = a return int(val - (val % step)) [x,y,w,h] = ROI x = int(max(min(x,self.wpxmax-w), 0)) y = int(max(min(y,self.hpxmax-h), 0)) return map(rounding, zip([x,y,w,h], rules)) else: return [0, 0, self.wpxmax , self.hpxmax]
[docs] def setCamROI(self, ROI=None) : """Set the ROI of camera (without binning) Keyword Args: ROI ( None or [int]*4) : [ x offset, y offset, x size, y size], if None, set to [0, 0, max Width, max height] Return: Camera ROI ([int]*4) : [x offset, y offset, x size, y size] """ [x,y,w,h] = self.roundCamROI(ROI) self.pylablibCamera.set_roi(hstart=x, hend=w, vstart=y, vend=h) x,w,y,h,xbin,ybin = self.pylablibCamera.get_roi() self.wpx = w #width self.hpx = h #height self.camROI = [x,y,w,h] return self.camROI
[docs] def startAcquisition(self): """Start acquisition or restart if already running Defined as function in Icamera interface but require some specific parameters some times""" raise NotImplementedError('Function startAcquisition not defined')
[docs] def clearBuffer(self) : """ Clear camera buffer from images. Use before imaging scans to make sure no previously acquired image is present in buffer""" if not self.pylablibCamera.acquisition_in_progress() : # normally should not happen but if acquisition stopped, restart it self.startAcquisition() while self.pylablibCamera.get_frames_status()[1] > 0 : self._image = self.pylablibCamera.read_oldest_image()
[docs] def grabArray(self) : """Get an image from the camera. Wait for trigger if external or generate one if software. Return: Camera image (numpy 2D array) """ self.imageAcqLastFailed = False try: if not self.pylablibCamera.acquisition_in_progress() : # normally should not happen but if acquisition stopped, restart it self.startAcquisition() if self.triggerMode==1 : self.sendSoftwareTrigger() self.pylablibCamera.wait_for_frame(since="lastread", nframes=1, timeout=self.timeout, error_on_stopped=True) self._image = self.pylablibCamera.read_oldest_image() if self.reversedAxes == [False, False] : self.image = np.array(self._image) elif self.reversedAxes == [True, False] : self.image = np.flip(np.array(self._image) , 1) #X axis is second dimension in image array elif self.reversedAxes == [False, True] : self.image = np.flip(np.array(self._image) , 0) #Y axis is first dimension in image array elif self.reversedAxes == [True, True] : self.image = np.flip(np.array(self._image) , (0,1)) else : self.image = np.array(self._image) print('WARNING ! : \n reversedAxes in camera config is not properly defined as [True/False , True/False] \n Axes unchanged from default [False, False]') except pllDeviceError as ex: print('ERROR ! : Error doc : %s' % ex.__doc__) self.imageAcqLastFailed = True return False return self.image.copy()