Skip to content

Add BaseBodycentricRepresentation - #14851

Merged
mhvk merged 3 commits into
astropy:mainfrom
oudeis-io:geodetic-repr-options
Jun 23, 2023
Merged

mhvk merged 3 commits into
astropy:mainfrom
oudeis-io:geodetic-repr-options

Conversation

@cmarmo

@cmarmo cmarmo commented May 19, 2023 •

Copy link
Copy Markdown
Member

Description

This pull request adds the possibility to create geodetic representations described by [planetocentric latitudes]
(https://en.wikipedia.org/wiki/Latitude#Geodetic_and_geocentric_latitudes), west positive longitudes, longitudes spanning from 0 to 360 degrees.
The default behavior is backward compatible.
Suggested in #11170 (comment).

Towards #11170.

This work is funded by the Europlanet 2024 Research Infrastructure (RI) Grant.

@github-actions

github-actions Bot commented May 19, 2023 •

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.

  • Do the proposed changes actually accomplish desired goals?
  • Do the proposed changes follow the Astropy coding guidelines?
  • Are tests added/updated as required? If so, do they follow the Astropy testing guidelines?
  • Are docs added/updated as required? If so, do they follow the Astropy documentation guidelines?
  • Is rebase and/or squash necessary? If so, please provide the author with appropriate instructions. Also see "When to rebase and squash commits".
  • Did the CI pass? If no, are the failures related? If you need to run daily and weekly cron jobs as part of the PR, please apply the "Extra CI" label. Codestyle issues can be fixed by the bot.
  • Is a change log needed? If yes, did the change log check pass? If no, add the "no-changelog-entry-needed" label. If this is a manual backport, use the "skip-changelog-checks" label unless special changelog handling is necessary.
  • Is this a big PR that makes a "What's new?" entry worthwhile and if so, is (1) a "what's new" entry included in this PR and (2) the "whatsnew-needed" label applied?
  • Is a milestone set? Milestone must be set but we cannot check for it on Actions; do not let the green checkmark fool you.
  • At the time of adding the milestone, if the milestone set requires a backport to release branch(es), apply the appropriate "backport-X.Y.x" label(s) before merge.

@pllim pllim added this to the v6.0 milestone May 19, 2023
@pllim
pllim requested a review from mhvk May 19, 2023 22:02
@cmarmo
cmarmo force-pushed the geodetic-repr-options branch from d3f53fd to a6e30fb Compare May 19, 2023 22:26
@cmarmo

cmarmo commented May 19, 2023

Copy link
Copy Markdown
Member Author

It seems like I'm still confused about units conversions... :(

@cmarmo
cmarmo force-pushed the geodetic-repr-options branch 3 times, most recently from f1a8a58 to 25fb355 Compare May 25, 2023 20:11
@cmarmo

cmarmo commented May 25, 2023

Copy link
Copy Markdown
Member Author

For the sake of completeness, this pull request makes the BaseGeodeticRepresentation closer to the Planetary Data System class Geodetic_Model.

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cmarmo - Good to have these options, but I do think at least some of them should be subclasses rather than options on the base class. For _ellipsoid', I ended up agreeing it was not necessary, since having it on the baseclass gives a little overhead only at class creation time, and in the end it is really the same thing as far as the actual calculations are concerned. But here the calculations for conversion to/from cartesian are effectively separated, making the code more complicated and giving overhead for every calculation. Generally, I think each different interpretation of the coordinates should have its own (base) class -- just like PhysicsSpherical is a different class from Spherical. I would say the rule should be that the moment from_cartesian and to_cartesian depend on any class attribute, it would be better to have a different class.
So, I think we definitely should have a separate base class for the planetocentric latitudes (BasePlanetoCentric?). I think we also will be better off with a separate class for West longitudes, though given the rarity of its use, perhaps this is best implemented via a mixin class that overrides from_cartesian and to_cartesian changing the sign of the longitude appropriately.
Only for _wrap_angle, I think it is fine to leave that on the base class -- the calculations do not depend on it, one can see it as similar to changing the class of the attributes.

to quantities holding correct values (with units of length and dimensionless,
respectively), or alternatively an ``_ellipsoid`` attribute to the relevant ERFA
index (as passed in to `erfa.eform`).
Longitudes are east positive and span from -180 to 180 degrees by default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have separate classes; see main comment.

@cmarmo
cmarmo force-pushed the geodetic-repr-options branch from 25fb355 to 50c29f4 Compare June 14, 2023 10:50

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the change to a different base class. That does feel much better!

But, seeing this again, I wonder about the approach for wrap_angle. Really, the problem is that we have a Longitude class that has a default of 360 degrees, while we would like 180 degrees. Would it make sense to just define

class Longitude180(Longitude):
    _default_wrap_angle = Angle(180 * u.deg)

and then use that? Then anyone who wants to have a different default, can just choose to use a different Longitude class. And we don't have to deal with the new _wrap_angle attribute.

p.s. Need to think a bit about the mixin still... And I haven't looked in detail over the tests.

raise AttributeError(
f"{cls.__name__} requires '_ellipsoid' or '_equatorial_radius' and '_flattening'."
)
if not hasattr(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small detail, but could do

if not u.Quantity(cls._wrap_angle).unit.is_equivalent(u.deg):

(but see my larger comment about _wrap_angle)

@cmarmo

cmarmo commented Jun 15, 2023

Copy link
Copy Markdown
Member Author

Thanks for your review @mhvk !
I have addressed the "obvious" fixes.
I have to better understand units and wrap angles for the rest of the comments.... I will be back ASAP.
Thanks again for your precious comments.

@cmarmo cmarmo changed the title Add planetary useful options to BaseGeodeticRepresentation Add BaseBodycentricRepresentation Jun 16, 2023
@cmarmo

cmarmo commented Jun 16, 2023

Copy link
Copy Markdown
Member Author

The tests are failing because the class WGS84BodycentricRepresentation, which I have defined in order to test the ability of using _ellipsoid with a BaseBodycentricRepresentation, persists and it is used by earth.py.
My understanding was that the teardown_function would take care of "preserving the original REPRESENTATION_CLASSES", so this failure should not happen.
Anyway it also seems like the selection of a representation only based on the ellipsoid in EarthLocation may lead to mistakes now that BaseBodycentricRepresentation also uses an ellipsoid.

On the long term, I see the importance of changing EarthLocation to a representation, but how should I proceed on the short term? Should I remove the possibility of defining a bodycentric representation using an ellipsoid?

Any suggestion? Thanks a lot!

@mhvk

mhvk commented Jun 17, 2023

Copy link
Copy Markdown
Contributor

Simplest right now would seem to not allow ellipsoid for Bodycentric. As is, ellipsoid is only defined for Earth, and it is only used in EarthLocation, so I think this is fine.

@cmarmo
cmarmo force-pushed the geodetic-repr-options branch from d17d2dc to 265e9bb Compare June 19, 2023 21:09
@cmarmo

cmarmo commented Jun 20, 2023

Copy link
Copy Markdown
Member Author

Hi @mhvk . I believe I have removed all the unnecessary conversions to degrees, following your comments.
I have updated the title of the pull request and the changelog to reflect what is done in the code: ie the introduction of a new BaseBodycentricRepresentation.
However, I have kept the attribute _wrap_angle and defaulted it at 360 for BaseBodycentricRepresentation as this is the default recommended by Cartographic Coordinates & Rotational Elements Working Group (see https://rdcu.be/b32WL page 26)....
I'm not completely convinced in having it removed ...

But if we stick with using _wrap_angle, we need to think a bit about how we can potentially make it faster - right now, the wrapping is done twice (I think).

I guess this is also because I don't understand this previous comment

@mhvk

mhvk commented Jun 22, 2023

Copy link
Copy Markdown
Contributor

@cmarmo - thanks for the changes. I'm still not sold on the _wrap_angle attribute - essentially you are making how data is displayed part of the class, while I feel what the class should cares about is only how data is used. And for the use of a longitude, it really doesn't matter what the wrap angle is (just like its units don't matter). I still think the way forward is to define a new Longitude180 class and use that where relevant.

However, I also think this discussion is actually distracting from the main point of this PR, which is to introduce a BaseBodycentricRepresentation class. How about splitting this up in pieces? I.e., here remove all stuff with wrap_angle and just get the basic class working.

Indeed, while I think the WestLongitude mixin class is the right approach, I'd even tend to put that in a separate PR as well, where it could include an update to the docs that make clearer what the use case is.

@cmarmo

cmarmo commented Jun 22, 2023

Copy link
Copy Markdown
Member Author

However, I also think this discussion is actually distracting from the main point of this PR, which is to introduce a BaseBodycentricRepresentation class. How about splitting this up in pieces? I.e., here remove all stuff with wrap_angle and just get the basic class working.

Indeed, while I think the WestLongitude mixin class is the right approach, I'd even tend to put that in a separate PR as well, where it could include an update to the docs that make clearer what the use case is.

I guess I'm loosing focus indeed... I need the Bodycentric representation for the frame definition, while west/east and 180/360 are not needed.... and I'm running out of time... ⏲️
Let's rescope the PR.

@mhvk

mhvk commented Jun 22, 2023

Copy link
Copy Markdown
Contributor

OK, thanks, ping me when I should look again. And apologies for not realizing this earlier!

@cmarmo

cmarmo commented Jun 22, 2023

Copy link
Copy Markdown
Member Author

And apologies for not realizing this earlier!

No problem! I'm treasuring all the comments for the follow-up! :)

@cmarmo
cmarmo force-pushed the geodetic-repr-options branch from 317bc2b to 918a6b3 Compare June 22, 2023 21:53
@cmarmo

cmarmo commented Jun 22, 2023

Copy link
Copy Markdown
Member Author

@mhvk thanks for your patience!
Is the PR acceptable in its current status?
Should I add something in the what's new section?

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! There are only nitpicks and suggestions for the docstrings left. But also: do indeed add to the whatsnew entry you already created for other geodetic representations.

cls._equatorial_radius, cls._flattening, cart.get_xyz(xyz_axis=-1)
)
return cls(lon, lat, height, copy=False)
return cls(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, but could you get this back to the default format? Be sure to delete the final , after copy=False, otherwise black will break it over several lines again.

to quantities holding correct values (with units of length and dimensionless,
respectively), or alternatively an ``_ellipsoid`` attribute to the relevant ERFA
index (as passed in to `erfa.eform`).
Longitudes are east positive and span from 0 to 360 degrees by default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: might as well leave this out for now.

Instead, I think here is the place to mention how lon, lat, and height are defined relative to the ellipsoid.

Alternatively, you could clarify the definition in geodetic_base_doc above (and then not use it for bodycentric)

Subclasses need to set attributes ``_equatorial_radius`` and ``_flattening``
to quantities holding correct values (with units of length and dimensionless,
respectively).
Longitudes are east positive and span from 0 to 360 degrees by default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I'd remove this for now and instead describe how the parameters are used (and how it is different from geodetic).

Alternatively, do not use geodetic_base_doc, but instead write a complete docstring here that also describes how lat is defined.

lon,
lat,
height,
copy=False,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, could you bring this on a single line?

@@ -0,0 +1,2 @@
Add ``BaseBodycentricRepresentation``, a new spheroidal representation for bodycentric
latitudes and longitudes spanning from 0 to 360 degrees.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the "spanning from 0 to 360 degrees" here too.

Comment thread docs/coordinates/representations.rst Outdated
`~astropy.coordinates.BaseBodycentricRepresentation` is the coordinate representation
recommended by the Cartographic Coordinates & Rotational Elements Working Group
(see for example its `2019 report <https://rdcu.be/b32WL>`_): the bodicentric latitude
and longitude are spherical latitude and longitude originated at the barycenter of the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

originated at -> relative to

Comment thread docs/coordinates/representations.rst Resolved
Comment thread docs/coordinates/representations.rst Outdated
degrees.
`~astropy.coordinates.BaseBodycentricRepresentation` is the coordinate representation
recommended by the Cartographic Coordinates & Rotational Elements Working Group
(see for example its `2019 report <https://rdcu.be/b32WL>`_): the bodicentric latitude

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bodicentric -> bodycentric

Comment thread docs/coordinates/representations.rst Resolved

@eerovaher eerovaher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm letting @mhvk do the main review, but I do have a few comments.

Comment on lines +148 to +150
x_spheroid = self._equatorial_radius * coslat * coslon
y_spheroid = self._equatorial_radius * coslat * sinlon
z_spheroid = self._equatorial_radius * (1 - self._flattening) * sinlat

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables are unused.

Suggested change
x_spheroid = self._equatorial_radius * coslat * coslon
y_spheroid = self._equatorial_radius * coslat * sinlon
z_spheroid = self._equatorial_radius * (1 - self._flattening) * sinlat

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed! They are no longer needed as the calculation is done for r already.

z_spheroid = self._equatorial_radius * (1 - self._flattening) * sinlat
r = (
self._equatorial_radius
* np.sqrt(coslat**2 + ((1 - self._flattening) * sinlat) ** 2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use np.hypot() here:

Suggested change
* np.sqrt(coslat**2 + ((1 - self._flattening) * sinlat) ** 2)
* np.hypot(coslat, (1 - self._flattening) * sinlat)

Comment on lines +172 to +175
[
WGS84GeodeticRepresentation,
IAUMARS2000BodycentricRepresentation,
],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this fit on one line?

Suggested change
[
WGS84GeodeticRepresentation,
IAUMARS2000BodycentricRepresentation,
],
[WGS84GeodeticRepresentation, IAUMARS2000BodycentricRepresentation],

If it does then the other similar cases should be updated analogously.

Comment thread docs/coordinates/representations.rst Outdated
Comment on lines +52 to +53
degrees, the height is the elevation above the surface of the spheroid (measured on the
perpendicular to the surface).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be replaced with the following?

Suggested change
degrees, the height is the elevation above the surface of the spheroid (measured on the
perpendicular to the surface).
degrees, the height is the elevation above the surface of the spheroid (measured
perpendicular to the surface).

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cmarmo - only some nitpicks left beyond @eerovaher's comments. With those, I'll be happy to merge!


Subclasses need to set attributes ``_equatorial_radius`` and ``_flattening``
to quantities holding correct values (with units of length and dimensionless,
respectively). the bodicentric latitude and longitude are spherical latitude

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the bodicentric" -> "The bodycentric"

Comment on lines +148 to +150
x_spheroid = self._equatorial_radius * coslat * coslon
y_spheroid = self._equatorial_radius * coslat * sinlon
z_spheroid = self._equatorial_radius * (1 - self._flattening) * sinlat

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed! They are no longer needed as the calculation is done for r already.

d = np.hypot(p, cart.z)
lat = np.arctan2(cart.z, p)
p_spheroid = cls._equatorial_radius * np.cos(lat)
z_spheroid = (cls._equatorial_radius * (1 - cls._flattening)) * np.sin(lat)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Total nitpick, but outer parentheses are not necessary.

Comment thread docs/coordinates/representations.rst Outdated
This is used internally for the standard Earth ellipsoids used in
`~astropy.coordinates.BaseGeodeticRepresentation` is used internally for the standard
Earth ellipsoids used in
`~astropy.coordinates.EarthLocation`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe combine with last line while you are making the last changes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I'm not sure to understand this comment....

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meant to combine the two lines to give```
Earth ellipsoids used in ~astropy.coordinates.EarthLocation

Comment thread docs/coordinates/representations.rst Outdated
recommended by the Cartographic Coordinates & Rotational Elements Working Group
(see for example its `2019 report <https://rdcu.be/b32WL>`_): the bodycentric latitude
and longitude are spherical latitude and longitude relative to the barycenter of the
body, the height is the distance from the spheroid surface on the line of sight.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the height is the distance from the spheroid surface on the line of sight" -> "height is the distance from the surface (measured radially)."

Comment thread docs/coordinates/representations.rst Outdated

Creating Your Own Geodetic Representation
-----------------------------------------
Creating Your Own Geodetic and Bodycentric Representation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make plural: "Representations"

@mhvk

mhvk commented Jun 23, 2023

Copy link
Copy Markdown
Contributor

@cmarmo - separately from this PR, my sense would be to try to follow this up with adding some of the I/O and WCS system things you have been mentioning rather than worry about west longitude and wrap angles!

Astropy also offers a `~astropy.coordinates.BaseGeodeticRepresentation` and
a `~astropy.coordinates.BaseBodycentricRepresentation` useful to
create specific representations on spheroidal bodies.
This is used internally for the standard Earth ellipsoids used in

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean to have this part about the internal use to be removed!

Subclasses need to set attributes ``_equatorial_radius`` and ``_flattening``
to quantities holding correct values (with units of length and dimensionless,
respectively). the bodicentric latitude and longitude are spherical latitude
respectively). the bodycentric latitude and longitude are spherical latitude

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to capitalize "The"

The latitude is a value ranging from -90 to 90 degrees, the longitude from 0 to 360
degrees.

`~astropy.coordinates.BaseGeodeticRepresentation` is used internally for the standard

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, sorry, you moved it here! This is better!

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks great now. I think I'll just merge, the one uncapitalized "t" can be done at some other time!

@mhvk
mhvk merged commit 9e3d836 into astropy:main Jun 23, 2023
@mhvk

mhvk commented Jun 23, 2023

Copy link
Copy Markdown
Contributor

Thanks, @cmarmo!!

@cmarmo

cmarmo commented Jun 23, 2023

Copy link
Copy Markdown
Member Author

Thanks @mhvk for your patience!

@cmarmo
cmarmo deleted the geodetic-repr-options branch June 23, 2023 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants