shape-plotters 0.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.
Files changed (44) hide show
  1. shape_plotters-0.1.0/.github/workflows/wheels.yml +77 -0
  2. shape_plotters-0.1.0/.gitignore +10 -0
  3. shape_plotters-0.1.0/CHANGELOG.md +48 -0
  4. shape_plotters-0.1.0/LICENSE +21 -0
  5. shape_plotters-0.1.0/PKG-INFO +120 -0
  6. shape_plotters-0.1.0/README.md +100 -0
  7. shape_plotters-0.1.0/conftest.py +5 -0
  8. shape_plotters-0.1.0/pyproject.toml +41 -0
  9. shape_plotters-0.1.0/setup.cfg +4 -0
  10. shape_plotters-0.1.0/shape_plotters/__init__.py +0 -0
  11. shape_plotters-0.1.0/shape_plotters/__main__.py +3 -0
  12. shape_plotters-0.1.0/shape_plotters/cli.py +19 -0
  13. shape_plotters-0.1.0/shape_plotters/core/__init__.py +0 -0
  14. shape_plotters-0.1.0/shape_plotters/core/energy.py +91 -0
  15. shape_plotters-0.1.0/shape_plotters/core/engine.py +451 -0
  16. shape_plotters-0.1.0/shape_plotters/core/fragments.py +63 -0
  17. shape_plotters-0.1.0/shape_plotters/core/neck.py +41 -0
  18. shape_plotters-0.1.0/shape_plotters/core/nodes.py +23 -0
  19. shape_plotters-0.1.0/shape_plotters/core/quadrature.py +41 -0
  20. shape_plotters-0.1.0/shape_plotters/core/result.py +92 -0
  21. shape_plotters-0.1.0/shape_plotters/core/widgets.py +68 -0
  22. shape_plotters-0.1.0/shape_plotters/renders/__init__.py +0 -0
  23. shape_plotters-0.1.0/shape_plotters/renders/beta.py +166 -0
  24. shape_plotters-0.1.0/shape_plotters/renders/fos.py +107 -0
  25. shape_plotters-0.1.0/shape_plotters.egg-info/PKG-INFO +120 -0
  26. shape_plotters-0.1.0/shape_plotters.egg-info/SOURCES.txt +42 -0
  27. shape_plotters-0.1.0/shape_plotters.egg-info/dependency_links.txt +1 -0
  28. shape_plotters-0.1.0/shape_plotters.egg-info/entry_points.txt +2 -0
  29. shape_plotters-0.1.0/shape_plotters.egg-info/requires.txt +8 -0
  30. shape_plotters-0.1.0/shape_plotters.egg-info/scm_file_list.json +39 -0
  31. shape_plotters-0.1.0/shape_plotters.egg-info/top_level.txt +1 -0
  32. shape_plotters-0.1.0/tests/__init__.py +0 -0
  33. shape_plotters-0.1.0/tests/test_beta_render.py +214 -0
  34. shape_plotters-0.1.0/tests/test_cli.py +41 -0
  35. shape_plotters-0.1.0/tests/test_energy.py +104 -0
  36. shape_plotters-0.1.0/tests/test_energy_local.py +61 -0
  37. shape_plotters-0.1.0/tests/test_engine.py +338 -0
  38. shape_plotters-0.1.0/tests/test_fos_render.py +114 -0
  39. shape_plotters-0.1.0/tests/test_fragments.py +44 -0
  40. shape_plotters-0.1.0/tests/test_neck.py +51 -0
  41. shape_plotters-0.1.0/tests/test_nodes.py +32 -0
  42. shape_plotters-0.1.0/tests/test_perf.py +64 -0
  43. shape_plotters-0.1.0/tests/test_quadrature.py +42 -0
  44. shape_plotters-0.1.0/tests/test_widgets.py +50 -0
