예제 #1
0
def move(comp_name, moves, check_distance=True, to_radians=False):
    """
    move (relatively) the axis of the given component by the specified amount of µm
    comp_name (str): name of the component
    moves (dict str -> str): axis -> distance (as text, and in µm for distances)
    check_distance (bool): if the axis is in meters, check that the move is not
      too big.
    to_radians (bool): will convert from degrees to radians if the axis is in radians,
      otherwise will fail
    """
    # for safety reason, we use µm instead of meters, as it's harder to type a
    # huge distance
    component = get_component(comp_name)

    act_mv = {} # axis -> value
    for axis_name, str_distance in moves.items():
        try:
            if axis_name not in component.axes:
                raise ValueError("Actuator %s has no axis '%s'" % (comp_name, axis_name))
            ad = component.axes[axis_name]
        except (TypeError, AttributeError):
            raise ValueError("Component %s is not an actuator" % comp_name)

        if ad.unit == "m":
            try:
                # Use convert_to_object() to allow typing negative values with e:
                # -1e-6 => '!!float -1.0e-6'. It's not very nice, but does work.
                distance = float(convert_to_object(str_distance)) * 1e-6  # µm -> m
            except ValueError:
                raise ValueError("Distance '%s' cannot be converted to a number" %
                                 str_distance)

            if check_distance and abs(distance) > MAX_DISTANCE:
                raise IOError("Distance of %f m is too big (> %f m), use '--big-distance' to allow the move." %
                              (abs(distance), MAX_DISTANCE))
        else:
            distance = convert_to_object(str_distance)

        if to_radians:
            if ad.unit == "rad":
                distance = math.radians(distance)
            else:
                raise ValueError("Axis %s is in %s, doesn't support value in degrees" % (axis_name, ad.unit))

        act_mv[axis_name] = distance
        logging.info(u"Will move %s.%s by %s", comp_name, axis_name,
                     units.readable_str(distance, ad.unit, sig=3))

    try:
        m = component.moveRel(act_mv)
        try:
            m.result(120)
        except KeyboardInterrupt:
            logging.warning("Cancelling relative move of component %s", comp_name)
            m.cancel()
            raise
    except Exception as exc:
        raise IOError("Failed to move component %s by %s: %s" %
                      (comp_name, act_mv, exc))
예제 #2
0
파일: main.py 프로젝트: delmic/odemis
def move(comp_name, moves, check_distance=True):
    """
    move (relatively) the axis of the given component by the specified amount of µm
    comp_name (str): name of the component
    check_distance (bool): if the axis is in meters, check that the move is not
      too big.
    moves (dict str -> str): axis -> distance (as text, and in µm for distances)
    """
    # for safety reason, we use µm instead of meters, as it's harder to type a
    # huge distance
    component = get_component(comp_name)

    act_mv = {} # axis -> value
    for axis_name, str_distance in moves.items():
        try:
            if axis_name not in component.axes:
                raise ValueError("Actuator %s has no axis '%s'" % (comp_name, axis_name))
            ad = component.axes[axis_name]
        except (TypeError, AttributeError):
            raise ValueError("Component %s is not an actuator" % comp_name)

        if ad.unit == "m":
            try:
                # Use convert_to_object() to allow typing negative values with e:
                # -1e-6 => '!!float -1.0e-6'. It's not very nice, but does work.
                distance = float(convert_to_object(str_distance)) * 1e-6  # µm -> m
            except ValueError:
                raise ValueError("Distance '%s' cannot be converted to a number" %
                                 str_distance)

            if check_distance and abs(distance) > MAX_DISTANCE:
                raise IOError("Distance of %f m is too big (> %f m), use '--big-distance' to allow the move." %
                              (abs(distance), MAX_DISTANCE))
        else:
            distance = convert_to_object(str_distance)

        act_mv[axis_name] = distance
        logging.info(u"Will move %s.%s by %s", comp_name, axis_name,
                     units.readable_str(distance, ad.unit, sig=3))

    try:
        m = component.moveRel(act_mv)
        try:
            m.result(120)
        except KeyboardInterrupt:
            logging.warning("Cancelling relative move of component %s", comp_name)
            m.cancel()
            raise
    except Exception as exc:
        raise IOError("Failed to move component %s by %s: %s" %
                      (comp_name, act_mv, exc))
