Skip to content

Commit eb95c00

Browse files
committed
Final testing suite
1 parent 754d9db commit eb95c00

File tree

6 files changed

+213
-140
lines changed

6 files changed

+213
-140
lines changed

src/diffpy/morph/morphs/morphrgrid.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,21 @@ class MorphRGrid(Morph):
5151
youtlabel = LABEL_GR
5252
parnames = ["rmin", "rmax", "rstep"]
5353

54+
# Define rmin rmax holders for adaptive x-grid refinement
55+
# Without these, the program r-grid can only decrease in interval size
56+
rmin_origin = None
57+
rmax_origin = None
58+
rstep_origin = None
59+
5460
def morph(self, x_morph, y_morph, x_target, y_target):
5561
"""Resample arrays onto specified grid."""
62+
if self.rmin is not None:
63+
self.rmin_origin = self.rmin
64+
if self.rmax is not None:
65+
self.rmax_origin = self.rmax
66+
if self.rstep is not None:
67+
self.rstep_origin = self.rstep
68+
5669
Morph.morph(self, x_morph, y_morph, x_target, y_target)
5770
rmininc = max(min(self.x_target_in), min(self.x_morph_in))
5871
r_step_target = (max(self.x_target_in) - min(self.x_target_in)) / (
@@ -66,11 +79,11 @@ def morph(self, x_morph, y_morph, x_target, y_target):
6679
max(self.x_target_in) + r_step_target,
6780
max(self.x_morph_in) + r_step_morph,
6881
)
69-
if self.rmin is None or self.rmin < rmininc:
82+
if self.rmin_origin is None or self.rmin_origin < rmininc:
7083
self.rmin = rmininc
71-
if self.rmax is None or self.rmax > rmaxinc:
84+
if self.rmax_origin is None or self.rmax_origin > rmaxinc:
7285
self.rmax = rmaxinc
73-
if self.rstep is None or self.rstep < rstepinc:
86+
if self.rstep_origin is None or self.rstep_origin < rstepinc:
7487
self.rstep = rstepinc
7588
# roundoff tolerance for selecting bounds on arrays.
7689
epsilon = self.rstep / 2

src/diffpy/morph/refine.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,11 @@ def _residual(self, pvals):
9696
rvec.extend([0] * diff_length)
9797
rvec = array(rvec)
9898
# Removal
99+
# For removal, pass the average RMS
100+
# This is fast and easy to compute
101+
# For sufficiently functions, this approximation becomes exact
99102
elif len(rvec) > self.res_length:
100-
avg_rms = sum(rvec**2) / self.res_length
103+
avg_rms = sum(rvec**2) / len(rvec)
101104
rvec = array([avg_rms for _ in range(self.res_length)])
102105

103106
return rvec

tests/test_morphfuncx.py

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,63 @@
11
import numpy as np
22
import pytest
33

4-
# from diffpy.morph.morphs.morphfuncx import MorphFuncx
5-
from diffpy.morph.morphs.morphfuncy import MorphFuncy
4+
from diffpy.morph.morphs.morphfuncx import MorphFuncx
65

76

8-
def sine_function(x, y, amplitude, frequency):
9-
return amplitude * np.sin(frequency * x) * y
7+
def x_exponential_function(x, y, x_amplitude, x_rate):
8+
return x_amplitude * np.exp(x_rate * x)
109

1110

12-
def exponential_decay_function(x, y, amplitude, decay_rate):
13-
return amplitude * np.exp(-decay_rate * x) * y
11+
def x_linear_function(x, y, x_slope, x_intercept):
12+
return x_slope * x + x_intercept
1413

1514

16-
def gaussian_function(x, y, amplitude, mean, sigma):
17-
return amplitude * np.exp(-((x - mean) ** 2) / (2 * sigma**2)) * y
15+
def x_cubic_function(x, y, x_amplitude, x_shift):
16+
return x_amplitude * (x - x_shift) ** 3
1817

