def to(self, unit_name=""): """ Returns None and alters the instance into one of the elligible alternative units for its dimension, if it exists in the alternative_units dict; """ dims = self.dimensions env_dims = environment.units_by_dimension derived = env_dims["derived"] defined = env_dims["defined"] power, dims_orig = phf._powers_of_derived(dims, env_dims) if not unit_name: print("Available units: ") for key in derived.get(dims_orig, {}): print(key) for key in defined.get(dims_orig, {}): print(key) if unit_name: defined_match = defined.get(dims_orig, {}).get(unit_name, {}) derived_match = derived.get(dims_orig, {}).get(unit_name, {}) unit_match = defined_match or derived_match if not unit_match: warnings.warn(f"No unit defined for '{unit_name}''.") new_factor = unit_match.get("Factor", 1)**power return Physical(self.value, self.dimensions, new_factor, self.precision)
def __float__(self): value = self.value dims = self.dimensions factor = self.factor prefixed = self.prefixed env_dims = environment.units_by_dimension or dict() power, _ = phf._powers_of_derived(dims, env_dims) if factor != 1: float_value = value * factor else: float_value = phf._auto_prefix_value(value, power, prefixed) return float(float_value)
def __float__(self): value = self.value factor = self.factor if factor != 1: return value * factor kg_bool = False dims = self.dimensions env_dims = environment.units_by_dimension or dict() power, _ = phf._powers_of_derived(dims, env_dims) dim_components = phf._get_unit_components_from_dims(dims) if len(dim_components) == 1 and dim_components[0][0] == "kg": kg_bool = True if self.prefixed: prefix = self.prefixed else: prefix = phf._auto_prefix(value, power, kg_bool) float_value = phf._auto_prefix_value(value, power, prefix, kg_bool) return float_value
def __mul__(self, other): if phf.is_nan(other): return other elif isinstance(other, NUMBER): return Physical( self.value * other, self.dimensions, self.factor, self.precision, self.prefixed, ) elif isinstance(other, Physical): new_dims = vec.add(self.dimensions, other.dimensions) new_power, new_dims_orig = phf._powers_of_derived( new_dims, environment.units_by_dimension) new_factor = self.factor * other.factor test_factor = phf._get_units_by_factor(new_factor, new_dims_orig, environment.units_by_factor, new_power) if not test_factor: new_factor = 1 try: new_value = self.value * other.value except: raise ValueError( f"Cannot multiply between {self} and {other}: " + ".value attributes are incompatible.") if new_dims == Dimensions(0, 0, 0, 0, 0, 0, 0): return new_value else: return Physical(new_value, new_dims, new_factor, self.precision) else: try: return Physical(self.value * other, self.dimensions, self.factor, self.precision) except: raise ValueError( f"Cannot multiply between {self} and {other}: " + ".value attributes are incompatible.")
def __truediv__(self, other): if isinstance(other, NUMBER): return Physical( self.value / other, self.dimensions, self.factor, self.precision, self.prefixed, ) elif isinstance(other, Physical): new_dims = vec.subtract(self.dimensions, other.dimensions) new_power, new_dims_orig = phf._powers_of_derived( new_dims, environment.units_by_dimension) new_factor = self.factor / other.factor if not phf._get_units_by_factor(new_factor, new_dims_orig, environment.units_by_factor, new_power): new_factor = 1 try: new_value = self.value / other.value except: raise ValueError( f"Cannot divide between {self} and {other}: " + ".value attributes are incompatible.") if new_dims == Dimensions(0, 0, 0, 0, 0, 0, 0): return new_value else: return Physical(new_value, new_dims, new_factor, self.precision) else: try: return Physical(self.value / other, self.dimensions, self.factor, self.precision) except: raise ValueError( f"Cannot divide between {self} and {other}: " + ".value attributes are incompatible.")
def _repr_template_(self, template: str = "") -> str: """ Returns a string that appropriately represents the Physical instance. The parameter,'template', allows two optional values: 'html' and 'latex'. which will only be utilized if the Physical exists in the Jupyter/iPython environment. """ # Access req'd attributes precision = self.precision dims = self.dimensions factor = self.factor val = self.value prefix = "" prefixed = self.prefixed eps = self._eps # Access external environment env_fact = environment.units_by_factor or dict() env_dims = environment.units_by_dimension or dict() # Do the expensive vector math method (call once, only) power, dims_orig = phf._powers_of_derived(dims, env_dims) # Determine if there is a symbol for these dimensions in the environment # and if the quantity is elligible to be prefixed symbol, prefix_bool = phf._evaluate_dims_and_factor( dims_orig, factor, power, env_fact, env_dims) # Get the appropriate prefix if prefix_bool and prefixed: prefix = prefixed elif prefix_bool and dims_orig == Dimensions(1, 0, 0, 0, 0, 0, 0): prefix = phf._auto_prefix(val, power, kg=True) elif prefix_bool: prefix = phf._auto_prefix(val, power, kg=False) # Format the exponent (may not be used, though) exponent = phf._format_exponent(power, repr_format=template, eps=eps) # Format the units if not symbol and phf._dims_basis_multiple(dims): components = phf._get_unit_components_from_dims(dims) units_symbol = phf._get_unit_string(components, repr_format=template) units = units_symbol units = phf._format_symbol(prefix, units_symbol, repr_format=template) exponent = "" elif not symbol: components = phf._get_unit_components_from_dims(dims) units_symbol = phf._get_unit_string(components, repr_format=template) units = units_symbol exponent = "" else: units = phf._format_symbol(prefix, symbol, repr_format=template) # Determine the appropriate display value value = val * factor if prefix_bool: # If the quantity has a "pre-fixed" prefix, it will override # the value generated in _auto_prefix_value if dims_orig == Dimensions(1, 0, 0, 0, 0, 0, 0): value = phf._auto_prefix_value(val, power, prefixed, kg=True) else: value = phf._auto_prefix_value(val, power, prefixed) pre_super = "" post_super = "" space = " " if template == "latex": space = r"\ " pre_super = "^{" post_super = "}" elif template == "html": space = " " pre_super = "<sup>" post_super = "</sup>" if not exponent: pre_super = "" post_super = "" return f"{value:.{precision}f}{space}{units}{pre_super}{exponent}{post_super}"
### TODO: add Ohms to definitions for testing # add energy modelling units to definitions for testing ### Testing parameters ### env_dims = si.environment.units_by_dimension env_fact = si.environment.units_by_factor units = { "A": 0.05 * kg, "B": 3.2e-3 * m, "C": 1000 * ft, "D": 1e6 * N, "E": 0.2 * kip, "F": 5 * N * 1e3 * kip, "Matt": 0.22 * kip, ## 20200417Matt added for dummy merge test } parameters = [(value, phf._powers_of_derived(value.dimensions, env_dims)) for value in units.values()] ### Tests of the Physical class ### ## Testing "._repr_" methods in order of appearance in ._repr_template_() ## def test__evaluate_dims_and_factor(): func = phf._evaluate_dims_and_factor assert func( si.Dimensions(1, 1, -2, 0, 0, 0, 0), 1 / 0.45359237 / 9.80665, 1, env_fact, env_dims, ) == ("lb", False)