Exemple #1
0
 def resetCams(self, curTime, cameras, table):
     resetEndTime = curTime
     for camera in cameras:
         exposureStart = max(curTime,
                             self.getTimeWhenCameraCanExpose(table, camera))
         # Cameras that have a pre-set exposure time can only use that
         # exposure time for clearing the sensor, hence why we take the
         # maximum of the min exposure time and the current exposure time.
         # \todo Is it possible for getExposureTime() to be less than
         # getMinExposureTime()? That would be a bug, right?
         minExposureTime = max(decimal.Decimal('.1'),
                               camera.getMinExposureTime(isExact=True),
                               camera.getExposureTime(isExact=True))
         exposureMode = camera.getExposureMode()
         if exposureMode == cockpit.handlers.camera.TRIGGER_AFTER:
             table.addToggle(exposureStart + minExposureTime, camera)
         elif exposureMode == cockpit.handlers.camera.TRIGGER_DURATION:
             table.addAction(exposureStart, camera, True)
             table.addAction(exposureStart + minExposureTime, camera, False)
         else:  # TRIGGER_BEFORE case
             table.addToggle(exposureStart, camera)
         resetEndTime = max(resetEndTime, exposureStart + minExposureTime)
         self.cameraToImageCount[camera] += 1
         self.cameraToIgnoredImageIndices[camera].add(
             self.cameraToImageCount[camera])
         self.cameraToIsReady[camera] = True
     return resetEndTime + decimal.Decimal('1e-6')
    def run(self):
        # For debugging purposes
        experiment.lastExperiment = self
        
        self.sanityCheckEnvironment()
        self.prepareHandlers()

        self.cameraToReadoutTime = dict([(c, c.getTimeBetweenExposures(isExact = True)) for c in self.cameras])
        for camera, readTime in self.cameraToReadoutTime.items():
            if type(readTime) is not decimal.Decimal:
                raise RuntimeError("Camera %s did not provide an exact (decimal.Decimal) readout time" % camera.name)

        for camera, func in self.camToFunc.items():
            events.subscribe(events.NEW_IMAGE % camera.name, func)
        for exposureTime in self.exposureTimes:
            if self.shouldAbort:
                break
            self.camToImages = {}
            self.camToNumImagesReceived = {}
            self.camToLock = {}
            for camera in self.cameras:
                # Prepare a memory buffer to store images in.
                width, height = camera.getImageSize()
                self.camToImages[camera] = numpy.zeros((self.numExposures, height, width))
                self.camToNumImagesReceived[camera] = 0
                self.camToLock[camera] = threading.Lock()
                # Indicate any frame transfer cameras for reset at start of
                # table.
                if camera.getExposureMode() == cockpit.handlers.camera.TRIGGER_AFTER:
                    self.cameraToIsReady[camera] = False
                
            self.table = self.generateActions(exposureTime)
            self.table.sort()
            self.examineActions()
            self.table.sort()
            self.table.enforcePositiveTimepoints()
            self.lastMinuteActions()
            self.doneReceivingThread = threading.Thread(target = self.waiter)
            self.doneReceivingThread.start()
            self.execute()
            
            if self.shouldAbort:
                break
            
            # Wait until it's been a short time after the last received image.
            self.doneReceivingThread.join()
            progress = cockpit.gui.progressDialog.ProgressDialog("Processing images", 
                    "Processing images for exposure time %.4f" % exposureTime,
                    parent = None)
            self.processImages(exposureTime)
            progress.Destroy()

        for camera, func in self.camToFunc.items():
            events.unsubscribe(events.NEW_IMAGE % camera.name, func)

        self.save()
        self.showResults()
        self.cleanup()
