Пример #1
0
 def __init__(self, lightToSequence, lightToIsOnDuringAcquisition,
              **kwargs):
     # Convert from light source names to light handlers.
     self.lightToSequence = {}
     for name, sequence in lightToSequence.items():
         handler = depot.getHandlerWithName(name)
         self.lightToSequence[handler] = sequence
     self.lightToIsOnDuringAcquisition = {}
     for name, isOn in lightToIsOnDuringAcquisition.items():
         handler = depot.getHandlerWithName(name)
         self.lightToIsOnDuringAcquisition[handler] = isOn
     # Call the ZStackExperiment constructor with all of our remaining
     # parameters, which are in the "kwargs" dictionary object.
     super().__init__(**kwargs)
Пример #2
0
 def augmentParams(self, params):
     self.saveSettings()
     params['settlingTime'] = guiUtils.tryParseNum(self.settlingTimeControl, float)
     params['startV'] = guiUtils.tryParseNum(self.startVControl, float)
     params['maxV'] = guiUtils.tryParseNum(self.maxVControl, float)
     params['vSteps'] = guiUtils.tryParseNum(self.vStepsControl)
     params['polarizerHandler'] = depot.getHandlerWithName('SI polarizer')
     return params
Пример #3
0
 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
Пример #4
0
    def takeImage(self):
        if not self.digitalClients:
            # No triggered devices registered.
            return
        camlines = sum([1<<self.digitalClients[cam] for cam in self.activeCameras])

        # We want to know if there are cameras using rolling shutter. If so, cameras must be triggered in advance
        exposureStartTime = [cam.getTimeBetweenExposures() for cam in self.activeCameras
                             if cam.getShutteringMode() == ElectronicShutteringMode.ROLLING]
        exposureStartTime = max(exposureStartTime, default=0)

        if camlines == 0:
            # No cameras to be triggered.
            return

        ltpairs = []
        for light in self.activeLights:
            lline = 1 << self.digitalClients[light]
            ltime = light.getExposureTime()
            ltpairs.append((lline, ltime))

        # Sort by exposure time
        ltpairs.sort(key = lambda item: item[1])

        # Generate a sequence of (time, digital state)
        # TODO: currently uses bulb exposure; should support other modes.
        if ltpairs:
            # Start by all active cameras and lights.
            state = camlines | functools.reduce(operator.ior, list(zip(*ltpairs))[0])
            if exposureStartTime != 0:
                seq = [(0, camlines)]
            seq.append((exposureStartTime, state))
            # Switch off each light as its exposure time expires.
            for lline, ltime in ltpairs:
                state -= lline
                seq.append((exposureStartTime + ltime, state))
        else:
            # No lights. Just trigger the cameras.
            seq = [(0, camlines)]

        # If there is an ambient light enabled, extend exposure as
        # necessary (see issue #669).
        ambient = depot.getHandlerWithName('Ambient')
        if ambient is not None and ambient.getIsEnabled():
            t = ambient.getExposureTime()
            if t > seq[-1][0]:
                seq.append((ambient.getExposureTime(), 0))

        # Switch all lights and cameras off.
        seq.append( (seq[-1][0] + 1, 0) )
        if self.callbacks.get('runSequence', None):
            self.callbacks['runSequence'](seq)
        else:
            self.softSequence(seq)
Пример #5
0
    def takeImage(self):
        if not self.digitalClients:
            # No triggered devices registered.
            return
        camlines = sum(
            [1 << self.digitalClients[cam] for cam in self.activeCameras])

        if camlines == 0:
            # No cameras to be triggered.
            return

        ltpairs = []
        for light in self.activeLights:
            lline = 1 << self.digitalClients[light]
            ltime = light.getExposureTime()
            ltpairs.append((lline, ltime))

        # Sort by exposure time
        ltpairs.sort(key=lambda item: item[1])

        # Generate a sequence of (time, digital state)
        # TODO: currently uses bulb exposure; should support other modes.
        if ltpairs:
            # Start by all active cameras and lights.
            state = camlines | functools.reduce(operator.ior,
                                                list(zip(*ltpairs))[0])
            seq = [(0, state)]
            # Switch off each light as its exposure time expires.
            for lline, ltime in ltpairs:
                state -= lline
                seq.append((ltime, state))
        else:
            # No lights. Just trigger the cameras.
            seq = [(0, camlines)]
        ambient = depot.getHandlerWithName('ambient')
        # If ambient light is enabled, extend exposure if necessary.
        if ambient.getIsEnabled():
            t = ambient.getExposureTime()
            if t > seq[-1][0]:
                seq.append((ambient.getExposureTime(), 0))
        # Switch all lights and cameras off.
        seq.append((seq[-1][0] + 1, 0))
        if self.callbacks.get('runSequence', None):
            self.callbacks['runSequence'](seq)
        else:
            self.softSequence(seq)
