Skip to content

Add support for equatorial_radius and flattening in BaseGeodeticRepresentation. - #14763

Merged
mhvk merged 4 commits into
astropy:mainfrom
oudeis-io:geodetic-representation-pr
May 11, 2023
Merged

mhvk merged 4 commits into
astropy:mainfrom
oudeis-io:geodetic-representation-pr

Conversation

@cmarmo

@cmarmo cmarmo commented May 5, 2023 •

Copy link
Copy Markdown
Member

Description

This pull request adds support for equatorial_radius and flattening in BaseGeodeticRepresentation.
A new class StandardGeodeticRepresentation is added inheriting from BaseGeodeticRepresentation, retrieving spheroid attributes from a standard code.
All geodetic representations classes are factorized into geodetic.py.

Tests are added.

Follows the suggestion in #14714 (review).

Towards #11170.

Thanks for considering it.

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

@github-actions

github-actions Bot commented May 5, 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.

@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch 2 times, most recently from 5eeecd0 to 923ce18 Compare May 5, 2023 22:27
@pllim pllim added this to the v6.0 milestone May 5, 2023
@pllim
pllim requested a review from mhvk May 5, 2023 23:00
@cmarmo

cmarmo commented May 6, 2023

Copy link
Copy Markdown
Member Author

I am able to reproduce the test failure locally with

python -m tox -e py311-test-double

I am still trying to understand why ... 🤔

@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, this looks great, and hence most of my comments (and perhaps confusion) are about names... I haven't quite figured out the best way forward, but think I better just submit my present review since you may have better ideas.

p.s. Review is far easier with things split out - thanks very much for humouring me!

Comment thread astropy/coordinates/geodetic.py
Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated
Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated
Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated
Comment thread docs/changes/coordinates/14763.feature.rst Outdated
Comment thread docs/changes/coordinates/14763.feature.rst Outdated
Comment thread astropy/coordinates/geodetic.py
@mhvk

mhvk commented May 7, 2023

Copy link
Copy Markdown
Contributor

Having just added the "whatsnew-needed" label, I think what we also have to do is to add some documentation... I think a short additional section at the end of https://docs.astropy.org/en/latest/coordinates/representations.html#creating-your-own-representations should be good enough for now.

@cmarmo

cmarmo commented May 8, 2023 •

Copy link
Copy Markdown
Member Author

@mhvk thanks for your review!
Before addressing your comments, I would like to clarify the issue about file/module and class names.

  1. My understanding is that the representation module-to-be contains classes representing different ways of describing the coordinates. The current BaseGeodeticClass is defined by two angles and a length, where the latitude is defined by the angle between the x-axis and the vertical to the surface at a specific point of the spheroid.
    Be the spheroid defined by a standard code or flattening and equatorial radius, does not change the essence of the representation. This is not the same as eg the spherical representation and the unit sphere representation: in that case the needed coordinates really change (r is not needed in the second).
    That said, I would like to ask you to reconsider the creation of a new class (the one I called StandardGeodeticRepresentation): this will automatically solve some of your comments (Add support for equatorial_radius and flattening in BaseGeodeticRepresentation. #14763 (comment) and Add support for equatorial_radius and flattening in BaseGeodeticRepresentation. #14763 (comment)) also forcing me to add checks about which attribute is defined like in Refactor EarthLocation as instance of BodyLocation. Add flattening and equatorial radius as parameters. #14714 (and answering Add support for equatorial_radius and flattening in BaseGeodeticRepresentation. #14763 (comment)).
    I understand the code itself looks cleaner here, but in my opinion an additional level of abstraction is unnecessary as it does not correspond to a different representation, and perhaps we are overcomplicating things for users.

  2. I believe we can safely use the name geodetic.py for the file containing the geodetic representation (even when generalized to other planets) as this is already done by the NAIF SPICE routines: for example the routines corresponding to gc2gde and gd2gc are recgeo and georec.
    A useful summary is available here: geodetic is the term used by NAIF SPICE "Applicable to bodies with equal equatorial radii."
    We may be more precise using planetodetic but then we might want to change the names of all the functions defined in EarthLocation too and I'm wondering if this is worth it.

Let me know how do you feel about those suggestions.
Thanks!

@mhvk

mhvk commented May 8, 2023

Copy link
Copy Markdown
Contributor

@cmarmo - when I did my review yesterday I also wondered if it was actually necessary to have two subclasses, and whether, instead, we should not just return closer to what you had, where BaseGeodeticRepresentation.__init_subclass__ just checks for _ellipsoid, and, if found, then sets _equatorial_radius and _flattening based on it.

Also, good to know that the consensus in the community is to just call it geodetic even for other planetary bodies. If so, let's go for it.

Anyway, it sounds like we have a plan!

p.s. It doesn't have to be now, but if you think it is better, I'd be fine with moving the explicit representations from earth.py to geodetic.py, i.e., just leaving EarthLocation only in earth.py. Once representations becomes its own module, then geodetic can move there, which would be quite logical.

@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch from 923ce18 to 042d51f Compare May 8, 2023 20:00
@cmarmo

cmarmo commented May 8, 2023 •

Copy link
Copy Markdown
Member Author

Anyway, it sounds like we have a plan!

Wonderful! :)
I have addressed some of your comments ... if you don't mind I'm going to resolve some of them: I realized I'm starting to miss inline comments and I need a way to check those I have addressed.... getting old... ;)

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