Exemple #3
0
    def getTimeWhenCameraCanExpose(self, table, camera):
        lastUseTime, action = table.getLastActionFor(camera)
        if lastUseTime is None:
            # No actions yet; assume camera is ready at the start of the
            # experiment.
            return 0

        nextUseTime = lastUseTime
        if camera.getExposureMode() == cockpit.handlers.camera.TRIGGER_BEFORE:
            # The camera actually finished exposing (and started reading
            # out) some time after lastUseTime, depending on its declared
            # exposure time.
            nextUseTime += camera.getExposureTime(isExact=True)
        nextUseTime += self.cameraToReadoutTime[camera] + decimal.Decimal(0.1)
        return nextUseTime
Exemple #4
0
    def run(self):
        # For debugging purposes
        experiment.lastExperiment = self

        self.sanityCheckEnvironment()
        self.prepareHandlers()

        self.cameraToReadoutTime = dict([
            (c, c.getTimeBetweenExposures(isExact=True)) for c in self.cameras
        ])
        for camera, readTime in self.cameraToReadoutTime.items():
            if type(readTime) is not decimal.Decimal:
                raise RuntimeError(
                    "Camera %s did not provide an exact (decimal.Decimal) readout time"
                    % camera.name)

        # Start out with no-exposure-time images to get a measured offset.
        multiplier = 0
        for camera, func in self.camToFunc.items():
            events.subscribe(events.NEW_IMAGE % camera.name, func)
        activeCameras = set(self.cameras)
        for i in range(self.numCollections):
            if not activeCameras or self.shouldAbort:
                break
            print("Running with cams", activeCameras)
            self.camToImages = {}
            self.camToNumImagesReceived = {}
            self.camToLock = {}
            for camera in activeCameras:
                # Prepare a memory buffer to store images in.
                width, height = camera.getImageSize()
                self.camToImages[camera] = numpy.zeros(
                    (self.numExposures, height, width))
                self.camToNumImagesReceived[camera] = 0
                self.camToLock[camera] = threading.Lock()
                # Indicate any frame transfer cameras for reset at start of
                # table.
                if camera.getExposureMode(
                ) == cockpit.handlers.camera.TRIGGER_AFTER:
                    self.cameraToIsReady[camera] = False

            self.table = self.generateActions(multiplier, activeCameras)
            self.table.sort()
            self.examineActions()
            self.table.sort()
            self.table.enforcePositiveTimepoints()
            self.lastMinuteActions()
            self.doneReceivingThread = threading.Thread(target=self.waiter)
            self.doneReceivingThread.start()
            self.execute()
            # Wait until it's been a short time after the last received image.
            self.doneReceivingThread.join()

            if multiplier == 0:
                multiplier = decimal.Decimal(1)
            else:
                multiplier *= self.exposureMultiplier
            activeCameras = self.processImages(multiplier)
            print("Came out with active cams", activeCameras)

        for camera, func in self.camToFunc.items():
            events.unsubscribe(events.NEW_IMAGE % camera.name, func)

        if self.shouldAbort:
            # Don't bother processing images.
            self.cleanup()
            return

        results = []
        for camera in self.cameras:
            results.append(self.makeFit(self.camToAverages[camera]))
        results = numpy.array(results, dtype=numpy.float32)
        results.shape = len(
            self.cameras), 1, 2, results.shape[-2], results.shape[-1]

        # Construct a header for the image data.
        pixel_size = wx.GetApp().Objectives.GetPixelSize()
        wavelengths = [c.wavelength for c in self.cameras]
        header = cockpit.util.datadoc.makeHeaderFor(results,
                                                    XYSize=pixel_size,
                                                    ZSize=0,
                                                    wavelengths=wavelengths)

        filehandle = open(self.savePath, 'wb')
        cockpit.util.datadoc.writeMrcHeader(header, filehandle)
        filehandle.write(results)
        filehandle.close()

        self.cleanup()
