示例#1
0
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
示例#2
0
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
    )
示例#3
0
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
示例#4
0
    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 []