Some of the corner-case tests in #6944 revealed some problematic behavior for frames that have velocities where the actual representation is UnitSpherical
. It turns out that this is true. The cases below illustrate the issue:
Note also that if #6944 is merged, it has a couple places with work-arounds for this bug. If this bug is fixed those work-arounds should be removed (search the coordinates
sub-package for #7028
to find them).
This works:
>>> f = ICRS(1*u.deg, 2*u.deg)
>>> f.cartesian
<CartesianRepresentation (x, y, z) [dimensionless]
( 0.99923861, 0.01744177, 0.0348995)>
But these two cases do not:
>>> f = ICRS(1*u.deg, 2*u.deg,
pm_dec=1*u.mas/u.yr, pm_ra_cosdec=2*u.mas/u.yr, radial_velocity=10*u.km/u.s)
>>> f.represent_as('cartesian', in_frame_units=True)
UnitConversionError: 'mas / (rad yr)' (frequency) and 'km / s' (speed) are not convertible
>>> f = ICRS(1*u.deg, 2*u.deg,
pm_dec=1*u.mas/u.yr, pm_ra_cosdec=2*u.mas/u.yr)
>>> g = f.transform_to(GCRS)
>>> g.cartesian
UnitConversionError: '1 / s' (frequency) and 'km / s' (speed) are not convertible
It's probably a useful clue that in the second failing case, f.cartesian
does work, but something in the transformation to GCRS is what makes it start failing. It's possible these are subtly different issues, but they are close enough that they probably have to be solved together.
@adrn or @mhvk, any idea what's going on here? One could argue that at least the transformation step above is somewhat ill-defined, but one should still be able to get out the cartesian representation even if the units are a bit odd...
Hi @eteq ,
I was trying to work on this issue. But in the example case,
>>> f = ICRS(1*u.deg, 2*u.deg,
pm_dec=1*u.mas/u.yr, pm_ra_cosdec=2*u.mas/u.yr, radial_velocity=10*u.km/u.s)
>>> f.represent_as('cartesian', in_frame_units=True)
The example has no distance
in it, but rather has a radial_velocity
. I didn't understand what exactly it means. Also, If I put some distance in the frame, it works perfectly!
Can you please make me understand the issue, I am getting confused.
@shreyasbapat Could you please try to see if https://github.com/astropy/astropy/pull/9064 fixes this issue? (Edit: it doesn't)
>>> f = ICRS(1*u.deg, 2*u.deg,
pm_dec=1*u.mas/u.yr, pm_ra_cosdec=2*u.mas/u.yr, radial_velocity=10*u.km/u.s)
>>> f.represent_as('cartesian', in_frame_units=True)
UnitConversionError: 'mas / (rad yr)' (frequency) and 'km / s' (speed) are not convertible
I think this one is unsolvable: without a distance, one cannot convert a proper motion to a spatial velocity, or a spatial velocity to an agular one. So, I think for this case, we simply need to make sure the error message is clearer (triggered by having an RV but no distance).
>>> f = ICRS(1*u.deg, 2*u.deg,
pm_dec=1*u.mas/u.yr, pm_ra_cosdec=2*u.mas/u.yr)
>>> g = f.transform_to(GCRS)
>>> repr(g)
# error
>>> g.data
<CartesianRepresentation (x, y, z) [dimensionless]
(0.99923901, 0.01742676, 0.03489572)
(has differentials w.r.t.: 's')>
g.data.differentials
<CartesianDifferential (d_x, d_y, d_z) in 1 / s
(6.07736084e-13, -1.85772092e-11, -8.12625661e-12)>
This is quite a bit more subtle. Without proper motion, g
is UnitSpherical
, which makes sense, and here it should be too, so there is something wrong with the transformation. For completeness, representing it on the unit sphere does work:
g.represent_as('unitspherical')
Out[24]:
<UnitSphericalRepresentation (lon, lat) in rad
(0.01743826, 0.0349028)
(has differentials w.r.t.: 's')>
In [25]: g.represent_as('unitspherical').differentials['s']
Out[25]:
<UnitSphericalDifferential (d_lon, d_lat) in rad / s
(-1.85963079e-11, -8.13120751e-12)>
But even so, g.cartesian
should work too - here, the problem is that frames decide for the user what units are sensible, insisting that a cartesian velocity is in km/s
(of course, this goes back to my long-standing complaint that coordinate units in the representation are decided for me...): https://github.com/astropy/astropy/blob/c3dc7b38303b3615945aa36a11ebf7bd31d5cc0a/astropy/coordinates/baseframe.py#L1744-L1753
The units themselves are gotten from:
g.representation_info
{astropy.coordinates.representation.CartesianRepresentation: {'names': ['x',
'y',
'z'],
'units': [None, None, None]},
astropy.coordinates.representation.UnitSphericalRepresentation: {'names': ('ra',
'dec'),
'units': (Unit("deg"), Unit("deg"))},
astropy.coordinates.representation.RadialRepresentation: {'names': ['distance'],
'units': [None]},
astropy.coordinates.representation.SphericalRepresentation: {'names': ('ra',
'dec',
'distance'),
'units': (Unit("deg"), Unit("deg"), None)},
astropy.coordinates.representation.PhysicsSphericalRepresentation: {'names': ['phi',
'theta',
'r'],
'units': [Unit("deg"), Unit("deg"), None]},
astropy.coordinates.representation.CylindricalRepresentation: {'names': ['rho',
'phi',
'z'],
'units': [None, Unit("deg"), None]},
astropy.coordinates.representation.CartesianDifferential: {'names': ('v_x',
'v_y',
'v_z'),
'units': (Unit("km / s"), Unit("km / s"), Unit("km / s"))},
astropy.coordinates.representation.UnitSphericalDifferential: {'names': ('pm_ra',
'pm_dec'),
'units': (Unit("mas / yr"), Unit("mas / yr"))},
astropy.coordinates.representation.SphericalDifferential: {'names': ('pm_ra',
'pm_dec',
'radial_velocity'),
'units': (Unit("mas / yr"), Unit("mas / yr"), Unit("km / s"))},
astropy.coordinates.representation.UnitSphericalCosLatDifferential: {'names': ('pm_ra_cosdec',
'pm_dec'),
'units': (Unit("mas / yr"), Unit("mas / yr"))},
astropy.coordinates.representation.SphericalCosLatDifferential: {'names': ('pm_ra_cosdec',
'pm_dec',
'radial_velocity'),
'units': (Unit("mas / yr"), Unit("mas / yr"), Unit("km / s"))},
astropy.coordinates.representation.RadialDifferential: {'names': ['d_distance'],
'units': [None]},
astropy.coordinates.representation.PhysicsSphericalDifferential: {'names': ['d_phi',
'd_theta',
'd_r'],
'units': [None, None, None]},
astropy.coordinates.representation.CylindricalDifferential: {'names': ['d_rho',
'd_phi',
'd_z'],
'units': [None, None, None]}}
One sees here that CartesianDifferential
is the only one that is wrong, which is because it has preferred units set at all.
Which probably means that the fix in #9086 is OK with a small modification: one should try to go to the requested units but not care if that fails.