Exemplo n.º 1
0
    def __init__(self):
        ## Maps axis to the handlers for that axis, sorted by their range of
        # motion.
        self.axisToHandlers = depot.getSortedStageMovers()

        ## XXX: We have a single index for all axis, even though each
        ## axis may have a different number of stages.  While we don't
        ## refactor this assumption, we just make copies of the movers
        ## with the most precise movement (issues #413 and #415)
        self.n_stages = max([len(s) for s in self.axisToHandlers.values()])
        for axis, stages in self.axisToHandlers.items():
            stages.extend([stages[-1]] * (self.n_stages - len(stages)))

        ## Indicates which stage handler is currently under control.
        self.curHandlerIndex = 0
        ## Maps Site unique IDs to Site instances.
        self.idToSite = {}
        ## Maps handler names to events indicating if those handlers
        # have stopped moving.
        self.nameToStoppedEvent = {}
        events.subscribe("stage mover", self.onMotion)
        events.subscribe("stage stopped", self.onStop)
        ## Device-speficic primitives to draw on the macrostage.
        self.primitives = set()
        for h in depot.getHandlersOfType(depot.STAGE_POSITIONER):
            ps = h.getPrimitives()
            if ps:
                self.primitives.update(ps)
        self.primitives.discard(None)
Exemplo n.º 2
0
    def __init__(self):
        ## Maps axis to the handlers for that axis, sorted by their range of
        # motion.
        self.axisToHandlers = depot.getSortedStageMovers()
        if set(self.axisToHandlers.keys()) != {0, 1, 2}:
            raise ValueError('stage mover requires 3 axis: X, Y, and Z')

        # FIXME: we should have sensible defaults.
        self._saved_top = userConfig.getValue('savedTop', default=3010.0)
        self._saved_bottom = userConfig.getValue('savedBottom', default=3000.0)

        ## XXX: We have a single index for all axis, even though each
        ## axis may have a different number of stages.  While we don't
        ## refactor this assumption, we just make copies of the movers
        ## with the most precise movement (issues #413 and #415)
        self.n_stages = max([len(s) for s in self.axisToHandlers.values()])
        for axis, stages in self.axisToHandlers.items():
            stages.extend([stages[-1]] * (self.n_stages - len(stages)))

        ## Indicates which stage handler is currently under control.
        self.curHandlerIndex = 0
        ## Maps Site unique IDs to Site instances.
        self.idToSite = {}

        # Compute the hard motion limits for each axis as the
        # summation of all limits for handlers on that axis.
        hard_limits = [None] * 3
        for axis in range(3):
            lower = 0.0
            upper = 0.0
            # We need set() to avoid duplicated handlers, and we might
            # have duplicated handlers because of the hack to meet
            # cockpit requirements that all axis have the same number
            # of handlers (see comments on issue #413).
            for handler in set(self.axisToHandlers[axis]):
                handler_limits = handler.getHardLimits()
                lower += handler_limits[0]
                upper += handler_limits[1]
            hard_limits[axis] = (lower, upper)
        # Use a tuple to prevent changes to it, and assemble it like
        # this to enable static code analysis.
        self._hard_limits = (hard_limits[0], hard_limits[1], hard_limits[2])

        ## Maps handler names to events indicating if those handlers
        # have stopped moving.
        self.nameToStoppedEvent = {}
        events.subscribe(events.STAGE_MOVER, self.onMotion)
        events.subscribe(events.STAGE_STOPPED, self.onStop)
Exemplo n.º 3
0
 def prepareHandlers(self):
     # Store the pre-experiment altitude.
     self.initialAltitude = cockpit.interfaces.stageMover.getPosition()[-1]
     # Ensure that we're the only ones moving things around.
     cockpit.interfaces.stageMover.waitForStop()
     # TODO: Handling multiple movers on an axis is broken. Do not proceed if
     # anything but the innermost Z mover is selected. Needs a proper fix.
     if (cockpit.interfaces.stageMover.mover.curHandlerIndex <
             len(depot.getSortedStageMovers()[2]) - 1):
         wx.MessageBox("Wrong axis mover selected.")
         raise Exception("Wrong axis mover selected.")
     # Prepare our position.
     cockpit.interfaces.stageMover.goToZ(self.altBottom, shouldBlock=True)
     self.zStart = cockpit.interfaces.stageMover.getAllPositions()[-1][-1]
     events.publish('prepare for experiment', self)
     # Prepare cameras.
     for camera in self.cameras:
         # We set the expsoure time here. This needs to be set before
         # the action table is generated, since the action table
         # uses camera.getExposureTime to figure out timings.
         exposureTime = float(self.getExposureTimeForCamera(camera))
         camera.setExposureTime(exposureTime)
