Skip to content
Open
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
23 changes: 23 additions & 0 deletions news/fix-single-peak.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* <news item>

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* Fixed extracting single peak with `py2` legacy cleanup

**Security:**

* <news item>
75 changes: 70 additions & 5 deletions src/diffpy/srmise/applications/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""

Expand Down Expand Up @@ -433,15 +490,21 @@ 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)
return

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)
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/diffpy/srmise/dataclusters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down Expand Up @@ -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
Expand All @@ -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]):
Expand Down
6 changes: 3 additions & 3 deletions src/diffpy/srmise/modelcluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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 = [
Expand Down
2 changes: 1 addition & 1 deletion src/diffpy/srmise/modelevaluators/aic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 3 additions & 2 deletions src/diffpy/srmise/modelparts.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions src/diffpy/srmise/pdfpeakextraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand Down
4 changes: 2 additions & 2 deletions src/diffpy/srmise/peakextraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/diffpy/srmise/peaks/terminationripples.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Loading