예제 #1
0
    def test_add_stream(self):

        test.gui_loop()

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(mic_mod, stream_bar)
        # stream_bar.setMicroscope(mic_mod, None)

        self.assertEqual(stream_bar.btn_add_stream.IsShown(), True)

        # No actions should be linked to the add stream button
        self.assertEqual(len(stream_bar.get_actions()), 0)

        # Add a callback/name combo to the add button
        def brightfield_callback():
            fake_stream = FakeBrightfieldStream("Brightfield")
            fixed_entry = stream_comp.StreamPanel(stream_bar, fake_stream,
                                                  mic_mod)
            stream_bar.add_stream(fixed_entry)

        stream_bar.add_action("Brightfield", brightfield_callback)

        brightfield_callback()
        test.gui_loop()
        self.assertEqual(len(stream_bar.get_actions()), 1)
        self.assertEqual(stream_bar.get_size(), 1)

        # Add another callback/name combo to the add button
        def sem_callback():
            fake_stream = FakeSEMStream("SEM:EDT")
            fixed_entry = stream_comp.StreamPanel(stream_bar, fake_stream,
                                                  mic_mod)
            stream_bar.add_stream(fixed_entry)

        stream_bar.add_action("SEM:EDT", sem_callback)

        sem_callback()
        test.gui_loop()
        self.assertEqual(len(stream_bar.get_actions()), 2)
        self.assertEqual(stream_bar.get_size(), 2)

        # Remove the Brightfield stream
        stream_bar.remove_action("Brightfield")
        test.gui_loop()
        self.assertEqual(len(stream_bar.get_actions()), 1)

        # Add another callback/name combo to the add button
        def custom_callback():
            fake_stream = FakeFluoStream("Custom")
            custom_entry = stream_comp.StreamPanel(stream_bar, fake_stream,
                                                   mic_mod)
            stream_bar.add_stream(custom_entry)

        stream_bar.add_action("Custom", custom_callback)

        # Clear remaining streams
        stream_bar.clear()
        test.gui_loop()
예제 #2
0
    def test_bandwidth_stream_panel(self):

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(mic_mod, stream_bar)

        fake_spec_stream = FakeSpectrumStream("First Fixed Stream")
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_spec_stream,
                                               mic_mod)
        stream_bar.add_stream(stream_panel)
        test.gui_loop()
예제 #3
0
    def test_bandwidth_stream_panel(self):

        tab_mod = self.create_simple_tab_model()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(tab_mod, stream_bar)

        fake_spec_stream = FakeSpectrumStream("First Fixed Stream")
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_spec_stream,
                                               tab_mod)
        stream_bar.add_stream(stream_panel)
        test.gui_loop()
예제 #4
0
    def __init__(self, tab_panel, tab_data, highlight_change=False):
        super(SecomSettingsController, self).__init__(tab_data)
        main_data = tab_data.main

        self._sem_panel = SemSettingsController(
            tab_panel.fp_settings_secom_sem, "No SEM found", highlight_change,
            tab_data)

        self._optical_panel = OpticalSettingsController(
            tab_panel.fp_settings_secom_optical, "No optical microscope found",
            highlight_change, tab_data)

        # Add the components based on what is available
        # TODO: move it to a separate thread to save time at init?
        if main_data.ccd:
            # Hide exposureTime as it's in local settings of the stream
            self.add_hw_component(main_data.ccd,
                                  self._optical_panel,
                                  hidden={"exposureTime"})

        if hasattr(tab_data, "confocal_set_stream"):
            conf_set_e = StreamController(tab_panel.pnl_opt_streams,
                                          tab_data.confocal_set_stream,
                                          tab_data)
            conf_set_e.stream_panel.flatten()  # removes the expander header
            # StreamController looks pretty much the same as SettingController
            self.setting_controllers.append(conf_set_e)
        else:
            tab_panel.pnl_opt_streams.Hide()  # Not needed

        # For now, we assume that the pinhole (axis) is global: valid for all
        # the confocal streams and FLIM stream. That's partly because most likely
        # the user wouldn't want to have separate values... and also because
        # anyway we don't currently support local stream axes.
        if main_data.pinhole:
            conf = get_hw_config(main_data.pinhole, self._hw_settings_config)
            for a in ("d", ):
                if a not in main_data.pinhole.axes:
                    continue
                self._optical_panel.add_axis(a, main_data.pinhole, conf.get(a))

        if main_data.ebeam:
            self.add_hw_component(main_data.ebeam, self._sem_panel)

            # If can do AutoContrast, display the button
            # TODO: check if detector has a .applyAutoContrast() method, instead
            # of detecting indirectly via the presence of .bpp.
            det = main_data.sed or main_data.bsd
            if det and model.hasVA(det, "bpp"):
                self._sem_panel.add_bc_control(det)