1918

20-
def polynomial_function(x, y, a, b, c):
21-
return (a * x**2 + b * x + c) * y
19+
def x_arctan_function(x, y, x_amplitude, x_frequency):
20+
return x_amplitude * np.arctan(x_frequency * x)
2221

2322

24-
def logarithmic_function(x, y, scale):
25-
return scale * np.log(1 + x) * y
23+
funcx_test_suite = [
24+
(
25+
x_exponential_function,
26+
{"x_amplitude": 2, "x_rate": 5},
27+
lambda x, y: 2 * np.exp(5 * x),
28+
),
29+
(
30+
x_linear_function,
31+
{"x_slope": 5, "x_intercept": 0.1},
32+
lambda x, y: 5 * x + 0.1,
33+
),
34+
(
35+
x_cubic_function,
36+
{"x_amplitude": 2, "x_shift": 5},
37+
lambda x, y: 2 * (x - 5) ** 3,
38+
),
39+
(
40+
x_arctan_function,
41+
{"x_amplitude": 4, "x_frequency": 2},
42+
lambda x, y: 4 * np.arctan(2 * x),
43+
),
44+
]
2645

2746

28-
# FIXME:
2947
@pytest.mark.parametrize(
3048
"function, parameters, expected_function",
31-
[
32-
(
33-
sine_function,
34-
{"amplitude": 2, "frequency": 5},
35-
lambda x, y: 2 * np.sin(5 * x) * y,
36-
),
37-
(
38-
exponential_decay_function,
39-
{"amplitude": 5, "decay_rate": 0.1},
40-
lambda x, y: 5 * np.exp(-0.1 * x) * y,
41-
),
42-
(
43-
gaussian_function,
44-
{"amplitude": 1, "mean": 5, "sigma": 1},
45-
lambda x, y: np.exp(-((x - 5) ** 2) / (2 * 1**2)) * y,
46-
),
47-
(
48-
polynomial_function,
49-
{"a": 1, "b": 2, "c": 0},
50-
lambda x, y: (x**2 + 2 * x) * y,
51-
),
52-
(
53-
logarithmic_function,
54-
{"scale": 0.5},
55-
lambda x, y: 0.5 * np.log(1 + x) * y,
56-
),
57-
],
49+
funcx_test_suite,
5850
)
5951
def test_funcy(function, parameters, expected_function):
6052
x_morph = np.linspace(0, 10, 101)
6153
y_morph = np.sin(x_morph)
6254
x_target = x_morph.copy()
6355
y_target = y_morph.copy()
64-
x_morph_expected = x_morph
65-
y_morph_expected = expected_function(x_morph, y_morph)
66-
morph = MorphFuncy()
67-
morph.funcy_function = function
68-
morph.funcy = parameters
56+
x_morph_expected = expected_function(x_morph, y_morph)
57+
y_morph_expected = y_morph
58+
morph = MorphFuncx()
59+
morph.funcx_function = function
60+
morph.funcx = parameters
6961
x_morph_actual, y_morph_actual, x_target_actual, y_target_actual = (
7062
morph.morph(x_morph, y_morph, x_target, y_target)
7163
)

tests/test_morphfuncxy.py

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,66 @@
11
import numpy as np
22
import pytest
33

4-
# from diffpy.morph.morphs.morphfuncxy import MorphFuncxy
5-
from diffpy.morph.morphs.morphfuncy import MorphFuncy
4+
from diffpy.morph.morphs.morphfuncxy import MorphFuncxy
65

6+
from .test_morphfuncx import funcx_test_suite
7+
from .test_morphfuncy import funcy_test_suite
78

