Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 18
Squeeze morph warning handling#272
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| **Added:** | ||
| * Warnings added to `squeeze` morph if the squeeze causes the grid to become non-monotonic. | ||
| **Changed:** | ||
| * <news item> | ||
| **Deprecated:** | ||
| * <news item> | ||
| **Removed:** | ||
| * <news item> | ||
| **Fixed:** | ||
| * <news item> | ||
| **Security:** | ||
| * <news item> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -54,6 +54,8 @@ def test_morphsqueeze(x_morph, x_target, squeeze_coeffs): | ||
| x_target_expected = x_target | ||
| y_target_expected = y_target | ||
| # actual output | ||
| # turn the coefficients into a list for passing to Polynomial | ||
| # the morphsqueeze function itself requires a dictionary | ||
| coeffs = [squeeze_coeffs[f"a{i}"] for i in range(len(squeeze_coeffs))] | ||
| squeeze_polynomial = Polynomial(coeffs) | ||
| x_squeezed = x_morph + squeeze_polynomial(x_morph) | ||
| @@ -139,16 +141,16 @@ def test_morphsqueeze_extrapolate(user_filesystem, squeeze_coeffs, wmsg_gen): | ||
| coeffs = [squeeze_coeffs[f"a{i}"] for i in range(len(squeeze_coeffs))] | ||
| squeeze_polynomial = Polynomial(coeffs) | ||
| x_squeezed = x_morph + squeeze_polynomial(x_morph) | ||
| with pytest.warns() as w: | ||
| with pytest.warns() as warning: | ||
| morphpy.morph_arrays( | ||
| np.array([x_morph, y_morph]).T, | ||
| np.array([x_target, y_target]).T, | ||
| squeeze=coeffs, | ||
| 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_squeezed), max(x_squeezed)]) | ||
| assert actual_wmsg == expected_wmsg | ||
| @@ -170,3 +172,134 @@ def test_morphsqueeze_extrapolate(user_filesystem, squeeze_coeffs, wmsg_gen): | ||
| ) | ||
| with pytest.warns(UserWarning, match=expected_wmsg): | ||
| 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 | ||
| squeeze_coeffs = {"a0": 0.01, "a1": 0.01, "a2": -0.1} | ||
sbillinge marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| x_grid = np.linspace(0, 10, 101) | ||
| coeffs = [squeeze_coeffs[f"a{i}"] for i in range(len(squeeze_coeffs))] | ||
| squeeze_polynomial = Polynomial(coeffs) | ||
| x_morph = x_grid + squeeze_polynomial(x_grid) | ||
| x_gradient = np.diff(x_morph) | ||
| x_gradient_sign = np.sign(x_gradient) | ||
| # non-strictly increasing means the gradient becomes 0 or negative | ||
| assert not np.all(x_gradient_sign > 0) | ||
| x_target = np.linspace(min(x_morph), max(x_morph), len(x_morph)) | ||
| y_target = np.sin(x_target) | ||
| y_morph = np.sin(x_morph) | ||
| # apply no squeeze, but the morph should sort the function | ||
| _, table = morphpy.morph_arrays( | ||
| np.array([x_morph, y_morph]).T, | ||
| np.array([x_target, y_target]).T, | ||
| squeeze=[0, 0, 0], | ||
| apply=True, | ||
| ) | ||
| x_refined, _ = table[:, 0], table[:, 1] | ||
| # grid should be properly sorted | ||
| assert np.allclose(x_refined, x_target) | ||
| # note that the function itself may be distorted | ||
| @pytest.mark.parametrize( | ||
| "squeeze_coeffs, x_morph", | ||
| [ | ||
sbillinge marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| # The following squeezes make the function non-monotonic. | ||
| # Expect code to work but issue the correct warning. | ||
| ([-1, -1, 2], np.linspace(-1, 1, 101)), | ||
| ( | ||
| [-1, -1, 0, 0, 2], | ||
| np.linspace(-1, 1, 101), | ||
| ), | ||
| ], | ||
| ) | ||
| def test_squeeze_warnings(user_filesystem, squeeze_coeffs, x_morph): | ||
| # call in .py | ||
| x_target = x_morph | ||
| y_target = np.sin(x_target) | ||
| squeeze_polynomial = Polynomial(squeeze_coeffs) | ||
| x_squeezed = x_morph + squeeze_polynomial(x_morph) | ||
| y_morph = np.sin(x_squeezed) | ||
| morph = MorphSqueeze() | ||
| morph.squeeze = squeeze_coeffs | ||
| with pytest.warns() as warning: | ||
| morphpy.morph_arrays( | ||
| np.array([x_morph, y_morph]).T, | ||
| np.array([x_target, y_target]).T, | ||
| squeeze=squeeze_coeffs, | ||
| apply=True, | ||
| ) | ||
| assert len(warning) == 1 | ||
| assert warning[0].category is UserWarning | ||
| actual_wmsg = str(warning[0].message) | ||
| expected_wmsg = ( | ||
| "Warning: The squeeze morph has interpolated your morphed " | ||
| "function from a non-monotonically increasing grid. " | ||
| "\nThis may not be an issue, but please check for your " | ||
| "particular case. " | ||
| "\nTo avoid squeeze making your grid non-monotonic, " | ||
| "here are some suggested fixes: " | ||
| "\n(1) Please decrease the order of your polynomial and try again. " | ||
| "\n(2) If you are using initial guesses of all 0, please ensure " | ||
| "your objective function only requires a small polynomial " | ||
| "squeeze to match your reference. " | ||
| "(In other words, there is good agreement between the two " | ||
| "functions.) " | ||
| "\n(3) If you expect a large polynomial squeeze to be needed, " | ||
| "please ensure your initial parameters for the polynomial " | ||
| "morph result in good agreement between your reference and " | ||
| "objective functions. One way to obtain such parameters is to " | ||
| "first apply a --hshift and --stretch morph. " | ||
| "Then, use the hshift parameter for a0 and stretch parameter for a1." | ||
| ) | ||
| assert expected_wmsg in actual_wmsg | ||
| # call in CLI | ||
| 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( | ||
| [ | ||
| "--squeeze", | ||
| ",".join(map(str, squeeze_coeffs)), | ||
| f"{morph_file.as_posix()}", | ||
| f"{target_file.as_posix()}", | ||
| "--apply", | ||
| "-n", | ||
| ] | ||
| ) | ||
| with pytest.warns(UserWarning) as warning: | ||
| single_morph(parser, opts, pargs, stdout_flag=False) | ||
| assert len(warning) == 1 | ||
| actual_wmsg = str(warning[0].message) | ||
| assert expected_wmsg in actual_wmsg | ||
| @pytest.mark.parametrize( | ||
| "x_sampled", | ||
| [ | ||
| # Expected output: all repeated datapoints are removed | ||
| # Test one duplicate per number | ||
| np.array([0, 0, 1, 1, 2, 2, 3, 3]), | ||
| # Test more than one duplicates per number | ||
| np.array([0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2]), | ||
| # Test with only one grid number | ||
| np.array([0, 0, 0, 0]), | ||
| # Test no duplicates | ||
| np.array([0, 1, 2, 3, 4]), | ||
| ], | ||
| ) | ||
| def test_handle_duplicates(x_sampled): | ||
| morph = MorphSqueeze() | ||
sbillinge marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| y_sampled = np.sin(x_sampled) | ||
| x_handled, y_handled = morph._handle_duplicates(x_sampled, y_sampled) | ||
| x_target = np.unique(x_sampled) | ||
| y_target = np.array([y_sampled[x_sampled == x].mean() for x in x_target]) | ||
| assert np.allclose(x_handled, x_target) | ||
| assert np.allclose(y_handled, y_target) | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.