Пример #6
0
 def setDetMode(self, mode):
     for mirrorIndex, isUp in self.modeToFlips[mode]:
         self.flipDownUp(mirrorIndex, isUp)
     for button in self.detPathButtons:
         button.setActive(button.GetLabel() == mode)
     self.curDetMode = mode
     #IMD 20150129 - flipping buttons for detection path also changes objective
     # set correct pixel size and image orientation
     objectiveHandler = depot.getHandlerWithName('objective')
     if mode == 'with AO & 85 nm pixel size':
         if (objectiveHandler.curObjective != '63x85nm'):
             objectiveHandler.changeObjective('63x85nm')
             print("Change objective 85 nm pixel")
     elif mode == 'w/o AO & 209 nm pixel size':
         if (objectiveHandler.curObjective != '63x209nm'):
             objectiveHandler.changeObjective('63x209nm')
             print("Change objective 209 nm pixel")
Пример #7
0
    def onLoadExposureSettings(self, event=None):
        dialog = wx.FileDialog(
            self,
            style=wx.FD_OPEN,
            wildcard='*.txt',
            message="Please select the settings file to load.",
            defaultDir=cockpit.util.files.getUserSaveDir())
        if dialog.ShowModal() != wx.ID_OK:
            # User cancelled.
            self.pathButton.setOption(self.currentPath)
            return
        handle = open(dialog.GetPath(), 'r')
        modeName = os.path.splitext(os.path.basename(handle.name))[0]
        #get name for new mode
        # abuse get value dialog which will also return a string.
        name = cockpit.gui.dialogs.getNumberDialog.getNumberFromUser(
            parent=self.topPanel,
            default=modeName,
            title='New Path Name',
            prompt='Name')
        if name not in self.paths:
            self.pathList.append(name)
        self.paths[name] = json.loads('\n'.join(handle.readlines()))
        handle.close()
        events.publish('load exposure settings', self.paths[name])
        #update button list
        self.pathButton.setOptions(
            map(lambda name: (name, lambda n=name: self.setPath(n)),
                self.pathList))
        #and set button value.
        self.pathButton.setOption(name)
        self.currentPath = name

        # If we're using the listbox approach to show/hide light controls,
        # then make sure all enabled lights are shown and vice versa.
        if self.lightList is not None:
            for i, name in enumerate(self.lightList.GetItems()):
                handler = depot.getHandlerWithName(name)
                self.lightList.SetStringSelection(name, handler.getIsEnabled())
            self.onLightSelect()
Пример #8
0
    def takeBurst(self, frameCount=10):
        """
        Use the internal triggering of the camera to take a burst of images

        Experimental
        """
        cameraMask = 0
        lightTimePairs = list()
        maxTime = 0
        for handler, line in self.handlerToDigitalLine.items():
            if handler.name in self.activeLights:
                maxTime = max(maxTime, handler.getExposureTime())
                exposureTime = handler.getExposureTime()
                lightTimePairs.append((line, exposureTime))
                maxTime = max(maxTime, exposureTime)
        for name, line in self.nameToDigitalLine.items():
            if name in self.activeCameras:
                cameraMask += line
                handler = depot.getHandlerWithName(name)
                handler.setExposureTime(maxTime)

        sleep(5)