Exemple #5
0
    def expose(self,
               curTime,
               cameras,
               lightTimePairs,
               table,
               pseudoGlobalExposure=False,
               previousMovementTime=0):
        # First, determine which cameras are not ready to be exposed, because
        # they may have seen light they weren't supposed to see (due to

        # bleedthrough from other cameras' exposures). These need
        # to be triggered (and we need to record that we want to throw away
        # those images) before we can proceed with the real exposure.
        camsToReset = set()
        for camera in cameras:
            if not self.cameraToIsReady[camera]:
                camsToReset.add(camera)
        if camsToReset:
            curTime = self.resetCams(curTime, camsToReset, table)
        # Figure out when we can start the exposure, based on the cameras
        # involved: their exposure modes, readout times, and last trigger
        # times determine how soon we can next trigger them (see
        # getTimeWhenCameraCanExpose() for more information).
        exposureStartTime = curTime
        # Adjust the exposure start based on when the cameras are ready.
        for camera in cameras:
            camExposureReadyTime = self.getTimeWhenCameraCanExpose(
                table, camera)
            # we add the readout time to get when the light should be trigger to
            # obtain pseudo global exposure
            camPseudoGlobalReadyTime = (camExposureReadyTime +
                                        self.cameraToReadoutTime[camera])
            exposureStartTime = max(exposureStartTime, camExposureReadyTime)

        # Determine the maximum exposure time, which depends on our light
        # sources as well as how long we have to wait for the cameras to be
        # ready to be triggered.
        maxExposureTime = 0
        if lightTimePairs:
            maxExposureTime = max(lightTimePairs, key=lambda a: a[1])[1]
        # Check cameras to see if they have minimum exposure times; take them
        # into account for when the exposure can end. Additionally, if they
        # are frame-transfer cameras, then we need to adjust maxExposureTime
        # to ensure that our triggering of the camera does not come too soon
        # (while it is still reading out the previous frame).

        for camera in cameras:
            maxExposureTime = max(maxExposureTime,
                                  camera.getMinExposureTime(isExact=True))
            if camera.getExposureMode(
            ) == cockpit.handlers.camera.TRIGGER_AFTER:
                nextReadyTime = self.getTimeWhenCameraCanExpose(table, camera)
                # Ensure camera is exposing for long enough to finish reading
                # out the last frame.
                maxExposureTime = max(maxExposureTime,
                                      nextReadyTime - exposureStartTime)

        # Open the shutters for the specified exposure times, centered within
        # the max exposure time.
        # Note that a None value here means the user wanted to expose the
        # cameras without any special light.
        exposureEndTime = exposureStartTime + maxExposureTime
        for light, exposureTime, in lightTimePairs:
            if light is not None and light.name is not 'ambient':  # i.e. not ambient light
                # Center the light exposure.
                timeSlop = maxExposureTime - exposureTime
                offset = timeSlop / 2
                table.addAction(exposureEndTime - exposureTime - offset, light,
                                True)
                table.addAction(exposureEndTime - offset, light, False)
            # Record this exposure time.
            if exposureTime not in self.lightToExposureTime[light]:
                self.lightToExposureTime[light].add(exposureTime)

        # Trigger the cameras. Keep track of which cameras we *aren't* using
        # here; if they are continuous-exposure cameras, then they may have
        # seen light that they shouldn't have, and need to be invalidated.

        usedCams = set()
        for camera in cameras:
            usedCams.add(camera)
            mode = camera.getExposureMode()
            if mode == cockpit.handlers.camera.TRIGGER_AFTER:
                table.addToggle(exposureEndTime, camera)
            elif mode == cockpit.handlers.camera.TRIGGER_DURATION:
                table.addAction(exposureStartTime, camera, True)
                table.addAction(exposureEndTime, camera, False)
            elif mode == cockpit.handlers.camera.TRIGGER_DURATION_PSEUDOGLOBAL:
                # We added some security time to the readout time that
                # we have to remove now
                cameraExposureStartTime = (exposureStartTime -
                                           self.cameraToReadoutTime[camera] -
                                           decimal.Decimal(0.005))
                table.addAction(cameraExposureStartTime, camera, True)
                table.addAction(exposureEndTime, camera, False)
            elif mode == cockpit.handlers.camera.TRIGGER_BEFORE:
                table.addToggle(exposureStartTime, camera)
            elif mode == cockpit.handlers.camera.TRIGGER_SOFT:
                table.addAction(exposureStartTime, camera, True)
            else:
                raise Exception('%s has no trigger mode set.' % camera)
            self.cameraToImageCount[camera] += 1
        for camera in self.cameras:
            if (camera not in usedCams and camera.getExposureMode()
                    == cockpit.handlers.camera.TRIGGER_AFTER):
                # Camera is a continuous-exposure/frame-transfer camera
                # and therefore saw light it shouldn't have; invalidate it.
                self.cameraToIsReady[camera] = False

        return exposureEndTime