@@ -0,0 +1,77 @@
1
+ name: wheels
2
+ on:
3
+ push:
4
+ tags: ['[0-9]+.[0-9]+.[0-9]+']
5
+ permissions:
6
+ contents: read
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-24.04
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ with:
13
+ fetch-depth: 0 # tags for setuptools_scm
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: '3.12'
17
+ - name: Build sdist and wheel
18
+ env:
19
+ SETUPTOOLS_SCM_PRETEND_VERSION_FOR_SHAPE_PLOTTERS: ${{ github.ref_name }}
20
+ run: |
21
+ python -m pip install --upgrade build
22
+ python -m build --outdir dist
23
+ - name: Verify wheel in clean venv
24
+ # Everything runs from a copy of the tests outside the checkout, so
25
+ # the tests import the installed wheel and not the source tree (and
26
+ # pip cannot mistake the checkout's egg-info for an installed copy).
27
+ # The timing budgets are skipped: they are calibrated for a developer
28
+ # machine, not a shared runner.
29
+ env:
30
+ MPLBACKEND: Agg
31
+ run: |
32
+ python -m venv /tmp/verify-wheel
33
+ mkdir /tmp/verify-tests
34
+ cp -r tests conftest.py /tmp/verify-tests/
35
+ cd /tmp/verify-tests
36
+ /tmp/verify-wheel/bin/pip install "$GITHUB_WORKSPACE"/dist/*.whl pytest
37
+ /tmp/verify-wheel/bin/python -m pytest tests -q --ignore=tests/test_perf.py
38
+ /tmp/verify-wheel/bin/shape-plotters --help
39
+ - name: Verify sdist installs from the tarball
40
+ run: |
41
+ python -m venv /tmp/verify-sdist
42
+ cd /tmp
43
+ /tmp/verify-sdist/bin/pip install "$GITHUB_WORKSPACE"/dist/*.tar.gz
44
+ /tmp/verify-sdist/bin/shape-plotters --help
45
+ - uses: actions/upload-artifact@v4
46
+ with:
47
+ name: dist
48
+ path: dist/*
49
+ release:
50
+ needs: build
51
+ runs-on: ubuntu-24.04
52
+ permissions:
53
+ contents: write # create/upload the Release
54
+ steps:
55
+ - uses: actions/download-artifact@v4
56
+ with:
57
+ name: dist
58
+ path: dist
59
+ - uses: softprops/action-gh-release@v2
60
+ with:
61
+ files: dist/*
62
+ pypi:
63
+ needs: build
64
+ runs-on: ubuntu-24.04
65
+ environment:
66
+ name: pypi
67
+ url: https://pypi.org/p/shape-plotters
68
+ permissions:
69
+ id-token: write # PyPI Trusted Publishing (OIDC)
70
+ steps:
71
+ - uses: actions/download-artifact@v4
72
+ with:
73
+ name: dist
74
+ path: dist
75
+ - uses: pypa/gh-action-pypi-publish@release/v1
76
+ with:
77
+ packages-dir: dist
@@ -0,0 +1,10 @@
1
+ .venv/
2
+ __pycache__/
3
+ .mypy_cache/
4
+ .pytest_cache/
5
+ .idea/
6
+ *.egg-info/
7
+ *.png
8
+ /docs
9
+ dist/
10
+ build/
@@ -0,0 +1,48 @@
1
+ # Changelog
2
+
3
+ Notable changes to shape-plotters. Versions follow semantic versioning.
4
+
5
+ ## 0.1.0
6
+
7
+ First release.
8
+
9
+ ### Added
10
+
11
+ - **Installable package.** `pip install shape-plotters` provides the
12
+ `shape-plotters` command; the parameterization libraries are pinned
13
+ dependencies.
14
+ - **Shared engine, one render per parameterization.** `shape-plotters beta`
15
+ and `shape-plotters fos` open the same interactive figure; everything
16
+ shape-specific comes from the render (contract in
17
+ `shape_plotters/core/result.py`).
18
+ - **Beta render** over beta-parameterization 4.0.1: sliders β1–β8, volume
19
+ conserved by the library. An orange overlay shows the centre-of-mass
20
+ corrected shape whenever its β1 differs from the slider value; a corrected
21
+ shape that turns out invalid is drawn greyed instead of vanishing.
22
+ - **FoS render** over fos-parameterization 3.0.0: sliders c and a3–a8 with
23
+ practical-limit markers, an extra ρ(z) panel with the library's dρ/dz, the
24
+ library's neck, and an orange overlay of the R(θ) star-convex representation
25
+ when its centre of mass is shifted. Separated shapes draw both fragments.
26
+ - **Energy-model grid.** R(θ) and the analytic dR/dθ are evaluated by the
27
+ libraries on a 2048-node Gauss-Legendre grid in cos θ, the dense grid of
28
+ the WMMM energy model, so the plot shows the shape the model evaluates.
29
+ - **Stats panel:** volume, surface and centre of mass by Gauss-Legendre
30
+ quadrature on that grid, neck position, radius and depth, and the fragment
31
+ volume and mass split at the neck.
32
+ - **Invalid shapes** stay visible: greyed, with the library's status name and
33
+ message as the panel title.
34
+ - **Display units:** fm / R₀ toggle with Z and N boxes (R₀ = 1.16 A^(1/3) fm).
35
+ - **Scission bands:** the neck-radius range 1.2–1.5 fm is shaded on the
36
+ cross-section panel.
37
+ - **Controls:** ± nudge buttons on every slider, Reset, and Save (300 dpi PNG
38
+ named after the parameters).
39
+ - **Optional Energy button.** Shown only when a local `wmmm` package is
40
+ importable; prints WMMM energies for the shape on screen. `wmmm` is not a
41
+ dependency and no model code, data or output is part of this repository.
42
+ - **Performance guards:** pytest budgets for artist mutation and frame time
43
+ (`tests/test_perf.py`).
44
+
45
+ ## Before 0.1.0
46
+
47
+ No changelog was kept during initial development (from 2026-07-03). See the
48
+ git history.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aleksander Augustyn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: shape-plotters
3
+ Version: 0.1.0
4
+ Summary: Interactive matplotlib plotters for axially symmetric nuclear shapes (beta, FoS)
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/AleksanderAugustyn/shape-plotters
7
+ Project-URL: Repository, https://github.com/AleksanderAugustyn/shape-plotters
8
+ Project-URL: Changelog, https://github.com/AleksanderAugustyn/shape-plotters/blob/master/CHANGELOG.md
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy>=2.0
13
+ Requires-Dist: scipy>=1.13
14
+ Requires-Dist: matplotlib>=3.8.4
15
+ Requires-Dist: beta-parameterization==4.0.1
16
+ Requires-Dist: fos-parameterization==3.0.0
17
+ Provides-Extra: test
18
+ Requires-Dist: pytest>=7; extra == "test"
19
+ Dynamic: license-file
20
+
21
+ # shape-plotters
22
+
23
+ Interactive matplotlib plotters for axially symmetric nuclear shapes. Move a
24
+ slider and the shape, its derivative and its integral properties update. One
25
+ shared engine draws the figure; each shape parameterization is a render module.
26
+
27
+ | render | parameterization | sliders | library |
28
+ |---|---|---|---|
29
+ | `beta` | spherical-harmonic (Legendre) expansion | β1–β8 | [beta-parameterization](https://github.com/AleksanderAugustyn/beta-parameterization) |
30
+ | `fos` | Fourier-over-Spheroid | c, a3–a8 | [fos-parameterization](https://github.com/AleksanderAugustyn/fos-parameterization) |
31
+
32
+ The shapes are not re-implemented here. R(θ) and the analytic dR/dθ come from
33
+ the compiled libraries, evaluated on a 2048-node Gauss-Legendre grid in cos θ.
34
+ That is the dense grid of the WMMM macroscopic-microscopic energy model, so
35
+ the plot shows exactly the shape the model evaluates.
36
+
37
+ ## What the figure shows
38
+
39
+ - **R(θ) and dR/dθ**, and the **cross-section** ρ(z) with equal axes. The FoS
40
+ render adds a ρ(z) panel with the library's dρ/dz.
41
+ - **Stats:** volume, surface and centre of mass by Gauss-Legendre quadrature,
42
+ the neck position, radius and depth, and the fragment volume and mass split
43
+ at the neck.
44
+ - **Overlays** (orange, dashed): for beta, the centre-of-mass corrected shape
45
+ when its β1 differs from the slider value; for FoS, the R(θ) star-convex
46
+ representation when its centre of mass is shifted.
47
+ - **Scission bands:** the neck-radius range 1.2–1.5 fm, shaded.
48
+ - **Invalid shapes** stay on screen, greyed, with the library's status as the
49
+ panel title.
50
+
51
+ Controls: ± nudge buttons on every slider, an fm / R₀ unit toggle with Z and N
52
+ boxes (R₀ = 1.16 A^(1/3) fm), Reset, and Save (300 dpi PNG named after the
53
+ parameters, written to the current directory). Red dotted marks on the FoS
54
+ sliders are practical limits.
55
+
56
+ ## Requirements
57
+
58
+ - Linux x86-64. The parameterization libraries ship manylinux wheels only;
59
+ WSL2 with WSLg works.
60
+ - Python 3.10 or newer with a matplotlib GUI backend. Tk is the default
61
+ (`python3-tk` on Debian/Ubuntu).
62
+
63
+ ## Install
64
+
65
+ pip install shape-plotters
66
+
67
+ or `pipx install shape-plotters` to get the command without touching another
68
+ environment. The parameterization libraries come along as prebuilt wheels
69
+ (Fortran shared library and libgfortran bundled), pinned to the exact versions
70
+ each render is written against.
71
+
72
+ Under WSL, keep the virtual environment on the Linux filesystem, not under
73
+ `/mnt/c`. The Windows drive is a 9P mount; a venv there makes matplotlib
74
+ rendering sluggish (~5× slower).
75
+
76
+ ## Run
77
+
78
+ shape-plotters beta
79
+ shape-plotters fos
80
+
81
+ `python -m shape_plotters beta` does the same.
82
+
83
+ ## Energy button
84
+
85
+ An Energy button appears when a Python package named `wmmm` is importable. It
86
+ prints the WMMM energies of the shape on screen. WMMM is not public yet and is
87
+ not a dependency: without it the button is absent and nothing else changes.
88
+ This repository contains the calling convention only, no model code, data or
89
+ output.
90
+
91
+ ## Development
92
+
93
+ git clone https://github.com/AleksanderAugustyn/shape-plotters.git
94
+ cd shape-plotters
95
+ python3 -m venv ~/.venvs/shape-plotters
96
+ source ~/.venvs/shape-plotters/bin/activate
97
+ pip install -e ".[test]"
98
+ python -m pytest
99
+
100
+ The WMMM smoke tests skip when `wmmm` is not installed. The frame-time budgets
101
+ in `tests/test_perf.py` assume a venv on the Linux filesystem.
102
+
103
+ shape_plotters/cli.py entry point and render registry
104
+ shape_plotters/core/ engine, widgets, quadrature, neck and fragment helpers
105
+ shape_plotters/core/result.py the render contract (what a render gives the engine)
106
+ shape_plotters/renders/ one module per parameterization
107
+ tests/ pytest suite, including frame-time budgets
108
+
109
+ A new parameterization is a new module in `shape_plotters/renders/` that
110
+ implements the render contract, plus one registry entry in `cli.py` and a
111
+ pinned library in `pyproject.toml`. The engine needs no change.
112
+
113
+ Releases are cut by pushing a version tag such as `0.1.0`; the `wheels`
114
+ workflow builds, tests and publishes to PyPI.
115
+
116
+ ## License
117
+
118
+ MIT, see [LICENSE](https://github.com/AleksanderAugustyn/shape-plotters/blob/master/LICENSE).
119
+ Changes are recorded in
120
+ [CHANGELOG.md](https://github.com/AleksanderAugustyn/shape-plotters/blob/master/CHANGELOG.md).
@@ -0,0 +1,100 @@
1
+ # shape-plotters
2
+
3
+ Interactive matplotlib plotters for axially symmetric nuclear shapes. Move a
4
+ slider and the shape, its derivative and its integral properties update. One
5
+ shared engine draws the figure; each shape parameterization is a render module.
6
+
7
+ | render | parameterization | sliders | library |
8
+ |---|---|---|---|
9
+ | `beta` | spherical-harmonic (Legendre) expansion | β1–β8 | [beta-parameterization](https://github.com/AleksanderAugustyn/beta-parameterization) |
10
+ | `fos` | Fourier-over-Spheroid | c, a3–a8 | [fos-parameterization](https://github.com/AleksanderAugustyn/fos-parameterization) |
11
+
12
+ The shapes are not re-implemented here. R(θ) and the analytic dR/dθ come from
13
+ the compiled libraries, evaluated on a 2048-node Gauss-Legendre grid in cos θ.
14
+ That is the dense grid of the WMMM macroscopic-microscopic energy model, so
15
+ the plot shows exactly the shape the model evaluates.
16
+
17
+ ## What the figure shows
18
+
19
+ - **R(θ) and dR/dθ**, and the **cross-section** ρ(z) with equal axes. The FoS
20
+ render adds a ρ(z) panel with the library's dρ/dz.
21
+ - **Stats:** volume, surface and centre of mass by Gauss-Legendre quadrature,
22
+ the neck position, radius and depth, and the fragment volume and mass split
23
+ at the neck.
24
+ - **Overlays** (orange, dashed): for beta, the centre-of-mass corrected shape
25
+ when its β1 differs from the slider value; for FoS, the R(θ) star-convex
26
+ representation when its centre of mass is shifted.
27
+ - **Scission bands:** the neck-radius range 1.2–1.5 fm, shaded.
28
+ - **Invalid shapes** stay on screen, greyed, with the library's status as the
29
+ panel title.
30
+
31
+ Controls: ± nudge buttons on every slider, an fm / R₀ unit toggle with Z and N
32
+ boxes (R₀ = 1.16 A^(1/3) fm), Reset, and Save (300 dpi PNG named after the
33
+ parameters, written to the current directory). Red dotted marks on the FoS
34
+ sliders are practical limits.
35
+
36
+ ## Requirements
37
+
38
+ - Linux x86-64. The parameterization libraries ship manylinux wheels only;
39
+ WSL2 with WSLg works.
40
+ - Python 3.10 or newer with a matplotlib GUI backend. Tk is the default
41
+ (`python3-tk` on Debian/Ubuntu).
42
+
43
+ ## Install
44
+
45
+ pip install shape-plotters
46
+
47
+ or `pipx install shape-plotters` to get the command without touching another
48
+ environment. The parameterization libraries come along as prebuilt wheels
49
+ (Fortran shared library and libgfortran bundled), pinned to the exact versions
50
+ each render is written against.
51
+
52
+ Under WSL, keep the virtual environment on the Linux filesystem, not under
53
+ `/mnt/c`. The Windows drive is a 9P mount; a venv there makes matplotlib
54
+ rendering sluggish (~5× slower).
55
+
56
+ ## Run
57
+
58
+ shape-plotters beta
59
+ shape-plotters fos
60
+
61
+ `python -m shape_plotters beta` does the same.
62
+
63
+ ## Energy button
64
+
65
+ An Energy button appears when a Python package named `wmmm` is importable. It
66
+ prints the WMMM energies of the shape on screen. WMMM is not public yet and is
67
+ not a dependency: without it the button is absent and nothing else changes.
68
+ This repository contains the calling convention only, no model code, data or
69
+ output.
70
+
71
+ ## Development
72
+
73
+ git clone https://github.com/AleksanderAugustyn/shape-plotters.git
74
+ cd shape-plotters
75
+ python3 -m venv ~/.venvs/shape-plotters
76
+ source ~/.venvs/shape-plotters/bin/activate
77
+ pip install -e ".[test]"
78
+ python -m pytest
79
+
80
+ The WMMM smoke tests skip when `wmmm` is not installed. The frame-time budgets
81
+ in `tests/test_perf.py` assume a venv on the Linux filesystem.
82
+
83
+ shape_plotters/cli.py entry point and render registry
84
+ shape_plotters/core/ engine, widgets, quadrature, neck and fragment helpers
85
+ shape_plotters/core/result.py the render contract (what a render gives the engine)
86
+ shape_plotters/renders/ one module per parameterization
87
+ tests/ pytest suite, including frame-time budgets
88
+
89
+ A new parameterization is a new module in `shape_plotters/renders/` that
90
+ implements the render contract, plus one registry entry in `cli.py` and a
91
+ pinned library in `pyproject.toml`. The engine needs no change.
92
+
93
+ Releases are cut by pushing a version tag such as `0.1.0`; the `wheels`
94
+ workflow builds, tests and publishes to PyPI.
95
+
96
+ ## License
97
+
98
+ MIT, see [LICENSE](https://github.com/AleksanderAugustyn/shape-plotters/blob/master/LICENSE).
99
+ Changes are recorded in
100
+ [CHANGELOG.md](https://github.com/AleksanderAugustyn/shape-plotters/blob/master/CHANGELOG.md).
@@ -0,0 +1,5 @@
1
+ import os
2
+ import sys
3
+
4
+ os.environ.setdefault("MPLBACKEND", "Agg")
5
+ sys.path.insert(0, os.path.dirname(__file__))
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "setuptools_scm>=8"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "shape-plotters"
7
+ description = "Interactive matplotlib plotters for axially symmetric nuclear shapes (beta, FoS)"
8
+ readme = "README.md"
9
+ license = "MIT"
10
+ license-files = ["LICENSE"]
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "numpy>=2.0",
14
+ # First releases that install alongside numpy 2.
15
+ "scipy>=1.13",
16
+ "matplotlib>=3.8.4",
17
+ # Exact pins: each render is written against one library API version.
18
+ "beta-parameterization==4.0.1",
19
+ "fos-parameterization==3.0.0",
20
+ ]
21
+ dynamic = ["version"]
22
+
23
+ [project.optional-dependencies]
24
+ test = ["pytest>=7"]
25
+
26
+ [project.scripts]
27
+ shape-plotters = "shape_plotters.cli:main"
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/AleksanderAugustyn/shape-plotters"
31
+ Repository = "https://github.com/AleksanderAugustyn/shape-plotters"
32
+ Changelog = "https://github.com/AleksanderAugustyn/shape-plotters/blob/master/CHANGELOG.md"
33
+
34
+ [tool.setuptools.packages.find]
35
+ include = ["shape_plotters*"]
36
+
37
+ # Version from git tags (setuptools_scm), as in the parameterization libraries.
38
+ [tool.setuptools_scm]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,3 @@
1
+ from shape_plotters.cli import main
2
+
3
+ main()
@@ -0,0 +1,19 @@
1
+ """Command-line entry point: shape-plotters beta|fos (or python -m shape_plotters)."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ from collections.abc import Sequence
6
+
7
+ from shape_plotters.core.engine import ShapePlotterApp
8
+ from shape_plotters.renders.beta import BetaRender
9
+ from shape_plotters.renders.fos import FoSRender
10
+
11
+ RENDERS = {"beta": BetaRender, "fos": FoSRender}
12
+
13
+
14
+ def main(argv: Sequence[str] | None = None) -> None:
15
+ parser = argparse.ArgumentParser(
16
+ prog="shape-plotters", description="Interactive nuclear-shape plotter")
17
+ parser.add_argument("render", choices=sorted(RENDERS))
18
+ args = parser.parse_args(argv)
19
+ ShapePlotterApp(RENDERS[args.render]()).run()
File without changes
@@ -0,0 +1,91 @@
1
+ """Optional WMMM energy adapter — the only module allowed to import wmmm.
2
+
3
+ The energy model is strictly local: wmmm is never a dependency of this
4
+ package (not even an optional extra) and is installed out-of-band as a local
5
+ editable install. This module carries the calling convention only — no model
6
+ code, data, or paths. The engine consults available() to decide whether the
7
+ Energy button exists; compute() returns EnergyResult, with failures in
8
+ EnergyResult.error rather than exceptions.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import importlib.util
13
+ from dataclasses import dataclass
14
+ from typing import Sequence
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class EnergyResult:
19
+ """One WMMM point result (energies in MeV); zero-filled when error is set."""
20
+ is_valid: bool
21
+ mass_excess: float
22
+ total_energy: float
23
+ macro_energy: float
24
+ micro_energy: float
25
+ surface_energy: float
26
+ coulomb_energy: float
27
+ proton_pairing_gap: float
28
+ neutron_pairing_gap: float
29
+ proton_k: int
30
+ neutron_k: int
31
+ corrected_beta10: float # cross-check channel (vs the render scalar), not displayed
32
+ error: str | None = None
33
+
34
+
35
+ # Model handles are configuration-immutable: one per (param_type,
36
+ # com_correction) for the app lifetime (~20 ms per compute thereafter).
37
+ _models: dict[tuple[str, bool], object] = {}
38
+
39
+
40
+ def available() -> bool:
41
+ """True when the wmmm package is importable; performs no import."""
42
+ return importlib.util.find_spec("wmmm") is not None
43
+
44
+
45
+ def _error(message: str) -> EnergyResult:
46
+ return EnergyResult(False, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
47
+ 0, 0, 0.0, error=message)
48
+
49
+
50
+ def _get_model(param_type: str, com_correction: bool):
51
+ key = (param_type, com_correction)
52
+ model = _models.get(key)
53
+ if model is None:
54
+ import wmmm # deferred: loads the Fortran library on first use only
55
+ model = wmmm.Model(param_type)
56
+ if not com_correction:
57
+ model.set("beta_10_com_shift", 0.0)
58
+ _models[key] = model
59
+ return model
60
+
61
+
62
+ def compute(param_type: str, z: int, n: int, shape: Sequence[float],
63
+ com_correction: bool = True) -> EnergyResult:
64
+ """One WMMM point computation; never raises.
65
+
66
+ Parameters
67
+ ----------
68
+ param_type : str
69
+ "legendre" (20 shape params) or "fos" (7).
70
+ z, n : int
71
+ Proton and neutron numbers.
72
+ shape : Sequence[float]
73
+ Shape parameters in WMMM's convention (raw slider values).
74
+ com_correction : bool
75
+ WMMM's beta_10_com_shift flag. False evaluates beta10 as given
76
+ (legendre only — inert on the fos path).
77
+ """
78
+ try:
79
+ model = _get_model(param_type, com_correction)
80
+ r = model.compute(int(z), int(n), list(shape))
81
+ except Exception as exc: # any wmmm failure becomes a stats-box message
82
+ return _error(f"{type(exc).__name__}: {exc}")
83
+ return EnergyResult(
84
+ is_valid=bool(r.is_valid), mass_excess=r.mass_excess,
85
+ total_energy=r.total_energy, macro_energy=r.macro_energy,
86
+ micro_energy=r.micro_energy, surface_energy=r.surface_energy,
87
+ coulomb_energy=r.coulomb_energy,
88
+ proton_pairing_gap=r.proton_pairing_gap,
89
+ neutron_pairing_gap=r.neutron_pairing_gap,
90
+ proton_k=int(r.proton_k), neutron_k=int(r.neutron_k),
91
+ corrected_beta10=r.corrected_beta10)