示例#1
0
class CoherentThread(QtCore.QThread):

    sigPowerChanged = QtCore.Signal(object)
    sigWavelengthChanged = QtCore.Signal(object)
    sigError = QtCore.Signal(object)

    def __init__(self, dev, driver, lock):
        QtCore.QThread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.dev = dev
        self.driver = driver
        self.driverLock = lock
        self.cmds = {}
        
        
    def setWavelength(self, wl):
        pass
        
    def setShutter(self, opened):
        wait = QtCore.QWaitCondition()
        cmd = ['setShutter', opened]
        with self.lock:
            self.cmds.append(cmd)
            
        
        
    def run(self):
        self.stopThread = False
        with self.driverLock:
            self.sigWavelengthChanged.emit(self.driver.getWavelength()*1e-9)
        while True:
            try:
                with self.driverLock:
                    power = self.driver.getPower() * 1e-3
                    wl = self.driver.getWavelength()*1e-9
                self.sigPowerChanged.emit(power)
                self.sigWavelengthChanged.emit(wl)
                time.sleep(0.5)
            except:
                debug.printExc("Error in Coherent laser communication thread:")
                
            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(0.02)


        self.driver.close()

    def stop(self, block=False):
        with self.lock:
            self.stopThread = True
        if block:
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
示例#2
0
class CoherentThread(Thread):

    sigPowerChanged = QtCore.Signal(object)
    sigWavelengthChanged = QtCore.Signal(object)
    sigError = QtCore.Signal(object)

    def __init__(self, dev, driver, lock):
        Thread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.dev = dev
        self.driver = driver
        self.driverLock = lock
        self.cmds = {}

    def setWavelength(self, wl):
        pass

    def setShutter(self, opened):
        wait = QtCore.QWaitCondition()
        cmd = ['setShutter', opened]
        with self.lock:
            self.cmds.append(cmd)

    def run(self):
        self.stopThread = False
        with self.driverLock:
            self.sigWavelengthChanged.emit(self.driver.getWavelength() * 1e-9)
        while True:
            try:
                with self.driverLock:
                    power = self.driver.getPower() * 1e-3
                    wl = self.driver.getWavelength() * 1e-9
                self.sigPowerChanged.emit(power)
                self.sigWavelengthChanged.emit(wl)
                time.sleep(0.5)
            except:
                debug.printExc("Error in Coherent laser communication thread:")

            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(0.02)

        self.driver.close()

    def stop(self, block=False):
        with self.lock:
            self.stopThread = True
        if block:
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
示例#3
0
class FilterWheelThread(Thread):

    fwPosChanged = QtCore.Signal(object)

    def __init__(self, dev, driver, lock):
        Thread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.dev = dev
        self.driver = driver
        self.driverLock = lock
        self.cmds = {}

    def run(self):
        self.stopThread = False
        with self.driverLock:
            self.fwPosChanged.emit(self.driver.getPos())
        while True:
            try:
                with self.driverLock:
                    pos = self.driver.getPos()
                self.fwPosChanged.emit(pos)
                time.sleep(0.5)
            except:
                debug.printExc("Error in Filter Wheel communication thread:")

            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(0.02)

        self.driver.close()

    def stop(self, block=False):
        with self.lock:
            self.stopThread = True
        if block:
            if not self.wait(10000):
                raise Exception(
                    "Timed out while waiting for Filter Wheel thread exit!")
