From e46ac632c99309edaebf44e3a086edf99c7794bb Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Tue, 7 Apr 2026 22:07:17 -0400 Subject: [PATCH 01/12] fix: fix load single peak in py3 support --- news/fix-single-peak.rst | 23 ++++++ src/diffpy/srmise/applications/extract.py | 75 +++++++++++++++++-- src/diffpy/srmise/dataclusters.py | 12 +-- src/diffpy/srmise/modelcluster.py | 6 +- src/diffpy/srmise/modelevaluators/aic.py | 2 +- src/diffpy/srmise/modelparts.py | 5 +- src/diffpy/srmise/peakextraction.py | 6 +- src/diffpy/srmise/peaks/terminationripples.py | 2 +- 8 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 news/fix-single-peak.rst diff --git a/news/fix-single-peak.rst b/news/fix-single-peak.rst new file mode 100644 index 0000000..db33779 --- /dev/null +++ b/news/fix-single-peak.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Fixed extracting single peak with `py2` legacy cleanup + +**Security:** + +* diff --git a/src/diffpy/srmise/applications/extract.py b/src/diffpy/srmise/applications/extract.py index f55b4d3..0383365 100755 --- a/src/diffpy/srmise/applications/extract.py +++ b/src/diffpy/srmise/applications/extract.py @@ -18,6 +18,63 @@ import numpy as np +def _resolve_cli_expression(expression, namespace): + """Resolve a CLI expression against an explicit namespace. + + Parameters + ---------- + expression : str + The user-supplied CLI expression. + namespace : dict + The explicit namespace allowed during evaluation. + + Returns + ------- + object + The resolved class or instance. + """ + return eval(expression, {"__builtins__": {}}, namespace) + + +def _baseline_namespace(): + """Return the baseline classes supported by the CLI.""" + from diffpy.srmise.baselines.arbitrary import Arbitrary + from diffpy.srmise.baselines.fromsequence import FromSequence + from diffpy.srmise.baselines.nanospherical import NanoSpherical + from diffpy.srmise.baselines.polynomial import Polynomial + + return { + "Arbitrary": Arbitrary, + "FromSequence": FromSequence, + "NanoSpherical": NanoSpherical, + "Polynomial": Polynomial, + } + + +def _peakfunction_namespace(): + """Return the peak-function classes supported by the CLI.""" + from diffpy.srmise.peaks.gaussian import Gaussian + from diffpy.srmise.peaks.gaussianoverr import GaussianOverR + from diffpy.srmise.peaks.terminationripples import TerminationRipples + + return { + "Gaussian": Gaussian, + "GaussianOverR": GaussianOverR, + "TerminationRipples": TerminationRipples, + } + + +def _modelevaluator_namespace(): + """Return the model evaluators supported by the CLI.""" + from diffpy.srmise.modelevaluators.aic import AIC + from diffpy.srmise.modelevaluators.aicc import AICc + + return { + "AIC": AIC, + "AICc": AICc, + } + + def main(): """Default SrMise entry-point.""" @@ -433,7 +490,10 @@ def main(): if options.peakfunction: try: - options.peakfunction = eval("peaks." + options.peakfunction) + options.peakfunction = _resolve_cli_expression( + options.peakfunction, + _peakfunction_namespace(), + ) except Exception as err: print(err) print("Could not create peak function '%s'. Exiting." % options.peakfunction) @@ -441,7 +501,10 @@ def main(): if options.modelevaluator: try: - options.modelevaluator = eval("modelevaluators." + options.modelevaluator) + options.modelevaluator = _resolve_cli_expression( + options.modelevaluator, + _modelevaluator_namespace(), + ) except Exception as err: print(err) print("Could not find ModelEvaluator '%s'. Exiting." % options.modelevaluator) @@ -483,10 +546,12 @@ def main(): bl = NanoSpherical() options.baseline = parsepars(bl, options.bspherical) - + elif options.baseline: try: - options.baseline = eval("baselines." + options.baseline) - + options.baseline = _resolve_cli_expression( + options.baseline, + _baseline_namespace(), + ) except Exception as err: print(err) print("Could not create baseline '%s'. Exiting." % options.baseline) diff --git a/src/diffpy/srmise/dataclusters.py b/src/diffpy/srmise/dataclusters.py index 4fe29b5..ba157e7 100644 --- a/src/diffpy/srmise/dataclusters.py +++ b/src/diffpy/srmise/dataclusters.py @@ -206,19 +206,19 @@ def __next__(self): if np.abs(nearest_cluster[1]) <= self.res: # Add to an existing cluster - self.lastcluster_idx = nearest_cluster[0] - if test_idx < self.clusters[nearest_cluster[0], 0]: - self.clusters[nearest_cluster[0], 0] = test_idx + self.lastcluster_idx = int(nearest_cluster[0]) + if test_idx < self.clusters[int(nearest_cluster[0]), 0]: + self.clusters[int(nearest_cluster[0]), 0] = test_idx else: - self.clusters[nearest_cluster[0], 1] = test_idx + self.clusters[int(nearest_cluster[0]), 1] = test_idx else: # Make a new cluster if nearest_cluster[1] < 0: # Insert left of nearest cluster - self.lastcluster_idx = nearest_cluster[0] + self.lastcluster_idx = int(nearest_cluster[0]) else: # insert right of nearest cluster - self.lastcluster_idx = nearest_cluster[0] + 1 + self.lastcluster_idx = int(nearest_cluster[0]) + 1 self.clusters = np.insert( self.clusters, int(self.lastcluster_idx), diff --git a/src/diffpy/srmise/modelcluster.py b/src/diffpy/srmise/modelcluster.py index 1643e38..f58a87b 100644 --- a/src/diffpy/srmise/modelcluster.py +++ b/src/diffpy/srmise/modelcluster.py @@ -1174,7 +1174,7 @@ def cleanfit(self): pos = np.array([p["position"] for p in self.model]) left_idx = pos.searchsorted(self.r_cluster[0]) right_idx = pos.searchsorted(self.r_cluster[-1]) - outside_idx = range(0, left_idx) + outside_idx = list(range(0, left_idx)) outside_idx.extend(range(right_idx, len(self.model))) # inside_idx = range(left_idx, right_idx) @@ -1538,8 +1538,8 @@ def prune(self): # Create model with ith peak removed, and distant peaks effectively fixed lo = max(i - peak_range, 0) hi = min(i + peak_range + 1, len(best_model)) - check_models[i] = best_model[lo:i].copy() - check_models[i].extend(best_model[i + 1 : hi].copy()) + check_models[i] = type(best_model)(best_model[lo:i]).copy() + check_models[i].extend(type(best_model)(best_model[i + 1: hi]).copy()) prune_mc.model = check_models[i] msg = [ diff --git a/src/diffpy/srmise/modelevaluators/aic.py b/src/diffpy/srmise/modelevaluators/aic.py index 24b4ef5..d04e4d2 100644 --- a/src/diffpy/srmise/modelevaluators/aic.py +++ b/src/diffpy/srmise/modelevaluators/aic.py @@ -106,7 +106,7 @@ def minpoints(self, npars): return 1 - def parpenalty(self, k): + def parpenalty(self, k, n=None): """Returns the cost for adding k parameters to the current model cluster. diff --git a/src/diffpy/srmise/modelparts.py b/src/diffpy/srmise/modelparts.py index 1778b9b..c58a7cd 100644 --- a/src/diffpy/srmise/modelparts.py +++ b/src/diffpy/srmise/modelparts.py @@ -430,8 +430,9 @@ def __getitem__(self, index): if isinstance(index, tuple) and len(index) == 2: start, end = index return self.__class__(super().__getitem__(slice(start, end))) - else: - return super().__getitem__(index) + if isinstance(index, slice): + return self.__class__(super().__getitem__(index)) + return super().__getitem__(index) def transform(self, in_format="internal", out_format="internal"): """Transforms format of parameters in this modelpart. diff --git a/src/diffpy/srmise/peakextraction.py b/src/diffpy/srmise/peakextraction.py index 06af50f..e1b3057 100644 --- a/src/diffpy/srmise/peakextraction.py +++ b/src/diffpy/srmise/peakextraction.py @@ -905,7 +905,7 @@ def extract_single(self, recursion_depth=1): ) else: # Update an existing cluster - mclusters[step.lastcluster_idx].change_slice(step.cut(step.lastcluster_idx)) + mclusters[int(step.lastcluster_idx)].change_slice(step.cut(step.lastcluster_idx)) # Find newly adjacent clusters adjacent = step.find_adjacent_clusters().ravel() @@ -969,7 +969,7 @@ def extract_single(self, recursion_depth=1): # near_peaks: array containing the indices of two nearest peaks on either side of border_x # other_peaks: all the other peaks in full_cluster # left_data, right_data: indices defining the extent of the "interpeak range" for x, etc. - near_peaks = np.array([], dtype=np.int) + near_peaks = np.array([], dtype=np.int64) # interpeak range goes from peak to peak of next nearest peaks, although their contributions # to the data are still removed. @@ -1122,7 +1122,7 @@ def extract_single(self, recursion_depth=1): # near_peaks: array containing the indices of two nearest peaks on either side of border_x # other_peaks: all the other peaks in new_cluster # left_data, right_data: indices defining the extent of the "interpeak range" for x, etc. - near_peaks = np.array([], dtype=np.int) + near_peaks = np.array([], dtype=np.int64) # interpeak range goes from peak to peak of next nearest peaks, although their contributions # to the data are still removed. diff --git a/src/diffpy/srmise/peaks/terminationripples.py b/src/diffpy/srmise/peaks/terminationripples.py index 0e4ddba..7d75195 100644 --- a/src/diffpy/srmise/peaks/terminationripples.py +++ b/src/diffpy/srmise/peaks/terminationripples.py @@ -316,7 +316,7 @@ def value(self, peak, r, rng=None): # issues is difficult to determine without detailed knowledge # of the underlying function. dr = (r[-1] - r[0]) / (len(r) - 1) - segments = np.ceil(dr / dr_super) + segments = int(np.ceil(dr / dr_super)) dr_segmented = dr / segments rpart = r[rng] From ed29b92577c7fa8a09d92d8df7955720329a39a2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 02:16:22 +0000 Subject: [PATCH 02/12] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/srmise/modelcluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffpy/srmise/modelcluster.py b/src/diffpy/srmise/modelcluster.py index f58a87b..de264fb 100644 --- a/src/diffpy/srmise/modelcluster.py +++ b/src/diffpy/srmise/modelcluster.py @@ -1539,7 +1539,7 @@ def prune(self): lo = max(i - peak_range, 0) hi = min(i + peak_range + 1, len(best_model)) check_models[i] = type(best_model)(best_model[lo:i]).copy() - check_models[i].extend(type(best_model)(best_model[i + 1: hi]).copy()) + check_models[i].extend(type(best_model)(best_model[i + 1 : hi]).copy()) prune_mc.model = check_models[i] msg = [ From e6786459fc71e9dc1454504d6adc82b9fb2a2299 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 8 Apr 2026 16:33:27 -0400 Subject: [PATCH 03/12] fix:check what else we edited --- src/diffpy/srmise/dataclusters.py | 14 +++++++------- src/diffpy/srmise/peakextraction.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/diffpy/srmise/dataclusters.py b/src/diffpy/srmise/dataclusters.py index ba157e7..a52f25a 100644 --- a/src/diffpy/srmise/dataclusters.py +++ b/src/diffpy/srmise/dataclusters.py @@ -206,19 +206,19 @@ def __next__(self): if np.abs(nearest_cluster[1]) <= self.res: # Add to an existing cluster - self.lastcluster_idx = int(nearest_cluster[0]) - if test_idx < self.clusters[int(nearest_cluster[0]), 0]: - self.clusters[int(nearest_cluster[0]), 0] = test_idx + self.lastcluster_idx = nearest_cluster[0] + if test_idx < self.clusters[nearest_cluster[0], 0]: + self.clusters[nearest_cluster[0], 0] = test_idx else: - self.clusters[int(nearest_cluster[0]), 1] = test_idx + self.clusters[nearest_cluster[0], 1] = test_idx else: # Make a new cluster if nearest_cluster[1] < 0: # Insert left of nearest cluster - self.lastcluster_idx = int(nearest_cluster[0]) + self.lastcluster_idx = nearest_cluster[0] else: # insert right of nearest cluster - self.lastcluster_idx = int(nearest_cluster[0]) + 1 + self.lastcluster_idx = nearest_cluster[0] + 1 self.clusters = np.insert( self.clusters, int(self.lastcluster_idx), @@ -289,7 +289,7 @@ def find_nearest_cluster(self, idx): return None flat_idx = clusters_flat.searchsorted(idx) - near_idx = flat_idx / 2 + near_idx = flat_idx // 2 if flat_idx == len(clusters_flat): # test_idx is right of the last cluster diff --git a/src/diffpy/srmise/peakextraction.py b/src/diffpy/srmise/peakextraction.py index e1b3057..c120766 100644 --- a/src/diffpy/srmise/peakextraction.py +++ b/src/diffpy/srmise/peakextraction.py @@ -905,7 +905,7 @@ def extract_single(self, recursion_depth=1): ) else: # Update an existing cluster - mclusters[int(step.lastcluster_idx)].change_slice(step.cut(step.lastcluster_idx)) + mclusters[step.lastcluster_idx].change_slice(step.cut(step.lastcluster_idx)) # Find newly adjacent clusters adjacent = step.find_adjacent_clusters().ravel() From 198d5a8368644575dd0ac0c96d9e118c18bf24a0 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 8 Apr 2026 17:27:18 -0400 Subject: [PATCH 04/12] fix: fix some unnecessary conversion to int --- src/diffpy/srmise/dataclusters.py | 6 +++--- src/diffpy/srmise/pdfpeakextraction.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/diffpy/srmise/dataclusters.py b/src/diffpy/srmise/dataclusters.py index a52f25a..364ef30 100644 --- a/src/diffpy/srmise/dataclusters.py +++ b/src/diffpy/srmise/dataclusters.py @@ -221,7 +221,7 @@ def __next__(self): self.lastcluster_idx = nearest_cluster[0] + 1 self.clusters = np.insert( self.clusters, - int(self.lastcluster_idx), + self.lastcluster_idx, [test_idx, test_idx], 0, ) @@ -304,8 +304,8 @@ def find_nearest_cluster(self, idx): # Calculate which of the two nearest clusters is closer distances = np.array( [ - self.x[idx] - self.x[self.clusters[int(near_idx) - 1, 1]], - self.x[idx] - self.x[self.clusters[int(near_idx), 0]], + self.x[idx] - self.x[self.clusters[near_idx - 1, 1]], + self.x[idx] - self.x[self.clusters[near_idx, 0]], ] ) if distances[0] < np.abs(distances[1]): diff --git a/src/diffpy/srmise/pdfpeakextraction.py b/src/diffpy/srmise/pdfpeakextraction.py index f665e3f..f0c50cd 100644 --- a/src/diffpy/srmise/pdfpeakextraction.py +++ b/src/diffpy/srmise/pdfpeakextraction.py @@ -888,9 +888,9 @@ def writepwastr(self, comments): # Generate parameter labels from the baseline function's parameterdict blf = self.extracted.baseline.owner() if blf.npars > 0: - parlbl = blf.parameterdict.keys() - paridx = np.array(blf.parameterdict.values()).argsort() - lines.append("# " + " ".join([str(parlbl[i]) for i in paridx])) + parlbl = list(blf.parameterdict.keys()) + paridx = np.array(list(blf.parameterdict.values())).argsort() + lines.append("# " + " ".join(str(parlbl[i]) for i in paridx)) blpars = " ".join([str(p) for p in self.extracted.baseline.pars]) else: blpars = "(no parameters)" From 7761883ccf2bec7d73a65cb799ecab03ba6c7aa5 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 8 Apr 2026 18:31:40 -0400 Subject: [PATCH 05/12] chore: revert CLI change --- src/diffpy/srmise/applications/extract.py | 80 +++-------------------- 1 file changed, 8 insertions(+), 72 deletions(-) diff --git a/src/diffpy/srmise/applications/extract.py b/src/diffpy/srmise/applications/extract.py index 0383365..10a2de2 100755 --- a/src/diffpy/srmise/applications/extract.py +++ b/src/diffpy/srmise/applications/extract.py @@ -18,62 +18,8 @@ import numpy as np -def _resolve_cli_expression(expression, namespace): - """Resolve a CLI expression against an explicit namespace. - - Parameters - ---------- - expression : str - The user-supplied CLI expression. - namespace : dict - The explicit namespace allowed during evaluation. - - Returns - ------- - object - The resolved class or instance. - """ - return eval(expression, {"__builtins__": {}}, namespace) - - -def _baseline_namespace(): - """Return the baseline classes supported by the CLI.""" - from diffpy.srmise.baselines.arbitrary import Arbitrary - from diffpy.srmise.baselines.fromsequence import FromSequence - from diffpy.srmise.baselines.nanospherical import NanoSpherical - from diffpy.srmise.baselines.polynomial import Polynomial - - return { - "Arbitrary": Arbitrary, - "FromSequence": FromSequence, - "NanoSpherical": NanoSpherical, - "Polynomial": Polynomial, - } -def _peakfunction_namespace(): - """Return the peak-function classes supported by the CLI.""" - from diffpy.srmise.peaks.gaussian import Gaussian - from diffpy.srmise.peaks.gaussianoverr import GaussianOverR - from diffpy.srmise.peaks.terminationripples import TerminationRipples - - return { - "Gaussian": Gaussian, - "GaussianOverR": GaussianOverR, - "TerminationRipples": TerminationRipples, - } - - -def _modelevaluator_namespace(): - """Return the model evaluators supported by the CLI.""" - from diffpy.srmise.modelevaluators.aic import AIC - from diffpy.srmise.modelevaluators.aicc import AICc - - return { - "AIC": AIC, - "AICc": AICc, - } - def main(): """Default SrMise entry-point.""" @@ -490,10 +436,7 @@ def main(): if options.peakfunction: try: - options.peakfunction = _resolve_cli_expression( - options.peakfunction, - _peakfunction_namespace(), - ) + options.peakfunction = eval("peaks." + options.peakfunction) except Exception as err: print(err) print("Could not create peak function '%s'. Exiting." % options.peakfunction) @@ -501,10 +444,7 @@ def main(): if options.modelevaluator: try: - options.modelevaluator = _resolve_cli_expression( - options.modelevaluator, - _modelevaluator_namespace(), - ) + options.modelevaluator = eval("modelevaluators." + options.modelevaluator) except Exception as err: print(err) print("Could not find ModelEvaluator '%s'. Exiting." % options.modelevaluator) @@ -546,16 +486,12 @@ def main(): bl = NanoSpherical() options.baseline = parsepars(bl, options.bspherical) - elif options.baseline: - try: - options.baseline = _resolve_cli_expression( - options.baseline, - _baseline_namespace(), - ) - except Exception as err: - print(err) - print("Could not create baseline '%s'. Exiting." % options.baseline) - return + try: + options.baseline = eval("baselines." + options.baseline) + except Exception as err: + print(err) + print("Could not create baseline '%s'. Exiting." % options.baseline) + return filename = args[0] From 0f3f7898b481c1dcebf170884929f83efa5d3429 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 22:31:59 +0000 Subject: [PATCH 06/12] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/srmise/applications/extract.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/diffpy/srmise/applications/extract.py b/src/diffpy/srmise/applications/extract.py index 10a2de2..2791367 100755 --- a/src/diffpy/srmise/applications/extract.py +++ b/src/diffpy/srmise/applications/extract.py @@ -18,9 +18,6 @@ import numpy as np - - - def main(): """Default SrMise entry-point.""" From b127396f71ef3e641a2688eb0c5d24b96bb8fec4 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 8 Apr 2026 18:33:36 -0400 Subject: [PATCH 07/12] chore: revert try except block --- src/diffpy/srmise/applications/extract.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/diffpy/srmise/applications/extract.py b/src/diffpy/srmise/applications/extract.py index 2791367..f79e9b1 100755 --- a/src/diffpy/srmise/applications/extract.py +++ b/src/diffpy/srmise/applications/extract.py @@ -483,12 +483,12 @@ def main(): bl = NanoSpherical() options.baseline = parsepars(bl, options.bspherical) - try: - options.baseline = eval("baselines." + options.baseline) - except Exception as err: - print(err) - print("Could not create baseline '%s'. Exiting." % options.baseline) - return + try: + options.baseline = eval("baselines." + options.baseline) + except Exception as err: + print(err) + print("Could not create baseline '%s'. Exiting." % options.baseline) + return filename = args[0] From 7863722baa6b97991c745ec7bd2ac69ba028d3e8 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 8 Apr 2026 21:01:41 -0400 Subject: [PATCH 08/12] some proper fix to the code --- src/diffpy/srmise/applications/extract.py | 31 +++++++++++++++---- src/diffpy/srmise/modelcluster.py | 4 +-- src/diffpy/srmise/modelevaluators/aic.py | 6 ++-- src/diffpy/srmise/peaks/gaussianoverr.py | 2 +- src/diffpy/srmise/peaks/terminationripples.py | 4 +-- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/diffpy/srmise/applications/extract.py b/src/diffpy/srmise/applications/extract.py index f79e9b1..adcd865 100755 --- a/src/diffpy/srmise/applications/extract.py +++ b/src/diffpy/srmise/applications/extract.py @@ -18,6 +18,21 @@ import numpy as np +def _baseline_namespace(): + """Return the baseline classes supported by the CLI.""" + from diffpy.srmise.baselines.arbitrary import Arbitrary + from diffpy.srmise.baselines.fromsequence import FromSequence + from diffpy.srmise.baselines.nanospherical import NanoSpherical + from diffpy.srmise.baselines.polynomial import Polynomial + + return { + "Arbitrary": Arbitrary, + "FromSequence": FromSequence, + "NanoSpherical": NanoSpherical, + "Polynomial": Polynomial, + } + + def main(): """Default SrMise entry-point.""" @@ -483,12 +498,16 @@ def main(): bl = NanoSpherical() options.baseline = parsepars(bl, options.bspherical) - try: - options.baseline = eval("baselines." + options.baseline) - except Exception as err: - print(err) - print("Could not create baseline '%s'. Exiting." % options.baseline) - return + try: + options.baseline = eval( + options.baseline, + {"__builtins__": {}}, + _baseline_namespace(), + ) + except Exception as err: + print(err) + print("Could not create baseline '%s'. Exiting." % options.baseline) + return filename = args[0] diff --git a/src/diffpy/srmise/modelcluster.py b/src/diffpy/srmise/modelcluster.py index de264fb..21a284d 100644 --- a/src/diffpy/srmise/modelcluster.py +++ b/src/diffpy/srmise/modelcluster.py @@ -1538,8 +1538,8 @@ def prune(self): # Create model with ith peak removed, and distant peaks effectively fixed lo = max(i - peak_range, 0) hi = min(i + peak_range + 1, len(best_model)) - check_models[i] = type(best_model)(best_model[lo:i]).copy() - check_models[i].extend(type(best_model)(best_model[i + 1 : hi]).copy()) + check_models[i] = best_model[lo:i].copy() + check_models[i].extend(best_model[i + 1: hi].copy()) prune_mc.model = check_models[i] msg = [ diff --git a/src/diffpy/srmise/modelevaluators/aic.py b/src/diffpy/srmise/modelevaluators/aic.py index d04e4d2..1fd7d5e 100644 --- a/src/diffpy/srmise/modelevaluators/aic.py +++ b/src/diffpy/srmise/modelevaluators/aic.py @@ -85,7 +85,7 @@ def evaluate(self, fit, count_fixed=False, kshift=0): if self.chisq is None: self.chisq = self.chi_squared(fit.value(), fit.y_cluster, fit.error_cluster) - self.stat = self.chisq + self.parpenalty(k, n) + self.stat = self.chisq + self.parpenalty(k) return self.stat @@ -106,7 +106,7 @@ def minpoints(self, npars): return 1 - def parpenalty(self, k, n=None): + def parpenalty(self, k): """Returns the cost for adding k parameters to the current model cluster. @@ -169,7 +169,7 @@ def growth_justified(self, fit, k_prime): logger.warning("AIC.growth_justified(): too few data to evaluate quality reliably.") n = self.minpoints(k_actual) - penalty = self.parpenalty(k_test, n) - self.parpenalty(k_actual, n) + penalty = self.parpenalty(k_test) - self.parpenalty(k_actual) return penalty < self.chisq diff --git a/src/diffpy/srmise/peaks/gaussianoverr.py b/src/diffpy/srmise/peaks/gaussianoverr.py index 3333e7a..b3237a4 100644 --- a/src/diffpy/srmise/peaks/gaussianoverr.py +++ b/src/diffpy/srmise/peaks/gaussianoverr.py @@ -534,7 +534,7 @@ def max(self, pars): guesspars = [[2.7, 0.15, 5], [3.7, 0.3, 5]] guess_peaks = Peaks([pf.actualize(p, "pwa") for p in guesspars]) - cluster = ModelCluster(guess_peaks, r, y, err, None, AICc, [pf]) + cluster = ModelCluster(guess_peaks, None, r, y, err, None, AICc, [pf]) qual1 = cluster.quality() print(qual1.stat) diff --git a/src/diffpy/srmise/peaks/terminationripples.py b/src/diffpy/srmise/peaks/terminationripples.py index 7d75195..6749014 100644 --- a/src/diffpy/srmise/peaks/terminationripples.py +++ b/src/diffpy/srmise/peaks/terminationripples.py @@ -416,12 +416,12 @@ def extend_grid(self, r, dr): guesspars = [[2.7, 0.15, 5], [3.7, 0.3, 5]] guess_peaks = Peaks([pf2.actualize(p, "pwa") for p in guesspars]) - cluster = ModelCluster(guess_peaks, r, y_ripple, err, None, AICc, [pf2]) + cluster = ModelCluster(guess_peaks, None, r, y_ripple, err, None, AICc, [pf2]) qual1 = cluster.quality() print(qual1.stat) cluster.fit() - yfit = cluster.calc() + yfit = cluster.valuebl() qual2 = cluster.quality() print(qual2.stat) From 1fbfa0aa4de6a5f46bba9078941d2dd082db17f2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 01:02:00 +0000 Subject: [PATCH 09/12] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/srmise/modelcluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffpy/srmise/modelcluster.py b/src/diffpy/srmise/modelcluster.py index 21a284d..abefffb 100644 --- a/src/diffpy/srmise/modelcluster.py +++ b/src/diffpy/srmise/modelcluster.py @@ -1539,7 +1539,7 @@ def prune(self): lo = max(i - peak_range, 0) hi = min(i + peak_range + 1, len(best_model)) check_models[i] = best_model[lo:i].copy() - check_models[i].extend(best_model[i + 1: hi].copy()) + check_models[i].extend(best_model[i + 1 : hi].copy()) prune_mc.model = check_models[i] msg = [ From c3d99843c162338383024c6e80af6377ff8eddfa Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Wed, 8 Apr 2026 22:14:09 -0400 Subject: [PATCH 10/12] fix: fix fetch qmax --- src/diffpy/srmise/pdfpeakextraction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diffpy/srmise/pdfpeakextraction.py b/src/diffpy/srmise/pdfpeakextraction.py index f0c50cd..6f04cc6 100644 --- a/src/diffpy/srmise/pdfpeakextraction.py +++ b/src/diffpy/srmise/pdfpeakextraction.py @@ -247,7 +247,7 @@ def defaultvars(self, *args): # Enable "dg" as alias for "effective_dy" if "dg" in args and "effective_dy" not in args: - nargs.add("effective_dy") + nargs.append("effective_dy") # Set other defaults PeakExtraction.defaultvars(self, *nargs) @@ -1000,7 +1000,7 @@ def find_qmax(r, y, showgraphs=False): new_y = resample(r, y, new_r) new_dr = (new_r[-1] - r[0]) / (len(new_r) - 1) - yfft = np.imag(np.fft.fft(new_y))[: len(new_y) / 2] + yfft = np.imag(np.fft.fft(new_y))[: len(new_y) // 2] d_ratio = stdratio(yfft) From cd002f31f019e98ff80a4b0003c7647a08c55018 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Thu, 9 Apr 2026 00:13:53 -0400 Subject: [PATCH 11/12] fix: correctly fix the single peak plot issue with correct plot --- src/diffpy/srmise/modelevaluators/base.py | 8 ++++---- src/diffpy/srmise/peaks/gaussian.py | 4 ++-- src/diffpy/srmise/peaks/gaussianoverr.py | 2 +- src/diffpy/srmise/peaks/terminationripples.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/diffpy/srmise/modelevaluators/base.py b/src/diffpy/srmise/modelevaluators/base.py index f190e27..a55df58 100644 --- a/src/diffpy/srmise/modelevaluators/base.py +++ b/src/diffpy/srmise/modelevaluators/base.py @@ -76,7 +76,7 @@ def __lt__(self, other): assert self.method == other.method # Comparison between same types required assert self.stat is not None and other.stat is not None # The statistic must already be calculated - if self.higher_is_better is not None: + if self.higher_is_better: return self.stat < other.stat else: return other.stat < self.stat @@ -87,7 +87,7 @@ def __le__(self, other): assert self.method == other.method # Comparison between same types required assert self.stat is not None and other.stat is not None # The statistic must already be calculated - if self.higher_is_better is not None: + if self.higher_is_better: return self.stat <= other.stat else: return other.stat <= self.stat @@ -114,7 +114,7 @@ def __gt__(self, other): assert self.method == other.method # Comparison between same types required assert self.stat is not None and other.stat is not None # The statistic must already be calculated - if self.higher_is_better is not None: + if self.higher_is_better: return self.stat > other.stat else: return other.stat > self.stat @@ -125,7 +125,7 @@ def __ge__(self, other): assert self.method == other.method # Comparison between same types required assert self.stat is not None and other.stat is not None # The statistic must already be calculated - if self.higher_is_better is not None: + if self.higher_is_better: return self.stat >= other.stat else: return other.stat >= self.stat diff --git a/src/diffpy/srmise/peaks/gaussian.py b/src/diffpy/srmise/peaks/gaussian.py index abf2a08..b992b2f 100644 --- a/src/diffpy/srmise/peaks/gaussian.py +++ b/src/diffpy/srmise/peaks/gaussian.py @@ -464,12 +464,12 @@ def max(self, pars): guesspars = [[2.7, 0.15, 5], [3.7, 0.3, 5]] guess_peaks = Peaks([pf.actualize(p, "pwa") for p in guesspars]) - cluster = ModelCluster(guess_peaks, r, y, err, None, AICc, [pf]) + cluster = ModelCluster(guess_peaks, None, r, y, err, None, AICc, [pf]) qual1 = cluster.quality() print(qual1.stat) cluster.fit() - yfit = cluster.calc() + yfit = cluster.value() qual2 = cluster.quality() print(qual2.stat) diff --git a/src/diffpy/srmise/peaks/gaussianoverr.py b/src/diffpy/srmise/peaks/gaussianoverr.py index b3237a4..c8f29d0 100644 --- a/src/diffpy/srmise/peaks/gaussianoverr.py +++ b/src/diffpy/srmise/peaks/gaussianoverr.py @@ -539,7 +539,7 @@ def max(self, pars): qual1 = cluster.quality() print(qual1.stat) cluster.fit() - yfit = cluster.calc() + yfit = cluster.value() qual2 = cluster.quality() print(qual2.stat) diff --git a/src/diffpy/srmise/peaks/terminationripples.py b/src/diffpy/srmise/peaks/terminationripples.py index 6749014..7a4a7d3 100644 --- a/src/diffpy/srmise/peaks/terminationripples.py +++ b/src/diffpy/srmise/peaks/terminationripples.py @@ -421,7 +421,7 @@ def extend_grid(self, r, dr): qual1 = cluster.quality() print(qual1.stat) cluster.fit() - yfit = cluster.valuebl() + yfit = cluster.value() qual2 = cluster.quality() print(qual2.stat) From 36e673308a7b7068c07fc1a092c0f5880be540cd Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Thu, 9 Apr 2026 00:40:59 -0400 Subject: [PATCH 12/12] fix: fix namespace when we have --no-extract option --- src/diffpy/srmise/applications/extract.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/diffpy/srmise/applications/extract.py b/src/diffpy/srmise/applications/extract.py index adcd865..16c0cc5 100755 --- a/src/diffpy/srmise/applications/extract.py +++ b/src/diffpy/srmise/applications/extract.py @@ -498,16 +498,17 @@ def main(): bl = NanoSpherical() options.baseline = parsepars(bl, options.bspherical) - try: - options.baseline = eval( - options.baseline, - {"__builtins__": {}}, - _baseline_namespace(), - ) - except Exception as err: - print(err) - print("Could not create baseline '%s'. Exiting." % options.baseline) - return + elif options.baseline is not None: + try: + options.baseline = eval( + options.baseline, + {"__builtins__": {}}, + _baseline_namespace(), + ) + except Exception as err: + print(err) + print("Could not create baseline '%s'. Exiting." % options.baseline) + return filename = args[0]