Repository navigation
Description
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
ayshih commentedon May 3, 2020
As a minor correction, our
observerattribute is a standardCoordinateAttribute, so it's a frame rather than aSkyCoord.And, as a clarification, this
observerattribute transforms everything to ourHeliographicStonyhurstframe, but theobstimecan 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.
taldcroft commentedon May 4, 2020
I'm open to suggestions, including returning False and even reverting the PR for now.
ayshih commentedon May 4, 2020
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()andBaseCoordinateFrame.is_equivalent_frame(). See my PR (#10290)ayshih commentedon May 4, 2020
The PR now has a test with a minimal example that doesn't involve SunPy.
taldcroft commentedon May 4, 2020
Thanks @ayshih for the fix!