123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- """
- Module defining unit prefixe class and some constants.
- Constant dict for SI and binary prefixes are defined as PREFIXES and
- BIN_PREFIXES.
- """
- from sympy.core.expr import Expr
- from sympy.core.sympify import sympify
- class Prefix(Expr):
- """
- This class represent prefixes, with their name, symbol and factor.
- Prefixes are used to create derived units from a given unit. They should
- always be encapsulated into units.
- The factor is constructed from a base (default is 10) to some power, and
- it gives the total multiple or fraction. For example the kilometer km
- is constructed from the meter (factor 1) and the kilo (10 to the power 3,
- i.e. 1000). The base can be changed to allow e.g. binary prefixes.
- A prefix multiplied by something will always return the product of this
- other object times the factor, except if the other object:
- - is a prefix and they can be combined into a new prefix;
- - defines multiplication with prefixes (which is the case for the Unit
- class).
- """
- _op_priority = 13.0
- is_commutative = True
- def __new__(cls, name, abbrev, exponent, base=sympify(10)):
- name = sympify(name)
- abbrev = sympify(abbrev)
- exponent = sympify(exponent)
- base = sympify(base)
- obj = Expr.__new__(cls, name, abbrev, exponent, base)
- obj._name = name
- obj._abbrev = abbrev
- obj._scale_factor = base**exponent
- obj._exponent = exponent
- obj._base = base
- return obj
- @property
- def name(self):
- return self._name
- @property
- def abbrev(self):
- return self._abbrev
- @property
- def scale_factor(self):
- return self._scale_factor
- @property
- def base(self):
- return self._base
- def __str__(self):
- # TODO: add proper printers and tests:
- if self.base == 10:
- return "Prefix(%r, %r, %r)" % (
- str(self.name), str(self.abbrev), self._exponent)
- else:
- return "Prefix(%r, %r, %r, %r)" % (
- str(self.name), str(self.abbrev), self._exponent, self.base)
- __repr__ = __str__
- def __mul__(self, other):
- from sympy.physics.units import Quantity
- if not isinstance(other, (Quantity, Prefix)):
- return super().__mul__(other)
- fact = self.scale_factor * other.scale_factor
- if fact == 1:
- return 1
- elif isinstance(other, Prefix):
- # simplify prefix
- for p in PREFIXES:
- if PREFIXES[p].scale_factor == fact:
- return PREFIXES[p]
- return fact
- return self.scale_factor * other
- def __truediv__(self, other):
- if not hasattr(other, "scale_factor"):
- return super().__truediv__(other)
- fact = self.scale_factor / other.scale_factor
- if fact == 1:
- return 1
- elif isinstance(other, Prefix):
- for p in PREFIXES:
- if PREFIXES[p].scale_factor == fact:
- return PREFIXES[p]
- return fact
- return self.scale_factor / other
- def __rtruediv__(self, other):
- if other == 1:
- for p in PREFIXES:
- if PREFIXES[p].scale_factor == 1 / self.scale_factor:
- return PREFIXES[p]
- return other / self.scale_factor
- def prefix_unit(unit, prefixes):
- """
- Return a list of all units formed by unit and the given prefixes.
- You can use the predefined PREFIXES or BIN_PREFIXES, but you can also
- pass as argument a subdict of them if you don't want all prefixed units.
- >>> from sympy.physics.units.prefixes import (PREFIXES,
- ... prefix_unit)
- >>> from sympy.physics.units import m
- >>> pref = {"m": PREFIXES["m"], "c": PREFIXES["c"], "d": PREFIXES["d"]}
- >>> prefix_unit(m, pref) # doctest: +SKIP
- [millimeter, centimeter, decimeter]
- """
- from sympy.physics.units.quantities import Quantity
- from sympy.physics.units import UnitSystem
- prefixed_units = []
- for prefix_abbr, prefix in prefixes.items():
- quantity = Quantity(
- "%s%s" % (prefix.name, unit.name),
- abbrev=("%s%s" % (prefix.abbrev, unit.abbrev))
- )
- UnitSystem._quantity_dimensional_equivalence_map_global[quantity] = unit
- UnitSystem._quantity_scale_factors_global[quantity] = (prefix.scale_factor, unit)
- prefixed_units.append(quantity)
- return prefixed_units
- yotta = Prefix('yotta', 'Y', 24)
- zetta = Prefix('zetta', 'Z', 21)
- exa = Prefix('exa', 'E', 18)
- peta = Prefix('peta', 'P', 15)
- tera = Prefix('tera', 'T', 12)
- giga = Prefix('giga', 'G', 9)
- mega = Prefix('mega', 'M', 6)
- kilo = Prefix('kilo', 'k', 3)
- hecto = Prefix('hecto', 'h', 2)
- deca = Prefix('deca', 'da', 1)
- deci = Prefix('deci', 'd', -1)
- centi = Prefix('centi', 'c', -2)
- milli = Prefix('milli', 'm', -3)
- micro = Prefix('micro', 'mu', -6)
- nano = Prefix('nano', 'n', -9)
- pico = Prefix('pico', 'p', -12)
- femto = Prefix('femto', 'f', -15)
- atto = Prefix('atto', 'a', -18)
- zepto = Prefix('zepto', 'z', -21)
- yocto = Prefix('yocto', 'y', -24)
- # http://physics.nist.gov/cuu/Units/prefixes.html
- PREFIXES = {
- 'Y': yotta,
- 'Z': zetta,
- 'E': exa,
- 'P': peta,
- 'T': tera,
- 'G': giga,
- 'M': mega,
- 'k': kilo,
- 'h': hecto,
- 'da': deca,
- 'd': deci,
- 'c': centi,
- 'm': milli,
- 'mu': micro,
- 'n': nano,
- 'p': pico,
- 'f': femto,
- 'a': atto,
- 'z': zepto,
- 'y': yocto,
- }
- kibi = Prefix('kibi', 'Y', 10, 2)
- mebi = Prefix('mebi', 'Y', 20, 2)
- gibi = Prefix('gibi', 'Y', 30, 2)
- tebi = Prefix('tebi', 'Y', 40, 2)
- pebi = Prefix('pebi', 'Y', 50, 2)
- exbi = Prefix('exbi', 'Y', 60, 2)
- # http://physics.nist.gov/cuu/Units/binary.html
- BIN_PREFIXES = {
- 'Ki': kibi,
- 'Mi': mebi,
- 'Gi': gibi,
- 'Ti': tebi,
- 'Pi': pebi,
- 'Ei': exbi,
- }
|