예제 #3
0
    def test_convertToObject_good(self):
        """
        check various inputs and compare to expected output
        for values that should work
        """
        # example value / input str / expected output
        tc = [("-1561", -1561),
              ("0.123", 0.123),
              ("true", True),
              ("c: 6,d: 1.3", {"c": 6., "d":1.3}),
              ("-9, -8", [-9, -8]),
              (" 9, -8", [9, -8]),
              ("0, -8, -15.e-3, 6.", [0, -8, -15e-3, 6.0]),
              ("0.1", 0.1),
              ("[aa,bb]", ["aa", "bb"]),
              # TODO: more complicated but nice to support for the user
              # ("256 x 256 px", (256, 256)),
              # ("21 x 0.2 m", (21, 0.2)),
              ("", None),
              ("{5: }", {5: None}), # Should it fail?
              ("-1, 63, 12", [-1, 63, 12]), # NotifyingList becomes a list
              ("9.3, -8", [9.3, -8]),
              # Note: we don't support SI prefixes
              ("[aa, c a]", ["aa", "c a"]),
              ]

        for str_val, expo in tc:
            out = convert_to_object(str_val)
            self.assertEqual(out, expo,
                 "Testing with '%s' -> %s" % (str_val, out))
예제 #4
0
파일: main.py 프로젝트: amuskens/odemis
def update_metadata(comp_name, key_val_str):
    """
    update the metadata of the given component with the given key/value
    key_val_str (dict str->str): key name -> value as a string
    """
    component = get_component(comp_name)

    md = {}
    for key_name, str_val in key_val_str.items():
        # Check that the metadata is a valid one. It's a bit tricky as there is no
        # "official" list. But we look at the ones defined in model.MD_*
        for n, v in inspect_getmembers(model, lambda m: isinstance(m, str)):
            if n.startswith("MD_") and v == key_name:
                key = key_name
                break
        else:
            # fallback to looking for MD_{key_name}
            try:
                key = getattr(model, "MD_%s" % key_name)
            except AttributeError:
                raise ValueError("Metadata key '%s' is unknown" % key_name)

        md[key] = convert_to_object(str_val)

    try:
        component.updateMetadata(md)
    except Exception as exc:
        raise IOError("Failed to update metadata of %s to %s: %s" %
                      (comp_name, md, exc))
예제 #5
0
파일: main.py 프로젝트: ktsitsikas/odemis
def update_metadata(comp_name, key_val_str):
    """
    update the metadata of the given component with the given key/value
    key_val_str (dict str->str): key name -> value as a string
    """
    component = get_component(comp_name)

    md = {}
    for key_name, str_val in key_val_str.items():
        # Check that the metadata is a valid one. It's a bit tricky as there is no
        # "official" list. But we look at the ones defined in model.MD_*
        for n, v in inspect.getmembers(model, lambda m: isinstance(m, str)):
            if n.startswith("MD_") and v == key_name:
                key = key_name
                break
        else:
            # fallback to looking for MD_{key_name}
            try:
                key = getattr(model, "MD_%s" % key_name)
            except AttributeError:
                raise ValueError("Metadata key '%s' is unknown" % key_name)

        md[key] = convert_to_object(str_val)

    try:
        component.updateMetadata(md)
    except Exception as exc:
        raise IOError("Failed to update metadata of %s to %s: %s" %
                      (comp_name, md, exc))
예제 #6
0
파일: main.py 프로젝트: ktsitsikas/odemis
def set_attr(comp_name, attr_val_str):
    """
    set the value of vigilant attribute of the given component.
    attr_val_str (dict str->str): attribute name -> value as a string
    """
    component = get_component(comp_name)

    for attr_name, str_val in attr_val_str.items():
        try:
            attr = getattr(component, attr_name)
        except Exception:
            raise ValueError("Failed to find attribute '%s' on component '%s'" % (attr_name, comp_name))

        if not isinstance(attr, model.VigilantAttributeBase):
            raise ValueError("'%s' is not a vigilant attribute of component %s" % (attr_name, comp_name))

        new_val = convert_to_object(str_val)

        # Special case for floats, due to rounding error, it's very hard to put the
        # exact value if it's an enumerated VA. So just pick the closest one in this
        # case.
        if isinstance(new_val, float) and (
           hasattr(attr, "choices") and isinstance(attr.choices, collections.Iterable)):
            orig_val = new_val
            new_val = util.find_closest(new_val, attr.choices)
            if new_val != orig_val:
                logging.debug("Adjusting value to %s", new_val)

        try:
            attr.value = new_val
        except Exception as exc:
            raise IOError("Failed to set %s.%s = '%s': %s" % (comp_name, attr_name, str_val, exc))
