Skip to content

Commit b360d89

Browse files
authored
Merge pull request #2 from namurphy/copy-from-plasmapy
Copy over code from PlasmaPy
2 parents c2c433d + 2000bbc commit b360d89

File tree

11 files changed

+2513
-61
lines changed

11 files changed

+2513
-61
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ jobs:
2929
matrix:
3030
include:
3131

32-
- name: Run plasmapy-calculator
33-
os: ubuntu-latest
34-
python: '3.11'
35-
nox_session: smoke_test
36-
3732
- name: Check consistency of pinned & project requirements
3833
os: ubuntu-latest
3934
python: '3.13'

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.11
1+
3.10

noxfile.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,12 @@ def validate_requirements(session: nox.Session) -> None:
114114
session.run("uv", "lock", "--check", "--offline", "--no-progress")
115115

116116

117-
@nox.session(python="3.11")
117+
@nox.session(python="3.10")
118118
def smoke_test(session: nox.Session) -> None:
119119
session.install(".")
120120
session.run("plasmapy-calculator")
121+
122+
123+
@nox.session
124+
def build(session: nox.Session) -> None:
125+
session.run("uv", "build", "--no-progress")

pyproject.toml

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,110 @@ authors = [
1313
{ name = "Erik Everson" },
1414
{ name = "Nick Murphy", email = "[email protected]" },
1515
]
16-
requires-python = ">=3.11.11,<3.12"
16+
requires-python = ">=3.10,<3.11"
1717
classifiers = [
1818
"Programming Language :: Python :: 3 :: Only",
19-
"Programming Language :: Python :: 3.11",
19+
"Programming Language :: Python :: 3.10",
20+
]
21+
# There were breaking changes in a voila | voila's dependencies since
22+
# the plasma calculator notebook was originally contributed to PlasmaPy,
23+
# which makes it prudent to tentatively pin dependencies to versions
24+
# that are known to work.
25+
dependencies = [
26+
"anyio==3.6.1",
27+
"argon2-cffi==21.3",
28+
"argon2-cffi-bindings==21.2",
29+
"astropy==5.1",
30+
"asttokens==2.0.5",
31+
"attrs==21.4",
32+
"backcall==0.2",
33+
"beautifulsoup4==4.11.1",
34+
"bleach==5.0.1",
35+
"cached-property==1.5.2",
36+
"cffi==1.15.1",
37+
"cycler==0.11",
38+
"debugpy==1.6",
39+
"decorator==5.1.1",
40+
"defusedxml==0.7.1",
41+
"entrypoints==0.4",
42+
"executing==0.8.3",
43+
"fastjsonschema==2.15.3",
44+
"fonttools==4.33.3",
45+
"idna==3.3",
46+
"ipykernel==6.15",
47+
"ipython==8.4",
48+
"ipython-genutils==0.2",
49+
"ipywidgets==7.6.5",
50+
"jedi==0.18.1",
51+
"jinja2==2.11.3",
52+
"jsonschema==4.6.1",
53+
"jupyter-client==6.1.12",
54+
"jupyter-core==4.10",
55+
"jupyter-server==1.18.1",
56+
"jupyterlab-pygments==0.2.2",
57+
"jupyterlab-widgets==1.1.1",
58+
"kiwisolver==1.4.3",
59+
"lxml==4.9.1",
60+
"markupsafe==2.0.1",
61+
"matplotlib==3.5.2",
62+
"matplotlib-inline==0.1.3",
63+
"mistune==0.8.4",
64+
"nbclient==0.5.13",
65+
"nbconvert==6.4.5",
66+
"nbformat==5.4",
67+
"nest-asyncio==1.5.5",
68+
"notebook==6.4.12",
69+
"numpy==1.23",
70+
"packaging==21.3",
71+
"pandas==1.4.3",
72+
"pandocfilters==1.5",
73+
"parso==0.8.3",
74+
"pexpect==4.8",
75+
"pickleshare==0.7.5",
76+
"pillow==9.2",
77+
"plasmapy==0.7",
78+
"prometheus-client==0.14.1",
79+
"prompt-toolkit==3.0.30",
80+
"psutil==5.9.1",
81+
"ptyprocess==0.7",
82+
"pure-eval==0.2.2",
83+
"pycparser==2.21",
84+
"pyerfa==2.0.0.1",
85+
"pygments==2.12",
86+
"pyparsing==3.0.9",
87+
"pyrsistent==0.18.1",
88+
"python-dateutil==2.8.2",
89+
"pytz==2022.1",
90+
"pyyaml==6",
91+
"pyzmq==23.2",
92+
"scipy==1.8.1",
93+
"send2trash==1.8",
94+
"setuptools==63.1",
95+
"six==1.16",
96+
"sniffio==1.2",
97+
"soupsieve==2.3.2.post1",
98+
"stack-data==0.3",
99+
"terminado==0.15",
100+
"testpath==0.6",
101+
"tornado==6.2",
102+
"tqdm==4.64",
103+
"traitlets==5.3",
104+
"voila==0.2.15",
105+
"wcwidth==0.2.5",
106+
"webencodings==0.5.1",
107+
"websocket-client==1.3.3",
108+
"widgetsnbextension==3.5.2",
109+
"xarray==2022.3",
20110
]
21-
dependencies = [ ]
22111

