Coverage for /usr/lib/python3/dist-packages/sympy/physics/units/quantities.py: 81%
80 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""
2Physical quantities.
3"""
5from sympy.core.expr import AtomicExpr
6from sympy.core.symbol import Symbol
7from sympy.core.sympify import sympify
8from sympy.physics.units.dimensions import _QuantityMapper
9from sympy.physics.units.prefixes import Prefix
12class Quantity(AtomicExpr):
13 """
14 Physical quantity: can be a unit of measure, a constant or a generic quantity.
15 """
17 is_commutative = True
18 is_real = True
19 is_number = False
20 is_nonzero = True
21 is_physical_constant = False
22 _diff_wrt = True
24 def __new__(cls, name, abbrev=None,
25 latex_repr=None, pretty_unicode_repr=None,
26 pretty_ascii_repr=None, mathml_presentation_repr=None,
27 is_prefixed=False,
28 **assumptions):
30 if not isinstance(name, Symbol):
31 name = Symbol(name)
33 if abbrev is None:
34 abbrev = name
35 elif isinstance(abbrev, str):
36 abbrev = Symbol(abbrev)
38 # HACK: These are here purely for type checking. They actually get assigned below.
39 cls._is_prefixed = is_prefixed
41 obj = AtomicExpr.__new__(cls, name, abbrev)
42 obj._name = name
43 obj._abbrev = abbrev
44 obj._latex_repr = latex_repr
45 obj._unicode_repr = pretty_unicode_repr
46 obj._ascii_repr = pretty_ascii_repr
47 obj._mathml_repr = mathml_presentation_repr
48 obj._is_prefixed = is_prefixed
49 return obj
51 def set_global_dimension(self, dimension):
52 _QuantityMapper._quantity_dimension_global[self] = dimension
54 def set_global_relative_scale_factor(self, scale_factor, reference_quantity):
55 """
56 Setting a scale factor that is valid across all unit system.
57 """
58 from sympy.physics.units import UnitSystem
59 scale_factor = sympify(scale_factor)
60 if isinstance(scale_factor, Prefix):
61 self._is_prefixed = True
62 # replace all prefixes by their ratio to canonical units:
63 scale_factor = scale_factor.replace(
64 lambda x: isinstance(x, Prefix),
65 lambda x: x.scale_factor
66 )
67 scale_factor = sympify(scale_factor)
68 UnitSystem._quantity_scale_factors_global[self] = (scale_factor, reference_quantity)
69 UnitSystem._quantity_dimensional_equivalence_map_global[self] = reference_quantity
71 @property
72 def name(self):
73 return self._name
75 @property
76 def dimension(self):
77 from sympy.physics.units import UnitSystem
78 unit_system = UnitSystem.get_default_unit_system()
79 return unit_system.get_quantity_dimension(self)
81 @property
82 def abbrev(self):
83 """
84 Symbol representing the unit name.
86 Prepend the abbreviation with the prefix symbol if it is defines.
87 """
88 return self._abbrev
90 @property
91 def scale_factor(self):
92 """
93 Overall magnitude of the quantity as compared to the canonical units.
94 """
95 from sympy.physics.units import UnitSystem
96 unit_system = UnitSystem.get_default_unit_system()
97 return unit_system.get_quantity_scale_factor(self)
99 def _eval_is_positive(self):
100 return True
102 def _eval_is_constant(self):
103 return True
105 def _eval_Abs(self):
106 return self
108 def _eval_subs(self, old, new):
109 if isinstance(new, Quantity) and self != old:
110 return self
112 def _latex(self, printer):
113 if self._latex_repr:
114 return self._latex_repr
115 else:
116 return r'\text{{{}}}'.format(self.args[1] \
117 if len(self.args) >= 2 else self.args[0])
119 def convert_to(self, other, unit_system="SI"):
120 """
121 Convert the quantity to another quantity of same dimensions.
123 Examples
124 ========
126 >>> from sympy.physics.units import speed_of_light, meter, second
127 >>> speed_of_light
128 speed_of_light
129 >>> speed_of_light.convert_to(meter/second)
130 299792458*meter/second
132 >>> from sympy.physics.units import liter
133 >>> liter.convert_to(meter**3)
134 meter**3/1000
135 """
136 from .util import convert_to
137 return convert_to(self, other, unit_system)
139 @property
140 def free_symbols(self):
141 """Return free symbols from quantity."""
142 return set()
144 @property
145 def is_prefixed(self):
146 """Whether or not the quantity is prefixed. Eg. `kilogram` is prefixed, but `gram` is not."""
147 return self._is_prefixed
149class PhysicalConstant(Quantity):
150 """Represents a physical constant, eg. `speed_of_light` or `avogadro_constant`."""
152 is_physical_constant = True