Exemple #6
0
    def run(self):
        # Returns True to close config dialog box, False or None otherwise.
        # Check if the user is set to save to an already-existing file.
        if self.savePath and os.path.exists(self.savePath):
            if not guiUtils.getUserPermission(
                ("The file:\n%s\nalready exists. " % self.savePath) +
                    "Are you sure you want to overwrite it?"):
                return False

        global lastExperiment
        lastExperiment = self
        self.sanityCheckEnvironment()
        self.prepareHandlers()

        self.cameraToReadoutTime = {
            c: c.getTimeBetweenExposures(isExact=True)
            for c in self.cameras
        }
        for camera, readTime in self.cameraToReadoutTime.items():
            if type(readTime) is not decimal.Decimal:
                raise RuntimeError(
                    "Camera %s did not provide an exact (decimal.Decimal) readout time"
                    % camera.name)

        # Indicate any frame transfer cameras for reset at start of table.
        for camera in self.cameras:
            if camera.getExposureMode(
            ) == cockpit.handlers.camera.TRIGGER_AFTER:
                self.cameraToIsReady[camera] = False

        self.createValidActionTable()
        if self.numReps > 1 and self.repDuration < self.table.lastActionTime / 1000:
            warning = "Repeat duration is less than the time required to run " \
                      "one repeat. Choose:" \
                      "\n    'OK' to run repeats as fast as possible;" \
                      "\n    'Cancel' to go back and change parameters."
            if not guiUtils.getUserPermission(warning):
                return False

        # ToDo: check duration of action table against timelapse settings
        # display appropriate warnings.
        self.lastMinuteActions()

        self._run_thread = threading.Thread(target=self.execute,
                                            name="Experiment-execute")
        self._run_thread.start()

        saveThread = None
        if self.savePath and max(self.cameraToImageCount.values()):

            cameraToExcitation = {c: 0.0 for c in self.cameras}
            for cameras, lightTimePairs in self.exposureSettings:
                ## If there's multiple light sources for the same
                ## camera pick the one with highest wavelength.  Main
                ## case of multiple light sources is single molecule
                ## localisation where a lower wavelength is doing the
                ## pumping while but excitation for fluorescence is
                ## with the higher wavelength.
                if lightTimePairs:
                    max_wavelength = max(
                        [l.wavelength for l, t in lightTimePairs])
                else:
                    max_wavelength = 0.0
                for camera in cameras:
                    if camera not in self.cameras:
                        continue
                    cameraToExcitation[camera] = max(
                        cameraToExcitation[camera], max_wavelength)

            saver = dataSaver.DataSaver(self.cameras, self.numReps,
                                        self.cameraToImageCount,
                                        self.cameraToIgnoredImageIndices,
                                        self._run_thread,
                                        self.savePath, self.sliceHeight,
                                        self.generateTitles(),
                                        cameraToExcitation)
            saver.startCollecting()
            saveThread = threading.Thread(target=saver.executeAndSave,
                                          name="Experiment-execute-save")
            saveThread.start()
            generatedFilenames.append(saver.getFilenames())

        cleanup_thread = threading.Thread(target=self.cleanup,
                                          args=[self._run_thread, saveThread],
                                          name="Experiment-cleanup")
        cleanup_thread.start()
        return True