Skip to content

Commit f47e167

Browse files
committed
Test/funct: trim target data to overlapping region and added more test
1 parent d42d234 commit f47e167

File tree

2 files changed

+92
-17
lines changed

2 files changed

+92
-17
lines changed

src/diffpy/morph/morphs/morphsqueeze.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
from numpy.polynomial import Polynomial
23
from scipy.interpolate import CubicSpline
34

@@ -7,7 +8,12 @@
78
class MorphSqueeze(Morph):
89
"""Squeeze the morph function.
910
10-
This applies a polynomial to squeeze the morph non-linearly.
11+
This applies a polynomial to squeeze the morph non-linearly. The resulting
12+
squeezed morph is interpolated to the (trimmed) target grid.
13+
Only the overlapping region between the squeezed morph and the target
14+
grid is used. The target is trimmed (or not) accordingly, and the final
15+
outputs (morph and target) are returned on the same grid, defined by this
16+
trimmed target range.
1117
1218
Configuration Variables
1319
-----------------------
@@ -33,11 +39,14 @@ def morph(self, x_morph, y_morph, x_target, y_target):
3339

3440
squeeze_polynomial = Polynomial(self.squeeze)
3541
x_squeezed = self.x_morph_in + squeeze_polynomial(self.x_morph_in)
42+
x_min = max(float(self.x_target_in[0]), float(x_squeezed[0]))
43+
x_max = min(float(self.x_target_in[-1]), float(x_squeezed[-1]))
44+
min_index = np.where(self.x_target_in >= x_min)[0][0]
45+
max_index = np.where(self.x_target_in <= x_max)[0][-1]
46+
self.x_target_out = self.x_target_in[min_index : max_index + 1]
47+
self.y_target_out = self.y_target_in[min_index : max_index + 1]
3648
self.y_morph_out = CubicSpline(x_squeezed, self.y_morph_in)(
37-
self.x_morph_in
49+
self.x_target_out
3850
)
39-
self.y_morph_out = CubicSpline(self.x_morph_in, self.y_morph_out)(
40-
self.x_target_in
41-
)
42-
self.x_morph_out = self.x_target_in
51+
self.x_morph_out = self.x_target_out
4352
return self.xyallout

tests/test_morphsqueeze.py

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,87 @@
2727
[0, 0, 0, 0, 0, 0],
2828
],
2929
)
30-
def test_morphsqueeze(squeeze_coeffs):
31-
x_target_expected = np.linspace(0, 10, 101)
32-
y_target_expected = np.sin(x_target_expected)
33-
# Different grid for morph data to test inputs with different grids
34-
# Morph grid must be finer than the target to avoid interpolation issues
35-
x_morph = np.linspace(-3, 13, 301)
30+
def test_morphsqueeze_target_extends_beyond_morph(squeeze_coeffs):
31+
# Target data extends beyond morph and different grids
32+
x_target = np.linspace(-3, 25, 401)
33+
y_target = np.sin(x_target)
34+
x_morph = np.linspace(0, 10, 301)
3635
squeeze_polynomial = Polynomial(squeeze_coeffs)
3736
x_squeezed = x_morph + squeeze_polynomial(x_morph)
3837
y_morph = np.sin(x_squeezed)
38+
# Trim target data to the region overlapping with the squeezed morph
39+
x_min = max(float(x_target[0]), float(x_squeezed[0]))
40+
x_max = min(float(x_target[-1]), float(x_squeezed[-1]))
41+
min_index = np.where(x_target >= x_min)[0][0]
42+
max_index = np.where(x_target <= x_max)[0][-1]
43+
x_morph_expected = x_target[min_index : max_index + 1]
44+
y_morph_expected = y_target[min_index : max_index + 1]
3945
morph = MorphSqueeze()
4046
morph.squeeze = squeeze_coeffs
4147
x_morph_actual, y_morph_actual, x_target_actual, y_target_actual = morph(
42-
x_morph, y_morph, x_target_expected, y_target_expected
48+
x_morph, y_morph, x_target, y_target
4349
)
44-
assert np.allclose(y_morph_actual, y_target_expected)
45-
assert np.allclose(x_morph_actual, x_target_expected)
46-
assert np.allclose(x_target_actual, x_target_expected)
47-
assert np.allclose(y_target_actual, y_target_expected)
50+
assert np.allclose(y_morph_actual, y_morph_expected)
51+
assert np.allclose(x_morph_actual, x_morph_expected)
52+
assert np.allclose(x_target_actual, x_morph_expected)
53+
assert np.allclose(y_target_actual, y_morph_expected)
54+
55+
import matplotlib.pyplot as plt
56+
57+
plt.figure()
58+
plt.plot(x_target, y_target, color="gray", label="target")
59+
plt.plot(x_morph, y_morph, color="black", label="morph")
60+
plt.scatter(x_morph_actual, y_morph_actual, color="gold", label="actual")
61+
plt.plot(
62+
x_morph_expected, y_morph_expected, color="purple", label="expected"
63+
)
64+
plt.legend()
65+
plt.show()
66+
67+
68+
@pytest.mark.parametrize(
69+
"squeeze_coeffs",
70+
[
71+
# The order of coefficients is [a0, a1, a2, ..., an]
72+
# Negative cubic squeeze coefficients
73+
[-0.2, -0.01, -0.001, -0.001],
74+
# Positive cubic squeeze coefficients
75+
[0.2, 0.01, 0.001, 0.001],
76+
# Positive and negative cubic squeeze coefficients
77+
[0.2, -0.01, 0.002, -0.001],
78+
# Quadratic squeeze coefficients
79+
[-0.2, 0.005, -0.007],
80+
# Linear squeeze coefficients
81+
[0.1, 0.3],
82+
# 4th order squeeze coefficients
83+
[0.2, -0.01, 0.001, -0.001, 0.0004],
84+
# Zeros and non-zeros, the full polynomial is applied
85+
[0, 0.03, 0, -0.001],
86+
# Testing zeros, expect no squeezing
87+
[0, 0, 0, 0, 0, 0],
88+
],
89+
)
90+
def test_morphsqueeze_morph_extends_beyond_target(squeeze_coeffs):
91+
# Different grid for morph and target data to test different grids
92+
x_target = np.linspace(0, 10, 101)
93+
y_target = np.sin(x_target)
94+
x_morph = np.linspace(-3, 15, 301)
95+
squeeze_polynomial = Polynomial(squeeze_coeffs)
96+
x_squeezed = x_morph + squeeze_polynomial(x_morph)
97+
y_morph = np.sin(x_squeezed)
98+
# Trim target data to the region overlapping with the squeezed morph
99+
x_min = max(float(x_target[0]), float(x_squeezed[0]))
100+
x_max = min(float(x_target[-1]), float(x_squeezed[-1]))
101+
min_index = np.where(x_target >= x_min)[0][0]
102+
max_index = np.where(x_target <= x_max)[0][-1]
103+
x_morph_expected = x_target[min_index : max_index + 1]
104+
y_morph_expected = y_target[min_index : max_index + 1]
105+
morph = MorphSqueeze()
106+
morph.squeeze = squeeze_coeffs
107+
x_morph_actual, y_morph_actual, x_target_actual, y_target_actual = morph(
108+
x_morph, y_morph, x_target, y_target
109+
)
110+
assert np.allclose(y_morph_actual, y_morph_expected)
111+
assert np.allclose(x_morph_actual, x_morph_expected)
112+
assert np.allclose(x_target_actual, x_morph_expected)
113+
assert np.allclose(y_target_actual, y_morph_expected)

0 commit comments

Comments
 (0)