Exemplo n.º 4
0
    def __init__(self):
        ## Maps axis to the handlers for that axis, sorted by their range of
        # motion.
        self.axisToHandlers = depot.getSortedStageMovers()

        ## XXX: We have a single index for all axis, even though each
        ## axis may have a different number of stages.  While we don't
        ## refactor this assumption, we just make copies of the movers
        ## with the most precise movement (issues #413 and #415)
        self.n_stages = max([len(s) for s in self.axisToHandlers.values()])
        for axis, stages in self.axisToHandlers.items():
            stages.extend([stages[-1]] * (self.n_stages - len(stages)))

        ## Indicates which stage handler is currently under control.
        self.curHandlerIndex = 0
        ## Maps Site unique IDs to Site instances.
        self.idToSite = {}
        ## Maps handler names to events indicating if those handlers
        # have stopped moving.
        self.nameToStoppedEvent = {}
        events.subscribe(events.STAGE_MOVER, self.onMotion)
        events.subscribe(events.STAGE_STOPPED, self.onStop)
    def runExperiment(self):
        # Returns True to close dialog box, None or False otherwise.
        self.saveSettings()
        # Find the Z mover with the smallest range of motion, assumed
        # to be our experiment mover.
        mover = depot.getSortedStageMovers()[2][-1]
        # Only use active cameras and enabled lights.
        # Must do list(filter) because we will iterate over the list
        # many times.
        cameras = list(
            filter(lambda c: c.getIsEnabled(),
                   depot.getHandlersOfType(depot.CAMERA)))
        if not cameras:
            wx.MessageDialog(
                self,
                message=
                "No cameras are enabled, so the experiment cannot be run.",
                style=wx.ICON_EXCLAMATION | wx.STAY_ON_TOP
                | wx.OK).ShowModal()
            return True

        exposureSettings = []
        if self.shouldExposeSimultaneously.GetValue():
            # A single exposure event with all cameras and lights.
            lightTimePairs = []
            for i, light in enumerate(self.allLights):
                if (self.allLights[i].getIsEnabled()
                        and self.lightExposureTimes[i].GetValue()):
                    lightTimePairs.append(
                        (light,
                         guiUtils.tryParseNum(self.lightExposureTimes[i],
                                              decimal.Decimal)))
            exposureSettings = [(cameras, lightTimePairs)]
        else:
            # A separate exposure for each camera.
            for camera in cameras:
                cameraSettings = self.cameraToExposureTimes[camera]
                settings = []
                for i, light in enumerate(self.allLights):
                    if not light.getIsEnabled():
                        continue
                    timeControl = cameraSettings[i]
                    if timeControl.GetValue():
                        settings.append(
                            (light,
                             guiUtils.tryParseNum(timeControl,
                                                  decimal.Decimal)))
                exposureSettings.append(([camera], settings))

        altitude = cockpit.interfaces.stageMover.getPositionForAxis(2)
        # Default to "current is bottom"
        altBottom = altitude
        zHeight = guiUtils.tryParseNum(self.stackHeight, float)
        if self.zPositionMode.GetStringSelection() == 'Current is center':
            altBottom = altitude - zHeight / 2
        elif self.zPositionMode.GetStringSelection() == 'Use saved top/bottom':
            altBottom = cockpit.interfaces.stageMover.mover.SavedBottom
            zHeight = cockpit.interfaces.stageMover.mover.SavedTop - altBottom

        sliceHeight = guiUtils.tryParseNum(self.sliceHeight, float)
        if zHeight == 0:
            # 2D mode.
            zHeight = 1e-6
            sliceHeight = 1e-6

        try:
            savePath = self.filepath_panel.GetPath()
        except Exception:
            cockpit.gui.ExceptionBox("Failed to get filename for data.",
                                     parent=self)
            return True

        params = {
            'numReps': guiUtils.tryParseNum(self.numReps),
            'repDuration': guiUtils.tryParseNum(self.repDuration, float),
            'zPositioner': mover,
            'altBottom': altBottom,
            'zHeight': zHeight,
            'sliceHeight': sliceHeight,
            'exposureSettings': exposureSettings,
            'savePath': savePath
        }
        experimentType = self.experimentType.GetStringSelection()
        module = self.experimentStringToModule[experimentType]
        if module in self.experimentModuleToPanel:
            # Add on the special parameters needed by this experiment type.
            params = self.experimentModuleToPanel[module].augmentParams(params)

        self.runner = module.EXPERIMENT_CLASS(**params)
        return self.runner.run()
