def _get_conversion_factor(old_units, new_units, dtype): """ Get the conversion factor between two units of equivalent dimensions. This is the number you multiply data by to convert from values in `old_units` to values in `new_units`. Parameters ---------- old_units: str or Unit object The current units. new_units : str or Unit object The units we want. dtype: NumPy dtype The dtype of the conversion factor Returns ------- conversion_factor : float `old_units / new_units` offset : float or None Offset between the old unit and new unit. """ if old_units.dimensions != new_units.dimensions: raise UnitConversionError(old_units, old_units.dimensions, new_units, new_units.dimensions) old_basevalue = old_units.base_value old_baseoffset = old_units.base_offset new_basevalue = new_units.base_value new_baseoffset = new_units.base_offset ratio = old_basevalue / new_basevalue if old_baseoffset == 0 and new_baseoffset == 0: return (ratio, None) else: # the dimensions are either temperature or angle (lat, lon) if old_units.dimensions == temperature: # for degree Celsius, back out the SI prefix scaling from # offset scaling for degree Fahrenheit old_prefix, _ = _split_prefix(str(old_units), old_units.registry.lut) if old_prefix != "": old_baseoffset /= old_basevalue new_prefix, _ = _split_prefix(str(new_units), new_units.registry.lut) if new_prefix != "": new_baseoffset /= new_basevalue return ratio, ratio * old_baseoffset - new_baseoffset
def _lookup_unit_symbol(symbol_str, unit_symbol_lut): """ Searches for the unit data tuple corresponding to the given symbol. Parameters ---------- symbol_str : str The unit symbol to look up. unit_symbol_lut : dict Dictionary with symbols as keys and unit data tuples as values. """ if symbol_str in unit_symbol_lut: # lookup successful, return the tuple directly return unit_symbol_lut[symbol_str] # could still be a known symbol with a prefix prefix, symbol_wo_prefix = _split_prefix(symbol_str, unit_symbol_lut) if prefix: # lookup successful, it's a symbol with a prefix unit_data = unit_symbol_lut[symbol_wo_prefix] prefix_value = unit_prefixes[prefix][0] # Need to add some special handling for comoving units # this is fine for now, but it wouldn't work for a general # unit that has an arbitrary LaTeX representation if symbol_wo_prefix != "cm" and symbol_wo_prefix.endswith("cm"): sub_symbol_wo_prefix = symbol_wo_prefix[:-2] sub_symbol_str = symbol_str[:-2] else: sub_symbol_wo_prefix = symbol_wo_prefix sub_symbol_str = symbol_str latex_repr = unit_data[3].replace( "{" + sub_symbol_wo_prefix + "}", "{" + sub_symbol_str + "}" ) # Leave offset and dimensions the same, but adjust scale factor and # LaTeX representation ret = ( unit_data[0] * prefix_value, unit_data[1], unit_data[2], latex_repr, False, ) unit_symbol_lut[symbol_str] = ret return ret # no dice raise UnitParseError( "Could not find unit symbol '%s' in the provided " "symbols." % symbol_str )
def _check_em_conversion(unit, to_unit=None, unit_system=None, registry=None): """Check to see if the units contain E&M units This function supports unyt's ability to convert data to and from E&M electromagnetic units. However, this support is limited and only very simple unit expressions can be readily converted. This function tries to see if the unit is an atomic base unit that is present in the em_conversions dict. If it does not contain E&M units, the function returns an empty tuple. If it does contain an atomic E&M unit in the em_conversions dict, it returns a tuple containing the unit to convert to and scale factor. If it contains a more complicated E&M unit and we are trying to convert between CGS & MKS E&M units, it raises an error. """ em_map = () if unit == to_unit or unit.dimensions not in em_conversion_dims: return em_map if unit.is_atomic: prefix, unit_wo_prefix = _split_prefix(str(unit), unit.registry.lut) else: prefix, unit_wo_prefix = "", str(unit) if (unit_wo_prefix, unit.dimensions) in em_conversions: em_info = em_conversions[unit_wo_prefix, unit.dimensions] em_unit = Unit(prefix + em_info[1], registry=registry) if to_unit is None: cmks_in_unit = current_mks in unit.dimensions.atoms() cmks_in_unit_system = unit_system.units_map[current_mks] cmks_in_unit_system = cmks_in_unit_system is not None if cmks_in_unit and cmks_in_unit_system: em_map = (unit_system[unit.dimensions], unit, 1.0) else: em_map = (None, em_unit, em_info[2]) elif to_unit.dimensions == em_unit.dimensions: em_map = (to_unit, em_unit, em_info[2]) if em_map: return em_map if unit_system is None: from unyt.unit_systems import unit_system_registry unit_system = unit_system_registry["mks"] for unit_atom in unit.expr.atoms(): if unit_atom.is_Number: continue bu = str(unit_atom) budims = Unit(bu, registry=registry).dimensions try: if str(unit_system[budims]) == bu: continue except MissingMKSCurrent: raise MKSCGSConversionError(unit) return em_map
def run(self): lines = [] for name, alt_names in name_alternatives.items(): prefix, base = _split_prefix(name, default_unit_registry.lut) if prefix != "": continue lut_entry = default_unit_registry[name] u = Unit(name) try: dimensions = all_dims[u.dimensions] except KeyError: if u.is_dimensionless: dimensions = "dimensionless" else: dimensions = u.dimensions try: mks_value = (1 * u).in_mks() except UnitsNotReducible: mks_value = "N/A" try: cgs_value = (1 * u).in_cgs() except UnitsNotReducible: cgs_value = "N/A" def generate_table_value(value): if value == "N/A": return value approx_string = "{:.4e}".format(value) real_string = str(value) fv = value.value close_value = float("{:.4e}".format(fv)) if (close_value - fv) / fv < 1e-6 and len(str(fv)) > 8: return approx_string if fv < 1e-4 or fv > 1e4 or len(str(fv)) > 8: return approx_string return real_string latex_repr = "``" + u.latex_repr + "``" if latex_repr == "````": latex_repr = "" with np.printoptions(precision=4, suppress=False, floatmode="maxprec"): lines.append(( name, str(dimensions), generate_table_value(mks_value), generate_table_value(cgs_value), latex_repr, str(lut_entry[4]), ", ".join([a for a in alt_names if a != name]), )) lines.insert( 0, [ "Unit Name", "Dimensions", "MKS value", "CGS Value", "LaTeX Representation", "SI Prefixable?", "Alternate Names", ], ) lines = as_rest_table(lines, full=False).split("\n") rst_file = self.state_machine.document.attributes["source"] self.state_machine.insert_input(lines, rst_file) return []