示例#4
0
文件: SerialMouse.py 项目: ablot/acq4
class MouseThread(QtCore.QThread):
    
    sigButtonChanged = QtCore.Signal(object)
    sigPositionChanged = QtCore.Signal(object)
    
    def __init__(self, dev, startState=None):
        QtCore.QThread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.dev = dev
        self.port = self.dev.port
        if startState is None:
            self.pos = [0, 0]
            self.btns = [0, 0]
        else:
            self.pos = startState['pos']
            self.btns = startState['btns']
        
    def run(self):
        self.stopThread = False
        self.sp = serial.Serial(int(self.port), baudrate=1200, bytesize=serial.SEVENBITS)
        time.sleep(3) ## Wait a few seconds for the mouse to say hello
        if self.sp.inWaiting() > 0:
            #print "Discarding %d bytes" % self.sp.inWaiting()
            self.sp.read(self.sp.inWaiting())
        while True:
            tdx = tdy = 0
            if self.sp.inWaiting() > 0:
                if self.sp.inWaiting() < 3:  ## could be in the middle of a packet, wait for more bytes to arrive
                    time.sleep(100e-3)
                    
                bytesWaiting = self.sp.inWaiting()
                if bytesWaiting < 3:  ## More bytes have not arrived, probably there is data corruption!
                    print "WARNING: possible corrupt data from serial mouse."
                    self.sp.read(bytesWaiting)
                    
                elif self.sp.inWaiting() >= 3: ## at least one packet is available.
                    while self.sp.inWaiting() >= 3:
                        (dx, dy, b0, b1) = self.readPacket()
                        tdx += dx
                        tdy += dy
                    self.pos = [self.pos[0] + tdx, self.pos[1] + tdy]
                    if tdx != 0 or tdy != 0:
                        #self.emit(QtCore.SIGNAL('positionChanged'), {'rel': (tdx, tdy), 'abs': self.pos})
                        self.sigPositionChanged.emit({'rel': (tdx, tdy), 'abs': self.pos})
                    if b0 != self.btns[0] or b1 != self.btns[1]:
                        self.btns = [b0, b1]
                        #self.emit(QtCore.SIGNAL('buttonChanged'), self.btns)
                        self.sigButtonChanged.emit(self.btns)
                        
            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(1e-3)
        self.sp.close()
            
    ## convert byte to signed byte
    @staticmethod
    def sint(x):
        return ((x+128)%256)-128

    def readPacket(self):
        d = self.sp.read(3)
        #print "%s %s %s" % (bin(ord(d[0])), bin(ord(d[1])), bin(ord(d[2])))
        b0 = (ord(d[0]) & 32) >> 5
        b1 = (ord(d[0]) & 16) >> 4
        xh = (ord(d[0]) & 3) << 6
        yh = (ord(d[0]) & 12) << 4
        xl = (ord(d[1]) & 63)
        yl = (ord(d[2]) & 63)
        
        #print "%s %s %s %s" % (bin(xh), bin(xl), bin(yh), bin(yl))
        return (MouseThread.sint(xl | xh), MouseThread.sint(yl | yh), b0, b1)
    
    def stop(self, block=False):
        #print "  stop: locking"
        with MutexLocker(self.lock):
            #print "  stop: requesting stop"
            self.stopThread = True
        if block:
            #print "  stop: waiting"
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
示例#5
0
class AcquireThread(Thread):

    sigNewFrame = QtCore.Signal(object)
    sigShowMessage = QtCore.Signal(object)

    def __init__(self, dev):
        Thread.__init__(self)
        self.dev = dev
        #self.cam = self.dev.getCamera()
        self.camLock = self.dev.camLock
        #size = self.cam.getSize()
        #self.state = {'binning': 1, 'exposure': .001, 'region': [0, 0, size[0]-1, size[1]-1], 'mode': 'No Trigger'}
        #self.state = self.dev.getParams(['binning', 'exposure', 'region', 'triggerMode'])
        self.stopThread = False
        self.lock = Mutex()
        self.acqBuffer = None
        #self.frameId = 0
        self.bufferTime = 5.0
        #self.ringSize = 30
        self.tasks = []

        ## This thread does not run an event loop,
        ## so we may need to deliver frames manually to some places
        self.connections = set()
        self.connectMutex = Mutex()

    def __del__(self):
        if hasattr(self, 'cam'):
            #self.cam.stop()
            self.dev.stopCamera()

    def start(self, *args):
        self.lock.lock()
        self.stopThread = False
        self.lock.unlock()
        Thread.start(self, *args)

    def connectCallback(self, method):
        with self.connectMutex:
            self.connections.add(method)

    def disconnectCallback(self, method):
        with self.connectMutex:
            if method in self.connections:
                self.connections.remove(method)

    #
    #def setParam(self, param, value):
    #    #print "PVCam:setParam", param, value
    #    start = False
    #    if self.isRunning():
    #        start = True
    #        #print "Camera.setParam: Stopping camera before setting parameter.."
    #        self.stop(block=True)
    #        #print "Camera.setParam: camera stopped"
    #    with self.lock:
    #        self.state[param] = value
    #    if start:
    #        #self.start(QtCore.QThread.HighPriority)
    #        self.start()
    #

    def run(self):
        #import cProfile
        ##cProfile.runctx('self._run()', globals(), locals(), sort='cumulative')
        #pr = cProfile.Profile()
        #pr.enable()
        #self._run()
        #pr.disable()
        #pr.print_stats(sort='cumulative')

        #def _run(self):
        size = self.dev.getParam('sensorSize')
        lastFrame = None
        lastFrameTime = None
        lastFrameId = None
        fps = None

        camState = dict(
            self.dev.getParams(
                ['binning', 'exposure', 'region', 'triggerMode']))
        binning = camState['binning']
        exposure = camState['exposure']
        region = camState['region']
        mode = camState['triggerMode']

        try:
            #self.dev.setParam('ringSize', self.ringSize, autoRestart=False)
            self.dev.startCamera()

            lastFrameTime = lastStopCheck = ptime.time()
            frameInfo = {}
            scopeState = None
            while True:
                ti = 0
                now = ptime.time()
                frames = self.dev.newFrames()

                ## If a new frame is available, process it and inform other threads
                if len(frames) > 0:
                    if lastFrameId is not None:
                        drop = frames[0]['id'] - lastFrameId - 1
                        if drop > 0:
                            print "WARNING: Camera dropped %d frames" % drop

                    ## Build meta-info for this frame(s)
                    info = camState.copy()

                    ss = self.dev.getScopeState()
                    if ss['id'] != scopeState:
                        scopeState = ss['id']
                        ## regenerate frameInfo here
                        ps = ss['pixelSize']  ## size of CCD pixel
                        transform = pg.SRTTransform3D(ss['transform'])

                        frameInfo = {
                            'pixelSize':
                            [ps[0] * binning[0],
                             ps[1] * binning[1]],  ## size of image pixel
                            'objective': ss.get('objective', None),
                            'deviceTransform': transform,
                        }

                    ## Copy frame info to info array
                    info.update(frameInfo)

                    ## Process all waiting frames. If there is more than one frame waiting, guess the frame times.
                    dt = (now - lastFrameTime) / len(frames)
                    if dt > 0:
                        info['fps'] = 1.0 / dt
                    else:
                        info['fps'] = None

                    for frame in frames:
                        frameInfo = info.copy()
                        data = frame.pop('data')
                        frameInfo.update(
                            frame)  # copies 'time' key supplied by camera
                        out = Frame(data, frameInfo)
                        with self.connectMutex:
                            conn = list(self.connections)
                        for c in conn:
                            c(out)
                        self.sigNewFrame.emit(out)

                    lastFrameTime = now
                    lastFrameId = frames[-1]['id']
                    loopCount = 0

                time.sleep(1e-3)

                ## check for stop request every 10ms
                if now - lastStopCheck > 10e-3:
                    lastStopCheck = now

                    ## If no frame has arrived yet, do NOT allow the camera to stop (this can hang the driver)   << bug should be fixed in pvcam driver, not here.
                    self.lock.lock()
                    if self.stopThread:
                        self.stopThread = False
                        self.lock.unlock()
                        break
                    self.lock.unlock()

                    diff = ptime.time() - lastFrameTime
                    if diff > (10 + exposure):
                        if mode == 'Normal':
                            self.dev.noFrameWarning(diff)
                            break
                        else:
                            pass  ## do not exit loop if there is a possibility we are waiting for a trigger

            #from debug import Profiler
            #prof = Profiler()
            with self.camLock:
                #self.cam.stop()
                self.dev.stopCamera()
            #prof.mark('      camera stop:')
        except:
            printExc("Error starting camera acquisition:")
            try:
                with self.camLock:
                    #self.cam.stop()
                    self.dev.stopCamera()
            except:
                pass
            self.sigShowMessage.emit(
                "ERROR starting acquisition (see console output)")
        finally:
            pass

    def stop(self, block=False):
        #print "AcquireThread.stop: Requesting thread stop, acquiring lock first.."
        with self.lock:
            self.stopThread = True
        #print "AcquireThread.stop: got lock, requested stop."
        #print "AcquireThread.stop: Unlocked, waiting for thread exit (%s)" % block
        if block:
            if not self.wait(10000):
                raise Exception("Timed out waiting for thread exit!")
        #print "AcquireThread.stop: thread exited"

    def reset(self):
        if self.isRunning():
            self.stop()
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
            #self.start(QtCore.QThread.HighPriority)
            self.start()
