Пример #1
0
 def test_running_backend_same_as_requested(self):
     # run enzel backend
     test.start_backend(ENZEL_CONFIG)
     # check if the role is enzel
     role = model.getMicroscope().role
     self.assertEqual(role, "enzel")
     # run enzel backend again
     test.start_backend(ENZEL_CONFIG)
     # it should still be enzel.
     role = model.getMicroscope().role
     self.assertEqual(role, "enzel")
Пример #2
0
 def test_running_backend_different_from_requested(self):
     # run sparc backend
     test.start_backend(SPARC_CONFIG)
     # check if the role is sparc
     role = model.getMicroscope().role
     self.assertEqual(role, "sparc")
     # now run another backend (enzel)
     test.start_backend(ENZEL_CONFIG)
     # check if the role now is enzel instead of sparc
     role = model.getMicroscope().role
     self.assertEqual(role, "enzel")
Пример #3
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")

        s1 = stream.FluoStream("fluo1", cls.ccd, cls.ccd.data, cls.light,
                               cls.light_filter)
        s1.excitation.value = sorted(s1.excitation.choices)[0]
        s2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data, cls.light,
                               cls.light_filter)
        s2.excitation.value = sorted(s2.excitation.choices)[-1]
        s3 = stream.BrightfieldStream("bf", cls.ccd, cls.ccd.data, cls.light)
        cls.streams = [s1, s2, s3]
Пример #4
0
    def OnInit(self):
        """ Initialize the GUI

        This method is automatically called from the :wx:`App` constructor

        """

        gui.legend_logo = "legend_logo_delmic.png"
        if self._is_standalone:
            microscope = None
            gui.icon = img.getIcon("icon/ico_gui_viewer_256.png")
            gui.name = odemis.__shortname__ + " Viewer"

            if "delphi" == self._is_standalone:
                gui.logo = img.getBitmap("logo_delphi.png")
                gui.legend_logo = "legend_logo_delphi.png"
        else:
            gui.icon = img.getIcon("icon/ico_gui_full_256.png")
            gui.name = odemis.__shortname__
            try:
                microscope = model.getMicroscope()
            except (IOError, Pyro4.errors.CommunicationError) as e:
                logging.exception("Failed to connect to back-end")
                msg = ("The Odemis GUI could not connect to the Odemis back-end:"
                       "\n\n{0}\n\n"
                       "Launch user interface anyway?").format(e)

                answer = wx.MessageBox(msg,
                                       "Connection error",
                                       style=wx.YES | wx.NO | wx.ICON_ERROR)
                if answer == wx.NO:
                    sys.exit(1)
                microscope = None
            else:
                if microscope.role == "delphi":
                    gui.logo = img.getBitmap("logo_delphi.png")
                    gui.legend_logo = "legend_logo_delphi.png"

        # TODO: if microscope.ghost is not empty => wait and/or display a special
        # "hardware status" tab.

        if microscope and microscope.role == "mbsem":
            self.main_data = guimodel.FastEMMainGUIData(microscope)
        else:
            self.main_data = guimodel.MainGUIData(microscope)
        # Load the main frame
        self.main_frame = main_xrc.xrcfr_main(None)

        self.init_gui()

        try:
            from odemis.gui.dev.powermate import Powermate
            self.dev_powermate = Powermate(self.main_data)
        except (LookupError, NotImplementedError) as ex:
            logging.debug("Not using Powermate: %s", ex)
        except Exception:
            logging.exception("Failed to load Powermate support")

        # Application successfully launched
        return True
Пример #5
0
    def setUpClass(cls):
        if driver.get_backend_status() == driver.BACKEND_RUNNING:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return

        # run the backend as a daemon
        # we cannot run it normally as the child would also think he's in a unittest
        cmd = ODEMISD_CMD + ODEMISD_ARG + [SPARC_CONFIG]
        ret = subprocess.call(cmd)
        if ret != 0:
            logging.error("Failed starting backend with '%s'", cmd)
        time.sleep(1) # time to start

        # Find CCD & SEM components
        cls.microscope = model.getMicroscope()
        for comp in model.getComponents():
            if comp.role == "ccd":
                cls.ccd = comp
            elif comp.role == "spectrometer":
                cls.spec = comp
            elif comp.role == "e-beam":
                cls.ebeam = comp
            elif comp.role == "se-detector":
                cls.sed = comp
            elif comp.role == "light":
                cls.light = comp
            elif comp.role == "filter":
                cls.light_filter = comp
Пример #6
0
 def setUp(self):
     if self.backend_was_running:
         self.skipTest("Running backend found")
     self.opm = acq.path.OpticalPathManager(model.getMicroscope())
     # Speed it up
     self.ccd.exposureTime.value = self.ccd.exposureTime.range[0]
     self.spccd.exposureTime.value = self.spccd.exposureTime.range[0]
Пример #7
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")

        s1 = stream.FluoStream("fluo1", cls.ccd, cls.ccd.data,
                               cls.light, cls.light_filter)
        s1.excitation.value = sorted(s1.excitation.choices)[0]
        s2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data,
                               cls.light, cls.light_filter)
        s2.excitation.value = sorted(s2.excitation.choices)[-1]
        s3 = stream.BrightfieldStream("bf", cls.ccd, cls.ccd.data, cls.light)
        cls.streams = [s1, s2, s3]
Пример #8
0
    def setUpClass(cls):
        if driver.get_backend_status() in driver.BACKEND_RUNNING:
            microscope = model.getMicroscope()
            if microscope.role != "meteor":
                logging.info(
                    "There is already running backend. It will be turned off, and the backend of METEOR will be turned on."
                )
                test.stop_backend()
                test.start_backend(METEOR_CONFIG)
            else:
                logging.info(
                    "There is METEOR backend already running. It will be used."
                )
        else:
            try:
                logging.info("METEOR backend will be turned on.")
                test.start_backend(METEOR_CONFIG)
            except Exception:
                raise

        # get the stage components
        cls.stage = model.getComponent(role="stage-bare")

        # get the metadata
        stage_md = cls.stage.getMetadata()
        cls.stage_grid_centers = stage_md[model.MD_SAMPLE_CENTERS]
        cls.stage_loading = stage_md[model.MD_FAV_POS_DEACTIVE]
