Astropy: frames with velocities and a "unit" representation fail to convert to cartesian

Created on 23 Dec 2017  ·  3Comments  ·  Source: astropy/astropy

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

Bug coordinates

All 3 comments

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)

9086 reminded me of this issue. For the two cases:

No distance but with RV

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

RV introduced by coordinate transformation

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

olebole picture olebole  ·  34Comments

aphearin picture aphearin  ·  40Comments

eteq picture eteq  ·  59Comments

bsipocz picture bsipocz  ·  32Comments

eteq picture eteq  ·  50Comments