예제 #7
0
    def test_convertToObject_bad(self):
        """
        check various inputs and compare to expected output
        for values that should raise an exception
        """
        # example value / input str
        tc = [("{5:"),
              ("[5.3"),
              # ("5,6]"), # TODO
              ]

        for str_val in tc:
            with self.assertRaises((ValueError, TypeError)):
                out = convert_to_object(str_val)
예제 #8
0
    def test_convertToObject_bad(self):
        """
        check various inputs and compare to expected output
        for values that should raise an exception
        """
        # example value / input str
        tc = [
            "{5:",
            "[5.3",
            # ("5,6]"), # TODO
        ]

        for str_val in tc:
            with self.assertRaises((ValueError, TypeError)):
                out = convert_to_object(str_val)
예제 #9
0
def set_attr(comp_name, attr_val_str):
    """
    set the value of vigilant attribute of the given component.
    attr_val_str (dict str->str): attribute name -> value as a string
    """
    component = get_component(comp_name)

    for attr_name, str_val in attr_val_str.items():
        try:
            attr = getattr(component, attr_name)
        except Exception:
            raise ValueError(
                "Failed to find attribute '%s' on component '%s'" %
                (attr_name, comp_name))

        if not isinstance(attr, model.VigilantAttributeBase):
            raise ValueError(
                "'%s' is not a vigilant attribute of component %s" %
                (attr_name, comp_name))

        new_val = convert_to_object(str_val)

        # Special case for floats, due to rounding error, it's very hard to put the
        # exact value if it's an enumerated VA. So just pick the closest one in this
        # case.
        if (isinstance(new_val, float) and hasattr(attr, "choices")
                and isinstance(attr.choices, collections.Iterable)):
            orig_val = new_val
            choices = [
                v for v in attr.choices if isinstance(v, numbers.Number)
            ]
            new_val = util.find_closest(new_val, choices)
            if new_val != orig_val:
                logging.debug("Adjusting value to %s", new_val)

        # Special case for None being referred to as "null" in YAML, but we should
        # also accept "None"
        elif new_val == "None" and not isinstance(attr.value, basestring):
            new_val = None
            logging.debug("Adjusting value to %s (null)", new_val)

        try:
            attr.value = new_val
        except Exception as exc:
            raise IOError("Failed to set %s.%s = '%s': %s" %
                          (comp_name, attr_name, str_val, exc))
예제 #10
0
    def test_convertToObject_good(self):
        """
        check various inputs and compare to expected output
        for values that should work
        """
        # example value / input str / expected output
        tc = [
            ("-1561", -1561),
            ("0.123", 0.123),
            ("true", True),
            ("c: 6,d: 1.3", {
                "c": 6.,
                "d": 1.3
            }),
            ("-9, -8", [-9, -8]),
            (" 9, -8", [9, -8]),
            ("0, -8, -15.e-3, 6.", [0, -8, -15e-3, 6.0]),
            ("0.1", 0.1),
            ("[aa,bb]", ["aa", "bb"]),
            # TODO: more complicated but nice to support for the user
            # ("256 x 256 px", (256, 256)),
            # ("21 x 0.2 m", (21, 0.2)),
            ("", None),
            ("{5: }", {
                5: None
            }),  # Should it fail?
            ("-1, 63, 12", [-1, 63, 12]),  # NotifyingList becomes a list
            ("9.3, -8", [9.3, -8]),
            # Note: we don't support SI prefixes
            ("[aa, c a]", ["aa", "c a"]),
        ]

        for str_val, expo in tc:
            out = convert_to_object(str_val)
            self.assertEqual(out, expo,
                             "Testing with '%s' -> %s" % (str_val, out))
