Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,9 @@ exclude = '''
| tests/data
)/
'''

[tool.pytest.ini_options]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
]
testpaths = ["tests"]
2 changes: 2 additions & 0 deletions src/diffpy/snmf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# package version
from diffpy.snmf.version import __version__

__all__ = ["__version__", "SNMFOptimizer"]

# silence the pyflakes syntax checker
assert __version__ or True

Expand Down
11 changes: 6 additions & 5 deletions src/diffpy/snmf/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import numpy as np
from snmf_class import SNMFOptimizer

from diffpy.snmf.snmf_class import SNMFOptimizer

# Example input files (not provided)
init_components_file = np.loadtxt("input/init_components.txt", dtype=float)
source_matrix_file = np.loadtxt("input/source_matrix.txt", dtype=float)
init_stretch_file = np.loadtxt("input/init_stretch.txt", dtype=float)
init_weights_file = np.loadtxt("input/init_weights.txt", dtype=float)
init_components_file = np.loadtxt("inputs/init_components.txt", dtype=float)
source_matrix_file = np.loadtxt("inputs/source_matrix.txt", dtype=float)
init_stretch_file = np.loadtxt("inputs/init_stretch.txt", dtype=float)
init_weights_file = np.loadtxt("inputs/init_weights.txt", dtype=float)

my_model = SNMFOptimizer(
source_matrix=source_matrix_file,
Expand Down
5 changes: 3 additions & 2 deletions src/diffpy/snmf/snmf_class.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import cvxpy as cp
import numpy as np
from plotter import SNMFPlotter
from scipy.optimize import minimize
from scipy.sparse import coo_matrix, diags

from diffpy.snmf.plotter import SNMFPlotter


class SNMFOptimizer:
"""An implementation of stretched NMF (sNMF), including sparse stretched NMF.
Expand Down Expand Up @@ -625,7 +626,7 @@ def update_stretch(self):
Updates matrix A using constrained optimization (equivalent to fmincon in MATLAB).
"""

# Flatten A for compatibility with the optimizer (since SciPy expects 1D input)
# Flatten A for compatibility with the optimizer (since SciPy expects 1D inputs)
stretch_flat_initial = self.stretch.flatten()

# Define the optimization function
Expand Down
21 changes: 21 additions & 0 deletions tests/inputs/test_snmf_optimizer/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
This test is a whole-program test of the SNMF Optimizer. It runs the optimization on known data with fixed, trusted settings, then asserts
whether the objective function is below a certain value after exactly a certain number of iterations.
It is a blunt-force instrument that can tell if a PR has completely broken things, but it will not catch regressions, and its method
of using objective function only can inadverdently validate a degenerate result. Use with caution.

This test uses data published in:
Stretched Non-negative Matrix Factorization[J].
Section 5.4 XRD
Tab. 7, Fig. 8 & 9
Gu R, Rakita Y, Lan L, et al.
Stretched Non-negative Matrix Factorization[J].
arXiv preprint arXiv:2311.15173, 2023.
and later republished as:
Gu, R., Rakita, Y., Lan, L. et al. Stretched non-negative matrix factorization.
npj Comput Mater 10, 193 (2024). https://doi.org/10.1038/s41524-024-01377-5
Data description:
"A stoichiometric mixture of 2:1 YOCl (>98% tetragonal phase) and MgMn2O4 (spinel phase) was uniformly mixed and sealed in a quartz capillary. It was then heated in a gradient furnance, meaning that each location on the quartz tube had a different temperature31. The absolute temperatures at each point along the sample were calibrated from the lattice expansion of a known calibration material, Ni. The data went from a low temperature of 368∘C to a highest temperature of 668∘C with a total of 20 individual temperature points. Using ‘pyFAI’32, the collected 2D diffraction patterns were then cleaned by masking the beam-stop and over-bright/dead pixels, followed by an azimuthal integration to gain 1D PXRD patterns. The 1D PXRD data was then used as inputs to the different NMF algorithms."
The data was originally sourced from:
O’Nolan D, Huang G, Kamm GE, et al (2020)
A thermal-gradient approach to variable-temperature measurements resolved in space.
Journal of Applied Crystallography 53(3):662–670.
Loading