示例#6
0
class Device(QtCore.QObject):
    """Abstract class defining the standard interface for Device subclasses."""
    def __init__(self, deviceManager, config, name):
        QtCore.QObject.__init__(self)
        self._lock_ = Mutex(QtCore.QMutex.Recursive)  ## no, good idea
        self._lock_tb_ = None
        self.dm = deviceManager
        self.dm.declareInterface(name, ['device'], self)
        #self.config = config
        self._name = name
    
    def name(self):
        return self._name
    
    def createTask(self, cmd, task):
        ### Read configuration, configure tasks
        ### Return a handle unique to this task
        pass
    
    #def __del__(self):
        #self.quit()
        
    def quit(self):
        pass
    
    def deviceInterface(self, win):
        """Return a widget with a UI to put in the device rack"""
        return None
        
    def taskInterface(self, task):
        """Return a widget with a UI to put in the task rack"""
        return TaskGui(self, task)
        

    def reserve(self, block=True, timeout=20):
        #print "Device %s attempting lock.." % self.name()
        if block:
            l = self._lock_.tryLock(int(timeout*1000))
            if not l:
                print "Timeout waiting for device lock for %s" % self.name()
                print "  Device is currently locked from:"
                print self._lock_tb_
                raise Exception("Timed out waiting for device lock for %s" % self.name())
        else:
            l = self._lock_.tryLock()
            if not l:
                #print "Device %s lock failed." % self.name()
                return False
                #print "  Device is currently locked from:"
                #print self._lock_tb_
                #raise Exception("Could not acquire lock", 1)  ## 1 indicates failed non-blocking attempt
        self._lock_tb_ = ''.join(traceback.format_stack()[:-1])
        #print "Device %s lock ok" % self.name()
        return True
        
    def release(self):
        try:
            self._lock_.unlock()
            self._lock_tb_ = None
        except:
            printExc("WARNING: Failed to release device lock for %s" % self.name())
            
    def getTriggerChannel(self, daq):
        """Return the name of the channel on daq that this device raises when it starts.
        Allows the DAQ to trigger off of this device."""
        return None
