def __init__(self, parent, configKey):
        super().__init__(parent=parent)

        self.configKey = configKey + self._CONFIG_KEY_SUFFIX
        self.allLights = depot.getHandlersOfType(depot.LIGHT_TOGGLE)
        self.settings = self.loadSettings()

        sizer = wx.BoxSizer(wx.VERTICAL)
        rowSizer = wx.BoxSizer(wx.HORIZONTAL)

        text = wx.StaticText(self, -1, "Exposure bleach compensation (%):")
        rowSizer.Add(text, 0, wx.ALL, 5)
        ## Ordered list of bleach compensation percentages.
        self.bleachCompensations, subSizer = guiUtils.makeLightsControls(
                self,
                [str(l.name) for l in self.allLights],
                self.settings['bleachCompensations'])
        rowSizer.Add(subSizer)
        sizer.Add(rowSizer)
        # Now a row for the collection order.
        rowSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.siCollectionOrder = guiUtils.addLabeledInput(self,
                rowSizer, label = "Collection order",
                control = wx.Choice(self, choices = sorted(COLLECTION_ORDERS.keys())),
                helperString = "What order to change the angle, phase, and Z step of the experiment. E.g. for \"Angle, Phase, Z\" Angle will change most slowly and Z will change fastest.")
        self.siCollectionOrder.SetSelection(self.settings['siCollectionOrder'])
        sizer.Add(rowSizer)
        self.SetSizerAndFit(sizer)
Exemple #2
0
 def __init__(self, parent, configKey):
     wx.Panel.__init__(self, parent = parent)
     self.configKey = configKey
     sizer = wx.GridSizer(2, 2, 2, 2)
     ## Maps strings to TextCtrls describing how to configure 
     # response curve experiments.
     self.settings = self.loadSettings()
     self.responseArgs = {}
     for key, label, helperString, validator in [
             ('responseMapNumExposures', 'Number of exposures', 
                 "How many exposures to take for each exposure time.",
              INTVALIDATOR),
             ('responseMapExposureTimes', 'Exposure times', 
                 "Comma-separated list of exposure times at which to collect data.",
              CSVVALIDATOR),
             ('responseMapCosmicRayThreshold', 
                 'Cosmic ray threshold',
                 "If any pixels in an image are more than this many standard deviations from the median, then the image is discarded.",
              FLOATVALIDATOR)]:
         control = guiUtils.addLabeledInput(self, sizer, 
             label = label, defaultValue = self.settings[key],
             helperString = helperString)
         if validator is not None: control.SetValidator(validator)
         self.responseArgs[key] = control
     rowSizer = wx.BoxSizer(wx.HORIZONTAL)
     control = wx.CheckBox(self, label = 'Preserve intermediary files')
     control.SetValue(self.settings['responseMapShouldPreserveIntermediaryFiles'])
     rowSizer.Add(control)
     guiUtils.addHelperString(self, rowSizer, 
             "Keep the raw data in addition to the averaged files.")
     self.responseArgs['responseMapShouldPreserveIntermediaryFiles'] = control
     sizer.Add(rowSizer)
     self.SetSizerAndFit(sizer)
Exemple #3
0
    def __init__(self, parent, configKey):
        super().__init__(parent=parent)
        self.configKey = configKey
        sizer = wx.GridSizer(2, 4, 1)
        ## Maps strings to TextCtrls describing how to configure
        # response curve experiments.
        self.settings = self.loadSettings()
        self.settlingTimeControl = guiUtils.addLabeledInput(
            self,
            sizer,
            label='settling time',
            defaultValue=self.settings['settlingTime'],
        )
        self.settlingTimeControl.SetValidator(FLOATVALIDATOR)

        self.vStepsControl = guiUtils.addLabeledInput(
            self,
            sizer,
            label='V steps',
            defaultValue=self.settings['vSteps'],
        )
        self.vStepsControl.SetValidator(INTVALIDATOR)

        self.startVControl = guiUtils.addLabeledInput(
            self,
            sizer,
            label='V start',
            defaultValue=self.settings['startV'],
        )
        self.startVControl.SetValidator(FLOATVALIDATOR)

        self.maxVControl = guiUtils.addLabeledInput(
            self,
            sizer,
            label='V max',
            defaultValue=self.settings['maxV'],
        )
        self.maxVControl.SetValidator(FLOATVALIDATOR)

        self.SetSizerAndFit(sizer)