Now definitely moving towards minimal comments and nitpicks - I think overall this is looking very good!

But obviously need to figure out why the tests are failing. My guess is that it is the registration of the test classes, and I give a suggestion in-line on how to fix this...

To do is a what's-new entry and documentation!

Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/geodetic.py
Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/geodetic.py Outdated
Comment thread astropy/coordinates/tests/test_geodetic_representations.py
Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated
Comment thread astropy/coordinates/geodetic.py Outdated
@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch from 7a62c19 to 6dce627 Compare May 9, 2023 01:08
@cmarmo cmarmo changed the title Add support for equatorial_radius and flattening in BaseGeodeticRepresentation. Add StandardGeodeticRepresentation. Add support for equatorial_radius and flattening in BaseGeodeticRepresentation. May 9, 2023
@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch from 6dce627 to 5007cf7 Compare May 9, 2023 01:14
Comment thread docs/coordinates/representations.rst Outdated

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

Great! Code is now all OK - the diff makes me feel this is exactly right, with just a clean chunk moved from earth.py to the new geodetic.py, and logical additions.

Most of the remaining comments are just textual, on the added documentation.

One thought (not for this PR!!): it might make sense to allow one to input a BaseGeodeticRepresentation subclass in EarthLocation.to_geodetic (maybe as the ellipsoid argument), so people can use their custom classes in there.

Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated
Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated
Comment thread docs/changes/coordinates/14763.feature.rst Outdated
Comment thread docs/coordinates/representations.rst Outdated
* `~astropy.coordinates.CylindricalRepresentation`:
cylindrical polar coordinates, represented by a cylindrical radius
(``rho``), azimuthal angle (``phi``), and height (``z``).
* `~astropy.coordinates.BaseGeodeticRepresentation`:

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 class is different in that it is not useful in itself but has to be subclassed. How about here describing WGS84GeodeticRepresentation (which is useful in itself), and then at the end noting the two other pre-defined ones, and giving a link to your new section about how to create one's own?

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.

This class is different in that it is not useful in itself but has to be subclassed.

I understand this point.
But then WGS84GeodeticRepresentation is a specific case, which is not true for the other items in the list.
What about removing the geodetic description from the list and adding a paragraph like:
"Astropy also offers a BaseGeodeticRepresentation useful to create specific representations on spheroidal bodies... blah...blah..."

Comment thread docs/coordinates/representations.rst Outdated
Comment thread docs/whatsnew/6.0.rst
Comment thread docs/whatsnew/6.0.rst Outdated
Comment thread pyproject.toml Outdated
Comment thread docs/whatsnew/6.0.rst Outdated
Comment thread astropy/coordinates/tests/test_geodetic_representations.py Outdated

@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 have some comments regarding the tests.

Comment on lines +29 to +30
def test_custombasegeodetic_error():
# Test incomplete initialization.

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'd like the test names to be descriptive enough that such comments would not be necessary. pytest shows the names of failing tests and they can be also displayed by running pytest with increased verbosity, but reading the comment requires looking up the source code for the test.

msg = "module 'erfa' has no attribute 'foo'"
with pytest.raises(AttributeError, match=msg):

class CustomGeodeticEllipsoidError(BaseGeodeticRepresentation):

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.

If I read the code I can figure out why an error is implemented as a subclass of BaseGeodeticRepresentation, but I'd rather not spend the effort.

Suggested change
class CustomGeodeticEllipsoidError(BaseGeodeticRepresentation):
class InvalidCustomGeodeticEllipsoid(BaseGeodeticRepresentation):

This also applies to the other class in this function.

Comment on lines +70 to +78
s1g = CustomGeodetic(
lon=[0.8, 1.3] * u.radian,
lat=[0.3, 0.98] * u.radian,
height=[100.0, 367.0] * u.m,
)

s2g = CartesianRepresentation.from_representation(s1g)

s3g = CustomGeodetic.from_representation(s2g)

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 don't like having variables that are used exactly once because I don't know that they'll be discarded almost immediately when I'm reading the code, so I try to memorize what they are only to find out very quickly that I can forget about them entirely.

Suggested change
s1g = CustomGeodetic(
lon=[0.8, 1.3] * u.radian,
lat=[0.3, 0.98] * u.radian,
height=[100.0, 367.0] * u.m,
)
s2g = CartesianRepresentation.from_representation(s1g)
s3g = CustomGeodetic.from_representation(s2g)
initial = CustomGeodetic(
lon=[0.8, 1.3] * u.radian,
lat=[0.3, 0.98] * u.radian,
height=[100.0, 367.0] * u.m,
)
roundtripped = CustomGeodetic.from_representation(
CartesianRepresentation.from_representation(initial)
)