示例#7
0
class MouseThread(Thread):

    sigButtonChanged = QtCore.Signal(object)
    sigPositionChanged = QtCore.Signal(object)

    def __init__(self, dev, startState=None):
        Thread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.dev = dev
        self.port = self.dev.port
        if startState is None:
            self.pos = [0, 0]
            self.btns = [0, 0]
        else:
            self.pos = startState['pos']
            self.btns = startState['btns']

    def run(self):
        self.stopThread = False
        self.sp = serial.Serial(int(self.port),
                                baudrate=1200,
                                bytesize=serial.SEVENBITS)
        time.sleep(3)  ## Wait a few seconds for the mouse to say hello
        if self.sp.inWaiting() > 0:
            #print "Discarding %d bytes" % self.sp.inWaiting()
            self.sp.read(self.sp.inWaiting())
        while True:
            tdx = tdy = 0
            if self.sp.inWaiting() > 0:
                if self.sp.inWaiting(
                ) < 3:  ## could be in the middle of a packet, wait for more bytes to arrive
                    time.sleep(100e-3)

                bytesWaiting = self.sp.inWaiting()
                if bytesWaiting < 3:  ## More bytes have not arrived, probably there is data corruption!
                    print "WARNING: possible corrupt data from serial mouse."
                    self.sp.read(bytesWaiting)

                elif self.sp.inWaiting(
                ) >= 3:  ## at least one packet is available.
                    while self.sp.inWaiting() >= 3:
                        (dx, dy, b0, b1) = self.readPacket()
                        tdx += dx
                        tdy += dy
                    self.pos = [self.pos[0] + tdx, self.pos[1] + tdy]
                    if tdx != 0 or tdy != 0:
                        #self.emit(QtCore.SIGNAL('positionChanged'), {'rel': (tdx, tdy), 'abs': self.pos})
                        self.sigPositionChanged.emit({
                            'rel': (tdx, tdy),
                            'abs': self.pos
                        })
                    if b0 != self.btns[0] or b1 != self.btns[1]:
                        self.btns = [b0, b1]
                        #self.emit(QtCore.SIGNAL('buttonChanged'), self.btns)
                        self.sigButtonChanged.emit(self.btns)

            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(1e-3)
        self.sp.close()

    ## convert byte to signed byte
    @staticmethod
    def sint(x):
        return ((x + 128) % 256) - 128

    def readPacket(self):
        d = self.sp.read(3)
        #print "%s %s %s" % (bin(ord(d[0])), bin(ord(d[1])), bin(ord(d[2])))
        b0 = (ord(d[0]) & 32) >> 5
        b1 = (ord(d[0]) & 16) >> 4
        xh = (ord(d[0]) & 3) << 6
        yh = (ord(d[0]) & 12) << 4
        xl = (ord(d[1]) & 63)
        yl = (ord(d[2]) & 63)

        #print "%s %s %s %s" % (bin(xh), bin(xl), bin(yh), bin(yl))
        return (MouseThread.sint(xl | xh), MouseThread.sint(yl | yh), b0, b1)

    def stop(self, block=False):
        #print "  stop: locking"
        with self.lock:
            #print "  stop: requesting stop"
            self.stopThread = True
        if block:
            #print "  stop: waiting"
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
示例#8
0
class SutterMP285Thread(Thread):

    sigPositionChanged = QtCore.Signal(object)
    sigError = QtCore.Signal(object)

    def __init__(self, dev, driver, driverLock, scale, limits, maxSpd):
        Thread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.scale = scale
        self.mp285 = driver
        self.driverLock = driverLock
        #self.monitor = True
        self.update = False
        self.resolution = 'fine'
        self.dev = dev
        #self.port = port
        #self.pos = [0, 0, 0]
        #self.baud = baud
        self.velocity = [0, 0, 0]
        self.limits = deepcopy(limits)
        self.limitChanged = False
        self.maxSpeed = maxSpd

        #self.posxyz = [ 0, 0, 0]

    def setResolution(self, res):
        with self.lock:
            self.resolution = res

    def setLimits(self, limits):
        with self.lock:
            self.limits = deepcopy(limits)
            self.limitChanged = True

    def setMaxSpeed(self, s):
        with self.lock:
            self.maxSpeed = s

    #def setMonitor(self, mon):
    #with self.lock:
    #self.monitor = mon
    def updatePos(self):
        with self.lock:
            self.update = True

    def setVelocity(self, v):
        with self.lock:
            self.velocity = v

    def run(self):
        self.stopThread = False
        #self.sp = serial.Serial(int(self.port), baudrate=self.baud, bytesize=serial.EIGHTBITS)
        #time.sleep(3) ## Wait a few seconds for the mouse to say hello
        ## clear buffer before starting
        #if self.sp.inWaiting() > 0:
        #print "Discarding %d bytes" % self.sp.inWaiting()
        #self.sp.read(self.sp.inWaiting())
        #import wingdbstub
        print "  Starting MP285 thread: 0x%x" % int(
            QtCore.QThread.currentThreadId())
        #import sip
        #print "    also known as 0x%x" % sip.unwrapinstance(self)
        velocity = np.array([0, 0, 0])
        pos = [0, 0, 0]

        try:
            self.getImmediatePos()
            monitor = True
        except:
            debug.printExc("Sutter MP285: Cannot determine position:")
            monitor = False

        while True:
            try:
                ## Lock and copy state to local variables
                with self.lock:
                    update = self.update
                    self.update = False
                    limits = deepcopy(self.limits)
                    maxSpeed = self.maxSpeed
                    newVelocity = np.array(self.velocity[:])
                    resolution = self.resolution
                    limitChanged = self.limitChanged
                    self.limitChanged = False

                ## if limits have changed, inform the device
                if monitor and limitChanged:  ## monitor is only true if this is a customized device with limit checking
                    self.sendLimits()

                ## If requested velocity is different from the current velocity, handle that.
                if np.any(newVelocity != velocity):
                    speed = np.clip(np.sum(newVelocity**2)**0.5, 0.,
                                    1.)  ## should always be 0.0-1.0
                    #print "new velocity:", newVelocity, "speed:", speed

                    if speed == 0:
                        nv = np.array([0, 0, 0])
                    else:
                        nv = newVelocity / speed

                    speed = np.clip(speed, 0, maxSpeed)
                    #print "final speed:", speed

                    ## stop current move, get position, start new move
                    #print "stop.."
                    self.stopMove()
                    #print "stop done."

                    #print "getpos..."
                    pos1 = self.readPosition()
                    if pos1 is not None:

                        if speed > 0:
                            #print "   set new velocity"
                            self.writeVelocity(speed,
                                               nv,
                                               limits=limits,
                                               pos=pos1,
                                               resolution=resolution)
                            #print "   done"

                        ## report current position

                        velocity = newVelocity
                    #print "done"

                ## If velocity is 0, we can do some position checks
                if np.all(velocity == 0):
                    newPos = None
                    if update:
                        newPos = self.readPosition()
                    elif monitor:
                        newPos = self.getImmediatePos()

                    if newPos is not None:  ## If position has changed, emit a signal.

                        change = [
                            newPos[i] - pos[i] for i in range(len(newPos))
                        ]
                        pos = newPos

                        if any(change):
                            #self.emit(QtCore.SIGNAL('positionChanged'), {'rel': change, 'abs': self.pos})
                            self.sigPositionChanged.emit({
                                'rel': change,
                                'abs': pos
                            })
                else:
                    ## moving; make a guess about the current position
                    pass
            except:
                pass
                debug.printExc("Error in MP285 thread:")

            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(0.02)

        self.mp285.close()

    def stop(self, block=False):
        #print "  stop: locking"
        with self.lock:
            #print "  stop: requesting stop"
            self.stopThread = True
        if block:
            #print "  stop: waiting"
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
        #print "  stop: done"

    def readPosition(self):
        try:
            with self.driverLock:
                pos = np.array(self.mp285.getPos())
            return pos * self.scale
        except TimeoutError:
            self.sigError.emit("Read timeout--press reset button on MP285.")
            return None
        except:
            self.sigError.emit("Read error--see console.")
            debug.printExc("Error getting packet:")
            return None

    def writeVelocity(self, spd, v, limits, pos, resolution):
        if not self.checkLimits(pos, limits):
            return

        ## check all limits for closest stop point
        pt = self.vectorLimit(pos, v, limits)
        if pt is None:
            return

        ## set speed
        #print "      SPD:", spd, "POS:", pt
        self._setSpd(spd, fineStep=(resolution == 'fine'))
        self._setPos(pt, block=False)

    def vectorLimit(self, pos, v, limits):
        ## return position of closest limit intersection given starting point and vector
        pts = []
        pos = np.array(pos)
        v = np.array(v)
        for i in [0, 1, 2]:
            if v[i] < 0:
                p = self.intersect(pos, v, limits[i][0], i)
            else:
                p = self.intersect(pos, v, limits[i][1], i)
            if p is not None:
                pts.append(p)
        if len(pts) == 0:
            return None
        lengths = [np.sum((p - pos)**2)**0.5 for p in pts]
        i = np.argmin(lengths)
        return pts[i]

    def intersect(self, pos, v, x, ax):
        ## return the point where vector pos->v intersects plane x along axis ax
        if v[ax] == 0:
            return None
        dx = x - pos[ax]
        return pos + dx * v / v[ax]

    def checkLimits(self, pos, limits):
        for i in [0, 1, 2]:
            #print 'pos, limits', pos[i]
            #print limits[i]
            #print limits[i][0]
            #print limits[i][1]
            if pos[i] < limits[i][0] or pos[i] > limits[i][1]:
                return False
        return True

    def sendLimits(self):
        limits = []
        for ax in [0, 1, 2]:
            for lim in [1, 0]:
                pos, en = self.limits[ax][lim]
                limits.append(pos / self.scale[ax] if en else None)
        with self.driverLock:
            self.mp285.setLimits(limits)

    def _setPos(self, pos, block=True):
        pos = np.array(pos) / self.scale
        with self.driverLock:
            self.mp285.setPos(pos, block=block)

    def stopMove(self):
        with self.driverLock:
            self.mp285.stop()

    def _setSpd(self, v, fineStep=True):
        ## This should be done with a calibrated speed table instead.
        v = int(v * 1e6)
        with self.driverLock:
            self.mp285.setSpeed(v, fineStep)

    def getImmediatePos(self):
        with self.driverLock:
            pos = np.array(self.mp285.getImmediatePos())
        return pos * self.scale