Exemple #4
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        rowSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.numPhases = guiUtils.addLabeledInput(
            self,
            rowSizer,
            label="Number of phases",
            helperString="How many phases do you want?")
        self.numPhases.SetValue(str(self.settings['numPhases']))
        self.Sizer.Insert(0, rowSizer)

        rowSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.numAngles = guiUtils.addLabeledInput(
            self,
            rowSizer,
            label="Number of angles",
            helperString="How many angles do you want?")
        self.numAngles.SetValue(str(self.settings['numAngles']))
        self.Sizer.Insert(1, rowSizer)

        self.Sizer.SetSizeHints(self)
Exemple #5
0
    def __init__(self, parent, configKey):
        super().__init__(parent=parent)

        self.configKey = configKey
        self.settings = self.loadSettings()

        sizer = wx.GridSizer(3, 2, 2, 2)
        ## Maps strings to TextCtrls describing how to configure
        # correction file experiments.
        self.correctionArgs = {}
        for key, label, helperString, validator in [
            ('correctionNumExposures', 'Number of exposures',
             "How many exposures to take for each exposure time.",
             INTVALIDATOR),
            ('correctionNumCollections', 'Number of collections',
             "Maximum number of exposure times to collect data for.",
             INTVALIDATOR),
            ('correctionExposureMultiplier', 'Exposure multiplier',
             "Multiplicative factor that governs how quickly we increase exposure time for measuring the camera's response.",
             FLOATVALIDATOR),
            ('correctionMaxIntensity', 'Max intensity',
             'Any images above this value are discarded; if we complete imaging and no images "survive", then we are done with data collection.',
             FLOATVALIDATOR),
            ('correctionCosmicRayThreshold', 'Cosmic ray threshold',
             "If any pixels in an image are more than this many standard deviations from the median, then the image is discarded.",
             FLOATVALIDATOR)
        ]:
            control = guiUtils.addLabeledInput(self,
                                               sizer,
                                               label=label,
                                               defaultValue=self.settings[key],
                                               helperString=helperString)
            control.SetValidator(validator)
            self.correctionArgs[key] = control
        rowSizer = wx.BoxSizer(wx.HORIZONTAL)
        control = wx.CheckBox(self, label='Preserve intermediary files')
        control.SetValue(
            self.settings['correctionShouldPreserveIntermediaryFiles'])
        rowSizer.Add(control)
        guiUtils.addHelperString(
            self, rowSizer,
            "Keep the raw data in addition to the averaged files.")
        self.correctionArgs[
            'correctionShouldPreserveIntermediaryFiles'] = control
        sizer.Add(rowSizer)
        self.SetSizerAndFit(sizer)
    def __init__(self,
                 parent,
                 resizeCallback,
                 resetCallback,
                 configKey='singleSiteExperiment'):
        super().__init__(parent,
                         style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
                         | wx.TAB_TRAVERSAL)
        self.parent = parent

        self.configKey = configKey
        self.resizeCallback = resizeCallback
        self.resetCallback = resetCallback

        ## cockpit.experiment.Experiment subclass instance -- mostly preserved for
        # debugging, so we can examine the state of the experiment.
        self.runner = None

        self.allLights = depot.getHandlersOfType(depot.LIGHT_TOGGLE)
        self.allLights.sort(key=lambda l: l.wavelength)
        self.allCameras = depot.getHandlersOfType(depot.CAMERA)
        self.allCameras.sort(key=lambda c: c.name)

        ## Map of default settings as loaded from config.
        self.settings = self.loadConfig()

        self.SetSizer(wx.BoxSizer(wx.VERTICAL))
        self.sizer = self.GetSizer()

        # Section for settings that are universal to all experiment types.
        universalSizer = wx.FlexGridSizer(2, 3, 5, 5)

        ## Maps experiment description strings to experiment modules.
        self.experimentStringToModule = collections.OrderedDict()
        for module in cockpit.experiment.experimentRegistry.getExperimentModules(
        ):
            self.experimentStringToModule[module.EXPERIMENT_NAME] = module

        self.experimentType = wx.Choice(
            self, choices=list(self.experimentStringToModule.keys()))
        self.experimentType.SetSelection(0)
        guiUtils.addLabeledInput(self,
                                 universalSizer,
                                 label="Experiment type:",
                                 control=self.experimentType)

        self.numReps = guiUtils.addLabeledInput(
            self,
            universalSizer,
            label="Number of reps:",
            defaultValue=self.settings['numReps'])
        self.numReps.SetValidator(guiUtils.INTVALIDATOR)

        self.repDuration = guiUtils.addLabeledInput(
            self,
            universalSizer,
            label="Rep duration (s):",
            defaultValue=self.settings['repDuration'],
            helperString="Amount of time that must pass between the start " +
            "of each rep. Use 0 if you don't want any wait time.")
        self.repDuration.SetValidator(guiUtils.FLOATVALIDATOR)

        self.zPositionMode = wx.Choice(self, choices=Z_POSITION_MODES)
        self.zPositionMode.SetSelection(0)
        guiUtils.addLabeledInput(self,
                                 universalSizer,
                                 label="Z position mode:",
                                 control=self.zPositionMode)

        self.stackHeight = guiUtils.addLabeledInput(
            self,
            universalSizer,
            label=u"Stack height (\u03bcm):",
            defaultValue=self.settings['stackHeight'])
        self.stackHeight.SetValidator(guiUtils.FLOATVALIDATOR)

        self.sliceHeight = guiUtils.addLabeledInput(
            self,
            universalSizer,
            label=u"Slice height (\u03bcm):",
            defaultValue=self.settings['sliceHeight'])
        self.sliceHeight.SetValidator(guiUtils.FLOATVALIDATOR)

        self.sizer.Add(universalSizer, 0, wx.ALL, border=5)

        ## Maps experiment modules to ExperimentUI instances holding the
        # UI for that experiment, if any.
        self.experimentModuleToPanel = {}
        for module in self.experimentStringToModule.values():
            if not hasattr(module, 'ExperimentUI'):
                # This experiment type has no special UI to set up.
                continue
            panel = module.ExperimentUI(self, self.configKey)
            panel.Hide()
            self.sizer.Add(panel)
            self.experimentModuleToPanel[module] = panel
        self.experimentType.Bind(wx.EVT_CHOICE, self.onExperimentTypeChoice)
        self.onExperimentTypeChoice()

        # Section for exposure settings. We allow either setting per-laser
        # exposure times and activating all cameras as a group, or setting
        # them per-laser and per-camera (and activating each camera-laser
        # grouping in sequence).
        exposureSizer = wx.BoxSizer(wx.VERTICAL)

        ## Controls which set of exposure settings we enable.
        self.shouldExposeSimultaneously = wx.CheckBox(
            self, label="Expose all cameras simultaneously")
        exposureSizer.Add(self.shouldExposeSimultaneously, 0, wx.ALL, border=5)
        ## Panel for holding controls for when we expose every camera
        # simultaneously.
        self.simultaneousExposurePanel = wx.Panel(
            self, name="simultaneous exposures")
        simultaneousSizer = wx.BoxSizer(wx.VERTICAL)
        simultaneousSizer.Add(
            wx.StaticText(self.simultaneousExposurePanel, -1,
                          "Exposure times for light sources:"), 0, wx.ALL, 5)

        ## Ordered list of exposure times for simultaneous exposure mode.
        self.lightExposureTimes, timeSizer = guiUtils.makeLightsControls(
            self.simultaneousExposurePanel,
            [str(l.name) for l in self.allLights],
            self.settings['simultaneousExposureTimes'])
        simultaneousSizer.Add(timeSizer)
        useCurrentButton = wx.Button(self.simultaneousExposurePanel, -1,
                                     "Use current settings")
        useCurrentButton.SetToolTip(
            wx.ToolTip(
                "Use the same settings as are currently used to take images with the '+' button"
            ))
        useCurrentButton.Bind(wx.EVT_BUTTON, self.onUseCurrentExposureSettings)
        simultaneousSizer.Add(useCurrentButton)

        self.simultaneousExposurePanel.SetSizerAndFit(simultaneousSizer)
        exposureSizer.Add(self.simultaneousExposurePanel, 0, wx.ALL, border=5)

        ## Panel for when we expose each camera in sequence.
        self.sequencedExposurePanel = wx.Panel(self,
                                               name="sequenced exposures")
        ## Maps a camera handler to an ordered list of exposure times.
        self.cameraToExposureTimes = {}
        sequenceSizer = wx.FlexGridSizer(
            len(self.settings['sequencedExposureSettings']) + 1,
            len(self.settings['sequencedExposureSettings'][0]) + 1, 1, 1)
        for label in [''] + [str(l.name) for l in self.allLights]:
            sequenceSizer.Add(
                wx.StaticText(self.sequencedExposurePanel, -1, label), 0,
                wx.ALIGN_RIGHT | wx.ALL, 5)
        for i, camera in enumerate(self.allCameras):
            sequenceSizer.Add(
                wx.StaticText(self.sequencedExposurePanel, -1,
                              str(camera.name)), 0, wx.TOP | wx.ALIGN_RIGHT, 8)
            times = []
            for (label, defaultVal) in zip(
                [str(l.name) for l in self.allLights],
                    self.settings['sequencedExposureSettings'][i]):
                exposureTime = wx.TextCtrl(self.sequencedExposurePanel,
                                           size=(40, -1),
                                           name="exposure: %s for %s" %
                                           (label, camera.name))
                exposureTime.SetValue(defaultVal)
                # allowEmpty=True lets validator know this control may be empty.
                exposureTime.SetValidator(guiUtils.FLOATVALIDATOR)
                exposureTime.allowEmpty = True
                sequenceSizer.Add(exposureTime, 0, wx.ALL, border=5)
                times.append(exposureTime)
            self.cameraToExposureTimes[camera] = times
        self.sequencedExposurePanel.SetSizerAndFit(sequenceSizer)
        exposureSizer.Add(self.sequencedExposurePanel, 0, wx.ALL, border=5)
        self.sizer.Add(exposureSizer)

        # Toggle which panel is displayed based on the checkbox.
        self.shouldExposeSimultaneously.Bind(wx.EVT_CHECKBOX,
                                             self.onExposureCheckbox)
        self.shouldExposeSimultaneously.SetValue(
            self.settings['shouldExposeSimultaneously'])
        self.onExposureCheckbox()

        self.filepath_panel = FilepathPanel(self)
        self.filepath_panel.SetTemplate(self.settings['filenameTemplate'])
        self.filepath_panel.UpdateFilename()
        self.Sizer.Add(self.filepath_panel, wx.SizerFlags(1).Expand().Border())

        # Save/load experiment settings buttons.
        saveLoadPanel = wx.Panel(self)
        rowSizer = wx.BoxSizer(wx.HORIZONTAL)
        saveButton = wx.Button(saveLoadPanel, -1,
                               "Save experiment settings...")
        saveButton.Bind(wx.EVT_BUTTON, self.onSaveExperiment)
        rowSizer.Add(saveButton, 0, wx.ALL, 5)
        loadButton = wx.Button(saveLoadPanel, -1,
                               "Load experiment settings...")
        loadButton.Bind(wx.EVT_BUTTON, self.onLoadExperiment)
        rowSizer.Add(loadButton, 0, wx.ALL, 5)
        saveLoadPanel.SetSizerAndFit(rowSizer)
        self.sizer.Add(saveLoadPanel, 0, wx.LEFT, 5)

        self.SetSizerAndFit(self.sizer)