예제 #11
0
파일: main.py 프로젝트: amuskens/odemis
def move_abs(comp_name, moves, check_distance=True):
    """
    move (in absolute) the axis of the given component to the specified position
    comp_name (str): name of the component
    check_distance (bool): if the axis is in meters, check that the move is not
      too big.
    moves (dict str -> str): axis -> position (as text)
    """
    component = get_component(comp_name)

    act_mv = {} # axis -> value
    for axis_name, str_position in moves.items():
        try:
            if axis_name not in component.axes:
                raise ValueError("Actuator %s has no axis '%s'" % (comp_name, axis_name))
            ad = component.axes[axis_name]
        except (TypeError, AttributeError):
            raise ValueError("Component %s is not an actuator" % comp_name)

        # Allow the user to indicate the position via the user-friendly choice entry
        position = None
        if hasattr(ad, "choices") and isinstance(ad.choices, dict):
            for key, value in ad.choices.items():
                if value == str_position:
                    logging.info("Converting '%s' into %s", str_position, key)
                    position = key
                    # Even if it's a big distance, we don't complain as it's likely
                    # that all choices are safe
                    break

        if position is None:
            if ad.unit == "m":
                try:
                    position = float(convert_to_object(str_position))
                except ValueError:
                    raise ValueError("Position '%s' cannot be converted to a number" % str_position)

                # compare to the current position, to see if the new position sounds reasonable
                cur_pos = component.position.value[axis_name]
                if check_distance and abs(cur_pos - position) > MAX_DISTANCE:
                    raise IOError("Distance of %f m is too big (> %f m), use '--big-distance' to allow the move." %
                                  (abs(cur_pos - position), MAX_DISTANCE))
            else:
                position = convert_to_object(str_position)

            # If only a couple of positions are possible, and asking for a float,
            # avoid the rounding error by looking for the closest possible
            if (isinstance(position, numbers.Real) and
                hasattr(ad, "choices") and
                isinstance(ad.choices, collections.Iterable) and
                position not in ad.choices):
                closest = util.find_closest(position, ad.choices)
                if util.almost_equal(closest, position, rtol=1e-3):
                    logging.debug("Adjusting value %.15g to %.15g", position, closest)
                    position = closest

        act_mv[axis_name] = position
        if isinstance(position, numbers.Real):
            pos_pretty = units.readable_str(position, ad.unit, sig=3)
        else:
            pos_pretty = "%s" % (position,)
        logging.info(u"Will move %s.%s to %s", comp_name, axis_name, pos_pretty)

    try:
        m = component.moveAbs(act_mv)
        try:
            m.result(120)
        except KeyboardInterrupt:
            logging.warning("Cancelling absolute move of component %s", comp_name)
            m.cancel()
            raise
    except Exception as exc:
        raise IOError("Failed to move component %s to %s: %s" %
                      (comp_name, act_mv, exc))
예제 #12
0
파일: main.py 프로젝트: ktsitsikas/odemis
def move_abs(comp_name, moves, check_distance=True):
    """
    move (in absolute) the axis of the given component to the specified position
    comp_name (str): name of the component
    check_distance (bool): if the axis is in meters, check that the move is not
      too big.
    moves (dict str -> str): axis -> position (as text)
    """
    component = get_component(comp_name)

    act_mv = {} # axis -> value
    for axis_name, str_position in moves.items():
        try:
            if axis_name not in component.axes:
                raise ValueError("Actuator %s has no axis '%s'" % (comp_name, axis_name))
            ad = component.axes[axis_name]
        except (TypeError, AttributeError):
            raise ValueError("Component %s is not an actuator" % comp_name)

        # Allow the user to indicate the position via the user-friendly choice entry
        position = None
        if (hasattr(ad, "choices") and isinstance(ad.choices, dict)):
            for key, value in ad.choices.items():
                if value == str_position:
                    logging.info("Converting '%s' into %s", str_position, key)
                    position = key
                    # Even if it's a big distance, we don't complain as it's likely
                    # that all choices are safe
                    break

        if position is None:
            if ad.unit == "m":
                try:
                    position = float(str_position)
                except ValueError:
                    raise ValueError("Position '%s' cannot be converted to a number" % str_position)

                # compare to the current position, to see if the new position sounds reasonable
                cur_pos = component.position.value[axis_name]
                if check_distance and abs(cur_pos - position) > MAX_DISTANCE:
                    raise IOError("Distance of %f m is too big (> %f m), use '--big-distance' to allow the move." %
                                  (abs(cur_pos - position), MAX_DISTANCE))
            else:
                position = convert_to_object(str_position)

            # If only a couple of positions are possible, and asking for a float,
            # avoid the rounding error by looking for the closest possible
            if (isinstance(position, numbers.Real) and
                hasattr(ad, "choices") and
                isinstance(ad.choices, collections.Iterable) and
                position not in ad.choices):
                closest = util.find_closest(position, ad.choices)
                if util.almost_equal(closest, position, rtol=1e-3):
                    logging.debug("Adjusting value %.15g to %.15g", position, closest)
                    position = closest

        act_mv[axis_name] = position
        logging.info(u"Will move %s.%s to %s", comp_name, axis_name,
                     units.readable_str(position, ad.unit, sig=3))

    try:
        m = component.moveAbs(act_mv)
        try:
            m.result(120)
        except KeyboardInterrupt:
            logging.warning("Cancelling absolute move of component %s", comp_name)
            m.cancel()
            raise
    except Exception as exc:
        raise IOError("Failed to move component %s to %s: %s" %
                      (comp_name, act_mv, exc))