示例#9
0
class Device(QtCore.QObject):
    """Abstract class defining the standard interface for Device subclasses."""
    def __init__(self, deviceManager, config, name):
        QtCore.QObject.__init__(self)

        # task reservation lock -- this is a recursive lock to allow a task to run its own subtasks
        # (for example, setting a holding value before exiting a task).
        # However, under some circumstances we might try to run two concurrent tasks from the same
        # thread (eg, due to calling processEvents() while waiting for the task to complete). We
        # don't have a good solution for this problem at present..
        self._lock_ = Mutex(QtCore.QMutex.Recursive)
        self._lock_tb_ = None
        self.dm = deviceManager
        self.dm.declareInterface(name, ['device'], self)
        self._name = name

    def name(self):
        return self._name

    def createTask(self, cmd, task):
        ### Read configuration, configure tasks
        ### Return a handle unique to this task
        pass

    def quit(self):
        pass

    def deviceInterface(self, win):
        """Return a widget with a UI to put in the device rack"""
        return None

    def taskInterface(self, task):
        """Return a widget with a UI to put in the task rack"""
        return TaskGui(self, task)

    def configPath(self):
        """Return the path used for storing configuration data for this device.

        This path should resolve to `acq4/config/devices/DeviceName_config`.
        """
        return os.path.join('devices', self.name() + '_config')

    def configFileName(self, filename):
        """Return the full path to a config file for this device.
        """
        filename = os.path.join(self.configPath(), filename)
        return self.dm.configFileName(filename)

    def readConfigFile(self, filename):
        """Read a config file from this device's configuration directory.
        """
        fileName = os.path.join(self.configPath(), filename)
        return self.dm.readConfigFile(fileName)

    def writeConfigFile(self, data, filename):
        """Write data to a config file in this device's configuration directory.
        """
        fileName = os.path.join(self.configPath(), filename)
        return self.dm.writeConfigFile(data, fileName)

    def appendConfigFile(self, data, filename):
        """Append data to a config file in this device's configuration directory.
        """
        fileName = os.path.join(self.configPath(), filename)
        return self.dm.appendConfigFile(data, fileName)

    def reserve(self, block=True, timeout=20):
        #print "Device %s attempting lock.." % self.name()
        if block:
            l = self._lock_.tryLock(int(timeout * 1000))
            if not l:
                print "Timeout waiting for device lock for %s" % self.name()
                print "  Device is currently locked from:"
                print self._lock_tb_
                raise Exception("Timed out waiting for device lock for %s" %
                                self.name())
        else:
            l = self._lock_.tryLock()
            if not l:
                #print "Device %s lock failed." % self.name()
                return False
                #print "  Device is currently locked from:"
                #print self._lock_tb_
                #raise Exception("Could not acquire lock", 1)  ## 1 indicates failed non-blocking attempt
        self._lock_tb_ = ''.join(traceback.format_stack()[:-1])
        #print "Device %s lock ok" % self.name()
        return True

    def release(self):
        try:
            self._lock_.unlock()
            self._lock_tb_ = None
        except:
            printExc("WARNING: Failed to release device lock for %s" %
                     self.name())

    def getTriggerChannel(self, daq):
        """Return the name of the channel on daq that this device raises when it starts.
        Allows the DAQ to trigger off of this device."""
        return None

    def __repr__(self):
        return '<%s "%s">' % (self.__class__.__name__, self.name())