assert "customgeodeticerror" not in REPRESENTATION_CLASSES


def test_custombasegeodetic_roundtrip():

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.

This test should be parametrized. If one of the asserts fails then the following asserts in the test function are not executed, but in the case of a parametrized test one of the parametrizations failing does not prevent other parametrizations of the same test from running, so a parametrized test suite is more granular and informative with no or very little extra effort.


s3g = CustomGeodetic.from_representation(s2g)

assert quantity_allclose(s1g.lon, s3g.lon)

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.

It is better to use assert_quantity_allclose() because it is more informative if the assertion fails.

@cmarmo

cmarmo commented May 9, 2023 •

Copy link
Copy Markdown
Member Author

@eerovaher , Thanks for your comments, I believe I have addressed all your concern?

@mhvk something is wrong with the conversion of _flattening... I am confused.
I had to manually force the conversion between a float and a dimensionless_unscaled, also the docstring is failing with a % since I have defined the flattening as u.percent

EDIT: removing a debugging print helped a lot... 😅

@mhvk

mhvk commented May 10, 2023

Copy link
Copy Markdown
Contributor

@cmarmo - the reason that _flattening didn't work is that we didn't quite do the ufunc right for that - my mistake to not notice that, really. I made a change locally, and also some small further changes to the tests (to split them up further as requested by @eerovaher and minimize the difference with what was there), but I cannot push to your branch. Could you allow me to? (Need to "Enable edits by maintainers".). If that's tricky, the rebased/squashed branch including a commit for the helpers is at https://github.com/mhvk/astropy/tree/representations-geodetic - you could get that and push to your branch yourself.

@mhvk

mhvk commented May 10, 2023

Copy link
Copy Markdown
Contributor

p.s. Just updated my branch with an additional commit that moves geodetic inside astropy.coordinates.representations (which was made its own submodule in #14792). It also corrected your commit to put back in that infamous noqa: F401 which also for me had been automatically removed.

@cmarmo

cmarmo commented May 10, 2023

Copy link
Copy Markdown
Member Author

I cannot check the "allow edits from maintainers" because of https://github.com/orgs/community/discussions/5634.
I'm going to make some manipulations locally ... back soon.

@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch from a5e35a3 to a10c965 Compare May 10, 2023 19:00
@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch from 5eb5e6d to a30f021 Compare May 10, 2023 19:13
@cmarmo

cmarmo commented May 10, 2023

Copy link
Copy Markdown
Member Author

I have pushed a new version of the documentation implementing my suggestion in answering this comment. Let me know if it is acceptable.

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

Sorry for the trouble, I hadn't realized group accounts were different!
And also sorry that my PR missed some things!

But it now all looks great! I have one possible suggestion for the documentation, but am also happy to merge as is, so will leave that up to you and approve now.

Comment thread docs/coordinates/representations.rst Outdated


Astropy also offers a `~astropy.coordinates.BaseGeodeticRepresentation` useful to
create specific representations on spheroidal bodies (see

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 this paragraph is very clear! Should we mention the existing earth-based ones? E.g.,


Astropy also offers a `~astropy.coordinates.BaseGeodeticRepresentation` useful to
create specific `repreentations` on spheroidal bodies. This is used internally for the
standard Earth ellipsoids used in `~astropy.coordinates.EarthLocation` 
(`~astropy.coordinates.WGS84GeodeticRepresentation`,
`~astropy.coordinates.WGS72GeodeticRepresentation`, and
`~astropy.coordinates.GRS80GeodeticRepresentation`), but 
can also be customized; see :ref:`astropy-coordinates-create-geodetic`.
All these are coordinates on ...

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.

I like it! I'm adding it right now.

@cmarmo
cmarmo force-pushed the geodetic-representation-pr branch from c08a964 to e6c0a86 Compare May 10, 2023 22:30
@mhvk
mhvk enabled auto-merge May 11, 2023 09:01
@mhvk

mhvk commented May 11, 2023

Copy link
Copy Markdown
Contributor

The tests seem to be stuck, so I'm going to close & reopen. Hopefully, that will resolve it. Otherwise, everything is OK, so I'm going to try our new "auto-merge" feature

@mhvk mhvk closed this May 11, 2023
auto-merge was automatically disabled May 11, 2023 09:01

Pull request was closed

@mhvk mhvk reopened this May 11, 2023
@mhvk
mhvk enabled auto-merge May 11, 2023 09:02
@mhvk
mhvk merged commit 80175d7 into astropy:main May 11, 2023
@cmarmo

cmarmo commented May 11, 2023

Copy link
Copy Markdown
Member Author

Thanks! 🥳

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