Пример #9
0
    def executeRep(self, repNum):
        # Get all light sources that the microscope has.
        allLights = depot.getHandlersOfType(depot.LIGHT_TOGGLE)
        # getHandlersOfType returns an unordered set datatype. If we want to
        # index into allLights, we need to convert it to a list first.
        allLights = list(allLights)
        # Print the names of all light sources.
        for light in allLights:
            print(light.name)
        # Get all power controls for light sources.
        allLightPowers = depot.getHandlersOfType(depot.LIGHT_POWER)

        # Get all camera handlers that the microscope has, and filter it
        # down to the ones that are currently active.
        allCameras = depot.getHandlersOfType(depot.CAMERA)
        # Create a new empty list.
        activeCams = []
        for camera in allCameras:
            if camera.getIsEnabled():
                # Camera is enabled.
                activeCams.append(camera)

        # Get a specific light.
        led650 = depot.getHandlerWithName("650 LED")

        # Get a specific light's power control (ditto).
        led650power = depot.getHandlerWithName("650 LED power")

        # Set the output power to use for this light source, when it is active.
        led650power.setPower(2.5)

        # Set this light source to be continually exposing.
        led650.setExposing(True)

        # Wait for some time (1.5 seconds in this case).
        time.sleep(1.5)

        # Set this light source to stop continually exposing.
        led650.setExposing(False)

        # Get another light source.
        laser488 = depot.getHandlerWithName("488 L")

        # Set this light source to be enabled when we take images.
        # Note: for lasers, an AOM in the laser box that acts as a light
        # shutter is automatically adjusted when you enable/disable lights.
        # I don't know how well enabling multiple lasers simultaneously works.
        # Note: lasers, the DIA light source, and the EPI light source, are
        # mutually exclusive as they use different shutters and only one
        # shutter can be active at a time for some unknown reason.
        laser488.setEnabled(True)

        # Take images, using all current active camera views and light
        # sources; wait for the image (and time of acquisition) from the named
        # camera to be available.
        # Note: The light sources selected automatically use the emission
        # filter you have set in the UI. If multiple lights use the same
        # emission filter, then they will expose simultaneously (if possible).
        # Note: that if you try to wait for an image
        # that will never arrive (e.g. for the wrong camera name) then your
        # script will get stuck at this point.
        # Note: you must have at least one light source enabled for any
        # image to be taken!
        eventName = 'new image %s' % activeCams[0].name
        image, timestamp = events.executeAndWaitFor(
            eventName, cockpit.interfaces.imager.takeImage, shouldBlock=True)

        # Get the min, max, median, and standard deviation of the image
        imageMin = image.min()
        imageMax = image.max()
        imageMedian = numpy.median(image)
        imageStd = numpy.std(image)

        print("Image stats:", imageMin, imageMax, imageMedian, imageStd)

        # Some miscellaneous functions below.

        # Get the current stage position; positions are in microns.
        curX, curY, curZ = cockpit.interfaces.stageMover.getPosition()
        # Move to a new Z position, and wait until we arrive.
        cockpit.interfaces.stageMover.goToZ(curZ + 5, shouldBlock=True)
        # Move to a new XY position.
        # Note: the goToXY function expects a "tuple" for the position,
        # hence the extra parentheses (i.e. "goToXY(x, y)" is invalid;
        # "goToXY((x, y))" is correct).
        cockpit.interfaces.stageMover.goToXY((curX + 50, curY - 50),
                                             shouldBlock=True)

        # Get the device responsible for the dichroics and light sources
        lightsDevice = depot.getDevice(cockpit.devices.lights)
        # Set a new filter/dichroic for the lower turret.
        lightsDevice.setFilter(isFirstFilter=True, label="2-488 L")
        # Set a new filter/dichroic for the upper turret.
        lightsDevice.setFilter(isFirstFilter=False, label="6-600bp")
Пример #10
0
    def executeRep(self, repNum):
        # Get all light sources that the microscope has.
        allLights = depot.getHandlersOfType(depot.LIGHT_TOGGLE)
        # getHandlersOfType returns an unordered set datatype. If we want to
        # index into allLights, we need to convert it to a list first.
        allLights = list(allLights)
        # Print the names of all light sources.
        for light in allLights:
            print(light.name)
        # Get all power controls for light sources.
        allLightPowers = depot.getHandlersOfType(depot.LIGHT_POWER)
        # Get all light source filters.
        allLightFilters = depot.getHandlersOfType(depot.LIGHT_FILTER)

        # Get all camera handlers that the microscope has, and filter it
        # down to the ones that are currently active.
        allCameras = depot.getHandlersOfType(depot.CAMERA)
        # Create a new empty list.
        activeCams = []
        for camera in allCameras:
            if camera.getIsEnabled():
                # Camera is enabled.
                activeCams.append(camera)

        # Get a specific light.
        deepstar405 = depot.getHandlerWithName("488 Deepstar")

        deepstar405power = depot.getHandlerWithName("488 Deepstar power")

        # Set the output power to use for this light source, when it is active.
        deepstar405power.setPower(15)

        # Get another light source. The "\n" in the name is a newline, which
        # was inserted (when this light source handler was created) to make
        # the light control button look nice.
        laser488 = depot.getHandlerWithName("488\nlight")

        # Set this light source to be enabled when we take images.
        laser488.setEnabled(True)

        # Take images, using all current active camera views and light
        # sources; wait for the image (and time of acquisition) from the named
        # camera to be available.
        # Note: that if you try to wait for an image
        # that will never arrive (e.g. for the wrong camera name) then your
        # script will get stuck at this point.
        eventName = 'new image %s' % activeCams[0].name
        image, timestamp = events.executeAndWaitFor(
            eventName, cockpit.interfaces.imager.takeImage, shouldBlock=True)

        # Get the min, max, median, and standard deviation of the image
        imageMin = image.min()
        imageMax = image.max()
        imageMedian = numpy.median(image)
        imageStd = numpy.std(image)

        print("Image stats:", imageMin, imageMax, imageMedian, imageStd)

        # Some miscellaneous functions below.

        # Get the current stage position; positions are in microns.
        curX, curY, curZ = cockpit.interfaces.stageMover.getPosition()
        # Move to a new Z position, and wait until we arrive.
        cockpit.interfaces.stageMover.goToZ(curZ + 5, shouldBlock=True)
        # Move to a new XY position.
        # Note: the goToXY function expects a "tuple" for the position,
        # hence the extra parentheses (i.e. "goToXY(x, y)" is invalid;
        # "goToXY((x, y))" is correct).
        cockpit.interfaces.stageMover.goToXY((curX + 50, curY - 50),
                                             shouldBlock=True)
