def delegateTo(self, trigSource, trigLine, trigTime=0, responseTime=0): if isinstance(trigSource, str): trigSource = depot.getHandler(trigSource, depot.EXECUTOR) self._trigger = trigSource.registerDigital(self, trigLine) self.triggerNow = self._trigger.triggerNow self._triggerTime = trigTime self._responseTime = responseTime
def getHandlers(self): self.handlers.append(cockpit.handlers.lightPower.LightPowerHandler( self.name + ' power', # name self.name + ' light source', # groupName { 'setPower': self._setPower, 'getPower': self._getPower, }, self.config.get('wavelength', None), curPower=.2, isEnabled=True)) trigsource = self.config.get('triggersource', None) trigline = self.config.get('triggerline', None) if trigsource: trighandler = depot.getHandler(trigsource, depot.EXECUTOR) else: trighandler = None self._exposureTime = 100 self.handlers.append(cockpit.handlers.lightSource.LightHandler( self.name, self.name + ' light source', {'setEnabled': lambda name, on: self._setEnabled(on), 'setExposureTime': lambda name, value: setattr(self, '_exposureTime', value), 'getExposureTime': lambda name: self._exposureTime}, self.config.get('wavelength', None), 100, trighandler, trigline)) return self.handlers
def getHandlers(self): """Return camera handlers.""" trigsource = self.config.get('triggersource', None) trigline = self.config.get('triggerline', None) if trigsource: trighandler = depot.getHandler(trigsource, depot.EXECUTOR) else: trighandler = None result = cockpit.handlers.camera.CameraHandler( "%s" % self.name, "universal camera", {'setEnabled': self.enableCamera, 'getImageSize': self.getImageSize, 'getTimeBetweenExposures': self.getTimeBetweenExposures, 'prepareForExperiment': self.prepareForExperiment, 'getExposureTime': self.getExposureTime, 'setExposureTime': self.setExposureTime, 'getSavefileInfo': self.getSavefileInfo, 'makeUI': self.makeUI, 'softTrigger': self.softTrigger}, cockpit.handlers.camera.TRIGGER_SOFT, trighandler, trigline) # will be set with value from hardware later self.handlers = [result] return [result]
def getHandlers(self): """Return device handlers. Derived classes may override this.""" # Querying remote for maxPower can cause delays, so set to None # and update later. self.handlers.append(cockpit.handlers.lightPower.LightPowerHandler( self.name + ' power', # name self.name + ' light source', # groupName { 'setPower': cockpit.util.threads.callInNewThread(self._proxy.set_power_mw), 'getPower': self._proxy.get_power_mw, # Synchronous - can hang threads. }, self.config.get('wavelength', None), 0, None, 20, #minPower, maxPower, curPower, isEnabled=True)) trigsource = self.config.get('triggersource', None) trigline = self.config.get('triggerline', None) if trigsource: trighandler = depot.getHandler(trigsource, depot.EXECUTOR) else: trighandler = None self._exposureTime = 100 self.handlers.append(cockpit.handlers.lightSource.LightHandler( self.name, self.name + ' light source', {'setEnabled': lambda name, on: self._setEnabled(on), 'setExposureTime': lambda name, value: setattr(self, '_exposureTime', value), 'getExposureTime': lambda name: self._exposureTime}, self.config.get('wavelength', None), 100, trighandler, trigline)) return self.handlers
def getHandlers(self): asource = self.config.get('analogsource', None) aline = self.config.get('analogline', None) aHandler = depot.getHandler(asource, depot.EXECUTOR) if aHandler is None: raise Exception('No control source.') axis = AXIS_MAP[self.config.get('axis', 2)] offset = self.config.get('offset', 0) gain = self.config.get('gain', 1) posMin = self.config.get('min', None) posMax = self.config.get('max', None) posRange = self.config.get('range', None) haveMin, haveMax, haveRange = [ v is not None for v in [posMin, posMax, posRange] ] if haveMin and haveMax: pass elif (haveMin, haveMax, haveRange) == (True, False, True): posMax = posMin + posRange elif (haveMin, haveMax, haveRange) == (False, True, True): posMin = posMax - posRange elif (haveMin, haveMax, haveRange) == (False, False, True): # Assume range starts from zero. posMin = 0 posMax = posRange else: raise Exception('No min, max or range specified for stage %s.' % self.name) # TODO - consider moving stepSizes creation to the handler. stepSizes = [self.config.get('minstep', (posMax - posMin) * 1e-5)] m = 5 while True: next = m * stepSizes[-1] if next > (posMax - posMin) / 10.: break stepSizes.append(next) m = [2, 5][m == 2] result = [] # Create handler without movement callbacks. handler = stagePositioner.PositionerHandler( "%d %s" % (axis, self.name), "%d stage motion" % axis, True, { 'getMovementTime': lambda x, start, delta: (Decimal(0.05), Decimal(0.05)), 'cleanupAfterExperiment': None, 'setSafety': self.setSafety }, axis, stepSizes, min(4, len(stepSizes)), (posMin, posMax), (posMin, posMax)) # Connect handler to analogue source to populate movement callbacks. handler.connectToAnalogSource(aHandler, aline, offset, gain) result.append(handler) return result
def finalizeInitialization(self): ## Replace lights strings with their handlers. handlers = [] for name in self.lights: h = depot.getHandler(name, depot.LIGHT_TOGGLE) if h: handlers.append(h) self.lights = handlers # Register this shutter with the LightHandler class. LightHandler.addShutter(self, self.lights)
def updateAfterMove(self, *args): # Accept *args so that can be called directly as a Pyro callback # or an event handler. self.lastFilter = self.currentFilter() # Emission filters for camera in self.cameras: h = depot.getHandler(camera, depot.CAMERA) if h is not None: h.updateFilter(self.lastFilter.label, self.lastFilter.value) # Excitation filters for h in self.lights: pass
def changeDrawer(self, newSetting=None): if newSetting is None: ns = self.settings[0] else: ns = newSetting self.settingIndex = self.settings.index(ns) for cname in ns.cameraNames: h = depot.getHandler(cname, depot.CAMERA) h.updateFilter(ns.cameraToDye[cname], ns.cameraToWavelength[cname]) for i, b in enumerate(self.buttons): state = i == self.settingIndex b.updateState(state)
def getHandlers(self): # Fetch analog configuration asource = self.config.get('analogsource', None) aline = self.config.get('analogline', None) gain = self.config.get('gain', 1) offset = self.config.get('offset', 0) # Fetch source handler and generate line handler. exe = depot.getHandler(asource, depot.EXECUTOR) h = exe.registerAnalog(self, aline, offset, gain, self.getMovementTime) # Add indexed positions if specified in config. positions = self.config.get('positions', None) if positions: h.positions = map(float, re.split('[;,]\s*', positions)) return [h]
def getHandlers(self): asource = self.config.get('analogsource', None) aline = self.config.get('analogline', None) offset = self.config.get('offset', 0) gain = self.config.get('gain', 1) dt = Decimal(self.config.get('settlingtime', 0.05)) aHandler = depot.getHandler(asource, depot.EXECUTOR) if aHandler is None: raise Exception('No control source.') movementTimeFunc = lambda x, start, delta: (0, dt) handler = aHandler.registerAnalog(self, aline, offset, gain, movementTimeFunc) # Connect handler to analogue source to populate movement callbacks. handler.connectToAnalogSource(aHandler, aline, offset, gain) result.append(handler) return result
def augmentParams(self, params): self.saveSettings() params['numAngles'] = 3 params['numPhases'] = 5 params['collectionOrder'] = self.siCollectionOrder.GetStringSelection() params['angleHandler'] = depot.getHandlerWithName('SI angle') params['phaseHandler'] = depot.getHandlerWithName('SI phase') params['polarizerHandler'] = depot.getHandlerWithName('SI polarizer') params['slmHandler'] = depot.getHandler('slm', depot.EXECUTOR) compensations = {} for i, light in enumerate(self.allLights): val = guiUtils.tryParseNum(self.bleachCompensations[i], float) if val: # Convert from percentage to multiplier compensations[light] = .01 * float(val) else: compensations[light] = 0 params['bleachCompensations'] = compensations return params
def getHandlers(self): asource = self.config.get('analogsource', None) aline = self.config.get('analogline', None) aHandler = depot.getHandler(asource, depot.EXECUTOR) if aHandler is None: raise Exception('No control source.') axis = AXIS_MAP[self.config.get('axis', 2)] offset = self.config.get('offset', 0) gain = self.config.get('gain', 1) posMin = self.config.get('min', None) posMax = self.config.get('max', None) posRange = self.config.get('range', None) haveMin, haveMax, haveRange = [ v is not None for v in [posMin, posMax, posRange] ] if haveMin and haveMax: pass elif (haveMin, haveMax, haveRange) == (True, False, True): posMax = posMin + posRange elif (haveMin, haveMax, haveRange) == (False, True, True): posMin = posMax - posRange elif (haveMin, haveMax, haveRange) == (False, False, True): # Assume range starts from zero. posMin = 0 posMax = posRange else: raise Exception('No min, max or range specified for stage %s.' % self.name) result = [] # Create handler without movement callbacks. handler = stagePositioner.PositionerHandler( "%d %s" % (axis, self.name), "%d stage motion" % axis, True, { 'getMovementTime': lambda x, start, delta: (Decimal(0.05), Decimal(0.05)) }, axis, (posMin, posMax), (posMin, posMax)) # Connect handler to analogue source to populate movement callbacks. handler.connectToAnalogSource(aHandler, aline, offset, gain) result.append(handler) return result
def getHandlers(self): aSource = self.config.get('analogsource', None) aLine = self.config.get('analogline', None) aHandler = depot.getHandler(aSource, depot.EXECUTOR) if aHandler is None: raise Exception('No control source.') gain = self.config.get('gain', 1) offset = self.config.get('offset', 0) h = aHandler.registerAnalog(self, aLine, offset, gain) # If there are indexed positions in the config, add them to the handler. idlevoltage = self.config.get('idlevoltage', 0) voltages = {} for vdef in self.config.get('sivoltages', '').split('\n'): if vdef is '': continue key, values = vdef.strip('\n').split(':') voltages[key] = tuple([float(v) for v in values.split(',')]) if not set(['default', None]).intersection(voltages): voltages[None] = 3 * [idlevoltage] h.positions = voltages return [h]
def getHandlers(self): self.handlers = [] trigsource = self.config.get('triggersource', None) trigline = self.config.get('triggerline', None) if trigsource: trighandler = depot.getHandler(trigsource, depot.EXECUTOR) else: trighandler = None self._exposureTime = 100 self.handlers.append( cockpit.handlers.lightSource.LightHandler( self.name, self.name + ' light source', { 'setEnabled': lambda name, on: time.sleep(0.5), 'setExposureTime': lambda name, value: setattr(self, '_exposureTime', value), 'getExposureTime': lambda name: self._exposureTime }, self.config.get('wavelength', None), 100, trighandler, trigline)) return self.handlers
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Find out what devices we have to work with. lightToggles = depot.getHandlersOfType(depot.LIGHT_TOGGLE) ## Maps LightSource handlers to their associated panels of controls. self.lightToPanel = dict() # Construct the UI. # Sizer for all controls. We'll split them into bottom half (light # sources) and top half (everything else). self.Sizer = wx.BoxSizer(wx.VERTICAL) # Panel for holding the non-lightsource controls. topPanel = wx.Panel(self) self.topPanel = topPanel topSizer = wx.BoxSizer(wx.VERTICAL) # A row of buttons for various actions we know we can take. buttonSizer = wx.BoxSizer(wx.HORIZONTAL) # Abort button abortButton = wx.Button(topPanel, wx.ID_ANY, "abort") abortButton.SetLabelMarkup( "<span foreground='red'><big><b>ABORT</b></big></span>") abortButton.Bind(wx.EVT_BUTTON, lambda event: events.publish(events.USER_ABORT)) buttonSizer.Add(abortButton, 1, wx.EXPAND) # Experiment & review buttons for lbl, fn in (("Single-site\nexperiment", lambda evt: singleSiteExperiment.showDialog(self)), ("Multi-site\nexperiment", lambda evt: multiSiteExperiment.showDialog(self)), ("View last\nfile", self.onViewLastFile)): btn = wx.Button(topPanel, wx.ID_ANY, lbl) btn.Bind(wx.EVT_BUTTON, fn) buttonSizer.Add(btn, 1, wx.EXPAND) # Video mode button videoButton = wx.ToggleButton(topPanel, wx.ID_ANY, "Live") videoButton.Bind(wx.EVT_TOGGLEBUTTON, lambda evt: cockpit.interfaces.imager.videoMode()) events.subscribe(cockpit.events.VIDEO_MODE_TOGGLE, lambda state: videoButton.SetValue(state)) buttonSizer.Add(videoButton, 1, wx.EXPAND) # Snap image button snapButton = wx.Button(topPanel, wx.ID_ANY, "Snap\nimage") snapButton.Bind( wx.EVT_BUTTON, lambda evt: cockpit.interfaces.imager.imager.takeImage()) buttonSizer.Add(snapButton, 1, wx.EXPAND) # Increase font size in top row buttons. for w in [child.GetWindow() for child in buttonSizer.Children]: w.SetFont(w.GetFont().Larger()) topSizer.Add(buttonSizer) topSizer.AddSpacer(ROW_SPACER) # Make UIs for any other handlers / devices and insert them into # our window, if possible. # Light power things will be handled later. lightPowerThings = depot.getHandlersOfType(depot.LIGHT_POWER) lightPowerThings.sort(key=lambda l: l.wavelength) # Camera UIs are drawn seperately. Currently, they are drawn first, # but this separation may make it easier to implement cameras in # ordered slots, giving the user control over exposure order. cameraThings = depot.getHandlersOfType(depot.CAMERA) # Ignore anything that is handled specially. ignoreThings = lightToggles + lightPowerThings ignoreThings += cameraThings # Remove ignoreThings from the full list of devices. otherThings = list(depot.getAllDevices()) otherThings.sort(key=lambda d: d.__class__.__name__) otherThings.extend(depot.getAllHandlers()) rowSizer = wx.WrapSizer(wx.HORIZONTAL) # Add objective control # If only one objective device (usual), add to end of top row, # otherwise add to start of 2nd row. hs = depot.getHandlersOfType(depot.OBJECTIVE) if len(hs) == 1: buttonSizer.Add(mainPanels.ObjectiveControls(self.topPanel), flag=wx.LEFT, border=2) else: rowSizer.Add(mainPanels.ObjectiveControls(self.topPanel), flag=wx.EXPAND) rowSizer.AddSpacer(COL_SPACER) ignoreThings.extend(hs) # Make the UI elements for the cameras. rowSizer.Add(mainPanels.CameraControlsPanel(self.topPanel), flag=wx.EXPAND) rowSizer.AddSpacer(COL_SPACER) # Add light controls. lightfilters = sorted(depot.getHandlersOfType(depot.LIGHT_FILTER)) ignoreThings.extend(lightfilters) # Add filterwheel controls. rowSizer.Add(mainPanels.FilterControls(self.topPanel), flag=wx.EXPAND) # Make the UI elements for eveything else. for thing in ignoreThings: if thing in otherThings: otherThings.remove(thing) for thing in sorted(otherThings): if depot.getHandler(thing, depot.CAMERA): # Camera UIs already drawn. continue item = thing.makeUI(topPanel) if item is not None: itemsizer = wx.BoxSizer(wx.VERTICAL) itemsizer.Add( cockpit.gui.mainPanels.PanelLabel(topPanel, thing.name)) itemsizer.Add(item, 1, wx.EXPAND) if rowSizer.GetChildren(): # Add a spacer. rowSizer.AddSpacer(COL_SPACER) rowSizer.Add(itemsizer, flag=wx.EXPAND) topSizer.Add(rowSizer) topPanel.SetSizerAndFit(topSizer) self.Sizer.Add(topPanel, flag=wx.EXPAND) self.Sizer.AddSpacer(ROW_SPACER) ## Panel for holding light sources. self.Sizer.Add(mainPanels.LightControlsPanel(self), flag=wx.EXPAND) keyboard.setKeyboardHandlers(self) self.joystick = joystick.Joystick(self) self.SetDropTarget(viewFileDropTarget.ViewFileDropTarget(self)) # Show the list of windows on right-click. self.Bind(wx.EVT_CONTEXT_MENU, lambda event: keyboard.martialWindows(self))
def changeDrawer(self, newSetting: DrawerSettings) -> None: for cname in newSetting.cameraNames: handler = depot.getHandler(cname, depot.CAMERA) handler.updateFilter(newSetting.cameraToDye[cname], newSetting.cameraToWavelength[cname])