You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This example used the ICRS object from the old API, so I'd like to propose two alternatives:
BaseCoordinateFrame carries a class method, perhaps called transform_angle_to, that takes a SkyCoord, Angle, and frame and returns another Angle in the new frame.
SkyCoord contains an angle parameter that gets transformed (if set) when SkyCoord.transform_to is called. I'm inclined against this one, since it effectively turns points (SkyCoords) into vectors. Also, since the transformation of position angles across coordinate systems would be one of the main use cases, this might require a note in the docs that the position_angle function is not related to this functionality.
This functionality would be appreciated to avoid some more wcs-handling for astropy/pyregion#43. Specifically, the ability to transform an angle measured off a point (which may not have the same coordinate system) to another coordinate system is needed.
I'm not familiar enough with WCS transformations to do this myself; I've seen @cdeil's gist attempt to find the new angle by using a small offset and pyregion's existing code to estimate it the new basis vectors with several transformations back and forth. I haven't found how the NED calculator makes the transformation.
I like that approach. How about something like this: (to use a mix of java syntax):
Angleastropy.coordinates.transform_angle(SkyCoordorigin, Angleangle, BaseCoordinateFramenew_frame)
""" Convert angle (defined as east of north from origin in origin's frame) to new_frame """
@sargas - yes, that seems fine. Thinking about it more, this could be a method of Angle actually. Note that for the first argument, it doesn't have to be SkyCoord, it could also be e.g. an ICRS frame with data (which is the underlying API, SkyCoord is just a convenience).
Similar functionality will be needed for postiion differences between two SkyCoord (and for proper motions, etc.). I'd guess we want this as part of coordinates generally rather than Angle (which is really just a Quantity with some nice input parsing). Maybe easiest to start with a function... (CC @eteq, who may have thought much more about this).
Sorry, I was unclear: I meant similar functionality is needed to transform position differences between two SkyCoord from one system to another. Position angle is just one aspect where the vector from one SkyCoord is in the sky and where one is interested in the angle only, not its norm.
separation and separation_3d, which gives the on-sky angle between two SkyCoords, or the 3d (unitful) distance.
So is the request here to do sort of the inverse of one or both of these? That is, get a skycoord that's some position angle offset from another, or offset by a specific RA and Dec?
I'm confused mostly by the use of the word "transform" - in SkyCoord, "transform" means "convert from one frame to another", which seems to be different from what you're saying (but maybe not?).
@astrofrog - ah, I see how it's done in SkyCoord.separation. Perhaps just Angle.transform_to(self, origin, new_frame), with a return-ed Angle
@eteq - I think my request is different then @mhvk, but the idea is this:
You have a point, and an angle measured from this point that depends on the coordinate system. The position angle between two SkyCoord is one example.
This angle is defined in a certain direction, so it is frame dependent.
SkyCoord.transform_to will change the point to the new coordinate system. The angle must also change numerically, but there is no function in astropy to calculate this.
If the angle is given by the position angle between two SkyCoord, then you could transform them and re-run SkyCoord.position_angle to get the new angle.
As an example, let's say you have a point at (0,0) in FK5, with a vector going due west (so, measuring from east of north, described by this point and Angle('270d')). If I transform to a coordinate frame that is the exact same as FK5 but with the poles reversed, the angle described in this new frame should be Angle('90d')
Another way to state it is that if star A is exactly due west of star B in the FK5 coordinate system (i.e., star_a.position_angle(star_b) == Angle('270d')), then after converting both stars to an upside-down FK5 system I know I should get a position angle of Angle('90d') regardless of where star B was (since it is now due east).
@eteq - sorry for the confusion. I think in the end @sargas and I would like to do similar things; in my case, suppose I have a position and proper motion in ICRS, I'd like to be able to transform both to Galactic, but so far, as I understood it, I can easily transform the coordinate only. Since, of course, the magnitude of the proper motion does not change, in the end all I really need is only the transformed position angle on the sky.
@mhvk - re: proper motion, that's definitely something we need to consider a "first class citizen" for coordinates (@adrn has been pushing this repeatedly), but I think we need to think carefully about the interface for proper motions (and radial velocities, too, to be fully 3D). But I'm I right you're thinking about this as a "lower-level" implementation for this?
In @mhvk 's case, he/she would need to get pa2 and sc1_t from sc1, pa1, and UpsideDownFK5. sc1_t is already obtained without sc2, as shown in your snippet.
Actually, I think I should ask clarification of @mhvk's case, since proper motion should be a frame-independent Angle/time AFAIK. Are you trying to transform the direction of the proper motion?
@sargas - I was simply thinking of converting μ(α), μ(δ) to μ(lᴵᴵ), μ(bᴵᴵ); you're right that of course |μ| remains the same, but the angle changes -- in just the same way your position angle would change, which is why I brought it up as an example.
@eteq - I was indeed only thinking of the low-level implementation, which requires to have a way to transform position angles -- I'm sorry that in the end my example only seems to have confused matters! But with something along the lines of what @sargas wants in place, proper motions will be all the easier to do.
@sargas - ok, so would something like this work for you?
sc1 = SkyCoord(0*u.deg,0*u.deg,frame='fk5')
pa1 = 270*u.deg
sc2 = sc1.skycoord_from_position_angle(pa1) #there's probably a better name for this...
sc1_t = sc1.transform_to(UpsideDownFK5)
sc2_t = sc2.transform_to(UpsideDownFK5)
pa2 = sc1_t.position_angle(sc2_t)
That is, the only thing that new that would need to be added to do this would be skycoord_from_position_angle (which could be useful in other circumstances, anyway).
The direction I'm coming at is that we don't really want to duplicate all the convenience functions with functions that just do the transforms and then the convenience functions - it's ok to just say that you have to do the transforms yourself. I think this would end up more as more readable code because it avoids the problem you mentioned in the initial issue comment about mixing the vector/point concepts.
But if you think that's too repetitive, maybe a utility function that just does a transform and a method in one go is the solution? So that would look something like the top three lines from the above, then the bottom three condensed into a helper function like transform_then_do([sc1, sc2], UpsideDownFK5, sc1.position_angle). That's almost as readable as the above, but more convinient if you're going to repeat many times...
@jwoillez - For "generalized transform of vectors", we definitely want to piggy-back on the work with the frames. But I think we need to think hard about the best way to do this in a way that won't be confusing to users by mixing the vector and point concepts too much - this includes the stuff @mhvk is saying about proper motions. I'm thinking this is a major goal for the version after 1.0, because it would be much more useful once we have the AltAz <-> ICRS conversions in place.
@eteq - Originally I was thinking this could be implemented analytically without approximating the temporary point (the result of the skycoord_from_position_angle function you give). As a stop-gap measure, I implemented this in an earlier pyregion PR:
If you look at other SkyCoord convenience functions (match_to_catalog_*, separation*, to_pixel), none of those depend on the frames used by the SkyCoord or the other object(s) (with the exception of to_pixel's wcs). I don't know any other use for a skycoord_from_position_angle or transform_then_do besides one possible implementation of this, either.
I did move away from this approach in order to be sure I remained consistent with previous code. Given that this will be needed whenever proper motions get handled and for @jwoillez's ideas with generalized frames, perhaps this could be tagged as a wishlist item for astropy.wcs.utils?
Activity
astrofrog commentedon Nov 10, 2014
Can we do option 1 but not bother with making it a class method? We could simply use a standalone function, right?
sargas commentedon Nov 10, 2014
I like that approach. How about something like this: (to use a mix of java syntax):
astrofrog commentedon Nov 10, 2014
@sargas - yes, that seems fine. Thinking about it more, this could be a method of Angle actually. Note that for the first argument, it doesn't have to be
SkyCoord, it could also be e.g. anICRSframe with data (which is the underlying API,SkyCoordis just a convenience).mhvk commentedon Nov 10, 2014
Similar functionality will be needed for postiion differences between two
SkyCoord(and for proper motions, etc.). I'd guess we want this as part of coordinates generally rather thanAngle(which is really just aQuantitywith some nice input parsing). Maybe easiest to start with a function... (CC @eteq, who may have thought much more about this).astrofrog commentedon Nov 10, 2014
@mhvk - positions between two
SkyCoordis already implemented, right?mhvk commentedon Nov 10, 2014
Sorry, I was unclear: I meant similar functionality is needed to transform position differences between two
SkyCoordfrom one system to another. Position angle is just one aspect where the vector from oneSkyCoordis in the sky and where one is interested in the angle only, not its norm.eteq commentedon Nov 10, 2014
@astrofrog @mhvk @sargas - I don't quite understand what is being discussed here. Some of the functionality that's related here:
SkyCoords.separationandseparation_3d, which gives the on-sky angle between twoSkyCoords, or the 3d (unitful) distance.So is the request here to do sort of the inverse of one or both of these? That is, get a skycoord that's some position angle offset from another, or offset by a specific RA and Dec?
I'm confused mostly by the use of the word "transform" - in
SkyCoord, "transform" means "convert from one frame to another", which seems to be different from what you're saying (but maybe not?).sargas commentedon Nov 10, 2014
@astrofrog - ah, I see how it's done in
SkyCoord.separation. Perhaps justAngle.transform_to(self, origin, new_frame), with a return-edAngle@eteq - I think my request is different then @mhvk, but the idea is this:
SkyCoordis one example.SkyCoord.transform_towill change the point to the new coordinate system. The angle must also change numerically, but there is no function in astropy to calculate this.If the angle is given by the position angle between two
SkyCoord, then you could transform them and re-runSkyCoord.position_angleto get the new angle.sargas commentedon Nov 10, 2014
As an example, let's say you have a point at (0,0) in FK5, with a vector going due west (so, measuring from east of north, described by this point and
Angle('270d')). If I transform to a coordinate frame that is the exact same as FK5 but with the poles reversed, the angle described in this new frame should beAngle('90d')Another way to state it is that if star A is exactly due west of star B in the FK5 coordinate system (i.e.,
star_a.position_angle(star_b) == Angle('270d')), then after converting both stars to an upside-down FK5 system I know I should get a position angle ofAngle('90d')regardless of where star B was (since it is now due east).mhvk commentedon Nov 10, 2014
@eteq - sorry for the confusion. I think in the end @sargas and I would like to do similar things; in my case, suppose I have a position and proper motion in ICRS, I'd like to be able to transform both to Galactic, but so far, as I understood it, I can easily transform the coordinate only. Since, of course, the magnitude of the proper motion does not change, in the end all I really need is only the transformed position angle on the sky.
eteq commentedon Nov 10, 2014
@sargas - so is the following snippet what you're asking about?
(Of course you'd have to define the transform to
UpsideDownFK5somewhere, but I think this gets the idea across)eteq commentedon Nov 10, 2014
@mhvk - re: proper motion, that's definitely something we need to consider a "first class citizen" for
coordinates(@adrn has been pushing this repeatedly), but I think we need to think carefully about the interface for proper motions (and radial velocities, too, to be fully 3D). But I'm I right you're thinking about this as a "lower-level" implementation for this?sargas commentedon Nov 10, 2014
@eteq Yes. This issue is about having a function that takes
sc1,pa1, andUpsideDownFK5and returnspa2One possible implementation (basically what's done in https://gist.github.com/cdeil/10597172 ) is to generate an
sc2that gives the right position angle.In @mhvk 's case, he/she would need to get
pa2andsc1_tfromsc1,pa1, andUpsideDownFK5.sc1_tis already obtained withoutsc2, as shown in your snippet.sargas commentedon Nov 10, 2014
Actually, I think I should ask clarification of @mhvk's case, since proper motion should be a frame-independent Angle/time AFAIK. Are you trying to transform the direction of the proper motion?
mhvk commentedon Nov 11, 2014
@sargas - I was simply thinking of converting μ(α), μ(δ) to μ(lᴵᴵ), μ(bᴵᴵ); you're right that of course |μ| remains the same, but the angle changes -- in just the same way your position angle would change, which is why I brought it up as an example.
@eteq - I was indeed only thinking of the low-level implementation, which requires to have a way to transform position angles -- I'm sorry that in the end my example only seems to have confused matters! But with something along the lines of what @sargas wants in place, proper motions will be all the easier to do.
jwoillez commentedon Nov 11, 2014
Can this request be generalized to transform of vectors?
Connected use cases could be:
Seems connected to SOFA/ERFA for the ICRF to ITRF transform.
eteq commentedon Nov 19, 2014
@sargas - ok, so would something like this work for you?
That is, the only thing that new that would need to be added to do this would be
skycoord_from_position_angle(which could be useful in other circumstances, anyway).The direction I'm coming at is that we don't really want to duplicate all the convenience functions with functions that just do the transforms and then the convenience functions - it's ok to just say that you have to do the transforms yourself. I think this would end up more as more readable code because it avoids the problem you mentioned in the initial issue comment about mixing the vector/point concepts.
But if you think that's too repetitive, maybe a utility function that just does a transform and a method in one go is the solution? So that would look something like the top three lines from the above, then the bottom three condensed into a helper function like
transform_then_do([sc1, sc2], UpsideDownFK5, sc1.position_angle). That's almost as readable as the above, but more convinient if you're going to repeat many times...@jwoillez - For "generalized transform of vectors", we definitely want to piggy-back on the work with the frames. But I think we need to think hard about the best way to do this in a way that won't be confusing to users by mixing the vector and point concepts too much - this includes the stuff @mhvk is saying about proper motions. I'm thinking this is a major goal for the version after 1.0, because it would be much more useful once we have the AltAz <-> ICRS conversions in place.
sargas commentedon Nov 23, 2014
@eteq - Originally I was thinking this could be implemented analytically without approximating the temporary point (the result of the
skycoord_from_position_anglefunction you give). As a stop-gap measure, I implemented this in an earlier pyregion PR:If you look at other
SkyCoordconvenience functions (match_to_catalog_*,separation*,to_pixel), none of those depend on the frames used by theSkyCoordor the other object(s) (with the exception ofto_pixel'swcs). I don't know any other use for askycoord_from_position_angleortransform_then_dobesides one possible implementation of this, either.I did move away from this approach in order to be sure I remained consistent with previous code. Given that this will be needed whenever proper motions get handled and for @jwoillez's ideas with generalized frames, perhaps this could be tagged as a wishlist item for
astropy.wcs.utils?bsipocz commentedon Mar 27, 2019
@eteq @adrn - isn't this one being addressed over the years by e.g. http://docs.astropy.org/en/stable/coordinates/matchsep.html#offsets ?
adrn commentedon Sep 23, 2026
Only 7 years late, but I think this is resolved by
directional_offset_by. Feel free to reopen if you disagree!