Skip to content

Commit 97383a0

Browse files
committed
Clarity update
1 parent b6136cf commit 97383a0

File tree

4 files changed

+56
-85
lines changed

4 files changed

+56
-85
lines changed

src/diffpy/morph/morph_io.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -447,17 +447,13 @@ def handle_extrapolation_warnings(morph):
447447

448448
def handle_check_increase_warning(squeeze_morph):
449449
if squeeze_morph is not None:
450-
if squeeze_morph.strictly_increasing:
451-
wmsg = None
452-
else:
450+
if not squeeze_morph.strictly_increasing:
453451
wmsg = (
454452
"Warning: The squeeze morph has interpolated your morphed "
455453
"function from a non-monotonically increasing grid. "
456-
"This can result in strange behavior in the non-unique "
457-
"grid regions. To disable this setting, "
458-
"please enable --check-increasing."
454+
"This can result in strange behavior in certain "
455+
"grid regions."
459456
)
460-
if wmsg:
461457
warnings.warn(
462458
wmsg,
463459
UserWarning,

src/diffpy/morph/morphpy.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def __get_morph_opts__(parser, scale, stretch, smear, plot, **kwargs):
5151
"reverse",
5252
"diff",
5353
"get-diff",
54-
"check-increase",
5554
]
5655
opts_to_ignore = ["multiple-morphs", "multiple-targets"]
5756
for opt in opts_storing_values:

src/diffpy/morph/morphs/morphsqueeze.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class MorphSqueeze(Morph):
7373
def __init__(self, config=None):
7474
super().__init__(config)
7575

76-
def _ensure_strictly_increase(self, x, x_sorted):
76+
def _check_strictly_increasing(self, x, x_sorted):
7777
if list(x) != list(x_sorted):
7878
self.strictly_increasing = False
7979
else:
@@ -83,20 +83,20 @@ def _sort_squeeze(self, x, y):
8383
"""Sort x,y according to the value of x."""
8484
xy = list(zip(x, y))
8585
xy_sorted = sorted(xy, key=lambda pair: pair[0])
86-
x_sorted, y_sorted = list(zip(*xy_sorted))
86+
x_sorted, y_sorted = numpy.array(list(zip(*xy_sorted)))
8787
return x_sorted, y_sorted
8888

8989
def _handle_duplicates(self, x, y):
9090
"""Remove duplicated x and use the mean value of y corresponded
9191
to the duplicated x."""
92-
unq_x, unq_inv = numpy.unique(x, return_inverse=True)
93-
if len(unq_x) == len(x):
92+
x_unique, inv = numpy.unique(x, return_inverse=True)
93+
if len(x_unique) == len(x):
9494
return x, y
9595
else:
96-
y_avg = numpy.zeros_like(unq_x)
97-
for i in range(len(unq_x)):
98-
y_avg[i] = numpy.array(y)[unq_inv == i].mean()
99-
return unq_x, y_avg
96+
y_avg = numpy.zeros_like(x_unique)
97+
for idx, _ in enumerate(x_unique):
98+
y_avg[idx] = y[inv == idx].mean()
99+
return x_unique, y_avg
100100

