Ejemplo n.º 1
0
    def reduce_unit(self, guide_unit=None):
        """
        Combine similar component units and scale, to form an
        equal Quantity in simpler units.

        Returns underlying value type if unit is dimensionless.
        """
        key = (self.unit, guide_unit)
        if key in Quantity._reduce_cache:
            (unit, value_factor) = Quantity._reduce_cache[key]
        else:
            value_factor = 1.0
            canonical_units = {
            }  # dict of dimensionTuple: (Base/ScaledUnit, exponent)
            # Bias result toward guide units
            if guide_unit is not None:
                for u, exponent in guide_unit.iter_base_or_scaled_units():
                    d = u.get_dimension_tuple()
                    if d not in canonical_units:
                        canonical_units[d] = [u, 0]
            for u, exponent in self.unit.iter_base_or_scaled_units():
                d = u.get_dimension_tuple()
                # Take first unit found in a dimension as canonical
                if d not in canonical_units:
                    canonical_units[d] = [u, exponent]
                else:
                    value_factor *= (u.conversion_factor_to(
                        canonical_units[d][0])**exponent)
                    canonical_units[d][1] += exponent
            new_base_units = {}
            for d in canonical_units:
                u, exponent = canonical_units[d]
                if exponent != 0:
                    assert u not in new_base_units
                    new_base_units[u] = exponent
            # Create new unit
            if len(new_base_units) == 0:
                unit = dimensionless
            else:
                unit = Unit(new_base_units)
            # There might be a factor due to unit conversion, even though unit is dimensionless
            # e.g. suppose unit is meter/centimeter
            if unit.is_dimensionless():
                unit_factor = unit.conversion_factor_to(dimensionless)
                if unit_factor != 1.0:
                    value_factor *= unit_factor
                    # print "value_factor = %s" % value_factor
                unit = dimensionless
            Quantity._reduce_cache[key] = (unit, value_factor)
        # Create Quantity, then scale (in case value is a container)
        # That's why we don't just scale the value.
        result = Quantity(self._value, unit)
        if value_factor != 1.0:
            # __mul__ strips off dimensionless, if appropriate
            result = result * value_factor
        if unit.is_dimensionless():
            assert unit is dimensionless  # should have been set earlier in this method
            if is_quantity(result):
                result = result._value
        return result
Ejemplo n.º 2
0
    def reduce_unit(self, guide_unit=None):
        """
        Combine similar component units and scale, to form an
        equal Quantity in simpler units.

        Returns underlying value type if unit is dimensionless.
        """
        key = (self.unit, guide_unit)
        if key in Quantity._reduce_cache:
            (unit, value_factor) = Quantity._reduce_cache[key]
        else:
            value_factor = 1.0
            canonical_units = {} # dict of dimensionTuple: (Base/ScaledUnit, exponent)
            # Bias result toward guide units
            if guide_unit is not None:
                for u, exponent in guide_unit.iter_base_or_scaled_units():
                    d = u.get_dimension_tuple()
                    if d not in canonical_units:
                        canonical_units[d] = [u, 0]
            for u, exponent in self.unit.iter_base_or_scaled_units():
                d = u.get_dimension_tuple()
                # Take first unit found in a dimension as canonical
                if d not in canonical_units:
                    canonical_units[d] = [u, exponent]
                else:
                    value_factor *= (u.conversion_factor_to(canonical_units[d][0])**exponent)
                    canonical_units[d][1] += exponent
            new_base_units = {}
            for d in canonical_units:
                u, exponent = canonical_units[d]
                if exponent != 0:
                    assert u not in new_base_units
                    new_base_units[u] = exponent
            # Create new unit
            if len(new_base_units) == 0:
                unit = dimensionless
            else:
                unit = Unit(new_base_units)
            # There might be a factor due to unit conversion, even though unit is dimensionless
            # e.g. suppose unit is meter/centimeter
            if unit.is_dimensionless():
                unit_factor = unit.conversion_factor_to(dimensionless)
                if unit_factor != 1.0:
                    value_factor *= unit_factor
                    # print "value_factor = %s" % value_factor
                unit = dimensionless
            Quantity._reduce_cache[key] = (unit, value_factor)
        # Create Quantity, then scale (in case value is a container)
        # That's why we don't just scale the value.
        result = Quantity(self._value, unit)
        if value_factor != 1.0:
            # __mul__ strips off dimensionless, if appropriate
            result = result * value_factor
        if unit.is_dimensionless():
            assert unit is dimensionless # should have been set earlier in this method
            if is_quantity(result):
                result = result._value
        return result