Exemplo n.º 6
0
    def __init__(self):
        ## Maps axis to the handlers for that axis, sorted by their range of
        # motion.
        self.axisToHandlers = depot.getSortedStageMovers()
        if set(self.axisToHandlers.keys()) != {0, 1, 2}:
            raise ValueError('stage mover requires 3 axis: X, Y, and Z')

        # FIXME: we should have sensible defaults (see issue #638).
        self._saved_top = userConfig.getValue('savedTop', default=3010.0)
        self._saved_bottom = userConfig.getValue('savedBottom', default=3000.0)

        ## XXX: We have a single index for all axis, even though each
        ## axis may have a different number of stages.  While we don't
        ## refactor this assumption, we just make copies of the movers
        ## with the most precise movement (issues #413 and #415)
        self.n_stages = max([len(s) for s in self.axisToHandlers.values()])
        for axis, stages in self.axisToHandlers.items():
            stages.extend([stages[-1]] * (self.n_stages - len(stages)))

        ## Indicates which stage handler is currently under control.
        self.curHandlerIndex = 0
        ## Maps Site unique IDs to Site instances.
        self.idToSite = {}

        # Compute the hard motion limits for each axis as the
        # summation of all limits for handlers on that axis.
        hard_limits = [None] * 3
        for axis in range(3):
            lower = 0.0
            upper = 0.0
            # We need set() to avoid duplicated handlers, and we might
            # have duplicated handlers because of the hack to meet
            # cockpit requirements that all axis have the same number
            # of handlers (see comments on issue #413).
            for handler in set(self.axisToHandlers[axis]):
                handler_limits = handler.getHardLimits()
                lower += handler_limits[0]
                upper += handler_limits[1]
            hard_limits[axis] = (lower, upper)
        # Use a tuple to prevent changes to it, and assemble it like
        # this to enable static code analysis.
        self._hard_limits = (hard_limits[0], hard_limits[1], hard_limits[2])

        # Compute the initial step sizes.  We have different step
        # sizes for each handler index which maybe doesn't make sense
        # anymore but comes from the time when it were the handlers
        # themselves that kept track of step size.
        self._step_sizes = [
        ]  # type: typing.List[typing.Tuple[float, float, float]]
        for stage_index in range(self.n_stages):
            default_step_sizes = []
            for axis in (0, 1, 2):
                limits = self.axisToHandlers[axis][stage_index].getHardLimits()
                step_size = SensiblePreviousStepSize(
                    (limits[1] - limits[0]) / 100.0)
                default_step_sizes.append(step_size)
            # Default is 1/100 of the axis length but in rectangular
            # stages that will lead to xy with different step sizes so
            # use the min of the two.
            min_xy = min(default_step_sizes[0], default_step_sizes[1])
            self._step_sizes.append((min_xy, min_xy, default_step_sizes[2]))

        ## Maps handler names to events indicating if those handlers
        # have stopped moving.
        self.nameToStoppedEvent = {}
        events.subscribe(events.STAGE_MOVER, self.onMotion)
        events.subscribe(events.STAGE_STOPPED, self.onStop)