unxt 0.1.dev463__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of unxt might be problematic. Click here for more details.
- unxt/__init__.py +79 -0
- unxt/_interop/__init__.py +18 -0
- unxt/_interop/optional_deps.py +13 -0
- unxt/_interop/unxt_interop_astropy/__init__.py +5 -0
- unxt/_interop/unxt_interop_astropy/custom_types.py +12 -0
- unxt/_interop/unxt_interop_astropy/dimensions.py +53 -0
- unxt/_interop/unxt_interop_astropy/quantity.py +308 -0
- unxt/_interop/unxt_interop_astropy/units.py +111 -0
- unxt/_interop/unxt_interop_gala/__init__.py +5 -0
- unxt/_interop/unxt_interop_gala/unitsystems.py +108 -0
- unxt/_interop/unxt_interop_mpl/__init__.py +81 -0
- unxt/_src/__init__.py +6 -0
- unxt/_src/dimensions.py +400 -0
- unxt/_src/experimental.py +234 -0
- unxt/_src/quantity/__init__.py +24 -0
- unxt/_src/quantity/angle.py +58 -0
- unxt/_src/quantity/base.py +1160 -0
- unxt/_src/quantity/base_angle.py +89 -0
- unxt/_src/quantity/base_parametric.py +290 -0
- unxt/_src/quantity/flag.py +137 -0
- unxt/_src/quantity/mixins.py +238 -0
- unxt/_src/quantity/quantity.py +123 -0
- unxt/_src/quantity/register_api.py +383 -0
- unxt/_src/quantity/register_conversions.py +95 -0
- unxt/_src/quantity/register_dispatches.py +246 -0
- unxt/_src/quantity/register_primitives.py +5075 -0
- unxt/_src/quantity/static_quantity.py +90 -0
- unxt/_src/quantity/unchecked.py +45 -0
- unxt/_src/quantity/value.py +289 -0
- unxt/_src/units.py +103 -0
- unxt/_src/unitsystems/__init__.py +40 -0
- unxt/_src/unitsystems/base.py +258 -0
- unxt/_src/unitsystems/builtin.py +190 -0
- unxt/_src/unitsystems/builtin_dimensions.py +21 -0
- unxt/_src/unitsystems/compare.py +13 -0
- unxt/_src/unitsystems/core.py +307 -0
- unxt/_src/unitsystems/flags.py +80 -0
- unxt/_src/unitsystems/realizations.py +73 -0
- unxt/_src/unitsystems/utils.py +95 -0
- unxt/_src/utils.py +112 -0
- unxt/_version.py +34 -0
- unxt/_version.pyi +2 -0
- unxt/dims.py +19 -0
- unxt/py.typed +0 -0
- unxt/quantity.py +172 -0
- unxt/setup_package.py +60 -0
- unxt/units.py +19 -0
- unxt/unitsystems.py +67 -0
- unxt-0.1.dev463.dist-info/METADATA +533 -0
- unxt-0.1.dev463.dist-info/RECORD +52 -0
- unxt-0.1.dev463.dist-info/WHEEL +4 -0
- unxt-0.1.dev463.dist-info/licenses/LICENSE +29 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Base classes for angular quantities."""
|
|
2
|
+
|
|
3
|
+
__all__ = ("AbstractAngle",)
|
|
4
|
+
|
|
5
|
+
import equinox as eqx
|
|
6
|
+
from jaxtyping import Array, Shaped
|
|
7
|
+
from plum import add_promotion_rule
|
|
8
|
+
|
|
9
|
+
import unxt_api as uapi
|
|
10
|
+
from .base import AbstractQuantity
|
|
11
|
+
from .quantity import Quantity
|
|
12
|
+
from .unchecked import BareQuantity
|
|
13
|
+
from unxt._src.dimensions import dimension, dimension_of
|
|
14
|
+
from unxt._src.quantity.value import StaticValue
|
|
15
|
+
from unxt.units import AbstractUnit
|
|
16
|
+
|
|
17
|
+
angle_dimension = dimension("angle")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AbstractAngle(AbstractQuantity):
|
|
21
|
+
"""Angular Quantity.
|
|
22
|
+
|
|
23
|
+
See Also
|
|
24
|
+
--------
|
|
25
|
+
`unxt.Angle` : a concrete implementation of this class.
|
|
26
|
+
|
|
27
|
+
Examples
|
|
28
|
+
--------
|
|
29
|
+
For this example, we will use the concrete implementation of
|
|
30
|
+
`unxt.AbstractAngle`, `unxt.Angle`.
|
|
31
|
+
|
|
32
|
+
>>> from unxt import Angle
|
|
33
|
+
|
|
34
|
+
>>> Angle(90, "deg")
|
|
35
|
+
Angle(Array(90, dtype=int32, ...), unit='deg')
|
|
36
|
+
|
|
37
|
+
Angles have to have dimensions of angle.
|
|
38
|
+
|
|
39
|
+
>>> try:
|
|
40
|
+
... Angle(90, "m")
|
|
41
|
+
... except ValueError as e:
|
|
42
|
+
... print(e)
|
|
43
|
+
Angle must have units with angular dimensions.
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
value: eqx.AbstractVar[Shaped[Array | StaticValue, "*shape"]]
|
|
48
|
+
"""The value of the `unxt.AbstractQuantity`."""
|
|
49
|
+
|
|
50
|
+
unit: eqx.AbstractVar[AbstractUnit]
|
|
51
|
+
"""The unit associated with this value."""
|
|
52
|
+
|
|
53
|
+
def __check_init__(self) -> None:
|
|
54
|
+
"""Check the initialization."""
|
|
55
|
+
if dimension_of(self) != angle_dimension:
|
|
56
|
+
msg = f"{type(self).__name__} must have units with angular dimensions."
|
|
57
|
+
raise ValueError(msg)
|
|
58
|
+
|
|
59
|
+
def wrap_to(
|
|
60
|
+
self, /, min: AbstractQuantity, max: AbstractQuantity
|
|
61
|
+
) -> "AbstractAngle":
|
|
62
|
+
"""Wrap the angle to the range [min, max).
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
min, max
|
|
67
|
+
The minimum, maximum value of the range.
|
|
68
|
+
|
|
69
|
+
See Also
|
|
70
|
+
--------
|
|
71
|
+
`unxt.quantity.wrap_to` : functional version of this method.
|
|
72
|
+
|
|
73
|
+
Examples
|
|
74
|
+
--------
|
|
75
|
+
>>> import unxt as u
|
|
76
|
+
>>> angle = u.Angle(370, "deg")
|
|
77
|
+
>>> angle.wrap_to(min=u.Q(0, "deg"), max=u.Q(360, "deg"))
|
|
78
|
+
Angle(Array(10, dtype=int32, ...), unit='deg')
|
|
79
|
+
|
|
80
|
+
"""
|
|
81
|
+
return uapi.wrap_to(self, min, max)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Add a rule that when a AbstractAngle interacts with a Quantity, the
|
|
85
|
+
# angle degrades to a Quantity. This is necessary for many operations, e.g.
|
|
86
|
+
# division of an angle by non-dimensionless quantity where the resulting units
|
|
87
|
+
# are not those of an angle.
|
|
88
|
+
add_promotion_rule(AbstractAngle, Quantity, Quantity)
|
|
89
|
+
add_promotion_rule(AbstractAngle, BareQuantity, BareQuantity)
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# pylint: disable=import-error, no-member, unsubscriptable-object
|
|
2
|
+
# b/c it doesn't understand dataclass fields
|
|
3
|
+
|
|
4
|
+
__all__ = ("AbstractParametricQuantity",)
|
|
5
|
+
|
|
6
|
+
from collections.abc import Callable
|
|
7
|
+
from functools import partial
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import equinox as eqx
|
|
11
|
+
import jax
|
|
12
|
+
import wadler_lindig as wl
|
|
13
|
+
from astropy.units import PhysicalType
|
|
14
|
+
from jaxtyping import Array, Shaped
|
|
15
|
+
from plum import dispatch, parametric, type_unparametrized
|
|
16
|
+
|
|
17
|
+
from dataclassish import field_items, fields
|
|
18
|
+
|
|
19
|
+
from .base import AbstractQuantity
|
|
20
|
+
from .value import StaticValue
|
|
21
|
+
from unxt._src.dimensions import name_of
|
|
22
|
+
from unxt.dims import AbstractDimension, dimension, dimension_of
|
|
23
|
+
from unxt.units import AbstractUnit, unit as parse_unit
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@parametric
|
|
27
|
+
class AbstractParametricQuantity(AbstractQuantity):
|
|
28
|
+
"""Arrays with associated units.
|
|
29
|
+
|
|
30
|
+
This class is parametrized by the dimensions of the units.
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
value: eqx.AbstractVar[Shaped[Array | StaticValue, "*shape"]]
|
|
35
|
+
"""The value of the `AbstractQuantity`."""
|
|
36
|
+
|
|
37
|
+
unit: eqx.AbstractVar[AbstractUnit]
|
|
38
|
+
"""The unit associated with this value."""
|
|
39
|
+
|
|
40
|
+
def __post_init__(self) -> None:
|
|
41
|
+
"""Check whether the arguments are valid."""
|
|
42
|
+
self._type_parameter: AbstractDimension
|
|
43
|
+
|
|
44
|
+
def __check_init__(self) -> None:
|
|
45
|
+
"""Check whether the arguments are valid."""
|
|
46
|
+
expected_dimensions = self._type_parameter
|
|
47
|
+
got_dimensions = dimension_of(self.unit)
|
|
48
|
+
if got_dimensions != expected_dimensions: # pylint: disable=unreachable
|
|
49
|
+
msg = "Physical type mismatch." # TODO: better error message
|
|
50
|
+
raise ValueError(msg)
|
|
51
|
+
|
|
52
|
+
# ---------------------------------------------------------------
|
|
53
|
+
# Plum stuff
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
@dispatch
|
|
57
|
+
def __init_type_parameter__(
|
|
58
|
+
cls, dims: AbstractDimension, /
|
|
59
|
+
) -> tuple[AbstractDimension]:
|
|
60
|
+
"""Check whether the type parameters are valid."""
|
|
61
|
+
return (dims,)
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
@dispatch
|
|
65
|
+
def __init_type_parameter__(cls, dims: str, /) -> tuple[AbstractDimension]:
|
|
66
|
+
"""Check whether the type parameters are valid."""
|
|
67
|
+
dims_: AbstractDimension
|
|
68
|
+
try:
|
|
69
|
+
dims_ = dimension(dims)
|
|
70
|
+
except ValueError:
|
|
71
|
+
dims_ = dimension_of(parse_unit(dims))
|
|
72
|
+
return (dims_,)
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
@dispatch
|
|
76
|
+
def __init_type_parameter__(cls, unit: AbstractUnit, /) -> tuple[AbstractDimension]:
|
|
77
|
+
"""Infer the type parameter from the arguments."""
|
|
78
|
+
dims = dimension_of(unit)
|
|
79
|
+
if dims != "unknown": # pylint: disable=unreachable
|
|
80
|
+
return (dims,)
|
|
81
|
+
return (PhysicalType(unit, unit.to_string(fraction=False)),)
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def __infer_type_parameter__(
|
|
85
|
+
cls, value: Any, unit: Any, **kwargs: Any
|
|
86
|
+
) -> tuple[AbstractDimension]:
|
|
87
|
+
"""Infer the type parameter from the arguments."""
|
|
88
|
+
return (dimension_of(parse_unit(unit)),)
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
@dispatch
|
|
92
|
+
def __le_type_parameter__(
|
|
93
|
+
cls, left: tuple[AbstractDimension], right: tuple[AbstractDimension]
|
|
94
|
+
) -> bool:
|
|
95
|
+
"""Define an order on type parameters.
|
|
96
|
+
|
|
97
|
+
That is, check whether `left <= right` or not.
|
|
98
|
+
"""
|
|
99
|
+
(dim_left,) = left
|
|
100
|
+
(dim_right,) = right
|
|
101
|
+
return dim_left == dim_right
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------
|
|
104
|
+
# misc
|
|
105
|
+
|
|
106
|
+
def __getnewargs_ex__(self) -> tuple[tuple[Any, ...], dict[str, Any]]:
|
|
107
|
+
"""Return args, kwargs for ``__new__``.
|
|
108
|
+
|
|
109
|
+
In protocols 2+, this is used to determine the values (args,
|
|
110
|
+
and kwargs) passed to ``__new__``. We implement ``__getnewargs_ex__``
|
|
111
|
+
instead of ``__getnewargs__`` because the latter does not support
|
|
112
|
+
keyword-only arguments.
|
|
113
|
+
|
|
114
|
+
Examples
|
|
115
|
+
--------
|
|
116
|
+
>>> import copy as pycopy
|
|
117
|
+
>>> import unxt as u
|
|
118
|
+
|
|
119
|
+
>>> x = u.Quantity([1, 2, 3], "m")
|
|
120
|
+
>>> pycopy.copy(x)
|
|
121
|
+
Quantity(Array([1, 2, 3], dtype=int32), unit='m')
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
return (), field_items(self)
|
|
125
|
+
|
|
126
|
+
# TODO: see if pickling can be accomplished without reduce.
|
|
127
|
+
# https://docs.python.org/3.12/library/pickle.html
|
|
128
|
+
def __reduce__(
|
|
129
|
+
self,
|
|
130
|
+
) -> tuple[Callable[..., "AbstractParametricQuantity"], tuple[Any, ...]]:
|
|
131
|
+
r"""Return the reduced value: a constructor and arguments.
|
|
132
|
+
|
|
133
|
+
The ``__reduce__`` protocol has limited support for keyword-only
|
|
134
|
+
argument. The only built-in means to pass kwargs is to the
|
|
135
|
+
``__setstate__`` method or through a callable with signature ``(obj,
|
|
136
|
+
state)``. Neither of these methods allow for the kwargs to be passed to
|
|
137
|
+
the constructor, only after the object is partially initialized. This
|
|
138
|
+
does not work well for JAX, Equinox, or particularly run-time
|
|
139
|
+
typechecking. To get around this, instead of the class type as the
|
|
140
|
+
customary first element of reduced value we will instead return a
|
|
141
|
+
`functools.partial`-wrapping of the class type with the kwargs bundled
|
|
142
|
+
into the partial object. This is allowed by the ``__reduce__`` protocol,
|
|
143
|
+
which says the first returned item must be any "callable object that
|
|
144
|
+
will be called to create the initial version of the object." In
|
|
145
|
+
conjunction with the standard args, the `functools.partial`-wrapped
|
|
146
|
+
class type will properly construct any parametric subclass.
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
functools.partial[type]
|
|
151
|
+
The `plum.type_unparametrized` form of this class object, which is
|
|
152
|
+
the parametric class without the specialization to the specific
|
|
153
|
+
parameter. The specialized subtype cannot be pickled since it is
|
|
154
|
+
dynamically produced. The type is wrapped into a `functools.partial`
|
|
155
|
+
with the keyword-only arguments to the constructor.
|
|
156
|
+
tuple[Any, ...]
|
|
157
|
+
The arguments to this class. Note: the keyword-only arguments are
|
|
158
|
+
bundled with the type.
|
|
159
|
+
|
|
160
|
+
Examples
|
|
161
|
+
--------
|
|
162
|
+
>>> import pickle
|
|
163
|
+
>>> import unxt as u
|
|
164
|
+
|
|
165
|
+
>>> x = u.Quantity([1, 2, 3], "m")
|
|
166
|
+
>>> pickle.dumps(x)
|
|
167
|
+
b'...'
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
args, kwargs = [], {}
|
|
171
|
+
for f in fields(self):
|
|
172
|
+
v = getattr(self, f.name)
|
|
173
|
+
if f.kw_only:
|
|
174
|
+
kwargs[f.name] = v
|
|
175
|
+
else:
|
|
176
|
+
args.append(v)
|
|
177
|
+
|
|
178
|
+
return partial(type_unparametrized(self), **kwargs), tuple(args)
|
|
179
|
+
|
|
180
|
+
def __pdoc__(
|
|
181
|
+
self,
|
|
182
|
+
*,
|
|
183
|
+
include_params: bool = False,
|
|
184
|
+
named_unit: bool = True,
|
|
185
|
+
use_short_name: bool = False,
|
|
186
|
+
**kwargs: Any,
|
|
187
|
+
) -> wl.AbstractDoc:
|
|
188
|
+
"""Return the Wadler-Lindig representation of this class.
|
|
189
|
+
|
|
190
|
+
This is used for the `__repr__` and `__str__` methods or when using the
|
|
191
|
+
`wadler_lindig` library.
|
|
192
|
+
|
|
193
|
+
Parameters
|
|
194
|
+
----------
|
|
195
|
+
include_params
|
|
196
|
+
If `True`, the type parameter is included in the representation. If
|
|
197
|
+
`False`, the type parameter is not included in the representation.
|
|
198
|
+
For example, ``Quantity['length'][i32]`` versus ``Quantity[i32]``.
|
|
199
|
+
named_unit
|
|
200
|
+
If `True`, the unit is included in the representation as a named
|
|
201
|
+
argument. If `False`, the unit is included as a positional argument.
|
|
202
|
+
For example, ``Quantity(<array>, unit='m')`` versus
|
|
203
|
+
``Quantity(<array>, 'm')``.
|
|
204
|
+
use_short_name
|
|
205
|
+
If `True` and the class has a ``short_name`` class variable, use the
|
|
206
|
+
short name instead of the full class name. For example, ``Q(...)``
|
|
207
|
+
instead of ``Quantity(...)``.
|
|
208
|
+
kwargs
|
|
209
|
+
Additional keyword arguments ``wadler_lindig.pdoc`` method for
|
|
210
|
+
formatting the value, stringified unit, and other fields.
|
|
211
|
+
|
|
212
|
+
Examples
|
|
213
|
+
--------
|
|
214
|
+
>>> import unxt as u
|
|
215
|
+
>>> import wadler_lindig as wl
|
|
216
|
+
|
|
217
|
+
>>> q = u.Quantity([1, 2, 3], "m")
|
|
218
|
+
|
|
219
|
+
The default pretty printing:
|
|
220
|
+
|
|
221
|
+
>>> wl.pprint(q)
|
|
222
|
+
Quantity(i32[3], unit='m')
|
|
223
|
+
|
|
224
|
+
The type parameter can be included in the representation:
|
|
225
|
+
|
|
226
|
+
>>> wl.pprint(q, include_params=True)
|
|
227
|
+
Quantity['length'](i32[3], unit='m')
|
|
228
|
+
|
|
229
|
+
The `str` method uses this as well:
|
|
230
|
+
|
|
231
|
+
>>> print(q)
|
|
232
|
+
Quantity['length']([1, 2, 3], unit='m')
|
|
233
|
+
|
|
234
|
+
Arrays can be printed in full:
|
|
235
|
+
|
|
236
|
+
>>> wl.pprint(q, short_arrays=False)
|
|
237
|
+
Quantity(Array([1, 2, 3], dtype=int32), unit='m')
|
|
238
|
+
|
|
239
|
+
The `repr` method uses this setting:
|
|
240
|
+
|
|
241
|
+
>>> print(repr(q))
|
|
242
|
+
Quantity(Array([1, 2, 3], dtype=int32), unit='m')
|
|
243
|
+
|
|
244
|
+
The units can be turned from a named argument to a positional argument
|
|
245
|
+
by setting `named_unit=False`:
|
|
246
|
+
|
|
247
|
+
>>> wl.pprint(q, named_unit=False)
|
|
248
|
+
Quantity(i32[3], 'm')
|
|
249
|
+
|
|
250
|
+
The class can be printed with its short name:
|
|
251
|
+
|
|
252
|
+
>>> wl.pprint(q, use_short_name=True)
|
|
253
|
+
Q(i32[3], unit='m')
|
|
254
|
+
|
|
255
|
+
Short name with type parameter:
|
|
256
|
+
|
|
257
|
+
>>> wl.pprint(q, use_short_name=True, include_params=True)
|
|
258
|
+
Q['length'](i32[3], unit='m')
|
|
259
|
+
|
|
260
|
+
"""
|
|
261
|
+
pdoc = super().__pdoc__(
|
|
262
|
+
include_params=include_params,
|
|
263
|
+
named_unit=named_unit,
|
|
264
|
+
use_short_name=use_short_name,
|
|
265
|
+
**kwargs,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Type Parameter
|
|
269
|
+
if not include_params:
|
|
270
|
+
param = wl.TextDoc("")
|
|
271
|
+
else:
|
|
272
|
+
param = wl.TextDoc(f"[{name_of(self._type_parameter)!r}]")
|
|
273
|
+
|
|
274
|
+
return wl.ConcatDoc(pdoc.children[0], param, *pdoc.children[1:])
|
|
275
|
+
|
|
276
|
+
def __repr__(self) -> str:
|
|
277
|
+
return wl.pformat(
|
|
278
|
+
self, include_params=False, named_unit=True, short_arrays=False, indent=4
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
def __str__(self) -> str:
|
|
282
|
+
return wl.pformat(
|
|
283
|
+
self,
|
|
284
|
+
include_params=True,
|
|
285
|
+
named_unit=True,
|
|
286
|
+
short_arrays="compact"
|
|
287
|
+
if not isinstance(self.value, jax.core.Tracer)
|
|
288
|
+
else True,
|
|
289
|
+
indent=4,
|
|
290
|
+
)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Flags for quantity operations."""
|
|
2
|
+
|
|
3
|
+
__all__ = ("AllowValue",)
|
|
4
|
+
|
|
5
|
+
from typing import Any, NoReturn
|
|
6
|
+
|
|
7
|
+
from plum import dispatch
|
|
8
|
+
|
|
9
|
+
import unxt_api as uapi
|
|
10
|
+
from .base import AbstractQuantity
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AllowValue:
|
|
14
|
+
"""A flag to allow a value to be passed through `unxt.ustrip`.
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
--------
|
|
18
|
+
>>> import jax.numpy as jnp
|
|
19
|
+
>>> import unxt as u
|
|
20
|
+
>>> from unxt.quantity import AllowValue
|
|
21
|
+
|
|
22
|
+
>>> x = jnp.array(1)
|
|
23
|
+
>>> y = u.ustrip(AllowValue, "km", x)
|
|
24
|
+
>>> y is x
|
|
25
|
+
True
|
|
26
|
+
|
|
27
|
+
>>> u.ustrip(AllowValue, "km", u.Q(1000, "m"))
|
|
28
|
+
Array(1., dtype=float32, ...)
|
|
29
|
+
|
|
30
|
+
This is a flag, so it cannot be instantiated.
|
|
31
|
+
|
|
32
|
+
>>> try:
|
|
33
|
+
... AllowValue()
|
|
34
|
+
... except TypeError as e:
|
|
35
|
+
... print(e)
|
|
36
|
+
Cannot instantiate AllowValue
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __new__(cls) -> NoReturn:
|
|
41
|
+
msg = "Cannot instantiate AllowValue"
|
|
42
|
+
raise TypeError(msg)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dispatch
|
|
46
|
+
def ustrip(flag: type[AllowValue], unit: Any, x: Any, /) -> Any:
|
|
47
|
+
"""Strip the units from a value. This is a no-op.
|
|
48
|
+
|
|
49
|
+
Examples
|
|
50
|
+
--------
|
|
51
|
+
>>> import jax.numpy as jnp
|
|
52
|
+
>>> import unxt as u
|
|
53
|
+
>>> from unxt.quantity import AllowValue
|
|
54
|
+
|
|
55
|
+
>>> x = jnp.array(1)
|
|
56
|
+
>>> y = u.ustrip(AllowValue, "km", x)
|
|
57
|
+
>>> y is x
|
|
58
|
+
True
|
|
59
|
+
|
|
60
|
+
>>> x = 1_000
|
|
61
|
+
>>> y = u.ustrip(AllowValue, "km", x)
|
|
62
|
+
>>> y is x
|
|
63
|
+
True
|
|
64
|
+
|
|
65
|
+
>>> x = "hello"
|
|
66
|
+
>>> y = u.ustrip(AllowValue, "km", x)
|
|
67
|
+
>>> y is x
|
|
68
|
+
True
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
return x
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dispatch
|
|
75
|
+
def ustrip(flag: type[AllowValue], x: Any, /) -> Any:
|
|
76
|
+
"""Strip the units from a value. This is a no-op.
|
|
77
|
+
|
|
78
|
+
Examples
|
|
79
|
+
--------
|
|
80
|
+
>>> import jax.numpy as jnp
|
|
81
|
+
>>> import unxt as u
|
|
82
|
+
>>> from unxt.quantity import AllowValue
|
|
83
|
+
|
|
84
|
+
>>> x = jnp.array(1)
|
|
85
|
+
>>> y = u.ustrip(AllowValue, x)
|
|
86
|
+
>>> y is x
|
|
87
|
+
True
|
|
88
|
+
|
|
89
|
+
>>> x = 1_000
|
|
90
|
+
>>> y = u.ustrip(AllowValue, x)
|
|
91
|
+
>>> y is x
|
|
92
|
+
True
|
|
93
|
+
|
|
94
|
+
>>> x = "hello"
|
|
95
|
+
>>> y = u.ustrip(AllowValue, x)
|
|
96
|
+
>>> y is x
|
|
97
|
+
True
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
return x
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dispatch # TODO: type annotate by value
|
|
104
|
+
def ustrip(flag: type[AllowValue], unit: Any, x: AbstractQuantity, /) -> Any:
|
|
105
|
+
"""Strip the units from a quantity.
|
|
106
|
+
|
|
107
|
+
Examples
|
|
108
|
+
--------
|
|
109
|
+
>>> import unxt as u
|
|
110
|
+
>>> from unxt.quantity import AllowValue
|
|
111
|
+
>>> q = u.Q(1000, "m")
|
|
112
|
+
>>> u.ustrip(AllowValue, "km", q)
|
|
113
|
+
Array(1., dtype=float32, ...)
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
return uapi.ustrip(unit, x)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dispatch
|
|
120
|
+
def ustrip(flag: type[AllowValue], x: AbstractQuantity, /) -> Any:
|
|
121
|
+
"""Strip the units from a quantity.
|
|
122
|
+
|
|
123
|
+
Examples
|
|
124
|
+
--------
|
|
125
|
+
>>> import jax.numpy as jnp
|
|
126
|
+
>>> import unxt as u
|
|
127
|
+
>>> from unxt.quantity import AllowValue
|
|
128
|
+
|
|
129
|
+
>>> x = u.Q(1, "kpc")
|
|
130
|
+
>>> y = u.ustrip(AllowValue, x)
|
|
131
|
+
>>> not isinstance(y, u.Quantity)
|
|
132
|
+
True
|
|
133
|
+
>>> y == 1
|
|
134
|
+
Array(True, dtype=bool, ...)
|
|
135
|
+
|
|
136
|
+
"""
|
|
137
|
+
return uapi.ustrip(x)
|