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
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])
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])
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]
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])
def _unit(self): """The unit(s) in which this constant is defined.""" return Unit(self._unit_string)
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)
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