8-
def sine_function(x, y, amplitude, frequency):
9-
return amplitude * np.sin(frequency * x) * y
10-
11-
12-
def exponential_decay_function(x, y, amplitude, decay_rate):
13-
return amplitude * np.exp(-decay_rate * x) * y
14-
15-
16-
def gaussian_function(x, y, amplitude, mean, sigma):
17-
return amplitude * np.exp(-((x - mean) ** 2) / (2 * sigma**2)) * y
18-
19-
20-
def polynomial_function(x, y, a, b, c):
21-
return (a * x**2 + b * x + c) * y
22-
23-
24-
def logarithmic_function(x, y, scale):
25-
return scale * np.log(1 + x) * y
9+
funcxy_test_suite = []
10+
for entry_y in funcy_test_suite:
11+
for entry_x in funcx_test_suite:
12+
funcxy_test_suite.append(
13+
(
14+
entry_x[0],
15+
entry_y[0],
16+
entry_x[1],
17+
entry_y[1],
18+
entry_x[2],
19+
entry_y[2],
20+
)
21+
)
2622

2723

2824
# FIXME:
2925
@pytest.mark.parametrize(
30-
"function, parameters, expected_function",
31-
[
32-
(
33-
sine_function,
34-
{"amplitude": 2, "frequency": 5},
35-
lambda x, y: 2 * np.sin(5 * x) * y,
36-
),
37-
(
38-
exponential_decay_function,
39-
{"amplitude": 5, "decay_rate": 0.1},
40-
lambda x, y: 5 * np.exp(-0.1 * x) * y,
41-
),
42-
(
43-
gaussian_function,
44-
{"amplitude": 1, "mean": 5, "sigma": 1},
45-
lambda x, y: np.exp(-((x - 5) ** 2) / (2 * 1**2)) * y,
46-
),
47-
(
48-
polynomial_function,
49-
{"a": 1, "b": 2, "c": 0},
50-
lambda x, y: (x**2 + 2 * x) * y,
51-
),
52-
(
53-
logarithmic_function,
54-
{"scale": 0.5},
55-
lambda x, y: 0.5 * np.log(1 + x) * y,
56-
),
57-
],
26+
"funcx_func, funcy_func, funcx_params, funcy_params, "
27+
"funcx_lambda, funcy_lambda",
28+
funcxy_test_suite,
5829
)
59-
def test_funcy(function, parameters, expected_function):
30+
def test_funcy(
31+
funcx_func,
32+
funcy_func,
33+
funcx_params,
34+
funcy_params,
35+
funcx_lambda,
36+
funcy_lambda,
37+
):
6038
x_morph = np.linspace(0, 10, 101)
6139
y_morph = np.sin(x_morph)
6240
x_target = x_morph.copy()
6341
y_target = y_morph.copy()
64-
x_morph_expected = x_morph
65-
y_morph_expected = expected_function(x_morph, y_morph)
66-
morph = MorphFuncy()
67-
morph.funcy_function = function
68-
morph.funcy = parameters
42+
x_morph_expected = funcx_lambda(x_morph, y_morph)
43+
y_morph_expected = funcy_lambda(x_morph, y_morph)
44+
45+
funcxy_params = {}
46+
funcxy_params.update(funcx_params)
47+
funcxy_params.update(funcy_params)
48+
49+
def funcxy_func(x, y, **funcxy_params):
50+
funcx_params = {}
51+
funcy_params = {}
52+
for param in funcxy_params.keys():
53+
if param[:2] == "x_":
54+
funcx_params.update({param: funcxy_params[param]})
55+
elif param[:2] == "y_":
56+
funcy_params.update({param: funcxy_params[param]})
57+
return funcx_func(x, y, **funcx_params), funcy_func(
58+
x, y, **funcy_params
59+
)
60+
61+
morph = MorphFuncxy()
62+
morph.funcxy_function = funcxy_func
63+
morph.funcxy = funcxy_params
6964
x_morph_actual, y_morph_actual, x_target_actual, y_target_actual = (
7065
morph.morph(x_morph, y_morph, x_target, y_target)
7166
)