Exemple #7
0
    def __init__(self, parent):
        super().__init__(parent,
                         title="OMX multi-site experiment",
                         style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)

        ## Whether or not we should abort the current experiment.
        self.shouldAbort = False
        events.subscribe(events.USER_ABORT, self.onAbort)

        ## List of all light handlers.
        self.allLights = depot.getHandlersOfType(depot.LIGHT_TOGGLE)
        ## List of booleans indicating which lights were active at the
        # start of the experiment.
        self.activeLights = [None for l in self.allLights]

        ## User's last-used inputs.
        self.settings = cockpit.util.userConfig.getValue(
            'multiSiteExperiment',
            default={
                'numCycles': '10',
                'cycleDuration': '60',
                'delayBeforeStarting': '0',
                'delayBeforeImaging': '0',
                'fileBase': '',
                'shouldCustomizeLightFrequencies': False,
                'shouldOptimizeSiteOrder': True,
                'lightFrequencies': ['1' for l in self.allLights],
            })

        ## Contains self.panel
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        ## Contains all UI widgets.
        self.panel = wx.Panel(self)
        ## Sizer for self.panel.
        self.panelSizer = wx.BoxSizer(wx.VERTICAL)
        ## Sizer for all controls except the start/cancel/reset buttons.
        controlsSizer = wx.BoxSizer(wx.HORIZONTAL)
        ## Sizer for a single column of controls.
        columnSizer = wx.BoxSizer(wx.VERTICAL)
        ## Panel for selecting sites to visit.
        self.sitesPanel = cockpit.gui.dialogs.enumerateSitesPanel.EnumerateSitesPanel(
            self.panel,
            label="Sites to visit:",
            size=(200, -1),
            minSize=CONTROL_SIZE)
        columnSizer.Add(self.sitesPanel)

        self.numCycles = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Number of cycles:",
            defaultValue=self.settings['numCycles'],
            size=FIELD_SIZE,
            minSize=CONTROL_SIZE)

        self.cycleDuration = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Min cycle duration (s):",
            defaultValue=self.settings['cycleDuration'],
            size=FIELD_SIZE,
            minSize=CONTROL_SIZE,
            helperString=
            "Minimum amount of time to pass between each cycle. If the " +
            "cycle finishes early, then I will wait until this much " +
            "time has passed. You can enter multiple values here " +
            "separated by commas; I will then use each wait time in " +
            "sequence; e.g. \"60,120,180\" means the first " +
            "cycle takes one minute, the second two, the third three, " +
            "the fourth one, the fifth two, and so on.")

        self.delayBeforeStarting = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Delay before starting (min):",
            defaultValue=self.settings['delayBeforeStarting'],
            size=FIELD_SIZE,
            minSize=CONTROL_SIZE,
            helperString=
            "Amount of time to wait before starting the experiment. " +
            "This is useful if you have a lengthy period to wait for " +
            "your cells to reach the stage you're interested in, for " +
            "example.")

        self.delayBeforeImaging = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Delay before imaging (s):",
            defaultValue=self.settings['delayBeforeImaging'],
            size=FIELD_SIZE,
            minSize=CONTROL_SIZE,
            helperString="Amount of time to wait after moving to a site before "
            + "I start imaging the site. This is mostly useful if " +
            "your stage needs time to stabilize after moving.")

        self.fileBase = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Data file base name:",
            defaultValue=self.settings['fileBase'],
            size=FIELD_SIZE,
            minSize=CONTROL_SIZE)

        controlsSizer.Add(columnSizer, 0, wx.ALL, 5)

        columnSizer = wx.BoxSizer(wx.VERTICAL)
        ## We don't necessarily have this option.
        self.shouldPowerDownWhenDone = None
        powerHandlers = depot.getHandlersOfType(depot.POWER_CONTROL)
        if powerHandlers:
            # There are devices that we could potentially turn off at end of
            # experiment.
            self.shouldPowerDownWhenDone = guiUtils.addLabeledInput(
                self.panel,
                columnSizer,
                label="Power off devices when done:",
                control=wx.CheckBox(self.panel),
                labelHeightAdjustment=0,
                border=3,
                flags=wx.ALL,
                helperString=
                "If checked, then at the end of the experiment, I will " +
                "power down all the devices I can.")

        self.shouldOptimizeSiteOrder = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Optimize route:",
            defaultValue=self.settings['shouldOptimizeSiteOrder'],
            control=wx.CheckBox(self.panel),
            labelHeightAdjustment=0,
            border=3,
            flags=wx.ALL,
            helperString=
            "If checked, then I will calculate an ordering of the sites " +
            "that will minimize the total time spent in transit; " +
            "otherwise, I will use the order you specify.")

        self.shouldCustomizeLightFrequencies = guiUtils.addLabeledInput(
            self.panel,
            columnSizer,
            label="Customize light frequencies:",
            defaultValue=self.settings['shouldCustomizeLightFrequencies'],
            control=wx.CheckBox(self.panel),
            labelHeightAdjustment=0,
            border=3,
            flags=wx.ALL,
            helperString=
            "This allows you to set up experiments where different " +
            "light sources are enabled for different cycles. If you " +
            "set a frequency of 5 for a given light, for example, " +
            "then that light will only be used for every 5th pass " +
            "(the 1st, 6th, 11th, etc. cycles). You can specify an " +
            "offset, too: \"5 + 1\" would enable the light for the " +
            "2nd, 7th, 12th, etc. cycles.")
        self.shouldCustomizeLightFrequencies.Bind(
            wx.EVT_CHECKBOX, self.onCustomizeLightFrequencies)
        self.lightFrequenciesPanel = wx.Panel(self.panel,
                                              style=wx.BORDER_SUNKEN
                                              | wx.TAB_TRAVERSAL)
        self.lightFrequencies, sizer = guiUtils.makeLightsControls(
            self.lightFrequenciesPanel,
            [str(l.wavelength) for l in self.allLights],
            self.settings['lightFrequencies'])
        self.lightFrequenciesPanel.SetSizerAndFit(sizer)
        self.lightFrequenciesPanel.Show(
            self.settings['shouldCustomizeLightFrequencies'])
        columnSizer.Add(self.lightFrequenciesPanel, 0,
                        wx.LEFT | wx.RIGHT | wx.BOTTOM, 5)

        controlsSizer.Add(columnSizer, 0, wx.ALL, 5)
        self.panelSizer.Add(controlsSizer)

        ## Controls whether or not the scanning experiment's parameters are
        # shown.
        self.showScanButton = wx.Button(self.panel, -1,
                                        "Show experiment settings")
        self.showScanButton.Bind(wx.EVT_BUTTON, self.onShowScanButton)
        self.panelSizer.Add(self.showScanButton, 0, wx.ALIGN_CENTER | wx.TOP,
                            5)
        ## This panel configures the experiment we perform when visiting sites.
        self.experimentPanel = experimentConfigPanel.ExperimentConfigPanel(
            self.panel,
            resizeCallback=self.onExperimentPanelResize,
            resetCallback=self.onExperimentPanelReset,
            configKey='multiSiteExperimentPanel',
            shouldShowFileControls=False)
        self.panelSizer.Add(self.experimentPanel, 0, wx.ALIGN_CENTER | wx.ALL,
                            5)
        self.experimentPanel.Hide()

        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)

        button = wx.Button(self.panel, -1, "Reset")
        button.SetToolTip(
            wx.ToolTip("Reload this window with all default values"))
        button.Bind(wx.EVT_BUTTON, self.onReset)
        buttonSizer.Add(button, 0, wx.ALL, 5)

        buttonSizer.Add((1, 0), 1, wx.EXPAND)

        button = wx.Button(self.panel, wx.ID_CANCEL, "Cancel")
        buttonSizer.Add(button, 0, wx.ALL, 5)

        button = wx.Button(self.panel, wx.ID_OK, "Start")
        button.SetToolTip(wx.ToolTip("Start the experiment"))
        button.Bind(wx.EVT_BUTTON, self.onStart)
        buttonSizer.Add(button, 0, wx.ALL, 5)

        self.panelSizer.Add(buttonSizer, 0, wx.ALL, 5)
        self.panel.SetSizerAndFit(self.panelSizer)
        self.sizer.Add(self.panel)
        self.SetSizerAndFit(self.sizer)