示例#10
0
文件: Camera.py 项目: hiuwo/acq4
class AcquireThread(QtCore.QThread):
    
    sigNewFrame = QtCore.Signal(object)
    sigShowMessage = QtCore.Signal(object)
    
    def __init__(self, dev):
        QtCore.QThread.__init__(self)
        self.dev = dev
        #self.cam = self.dev.getCamera()
        self.camLock = self.dev.camLock
        #size = self.cam.getSize()
        #self.state = {'binning': 1, 'exposure': .001, 'region': [0, 0, size[0]-1, size[1]-1], 'mode': 'No Trigger'}
        #self.state = self.dev.getParams(['binning', 'exposure', 'region', 'triggerMode'])
        self.stopThread = False
        self.lock = Mutex()
        self.acqBuffer = None
        #self.frameId = 0
        self.bufferTime = 5.0
        #self.ringSize = 30
        self.tasks = []
        
        ## This thread does not run an event loop,
        ## so we may need to deliver frames manually to some places
        self.connections = set()
        self.connectMutex = Mutex()
    
    def __del__(self):
        if hasattr(self, 'cam'):
            #self.cam.stop()
            self.dev.stopCamera()
    
    def start(self, *args):
        self.lock.lock()
        self.stopThread = False
        self.lock.unlock()
        QtCore.QThread.start(self, *args)
        
    
    def connectCallback(self, method):
        with self.connectMutex:
            self.connections.add(method)
    
    def disconnectCallback(self, method):
        with self.connectMutex:
            if method in self.connections:
                self.connections.remove(method)
    #
    #def setParam(self, param, value):
    #    #print "PVCam:setParam", param, value
    #    start = False
    #    if self.isRunning():
    #        start = True
    #        #print "Camera.setParam: Stopping camera before setting parameter.."
    #        self.stop(block=True)
    #        #print "Camera.setParam: camera stopped"
    #    with self.lock:
    #        self.state[param] = value
    #    if start:
    #        #self.start(QtCore.QThread.HighPriority)
    #        self.start()
    #    
    
    def run(self):
        #import cProfile
        ##cProfile.runctx('self._run()', globals(), locals(), sort='cumulative')
        #pr = cProfile.Profile()
        #pr.enable()
        #self._run()
        #pr.disable()
        #pr.print_stats(sort='cumulative')
        
    #def _run(self):
        size = self.dev.getParam('sensorSize')
        lastFrame = None
        lastFrameTime = None
        lastFrameId = None
        fps = None
        
        camState = dict(self.dev.getParams(['binning', 'exposure', 'region', 'triggerMode']))
        binning = camState['binning']
        exposure = camState['exposure']
        region = camState['region']
        mode = camState['triggerMode']
        
        try:
            #self.dev.setParam('ringSize', self.ringSize, autoRestart=False)
            self.dev.startCamera()
            
            lastFrameTime = lastStopCheck = ptime.time()
            frameInfo = {}
            scopeState = None
            while True:
                ti = 0
                now = ptime.time()
                frames = self.dev.newFrames()
                
                #with self.camLock:
                    #frame = self.cam.lastFrame()
                ## If a new frame is available, process it and inform other threads
                if len(frames) > 0:
                    if lastFrameId is not None:
                        drop = frames[0]['id'] - lastFrameId - 1
                        if drop > 0:
                            print "WARNING: Camera dropped %d frames" % drop
                        
                    ## Build meta-info for this frame(s)
                    info = camState.copy()
                    
                    ## frameInfo includes pixelSize, objective, centerPosition, scopePosition, imagePosition
                    ss = self.dev.getScopeState()
                    if ss['id'] != scopeState:
                        #print "scope state changed"
                        scopeState = ss['id']
                        ## regenerate frameInfo here
                        ps = ss['pixelSize']  ## size of CCD pixel
                        #pos = ss['centerPosition']
                        #pos2 = [pos[0] - size[0]*ps[0]*0.5 + region[0]*ps[0], pos[1] - size[1]*ps[1]*0.5 + region[1]*ps[1]]
                        
                        transform = pg.SRTTransform3D(ss['transform'])
                        #transform.translate(region[0]*ps[0], region[1]*ps[1])  ## correct for ROI here
                        
                        frameInfo = {
                            'pixelSize': [ps[0] * binning[0], ps[1] * binning[1]],  ## size of image pixel
                            #'scopePosition': ss['scopePosition'],
                            #'centerPosition': pos,
                            'objective': ss.get('objective', None),
                            #'imagePosition': pos2
                            #'cameraTransform': ss['transform'],
                            'cameraTransform': transform,
                        }
                        
                    ## Copy frame info to info array
                    info.update(frameInfo)
                    #for k in frameInfo:
                        #info[k] = frameInfo[k]
                    
                    ## Process all waiting frames. If there is more than one frame waiting, guess the frame times.
                    dt = (now - lastFrameTime) / len(frames)
                    if dt > 0:
                        info['fps'] = 1.0/dt
                    else:
                        info['fps'] = None
                    
                    for frame in frames:
                        frameInfo = info.copy()
                        data = frame['data']
                        #print data
                        del frame['data']
                        frameInfo.update(frame)
                        out = Frame(data, frameInfo)
                        with self.connectMutex:
                            conn = list(self.connections)
                        for c in conn:
                            c(out)
                        #self.emit(QtCore.SIGNAL("newFrame"), out)
                        self.sigNewFrame.emit(out)
                        
                    lastFrameTime = now
                    lastFrameId = frames[-1]['id']
                    loopCount = 0
                        
                time.sleep(1e-3)
                
                ## check for stop request every 10ms
                if now - lastStopCheck > 10e-3: 
                    lastStopCheck = now
                    
                    ## If no frame has arrived yet, do NOT allow the camera to stop (this can hang the driver)   << bug should be fixed in pvcam driver, not here.
                    self.lock.lock()
                    if self.stopThread:
                        self.stopThread = False
                        self.lock.unlock()
                        break
                    self.lock.unlock()
                    
                    diff = ptime.time()-lastFrameTime
                    if diff > (10 + exposure):
                        if mode == 'Normal':
                            print "Camera acquisition thread has been waiting %02f sec but no new frames have arrived; shutting down." % diff
                            break
                        else:
                            pass  ## do not exit loop if there is a possibility we are waiting for a trigger
                                
                
            #from debug import Profiler
            #prof = Profiler()
            with self.camLock:
                #self.cam.stop()
                self.dev.stopCamera()
            #prof.mark('      camera stop:')
        except:
            try:
                with self.camLock:
                    #self.cam.stop()
                    self.dev.stopCamera()
            except:
                pass
            printExc("Error starting camera acquisition:")
            #self.emit(QtCore.SIGNAL("showMessage"), "ERROR starting acquisition (see console output)")
            self.sigShowMessage.emit("ERROR starting acquisition (see console output)")
        finally:
            pass
            #print "Camera ACQ thread exited."
        
    def stop(self, block=False):
        #print "AcquireThread.stop: Requesting thread stop, acquiring lock first.."
        with self.lock:
            self.stopThread = True
        #print "AcquireThread.stop: got lock, requested stop."
        #print "AcquireThread.stop: Unlocked, waiting for thread exit (%s)" % block
        if block:
            if not self.wait(10000):
                raise Exception("Timed out waiting for thread exit!")
        #print "AcquireThread.stop: thread exited"

    def reset(self):
        if self.isRunning():
            self.stop()
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
            #self.start(QtCore.QThread.HighPriority)
            self.start()