23112
scripts.plasmapy-calculator = "plasmapy_calculator:main"
24113

25114
[dependency-groups]
26115
dev = [
27-
"nox>=2025.5.1",
28-
"uv>=0.8.4",
116+
"nox",
117+
"uv",
29118
]
119+
120+
[tool.uv.build-backend]
121+
source-include = [ "src/plasmapy_calculator/favicon.ico" ]
122+
data = { data = "src/plasmapy_calculator/favicon.ico" }
Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,58 @@
1+
"""
2+
Script and utilities to launch the plasma calculator.
3+
"""
4+
5+
__all__ = ["main"]
6+
7+
import argparse
8+
import pathlib
9+
import subprocess
10+
11+
_description = """
12+
Plasma calculator is a tool that opens a page in a web browser for
13+
interactive calculation of plasma parameters.
14+
15+
This tool is currently in the prototype stage and is expected to change in
16+
the future. Please raise an issue at the following link to provide suggestions
17+
and feedback: https://github.com/PlasmaPy/PlasmaPy/issues/new
18+
"""
19+
20+
121
def main() -> None:
2-
print("Hello from plasmapy-calculator!")
22+
"""
23+
Stub function for command line tool that launches the plasma calculator notebook.
24+
"""
25+
parser = argparse.ArgumentParser(description=_description)
26+
parser.add_argument(
27+
"--port", type=int, default=8866, help="Port to run the notebook"
28+
)
29+
parser.add_argument(
30+
"--dark", action="store_true", help="Turn on dark mode, reduces eye strain"
31+
)
32+
parser.add_argument(
33+
"--no-browser", action="store_true", help="Do not open the browser"
34+
)
35+
36+
module_path = pathlib.Path(__file__).parent.absolute()
37+
notebook_path = module_path / "plasma_calculator.ipynb"
38+
favicon_path = module_path / "favicon.ico"
39+
40+
args = parser.parse_args()
41+
theme = "dark" if args.dark else "light"
42+
no_browser = "--no-browser" if args.no_browser else ""
43+
44+
command = [
45+
"voila",
46+
notebook_path,
47+
f"--port={args.port}",
48+
f"--theme={theme}",
49+
f"--VoilaConfiguration.file_whitelist={favicon_path}",
50+
]
51+
if no_browser:
52+
command.append(no_browser)
53+
54+
try:
55+
subprocess.call(command) # noqa: S603
56+
except KeyboardInterrupt:
57+
# We'll need to switch from print() to using logging library
58+
print("Stopping calculator! Bye") # noqa: T201
87.9 KB
Binary file not shown.
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
"""
2+
Collection of private functions to load properties and construct widgets.
3+
"""
4+
5+
__all__: list[str] = []
6+
7+
import json
8+
import warnings
9+
from pathlib import Path
10+
11+
import astropy.units as u
12+
from ipywidgets import widgets
13+
14+
from plasmapy_calculator.widget_helpers import (
15+
_calculate_button,
16+
_CheckBox,
17+
_clear_button,
18+
_create_label,
19+
_create_widget,
20+
_FloatBox,
21+
_FunctionInfo,
22+
_IonBox,
23+
_ParticleBox,
24+
_process_queue,
25+
)
26+
27+
warnings.filterwarnings(
28+
action="ignore",
29+
message="Passing unrecognized arguments",
30+
category=DeprecationWarning,
31+
) # see issue 2370 for a deprecation warning from traitlets
32+
33+
LIGHT_BLUE = "#00BFD8"
34+
"""
35+
LIGHT_BLUE: Constant for light blue color 00BFD8
36+
"""
37+
LIGHT_GRAY = "#A9A9A9"
38+
"""
39+
LIGHT_GRAY: Constant for light gray color A9A9A9
40+
"""
41+
42+
grid_data = [
43+
[
44+
_create_label("Parameter", color=LIGHT_BLUE),
45+
_create_label("Value", color=LIGHT_BLUE),
46+
_create_label("Unit", color=LIGHT_BLUE),
47+
],
48+
[
49+
_create_label("B - Magnetic Field Magnitude:"),
50+
*_create_widget(
51+
_FloatBox,
52+
property_name="B",
53+
unit=u.T,
54+
opts=[u.T, u.G, u.uG],
55+
),
56+
],
57+
[
58+
_create_label("Particle:"),
59+
_create_widget(
60+
_ParticleBox,
61+
property_name="particle",
62+
property_alias="particle_type",
63+
placeholder="Enter particle e.g. neutron,He",
64+
),
65+
],
66+
[
67+
_create_label("Ion:"),
68+
_create_widget(
69+
_IonBox,
70+
property_name="ion",
71+
property_alias="ion_type",
72+
placeholder="Enter ion e.g. He 2+",
73+
),
74+
],
75+
[
76+
_create_label("Convert to Hertz:"),
77+
_create_widget(_CheckBox, property_name="to_hz"),
78+
],
79+
[
80+
_create_label("_" * 20, color=LIGHT_BLUE),
81+
_create_label("Density Number"),
82+
_create_label("_" * 20, color=LIGHT_BLUE),
83+
],
84+
[
85+
_create_label("n - Standard Density Number:"),
86+
*_create_widget(
87+
_FloatBox,
88+
property_name="n",
89+
unit=u.m**-3,
90+
opts=[u.m**-3, u.cm**-3, u.mm**-3],
91+
),
92+
],
93+
[
94+
_create_label("n<sub>e</sub> - Electron Density Number:"),
95+
*_create_widget(
96+
_FloatBox,
97+
property_name="n_e",
98+
unit=u.m**-3,
99+
opts=[u.m**-3, u.cm**-3, u.mm**-3],
100+
),
101+
],
102+
[
103+
_create_label("n<sub>i</sub> - Ion Number Density:"),
104+
*_create_widget(
105+
_FloatBox,
106+
property_name="n_i",
107+
unit=u.m**-3,
108+
opts=[u.m**-3, u.cm**-3, u.mm**-3],
109+
),
110+
],
111+
[
112+
_create_label("_" * 20, color=LIGHT_BLUE),
113+
_create_label("Temperature"),
114+
_create_label("_" * 20, color=LIGHT_BLUE),
115+
],
116+
[
117+
_create_label("T - Standard Temperature:"),
118+
_create_widget(_FloatBox, property_name="T", min=0, unit=u.K),
119+
_create_label("K", color=LIGHT_GRAY),
120+
],
121+
[
122+
_create_label("T<sub>e</sub> - Electron Temperature:"),
123+
_create_widget(_FloatBox, property_name="T_e", min=0, unit=u.K),
124+
_create_label("K", color=LIGHT_GRAY),
125+
],
126+
[
127+
_create_label("T<sub>i</sub> - Ion Temperature:"),
128+
_create_widget(_FloatBox, property_name="T_i", min=0, unit=u.K),
129+
_create_label("K", color=LIGHT_GRAY),
130+
],
131+
]
132+
"""
133+
grid_data: Contains widgets layout for input parameters
134+
"""
135+
136+
137+
def _create_interactive_layout():
138+
"""
139+
Interactive grid layout for input parameters populated in grid_data.
140+
"""
141+
grid = widgets.GridspecLayout(18, 3)
142+
grid.layout.margin = "10px"
143+
144+
for i, row in enumerate(grid_data):
145+
for j, cell in enumerate(row):
146+
grid[i, j] = cell
147+
148+
grid[-1, 0] = _calculate_button
149+
grid[-1, 1] = _clear_button
150+
return grid
151+
152+
153+
def _create_output_layout():
154+
"""
155+
Tab layout for output parameters, populated from
156+
``properties_metadata.json``.
157+
"""
158+
app = widgets.Tab()
159+
children = []
160+
161+
properties_metadata = Path("properties_metadata.json")
162+
163+
with properties_metadata.open() as f:
164+
data = json.load(f)
165+
166+
for i, title in enumerate(data):
167+
grid_layout = widgets.GridspecLayout(10, 2, width="100%")
168+
for j, prop in enumerate(data[title]):
169+
fn = _FunctionInfo(prop["module_name"], prop["function_name"])
170+
if "spec_combo" in prop:
171+
for spec_combo in prop["spec_combo"]:
172+
fn.add_combo(spec_combo)
173+
grid_layout[j, 0] = _create_label(prop["function_name"] + ":")
174+
grid_layout[j, 1] = fn.get_output_widget()
175+
_process_queue.append(fn)
176+
children.append(grid_layout)
177+
app.set_title(i, title)
178+
app.children = children
179+
180+
return app

0 commit comments

Comments
 (0)