예제 #5
0
    def test_zflatten(self):

        test.gui_loop()

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(mic_mod, stream_bar)

        fake_sem_stream = FakeSEMStream("Flatten Test")
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_sem_stream,
                                               mic_mod)
        stream_bar.add_stream(stream_panel)
        test.gui_loop()

        stream_panel.flatten()

        test.gui_loop()
예제 #6
0
    def test_zflatten(self):

        test.gui_loop()

        tab_mod = self.create_simple_tab_model()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(tab_mod, stream_bar)

        fake_sem_stream = FakeSEMStream("Flatten Test")
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_sem_stream,
                                               tab_mod)
        stream_bar.add_stream(stream_panel)
        test.gui_loop()

        stream_panel.flatten()

        test.gui_loop()
예제 #7
0
    def test_dyeexpander(self):

        tab_mod = self.create_simple_tab_model()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(tab_mod, stream_bar)

        fake_fluo_stream = FakeFluoStream("Fluo Stream")
        dye_panel = stream_comp.StreamPanel(stream_bar, fake_fluo_stream,
                                            tab_mod)
        stream_bar.add_stream(dye_panel)

        # print stream_panel._expander.GetSize()
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_fluo_stream,
                                               tab_mod)
        stream_bar.add_stream(stream_panel)
        # print stream_panel._expander.GetSize()
        test.gui_loop()
