Exemple #1
0
    def __init__(self, deviceManager, config, name):
        Device.__init__(self, deviceManager, config, name)
        OptomechDevice.__init__(self, deviceManager, config, name)
        self._scopeDev = deviceManager.getDevice(config['scopeDevice'])
        self._stageOrientation = {'angle': 0, 'inverty': False}
        self._opts = {
            'searchHeight': config.get('searchHeight', 2e-3),
            'searchTipHeight': config.get('searchTipHeight', 1.5e-3),
            'approachHeight': config.get('approachHeight', 100e-6),
            'idleHeight': config.get('idleHeight', 1e-3),
            'idleDistance': config.get('idleDistance', 7e-3),
            'showCameraModuleUI': config.get('showCameraModuleUI', True),
        }
        parent = self.parentDevice()
        if not isinstance(parent, Stage):
            raise Exception(
                "Pipette device requires some type of translation stage as its parent."
            )
        self.pitch = parent.pitch * np.pi / 180.
        self._camInterfaces = weakref.WeakKeyDictionary()

        self.target = None

        cal = self.readConfigFile('calibration')
        if cal != {}:
            self.setStageOrientation(cal['angle'], cal['inverty'])
            self.setDeviceTransform(cal['transform'])

        self.tracker = PipetteTracker(self)
        deviceManager.declareInterface(name, ['pipette'], self)
Exemple #2
0
 def __init__(self, dm, config, name):
     self.omConf = {}
     for k in ['parentDevice', 'transform']:
         if k in config:
             self.omConf[k] = config.pop(k)
     OptomechDevice.__init__(self, dm, config, name)
     DAQGeneric.__init__(self, dm, config, name)
Exemple #3
0
    def __init__(self, manager, config, name):
        self.config = config
        self.manager = manager
        self.hasPowerIndicator = False
        self.hasShutter = False
        self.hasTriggerableShutter = False
        self.hasQSwitch = False
        self.hasPCell = False
        self.hasTunableWavelength = False

        self.params = {
            'expectedPower': config.get('power', None),  ## Expected output
            'currentPower': None,  ## Last measured output power
            'scopeTransmission':
            None,  ## percentage of output power that is transmitted to slice
            'tolerance': 10.0,  ## in %
            'useExpectedPower': True,
            'powerAlert':
            True  ## set True if you want changes in output power to raise an error
        }

        daqConfig = {
        }  ### DAQ generic needs to know about powerIndicator, pCell, shutter, qswitch
        if 'powerIndicator' in config:
            self.hasPowerIndicator = True
            #### name of powerIndicator is config['powerIndicator']['channel'][0]
            #daqConfig['powerInd'] = {'channel': config['powerIndicator']['channel'], 'type': 'ai'}
        if 'shutter' in config:
            daqConfig['shutter'] = config['shutter']
            self.hasTriggerableShutter = True
            self.hasShutter = True
        if 'qSwitch' in config:
            daqConfig['qSwitch'] = config['qSwitch']
            self.hasQSwitch = True
        if 'pCell' in config:
            daqConfig['pCell'] = config['pCell']
            self.hasPCell = True

        daqConfig['power'] = {
            'type': 'ao',
            'units': 'W'
        }  ## virtual channel used for creating control widgets
        DAQGeneric.__init__(self, manager, daqConfig, name)
        OptomechDevice.__init__(self, manager, config, name)

        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.variableLock = Mutex(QtCore.QMutex.Recursive)
        self.calibrationIndex = None
        self.pCellCalibration = None
        self.getPowerHistory()

        #self.scope = manager.getDevice(self.config['scope'])
        #self.scope.sigObjectiveChanged.connect(self.objectiveChanged)
        self.sigGlobalSubdeviceChanged.connect(
            self.opticStateChanged
        )  ## called when objectives/filters have been switched

        manager.declareInterface(name, ['laser'], self)
        manager.sigAbortAll.connect(self.closeShutter)