tests/test_morphfuncy.py

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,58 @@
44
from diffpy.morph.morphs.morphfuncy import MorphFuncy
55

66

7-
def sine_function(x, y, amplitude, frequency):
8-
return amplitude * np.sin(frequency * x) * y
7+
def y_sine_function(x, y, y_amplitude, y_frequency):
8+
return y_amplitude * np.sin(y_frequency * x) * y
99

1010

11-
def exponential_decay_function(x, y, amplitude, decay_rate):
12-
return amplitude * np.exp(-decay_rate * x) * y
11+
def y_exponential_decay_function(x, y, y_amplitude, y_decay_rate):
12+
return y_amplitude * np.exp(-y_decay_rate * x) * y
1313

1414

15-
def gaussian_function(x, y, amplitude, mean, sigma):
16-
return amplitude * np.exp(-((x - mean) ** 2) / (2 * sigma**2)) * y
15+
def y_gaussian_function(x, y, y_amplitude, y_mean, y_sigma):
16+
return y_amplitude * np.exp(-((x - y_mean) ** 2) / (2 * y_sigma**2)) * y
1717

1818

19-
def polynomial_function(x, y, a, b, c):
20-
return (a * x**2 + b * x + c) * y
19+
def y_polynomial_function(x, y, y_a, y_b, y_c):
20+
return (y_a * x**2 + y_b * x + y_c) * y
2121

2222

23-
def logarithmic_function(x, y, scale):
24-
return scale * np.log(1 + x) * y
23+
def y_logarithmic_function(x, y, y_scale):
24+
return y_scale * np.log(1 + x) * y
25+
26+
27+
funcy_test_suite = [
28+
(
29+
y_sine_function,
30+
{"y_amplitude": 2, "y_frequency": 5},
31+
lambda x, y: 2 * np.sin(5 * x) * y,
32+
),
33+
(
34+
y_exponential_decay_function,
35+
{"y_amplitude": 5, "y_decay_rate": 0.1},
36+
lambda x, y: 5 * np.exp(-0.1 * x) * y,
37+
),
38+
(
39+
y_gaussian_function,
40+
{"y_amplitude": 1, "y_mean": 5, "y_sigma": 1},
41+
lambda x, y: np.exp(-((x - 5) ** 2) / (2 * 1**2)) * y,
42+
),
43+
(
44+
y_polynomial_function,
45+
{"y_a": 1, "y_b": 2, "y_c": 0},
46+
lambda x, y: (x**2 + 2 * x) * y,
47+
),
48+
(
49+
y_logarithmic_function,
50+
{"y_scale": 0.5},
51+
lambda x, y: 0.5 * np.log(1 + x) * y,
52+
),
53+
]
2554

2655

2756
@pytest.mark.parametrize(
2857
"function, parameters, expected_function",
29-
[
30-
(
31-
sine_function,
32-
{"amplitude": 2, "frequency": 5},
33-
lambda x, y: 2 * np.sin(5 * x) * y,
34-
),
35-
(
36-
exponential_decay_function,
37-
{"amplitude": 5, "decay_rate": 0.1},
38-
lambda x, y: 5 * np.exp(-0.1 * x) * y,
39-
),
40-
(
41-
gaussian_function,
42-
{"amplitude": 1, "mean": 5, "sigma": 1},
43-
lambda x, y: np.exp(-((x - 5) ** 2) / (2 * 1**2)) * y,
44-
),
45-
(
46-
polynomial_function,
47-
{"a": 1, "b": 2, "c": 0},
48-
lambda x, y: (x**2 + 2 * x) * y,
49-
),
50-
(
51-
logarithmic_function,
52-
{"scale": 0.5},
53-
lambda x, y: 0.5 * np.log(1 + x) * y,
54-
),
55-
],
58+
funcy_test_suite,
5659
)
5760
def test_funcy(function, parameters, expected_function):
5861
x_morph = np.linspace(0, 10, 101)

0 commit comments

Comments
 (0)