diff --git a/news/extrap_fix.rst b/news/extrap_fix.rst new file mode 100644 index 00000000..f40a9c51 --- /dev/null +++ b/news/extrap_fix.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Applying a function with no extrapolation no longer produces an error. + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index 735b5e78..84737816 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ authors = [ maintainers = [ { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, ] -description = "Python package for manipulating and comparing PDF profiles" +description = "Python package for manipulating and comparing 1D signals." keywords = ['diffpy', 'pdf', 'data interpretation'] readme = "README.rst" requires-python = ">=3.11, <3.14" diff --git a/src/diffpy/morph/morph_io.py b/src/diffpy/morph/morph_io.py index 5c013a77..b0d80b68 100644 --- a/src/diffpy/morph/morph_io.py +++ b/src/diffpy/morph/morph_io.py @@ -501,38 +501,39 @@ def tabulate_results(multiple_morph_results): def handle_extrapolation_warnings(morph): if morph is not None: extrapolation_info = morph.extrapolation_info - is_extrap_low = extrapolation_info["is_extrap_low"] - is_extrap_high = extrapolation_info["is_extrap_high"] - cutoff_low = extrapolation_info["cutoff_low"] - cutoff_high = extrapolation_info["cutoff_high"] - - if is_extrap_low and is_extrap_high: - wmsg = ( - "Warning: points with grid value below " - f"{cutoff_low} and above " - f"{cutoff_high} " - f"are extrapolated." - ) - elif is_extrap_low: - wmsg = ( - "Warning: points with grid value below " - f"{cutoff_low} " - f"are extrapolated." - ) - elif is_extrap_high: - wmsg = ( - "Warning: points with grid value above " - f"{cutoff_high} " - f"are extrapolated." - ) - else: - wmsg = None + if extrapolation_info is not None: + is_extrap_low = extrapolation_info["is_extrap_low"] + is_extrap_high = extrapolation_info["is_extrap_high"] + cutoff_low = extrapolation_info["cutoff_low"] + cutoff_high = extrapolation_info["cutoff_high"] + + if is_extrap_low and is_extrap_high: + wmsg = ( + "Warning: points with grid value below " + f"{cutoff_low} and above " + f"{cutoff_high} " + f"are extrapolated." + ) + elif is_extrap_low: + wmsg = ( + "Warning: points with grid value below " + f"{cutoff_low} " + f"are extrapolated." + ) + elif is_extrap_high: + wmsg = ( + "Warning: points with grid value above " + f"{cutoff_high} " + f"are extrapolated." + ) + else: + wmsg = None - if wmsg: - warnings.warn( - wmsg, - UserWarning, - ) + if wmsg: + warnings.warn( + wmsg, + UserWarning, + ) def handle_check_increase_warning(squeeze_morph): diff --git a/src/diffpy/morph/morphs/morph.py b/src/diffpy/morph/morphs/morph.py index 7ffccd15..8552d5d7 100644 --- a/src/diffpy/morph/morphs/morph.py +++ b/src/diffpy/morph/morphs/morph.py @@ -124,6 +124,7 @@ def __init__(self, config=None): All configuration variables. """ # declare empty attributes + self.extrapolation_info = None if config is None: config = {} self.x_morph_in = None diff --git a/tests/test_morphshift.py b/tests/test_morphshift.py index 1ae2e0f7..28b2d1bf 100644 --- a/tests/test_morphshift.py +++ b/tests/test_morphshift.py @@ -105,3 +105,36 @@ def test_morphshift_extrapolate(user_filesystem, capsys, hshift, wmsg_gen): ) with pytest.warns(UserWarning, match=expected_wmsg): single_morph(parser, opts, pargs, stdout_flag=False) + + +def test_morphshift_no_warning(user_filesystem): + # Apply a shift with no extrapolation + # There should be no warning or errors produced + x_morph = numpy.linspace(0, 10, 101) + y_morph = numpy.sin(x_morph) + x_target = x_morph.copy() + y_target = y_morph.copy() + morphpy.morph_arrays( + numpy.array([x_morph, y_morph]).T, + numpy.array([x_target, y_target]).T, + hshift=0, + apply=True, + ) + + # CLI test + morph_file, target_file = create_morph_data_file( + user_filesystem / "cwd_dir", x_morph, y_morph, x_target, y_target + ) + + parser = create_option_parser() + (opts, pargs) = parser.parse_args( + [ + "--scale=1", + "--hshift=0", + f"{morph_file.as_posix()}", + f"{target_file.as_posix()}", + "--apply", + "-n", + ] + ) + single_morph(parser, opts, pargs, stdout_flag=False) diff --git a/tests/test_morphsqueeze.py b/tests/test_morphsqueeze.py index 2bb65b0f..8a172086 100644 --- a/tests/test_morphsqueeze.py +++ b/tests/test_morphsqueeze.py @@ -174,6 +174,44 @@ def test_morphsqueeze_extrapolate(user_filesystem, squeeze_coeffs, wmsg_gen): single_morph(parser, opts, pargs, stdout_flag=False) +def test_morphsqueeze_no_warning(user_filesystem): + # Apply a squeeze with no extrapolation + # There should be no warning or errors produced + squeeze_coeffs = {"a0": 0, "a1": 0} + x_morph = np.linspace(0, 10, 101) + y_morph = np.sin(x_morph) + x_target = x_morph.copy() + y_target = y_morph.copy() + morph = MorphSqueeze() + morph.squeeze = squeeze_coeffs + coeffs = [squeeze_coeffs[f"a{i}"] for i in range(len(squeeze_coeffs))] + morphpy.morph_arrays( + np.array([x_morph, y_morph]).T, + np.array([x_target, y_target]).T, + squeeze=coeffs, + apply=True, + ) + + # CLI test + morph_file, target_file = create_morph_data_file( + user_filesystem / "cwd_dir", x_morph, y_morph, x_target, y_target + ) + + parser = create_option_parser() + (opts, pargs) = parser.parse_args( + [ + "--scale=1", + "--squeeze", + ",".join(map(str, coeffs)), + f"{morph_file.as_posix()}", + f"{target_file.as_posix()}", + "--apply", + "-n", + ] + ) + single_morph(parser, opts, pargs, stdout_flag=False) + + def test_non_unique_grid(): # Test giving morphsqueeze a non-unique grid # Expect it to return a unique grid diff --git a/tests/test_morphstretch.py b/tests/test_morphstretch.py index 311c92e4..fb076204 100644 --- a/tests/test_morphstretch.py +++ b/tests/test_morphstretch.py @@ -101,16 +101,16 @@ def test_morphshift_extrapolate(user_filesystem, stretch, wmsg_gen): y_morph = numpy.sin(x_morph) x_target = x_morph.copy() y_target = y_morph.copy() - with pytest.warns() as w: + with pytest.warns() as warning: morphpy.morph_arrays( numpy.array([x_morph, y_morph]).T, numpy.array([x_target, y_target]).T, stretch=stretch, apply=True, ) - assert len(w) == 1 - assert w[0].category is UserWarning - actual_wmsg = str(w[0].message) + assert len(warning) == 1 + assert warning[0].category is UserWarning + actual_wmsg = str(warning[0].message) expected_wmsg = wmsg_gen([min(x_morph), max(x_morph)]) assert actual_wmsg == expected_wmsg @@ -131,3 +131,36 @@ def test_morphshift_extrapolate(user_filesystem, stretch, wmsg_gen): ) with pytest.warns(UserWarning, match=expected_wmsg): single_morph(parser, opts, pargs, stdout_flag=False) + + +def test_morphshift_no_warning(user_filesystem): + # Apply a stretch with no extrapolation + # There should be no warning or errors produced + x_morph = numpy.linspace(1, 10, 101) + y_morph = numpy.sin(x_morph) + x_target = x_morph.copy() + y_target = y_morph.copy() + morphpy.morph_arrays( + numpy.array([x_morph, y_morph]).T, + numpy.array([x_target, y_target]).T, + stretch=0, + apply=True, + ) + + # CLI test + morph_file, target_file = create_morph_data_file( + user_filesystem / "cwd_dir", x_morph, y_morph, x_target, y_target + ) + + parser = create_option_parser() + (opts, pargs) = parser.parse_args( + [ + "--scale=1", + "--stretch=0", + f"{morph_file.as_posix()}", + f"{target_file.as_posix()}", + "--apply", + "-n", + ] + ) + single_morph(parser, opts, pargs, stdout_flag=False)