예제 #8
0
    def test_standardexpander(self):

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(mic_mod, stream_bar)

        fake_sem_stream = FakeSEMStream("First Fixed Stream")
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_sem_stream,
                                               mic_mod)
        stream_bar.add_stream(stream_panel)
        test.gui_loop()

        self.assertEqual("First Fixed Stream",
                         stream_panel._expander._label_ctrl.GetLabel())
        test.gui_loop()

        # Clear remaining streams
        stream_bar.clear()
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 0)
예제 #9
0
    def test_dyeexpander(self):

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(mic_mod, stream_bar)

        fake_fluo_stream = FakeFluoStream("Fluo Stream")
        dye_panel = stream_comp.StreamPanel(stream_bar, fake_fluo_stream,
                                            mic_mod)
        stream_bar.add_stream(dye_panel)

        # print stream_panel._expander.GetSize()
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_fluo_stream,
                                               mic_mod)
        stream_bar.add_stream(stream_panel)
        # print stream_panel._expander.GetSize()
        test.gui_loop()

        # Clear remaining streams
        stream_bar.clear()
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 0)
예제 #10
0
    def __init__(self, parent, orig_tab_data):
        xrcfr_acq.__init__(self, parent)

        self.conf = get_acqui_conf()

        for n in presets:
            self.cmb_presets.Append(n)
        # TODO: record and reuse the preset used?
        self.cmb_presets.Select(0)

        self.filename = model.StringVA(self._get_default_filename())
        self.filename.subscribe(self._onFilename, init=True)

        # a ProgressiveFuture if the acquisition is going on
        self.acq_future = None
        self._acq_future_connector = None

        # duplicate the interface, but with only one view
        self._tab_data_model = self.duplicate_tab_data_model(orig_tab_data)

        # Create a new settings controller for the acquisition dialog
        self._settings_controller = SecomSettingsController(self,
                                                       self._tab_data_model,
                                                       highlight_change=True)
        # FIXME: pass the fold_panels

        # Compute the preset values for each preset
        self._preset_values = {} # dict string -> dict (SettingEntries -> value)
        orig_entries = self._settings_controller.entries
        self._orig_settings = preset_as_is(orig_entries) # to detect changes
        for n, preset in presets.items():
            self._preset_values[n] = preset(orig_entries)
        # Presets which have been confirmed on the hardware
        self._presets_confirmed = set() # (string)

        orig_view = orig_tab_data.focussedView.value
        view = self._tab_data_model.focussedView.value

        self.stream_controller = StreamController(self._tab_data_model,
                                                  self.pnl_secom_streams)
        # The streams currently displayed are the one visible
        self.add_all_streams(orig_view.getStreams())

        # If it could be possible to do fine alignment, allow the user to choose
        if self._can_fine_align(self._tab_data_model.streams.value):
            self.chkbox_fine_align.Show()
            # Set to True to make it the default, but will be automatically
            # disabled later if the current visible streams don't allow it.
            self.chkbox_fine_align.Value = True
            main_data = self._tab_data_model.main
            self._ovrl_stream = stream.OverlayStream("fine alignment", main_data.ccd,
                                         main_data.ebeam, main_data.sed)
            self._ovrl_stream.dwellTime.value = main_data.fineAlignDwellTime.value
        else:
            self.chkbox_fine_align.Show(False)
            self.chkbox_fine_align.Value = False

        self._prev_fine_align = self.chkbox_fine_align.Value

        # make sure the view displays the same thing as the one we are
        # duplicating
        view.view_pos.value = orig_view.view_pos.value
        view.mpp.value = orig_view.mpp.value
        view.merge_ratio.value = orig_view.merge_ratio.value

        # attach the view to the viewport
        self.pnl_view_acq.setView(view, self._tab_data_model)

        self.Bind(wx.EVT_CHAR_HOOK, self.on_key)

        self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_close)
        self.btn_change_file.Bind(wx.EVT_BUTTON, self.on_change_file)
        self.btn_secom_acquire.Bind(wx.EVT_BUTTON, self.on_acquire)
        self.cmb_presets.Bind(wx.EVT_COMBOBOX, self.on_preset)
        self.Bind(wx.EVT_CLOSE, self.on_close)
        # on_streams_changed is compatible because it doesn't use the args
        self.chkbox_fine_align.Bind(wx.EVT_CHECKBOX, self.on_streams_changed)

        self.on_preset(None) # will force setting the current preset

        pub.subscribe(self.on_setting_change, 'setting.changed')
        # TODO: we should actually listen to the stream tree, but it's not
        # currently possible.
        # Currently just use view.last_update which should be "similar"
        view.lastUpdate.subscribe(self.on_streams_changed)
