Add velocity support to coordinate frames and transformations#6219
Add velocity support to coordinate frames and transformations#6219eteq merged 66 commits intoastropy:masterfrom
Conversation
856e89b to
68457ec
Compare
|
@adrn - I have some smaller comments in the PR, but overall this looks very nice. Good to see that it all meshes together so well! I guess the largest comment is worth bringing up here too: should One other comment, just to be sure: I guess you and @eteq decided that |
|
Note: Will need minor rebase after #6236 is merged. |
bc3247b to
472f385
Compare
Do you mean
Yes, that was my (our?) plan -- will make sure we clearly document this! cc @mhvk |
|
An API question here, also relevant for #6226. I'm sure this has been discussed, so forgive me for that. This PR handles transformations between frames, but what should we do with transformations when the Star = coord.ICRS(ra=130*u.deg, dec=22*u.deg, pm_ra=100*u.mas/u.y, pm_dec=2*u.mas/u.yr, distance=100*u.pc, obstime=Time(57923.430, format='mjd'))
Star.transform_to(coord.ICRS(obstime="J2000")) |
|
@StuartLittlefair - I don't think the update currently happens -- one can clearly not assume much! I agree with your expectation, so think we either have to implement it (not difficult in itself, though it will become much more useful once we properly include errors), or raise if the |
|
p.s. The "not difficult in itself" is of course an understatement. It means we need to presume 0 for PM/RV values that are not present. My own sense would be strictness here: raise for missing values, with the exception message saying one can put in 0 if needed (just like I suggested one has to put a nominal distance for transformations that change the observer's perspective). |
|
Agreed - this is the approach used inside erfa as well, except that they automatically insert 0 for missing data and return a warning flag. I agree we should be more cautious. |
turns out there were *two* problems: self._representation was being used instead of self.representation (which initializes an absent _representation), and self._data.differential was failing when _data was None or differentials were absent
…seCoordinateFrame
…ion and velocity of galactic center
mhvk
left a comment
There was a problem hiding this comment.
I went over this again with a fairly fine comb, and found mostly nitpicks, but also some more serious issues, in particular the test for unequal obstime.
astropy/coordinates/baseframe.py
Outdated
|
|
||
| if (getattr(self.data, 'differentials', None) and | ||
| hasattr(self, 'obstime') and hasattr(new_frame, 'obstime') and | ||
| np.all(self.obstime == new_frame.obstime)): |
There was a problem hiding this comment.
Hmm, this surely has to be np.any(self.obstime != new_frame.obstime). And that this should be tested!
There was a problem hiding this comment.
Also, just to be sure, since ICRS does not have an obstime, does this mean transforming to it will always work?
There was a problem hiding this comment.
Hmm, this surely has to be np.any(self.obstime != new_frame.obstime). And that this should be tested!
Good point! I recall writing a test for this, but I don't see it now. It's possible I did not commit it ... (it was ~1am local time, so I will blame that...)
Also, just to be sure, since ICRS does not have an obstime, does this mean transforming to it will always work?
No, because in most (all?) cases, to get to ICRS from something that has an obstime you first have to do a transform into J2000 obstime. Certainly the AltAz (the most important case) works that way.
There was a problem hiding this comment.
I take back that last part... I was getting those confused with the FK5 which have a specified equinox. So yes, it does work, and I'm adding a test for that.
There was a problem hiding this comment.
Possibly, it should be that if obstime is not given on a frame, it is assumed to be J2000 for this purposes. Of course, on SkyCoord, this would just work, since there the obstime is propagated.
astropy/coordinates/baseframe.py
Outdated
| data_repr = 'Data:\n' + data_repr | ||
|
|
||
| if (getattr(self.data, 'differentials', None) and | ||
| 's' in self.data.differentials): |
| RepresentationMapping('lat', 'alt') | ||
| ], | ||
| r.SphericalCosLatDifferential: [ | ||
| RepresentationMapping('d_lon_coslat', 'pm_az', u.mas/u.yr), |
There was a problem hiding this comment.
This should be pm_az_cosalt - and needs a test case...
There was a problem hiding this comment.
Though, what do you mean by a test case? You mean tests for proper motions in AltAz in general?
There was a problem hiding this comment.
The test case I meant was iniatializing - presumably, as it was, it would fail with AltAz(..., pm_az_cosalt=..., ...).
| RepresentationMapping('d_distance', 'radial_velocity', u.km/u.s), | ||
| ], | ||
| r.SphericalDifferential: [ | ||
| RepresentationMapping('d_lon', 'pm_ra', u.mas/u.yr), |
There was a problem hiding this comment.
Oops, copy & paste mistake: should be pm_lon and pm_lat.
| A representation object or ``None`` to have no data (or use the other | ||
| keywords below). | ||
|
|
||
| ra : `Angle`, optional, must be keyword |
There was a problem hiding this comment.
It is not true that this must be a keyword... (and same for all up to radial_velocity)
There was a problem hiding this comment.
All of these instances of "must be keyword" are from master...would you like me to address them here?
e.g., https://github.com/astropy/astropy/blob/master/astropy/coordinates/builtin_frames/icrs.py#L27
There was a problem hiding this comment.
I'd call this either a "bug" or "docfix", so should do it in a separate PR
There was a problem hiding this comment.
It mostly annoys me, but as long as it gets done, that's fine.
There was a problem hiding this comment.
I added a note to #6260 to remind me to do this.
| representation : `BaseRepresentation` or None | ||
| A representation object or None to have no data (or use the other keywords) | ||
|
|
||
| l : `Angle`, optional, must be keyword |
There was a problem hiding this comment.
"must be keyword" is not true.
| rmlat = RepresentationMapping('lat', 'lat', 'recommended') | ||
| component_list.insert(0, rmlat) | ||
|
|
||
| lists_done.append(component_list) |
There was a problem hiding this comment.
Ah, now see that we don't yet support velocities. Maybe add TODO here?
| representation : `BaseRepresentation` or None | ||
| A representation object or None to have no data (or use the other keywords) | ||
|
|
||
| sgl : `Angle`, optional, must be keyword |
There was a problem hiding this comment.
The "must be keyword" again is not true.
| if allowed_classes is not None: | ||
| self.allowed_classes = tuple(allowed_classes) | ||
| else: | ||
| self.allowed_classes = None |
There was a problem hiding this comment.
Maybe just set to BaseDifferential? That makes the check below more straightforward.
|
|
||
| # two classes | ||
| rep2 = icrs.represent_as(r.CartesianRepresentation, | ||
| r.SphericalCosLatDifferential) |
There was a problem hiding this comment.
Do we really want a test that checks unwanted behaviour? The reason that this doesn't feel is only because of the work-around for UnitSphericalRepresentation and RadialDifferential! I'd remove this test and write a TODO that things like this should fail in the future (or make them fail already...).
|
On including this in 2.0, I think it is quite close, but am not sure how much gain it is to people if Overall, I'm neutral on whether to include this in 2.0 (though if forced to choose, I'd not). |
My thoughts exactly - in particular, the notable time pressure is the Gaia data release in ~April 2018. If no PMs are in until 3.0, then users have at best a few months to learn/experiment, whereas this way, they have a fighting chance of getting code for Gaia in that actually has a stable API (assuming we do that in 3.0). I agree an LTS is not the best time to do this, but I think the externalities are forcing our hand here... |
|
(I just pushed up a PR to address the |
Pretty sure this is a holdover. As I mentioned above I think this is best addressed in a follow-on PR (and is docs so we can do it later, so I'd say not in this PR) |
eteq
left a comment
There was a problem hiding this comment.
Guess I should have done this before... but I'm happy with it as it stands.
|
Sorry I missed @mhvk's comments above:
I agree with @eteq's points above, and about preparing for Gaia.
I think we can guarantee that the frame-level initialization of coordinates with proper motions will be stable, no? That is, I think it is reasonable to assume that |
|
Alright, since everything is passing, I think we can go ahead and put this in, as @adrn and I think it's good to get this in for an experimental basis. @mhvk, I took your "neutral" above as being "if you're the deciding vote you vote no". But if you really think we shouldn't, there's still a window where we could back it (and #6226) out between now and release, as it's a straightforward revert commit of the merge. But I do think this is the best way forward, following from the original implementation of coordinates where we started with an experimental API, kept as much of it as we could (especially the higher-level parts) and used that to build the better system. Appreciate everyone's help with this, especially @mhvk and @StuartLittlefair ! (and @adrn of course) |
Add velocity support to coordinate frames and transformations
|
🎆 🎆 🎆 (And now on to |
This is the 3rd of several PR's that add support for velocities in
astropy.coordinates.This PR focuses on the high-level API: passing velocity data in to frames and
SkyCoord.