From 0e4f2a3798c8c2503c3dccb2a00d3061540bb259 Mon Sep 17 00:00:00 2001 From: Andrea-gm <162758982+Andrea-gm@users.noreply.github.com> Date: Thu, 5 Mar 2026 18:08:07 -0800 Subject: [PATCH 1/4] Added convergence flag to fit() --- src/diffpy/stretched_nmf/snmf_class.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/diffpy/stretched_nmf/snmf_class.py b/src/diffpy/stretched_nmf/snmf_class.py index d5f6603..566e965 100644 --- a/src/diffpy/stretched_nmf/snmf_class.py +++ b/src/diffpy/stretched_nmf/snmf_class.py @@ -210,7 +210,8 @@ def fit(self, rho=0, eta=0, reset=True): the output of the previous fit() as their input. """ - + self.converged_ = False + if reset: self.components_ = self.init_components.copy() self.weights_ = self.init_weights.copy() @@ -294,6 +295,7 @@ def fit(self, rho=0, eta=0, reset=True): self.objective_difference < self.objective_function * self.tol and outiter >= self.min_iter ): + self.converged_ = True break self.normalize_results() From c2a825fb1dcb07bf7deadb1da0f8dd0378e81cd9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 02:14:09 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/stretched_nmf/snmf_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffpy/stretched_nmf/snmf_class.py b/src/diffpy/stretched_nmf/snmf_class.py index 566e965..f96c854 100644 --- a/src/diffpy/stretched_nmf/snmf_class.py +++ b/src/diffpy/stretched_nmf/snmf_class.py @@ -211,7 +211,7 @@ def fit(self, rho=0, eta=0, reset=True): fit() as their input. """ self.converged_ = False - + if reset: self.components_ = self.init_components.copy() self.weights_ = self.init_weights.copy() From fe8102411aacbf4e09d22d2bd8afbe5c50c5cd9c Mon Sep 17 00:00:00 2001 From: Andrea-gm <162758982+Andrea-gm@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:17:56 -0800 Subject: [PATCH 3/4] Added news --- news/add-convergence-flag.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 news/add-convergence-flag.rst diff --git a/news/add-convergence-flag.rst b/news/add-convergence-flag.rst new file mode 100644 index 0000000..e4776b7 --- /dev/null +++ b/news/add-convergence-flag.rst @@ -0,0 +1,25 @@ +**Added:** + +* SNMFOptimizer.converged_ attribute to indicate whether the optimization + successfully reached the convergence tolerance (True) or stopped because the + maximum number of iterations was reached (False). + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* From f24c5e3b8e6cbcec134b0c201933b1f999014718 Mon Sep 17 00:00:00 2001 From: Andrea-gm <162758982+Andrea-gm@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:36:50 -0800 Subject: [PATCH 4/4] Update snmf_class.py Was giving me errors due to use of python 3.11 --- src/diffpy/stretched_nmf/snmf_class.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/diffpy/stretched_nmf/snmf_class.py b/src/diffpy/stretched_nmf/snmf_class.py index f96c854..35692b9 100644 --- a/src/diffpy/stretched_nmf/snmf_class.py +++ b/src/diffpy/stretched_nmf/snmf_class.py @@ -252,11 +252,12 @@ def fit(self, rho=0, eta=0, reset=True): sparsity_term = self.eta * np.sum( np.sqrt(self.components_) ) # Square root penalty + obj_diff = ( + self.objective_function - regularization_term - sparsity_term + ) print( f"Start, Objective function: {self.objective_function:.5e}" - f", Obj - reg/sparse: {self.objective_function - - regularization_term - - sparsity_term:.5e}" + f", Obj - reg/sparse: {obj_diff:.5e}" ) # Main optimization loop @@ -275,11 +276,12 @@ def fit(self, rho=0, eta=0, reset=True): sparsity_term = self.eta * np.sum( np.sqrt(self.components_) ) # Square root penalty + obj_diff = ( + self.objective_function - regularization_term - sparsity_term + ) print( f"Obj fun: {self.objective_function:.5e}, " - f"Obj - reg/sparse: {self.objective_function - - regularization_term - - sparsity_term:.5e}, " + f", Obj - reg/sparse: {obj_diff:.5e}" f"Iter: {self.outiter}" )