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._name = name
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 __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)
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 __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 __init__(self, manager): Qt.QMainWindow.__init__(self) self.setWindowTitle("Log") path = os.path.dirname(__file__) self.setWindowIcon(Qt.QIcon(os.path.join(path, 'logIcon.png'))) self.wid = LogWidget(self, manager) self.wid.ui.input = Qt.QLineEdit() self.wid.ui.gridLayout.addWidget(self.wid.ui.input, 2, 0, 1, 3) self.wid.ui.dirLabel.setText("Current Storage Directory: None") self.setCentralWidget(self.wid) self.resize(1000, 500) self.manager = manager #global WIN global WIN WIN = self self.msgCount = 0 self.logCount = 0 self.logFile = None configfile.writeConfigFile( '', self.fileName() ) ## start a new temp log file, destroying anything left over from the last session. self.buttons = [ ] ## weak references to all Log Buttons get added to this list, so it's easy to make them all do things, like flash red. self.lock = Mutex() self.errorDialog = ErrorDialog() self.wid.ui.input.returnPressed.connect(self.textEntered) self.sigLogMessage.connect(self.queuedLogMsg, Qt.Qt.QueuedConnection)
def __init__(self, manager, config, name): try: import MMCorePy except ImportError: if sys.platform != 'win32': raise # MM does not install itself to standard path. User should take care of this, # but we can make a guess.. path = config.get('path', 'C:\\Program Files\\Micro-Manager-1.4') sys.path.append(path) os.environ['PATH'] = os.environ['PATH'] + ';' + path try: import MMCorePy finally: sys.path.pop() self.camName = str(name) # we will use this name as the handle to the MM camera self.mmc = MMCorePy.CMMCore() self._triggerProp = None # the name of the property for setting trigger mode self._triggerModes = ({}, {}) # forward and reverse mappings for the names of trigger modes self._binningMode = None # 'x' or 'xy' for binning strings like '1' and '1x1', respectively self.camLock = Mutex(Mutex.Recursive) ## Lock to protect access to camera self._config = config Camera.__init__(self, manager, config, name) ## superclass will call setupCamera when it is ready. self.acqBuffer = None self.frameId = 0 self.lastFrameTime = None
def __init__(self, dev): self.dev = dev self.lock = Mutex(recursive=True) self.stopped = False self.interval = 0.3 Thread.__init__(self)
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.switchDevice = None self.currentSwitchPosition = None self.currentObjective = None self._focusDevice = None self._positionDevice = None self._surfaceDepth = None self.objectives = collections.OrderedDict() ## Format of self.objectives is: ## { ## switchPosition1: {objName1: objective1, objName2: objective, ...}, ## switchPosition2: {objName1: objective1, objName2: objective, ...}, ## } for k1, objs in config['objectives'].iteritems( ): ## Set default values for each objective self.objectives[k1] = collections.OrderedDict() for k2, o in objs.iteritems(): obj = Objective(o, self, (k1, k2)) self.objectives[k1][k2] = obj #obj.sigTransformChanged.connect(self.objectiveTransformChanged) ## Keep track of the objective currently in use for each position ## Format is: { switchPosition1: objective1, ... } self.selectedObjectives = collections.OrderedDict([ (i, self.objectives[i].values()[0]) for i in self.objectives ]) for obj in self.selectedObjectives.values(): self.addSubdevice(obj) ## if there is a light source, configure it here if 'lightSource' in config: self.lightSource = dm.getDevice(config['lightSource']) self.lightSource.sigLightChanged.connect(self._lightChanged) else: self.lightSource = None ## If there is a switch device, configure it here if 'objectiveSwitch' in config: self.switchDevice = dm.getDevice( config['objectiveSwitch'][0]) ## Switch device self.objSwitchId = config['objectiveSwitch'][1] ## Switch ID #self.currentSwitchPosition = str(self.switchDevice.getSwitch(self.objSwitchId)) self.switchDevice.sigSwitchChanged.connect( self.objectiveSwitchChanged) self.objectiveSwitchChanged() else: self.setObjectiveIndex(0) cal = self.readConfigFile('calibration') if 'surfaceDepth' in cal: self.setSurfaceDepth(cal['surfaceDepth']) dm.declareInterface(name, ['microscope'], self)
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 __init__(self): Thread.__init__(self) self.prot = None self._stop = False self._frame = None self._paused = False self.lock = Mutex(recursive=True)
def __init__(self): self.cams = {} self.lock = Mutex() #self.pvcam = windll.Pvcam32 if _PVCamClass.PVCAM_CREATED: raise Exception( "Will not create another pvcam instance--use the pre-existing PVCam object." ) init = LIB.pvcam_init()() if init < 1: raise Exception( "Could not initialize pvcam library (pl_pvcam_init): %s" % self.error()) # This should happen before every new exposure (?) if LIB.exp_init_seq()() < 1: raise Exception( "Could not initialize pvcam library (pl_exp_init_seq): %s" % self.error()) _PVCamClass.PVCAM_CREATED = True global externalParams self.paramTable = OrderedDict() for p in externalParams: self.paramTable[p] = self.paramFromString(p) atexit.register(self.quit)
def __init__(self, dm, config, name): Device.__init__(self, dm, config, name) self.config = config self.lock = Mutex(QtCore.QMutex.Recursive) self.port = config['port'] self.scale = config['scale'] self.pos = [0, 0] self.buttons = [0, 0] ## Reload the last known state of the mouse if it was last modified recently enough self.stateFile = os.path.join('devices', self.name + "_last_state.cfg") state = dm.readConfigFile(self.stateFile) if state != {} and time.time() - state.get('time', 0) < 36000: self.pos = state['pos'] self.buttons = state['buttons'] self.mThread = MouseThread(self, { 'pos': self.pos[:], 'btns': self.buttons[:] }) self.mThread.sigPositionChanged.connect(self.posChanged) self.mThread.sigButtonChanged.connect(self.btnChanged) #self.proxy1 = proxyConnect(None, self.sigPositionChanged, self.storeState, 3.0) ## wait 3 seconds before writing changes #self.proxy2 = proxyConnect(None, self.sigSwitchChanged, self.storeState, 3.0) self.proxy1 = SignalProxy(self.sigPositionChanged, slot=self.storeState, delay=3.0) self.proxy2 = SignalProxy(self.sigSwitchChanged, slot=self.storeState, delay=3.0) self.mThread.start()
def __init__(self, dm, config, name): Device.__init__(self, dm, config, name) OptomechDevice.__init__(self, dm, config, name) # total device transform will be composed of a base transform (defined in the config) # and a dynamic translation provided by the hardware. self._baseTransform = Qt.QMatrix4x4(self.deviceTransform()) self._stageTransform = Qt.QMatrix4x4() self._invStageTransform = Qt.QMatrix4x4() self.config = config self.lock = Mutex(Qt.QMutex.Recursive) self.pos = [0] * 3 self._defaultSpeed = 'fast' self.pitch = config.get('pitch', 27) self.setFastSpeed(config.get('fastSpeed', 1e-3)) self.setSlowSpeed(config.get('slowSpeed', 10e-6)) # used to emit signal when position passes a threshold self.switches = {} self.switchThresholds = {} for name, spec in config.get('switches', {}).items(): self.switches[name] = None self.switchThresholds[name] = spec self._limits = [(None, None), (None, None), (None, None)] self._progressDialog = None self._progressTimer = Qt.QTimer() self._progressTimer.timeout.connect(self.updateProgressDialog) dm.declareInterface(name, ['stage'], self)
def __init__(self): QtCore.QObject.__init__(self) if DataManager.INSTANCE is not None: raise Exception("Attempted to create more than one DataManager!") DataManager.INSTANCE = self self.cache = {} self.lock = Mutex(QtCore.QMutex.Recursive)
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()
def __init__(self, ui): self.ui = ui self.manager = ui.manager self.clampName = ui.clampName Thread.__init__(self) self.lock = Mutex(QtCore.QMutex.Recursive) self.stopThread = True self.paramsUpdated = True
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
def __init__(self, path, manager): QtCore.QObject.__init__(self) self.manager = manager self.delayedChanges = [] self.path = os.path.abspath(path) self.parentDir = None self.lock = Mutex(QtCore.QMutex.Recursive) self.sigproxy = SignalProxy(self.sigChanged, slot=self.delayedChange)
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 __init__(self, task, frames, daqResult): self.lock = Mutex(recursive=True) self._task = task self._frames = frames self._daqResult = daqResult self._marr = None self._arr = None self._frameTimes = None self._frameTimesPrecise = False
def __init__(self, laserDev, scannerDev): Thread.__init__(self) self._abort = False self._video = True self._closeShutter = True # whether to close shutter at end of acquisition self.lock = Mutex(recursive=True) self.manager = acq4.Manager.getManager() self.laserDev = laserDev self.scannerDev = scannerDev
def __init__(self, *args, **kargs): self.camLock = Mutex(Mutex.Recursive) ## Lock to protect access to camera self.ringSize = 50 Camera.__init__(self, *args, **kargs) ## superclass will call setupCamera when it is ready. self.acqBuffer = None self.frameId = 0 self.lastIndex = None self.lastFrameTime = None self.stopOk = False
def __init__(self, dev, cmd, parentTask): DeviceTask.__init__(self, dev, cmd, parentTask) self.cmd = cmd self.daqTasks = [] self.spotSize = None # We use this flag to exit from the sleep loop in start() in case the # task is aborted during that time. self.aborted = False self.abortLock = Mutex(recursive=True)
def __init__(self, ui): Thread.__init__(self) self.ui = ui self.dm = self.ui.manager self.lock = Mutex(Qt.QMutex.Recursive) self.stopThread = True self.abortThread = False self.paused = False self._currentTask = None self._systrace = None
def __init__(self, dev): self.dev = dev self.lock = Mutex(recursive=True) self.stopped = False self.interval = 0.3 self.nextMoveId = 0 self.moveRequest = None self._moveStatus = {} Thread.__init__(self)
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 __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 __init__(self): self.pos = np.zeros(3) self.target = None self.speed = None self.velocity = None self._quit = False self.lock = Mutex() self.interval = 30e-3 self.lastUpdate = None self.currentMove = None Thread.__init__(self)
def __init__(self, dm, config, name): self.port = config[ 'port'] - 1 ## windows com ports start at COM1, pyserial ports start at 0 self.baud = config.get('baud', 19200) self.driver = Coherent(self.port, self.baud) self.driverLock = Mutex( QtCore.QMutex.Recursive) ## access to low level driver calls self.coherentLock = Mutex( QtCore.QMutex.Recursive) ## access to self.attributes self.coherentPower = 0 self.coherentWavelength = 0 self.mThread = CoherentThread(self, self.driver, self.driverLock) self.mThread.sigPowerChanged.connect(self.powerChanged) self.mThread.sigWavelengthChanged.connect(self.wavelengthChanged) self.mThread.start() Laser.__init__(self, dm, config, name) self.hasShutter = True self.hasTunableWavelength = True
def __init__(self, dm, config, name): Device.__init__(self, dm, config, name) OptomechDevice.__init__(self, dm, config, name) self.config = config self.configFile = os.path.join('devices', name + '_config.cfg') self.lock = Mutex(QtCore.QMutex.Recursive) self.port = config[ 'port'] ## windows com ports start at COM1, pyserial ports start at 0 # whether this device has an arduino interface protecting it from roe/serial collisions # (see acq4/drivers/SutterMP285/mp285_hack) # If not, then position monitoring is disabled. self.useArduino = config.get('useArduino', False) self.scale = config.pop('scale', (1, 1, 1)) # Interpret "COM1" as port 0 if isinstance(self.port, basestring) and self.port.lower()[:3] == 'com': self.port = int(self.port[3:]) - 1 self.baud = config.get('baud', 9600) ## 9600 is probably factory default self.pos = [0, 0, 0] self.limits = [[[0, False], [0, False]], [[0, False], [0, False]], [[0, False], [0, False]]] self.maxSpeed = 1e-3 self.loadConfig() self.mp285 = SutterMP285Driver(self.port, self.baud) self.driverLock = Mutex(QtCore.QMutex.Recursive) self.mThread = SutterMP285Thread(self, self.mp285, self.driverLock, self.scale, self.limits, self.maxSpeed) self.mThread.sigPositionChanged.connect(self.posChanged) if self.useArduino: self.mThread.start() dm.declareInterface(name, ['stage'], self)
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!")
def __init__(self, dm, config, name): Device.__init__(self, dm, config, name) self._DGLock = Mutex( Qt.QMutex.Recursive) ## protects access to _DGHolding, _DGConfig ## Do some sanity checks here on the configuration # 'channels' key is expected; for backward compatibility we just use the top-level config. config = config.get('channels', config) self._DGConfig = config self._DGHolding = {} for ch in config: if config[ch]['type'][0] != 'a' and ('scale' in config[ch] or 'offset' in config[ch]): raise Exception( "Scale/offset only allowed for analog channels. (%s.%s)" % (name, ch)) if 'scale' not in config[ch]: config[ch][ 'scale'] = 1 ## must be int to prevent accidental type conversion on digital data if 'offset' not in config[ch]: config[ch]['offset'] = 0 if config[ch].get('invert', False): if config[ch]['type'][0] != 'd': raise Exception( "Inversion only allowed for digital channels. (%s.%s)" % (name, ch)) config[ch]['scale'] = -1 config[ch]['offset'] = -1 #print "chan %s scale %f" % (ch, config[ch]['scale']) if 'holding' not in config[ch]: config[ch]['holding'] = 0.0 ## It is possible to create virtual channels with no real hardware connection if 'device' not in config[ch]: #print "Assuming channel %s is virtual:" % ch, config[ch] config[ch]['virtual'] = True ## set holding value for all output channels now if config[ch]['type'][1] == 'o': self.setChanHolding(ch, config[ch]['holding']) #self._DGHolding[ch] = config[ch]['holding'] dm.declareInterface(name, ['daqChannelGroup'], self) for ch in config: dm.declareInterface(name + "." + ch, ['daqChannel'], ChannelHandle(self, ch))
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)
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
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()
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()
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
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!")
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