Skip to content

test: adding a test to unsqueeze squeezed data #180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
23 changes: 23 additions & 0 deletions news/test_squeeze.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* Polynomial squeeze of x-axis of morphed data

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
48 changes: 48 additions & 0 deletions src/diffpy/morph/morphs/morphsqueeze.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import numpy as np
from numpy.polynomial import Polynomial
from scipy.interpolate import interp1d

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


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

This applies a polynomial to squeeze the morph non-linearly.

Configuration Variables
-----------------------
squeeze
list or array-like
Polynomial coefficients [a0, a1, ..., an] for the squeeze function.
"""

# Define input output types
summary = "Squeeze morph by polynomial shift"
xinlabel = LABEL_RA
yinlabel = LABEL_GR
xoutlabel = LABEL_RA
youtlabel = LABEL_GR
parnames = ["squeeze"]

def morph(self, x_morph, y_morph, x_target, y_target):

Morph.morph(self, x_morph, y_morph, x_target, y_target)
if self.squeeze is None or np.allclose(self.squeeze, 0):
self.x_morph_out = self.x_morph_in
self.y_morph_out = self.y_morph_in
return self.xyallout

squeeze_polynomial = Polynomial(self.squeeze)
x_squeezed = self.x_morph_in + squeeze_polynomial(self.x_morph_in)

self.y_morph_out = interp1d(
x_squeezed,
self.y_morph_in,
kind="cubic",
bounds_error=False,
fill_value="extrapolate",
)(self.x_morph_in)
self.x_morph_out = self.x_morph_in

return self.xyallout
48 changes: 48 additions & 0 deletions tests/test_morphsqueeze.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import numpy as np
import pytest
from numpy.polynomial import Polynomial

from diffpy.morph.morphs.morphsqueeze import MorphSqueeze


@pytest.mark.parametrize(
"squeeze_coeffs",
[
# The order of coefficients is [a0, a1, a2, ..., an]
# Negative cubic squeeze coefficients
[-0.2, -0.01, -0.001, -0.001],
# Positive cubic squeeze coefficients
[0.2, 0.01, 0.001, 0.001],
# Positive and negative cubic squeeze coefficients
[0.2, -0.01, 0.001, -0.001],
# Quadratic squeeze coefficients
[-0.2, 0.005, -0.003],
# Linear squeeze coefficients
[0.1, 0.3],
# 4th order squeeze coefficients
[0.2, -0.01, 0.001, -0.001, 0.0001],
# Testing zeros
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs a statement of the desired behavior when it is fed zeros. Also, do we need a test for some zeros and others not zero? What behavior we want then?

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
],
)
def test_morphsqueeze(squeeze_coeffs):

Copy link
Contributor

Choose a reason for hiding this comment

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

please close this code up. Use empty lines only where they are needed for syntactic clarity.

Copy link
Contributor

Choose a reason for hiding this comment

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

close up. no blank line here (and everywhere below)

x_target = np.linspace(0, 10, 1000)
y_target = np.sin(x_target)

squeeze_polynomial = Polynomial(squeeze_coeffs)
x_squeezed = x_target + squeeze_polynomial(x_target)

x_morph = x_target.copy()
y_morph = np.sin(x_squeezed)

morph = MorphSqueeze()
morph.squeeze = squeeze_coeffs

x_actual, y_actual, x_expected, y_expected = morph(
Copy link
Contributor

Choose a reason for hiding this comment

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

this is not right. You can't have an "expected" returned by the function. x_expected and y_expected are what you are calling x_target and y_target I think. I would just rename them from the beginning.

x_morph, y_morph, x_target, y_target
)

# Check that the morphed (actual) data matches the expected data
# Including tolerance error because of extrapolation error
Copy link
Contributor

Choose a reason for hiding this comment

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

this is a no-no. You are updating the test to make it pass, but the test should express the behavior we want, then write whatever code we need to make the test pass. We don't want a loose test to pass because we haven't coded the edge-case correctly.

assert np.allclose(y_actual, y_expected, atol=0.1)