Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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/extrapolate-warning.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* No news added: Add warning for extrapolation in morphsqueeze.py.

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
27 changes: 27 additions & 0 deletions src/diffpy/morph/morphs/morphsqueeze.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
"""Class MorphSqueeze -- Apply a polynomial to squeeze the morph
function."""

import warnings

import numpy as np
from numpy.polynomial import Polynomial
from scipy.interpolate import CubicSpline

from diffpy.morph.morphs.morph import LABEL_GR, LABEL_RA, Morph


def custom_formatwarning(msg, *args, **kwargs):
return f"{msg}\n"


warnings.formatwarning = custom_formatwarning


class MorphSqueeze(Morph):
"""Squeeze the morph function.

Expand Down Expand Up @@ -85,4 +94,22 @@ def morph(self, x_morph, y_morph, x_target, y_target):
high_extrap = np.where(self.x_morph_in > x_squeezed[-1])[0]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to remove these few lines of code? I can't find other references to the variables defined here.

Copy link
Collaborator

@Sparks29032 Sparks29032 Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were variables we made before to store what you have now called begin_end_squeeze. You can delete it if you prefer using begin_end_squeeze.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find these variables provide a handy interface to test the extrapolated effect in test_morphsqueeze, so I think we should keep them.

self.extrap_index_low = low_extrap[-1] if low_extrap.size else None
self.extrap_index_high = high_extrap[0] if high_extrap.size else None

begin_end_sqeeze = min(x_squeezed), max(x_squeezed)
begin_end_in = min(self.x_morph_in), max(self.x_morph_in)
if not (
begin_end_sqeeze[0] <= begin_end_in[0]
and begin_end_in[-1] >= begin_end_in[-1]
):
wmsg = (
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output effect:
image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make it say Warning: on the CLI as well?

"\nExtrapolating the morphed function via CubicSpline:\n"
f"Obtaining grid points between {begin_end_in[0]} and "
f"{begin_end_in[1]}.\n"
f"Points below {begin_end_sqeeze[0]} and "
f"above {begin_end_sqeeze[1]} will be extrapolated."
)
warnings.warn(
wmsg,
UserWarning,
)
return self.xyallout
27 changes: 27 additions & 0 deletions tests/test_morphsqueeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,30 @@ def test_morphsqueeze(x_morph, x_target, squeeze_coeffs):
assert np.allclose(x_morph_actual, x_morph_expected)
assert np.allclose(x_target_actual, x_target)
assert np.allclose(y_target_actual, y_target)


def test_morphsqueeze_extrapolate():
x_morph = np.linspace(0, 10, 101)
y_morph = np.sin(x_morph)
x_target = x_morph
y_target = y_morph
squeeze_coeff = {"a0": 0.01, "a1": -0.0005, "a2": -0.0005, "a3": -1e-6}
morph = MorphSqueeze()
morph.squeeze = squeeze_coeff
coeffs = [squeeze_coeff[f"a{i}"] for i in range(len(squeeze_coeff))]
squeeze_polynomial = Polynomial(coeffs)
x_squeezed = x_morph + squeeze_polynomial(x_morph)
with pytest.warns() as w:
x_morph_actual, y_morph_actual, x_target_actual, y_target_actual = (
morph(x_morph, y_morph, x_target, y_target)
)
assert len(w) == 1
assert w[0].category is UserWarning
actual_wmsg = str(w[0].message)
expected_wmsg = (
"\nExtrapolating the morphed function via CubicSpline:\n"
f"Obtaining grid points between {x_morph[0]} and {x_morph[-1]}.\n"
f"Points below {x_squeezed[0]} and "
f"above {x_squeezed[-1]} will be extrapolated."
)
assert actual_wmsg == expected_wmsg
Loading