Skip to content

Changes to SkyCoord equality incompatible with a SkyCoord frame attribute #10287

Closed

Description

@dstansby

In sunpy one of the frame attributes we set on some of our frames is an observer attribute, which is itself a SkyCoord. The recent changes to coordinate equality checking in #10154 break some functionality however, because sc1 != sc2 now errors instead of returning False if sc1 is in a different frame to sc2.

In particular, a traceback where we are now seeing errors is

>       assert_quantity_allclose(implicit.separation_3d(explicit2), 0*u.AU, atol=1e-10*u.AU)

sunpy/coordinates/tests/test_transformations.py:500: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../astropy/astropy/coordinates/sky_coordinate.py:1054: in separation_3d
    if not self.is_equivalent_frame(other):
../astropy/astropy/coordinates/sky_coordinate.py:970: in is_equivalent_frame
    if np.any(getattr(self, fattrnm) != getattr(other, fattrnm)):
../astropy/astropy/coordinates/baseframe.py:1656: in __ne__
    return np.logical_not(self == value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <HeliographicStonyhurst Coordinate (obstime=2019-06-01T00:00:00.000): (lon, lat, radius) in (deg, deg, AU)
    (0., -0.72605048, 1.01396311)>
value = <HeliographicStonyhurst Coordinate (obstime=2019-12-01T00:00:00.000): (lon, lat, radius) in (deg, deg, AU)
    (0., 0.94857499, 0.98618233)>

    def __eq__(self, value):
        """Equality operator for frame.
    
        This implements strict equality and requires that the frames are
        equivalent and that the representation data are exactly equal.
        """
        is_equiv = self.is_equivalent_frame(value)
    
        if self._data is None and value._data is None:
            # For Frame with no data, == compare is same as is_equivalent_frame()
            return is_equiv
    
        if not is_equiv:
>           raise TypeError(f'cannot compare: objects must have equivalent frames: '
                            f'{self.replicate_without_data()} vs. '
                            f'{value.replicate_without_data()}')
E           TypeError: cannot compare: objects must have equivalent frames: <HeliographicStonyhurst Frame (obstime=2019-06-01T00:00:00.000)> vs. <HeliographicStonyhurst Frame (obstime=2019-12-01T00:00:00.000)>

Because is_equivalent_frame checks all the attrs in this line:

../astropy/astropy/coordinates/sky_coordinate.py:970: in is_equivalent_frame
    if np.any(getattr(self, fattrnm) != getattr(other, fattrnm)):

it will check our observer attribute, but now the != call raises an error instead of just returning False, when self and other are not in the same frame.

I'm not entirely sure what the best way to solve this is. One the one hand, I see conceptually why an error is now raised when trying to compare coordinates in two different frames. On the other hand, I'm not sure how to practically solve this new issue, without making != return True when the two frames are different.

Activity

  1. ayshih commented on May 3, 2020

    @ayshih
    Contributor

    As a minor correction, our observer attribute is a standard CoordinateAttribute, so it's a frame rather than a SkyCoord.

    And, as a clarification, this observer attribute transforms everything to our HeliographicStonyhurst frame, but the obstime can be different, so the frames may not be strictly equivalent.

    I think the best solution would be to modify the frame-attribute machinery to treat coordinate attributes specially.

  2. taldcroft commented on May 4, 2020

    @taldcroft
    Member

    I'm open to suggestions, including returning False and even reverting the PR for now.

  3. ayshih commented on May 4, 2020

    @ayshih
    Contributor

    I don't think we need to change the equality behavior for this issue. To fix this, we need only to have special handling within SkyCoord.is_equivalent_frame() and BaseCoordinateFrame.is_equivalent_frame(). See my PR (#10290)

  4. ayshih commented on May 4, 2020

    @ayshih
    Contributor

    The PR now has a test with a minimal example that doesn't involve SunPy.

  5. taldcroft commented on May 4, 2020

    @taldcroft
    Member

    Thanks @ayshih for the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions