From 504242733a5af2f49cf15d8eabfc4bd317747787 Mon Sep 17 00:00:00 2001 From: John Halloran Date: Sun, 12 Apr 2026 15:21:21 -0400 Subject: [PATCH 1/5] fix: use matplotlib-base when installing with conda-forge --- README.rst | 4 ++++ docs/source/getting-started.rst | 4 ++++ news/forge-cleanup.rst | 23 +++++++++++++++++++++++ requirements/conda.txt | 2 +- 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 news/forge-cleanup.rst diff --git a/README.rst b/README.rst index b87a7c1f..44fb3b82 100644 --- a/README.rst +++ b/README.rst @@ -69,6 +69,10 @@ The preferred method is conda:: conda create -n diffpy.stretched-nmf_env diffpy.stretched-nmf conda activate diffpy.stretched-nmf_env +For interactive plotting with ``show_plots=True``, use a GUI-capable desktop +environment. Conda installs use ``matplotlib-base``, which is sufficient for +plotting but still depends on an available interactive Matplotlib backend. + Alternatively, install from PyPI with pip:: pip install diffpy.stretched-nmf diff --git a/docs/source/getting-started.rst b/docs/source/getting-started.rst index 7c2e6a44..1104eadf 100644 --- a/docs/source/getting-started.rst +++ b/docs/source/getting-started.rst @@ -17,6 +17,10 @@ The preferred method is conda: conda create -n diffpy.stretched-nmf_env diffpy.stretched-nmf conda activate diffpy.stretched-nmf_env +For interactive plotting with ``show_plots=True``, use a GUI-capable desktop +environment. Conda installs use ``matplotlib-base``, which is sufficient for +plotting but still depends on an available interactive Matplotlib backend. + Alternatively, install from PyPI with pip: .. code-block:: bash diff --git a/news/forge-cleanup.rst b/news/forge-cleanup.rst new file mode 100644 index 00000000..17db9ea2 --- /dev/null +++ b/news/forge-cleanup.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Use matplotlib-base when installing with conda-forge + +**Security:** + +* diff --git a/requirements/conda.txt b/requirements/conda.txt index 60eeedae..693bc6d6 100644 --- a/requirements/conda.txt +++ b/requirements/conda.txt @@ -1,5 +1,5 @@ numpy -matplotlib +matplotlib-base scipy cvxpy diffpy.utils From ad580c11e320c6fe0d345be8328bd1ccd9783263 Mon Sep 17 00:00:00 2001 From: John Halloran Date: Sun, 12 Apr 2026 15:48:57 -0400 Subject: [PATCH 2/5] refactor: rename cli entrypoint to 'snmf' from 'diffpy.stretched-nmf' --- README.rst | 4 ++-- docs/source/getting-started.rst | 2 +- pyproject.toml | 2 +- src/diffpy/stretched_nmf/snmf_app.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 44fb3b82..10c0dd54 100644 --- a/README.rst +++ b/README.rst @@ -83,13 +83,13 @@ For source installs (after cloning the repo):: Quick check:: - diffpy.stretched-nmf --version + snmf --version python -c "import diffpy.stretched_nmf; print(diffpy.stretched_nmf.__version__)" To view the basic usage and available commands, type :: - diffpy.stretched-nmf -h + snmf -h Getting Started --------------- diff --git a/docs/source/getting-started.rst b/docs/source/getting-started.rst index 1104eadf..a887b242 100644 --- a/docs/source/getting-started.rst +++ b/docs/source/getting-started.rst @@ -40,7 +40,7 @@ Verify the CLI and Python import: .. code-block:: bash - diffpy.stretched-nmf --version + snmf --version python -c "import diffpy.stretched_nmf; print(diffpy.stretched_nmf.__version__)" Basic usage diff --git a/pyproject.toml b/pyproject.toml index 2e55cb08..bc0c0fb2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ exclude = [] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) [project.scripts] -"diffpy.stretched-nmf" = "diffpy.stretched_nmf.snmf_app:main" +"snmf" = "diffpy.stretched_nmf.snmf_app:main" [tool.setuptools.dynamic] dependencies = {file = ["requirements/pip.txt"]} diff --git a/src/diffpy/stretched_nmf/snmf_app.py b/src/diffpy/stretched_nmf/snmf_app.py index 57f6397f..45f386ec 100644 --- a/src/diffpy/stretched_nmf/snmf_app.py +++ b/src/diffpy/stretched_nmf/snmf_app.py @@ -5,7 +5,7 @@ def main(): parser = argparse.ArgumentParser( - prog="diffpy.stretched-nmf", + prog="snmf", description=( "A python package implementing the stretched NMF algorithm.\n\n" "For more information, visit: " @@ -23,7 +23,7 @@ def main(): args = parser.parse_args() if args.version: - print(f"diffpy.stretched-nmf {__version__}") + print(f"snmf {__version__}") else: # Default behavior when no arguments are given parser.print_help() From e9c16905bfc794012328e24c3545545855765515 Mon Sep 17 00:00:00 2001 From: John Halloran Date: Sun, 12 Apr 2026 15:50:25 -0400 Subject: [PATCH 3/5] chore: add news item for previous commit --- news/forge-cleanup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/news/forge-cleanup.rst b/news/forge-cleanup.rst index 17db9ea2..26c98cf2 100644 --- a/news/forge-cleanup.rst +++ b/news/forge-cleanup.rst @@ -4,7 +4,7 @@ **Changed:** -* +* Rename cli entrypoint to 'snmf' from 'diffpy.stretched-nmf' **Deprecated:** From d395a30535942804e117d35f7ce423b25cb6f5fd Mon Sep 17 00:00:00 2001 From: John Halloran Date: Sun, 12 Apr 2026 15:58:40 -0400 Subject: [PATCH 4/5] fix: produce an error if test files are missing --- news/forge-cleanup.rst | 1 + tests/test_snmf_optimizer.py | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/news/forge-cleanup.rst b/news/forge-cleanup.rst index 26c98cf2..a0a0d602 100644 --- a/news/forge-cleanup.rst +++ b/news/forge-cleanup.rst @@ -16,6 +16,7 @@ **Fixed:** +* Produce an error if test files are missing * Use matplotlib-base when installing with conda-forge **Security:** diff --git a/tests/test_snmf_optimizer.py b/tests/test_snmf_optimizer.py index d9a42491..27cae5d7 100644 --- a/tests/test_snmf_optimizer.py +++ b/tests/test_snmf_optimizer.py @@ -5,9 +5,11 @@ from diffpy.stretched_nmf.snmf_class import SNMFOptimizer -DATA_DIR = Path(__file__).parent / "inputs/test_snmf_optimizer" +DATA_DIR = ( + Path(__file__).resolve().parents[1] + / "docs/examples/data/XRD-MgMnO-YCl-real" +) -# Skip the test entirely if any inputs file is missing _required = [ "init-components.txt", "source-matrix.txt", @@ -15,18 +17,21 @@ "init-weights.txt", ] _missing = [f for f in _required if not (DATA_DIR / f).exists()] -pytestmark = pytest.mark.skipif( - _missing, reason=f"Missing test data files: {_missing}" -) @pytest.fixture(scope="module") def inputs(): + if _missing: + pytest.fail( + f"Missing required test data files in {DATA_DIR}: {_missing}" + ) return { "components": np.loadtxt( DATA_DIR / "init-components.txt", dtype=float ), - "source": np.loadtxt(DATA_DIR / "source-matrix.txt", dtype=float), + "source": np.loadtxt( + DATA_DIR / "source-matrix.txt", dtype=float, skiprows=4 + ), "stretch": np.loadtxt(DATA_DIR / "init-stretch.txt", dtype=float), "weights": np.loadtxt(DATA_DIR / "init-weights.txt", dtype=float), } From bce633797a6b762f52c5995ba6514eb13028de9f Mon Sep 17 00:00:00 2001 From: John Halloran Date: Sun, 12 Apr 2026 16:02:30 -0400 Subject: [PATCH 5/5] docs: explain the current entrypoint when the help command is used --- src/diffpy/stretched_nmf/snmf_app.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/diffpy/stretched_nmf/snmf_app.py b/src/diffpy/stretched_nmf/snmf_app.py index 45f386ec..085e4c3d 100644 --- a/src/diffpy/stretched_nmf/snmf_app.py +++ b/src/diffpy/stretched_nmf/snmf_app.py @@ -8,6 +8,9 @@ def main(): prog="snmf", description=( "A python package implementing the stretched NMF algorithm.\n\n" + "Currently, this project is used by importing " + "`SNMFOptimizer` in Python rather than through a command-line " + "workflow.\n\n" "For more information, visit: " "https://github.com/diffpy/diffpy.stretched-nmf/" ),