Exemple #4
0
 def __init__(self, manager, config, name):
     self.config = config
     self.manager = manager
     self.hasPowerIndicator = False
     self.hasShutter = False
     self.hasTriggerableShutter = False
     self.hasQSwitch = False
     self.hasPCell = False
     self.hasTunableWavelength = False
     
     self.params = {
         'expectedPower': config.get('power', None), ## Expected output
         'currentPower': None, ## Last measured output power
         'scopeTransmission': None, ## percentage of output power that is transmitted to slice
         'tolerance': 10.0, ## in %
         'useExpectedPower': True,
         'powerAlert': True ## set True if you want changes in output power to raise an error
         }
     
     daqConfig = {} ### DAQ generic needs to know about powerIndicator, pCell, shutter, qswitch
     if 'powerIndicator' in config:
         self.hasPowerIndicator = True
         #### name of powerIndicator is config['powerIndicator']['channel'][0]
         #daqConfig['powerInd'] = {'channel': config['powerIndicator']['channel'], 'type': 'ai'}
     if 'shutter' in config:
         daqConfig['shutter'] = config['shutter']
         self.hasTriggerableShutter = True
         self.hasShutter = True
     if 'qSwitch' in config:
         daqConfig['qSwitch'] = config['qSwitch']
         self.hasQSwitch = True
     if 'pCell' in config:
         daqConfig['pCell'] = config['pCell']
         self.hasPCell = True
                     
     daqConfig['power'] = {'type': 'ao', 'units': 'W'}  ## virtual channel used for creating control widgets
     DAQGeneric.__init__(self, manager, daqConfig, name)
     OptomechDevice.__init__(self, manager, config, name)
    
     self._configDir = os.path.join('devices', self.name() + '_config')
     self.lock = Mutex(QtCore.QMutex.Recursive)
     self.variableLock = Mutex(QtCore.QMutex.Recursive)
     self.calibrationIndex = None
     self.pCellCalibration = None
     self.getPowerHistory()
     
     #self.scope = manager.getDevice(self.config['scope'])
     #self.scope.sigObjectiveChanged.connect(self.objectiveChanged)
     self.sigGlobalSubdeviceChanged.connect(self.opticStateChanged) ## called when objectives/filters have been switched
     
     manager.declareInterface(name, ['laser'], self)
Exemple #5
0
    def __init__(self, config, fw, key):
        self._config = config
        self._fw = fw
        self._key = key
        #print config, key
        key = str(key)
        if key in config:
            name = '%s-%s' % ((int(key) + 1), config[key]['name'])
            self._description = config[key]['description']
        else:
            name = '%s-%s' % ((int(key) + 1), 'empty')
            self._description = '-'

        OptomechDevice.__init__(self, fw.dm, {}, name)
Exemple #6
0
 def __init__(self, dm, config, name):
     Device.__init__(self, dm, config, name)
     OptomechDevice.__init__(self, dm, config, name)
     
     self.config = config
     self.lock = Mutex(QtCore.QMutex.Recursive)
     self.devGui = None
     self.lastRunTime = None
     self.calibrationIndex = None
     self.targetList = [1.0, {}]  ## stores the grids and points used by TaskGui so that they persist
     self.currentCommand = [0,0] ## The last requested voltage values (but not necessarily the current voltage applied to the mirrors)
     self.currentVoltage = [0, 0]
     self.shutterOpen = True ## indicates whether the virtual shutter is closed (the beam is steered to its 'off' position).
     if 'offVoltage' in config:
         self.setShutterOpen(False)
     dm.declareInterface(name, ['scanner'], self)
Exemple #7
0
    def __init__(self, dm, config, name):

        Device.__init__(self, dm, config, name)
        OptomechDevice.__init__(self, dm, config, name)

        self.scopeDev = None
        self.currentFilter = None
        p = self
        while p is not None:
            p = p.parentDevice()
            if isinstance(p, Microscope):
                self.scopeDev = p

        self.port = config[
            'port']  ## windows com ports start at COM1, pyserial ports start at 0
        self.baud = config.get('baud', 115200)
        #self.positionLabels = config.get('postionLabels')

        self.driver = FilterWheelDriver(self.port, self.baud)
        self.driverLock = Mutex(
            QtCore.QMutex.Recursive)  ## access to low level driver calls
        self.filterWheelLock = Mutex(
            QtCore.QMutex.Recursive)  ## access to self.attributes

        self.filters = OrderedDict()
        ## Format of self.filters is:
        ## {
        ##    filterWheelPosition1: {filterName: filter},
        ##    filterWheelPosition2: {filterName: filter},
        ## }
        nPos = self.getPositionCount()
        for k in range(nPos):  ## Set value for each filter
            filt = Filter(config['filters'], self, k)
            self.filters[k] = filt

        #print self.filters.values()
        #print self.filters[1].name(), self.filters[1].description()
        #if len(self.positionLabels) != self.getPositionCount():
        #    raise Exception("Number of FilterWheel positions %s must correspond to number of labels!" % self.getPositionCount())

        with self.driverLock:
            self.currentFWPosition = self.driver.getPos()
            self.currentFilter = self.getFilter()

        self.fwThread = FilterWheelThread(self, self.driver, self.driverLock)
        self.fwThread.fwPosChanged.connect(self.positionChanged)
        self.fwThread.start()