예제 #11
0
class AcquisitionDialog(xrcfr_acq):
    """ Wrapper class responsible for additional initialization of the
    Acquisition Dialog created in XRCed
    """

    # TODO: share more code with cont.acquisition
    def __init__(self, parent, orig_tab_data):
        xrcfr_acq.__init__(self, parent)

        self.conf = get_acqui_conf()

        for n in presets:
            self.cmb_presets.Append(n)
        # TODO: record and reuse the preset used?
        self.cmb_presets.Select(0)

        self.filename = model.StringVA(self._get_default_filename())
        self.filename.subscribe(self._onFilename, init=True)

        # a ProgressiveFuture if the acquisition is going on
        self.acq_future = None
        self._acq_future_connector = None

        # duplicate the interface, but with only one view
        self._tab_data_model = self.duplicate_tab_data_model(orig_tab_data)

        # Create a new settings controller for the acquisition dialog
        self._settings_controller = SecomSettingsController(self,
                                                       self._tab_data_model,
                                                       highlight_change=True)
        # FIXME: pass the fold_panels

        # Compute the preset values for each preset
        self._preset_values = {} # dict string -> dict (SettingEntries -> value)
        orig_entries = self._settings_controller.entries
        self._orig_settings = preset_as_is(orig_entries) # to detect changes
        for n, preset in presets.items():
            self._preset_values[n] = preset(orig_entries)
        # Presets which have been confirmed on the hardware
        self._presets_confirmed = set() # (string)

        orig_view = orig_tab_data.focussedView.value
        view = self._tab_data_model.focussedView.value

        self.stream_controller = StreamController(self._tab_data_model,
                                                  self.pnl_secom_streams)
        # The streams currently displayed are the one visible
        self.add_all_streams(orig_view.getStreams())

        # If it could be possible to do fine alignment, allow the user to choose
        if self._can_fine_align(self._tab_data_model.streams.value):
            self.chkbox_fine_align.Show()
            # Set to True to make it the default, but will be automatically
            # disabled later if the current visible streams don't allow it.
            self.chkbox_fine_align.Value = True
            main_data = self._tab_data_model.main
            self._ovrl_stream = stream.OverlayStream("fine alignment", main_data.ccd,
                                         main_data.ebeam, main_data.sed)
            self._ovrl_stream.dwellTime.value = main_data.fineAlignDwellTime.value
        else:
            self.chkbox_fine_align.Show(False)
            self.chkbox_fine_align.Value = False

        self._prev_fine_align = self.chkbox_fine_align.Value

        # make sure the view displays the same thing as the one we are
        # duplicating
        view.view_pos.value = orig_view.view_pos.value
        view.mpp.value = orig_view.mpp.value
        view.merge_ratio.value = orig_view.merge_ratio.value

        # attach the view to the viewport
        self.pnl_view_acq.setView(view, self._tab_data_model)

        self.Bind(wx.EVT_CHAR_HOOK, self.on_key)

        self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_close)
        self.btn_change_file.Bind(wx.EVT_BUTTON, self.on_change_file)
        self.btn_secom_acquire.Bind(wx.EVT_BUTTON, self.on_acquire)
        self.cmb_presets.Bind(wx.EVT_COMBOBOX, self.on_preset)
        self.Bind(wx.EVT_CLOSE, self.on_close)
        # on_streams_changed is compatible because it doesn't use the args
        self.chkbox_fine_align.Bind(wx.EVT_CHECKBOX, self.on_streams_changed)

        self.on_preset(None) # will force setting the current preset

        pub.subscribe(self.on_setting_change, 'setting.changed')
        # TODO: we should actually listen to the stream tree, but it's not
        # currently possible.
        # Currently just use view.last_update which should be "similar"
        view.lastUpdate.subscribe(self.on_streams_changed)


    def duplicate_tab_data_model(self, orig):
        """
        Duplicate a MicroscopyGUIData and adapt it for the acquisition window
        The streams will be shared, but not the views
        orig (MicroscopyGUIData)
        return (MicroscopyGUIData)
        """
        new = copy.copy(orig) # shallow copy

        # create view (which cannot move or focus)
        view = guimodel.MicroscopeView(orig.focussedView.value.name.value)

        # differentiate it (only one view)
        new.views = {"all": view}
        new.focussedView = model.VigilantAttribute(view)
        new.viewLayout = model.IntEnumerated(guimodel.VIEW_LAYOUT_ONE,
                                             choices=set([guimodel.VIEW_LAYOUT_ONE]))

        return new

    def add_all_streams(self, visible_streams):
        """
        Add all the streams present in the interface model to the stream panel.
        visible_streams (list of streams): the streams that should be visible
        """
        # the order the streams are added should not matter on the display, so
        # it's ok to not duplicate the streamTree literally
        view = self._tab_data_model.focussedView.value

        # Add stream to view first, so that the "visible" button is correct
        for s in visible_streams:
            view.addStream(s)

        # go through all the streams available in the interface model
        for s in self._tab_data_model.streams.value:
            sp = self.stream_controller.addStreamForAcquisition(s)

    def remove_all_streams(self):
        """ Remove the streams we added to the view on creation """
        # Ensure we don't update the view after the window is destroyed
        view = self._tab_data_model.focussedView.value

        for s in view.getStreams():
            view.removeStream(s)

    def find_current_preset(self):
        """
        find the name of the preset identical to the current settings (not
          including "Custom")
        returns (string): name of the preset
        raises KeyError: if no preset can be found
        """
        # check each preset
        for n, settings in self._preset_values.items():
            # compare each value between the current and proposed
            different = False
            for entry, value in settings.items():
                if entry.va.value != value:
                    different = True
                    break
            if not different:
                return n

        raise KeyError()

    def _can_fine_align(self, streams):
        """
        Return True if with the given streams it would make sense to fine align
        streams (iterable of Stream)
        return (bool): True if at least a SEM and an optical stream are present
        """
        # check for a SEM stream
        for s in streams:
            if isinstance(s, EM_STREAMS):
                break
        else:
            return False

        # check for an optical stream
        for s in streams:
            if isinstance(s, OPTICAL_STREAMS):
                break
        else:
            return False

        return True

    @call_after
    def update_setting_display(self):
        # if gauge was left over from an error => now hide it
        if self.gauge_acq.IsShown():
            self.gauge_acq.Hide()
            self.Layout()

        # Enable/disable Fine alignment check box
        streams = self._tab_data_model.focussedView.value.getStreams()
        can_fa = self._can_fine_align(streams)
        if self.chkbox_fine_align.Enabled:
            self._prev_fine_align = self.chkbox_fine_align.Value
        self.chkbox_fine_align.Enable(can_fa)
        # Uncheck if disabled, otherwise put same as previous value
        self.chkbox_fine_align.Value = (can_fa and self._prev_fine_align)


        self.update_acquisition_time()

        # update highlight
        for se, value in self._orig_settings.items():
            se.highlight(se.va.value != value)

    def on_streams_changed(self, val):
        """
        When the list of streams to acquire has changed
        """
        self.update_setting_display()

    def on_setting_change(self, setting_ctrl):
        self.update_setting_display()

        # check presets and fall-back to custom
        try:
            preset_name = self.find_current_preset()
            logging.debug("Detected preset %s", preset_name)
        except KeyError:
            # should not happen with the current preset_no_change
            logging.exception("Couldn't match any preset")
            preset_name = u"Custom"

        self.cmb_presets.SetValue(preset_name)

    def update_acquisition_time(self):
        streams = self._tab_data_model.focussedView.value.getStreams()
        if streams:
            if self.chkbox_fine_align.Value:
                streams.add(self._ovrl_stream)
            acq_time = acq.estimateTime(streams)
            acq_time = math.ceil(acq_time) # round a bit pessimistically
            txt = "The estimated acquisition time is {}."
            txt = txt.format(units.readable_time(acq_time))
        else:
            txt = "No streams present."

        self.lbl_acqestimate.SetLabel(txt)

    def _get_default_filename(self):
        """
        Return a good default filename
        """
        # TODO: check the file doesn't yet exist (if the computer clock is
        # correct it's unlikely)
        return os.path.join(self.conf.last_path,
                            u"%s%s" % (time.strftime("%Y%m%d-%H%M%S"),
                                             self.conf.last_extension)
                            )

    def _onFilename(self, name):
        """ updates the GUI when the filename is updated """
        # decompose into path/file
        path, base = os.path.split(name)
        self.txt_destination.SetValue(unicode(path))
        # show the end of the path (usually more important)
        self.txt_destination.SetInsertionPointEnd()
        self.txt_filename.SetValue(unicode(base))

    def on_preset(self, evt):
        preset_name = self.cmb_presets.GetValue()
        try:
            new_preset = self._preset_values[preset_name]
        except KeyError:
            logging.debug("Not changing settings for preset %s", preset_name)
            return

        logging.debug("Changing setting to preset %s", preset_name)

        # TODO: presets should also be able to change the special stream settings
        # (eg: accumulation/interpolation) when we have them

        # apply the recorded values
        apply_preset(new_preset)

        # The hardware might not exactly apply the setting as computed in the
        # preset. We need the _exact_ same value to find back which preset is
        # currently selected. So update the values the first time.
        # TODO: this should not be necessary once the settings only change the
        # stream settings, and not directly the hardware.
        if not preset_name in self._presets_confirmed:
            for se in new_preset.keys():
                new_preset[se] = se.va.value
            self._presets_confirmed.add(preset_name)

        self.update_setting_display()

    def on_key(self, evt):
        """ Dialog key press handler. """
        if evt.GetKeyCode() == wx.WXK_ESCAPE:
            self.Close()
        else:
            evt.Skip()

    def on_change_file(self, evt):
        """
        Shows a dialog to change the path, name, and format of the acquisition
        file.
        returns nothing, but updates .filename and .conf
        """
        new_name = ShowAcquisitionFileDialog(self, self.filename.value)
        self.filename.value = new_name

    def on_close(self, evt):
        """ Close event handler that executes various cleanup actions
        """
        if self.acq_future:
            # TODO: ask for confirmation before cancelling?
            # What to do if the acquisition is done while asking for
            # confirmation?
            msg = "Cancelling acquisition due to closing the acquisition window"
            logging.info(msg)
            self.acq_future.cancel()

        self.remove_all_streams()
        # stop listening to events
        pub.unsubscribe(self.on_setting_change, 'setting.changed')

        self.Destroy()

    def _pause_settings(self):
        """
        Pause the settings of the GUI and save the values for restoring them later
        """
        self._settings_controller.pause()
        self._settings_controller.enable(False)

    def _resume_settings(self):
        self._settings_controller.resume()
        self._settings_controller.enable(True)

    def on_acquire(self, evt):
        """
        Start the acquisition (really)
        """
        self.btn_secom_acquire.Disable()

        # disable estimation time updates during acquisition
        view = self._tab_data_model.focussedView.value
        view.lastUpdate.unsubscribe(self.on_streams_changed)

        # TODO: freeze all the settings so that it's not possible to change anything
        self._pause_settings()

        self.gauge_acq.Show()
        self.Layout() # to put the gauge at the right place

        # start acquisition + connect events to callback
        streams = self._tab_data_model.focussedView.value.getStreams()

        # Add the overlay stream if the fine alignment check box is checked
        if self.chkbox_fine_align.Value:
            streams.add(self._ovrl_stream)

        # It should never be possible to reach here with no streams
        self.acq_future = acq.acquire(streams)
        self._acq_future_connector = ProgessiveFutureConnector(self.acq_future,
                                                               self.gauge_acq,
                                                               self.lbl_acqestimate)
        self.acq_future.add_done_callback(self.on_acquisition_done)

        self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_cancel)

    def on_cancel(self, evt):
        """
        Called during acquisition when pressing the cancel button
        """
        if not self.acq_future:
            msg = "Tried to cancel acquisition while it was not started"
            logging.warning(msg)
            return

        self.acq_future.cancel()
        # all the rest will be handled by on_acquisition_done()

    @call_after
    def on_acquisition_done(self, future):
        """
        Callback called when the acquisition is finished (either successfully or
        cancelled)
        """
        # bind button back to direct closure
        self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_close)
        self._resume_settings()

        # reenable estimation time updates
        view = self._tab_data_model.focussedView.value
        view.lastUpdate.subscribe(self.on_streams_changed)

        try:
            data = future.result(1) # timeout is just for safety
        except CancelledError:
            # put back to original state:
            # re-enable the acquire button
            self.btn_secom_acquire.Enable()

            # hide progress bar (+ put pack estimated time)
            self.update_acquisition_time()
            self.gauge_acq.Hide()
            self.Layout()
            return
        except Exception:
            # We cannot do much: just warn the user and pretend it was cancelled
            logging.exception("Acquisition failed")
            self.btn_secom_acquire.Enable()
            self.lbl_acqestimate.SetLabel("Acquisition failed.")
            # leave the gauge, to give a hint on what went wrong.
            return

        # save result to file
        self.lbl_acqestimate.SetLabel("Saving file...")
        try:
            thumb = acq.computeThumbnail(
                            self._tab_data_model.focussedView.value.stream_tree,
                            future)
            filename = self.filename.value
            exporter = dataio.get_exporter(self.conf.last_format)
            exporter.export(filename, data, thumb)
            logging.info("Acquisition saved as file '%s'.", filename)
        except Exception:
            logging.exception("Saving acquisition failed")
            self.btn_secom_acquire.Enable()
            self.lbl_acqestimate.SetLabel("Saving acquisition file failed.")
            return

        self.lbl_acqestimate.SetLabel("Acquisition completed.")

        # We don't allow to acquire anymore => change button name
        self.btn_cancel.SetLabel("Close")
