Пример #1
0
 def __init__(
     self,
     name,
     length_unit,
     mass_unit,
     time_unit,
     temperature_unit="K",
     angle_unit="rad",
     current_mks_unit="A",
     luminous_intensity_unit="cd",
     registry=None,
 ):
     self.registry = registry
     self.units_map = OrderedDict(
         [
             (dimensions.length, length_unit),
             (dimensions.mass, mass_unit),
             (dimensions.time, time_unit),
             (dimensions.temperature, temperature_unit),
             (dimensions.angle, angle_unit),
             (dimensions.current_mks, current_mks_unit),
             (dimensions.luminous_intensity, luminous_intensity_unit),
         ]
     )
     for k, v in self.units_map.items():
         if v is not None:
             if hasattr(v, "value") and hasattr(v, "units"):
                 self.units_map[k] = v.value * v.units.expr
             else:
                 self.units_map[k] = parse_unyt_expr(str(v))
     for dimension, unit in self.units_map.items():
         # CGS sets the current_mks unit to none, so catch it here
         if unit is None and dimension is dimensions.current_mks:
             continue
         if unit.is_Mul:
             unit = unit.as_coeff_Mul()[1]
         if (
             self.registry is not None
             and self.registry[str(unit)][1] is not dimension
         ):
             raise IllDefinedUnitSystem(self.units_map)
         elif self.registry is None:
             bu = _split_prefix(str(unit), default_lut)[1]
             inferred_dimension = default_lut[inv_name_alternatives[bu]][1]
             if inferred_dimension is not dimension:
                 raise IllDefinedUnitSystem(self.units_map)
     self._dims = [
         "length",
         "mass",
         "time",
         "temperature",
         "angle",
         "current_mks",
         "luminous_intensity",
     ]
     self.registry = registry
     self.base_units = self.units_map.copy()
     unit_system_registry[name] = self
     self.name = name
Пример #2
0
 def __setitem__(self, key, value):
     if isinstance(key, str):
         if key not in self._dims:
             self._dims.append(key)
         key = getattr(dimensions, key)
     if self.units_map[cmks] is None and cmks in key.free_symbols:
         raise MissingMKSCurrent(self.name)
     self.units_map[key] = parse_unyt_expr(str(value))
Пример #3
0
    def __getitem__(self, key):
        from unyt.unit_object import Unit

        if isinstance(key, str):
            key = getattr(dimensions, key)
        um = self.units_map
        if key not in um or um[key] is None:
            if cmks in key.free_symbols and self.units_map[cmks] is None:
                raise MissingMKSCurrent(self.name)
            units = _get_system_unit_string(key, self.units_map)
            self.units_map[key] = parse_unyt_expr(units)
            return Unit(units, registry=self.registry)
        return Unit(self.units_map[key], registry=self.registry)
Пример #4
0
    def __new__(
        cls,
        unit_expr=sympy_one,
        base_value=None,
        base_offset=0.0,
        dimensions=None,
        registry=None,
        latex_repr=None,
    ):
        """
        Create a new unit. May be an atomic unit (like a gram) or combinations
        of atomic units (like g / cm**3).

        Parameters
        ----------
        unit_expr : Unit object, sympy.core.expr.Expr object, or str
            The symbolic unit expression.
        base_value : float
            The unit's value in yt's base units.
        base_offset : float
            The offset necessary to normalize temperature units to a common
            zero point.
        dimensions : sympy.core.expr.Expr
            A sympy expression representing the dimensionality of this unit.
            It must contain only mass, length, time, temperature and angle
            symbols.
        registry : UnitRegistry object
            The unit registry we use to interpret unit symbols.
        latex_repr : string
            A string to render the unit as LaTeX

        """
        unit_cache_key = None
        # Simplest case. If user passes a Unit object, just use the expr.
        if hasattr(unit_expr, "is_Unit"):
            # grab the unit object's sympy expression.
            unit_expr = unit_expr.expr
        elif hasattr(unit_expr, "units") and hasattr(unit_expr, "value"):
            # something that looks like a unyt_array, grab the unit and value
            if unit_expr.shape != ():
                raise UnitParseError(
                    "Cannot create a unit from a non-scalar unyt_array, "
                    "received: %s" % (unit_expr,)
                )
            value = unit_expr.value
            if value == 1:
                unit_expr = unit_expr.units.expr
            else:
                unit_expr = unit_expr.value * unit_expr.units.expr
        # Parse a text unit representation using sympy's parser
        elif isinstance(unit_expr, (str, bytes)):
            if isinstance(unit_expr, bytes):
                unit_expr = unit_expr.decode("utf-8")

            # this cache substantially speeds up unit conversions
            if registry and unit_expr in registry._unit_object_cache:
                return registry._unit_object_cache[unit_expr]
            unit_cache_key = unit_expr
            unit_expr = parse_unyt_expr(unit_expr)
        # Make sure we have an Expr at this point.
        if not isinstance(unit_expr, Expr):
            raise UnitParseError(
                "Unit representation must be a string or "
                "sympy Expr. '%s' has type '%s'." % (unit_expr, type(unit_expr))
            )

        if dimensions is None and unit_expr is sympy_one:
            dimensions = dimensionless

        if registry is None:
            # Caller did not set the registry, so use the default.
            registry = default_unit_registry

        # done with argument checking...

        # see if the unit is atomic.
        is_atomic = False
        if isinstance(unit_expr, Symbol):
            is_atomic = True

        #
        # check base_value and dimensions
        #

        if base_value is not None:
            # check that base_value is a float or can be converted to one
            try:
                base_value = float(base_value)
            except ValueError:
                raise UnitParseError(
                    "Could not use base_value as a float. "
                    "base_value is '%s' (type '%s')." % (base_value, type(base_value))
                )

            # check that dimensions is valid
            if dimensions is not None:
                _validate_dimensions(dimensions)
        else:
            # lookup the unit symbols
            unit_data = _get_unit_data_from_expr(unit_expr, registry.lut)
            base_value = unit_data[0]
            dimensions = unit_data[1]
            if len(unit_data) > 2:
                base_offset = unit_data[2]
                latex_repr = unit_data[3]
            else:
                base_offset = 0.0

        # Create obj with superclass construct.
        obj = super(Unit, cls).__new__(cls)

        # Attach attributes to obj.
        obj.expr = unit_expr
        obj.is_atomic = is_atomic
        obj.base_value = base_value
        obj.base_offset = base_offset
        obj.dimensions = dimensions
        obj._latex_repr = latex_repr
        obj.registry = registry
        # lets us avoid isinstance calls
        obj.is_Unit = True

        # if we parsed a string unit expression, cache the result
        # for faster lookup later
        if unit_cache_key is not None:
            registry._unit_object_cache[unit_cache_key] = obj

        # Return `obj` so __init__ can handle it.

        return obj