Skip to content

TST: Compat with numpy 1.25.dev - #14718

Merged
pllim merged 2 commits into
astropy:mainfrom
pllim:why-did-they-changed-math
May 5, 2023
Merged

pllim merged 2 commits into
astropy:mainfrom
pllim:why-did-they-changed-math

Conversation

@pllim

@pllim pllim commented Apr 29, 2023

Copy link
Copy Markdown
Member

Description

This pull request is an attempt to fix #14705 (what's remaining after Larry's fixes).

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.

  • Do the proposed changes actually accomplish desired goals?
  • Do the proposed changes follow the Astropy coding guidelines?
  • Are tests added/updated as required? If so, do they follow the Astropy testing guidelines?
  • Are docs added/updated as required? If so, do they follow the Astropy documentation guidelines?
  • Is rebase and/or squash necessary? If so, please provide the author with appropriate instructions. Also see "When to rebase and squash commits".
  • Did the CI pass? If no, are the failures related? If you need to run daily and weekly cron jobs as part of the PR, please apply the "Extra CI" label. Codestyle issues can be fixed by the bot.
  • Is a change log needed? If yes, did the change log check pass? If no, add the "no-changelog-entry-needed" label. If this is a manual backport, use the "skip-changelog-checks" label unless special changelog handling is necessary.
  • Is this a big PR that makes a "What's new?" entry worthwhile and if so, is (1) a "what's new" entry included in this PR and (2) the "whatsnew-needed" label applied?
  • Is a milestone set? Milestone must be set but we cannot check for it on Actions; do not let the green checkmark fool you.
  • At the time of adding the milestone, if the milestone set requires a backport to release branch(es), apply the appropriate "backport-X.Y.x" label(s) before merge.


assert np.all(inside_bbox == outside_bbox)
# FIXME: https://github.com/astropy/astropy/issues/14705
# ValueError: operands could not be broadcast together with shapes (1100,) (1099,)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Might point to a subtle bug deep within modeling bounding box machinery? 🤷

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably an unfortunate rounding error; still, not nice!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, if someone knows how to properly fix it in Gaussian2D, that would be better.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think the fix has to be here somewhere:

t = np.arctan2(-b * np.tan(theta), a)
dx = a * np.cos(t) * np.cos(theta) - b * np.sin(t) * np.sin(theta)
t = np.arctan2(b, a * np.tan(theta))
dy = b * np.sin(t) * np.cos(theta) + a * np.cos(t) * np.sin(theta)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I guess a more hacky alternative is to modify the test case so this won't happen for that test but it is not a real fix.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess it really depends on the goal of the test.... If it was just a sanity check that basically the box was the same, with a slop of 1 pixel due to rounding allowed, then it would be fine to adjust it. But I don't know...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The part of the test which is failing has nothing to do with the precise construction of the bounding box... Nor does it have anything to do with checking "if the box was the same"... Nor can it be the result of a "rounding error"..

The point of the test where it is failing is showing that a model properly discriminates if the inputs are inside/outside the bounding box when integrated into the model evaluation process.

It specifically constricts two sets of inputs x1, y1, x2, y2 such that:

  1. All the points in x1, y1 are in x2, y2 respectively
  2. All points in x2, y2 not in x1, y1 lie outside the bounding box

The model is then evaluated on these points without/with bounding box enforcement respectively (to x1, y1 vs x2, y2). This means that all the outputs corresponding to points outside the bounding box should be set to np.NaN. Consequently, due to the specific construction of x2, y2 relative to x1, y1 it should be the case that all the non np.NaN outputs of both evaluations should exactly correspond without any rounding errors (it is literally an exactly repeated computation).

To see that the assumptions should be satisfied, note that (1) is satisfied by

x1 = np.arange(xlim[0], xlim[1], ddx)
y1 = np.arange(ylim[0], ylim[1], ddx)
x2 = np.concatenate(
(
[xlim[0] - idx * ddx for idx in range(10, 0, -1)],
x1,
[xlim[1] + idx * ddx for idx in range(1, 10)],
)
)
y2 = np.concatenate(
(
[ylim[0] - idx * ddx for idx in range(10, 0, -1)],
y1,
[ylim[1] + idx * ddx for idx in range(1, 10)],
)
)

because the construction of x2, y2 by concatenating points onto x1, y2 respectively.

While (2) is satisfied by the fact that the bounding box limits are used and the additional points are all created strictly -/+idx*ddx where idx != 0, where -/+ is with respect to the lower/upper bounds of the bounding box. This implies that all the additional points are strictly outside the bounding box. There should be no rounding error issues ddx = .01, which is much much larger than machine precision (so well outside any rounding error concerns).

Since bounding boxes discriminate the input points lying outside the box using

def outside(self, _input: np.ndarray):
"""
Parameters
----------
_input : np.ndarray
The evaluation input in the form of an array.
Returns
-------
Boolean array indicating which parts of _input are outside the interval:
True -> position outside interval
False -> position inside interval
"""
return np.logical_or(_input < self.lower, _input > self.upper)