예제 #12
0
    def test_stream_interface(self):

        test.gui_loop()

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar

        _ = StreamController(mic_mod, stream_bar)
        # stream_bar.setMicroscope(mic_mod, None)

        # Hide the Stream add button
        self.assertEqual(stream_bar.btn_add_stream.IsShown(), True)
        stream_bar.hide_add_button()
        test.gui_loop()
        self.assertEqual(stream_bar.btn_add_stream.IsShown(), False)

        # Show Stream add button
        stream_bar.show_add_button()
        test.gui_loop()
        self.assertEqual(stream_bar.btn_add_stream.IsShown(), True)

        # Add an editable entry
        fake_cstream = FakeFluoStream("First Custom Stream")
        custom_entry = stream_comp.StreamPanel(stream_bar, fake_cstream,
                                               mic_mod)
        stream_bar.add_stream(custom_entry)
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 1)
        self.assertEqual(stream_bar.stream_panels.index(custom_entry), 0)

        # Add a fixed stream
        fake_fstream1 = FakeSEMStream("First Fixed Stream")
        fixed_entry = stream_comp.StreamPanel(stream_bar, fake_fstream1,
                                              mic_mod)
        stream_bar.add_stream(fixed_entry)
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 2)
        self.assertEqual(stream_bar.stream_panels.index(fixed_entry), 0)
        self.assertEqual(stream_bar.stream_panels.index(custom_entry), 1)

        # Add a fixed stream
        fake_fstream2 = FakeSEMStream("Second Fixed Stream")
        fixed_entry2 = stream_comp.StreamPanel(stream_bar, fake_fstream2,
                                               mic_mod)
        stream_bar.add_stream(fixed_entry2)
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 3)
        self.assertEqual(stream_bar.stream_panels.index(fixed_entry2), 1)
        self.assertEqual(stream_bar.stream_panels.index(custom_entry), 2)

        # Hide first stream by changing to a view that only show SEM streams
        semview = guimodel.MicroscopeView(
            "SEM view", stream_classes=(stream_mod.SEMStream, ))
        # stream_bar.hide_stream(0)
        mic_mod.focussedView.value = semview
        test.gui_loop()
        self.assertEqual(stream_bar.get_size(), 3)
        self.assertFalse(custom_entry.IsShown())

        # Delete the second fixed stream
        stream_bar.remove_stream_panel(fixed_entry2)
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 2)

        # Clear remainging streams
        stream_bar.clear()
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 0)
예제 #13
0
    def test_expander(self):

        test.gui_loop()

        mic_mod = FakeMicroscopeModel()
        stream_bar = self.app.test_frame.stream_bar
        _ = StreamController(mic_mod, stream_bar)

        fake_sem_stream = FakeSEMStream("First Fixed Stream")
        stream_panel = stream_comp.StreamPanel(stream_bar, fake_sem_stream,
                                               mic_mod)
        stream_bar.add_stream(stream_panel)
        test.gui_loop()

        # REMOVE BUTTON TEST

        old_label_pos = stream_panel._expander._label_ctrl.GetPosition()

        stream_panel.show_remove_btn(False)
        test.gui_loop()

        self.assertFalse(stream_panel._expander._btn_rem.IsShown())

        new_label_pos = stream_panel._expander._label_ctrl.GetPosition()

        self.assertEqual(old_label_pos, new_label_pos)

        stream_panel.show_remove_btn(True)
        test.gui_loop()

        self.assertTrue(stream_panel._expander._btn_rem.IsShown())

        new_label_pos = stream_panel._expander._label_ctrl.GetPosition()

        self.assertEqual(old_label_pos, new_label_pos)

        # END REMOVE BUTTON TEST

        # VISIBILITY BUTTON TEST

        old_pbtn_pos = stream_panel._expander._btn_updated.GetPosition()

        stream_panel.show_visible_btn(False)
        test.gui_loop()

        self.assertFalse(stream_panel._expander._btn_vis.IsShown())

        new_pbtn_pos = stream_panel._expander._btn_updated.GetPosition()

        self.assertEqual(old_pbtn_pos, new_pbtn_pos)

        stream_panel.show_visible_btn(True)
        test.gui_loop()

        self.assertTrue(stream_panel._expander._btn_vis.IsShown())

        new_pbtn_pos = stream_panel._expander._btn_updated.GetPosition()

        self.assertEqual(old_pbtn_pos, new_pbtn_pos)

        # END VISIBILITY BUTTON TEST

        # PLAY BUTTON TEST

        old_vbtn_pos = stream_panel._expander._btn_vis.GetPosition()

        stream_panel.show_updated_btn(False)
        test.gui_loop()

        self.assertFalse(stream_panel._expander._btn_updated.IsShown())

        new_vbtn_pos = stream_panel._expander._btn_vis.GetPosition()

        self.assertEqual(old_vbtn_pos, new_vbtn_pos)

        stream_panel.show_updated_btn(True)
        test.gui_loop()

        self.assertTrue(stream_panel._expander._btn_updated.IsShown())

        new_vbtn_pos = stream_panel._expander._btn_vis.GetPosition()

        self.assertEqual(old_vbtn_pos, new_vbtn_pos)

        # END BUTTON TEST

        # Clear remainging streams
        stream_bar.clear()
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 0)
예제 #14
0
    def test_static_streams(self):

        tab_mod = self.create_simple_tab_model()
        stream_bar = self.app.test_frame.stream_bar
        stream_cont = StreamController(tab_mod, stream_bar)

        fluomd = {
            model.MD_DESCRIPTION: "test",
            model.MD_ACQ_DATE: time.time(),
            model.MD_BPP: 12,
            model.MD_BINNING: (1, 2),  # px, px
            model.MD_PIXEL_SIZE: (1e-6, 2e-5),  # m/px
            model.MD_POS: (13.7e-3, -30e-3),  # m
            model.MD_EXP_TIME: 1.2,  # s
            model.MD_IN_WL: (500e-9, 520e-9),  # m
            model.MD_OUT_WL: (600e-9, 630e-9),  # m
        }

        fluod = model.DataArray(numpy.zeros((512, 256), dtype="uint16"),
                                fluomd)
        # Create the streams the same way as when opening a file, in
        # cont.tabs.AnalysisTab.display_new_data()
        fluo_panel = stream_cont.addStatic("Fluo Stream",
                                           fluod,
                                           cls=stream_mod.StaticFluoStream,
                                           add_to_all_views=True)

        # Check it indeed created a panel entry to a static fluo stream
        self.assertIsInstance(fluo_panel.stream, stream_mod.StaticFluoStream)

        # White box testing: we expect that the excitation/emission information
        # are simple text, and no combo boxes (as it's all static)
        self.assertIsInstance(fluo_panel._txt_emission, wx.TextCtrl)
        self.assertIsInstance(fluo_panel._txt_excitation, wx.TextCtrl)
        test.gui_loop()

        semmd = {
            model.MD_DESCRIPTION: "test",
            model.MD_ACQ_DATE: time.time(),
            model.MD_BPP: 12,
            model.MD_BINNING: (1, 2),  # px, px
            model.MD_PIXEL_SIZE: (1e-6, 2e-5),  # m/px
            model.MD_POS: (13.7e-3, -30e-3),  # m
            model.MD_EXP_TIME: 1.2,  # s
        }

        semd = model.DataArray(numpy.zeros((256, 256), dtype="uint16"), semmd)
        # Create the streams the same way as when opening a file, in
        # cont.tabs.AnalysisTab.display_new_data()
        sem_panel = stream_cont.addStatic("SEM Stream",
                                          semd,
                                          cls=stream_mod.StaticSEMStream,
                                          add_to_all_views=True)

        # Check it indeed created a panel entry to a static fluo stream
        self.assertIsInstance(sem_panel.stream, stream_mod.StaticSEMStream)

        # White box testing: we expect autobc is available
        self.assertIsInstance(sem_panel._btn_autobc, wx.Control)

        # Clear remaining streams
        stream_bar.clear()
        test.gui_loop()

        self.assertEqual(stream_bar.get_size(), 0)