Пример #9
0
    def setUpClass(cls):
        if driver.get_backend_status() == driver.BACKEND_RUNNING:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return

        # run the backend as a daemon
        # we cannot run it normally as the child would also think he's in a unittest
        cmd = ODEMISD_CMD + ODEMISD_ARG + [SPARC_CONFIG]
        ret = subprocess.call(cmd)
        if ret != 0:
            logging.error("Failed starting backend with '%s'", cmd)
        time.sleep(1) # time to start

        # Find CCD & SEM components
        cls.microscope = model.getMicroscope()
        for comp in model.getComponents():
            if comp.role == "ccd":
                cls.ccd = comp
            elif comp.role == "spectrometer":
                cls.spec = comp
            elif comp.role == "e-beam":
                cls.ebeam = comp
            elif comp.role == "se-detector":
                cls.sed = comp
Пример #10
0
    def setUpClass(cls):

        try:
            test.start_backend(SPARC2_FOCUS2_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # find components by their role
        cls.ccd = model.getComponent(role="ccd0")
        cls.spccd = model.getComponent(role="sp-ccd3")
        cls.focus = model.getComponent(role="focus")
        cls.spgr = model.getComponent(role="spectrograph")
        cls.spgr_ded = model.getComponent(role="spectrograph-dedicated")
        cls.bl = model.getComponent(role="brightlight")
        cls.microscope = model.getMicroscope()
        cls.optmngr = path.OpticalPathManager(cls.microscope)
        cls.specline_ccd = stream.BrightfieldStream("Spectrograph_line_ccd",
                                                    cls.ccd, cls.ccd.data,
                                                    cls.bl)
        cls.specline_spccd = stream.BrightfieldStream(
            "Spectrograph line_spccd", cls.spccd, cls.spccd.data, cls.bl)

        # The good focus position is the start up position
        cls._good_focus = cls.focus.position.value["z"]
Пример #11
0
def get_backend_status():
    try:
        # Fast path: if no back-end file, for sure, it is stopped.
        # The main goal is to avoid showing confusing error messages from Pyro.
        if not os.path.exists(model.BACKEND_FILE):
            return BACKEND_STOPPED

        model._core._microscope = None  # force reset of the microscope
        microscope = model.getMicroscope()
        if not microscope.ghosts.value:
            return BACKEND_RUNNING
        else:
            # Not all components are working => we are "starting" (or borked)
            return BACKEND_STARTING
    except (IOError, CommunicationError):
        if os.path.exists(model.BACKEND_FILE):
            logging.debug(
                "No microscope found, it's sign the back-end is not responding"
            )
            return BACKEND_DEAD
        else:
            logging.debug("Back-end %s file doesn't exists",
                          model.BACKEND_FILE)
            return BACKEND_STOPPED
    except:
        logging.exception("Unresponsive back-end")
        return BACKEND_DEAD

    return BACKEND_DEAD  # Note: unreachable, but leave in case code will be changed
Пример #12
0
 def setUp(self):
     if self.backend_was_running:
         self.skipTest("Running backend found")
     self.opm = acq.path.OpticalPathManager(model.getMicroscope())
     # Speed it up
     self.ccd.exposureTime.value = self.ccd.exposureTime.range[0]
     self.spccd.exposureTime.value = self.spccd.exposureTime.range[0]
Пример #13
0
def start_backend(config):
    """
    Start the backend by checking the currently running backend. Basically 2 cases/scenarios:
        1. If no running backend => run the requested one.
        2. If there is running backend =>
            a. If the running backend is same as requested one => do nothing
            b. If the running backend is different from the requested one => stop the running, and run the requested one.
    In case the backend fails to start a IOError will be raised.
    config (str): path to the microscope config file.
    """
    # check if a backend is running
    if driver.get_backend_status() in (driver.BACKEND_RUNNING,
                                       driver.BACKEND_STARTING):
        current_model = model.getMicroscope().model
        try:
            req_model = modelgen.Instantiator(open(config)).ast
        except Exception as exp:
            raise ValueError(exp)
        if current_model == req_model:
            logging.info("Backend for %s already running", config)
            return
        else:
            logging.info(
                "There is a backend running already, it will be turned off, and the backend \
                                %s will be run instead.", config)
            stop_backend()
            run_backend(config)

    # check if no backend is running
    else:
        run_backend(config)
Пример #14
0
    def __init__(self, standalone=False):
        """
        standalone (boolean): do not try to connect to the backend
        """
        # Replace the standard 'get_resources' with our augmented one, that
        # can handle more control types. See the xhandler package for more info.
        main_xrc.get_resources = odemis_get_resources

        # Declare attributes BEFORE calling the super class constructor
        # because it will call 'OnInit' which uses them.

        # HTTP documentation http server process
        self.http_proc = None

        self.main_data = None
        self.main_frame = None
        self._tab_controller = None
        self._is_standalone = standalone

        if not standalone:
            try:
                driver.speedUpPyroConnect(model.getMicroscope())
            except Exception:
                logging.exception("Failed to speed up start up")

        # Output catcher using a helper class
        wx.App.outputWindowClass = OdemisOutputWindow

        # Constructor of the parent class
        # ONLY CALL IT AT THE END OF :py:method:`__init__` BECAUSE OnInit will
        # be called
        # and it needs the attributes defined in this constructor!
        wx.App.__init__(self, redirect=True)
Пример #15
0
    def test_secom(self):
        """
        Check it properly detects that a SECOM is missing a component
        """
        # Start the backend
        try:
            broken_config_path = CONFIG_PATH + "sim/secom-sim.odm.yaml"
            test.start_backend(broken_config_path)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            self.skipTest("Running backend found")
        except IOError as exp:
            logging.error(str(exp))
            raise

        # Check it fails
        microscope = model.getMicroscope()
        gdata = MainGUIData(microscope)

        self.assertEqual(gdata.microscope, microscope)
        self.assertEqual(gdata.role, microscope.role)

        self.assertIsInstance(gdata.ccd, model.ComponentBase)
        self.assertIn(gdata.ccd, gdata.ccds)
        self.assertIsInstance(gdata.stage, model.ComponentBase)
        self.assertIsNone(gdata.spectrograph)

        self.assertIsNotNone(gdata.opm)
        self.assertIsNotNone(gdata.settings_obs)

        test.stop_backend()
Пример #16
0
    def setUpClass(cls):

        try:
            test.start_backend(SPARC2_FOCUS2_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # find components by their role
        cls.ccd = model.getComponent(role="ccd0")
        cls.spccd = model.getComponent(role="sp-ccd3")
        cls.focus = model.getComponent(role="focus")
        cls.spgr = model.getComponent(role="spectrograph")
        cls.spgr_ded = model.getComponent(role="spectrograph-dedicated")
        cls.bl = model.getComponent(role="brightlight")
        cls.microscope = model.getMicroscope()
        cls.optmngr = path.OpticalPathManager(cls.microscope)
        cls.specline_ccd = stream.BrightfieldStream("Spectrograph_line_ccd", cls.ccd, cls.ccd.data, cls.bl)
        cls.specline_spccd = stream.BrightfieldStream ("Spectrograph line_spccd", cls.spccd, cls.spccd.data, cls.bl)

        # The good focus position is the start up position
        cls._good_focus = cls.focus.position.value["z"]
Пример #17
0
 def test_no_running_backend(self):
     # check if there is no running backend
     backend_status = driver.get_backend_status()
     self.assertIn(backend_status,
                   [driver.BACKEND_STOPPED, driver.BACKEND_DEAD])
     # run enzel
     test.start_backend(ENZEL_CONFIG)
     # now check if the role is enzel
     role = model.getMicroscope().role
     self.assertEqual(role, "enzel")
Пример #18
0
def list_components(pretty=True):
    """
    pretty (bool): if True, display with pretty-printing
    """
    # We actually just browse as a tree the microscope
    try:
        microscope = model.getMicroscope()
    except Exception:
        raise IOError("Failed to contact the back-end")

    print_component_tree(microscope, pretty=pretty)
Пример #19
0
def list_components(pretty=True):
    """
    pretty (bool): if True, display with pretty-printing
    """
    # We actually just browse as a tree the microscope
    try:
        microscope = model.getMicroscope()
    except Exception:
        raise IOError("Failed to contact the back-end")

    print_component_tree(microscope, pretty=pretty)
Пример #20
0
def get_detector(comp_name):
    """
    return the actuator component with the given name
    comp_name (string): name of the component to find
    raises
        LookupError if the component doesn't exist
        other exception if there is an error while contacting the backend
    """
    # isinstance() doesn't work, so we just list every component in microscope.detectors
    microscope = model.getMicroscope()
    return get_component_from_set(comp_name, microscope.detectors)
Пример #21
0
def get_detector(comp_name):
    """
    return the actuator component with the given name
    comp_name (string): name of the component to find
    raises
        LookupError if the component doesn't exist
        other exception if there is an error while contacting the backend
    """
    # isinstance() doesn't work, so we just list every component in microscope.detectors
    microscope = model.getMicroscope()
    return get_component_from_set(comp_name, microscope.detectors)
Пример #22
0
    def setUpClass(cls):
        try:
            test.start_backend(ENZEL_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.light = model.getComponent(role="light")
        cls.focus = model.getComponent(role="focus")
        cls.light_filter = model.getComponent(role="filter")
        cls.stage = model.getComponent(role="stage")
        # Make sure the lens is referenced
        cls.focus.reference({'z'}).result()
        # The 5DoF stage is not referenced automatically, so let's do it now
        stage_axes = set(cls.stage.axes.keys())
        cls.stage.reference(stage_axes).result()
        # Create 1 sem stream and 2 fm streams to be used in testing
        ss1 = stream.SEMStream(
            "sem1",
            cls.sed,
            cls.sed.data,
            cls.ebeam,
            emtvas={"dwellTime", "scale", "magnification", "pixelSize"})

        cls.ccd.exposureTime.value = cls.ccd.exposureTime.range[0]  # go fast
        fs1 = stream.FluoStream("fluo1",
                                cls.ccd,
                                cls.ccd.data,
                                cls.light,
                                cls.light_filter,
                                focuser=cls.focus)
        fs1.excitation.value = sorted(fs1.excitation.choices)[0]

        fs2 = stream.FluoStream("fluo2",
                                cls.ccd,
                                cls.ccd.data,
                                cls.light,
                                cls.light_filter,
                                focuser=cls.focus)
        fs2.excitation.value = sorted(fs2.excitation.choices)[-1]
        cls.sem_streams = [ss1]
        cls.fm_streams = [fs1, fs2]
Пример #23
0
def getCurrentPositionLabel(current_pos, stage):
    """
    Determine where lies the current stage position
    :param current_pos: (dict str->float) Current position of the stage
    :param stage: (Actuator) the stage component 
    :return: (int) a value representing stage position from the constants LOADING, IMAGING, TILTED, COATING..etc
    """
    role = model.getMicroscope().role
    if role == 'enzel':
        return _getCurrentEnzelPositionLabel(current_pos, stage)
    elif role == 'meteor':
        return _getCurrentMeteorPositionLabel(current_pos, stage)
    else:
        raise LookupError("Unhandled microscope role %s" % role)
Пример #24
0
    def setUpClass(cls):
        if TEST_NOHW is True:
            raise unittest.SkipTest(
                "No simulator running or HW present. Skip fastem ROA tests.")

        # get the hardware components
        cls.microscope = model.getMicroscope()
        cls.asm = model.getComponent(role="asm")
        cls.mppc = model.getComponent(role="mppc")
        cls.multibeam = model.getComponent(role="multibeam")
        cls.descanner = model.getComponent(role="descanner")
        cls.stage = model.getComponent(
            role="stage"
        )  # TODO replace with stage-scan when ROA conversion method available
        cls.stage.reference({"x", "y"}).result()
Пример #25
0
    def __init__(self, standalone=False, file_name=None):
        """

        Args:
            standalone: (bool or str) False, if not standalone, name string otherwise
            file_name: (str) Path to the file to open on launch

        """
        # Replace the standard 'get_resources' with our augmented one, that
        # can handle more control types. See the xhandler package for more info.
        main_xrc.get_resources = odemis_get_resources

        # Declare attributes BEFORE calling the super class constructor
        # because it will call 'OnInit' which uses them.

        self.main_data = None
        self.main_frame = None
        self.tab_controller = None
        self._is_standalone = standalone
        self._snapshot_controller = None
        self._menu_controller = None
        self.plugins = []  # List of instances of plugin.Plugins

        # User input devices
        self.dev_powermate = None

        l = logging.getLogger()
        self.log_level = l.getEffectiveLevel()

        if not self._is_standalone:
            try:
                driver.speedUpPyroConnect(model.getMicroscope())
            except Exception:
                logging.exception("Failed to speed up start up")

        # Output catcher using a helper class
        wx.App.outputWindowClass = OdemisOutputWindow

        # Constructor of the parent class
        # ONLY CALL IT AT THE END OF :py:method:`__init__` BECAUSE OnInit will
        # be called
        # and it needs the attributes defined in this constructor!
        wx.App.__init__(self, redirect=True)

        if file_name:
            tab = self.main_data.getTabByName('analysis')
            self.main_data.tab.value = tab
            wx.CallLater(500, tab.load_data, file_name)
Пример #26
0
    def __init__(self, standalone=False, file_name=None):
        """

        Args:
            standalone: (bool or str) False, if not standalone, name string otherwise
            file_name: (str) Path to the file to open on launch

        """
        # Replace the standard 'get_resources' with our augmented one, that
        # can handle more control types. See the xhandler package for more info.
        main_xrc.get_resources = odemis_get_resources

        # Declare attributes BEFORE calling the super class constructor
        # because it will call 'OnInit' which uses them.

        self.main_data = None
        self.main_frame = None
        self.tab_controller = None
        self._is_standalone = standalone
        self._snapshot_controller = None
        self._menu_controller = None
        self.plugins = []  # List of instances of plugin.Plugins

        # User input devices
        self.dev_powermate = None

        l = logging.getLogger()
        self.log_level = l.getEffectiveLevel()

        if not self._is_standalone:
            try:
                driver.speedUpPyroConnect(model.getMicroscope())
            except Exception:
                logging.exception("Failed to speed up start up")

        # Output catcher using a helper class
        wx.App.outputWindowClass = OdemisOutputWindow

        # Constructor of the parent class
        # ONLY CALL IT AT THE END OF :py:method:`__init__` BECAUSE OnInit will
        # be called
        # and it needs the attributes defined in this constructor!
        wx.App.__init__(self, redirect=True)

        if file_name:
            tab = self.main_data.getTabByName('analysis')
            self.main_data.tab.value = tab
            wx.CallLater(500, tab.load_data, file_name)
Пример #27
0
def list_components(pretty=True):
    """
    pretty (bool): if True, display with pretty-printing
    """
    # Show the root first, and don't use it for the graph, because its "children"
    # are actually "dependencies", and it'd multiple parents in the graph.
    microscope = model.getMicroscope()
    subcomps = model.getComponents() - {microscope}

    print_component(microscope, pretty)
    if pretty:
        graph = build_graph_children(subcomps)
        print_component_graph(graph, pretty, 1)
    else:
        # The "pretty" code would do the same, but much slower
        for c in subcomps:
            print_component(c, pretty)
Пример #28
0
    def test_speedUpPyroConnect(self):
        need_stop = False
        if driver.get_backend_status() != driver.BACKEND_RUNNING:
            need_stop = True
            cmd = ODEMISD_CMD + ODEMISD_ARG + [SECOM_CONFIG]
            ret = subprocess.call(cmd)
            if ret != 0:
                logging.error("Failed starting backend with '%s'", cmd)
            time.sleep(1) # time to start
        else:
            model._components._microscope = None # force reset of the microscope for next connection

        speedUpPyroConnect(model.getMicroscope())

        if need_stop:
            cmd = ODEMISD_CMD + ["--kill"]
            subprocess.call(cmd)
Пример #29
0
def get_backend_status():
    try:
        model._core._microscope = None # force reset of the microscope
        microscope = model.getMicroscope()
        if len(microscope.name) > 0:
            return BACKEND_RUNNING
    except (IOError, CommunicationError):
        logging.info("Failed to find microscope")
        if os.path.exists(model.BACKEND_FILE):
            return BACKEND_DEAD
        else:
            logging.info("Back-end %s file doesn't exists", model.BACKEND_FILE)
            return BACKEND_STOPPED
    except:
        logging.exception("Unresponsive back-end")
        return BACKEND_DEAD

    return BACKEND_DEAD
Пример #30
0
def get_backend_status():
    try:
        model._core._microscope = None  # force reset of the microscope
        microscope = model.getMicroscope()
        if len(microscope.name) > 0:
            return BACKEND_RUNNING
    except (IOError, CommunicationError):
        logging.info("Failed to find microscope")
        if os.path.exists(model.BACKEND_FILE):
            return BACKEND_DEAD
        else:
            logging.info("Back-end %s file doesn't exists", model.BACKEND_FILE)
            return BACKEND_STOPPED
    except:
        logging.exception("Unresponsive back-end")
        return BACKEND_DEAD

    return BACKEND_DEAD
Пример #31
0
    def test_speedUpPyroConnect(self):
        try:
            test.start_backend(SECOM_CONFIG)
            need_stop = True
        except LookupError:
            logging.info("A running backend is already found, will not stop it")
            need_stop = False
        except IOError as exp:
            logging.error(str(exp))
            raise

        model._components._microscope = None # force reset of the microscope for next connection

        speedUpPyroConnect(model.getMicroscope())

        time.sleep(2)
        if need_stop:
            test.stop_backend()
Пример #32
0
    def test_speedUpPyroConnect(self):
        try:
            test.start_backend(SECOM_CONFIG)
            need_stop = True
        except LookupError:
            logging.info(
                "A running backend is already found, will not stop it")
            need_stop = False
        except IOError as exp:
            logging.error(str(exp))
            raise

        model._components._microscope = None  # force reset of the microscope for next connection

        speedUpPyroConnect(model.getMicroscope())

        time.sleep(2)
        if need_stop:
            test.stop_backend()
Пример #33
0
def wait_backend_ready():
    """ Wait until the backend is ready of clearly failed
    return (bool): True if the backend is ready, False if it failed to start
    """
    left = 30  # s

    tstart = time.time()
    # First, wait a bit to make sure the backend is started
    sys.stdout.write("  Sleeping for {0} seconds...\r".format(left))
    time.sleep(5)

    left -= 5
    try:
        model._core._microscope = None  # force reset of the microscope
        microscope = model.getMicroscope()
        nghosts = len(microscope.ghosts.value) # Components still to start
    except Exception:
        logging.error("Back-end unreachable")
        return False

    try:
        while left > 0:
            left -= 1
            sys.stdout.flush()
            sys.stdout.write("  Sleeping for {0} seconds...\r".format(left))
            time.sleep(1)

            # TODO: detect the backend stopped
            prev_nghosts = nghosts
            nghosts = len(microscope.ghosts.value)
            if nghosts == 0:
                break  # Everything is started
            elif nghosts < prev_nghosts:
                # Allow to wait 3 s more per component started
                left += 3 * (prev_nghosts - nghosts)

        print
        logging.info("Back-end took %d s to start", time.time() - tstart)
    except KeyboardInterrupt:
        print "\n  Sleep interrupted..."

    return True
Пример #34
0
    def setUpClass(cls):
        try:
            test.start_backend(SPARC_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # Find CCD & SEM components
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.spec = model.getComponent(role="spectrometer")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.lenswitch = model.getComponent(role="lens-switch")
        cls.spec_det_sel = model.getComponent(role="spec-det-selector")
        cls.ar_spec_sel = model.getComponent(role="ar-spec-selector")
Пример #35
0
    def setUpClass(cls):
        try:
            test.start_backend(SPARC_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # Find CCD & SEM components
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.spec = model.getComponent(role="spectrometer")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.lenswitch = model.getComponent(role="lens-switch")
        cls.spec_det_sel = model.getComponent(role="spec-det-selector")
        cls.ar_spec_sel = model.getComponent(role="ar-spec-selector")
Пример #36
0
    def setUpClass(cls):
        try:
            test.start_backend(CRYOSECOM_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.light = model.getComponent(role="light")
        cls.focus = model.getComponent(role="focus")
        cls.light_filter = model.getComponent(role="filter")
        cls.stage = model.getComponent(role="stage")
        # Create 1 sem stream and 2 fm streams to be used in testing
        ss1 = stream.SEMStream(
            "sem1",
            cls.sed,
            cls.sed.data,
            cls.ebeam,
            emtvas={"dwellTime", "scale", "magnification", "pixelSize"})

        fs1 = stream.FluoStream("fluo1",
                                cls.ccd,
                                cls.ccd.data,
                                cls.light,
                                cls.light_filter,
                                focuser=cls.focus)
        fs1.excitation.value = sorted(fs1.excitation.choices)[0]

        fs2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data, cls.light,
                                cls.light_filter)
        fs2.excitation.value = sorted(fs2.excitation.choices)[-1]
        cls.sem_streams = [ss1]
        cls.fm_streams = [fs1, fs2]
Пример #37
0
def stop_move():
    """
    stop the move of every axis of every actuators
    """
    # We actually just browse as a tree the microscope
    try:
        microscope = model.getMicroscope()
        actuators = microscope.actuators
    except Exception:
        logging.error("Failed to contact the back-end")
        return 127

    ret = 0
    for actuator in actuators:
        try:
            actuator.stop()
        except Exception:
            logging.error("Failed to stop actuator %s", actuator.name)
            ret = 127

    return ret
Пример #38
0
def get_backend_status():
    try:
        model._core._microscope = None  # force reset of the microscope
        microscope = model.getMicroscope()
        if not microscope.ghosts.value:
            return BACKEND_RUNNING
        else:
            # Not all components are working => we are "starting" (or borked)
            return BACKEND_STARTING
    except (IOError, CommunicationError):
        logging.info("Failed to find microscope")
        if os.path.exists(model.BACKEND_FILE):
            return BACKEND_DEAD
        else:
            logging.info("Back-end %s file doesn't exists", model.BACKEND_FILE)
            return BACKEND_STOPPED
    except:
        logging.exception("Unresponsive back-end")
        return BACKEND_DEAD

    return BACKEND_DEAD
Пример #39
0
def get_backend_status():
    try:
        model._core._microscope = None # force reset of the microscope
        microscope = model.getMicroscope()
        if not microscope.ghosts.value:
            return BACKEND_RUNNING
        else:
            # Not all components are working => we are "starting" (or borked)
            return BACKEND_STARTING
    except (IOError, CommunicationError):
        logging.info("Failed to find microscope")
        if os.path.exists(model.BACKEND_FILE):
            return BACKEND_DEAD
        else:
            logging.info("Back-end %s file doesn't exists", model.BACKEND_FILE)
            return BACKEND_STOPPED
    except:
        logging.exception("Unresponsive back-end")
        return BACKEND_DEAD

    return BACKEND_DEAD
Пример #40
0
def get_backend_status():
    try:
        model._core._microscope = None # force reset of the microscope
        microscope = model.getMicroscope()
        if not microscope.ghosts.value:
            return BACKEND_RUNNING
        else:
            # Not all components are working => we are "starting" (or borked)
            return BACKEND_STARTING
    except (IOError, CommunicationError):
        if os.path.exists(model.BACKEND_FILE):
            logging.debug("No microscope found, it's sign the back-end is not responding")
            return BACKEND_DEAD
        else:
            logging.debug("Back-end %s file doesn't exists", model.BACKEND_FILE)
            return BACKEND_STOPPED
    except:
        logging.exception("Unresponsive back-end")
        return BACKEND_DEAD

    return BACKEND_DEAD  # Note: unreachable, but leave in case code will be changed
Пример #41
0
def stop_move():
    """
    stop the move of every axis of every actuators
    """
    # We actually just browse as a tree the microscope
    try:
        microscope = model.getMicroscope()
        actuators = microscope.actuators
    except Exception:
        logging.error("Failed to contact the back-end")
        return 127

    ret = 0
    for actuator in actuators:
        try:
            actuator.stop()
        except Exception:
            logging.error("Failed to stop actuator %s", actuator.name)
            ret = 127

    return ret
Пример #42
0
    def test_secom_missing_stage(self):
        """
        Check it properly detects that a SECOM is missing a component
        """
        # Start the backend
        try:
            broken_config_path = os.path.dirname(
                __file__) + "/secom-sim-no-stage.odm.yaml"
            test.start_backend(broken_config_path)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            self.skipTest("Running backend found")
        except IOError as exp:
            logging.error(str(exp))
            raise

        # Check it fails
        microscope = model.getMicroscope()
        with self.assertRaises(KeyError):
            MainGUIData(microscope)

        test.stop_backend()
Пример #43
0
def wait_backend_ready():
    """ Wait until the backend is ready of clearly failed
    return (bool): True if the backend is ready, False if it failed to start
    """
    left = 30  # s

    tstart = time.time()
    # First, wait a bit to make sure the backend is started
    logging.info("Sleeping for %g seconds...", left)
    time.sleep(5)

    left -= 5
    try:
        model._core._microscope = None  # force reset of the microscope
        microscope = model.getMicroscope()
        nghosts = len(microscope.ghosts.value)  # Components still to start
    except Exception:
        logging.error("Back-end unreachable, probably failed to start")
        return False

    try:
        while left > 0:
            left -= 1
            time.sleep(1)

            # TODO: detect the backend stopped
            prev_nghosts = nghosts
            nghosts = len(microscope.ghosts.value)
            if nghosts == 0:
                break  # Everything is started
            elif nghosts < prev_nghosts:
                # Allow to wait 3 s more per component started
                left += 3 * (prev_nghosts - nghosts)

        logging.info("Back-end took %d s to start", time.time() - tstart)
    except KeyboardInterrupt:
        logging.info("Sleep interrupted...")

    return True
Пример #44
0
    def OnInit(self):
        """ Application initialization, automatically run from the :wx:`App`
        constructor.
        """

        if self._is_standalone:
            microscope = None
        else:
            try:
                microscope = model.getMicroscope()
            except (IOError, Pyro4.errors.CommunicationError), e:
                logging.exception("Failed to connect to back-end")
                msg = ("The Odemis GUI could not connect to the Odemis back-end:"
                       "\n\n{0}\n\n"
                       "Launch user interface anyway?").format(e)

                answer = wx.MessageBox(msg,
                                       "Connection error",
                                        style=wx.YES | wx.NO | wx.ICON_ERROR)
                if answer == wx.NO:
                    sys.exit(1)
                microscope = None
Пример #45
0
    def setUpClass(cls):

        if driver.get_backend_status() == driver.BACKEND_RUNNING:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return

        # run the backend as a daemon
        # we cannot run it normally as the child would also think he's in a unittest
        cmd = ODEMISD_CMD + ODEMISD_ARG + [SECOM_CONFIG]
        ret = subprocess.call(cmd)
        if ret != 0:
            logging.error("Failed starting backend with '%s'", cmd)
        time.sleep(1) # time to start

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        for comp in model.getComponents():
            if comp.role == "ccd":
                cls.ccd = comp
            elif comp.role == "spectrometer":
                cls.spec = comp
            elif comp.role == "e-beam":
                cls.ebeam = comp
            elif comp.role == "se-detector":
                cls.sed = comp
            elif comp.role == "light":
                cls.light = comp
            elif comp.role == "filter":
                cls.light_filter = comp

        s1 = stream.FluoStream("fluo1", cls.ccd, cls.ccd.data,
                               cls.light, cls.light_filter)
        s2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data,
                               cls.light, cls.light_filter)
        s2.excitation.value = s2.excitation.range[1]
        s3 = stream.BrightfieldStream("bf", cls.ccd, cls.ccd.data, cls.light)
        cls.streams = [s1, s2, s3]
Пример #46
0
def acquire_spec(wls, wle, res, dt, filename):
    """
    wls (float): start wavelength in m
    wle (float): end wavelength in m
    res (int): number of points to acquire
    dt (float): dwell time in seconds
    filename (str): filename to save to
    """
    # TODO: take a progressive future to update and know if it's the end

    ebeam = model.getComponent(role="e-beam")
    sed = model.getComponent(role="se-detector")
    mchr = model.getComponent(role="monochromator")
    try:
        sgrh = model.getComponent(role="spectrograph")
    except LookupError:
        sgrh = model.getComponent(role="spectrograph-dedicated")
    opm = acq.path.OpticalPathManager(model.getMicroscope())

    prev_dt = ebeam.dwellTime.value
    prev_res = ebeam.resolution.value
    prev_scale = ebeam.scale.value
    prev_trans = ebeam.translation.value
    prev_wl = sgrh.position.value["wavelength"]

    # Create a stream for monochromator scan
    mchr_s = MonochromatorScanStream("Spectrum", mchr, ebeam, sgrh, opm=opm)
    mchr_s.startWavelength.value = wls
    mchr_s.endWavelength.value = wle
    mchr_s.numberOfPixels.value = res
    mchr_s.dwellTime.value = dt
    mchr_s.emtTranslation.value = ebeam.translation.value

    # Create SEM survey stream
    survey_s = stream.SEMStream("Secondary electrons survey",
                                sed, sed.data, ebeam,
        emtvas={"translation", "scale", "resolution", "dwellTime"},
    )
    # max FoV, with scale 4
    survey_s.emtTranslation.value = (0, 0)
    survey_s.emtScale.value = (4, 4)
    survey_s.emtResolution.value = (v / 4 for v in ebeam.resolution.range[1])
    survey_s.emtDwellTime.value = 10e-6  # 10µs is hopefully enough

    # Acquire using the acquisition manager
    # Note: the monochromator scan stream is unknown to the acquisition manager,
    # so it'll be done last
    expt = acq.estimateTime([survey_s, mchr_s])
    f = acq.acquire([survey_s, mchr_s])

    try:
        # Note: the timeout is important, as it allows to catch KeyboardInterrupt
        das, e = f.result(2 * expt + 1)
    except KeyboardInterrupt:
        logging.info("Stopping before end of acquisition")
        f.cancel()
        return
    finally:
        logging.debug("Restoring hardware settings")
        if prev_res != (1, 1):
            ebeam.resolution.value = prev_res
        ebeam.dwellTime.value = prev_dt
        sgrh.moveAbs({"wavelength": prev_wl})
        ebeam.scale.value = prev_scale
        ebeam.translation.value = prev_trans
        if prev_res != (1, 1):
            ebeam.resolution.value = prev_res
        ebeam.dwellTime.value = prev_dt

    if e:
        logging.error("Acquisition failed: %s", e)

    if das:
        # Save the file
        exporter = dataio.find_fittest_converter(filename)
        exporter.export(filename, das)
        logging.info("Spectrum successfully saved to %s", filename)
        raw_input("Press Enter to close.")
Пример #47
0
    def OnInit(self):
        """ Initialize the GUI

        This method is automatically called from the :wx:`App` constructor

        """

        gui.legend_logo = "legend_logo_delmic.png"
        if self._is_standalone:
            microscope = None
            gui.icon = img.getIcon("icon/ico_gui_viewer_256.png")
            gui.name = odemis.__shortname__ + " Viewer"

            if "delphi" == self._is_standalone:
                gui.logo = img.getBitmap("logo_delphi.png")
                gui.legend_logo = "legend_logo_delphi.png"
        else:
            gui.icon = img.getIcon("icon/ico_gui_full_256.png")
            gui.name = odemis.__shortname__
            try:
                microscope = model.getMicroscope()
            except (IOError, Pyro4.errors.CommunicationError) as e:
                logging.exception("Failed to connect to back-end")
                msg = ("The Odemis GUI could not connect to the Odemis back-end:"
                       "\n\n{0}\n\n"
                       "Launch user interface anyway?").format(e)

                answer = wx.MessageBox(msg,
                                       "Connection error",
                                       style=wx.YES | wx.NO | wx.ICON_ERROR)
                if answer == wx.NO:
                    sys.exit(1)
                microscope = None
            else:
                if microscope.role == "delphi":
                    gui.logo = img.getBitmap("logo_delphi.png")
                    gui.legend_logo = "legend_logo_delphi.png"

        logging.info("\n\n************  Starting Odemis GUI  ************\n")
        logging.info("Odemis GUI v%s (from %s)", odemis.__version__, __file__)
        logging.info("wxPython v%s", wx.version())

        # TODO: if microscope.ghost is not empty => wait and/or display a special
        # "hardware status" tab.

        self.main_data = guimodel.MainGUIData(microscope)
        # Load the main frame
        self.main_frame = main_xrc.xrcfr_main(None)

        self.init_gui()

        try:
            from odemis.gui.dev.powermate import Powermate
            self.dev_powermate = Powermate(self.main_data)
        except (LookupError, NotImplementedError) as ex:
            logging.debug("Not using Powermate: %s", ex)
        except Exception:
            logging.exception("Failed to load Powermate support")

        # Application successfully launched
        return True
Пример #48
0
def main(args):
    """
    Handles the command line arguments
    args is the list of arguments passed
    return (int): value to return to the OS as program exit code
    """

    # arguments handling
    parser = argparse.ArgumentParser(prog="odemis-cli",
                                     description=odemis.__fullname__)

    parser.add_argument('--version', dest="version", action='store_true',
                        help="show program's version number and exit")
    opt_grp = parser.add_argument_group('Options')
    opt_grp.add_argument("--log-level", dest="loglev", metavar="<level>", type=int,
                        default=0, help="set verbosity level (0-2, default = 0)")
    opt_grp.add_argument("--machine", dest="machine", action="store_true", default=False,
                         help="display in a machine-friendly way (i.e., no pretty printing)")
    dm_grp = parser.add_argument_group('Microscope management')
    dm_grpe = dm_grp.add_mutually_exclusive_group()
    dm_grpe.add_argument("--kill", "-k", dest="kill", action="store_true", default=False,
                         help="kill the running back-end")
    dm_grpe.add_argument("--check", dest="check", action="store_true", default=False,
                         help="check for a running back-end (only returns exit code)")
    dm_grpe.add_argument("--scan", dest="scan", action="store_true", default=False,
                         help="scan for possible devices to connect (the back-end must be stopped)")
    dm_grpe.add_argument("--list", "-l", dest="list", action="store_true", default=False,
                         help="list the components of the microscope")
    dm_grpe.add_argument("--list-prop", "-L", dest="listprop", metavar="<component>",
                         help="list the properties of a component")
    dm_grpe.add_argument("--set-attr", "-s", dest="setattr", nargs=3, action='append',
                         metavar=("<component>", "<attribute>", "<value>"),
                         help="set the attribute of a component (lists are delimited by commas,"
                         " dictionary keys are delimited by colon)")
    dm_grpe.add_argument("--move", "-m", dest="move", nargs=3, action='append',
                         metavar=("<component>", "<axis>", "<distance>"),
                         help=u"move the axis by the amount of µm.")
    dm_grpe.add_argument("--position", "-p", dest="position", nargs=3, action='append',
                         metavar=("<component>", "<axis>", "<position>"),
                         help=u"move the axis to the given position in µm.")
    dm_grpe.add_argument("--stop", "-S", dest="stop", action="store_true", default=False,
                         help="immediately stop all the actuators in all directions.")
    dm_grpe.add_argument("--acquire", "-a", dest="acquire", nargs="+",
                         metavar=("<component>", "data-flow"),
                         help="acquire an image (default data-flow is \"data\")")
    dm_grp.add_argument("--output", "-o", dest="output",
                        help="name of the file where the image should be saved after acquisition. The file format is derived from the extension (TIFF and HDF5 are supported).")
    dm_grpe.add_argument("--live", dest="live", nargs="+",
                         metavar=("<component>", "data-flow"),
                         help="display and update an image on the screen (default data-flow is \"data\")")

    options = parser.parse_args(args[1:])

    # To allow printing unicode even with pipes
    ensure_output_encoding()

    # Cannot use the internal feature, because it doesn't support multiline
    if options.version:
        print (odemis.__fullname__ + " " + odemis.__version__ + "\n" +
               odemis.__copyright__ + "\n" +
               "Licensed under the " + odemis.__license__)
        return 0

    # Set up logging before everything else
    if options.loglev < 0:
        parser.error("log-level must be positive.")
    # TODO: allow to put logging level so low that nothing is ever output
    loglev_names = [logging.WARNING, logging.INFO, logging.DEBUG]
    loglev = loglev_names[min(len(loglev_names) - 1, options.loglev)]

    # change the log format to be more descriptive
    handler = logging.StreamHandler()
    logging.getLogger().setLevel(loglev)
    handler.setFormatter(logging.Formatter('%(asctime)s (%(module)s) %(levelname)s: %(message)s'))
    logging.getLogger().addHandler(handler)

    # anything to do?
    if (not options.check and not options.kill and not options.scan
        and not options.list and not options.stop and options.move is None
        and options.position is None
        and options.listprop is None and options.setattr is None
        and options.acquire is None and options.live is None):
        logging.error("no action specified.")
        return 127
    if options.acquire is not None and options.output is None:
        logging.error("name of the output file must be specified.")
        return 127


    logging.debug("Trying to find the backend")
    status = get_backend_status()
    if options.check:
        logging.info("Status of back-end is %s", status)
        return status_to_xtcode[status]

    # scan needs to have the backend stopped
    if options.scan:
        if status == BACKEND_RUNNING:
            logging.error("Back-end running while trying to scan for devices")
            return 127
        try:
            return scan()
        except Exception:
            logging.exception("Unexpected error while performing scan.")
            return 127

    # check if there is already a backend running
    if status == BACKEND_STOPPED:
        logging.error("No running back-end")
        return 127
    elif status == BACKEND_DEAD:
        logging.error("Back-end appears to be non-responsive.")
        return 127

    try:
        if options.kill:
            return kill_backend()

        logging.debug("Executing the actions")

        if options.list:
            return list_components(pretty=not options.machine)
        elif options.listprop is not None:
            # Speed up is only worthy if many VAs are accessed
            odemis.util.driver.speedUpPyroConnect(model.getMicroscope())
            return list_properties(options.listprop, pretty=not options.machine)
        elif options.setattr is not None:
            for c, a, v in options.setattr:
                ret = set_attr(c, a, v)
                if ret != 0:
                    return ret
        elif options.position is not None:
            for c, a, d in options.position:
                ret = move_abs(c, a, d)
                # TODO warn if same axis multiple times
                if ret != 0:
                    return ret
            time.sleep(0.5)
        elif options.move is not None:
            for c, a, d in options.move:
                ret = move(c, a, d)
                # TODO move commands to the same actuator should be agglomerated
                if ret != 0:
                    return ret
            time.sleep(0.5) # wait a bit for the futures to close nicely
        elif options.stop:
            return stop_move()
        elif options.acquire is not None:
            component = options.acquire[0]
            if len(options.acquire) == 1:
                dataflows = ["data"]
            else:
                dataflows = options.acquire[1:]
            filename = options.output.decode(sys.getfilesystemencoding())
            return acquire(component, dataflows, filename)
        elif options.live is not None:
            component = options.live[0]
            if len(options.live) == 1:
                dataflow = "data"
            elif len(options.live) == 2:
                dataflow = options.acquire[2]
            else:
                logging.error("live command accepts only one data-flow")
                return 127
            return live_display(component, dataflow)
    except:
        logging.exception("Unexpected error while performing action.")
        return 127

    return 0