示例#11
0
文件: SutterMP285.py 项目: ablot/acq4
class SutterMP285Thread(QtCore.QThread):

    sigPositionChanged = QtCore.Signal(object)
    sigError = QtCore.Signal(object)

    def __init__(self, dev, driver, driverLock, scale, limits, maxSpd):
        QtCore.QThread.__init__(self)
        self.lock = Mutex(QtCore.QMutex.Recursive)
        self.scale = scale
        self.mp285 = driver
        self.driverLock = driverLock
        #self.monitor = True
        self.update = False
        self.resolution = 'fine'
        self.dev = dev
        #self.port = port
        #self.pos = [0, 0, 0]
        #self.baud = baud
        self.velocity = [0,0,0]
        self.limits = deepcopy(limits)
        self.limitChanged = False
        self.maxSpeed = maxSpd
        
        #self.posxyz = [ 0, 0, 0]
        
    def setResolution(self, res):
        with self.lock:
            self.resolution = res
        
    def setLimits(self, limits):
        with self.lock:
            self.limits = deepcopy(limits)
            self.limitChanged = True
            
    def setMaxSpeed(self, s):
        with self.lock:
            self.maxSpeed = s
            
    #def setMonitor(self, mon):
        #with self.lock:
            #self.monitor = mon
    def updatePos(self):
        with self.lock:
            self.update = True
        
    def setVelocity(self, v):
        with self.lock:
            self.velocity = v
        
    def run(self):
        self.stopThread = False
        #self.sp = serial.Serial(int(self.port), baudrate=self.baud, bytesize=serial.EIGHTBITS)
        #time.sleep(3) ## Wait a few seconds for the mouse to say hello
        ## clear buffer before starting
        #if self.sp.inWaiting() > 0:
            #print "Discarding %d bytes" % self.sp.inWaiting()
            #self.sp.read(self.sp.inWaiting())
        #import wingdbstub
        print "  Starting MP285 thread: 0x%x" % int(QtCore.QThread.currentThreadId())
        #import sip
        #print "    also known as 0x%x" % sip.unwrapinstance(self)
        velocity = np.array([0,0,0])
        pos = [0,0,0]
        
        try:
            self.getImmediatePos()
            monitor = True
        except:
            debug.printExc("Sutter MP285: Cannot determine position:")
            monitor = False
        
        while True:
            try:
                ## Lock and copy state to local variables
                with self.lock:
                    update = self.update
                    self.update = False
                    limits = deepcopy(self.limits)
                    maxSpeed = self.maxSpeed
                    newVelocity = np.array(self.velocity[:])
                    resolution = self.resolution
                    limitChanged = self.limitChanged
                    self.limitChanged = False
                    
                ## if limits have changed, inform the device
                if monitor and limitChanged:   ## monitor is only true if this is a customized device with limit checking
                    self.sendLimits()
                
                ## If requested velocity is different from the current velocity, handle that.
                if np.any(newVelocity != velocity):
                    speed = np.clip(np.sum(newVelocity**2)**0.5, 0., 1.)   ## should always be 0.0-1.0
                    #print "new velocity:", newVelocity, "speed:", speed
                    
                    if speed == 0:
                        nv = np.array([0,0,0])
                    else:
                        nv = newVelocity/speed
                        
                    speed = np.clip(speed, 0, maxSpeed)
                    #print "final speed:", speed
                    
                    ## stop current move, get position, start new move
                    #print "stop.."
                    self.stopMove()
                    #print "stop done."
                    
                    #print "getpos..."
                    pos1 = self.readPosition()
                    if pos1 is not None:
                        
                        if speed > 0:
                            #print "   set new velocity"
                            self.writeVelocity(speed, nv, limits=limits, pos=pos1, resolution=resolution)
                            #print "   done"
                            
                        ## report current position
                        
                            
                        velocity = newVelocity
                    #print "done"
                
                ## If velocity is 0, we can do some position checks
                if np.all(velocity == 0):
                    newPos = None
                    if update:
                        newPos = self.readPosition()
                    elif monitor:
                        newPos = self.getImmediatePos()
    
                    if newPos is not None: ## If position has changed, emit a signal.
        
                        change = [newPos[i] - pos[i] for i in range(len(newPos))]
                        pos = newPos
        
                        if any(change):
                            #self.emit(QtCore.SIGNAL('positionChanged'), {'rel': change, 'abs': self.pos})
                            self.sigPositionChanged.emit({'rel': change, 'abs': pos})
                else:
                    ## moving; make a guess about the current position
                    pass
            except:
                pass
                debug.printExc("Error in MP285 thread:")
                
            self.lock.lock()
            if self.stopThread:
                self.lock.unlock()
                break
            self.lock.unlock()
            time.sleep(0.02)


        self.mp285.close()

    def stop(self, block=False):
        #print "  stop: locking"
        with self.lock:
            #print "  stop: requesting stop"
            self.stopThread = True
        if block:
            #print "  stop: waiting"
            if not self.wait(10000):
                raise Exception("Timed out while waiting for thread exit!")
        #print "  stop: done"


    def readPosition(self):
        try:
            with self.driverLock:
                pos = np.array(self.mp285.getPos())
            return pos*self.scale
        except TimeoutError:
            self.sigError.emit("Read timeout--press reset button on MP285.")
            return None
        except:
            self.sigError.emit("Read error--see console.")
            debug.printExc("Error getting packet:")
            return None
        
    def writeVelocity(self, spd, v, limits, pos, resolution):
        if not self.checkLimits(pos, limits):
            return
        
        ## check all limits for closest stop point
        pt = self.vectorLimit(pos, v, limits)
        if pt is None:
            return
        
        ## set speed
        #print "      SPD:", spd, "POS:", pt
        self._setSpd(spd, fineStep=(resolution=='fine'))
        self._setPos(pt, block=False)
        
                
    def vectorLimit(self, pos, v, limits):
        ## return position of closest limit intersection given starting point and vector
        pts = []
        pos = np.array(pos)
        v = np.array(v)
        for i in  [0,1,2]:
            if v[i] < 0:
                p = self.intersect(pos, v, limits[i][0], i)
            else:
                p = self.intersect(pos, v, limits[i][1], i)
            if p is not None:
                pts.append(p)
        if len(pts) == 0:
            return None
        lengths = [np.sum((p-pos)**2)**0.5 for p in pts]
        i = np.argmin(lengths)
        return pts[i]
        
            
    def intersect(self, pos, v, x, ax):
        ## return the point where vector pos->v intersects plane x along axis ax
        if v[ax] == 0:
            return None
        dx = x-pos[ax]
        return pos + dx * v/v[ax]
            
    def checkLimits(self, pos, limits):
        for i in [0,1,2]:
            #print 'pos, limits', pos[i]
            #print limits[i]
            #print limits[i][0]
            #print limits[i][1]
            if pos[i] < limits[i][0] or pos[i] > limits[i][1]:
                return False
        return True
        
    def sendLimits(self):
        limits = []
        for ax in [0,1,2]:
            for lim in [1,0]:
                pos, en = self.limits[ax][lim]
                limits.append(pos/self.scale[ax] if en else None)
        with self.driverLock:
            self.mp285.setLimits(limits)
        
    def _setPos(self, pos, block=True):
        pos = np.array(pos) / self.scale
        with self.driverLock:
            self.mp285.setPos(pos, block=block)
    
    def stopMove(self):
        with self.driverLock:
            self.mp285.stop()
            
    def _setSpd(self, v, fineStep=True):
        ## This should be done with a calibrated speed table instead.
        v = int(v*1e6)
        with self.driverLock:
            self.mp285.setSpeed(v, fineStep)
            
        
    def getImmediatePos(self):
        with self.driverLock:
            pos = np.array(self.mp285.getImmediatePos())
        return pos*self.scale