101101
def morph(self, x_morph, y_morph, x_target, y_target):
102102
"""Apply a polynomial to squeeze the morph function.
@@ -112,7 +112,7 @@ def morph(self, x_morph, y_morph, x_target, y_target):
112112
x_squeezed_sorted, y_morph_sorted = self._sort_squeeze(
113113
x_squeezed, self.y_morph_in
114114
)
115-
self._ensure_strictly_increase(x_squeezed, x_squeezed_sorted)
115+
self._check_strictly_increasing(x_squeezed, x_squeezed_sorted)
116116
x_squeezed_sorted, y_morph_sorted = self._handle_duplicates(
117117
x_squeezed_sorted, y_morph_sorted
118118
)

tests/test_morphsqueeze.py

Lines changed: 44 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -172,80 +172,56 @@ def test_morphsqueeze_extrapolate(user_filesystem, squeeze_coeffs, wmsg_gen):
172172
single_morph(parser, opts, pargs, stdout_flag=False)
173173

174174

175-
@pytest.mark.parametrize(
176-
"squeeze_coeffs, x_morph",
177-
[
178-
({"a0": 0.01, "a1": 0.01, "a2": -0.1}, np.linspace(0, 10, 101)),
179-
],
180-
)
181-
def test_non_strictly_increasing_squeeze(squeeze_coeffs, x_morph):
182-
x_target = x_morph
183-
y_target = np.sin(x_target)
175+
def test_non_unique_grid():
176+
squeeze_coeffs = {"a0": 0.01, "a1": 0.01, "a2": -0.1}
177+
x_grid = np.linspace(0, 10, 101)
178+
184179
coeffs = [squeeze_coeffs[f"a{i}"] for i in range(len(squeeze_coeffs))]
185180
squeeze_polynomial = Polynomial(coeffs)
186-
x_squeezed = x_morph + squeeze_polynomial(x_morph)
187-
# non-strictly-increasing
188-
assert not np.all(np.sign(np.diff(x_squeezed)) > 0)
189-
y_morph = np.sin(x_squeezed)
190-
# all zero initial guess
191-
morph_results = morphpy.morph_arrays(
181+
x_morph = x_grid + squeeze_polynomial(x_grid)
182+
x_gradient = np.diff(x_morph)
183+
x_gradient_sign = np.sign(x_gradient)
184+
# non-strictly increasing means the gradient becomes 0 or negative
185+
assert not np.all(x_gradient_sign > 0)
186+
187+
x_target = np.linspace(min(x_morph), max(x_morph), len(x_morph))
188+
y_target = np.sin(x_target)
189+
190+
y_morph = np.sin(x_morph)
191+
# apply no squeeze, but the morph should sort the function
192+
_, table = morphpy.morph_arrays(
192193
np.array([x_morph, y_morph]).T,
193194
np.array([x_target, y_target]).T,
194-
squeeze=[0, 0, 0],
195+
squeeze=[0, 0, 0.0001],
195196
apply=True,
196197
)
197-
_, y_morph_actual = morph_results[1].T # noqa: F841
198-
y_morph_expected = np.sin(x_morph) # noqa: F841
199-
# squeeze morph extrapolates.
200-
# Need to extract extrap_index from morph_results to examine
201-
# the convergence.
202-
# assert np.allclose(y_morph_actual, y_morph_expected, atol=1e-3)
203-
# Raise warning when called without --check-increase
204-
with pytest.warns() as w:
205-
morph_results = morphpy.morph_arrays(
206-
np.array([x_morph, y_morph]).T,
207-
np.array([x_target, y_target]).T,
208-
squeeze=[0.01, 0.01, -0.1],
209-
apply=True,
210-
)
211-
assert w[0].category is UserWarning
212-
actual_wmsg = " ".join([str(w[i].message) for i in range(len(w))])
213-
expected_wmsg = (
214-
"Warning: The squeeze morph has interpolated your morphed "
215-
"function from a non-monotonically increasing grid. "
216-
)
217-
assert expected_wmsg in actual_wmsg
218-
_, y_morph_actual = morph_results[1].T # noqa: F841
219-
y_morph_expected = np.sin(x_morph) # noqa: F841
220-
# squeeze morph extrapolates.
221-
# Need to extract extrap_index from morph_results to examine
222-
# the convergence.
223-
# assert np.allclose(y_morph_actual, y_morph_expected, atol=1e-3)
224-
# System exits when called with --check-increase
225-
with pytest.raises(SystemExit) as excinfo:
226-
morphpy.morph_arrays(
227-
np.array([x_morph, y_morph]).T,
228-
np.array([x_target, y_target]).T,
229-
squeeze=[0.01, 0.009, -0.1],
230-
check_increase=True,
231-
)
232-
actual_emsg = str(excinfo.value)
233-
expected_emsg = "2"
234-
assert expected_emsg == actual_emsg
198+
x_refined, y_refined = table[:, 0], table[:, 1]
199+
200+
# grid should be properly sorted
201+
assert np.allclose(x_refined, x_target)
202+
203+
print(y_refined, y_target)
204+
x_sorted = x_morph.copy()
205+
x_sorted.sort()
206+
print(x_morph)
207+
print(x_sorted)
208+
# function values
209+
assert np.allclose(y_refined, y_target)
235210

236211

237212
@pytest.mark.parametrize(
238213
"squeeze_coeffs, x_morph",
239214
[
215+
# The following squeezes make the function non-monotonic
240216
({"a0": -1, "a1": -1, "a2": 2}, np.linspace(-1, 1, 101)),
241217
(
242218
{"a0": -1, "a1": -1, "a2": 0, "a3": 0, "a4": 2},
243219
np.linspace(-1, 1, 101),
244220
),
245221
],
246222
)
247-
def test_sort_squeeze_bad(user_filesystem, squeeze_coeffs, x_morph):
248-
# call in .py without --check-increase
223+
def test_squeeze_warnings(user_filesystem, squeeze_coeffs, x_morph):
224+
# call in .py
249225
x_target = x_morph
250226
y_target = np.sin(x_target)
251227
coeffs = [squeeze_coeffs[f"a{i}"] for i in range(len(squeeze_coeffs))]
@@ -267,10 +243,12 @@ def test_sort_squeeze_bad(user_filesystem, squeeze_coeffs, x_morph):
267243
expected_wmsg = (
268244
"Warning: The squeeze morph has interpolated your morphed "
269245
"function from a non-monotonically increasing grid. "
246+
"This can result in strange behavior in certain "
247+
"grid regions."
270248
)
271249
assert expected_wmsg in actual_wmsg
272250

273-
# call in CLI without --check-increase
251+
# call in CLI
274252
morph_file, target_file = create_morph_data_file(
275253
user_filesystem / "cwd_dir", x_morph, y_morph, x_target, y_target
276254
)
@@ -293,18 +271,16 @@ def test_sort_squeeze_bad(user_filesystem, squeeze_coeffs, x_morph):
293271

294272

295273
def test_handle_duplicates():
296-
unq_x = np.linspace(0, 11, 10)
274+
x_choices = np.linspace(0, 10, 11)
297275
iter = 10
298276
morph = MorphSqueeze()
299277
for i in range(iter):
300-
actual_x = np.random.choice(unq_x, size=20)
301-
actual_y = np.sin(actual_x)
302-
actual_handled_x, actual_handled_y = morph._handle_duplicates(
303-
actual_x, actual_y
304-
)
305-
expected_handled_x = np.unique(actual_x)
306-
expected_handled_y = np.array(
307-
[actual_y[actual_x == x].mean() for x in expected_handled_x]
278+
x_sampled = np.random.choice(x_choices, size=20)
279+
y_sampled = np.sin(x_sampled)
280+
x_handled, y_handled = morph._handle_duplicates(x_sampled, y_sampled)
281+
x_target = np.unique(x_sampled)
282+
y_target = np.array(
283+
[y_sampled[x_sampled == x].mean() for x in x_target]
308284
)
309-
assert np.allclose(actual_handled_x, expected_handled_x)
310-
assert np.allclose(actual_handled_y, expected_handled_y)
285+
assert np.allclose(x_handled, x_target)
286+
assert np.allclose(y_handled, y_target)

0 commit comments

Comments
 (0)