Пример #11
0
    def generateActions(self):
        table = actionTable.ActionTable()
        # Open all light sources for the duration of the experiment.
        # Normally the delay generator logic would do this for us.
        for cameras, exposures in self.exposureSettings:
            for light, exposureTime in exposures:
                table.addAction(0, light, True)
        shutter = depot.getHandlerWithName('488 shutter')
        delayGen = depot.getHandlerWithName('Delay generator trigger')
        curTime = 0
        table.addAction(curTime, shutter, True)
        prevAltitude = None
        numZSlices = int(math.ceil(self.zHeight / self.sliceHeight))
        for zIndex in range(numZSlices):
            # Move to the next position, then wait for the stage to
            # stabilize.
            zTarget = self.zStart + self.sliceHeight * zIndex
            motionTime, stabilizationTime = 0, 0
            if prevAltitude is not None:
                motionTime, stabilizationTime = self.zPositioner.getMovementTime(
                    prevAltitude, zTarget)
            table.addAction(curTime + motionTime, self.zPositioner, zTarget)
            curTime += motionTime + stabilizationTime
            prevAltitude = zTarget

            # Trigger the delay generator. Do it slightly *after* the trigger
            # of the cameras below, so that we ensure the first exposure, which
            # may be very brief, is fully-contained in a camera exposure.
            table.addToggle(curTime + decimal.Decimal('.5'), delayGen)
            # Trigger the cameras twice. Lazy; only allow one set of cameras.
            cameras = self.exposureSettings[0][0]
            for camera in cameras:
                table.addToggle(curTime, camera)
                table.addToggle(curTime + self.exposureDelay, camera)
                self.cameraToImageCount[camera] += 2
            maxCamDelay = max(
                c.getTimeBetweenExposures(isExact=True) for c in cameras)
            # Wait for the exposure to complete and/or for the cameras to be
            # ready again.
            longExposureTime = self.exposureSettings[0][1][0][
                1] * self.exposureMultiplier
            curTime += self.exposureDelay + max(
                maxCamDelay, self.exposureDelay + longExposureTime)
            # Plus a little extra for the cameras to recover.
            # \todo This seems a bit excessive; why do we need to wait so
            # long for the Zyla to be ready?
            curTime += decimal.Decimal('10')
            # Hold the Z motion flat during the exposure.
            table.addAction(curTime, self.zPositioner, zTarget)

        # Close all light sources we opened at the start.
        # Normally the delay generator logic would do this for us.
        for cameras, exposures in self.exposureSettings:
            for light, exposureTime in exposures:
                table.addAction(curTime, light, False)

        # Move back to the start so we're ready for the next rep.
        motionTime, stabilizationTime = self.zPositioner.getMovementTime(
            self.zHeight, 0)
        curTime += motionTime
        table.addAction(curTime, self.zPositioner, 0)

        # Hold flat for the stabilization time, and any time needed for
        # the cameras to be ready. Only needed if we're doing multiple
        # reps, so we can proceed immediately to the next one.
        cameraReadyTime = 0
        if self.numReps > 1:
            for cameras, lightTimePairs in self.exposureSettings:
                for camera in cameras:
                    cameraReadyTime = max(
                        cameraReadyTime,
                        self.getTimeWhenCameraCanExpose(table, camera))
        table.addAction(max(curTime + stabilizationTime, cameraReadyTime),
                        self.zPositioner, 0)

        return table