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
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))
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)
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