Skip to content

Make frame attribute equivalency checks symmetric - #10658

Merged
mhvk merged 1 commit into
astropy:masterfrom
ludwigschwardt:symmetric-frame-attr-checks
Aug 18, 2020
Merged

mhvk merged 1 commit into
astropy:masterfrom
ludwigschwardt:symmetric-frame-attr-checks

Conversation

@ludwigschwardt

Copy link
Copy Markdown
Contributor

Description

The BaseCoordinateFrame._frameattr_equiv(left_fattr, right_fattr) check is not symmetric with respect to the two attributes.

If the left attribute is a coordinate frame or representation and the right one isn't, the method returns False.

If the right attribute is a coordinate frame or representation and the left one isn't, one is at the mercy of the underlying equality operator instead. This typically results in a TypeError (or a FutureWarning in the case of an EarthLocationAttribute vs an unspecified None).

This was encountered when calculating the angular separation between a star and the Sun in a common AltAz frame. The Sun SkyCoord had an extra obsgeoloc frame attribute due to its GCRS origins while the star SkyCoord had this as None. Then sun.separation(star) works but star.separation(sun) raises a TypeError.
`
This extends @ayshih's changes in #10290, so it can be considered a bug fix of the development version.

@pllim
pllim requested a review from mhvk August 15, 2020 00:09
@pllim pllim added this to the v4.1 milestone Aug 15, 2020
@pllim pllim added Affects-dev PRs and issues that do not impact an existing Astropy release Bug labels Aug 15, 2020
@pllim
pllim requested review from adrn and eteq August 15, 2020 00:10

@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.

Thanks very much! This looks good - I particularly appreciate the great tests - just some very minor and rather nitpicky comments. Hardly worth making another commit, but, hey, you can then squash the two commits and add this PR number to the old changelog entry... But am approving since if you prefer to be just done, that is fine too!

Comment thread astropy/coordinates/baseframe.py Outdated
if left_fattr is right_fattr:
# shortcut if it's exactly the same object
return True
if left_fattr is None or right_fattr is None:

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 was about to write "what if both are None?" when I realized that case is caught by the clause above. How about making this "elif" to make that link clearer?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

Comment thread astropy/coordinates/baseframe.py Outdated
if isinstance(right_fattr, r.BaseRepresentationOrDifferential):
left_is_repr = isinstance(left_fattr, r.BaseRepresentationOrDifferential)
right_is_repr = isinstance(right_fattr, r.BaseRepresentationOrDifferential)
if left_is_repr or right_is_repr:

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.

How about reversing the order a bit:

if left_is_repr and right_is_repr:
   <actual useful code>
elif left_is_repr or right_is_repr:
    return False

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I like this a lot. I consider indentation harmful - especially a lone else: floating in the middle of nowhere.

I picked the original order to have the smallest possible diff to make the review easier, so now I'll make it better.

Comment thread astropy/coordinates/baseframe.py Outdated
if left_is_coord and right_is_coord:
# both are coordinates
if left_fattr.is_equivalent_frame(right_fattr):
return np.all(left_fattr == right_fattr)

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.

Actually, thinking about how this continues, since we want to make sure the code always returns True or False, I think it would make sense to guard the code at the end in a try/except, as in

try:
    return np.all(left_attr == right_attr)
except Exception:
    return False

With that, in principle, you could have only the both repr and both frame checks, since that would catch all mismatches. But code is probably clearer as you have it!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

... and catching Exception might hide broken stuff. I have a slight preference for the status quo due to that.

@ludwigschwardt

Copy link
Copy Markdown
Contributor Author

I appreciate nitpicking :-)

On the changelog entry: is it needed since it is essentially a development version bugfix, and if so, what under which version should I put it?

@mhvk

mhvk commented Aug 17, 2020

Copy link
Copy Markdown
Contributor

@ludwigschwardt - I would just add the PR number to whatever was added before, since this extends that addition (i.e., no new line of text needed). (Note that I didn't check what was added before, so feel free to tell me this makes no sense!)

The `BaseCoordinateFrame._frameattr_equiv(left_fattr, right_fattr)`
check is not symmetric with respect to the two attributes.

If the left attribute is a coordinate frame or representation and the
right one isn't, the method returns False. If the right attribute is a
coordinate frame or representation and the left one isn't, one is at the
mercy of the underlying equality operator instead. This typically
results in a TypeError (or a FutureWarning in the case of an
EarthLocationAttribute vs an unspecified None).

This was encountered when calculating the angular separation between
a star and the Sun in a common AltAz frame. The Sun SkyCoord had an
extra `obsgeoloc` frame attribute due to its GCRS origins while the
star SkyCoord had this as None. Then `Sun.separation(star)` works but
`star.separation(Sun)` raises a TypeError.
@ludwigschwardt
ludwigschwardt force-pushed the symmetric-frame-attr-checks branch from 3fea35f to e667d31 Compare August 17, 2020 16:48
@ludwigschwardt

Copy link
Copy Markdown
Contributor Author

#10290 has no changelog entry, so that's that :-)

I've squashed the suggested changes together.

@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.

Thanks, looks great now!

If you have the energy to add tests for the missing coverage, then that would be great, but don't feel obliged (it was missing before -- if it had been better you wouldn't have had a PR to make...)

@ludwigschwardt

Copy link
Copy Markdown
Contributor Author

I considered that.

One problem is that it is quite hard to get a misbehaving frame attribute in normal use. The only common type mismatch is when you have None instead of the expected attribute instance, and that now has a dedicated short-circuit at the top of the function. Otherwise you have to construct two Frames/SkyCoords with attributes that have the same name but different attribute types, which seems a bit contrived. This is one plus of the try...except(Exception) approach: less code to cover :-)

@mhvk

mhvk commented Aug 18, 2020

Copy link
Copy Markdown
Contributor

OK, no worries - as you didn't make the coverage any worse, let's just merge!

@mhvk
mhvk merged commit 0f5c080 into astropy:master Aug 18, 2020
vla22 pushed a commit to ska-telescope/katpoint that referenced this pull request Aug 18, 2020
We should be able to remove this once Astropy 4.1 is released, which
includes astropy/astropy#10658.
eteq pushed a commit to eteq/astropy that referenced this pull request Oct 12, 2020
…attr-checks

Make frame attribute equivalency checks symmetric
eteq pushed a commit that referenced this pull request Oct 13, 2020
…ecks

Make frame attribute equivalency checks symmetric
vla22 pushed a commit to ska-telescope/katpoint that referenced this pull request Nov 3, 2020
Astropy 4.1 causes some Solar System objects to shift by 5 mas in the
body unit tests. Since the tolerance is 1 mas, this causes the tests
to fail. This is most likely due to astropy/astropy#10666, which
improves the treatment of solar light deflection for nearby objects.
Take the new positions as gospel, since the old behaviour is considered
to be a bug.

Now that Astropy 4.1 is out we can also remove a workaround for 4.1rc1
(fixed in astropy/astropy#10658).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Affects-dev PRs and issues that do not impact an existing Astropy release Bug coordinates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants