Example #1
0
def convert_units(x, target):
    """Convert or attach units to a variable.

    Parameters
    ----------
    x : float
        Quantity to convert.
    target : str
        Target units given as an acceptable astropy.units string (e.g. 'km').

    Raises
    ------
    Exception
        If the conversion fails.

    Examples
    --------
    >>> conv(5, 'kpc')
    <Quantity 5. kpc>

    >>> x = 4e14
    >>> x = conv(x, 'solMass')
    >>> conv(x, 'kg')
    <Quantity 7.95390166e+44 kg>

    """
    try:
        x = x.to(Unit(target))
    except AttributeError:
        x = x * Unit(target)
    except Exception as e:
        raise

    return x
Example #2
0
 def p_main(p):
     '''
     main : factor combined_units
          | combined_units
          | factor
     '''
     from astropy.units.core import Unit
     if len(p) == 3:
         p[0] = Unit(p[1] * p[2])
     else:
         p[0] = Unit(p[1])
Example #3
0
 def p_main(p):
     '''
     main : factor combined_units
          | combined_units
          | OPEN_BRACKET combined_units CLOSE_BRACKET
          | factor
     '''
     from astropy.units.core import Unit
     from astropy.units import dex
     if len(p) == 3:
         p[0] = Unit(p[1] * p[2])
     elif len(p) == 4:
         p[0] = dex(p[2])
     else:
         p[0] = Unit(p[1])
Example #4
0
 def p_division_product_of_units(p):
     '''
     division_product_of_units : division_product_of_units division product_of_units
                               | product_of_units
     '''
     from astropy.units.core import Unit
     if len(p) == 4:
         p[0] = Unit(p[1] / p[3])
     else:
         p[0] = p[1]
Example #5
0
 def p_main(p):
     '''
     main : product_of_units
          | factor product_of_units
          | factor product product_of_units
          | division_product_of_units
          | factor division_product_of_units
          | factor product division_product_of_units
          | inverse_unit
          | factor inverse_unit
          | factor product inverse_unit
          | factor
     '''
     from astropy.units.core import Unit
     if len(p) == 2:
         p[0] = Unit(p[1])
     elif len(p) == 3:
         p[0] = Unit(p[1] * p[2])
     elif len(p) == 4:
         p[0] = Unit(p[1] * p[3])
Example #6
0
    def _unit(self):
        """The unit(s) in which this constant is defined."""

        return Unit(self._unit_string)