It follows that the endpoints of the bounding box should lie within it (i.e. it defines a closed interval on each axis). So by construction all the inputs in x1, y1 are inside the bounding box. Therefore, evaluating the model on x1, y1 regardless of bounding box enforcement should result in no np.NaN outputs (Gaussian2D is well behaved on its bounding box intervals). While evaluating the model on x2, y2 should result in np.NaN values for all the points not corresponding to those in x1, y1, while the corresponding points between x1, y1 and x2, y2 should all exactly match.

Note that, the error in question:

ValueError: operands could not be broadcast together with shapes (1100,) (1099,)

Indicates that some point in x1, y1 is being evaluated to np.NaN in the x2, y2 computation. There are a few possibilities:

  1. The bounding box incorrectly discriminating on the endpoints of the bounding box as those points are specifically included in the computation. Meaning there is an issue with the > or < comparisons in the outside method.
  2. Some sort of new numerical issue is causing a np.NaN occur when evaluating Gaussian2D on points contained within its bounding box (this is surprising since the default bounding box for Gaussian2D is selected specifically so that no numerical errors should occur when evaluating on points contained within it).
  3. There is an issue with
    outside_bbox = outside_bbox[~np.isnan(outside_bbox)]
    wherein ~np.isnan(...) is incorrectly flagging a non-np.NaN value as NaN.

The way I could distinguish between these possibilities would be

  1. Compare inside_bbox with inside_bbox[~np.isnan(inside_bbox)] (eliminates/confirms possibility (2))
  2. and/or Compute inside_bbox with the with_bounding_box=True option (eliminates/confirms possibility (1))
  3. Manually examine the raw values of inside_bbox and outside_bbox (eliminates/confirms possibility (3))

However, I can no-longer reproduce this issue, see #14771 so I cannot exactly determine the cause.

@pllim
pllim requested review from larrybradley and mhvk April 29, 2023 01:57
@pllim pllim added the Extra CI Run cron CI as part of PR label Apr 29, 2023

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, looks good to me, with a possible suggestion, as I'd prefer not to have numbers in their that appear precise but are just set not to trigger failures...


assert np.all(inside_bbox == outside_bbox)
# FIXME: https://github.com/astropy/astropy/issues/14705
# ValueError: operands could not be broadcast together with shapes (1100,) (1099,)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably an unfortunate rounding error; still, not nice!

coordinates/tests/test_intermediate_transformations.py tests

@larrybradley larrybradley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Like @mhvk, I also suspect the shape mismatch is due to a rounding error.

@pllim

pllim commented May 5, 2023

Copy link
Copy Markdown
Member Author

I am not going to even try LTS with this one given the other backport has like 100 failures.

Since no one has idea to fix the bounding box for real, just gonna merge this then. Thanks!

@pllim
pllim enabled auto-merge May 5, 2023 21:58
@pllim
pllim merged commit e3b2444 into astropy:main May 5, 2023
@pllim
pllim deleted the why-did-they-changed-math branch May 5, 2023 21:58
meeseeksmachine pushed a commit to meeseeksmachine/astropy that referenced this pull request May 5, 2023
meeseeksmachine pushed a commit to meeseeksmachine/astropy that referenced this pull request May 5, 2023
# FIXME: https://github.com/astropy/astropy/issues/14705
# ValueError: operands could not be broadcast together with shapes (1100,) (1099,)
if model_class != Gaussian2D:
assert np.all(inside_bbox == outside_bbox)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This "fix" is far far too aggressive. The only issue here is with numpy 1.25.dev and at the very least this should be restricted to that case only. As it stands, this "fix" turns off testing in all cases.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for the follow up fix of this "fix"!

pllim added a commit that referenced this pull request May 6, 2023
meeseeksmachine pushed a commit to meeseeksmachine/astropy that referenced this pull request May 6, 2023
meeseeksmachine pushed a commit to meeseeksmachine/astropy that referenced this pull request May 6, 2023
pllim added a commit that referenced this pull request May 6, 2023
…718-on-v5.3.x

Backport PR #14718 on branch v5.3.x (TST: Compat with numpy 1.25.dev)
pllim added a commit that referenced this pull request May 6, 2023
…718-on-v5.2.x

Backport PR #14718 on branch v5.2.x (TST: Compat with numpy 1.25.dev)
pllim added a commit to pllim/astropy that referenced this pull request May 6, 2023
pllim added a commit to pllim/astropy that referenced this pull request May 6, 2023
pllim added a commit that referenced this pull request May 7, 2023
Backport PR 14771 to v5.2.x ( Revert Gaussian test change from #14718)
pllim added a commit that referenced this pull request May 7, 2023
Backport PR 14771 to v5.3.x ( Revert Gaussian test change from #14718)
pllim added a commit to pllim/astropy that referenced this pull request Jun 14, 2023
from numpy cos/sin changes that have since been reverted in 1.25.dev
pllim added a commit to pllim/astropy that referenced this pull request Jun 14, 2023
from numpy cos/sin changes that have since been reverted in 1.25.dev
pllim added a commit to pllim/astropy that referenced this pull request Jun 19, 2023
from numpy cos/sin changes that have since been reverted in 1.25.dev
pllim added a commit to pllim/astropy that referenced this pull request Jun 20, 2023
from numpy cos/sin changes that have since been reverted in 1.25.dev
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TST: coordinates and modeling test failures in devdeps job

4 participants