Exemple #8
0
 def __init__(self, dm, config, name):
     Device.__init__(self, dm, config, name)
     OptomechDevice.__init__(self, dm, config, name)
     
     self.config = config
     self.lock = Mutex(QtCore.QMutex.Recursive)
     self.devGui = None
     self.lastRunTime = None
     self.calibrationIndex = None
     self.targetList = [1.0, {}]  ## stores the grids and points used by TaskGui so that they persist
     self._configDir = os.path.join('devices', self.name() + '_config')
     self.currentCommand = [0,0] ## The last requested voltage values (but not necessarily the current voltage applied to the mirrors)
     self.currentVoltage = [0, 0]
     self.shutterOpen = True ## indicates whether the virtual shutter is closed (the beam is steered to its 'off' position).
     if 'offVoltage' in config:
         self.setShutterOpen(False)
     dm.declareInterface(name, ['scanner'], self)
Exemple #9
0
    def __init__(self, deviceManager, config, name):
        Device.__init__(self, deviceManager, config, name)
        OptomechDevice.__init__(self, deviceManager, config, name)
        self._scopeDev = deviceManager.getDevice(config['scopeDevice'])
        self._stageOrientation = {'angle': 0, 'inverty': False}
        self._opts = {
            'searchHeight': config.get('searchHeight', 2e-3),
            'searchTipHeight': config.get('searchTipHeight', 1.5e-3),
            'approachHeight': config.get('approachHeight', 100e-6),
            'idleHeight': config.get('idleHeight', 1e-3),
            'idleDistance': config.get('idleDistance', 7e-3),
        }
        parent = self.parentDevice()
        assert isinstance(parent, Stage)
        self.pitch = parent.pitch * np.pi / 180.

        cal = self.readConfigFile('calibration')
        if cal != {}:
            self.setStageOrientation(cal['angle'], cal['inverty'])
            self.setDeviceTransform(cal['transform'])

        self.tracker = PipetteTracker(self)
Exemple #10
0
    def __init__(self, dm, config, name):
        OptomechDevice.__init__(self, dm, config, name)

        self.lock = Mutex(Mutex.Recursive)

        # Generate config to use for DAQ
        daqConfig = {}
        if 'exposeChannel' in config:
            daqConfig['exposure'] = config['exposeChannel']
        if 'triggerInChannel' in config:
            daqConfig['trigger'] = config['triggerInChannel']
        DAQGeneric.__init__(self, dm, daqConfig, name)

        self.camConfig = config
        self.stateStack = []

        if 'scaleFactor' not in self.camConfig:
            self.camConfig['scaleFactor'] = [1., 1.]

        ## Default values for scope state. These will be used if there is no scope defined.
        self.scopeState = {
            'id': 0,
        }

        self.scopeDev = None
        p = self
        while p is not None:
            p = p.parentDevice()
            if isinstance(p, Microscope):
                self.scopeDev = p
                self.scopeDev.sigObjectiveChanged.connect(
                    self.objectiveChanged)
                break

        self.transformChanged()
        if self.scopeDev is not None:
            self.objectiveChanged()

        self.setupCamera()
        #print "Camera: setupCamera returned, about to create acqThread"
        self.sensorSize = self.getParam('sensorSize')
        tr = pg.SRTTransform3D()
        tr.translate(-self.sensorSize[0] * 0.5, -self.sensorSize[1] * 0.5)
        self.setDeviceTransform(self.deviceTransform() * tr)

        self.acqThread = AcquireThread(self)
        #print "Camera: acqThread created, about to connect signals."
        self.acqThread.finished.connect(self.acqThreadFinished)
        self.acqThread.started.connect(self.acqThreadStarted)
        self.acqThread.sigShowMessage.connect(self.showMessage)
        self.acqThread.sigNewFrame.connect(self.newFrame)
        #print "Camera: signals connected:"

        self.sigGlobalTransformChanged.connect(self.transformChanged)

        if config != None:
            # look for 'defaults', then 'params' to preserve backward compatibility.
            defaults = config.get('defaults', config.get('params', {}))
            #print "Camera: setting configuration params."
            try:
                self.setParams(defaults)
            except:
                printExc("Error default setting camera parameters:")
        #print "Camera: no config params to set."
        dm.declareInterface(name, ['camera'], self)
Exemple #11
0
    def setDeviceTransform(self, tr):
        OptomechDevice.setDeviceTransform(self, tr)

        cal = self.readConfigFile('calibration')
        cal['transform'] = pg.SRTTransform3D(tr)
        self.writeConfigFile(cal, 'calibration')
