physpyx 2.3.0__tar.gz → 3.1.0__tar.gz
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.
- {physpyx-2.3.0 → physpyx-3.1.0}/PKG-INFO +3 -3
- {physpyx-2.3.0 → physpyx-3.1.0}/pyproject.toml +12 -12
- {physpyx-2.3.0 → physpyx-3.1.0}/pyproject.toml.orig +25 -25
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/qty.py +21 -2
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/quantity.py +35 -19
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/registry.py +16 -14
- {physpyx-2.3.0 → physpyx-3.1.0}/README.md +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/__init__.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/astronomy.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/constants.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/context.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/data/all-nuclides.csv +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/helper.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/manager.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/nuclide.py +0 -0
- {physpyx-2.3.0 → physpyx-3.1.0}/src/physpyx/physpyx.py +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: physpyx
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Provides a way to use python code in LaTeX
|
|
5
5
|
Author: Jérôme Dufour
|
|
6
6
|
Author-email: Jérôme Dufour <jerome.dufour@eduvaud.ch>
|
|
7
7
|
License-Expression: GPL-3.0-or-later
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
8
|
Classifier: Operating System :: Unix
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Topic :: Education
|
|
11
11
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
12
12
|
Requires-Dist: numpy>=2.3.4
|
|
13
13
|
Requires-Dist: pint>=0.25.1
|
|
14
14
|
Requires-Dist: scipy>=1.17.0
|
|
15
15
|
Requires-Python: >=3.13
|
|
16
|
-
Project-URL: Repository, https://bitbucket.org/jdufour/physpyx/src/master/
|
|
17
16
|
Project-URL: Changelog, https://bitbucket.org/jdufour/physpyx/src/master/CHANGELOG.md
|
|
18
17
|
Project-URL: Documentation, https://physpyx.readthedocs.io/fr/latest/
|
|
18
|
+
Project-URL: Repository, https://bitbucket.org/jdufour/physpyx/src/master/
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
|
|
21
21
|
# PhysPyX
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "physpyx"
|
|
3
|
-
version = "
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "Provides a way to use python code in LaTeX"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
license = "GPL-3.0-or-later"
|
|
5
8
|
classifiers = [
|
|
6
|
-
"Programming Language :: Python :: 3",
|
|
7
9
|
"Operating System :: Unix",
|
|
10
|
+
"Programming Language :: Python :: 3",
|
|
8
11
|
"Topic :: Education",
|
|
9
12
|
"Topic :: Scientific/Engineering :: Physics",
|
|
10
13
|
]
|
|
11
|
-
license = "GPL-3.0-or-later"
|
|
12
|
-
readme = "README.md"
|
|
13
|
-
requires-python = ">=3.13"
|
|
14
14
|
dependencies = [
|
|
15
15
|
"numpy>=2.3.4",
|
|
16
16
|
"pint>=0.25.1",
|
|
@@ -22,27 +22,27 @@ name = "Jérôme Dufour"
|
|
|
22
22
|
email = "jerome.dufour@eduvaud.ch"
|
|
23
23
|
|
|
24
24
|
[project.urls]
|
|
25
|
-
Repository = "https://bitbucket.org/jdufour/physpyx/src/master/"
|
|
26
25
|
Changelog = "https://bitbucket.org/jdufour/physpyx/src/master/CHANGELOG.md"
|
|
27
26
|
Documentation = "https://physpyx.readthedocs.io/fr/latest/"
|
|
27
|
+
Repository = "https://bitbucket.org/jdufour/physpyx/src/master/"
|
|
28
28
|
|
|
29
29
|
[dependency-groups]
|
|
30
30
|
dev = [
|
|
31
|
-
"mypy>=1.18.1",
|
|
32
31
|
"ipdb>=0.13.13",
|
|
33
|
-
"
|
|
32
|
+
"mypy>=2.3.0",
|
|
34
33
|
"ruff>=0.16.0",
|
|
34
|
+
"scipy-stubs>=1.17.1.5",
|
|
35
35
|
]
|
|
36
36
|
docs = [
|
|
37
|
+
"myst-parser>=4.0.1",
|
|
37
38
|
"sphinx>=7.1.2",
|
|
38
|
-
"sphinx-rtd-theme>=3.0.2",
|
|
39
39
|
"sphinx-argparse>=0.5.2",
|
|
40
|
-
"myst-parser>=4.0.1",
|
|
41
|
-
"sphinx-autodoc2>=0.5.0",
|
|
42
40
|
"sphinx-autobuild>=2025.8.25",
|
|
41
|
+
"sphinx-autodoc2>=0.5.0",
|
|
43
42
|
"sphinx-design>=0.7.0",
|
|
43
|
+
"sphinx-rtd-theme>=3.0.2",
|
|
44
44
|
]
|
|
45
45
|
|
|
46
46
|
[build-system]
|
|
47
|
-
requires = ["uv_build>=0.
|
|
47
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
48
48
|
build-backend = "uv_build"
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "physpyx"
|
|
3
|
-
version = "
|
|
3
|
+
version = "3.1.0"
|
|
4
|
+
description = "Provides a way to use python code in LaTeX"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
license = "GPL-3.0-or-later"
|
|
4
8
|
authors = [
|
|
5
|
-
|
|
9
|
+
{ name = "Jérôme Dufour", email = "jerome.dufour@eduvaud.ch" },
|
|
6
10
|
]
|
|
7
|
-
description = "Provides a way to use python code in LaTeX"
|
|
8
11
|
classifiers = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"Topic :: Scientific/Engineering :: Physics"
|
|
12
|
+
"Operating System :: Unix",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Topic :: Education",
|
|
15
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
13
16
|
]
|
|
14
|
-
license = "GPL-3.0-or-later"
|
|
15
|
-
readme = "README.md"
|
|
16
|
-
requires-python = ">=3.13"
|
|
17
17
|
dependencies = [
|
|
18
18
|
"numpy>=2.3.4",
|
|
19
19
|
"pint>=0.25.1",
|
|
20
20
|
"scipy>=1.17.0",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
|
+
[project.urls]
|
|
24
|
+
Changelog = "https://bitbucket.org/jdufour/physpyx/src/master/CHANGELOG.md"
|
|
25
|
+
Documentation = "https://physpyx.readthedocs.io/fr/latest/"
|
|
26
|
+
Repository = "https://bitbucket.org/jdufour/physpyx/src/master/"
|
|
27
|
+
|
|
23
28
|
[dependency-groups]
|
|
24
29
|
dev = [
|
|
25
|
-
"mypy>=1.18.1",
|
|
26
30
|
"ipdb>=0.13.13",
|
|
27
|
-
"
|
|
31
|
+
"mypy>=2.3.0",
|
|
28
32
|
"ruff>=0.16.0",
|
|
33
|
+
"scipy-stubs>=1.17.1.5",
|
|
29
34
|
]
|
|
30
35
|
docs = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
"myst-parser>=4.0.1",
|
|
37
|
+
"sphinx>=7.1.2",
|
|
38
|
+
"sphinx-argparse>=0.5.2",
|
|
39
|
+
"sphinx-autobuild>=2025.8.25",
|
|
40
|
+
"sphinx-autodoc2>=0.5.0",
|
|
41
|
+
"sphinx-design>=0.7.0",
|
|
42
|
+
"sphinx-rtd-theme>=3.0.2",
|
|
38
43
|
]
|
|
39
44
|
|
|
40
45
|
[build-system]
|
|
41
|
-
requires = ["uv_build>=0.
|
|
46
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
42
47
|
build-backend = "uv_build"
|
|
43
|
-
|
|
44
|
-
[project.urls]
|
|
45
|
-
Repository = "https://bitbucket.org/jdufour/physpyx/src/master/"
|
|
46
|
-
Changelog = "https://bitbucket.org/jdufour/physpyx/src/master/CHANGELOG.md"
|
|
47
|
-
Documentation = "https://physpyx.readthedocs.io/fr/latest/"
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import sys
|
|
3
|
+
from collections.abc import Iterable
|
|
3
4
|
from logging import getLogger
|
|
5
|
+
from typing import cast
|
|
4
6
|
|
|
7
|
+
from numpy import array
|
|
5
8
|
from pint._typing import Scalar
|
|
6
9
|
from pint.facets.context import Context
|
|
7
10
|
|
|
@@ -41,7 +44,7 @@ class Qty(PTManager):
|
|
|
41
44
|
"\\ExplSyntaxOn\n\\prop_gset_from_keyval:Nn \\g_physpyx_pty_prop {\n"
|
|
42
45
|
)
|
|
43
46
|
for variable, qty in sys._getframe(2).f_locals.items():
|
|
44
|
-
if isinstance(qty, SiunitxQuantity):
|
|
47
|
+
if variable != "_" and isinstance(qty, SiunitxQuantity):
|
|
45
48
|
for name, new in qty.export(variable):
|
|
46
49
|
outfile.write(f"\t{{{name}}} = {{{new}}},\n")
|
|
47
50
|
if old := current.pop(name, None):
|
|
@@ -56,7 +59,7 @@ class Qty(PTManager):
|
|
|
56
59
|
|
|
57
60
|
def __call__(
|
|
58
61
|
self,
|
|
59
|
-
value: Scalar |
|
|
62
|
+
value: Scalar | Iterable[Scalar | SiunitxQuantity] | str,
|
|
60
63
|
unit: str | None = None,
|
|
61
64
|
to: str | None = None,
|
|
62
65
|
fmt: str = "g",
|
|
@@ -90,6 +93,22 @@ class Qty(PTManager):
|
|
|
90
93
|
if unit is not None:
|
|
91
94
|
logger.warning("Units are ignored when instanciating a constant")
|
|
92
95
|
value, unit, fmt = self._constants(value, fmt)
|
|
96
|
+
elif isinstance(value, Iterable):
|
|
97
|
+
if all(isinstance(item, SiunitxQuantity) for item in value):
|
|
98
|
+
value = cast(Iterable[SiunitxQuantity], value)
|
|
99
|
+
dim = {v.dimensionality for v in value}
|
|
100
|
+
if len(dim) != 1:
|
|
101
|
+
raise ValueError(
|
|
102
|
+
f"Can't create a vector with different dimensionality ({dim})"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if unit == None:
|
|
106
|
+
unit = ""
|
|
107
|
+
if self._ureg.Unit(unit).dimensionality != dim.pop():
|
|
108
|
+
raise ValueError("Need to set unit with correct dimensionality")
|
|
109
|
+
value = array([v.fmtex(to=unit).m for v in value])
|
|
110
|
+
else:
|
|
111
|
+
value = array(value)
|
|
93
112
|
|
|
94
113
|
q = self._ureg.Quantity(
|
|
95
114
|
value,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from collections.abc import Generator, Iterator
|
|
1
|
+
from collections.abc import Generator, Iterable, Iterator
|
|
2
2
|
from logging import getLogger
|
|
3
3
|
from typing import ClassVar, Self, TypedDict, cast
|
|
4
4
|
|
|
5
|
-
from numpy import cross, linalg
|
|
5
|
+
from numpy import cross, linalg
|
|
6
6
|
from pint._typing import Magnitude, UnitLike
|
|
7
7
|
from pint.registry import Quantity
|
|
8
8
|
|
|
@@ -30,12 +30,13 @@ class SiunitxQuantity(Quantity):
|
|
|
30
30
|
"degree_Celsius": "celsius",
|
|
31
31
|
"delta_degree_Celsius": "celsius",
|
|
32
32
|
"electron_volt": "electronvolt",
|
|
33
|
+
"light_year": "lightyear",
|
|
34
|
+
"meter_Hg": "mHg",
|
|
33
35
|
"metric_ton": "tonne",
|
|
34
36
|
"revolutions_per_minute": "rpm",
|
|
35
37
|
"speed_of_light": "celerity",
|
|
36
38
|
"standard_atmosphere": "atm",
|
|
37
39
|
"unified_atomic_mass_unit": "amu",
|
|
38
|
-
"meter_Hg": "mHg",
|
|
39
40
|
"watt_hour": "watthour",
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -81,8 +82,8 @@ class SiunitxQuantity(Quantity):
|
|
|
81
82
|
return alt
|
|
82
83
|
|
|
83
84
|
def __iter__(self) -> Iterator["SiunitxQuantity"]:
|
|
84
|
-
# NOTE: this is used to set formatting options in tuple expansions
|
|
85
|
-
#
|
|
85
|
+
# NOTE: this is used to set formatting options in tuple expansions rx,
|
|
86
|
+
# ry = qty([3, 2], "kilometer", fmt=".1e")
|
|
86
87
|
for val in super().__iter__():
|
|
87
88
|
val._fmt = self._fmt
|
|
88
89
|
val._base = self._base
|
|
@@ -98,33 +99,35 @@ class SiunitxQuantity(Quantity):
|
|
|
98
99
|
elif self._preferred:
|
|
99
100
|
quantity = self._REGISTRY.to_preferred_units(self)
|
|
100
101
|
if self._compact:
|
|
102
|
+
if isinstance(self.m, Iterable):
|
|
103
|
+
raise ValueError("'compact=True' for vectors has an undefined behavior")
|
|
101
104
|
quantity = cast(SiunitxQuantity, self.to_compact())
|
|
102
105
|
|
|
103
106
|
quantity._fmt = self._fmt
|
|
104
107
|
return (
|
|
105
108
|
quantity._format_array()
|
|
106
|
-
if isinstance(quantity.m,
|
|
109
|
+
if isinstance(quantity.m, Iterable)
|
|
107
110
|
else quantity._format_scalar()
|
|
108
111
|
)
|
|
109
112
|
|
|
113
|
+
def _format_magnitude(self, m: float) -> str:
|
|
114
|
+
out = f"{m:{self._fmt}}"
|
|
115
|
+
if out.startswith("1e"):
|
|
116
|
+
return out[1:]
|
|
117
|
+
elif out.startswith("-1e"):
|
|
118
|
+
return "-" + out[2:]
|
|
119
|
+
return out
|
|
120
|
+
|
|
110
121
|
def _format_array(self) -> str:
|
|
111
122
|
if self.m.ndim != 1:
|
|
112
123
|
raise NotImplementedError
|
|
113
124
|
out = r"\begin{pmatrix}"
|
|
114
125
|
if isinstance(self.m[0], complex):
|
|
115
126
|
out += "\\\\".join(
|
|
116
|
-
|
|
117
|
-
rf"\complexnum{{{v:{self._fmt}}}}" if abs(v) > 1e-16 else r"\num{0}"
|
|
118
|
-
for v in self.m
|
|
119
|
-
]
|
|
127
|
+
rf"\complexnum{{{self._format_magnitude(m)}}}" for m in self.m
|
|
120
128
|
)
|
|
121
129
|
else:
|
|
122
|
-
out += "\\\\".join(
|
|
123
|
-
[
|
|
124
|
-
rf"\num{{{v:{self._fmt}}}}" if abs(v) > 1e-16 else r"\num{0}"
|
|
125
|
-
for v in self.m
|
|
126
|
-
]
|
|
127
|
-
)
|
|
130
|
+
out += "\\\\".join(rf"\num{{{self._format_magnitude(m)}}}" for m in self.m)
|
|
128
131
|
|
|
129
132
|
out += r"\end{pmatrix}"
|
|
130
133
|
if ustr := self._format_unit():
|
|
@@ -132,9 +135,7 @@ class SiunitxQuantity(Quantity):
|
|
|
132
135
|
return out
|
|
133
136
|
|
|
134
137
|
def _format_scalar(self) -> str:
|
|
135
|
-
out =
|
|
136
|
-
if out.startswith("1e"):
|
|
137
|
-
out = out[1:]
|
|
138
|
+
out = self._format_magnitude(self.m)
|
|
138
139
|
if ustr := self._format_unit():
|
|
139
140
|
if isinstance(self.m, complex):
|
|
140
141
|
return rf"\complexqty{{{out}}}{{{ustr}}}"
|
|
@@ -156,6 +157,21 @@ class SiunitxQuantity(Quantity):
|
|
|
156
157
|
# "PlainQuantity[Unknown]"'
|
|
157
158
|
return cast(SiunitxQuantity, super().__add__(other))
|
|
158
159
|
|
|
160
|
+
def __truediv__(self, other: object) -> "SiunitxQuantity":
|
|
161
|
+
# NOTE: to fix typing warning 'Cannot access attribute "???" for class
|
|
162
|
+
# "PlainQuantity[Unknown]"'
|
|
163
|
+
return cast(SiunitxQuantity, super().__truediv__(other))
|
|
164
|
+
|
|
165
|
+
def __mul__(self, other: object) -> "SiunitxQuantity":
|
|
166
|
+
# NOTE: to fix typing warning 'Cannot access attribute "???" for class
|
|
167
|
+
# "PlainQuantity[Unknown]"'
|
|
168
|
+
return cast(SiunitxQuantity, super().__mul__(other))
|
|
169
|
+
|
|
170
|
+
def __rmul__(self, other: object) -> "SiunitxQuantity":
|
|
171
|
+
# NOTE: to fix typing warning 'Cannot access attribute "???" for class
|
|
172
|
+
# "PlainQuantity[Unknown]"'
|
|
173
|
+
return cast(SiunitxQuantity, super().__rmul__(other))
|
|
174
|
+
|
|
159
175
|
def _format_unit(self) -> str:
|
|
160
176
|
num = ""
|
|
161
177
|
den = ""
|
|
@@ -2,6 +2,7 @@ from typing import Any, cast
|
|
|
2
2
|
|
|
3
3
|
from pint.facets.context import Context
|
|
4
4
|
from pint.registry import GenericUnitRegistry, Unit
|
|
5
|
+
from pint.util import UnitsContainer
|
|
5
6
|
|
|
6
7
|
from physpyx.context import SiunitxContext
|
|
7
8
|
from physpyx.quantity import SiunitxQuantity
|
|
@@ -23,31 +24,32 @@ class SiunitxUnitRegistry(GenericUnitRegistry):
|
|
|
23
24
|
self.define("an = year")
|
|
24
25
|
self.define("ans = years")
|
|
25
26
|
self.define("celerity = speed_of_light")
|
|
26
|
-
self.define("
|
|
27
|
-
self.define("
|
|
27
|
+
self.define("swissfranc = [currency]")
|
|
28
|
+
self.define("swisscent = swissfranc * 0.01")
|
|
28
29
|
self._preferred_units = {
|
|
29
30
|
Unit(name).dimensionality: name
|
|
30
31
|
for name in [
|
|
31
|
-
"meter",
|
|
32
|
-
"second",
|
|
33
|
-
"kilogram",
|
|
34
32
|
"ampere",
|
|
33
|
+
"coulomb",
|
|
34
|
+
"farad",
|
|
35
|
+
"henry",
|
|
36
|
+
"joule",
|
|
35
37
|
"kelvin",
|
|
36
|
-
"
|
|
37
|
-
"meter per second",
|
|
38
|
+
"kilogram",
|
|
38
39
|
"meter per second squared",
|
|
40
|
+
"meter per second",
|
|
41
|
+
"meter",
|
|
42
|
+
"mole",
|
|
39
43
|
"newton",
|
|
40
|
-
"joule",
|
|
41
|
-
"watt",
|
|
42
|
-
"pascal",
|
|
43
|
-
"volt",
|
|
44
44
|
"ohm",
|
|
45
|
+
"pascal",
|
|
46
|
+
"second",
|
|
45
47
|
"tesla",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"coulomb",
|
|
48
|
+
"volt",
|
|
49
|
+
"watt",
|
|
49
50
|
]
|
|
50
51
|
}
|
|
52
|
+
self._preferred_units[UnitsContainer({"[currency]": 1})] = "swissfranc"
|
|
51
53
|
|
|
52
54
|
def enable_contexts(self, *names_or_contexts: str | Context, **kwargs: Any) -> None:
|
|
53
55
|
for context in names_or_contexts:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|