Example #7
0
    def __new__(
        cls,
        value,
        unit=None,
        tags={},
        dtype=None,
        copy=True,
        order=None,
        subok=False,
        ndmin=0,
    ):

        if unit is not None:
            # convert unit first, to avoid multiple string->unit conversions
            unit = Unit(unit)

        # optimize speed for Quantity with no dtype given, copy=False
        if isinstance(value, u.Quantity):
            if unit is not None and unit is not value.unit:
                value = value.to(unit)
                # the above already makes a copy (with float dtype)
                copy = False

            if type(value) is not cls and not (subok and isinstance(value, cls)):
                value = value.view(cls)

            if dtype is None:
                if not copy:
                    return value

                if value.dtype.kind in "iu":
                    dtype = float

            return np.array(
                value, dtype=dtype, copy=copy, order=order, subok=True, ndmin=ndmin,
            )

        # Maybe str, or list/tuple of Quantity? If so, this may set value_unit.
        # To ensure array remains fast, we short-circuit it.
        value_unit = None
        if not isinstance(value, np.ndarray):
            if isinstance(value, str):
                # The first part of the regex string matches any integer/float;
                # the second parts adds possible trailing .+-, which will break
                # the float function below and ensure things like 1.2.3deg
                # will not work.
                pattern = (
                    r"\s*[+-]?"
                    r"((\d+\.?\d*)|(\.\d+)|([nN][aA][nN])|"
                    r"([iI][nN][fF]([iI][nN][iI][tT][yY]){0,1}))"
                    r"([eE][+-]?\d+)?"
                    r"[.+-]?"
                )

                v = re.match(pattern, value)
                unit_string = None
                try:
                    value = float(v.group())

                except Exception:
                    raise TypeError(
                        'Cannot parse "{}" as a {}. It does not '
                        "start with a number.".format(value, cls.__name__)
                    )

                unit_string = v.string[v.end() :].strip()
                if unit_string:
                    value_unit = Unit(unit_string)
                    if unit is None:
                        unit = value_unit  # signal no conversion needed below.

            elif (
                isiterable(value)
                and len(value) > 0
                and all(isinstance(v, VPLANETQuantity) for v in value)
            ):
                # Convert all quantities to the same unit.
                if unit is None:
                    unit = value[0].unit
                value = [q.to_value(unit) for q in value]
                value_unit = unit  # signal below that conversion has been done

        if value_unit is None:
            # If the value has a `unit` attribute and if not None
            # (for Columns with uninitialized unit), treat it like a quantity.
            value_unit = getattr(value, "unit", None)
            if value_unit is None:
                # Default to dimensionless for no (initialized) unit attribute.
                if unit is None:
                    unit = cls._default_unit
                value_unit = unit  # signal below that no conversion is needed
            else:
                try:
                    value_unit = Unit(value_unit)
                except Exception as exc:
                    raise TypeError(
                        "The unit attribute {!r} of the input could "
                        "not be parsed as an astropy Unit, raising "
                        "the following exception:\n{}".format(value.unit, exc)
                    )

                if unit is None:
                    unit = value_unit
                elif unit is not value_unit:
                    copy = False  # copy will be made in conversion at end

        value = np.array(
            value, dtype=dtype, copy=copy, order=order, subok=False, ndmin=ndmin,
        )

        # check that array contains numbers or long int objects
        if value.dtype.kind in "OSU" and not (
            value.dtype.kind == "O" and isinstance(value.item(0), numbers.Number)
        ):
            raise TypeError("The value must be a valid Python or Numpy numeric type.")

        # by default, cast any integer, boolean, etc., to float
        if dtype is None and value.dtype.kind in "iuO":
            value = value.astype(float)

        # if we allow subclasses, allow a class from the unit.
        if subok:
            qcls = getattr(unit, "_quantity_class", cls)
            if issubclass(qcls, cls):
                cls = qcls

        value = value.view(cls)
        value._set_unit(value_unit)

        # Custom tags
        value.tags = tags

        if unit is value_unit:
            return value
        else:
            # here we had non-Quantity input that had a "unit" attribute
            # with a unit different from the desired one.  So, convert.
            return value.to(unit)
Example #8
0
def quantity_return_(
    res: T.Any,
    unit: T.Union[None, UnitableType] = None,
    to_value: bool = False,
    equivalencies: list = [],
    decompose: T.Union[bool, T.Sequence] = False,
):
    """Control function return of :class:`~astropy.units.Quantity`.

    Parameters
    ----------
    res: :class:`~astropy.units.Quantity`, optional
        the result
    {parameters}

    Returns
    -------
    res:
        function output, converted / decomposed / evaluated to desired units

    Raises
    ------
    {raises}

    Examples
    --------
    How to apply in a function directly

    >>> def example_function(x, **kw):
    ...     return quantity_return_(x, unit=kw.get('unit', None),
    ...                             to_value=kw.get('to_value', False),
    ...                             equivalencies=kw.get('equivalencies', []),
    ...                             decompose=kw.get('decompose', []))
    >>> example_function(10*u.km, unit=u.m, to_value=True)
    10000.0

    """
    # fast checks to do nothing
    # nothing required
    if not hasattr(res, "to"):
        return res
    # nothing asked
    elif ((unit is None)
          & (to_value is False)
          & (equivalencies == [])
          & (decompose is False)):
        return res

    # --------------------
    # Decomposing

    if decompose is False:
        pass
    elif decompose is True:
        res = res.decompose()
    elif decompose:  # decompose is NOT empty list
        clss = (Unit, IrreducibleUnit)
        bases = [
            Unit(x) if not issubclass(x.__class__, clss) else x
            for x in decompose
        ]
        res = res.decompose(bases=bases)

    # --------------------
    # Returning

    if (unit is None) and (to_value is False):  # nothing further required
        pass
    elif to_value is True:  # return value
        unit = u.Unit(unit) if unit is not None else unit
        res = res.to_value(unit, equivalencies=equivalencies)
    else:  # return, with unit conversion
        if equivalencies:  # has equivalencies, must use "to"
            res = res.to(u.Unit(unit), equivalencies=equivalencies)
        else:  # no equivalencies, can convert in-place
            res <<= u.Unit(unit)

    return res