Exemple #12
0
    def __init__(self, dm, config, name):
        OptomechDevice.__init__(self, dm, config, name)
        
        self.lock = Mutex(Mutex.Recursive)
        
        # Generate config to use for DAQ 
        daqConfig = {}
        if 'exposeChannel' in config:
            daqConfig['exposure'] = config['exposeChannel']
        if 'triggerInChannel' in config:
            daqConfig['trigger'] = config['triggerInChannel']
        DAQGeneric.__init__(self, dm, daqConfig, name)
        
        self.camConfig = config
        self.stateStack = []
        
        
        if 'scaleFactor' not in self.camConfig:
            self.camConfig['scaleFactor'] = [1., 1.]
        
        ## Default values for scope state. These will be used if there is no scope defined.
        self.scopeState = {
            'id': 0,
            #'scopePosition': [0, 0],   ## position of scope in global coords
            #'centerPosition': [0, 0],  ## position of objective in global coords (objective may be offset from center of scope)
            #'offset': [0, 0],
            #'objScale': 1,
            #'pixelSize': (1, 1),
            #'objective': '',
            #'transform': None,
        }
        

        self.scopeDev = None
        p = self
        while p is not None:
            p = p.parentDevice()
            if isinstance(p, Microscope):
                self.scopeDev = p
                self.scopeDev.sigObjectiveChanged.connect(self.objectiveChanged)
                break
        
        #if 'scopeDevice' in config:
            #self.scopeDev = self.dm.getDevice(config['scopeDevice'])
            #self.scopeDev.sigPositionChanged.connect(self.positionChanged)
            ### Cache microscope state for fast access later
            #self.objectiveChanged()
            #self.positionChanged()
        #else:
            #self.scopeDev = None
        self.transformChanged()
        if self.scopeDev is not None:
            self.objectiveChanged()
        
        
        self.setupCamera() 
        #print "Camera: setupCamera returned, about to create acqThread"
        self.sensorSize = self.getParam('sensorSize')
        tr = pg.SRTTransform3D()
        tr.translate(-self.sensorSize[0]*0.5, -self.sensorSize[1]*0.5)
        self.setDeviceTransform(self.deviceTransform() * tr)
        
        
        self.acqThread = AcquireThread(self)
        #print "Camera: acqThread created, about to connect signals."
        self.acqThread.finished.connect(self.acqThreadFinished)
        self.acqThread.started.connect(self.acqThreadStarted)
        self.acqThread.sigShowMessage.connect(self.showMessage)
        self.acqThread.sigNewFrame.connect(self.newFrame)
        #print "Camera: signals connected:"
        
        self.sigGlobalTransformChanged.connect(self.transformChanged)
        
        if config != None:
            # look for 'defaults', then 'params' to preserve backward compatibility.
            defaults = config.get('defaults', config.get('params', {}))
            #print "Camera: setting configuration params."
            try:
                self.setParams(defaults)
            except:
                printExc("Error default setting camera parameters:")
        #print "Camera: no config params to set."
        dm.declareInterface(name, ['camera'], self)
Exemple #13
0
    def __init__(self, dm, config, name):

        Device.__init__(self, dm, config, name)

        self.lock = Mutex(QtCore.QMutex.Recursive)

        self._filters = OrderedDict()
        self._slotNames = OrderedDict()
        self._slotIndicators = OrderedDict()

        nPos = self.getPositionCount()
        ports = config.get('ports', None)
        for k in range(nPos):  ## Set value for each filter
            slot = config['slots'].get(str(k))
            if slot is None:
                self._filters[k] = None
                self._slotNames[k] = "empty"
                continue

            if isinstance(slot, str):
                # We are only naming this slot; no actual filter device is defined here
                self._filters[k] = None
                self._slotNames[k] = slot
            elif isinstance(slot, dict):
                filtname = slot['device']
                filt = dm.getDevice(filtname)
                self._filters[k] = filt
                self._slotNames[k] = slot.get('name', filt.name())
                devports = filt.ports()
                if ports is None:
                    ports = devports
                elif set(ports) != set(devports):
                    raise Exception(
                        "FilterSet %r does not have the expected ports (%r vs %r)"
                        % (filt, devports, ports))
            else:
                raise TypeError(
                    "Slot definition must be str or dict; got: %r" % slot)

            if 'hotkey' in slot:
                dev = dm.getDevice(slot['hotkey']['device'])
                key = slot['hotkey']['key']
                dev.addKeyCallback(key, self._hotkeyPressed, (k, ))
                self._slotIndicators[k] = (dev, key)
                # todo: connect to key

        config['ports'] = ports

        OptomechDevice.__init__(self, dm, config, name)

        self._lastFuture = None
        self._lastPosition = None

        # polling thread just checks position regularly; this causes sigFilterChanged to be emitted
        # whenever a change is detected
        pollInterval = config.get('pollInterval', 0.1)
        if pollInterval is not None:
            self.fwThread = FilterWheelPollThread(self, interval=pollInterval)
            self.fwThread.start()

        dm.sigAbortAll.connect(self.stop)

        if 'initialSlot' in config:
            self.setPosition(config['initialSlot'])