Skip to content

Allow representations to be masked, with possibly different masks for the components - #16845

Closed
mhvk wants to merge 5 commits into
astropy:mainfrom
mhvk:masked-representations-allow-different-masks
Closed

mhvk wants to merge 5 commits into
astropy:mainfrom
mhvk:masked-representations-allow-different-masks

Conversation

@mhvk

@mhvk mhvk commented Aug 18, 2024 •

Copy link
Copy Markdown
Contributor

This pull request is the first step in making SkyCoord able to deal with masks, by giving representations a mask. In general, I tried to make the behaviour similar to that of Time, which means, e.g., that the mask strictly refers to that of the data, not any associated differentials (similarly, for frames, the mask will not include information from any attributes, just like Time does not include information from location).

One difference is that the mask is not shared between the three components. This is because I think we want to be able to support SkyCoord of catalogues in which some of the sources do not have an associated distance. Most logical is for those just to have a masked distance, but unmasked longitude and latitude. But to support that, the components of SphericalRepresentation need to have independent masks. (I went some way in seeing if the angles still could have a shared mask, but ended up feeling this became too complex and fragile)

So, right now, the representations have a .mask property which just or's everything together, as well as a get_mask method, which allows one to select specific components.

EDIT: This is a follow up of #16844 Note that this builds on #16842 and #16844. The most important commit is the last one. Opening as draft for now to allow comments on the general idea first.

  • By checking this box, the PR author has requested that maintainers do NOT use the "Squash and Merge" button. Maintainers should respect this when possible; however, the final decision is at the discretion of the maintainer that merges the PR.

@github-actions

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 instructions for rebase and squash.
  • 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?
  • 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.

@mhvk
mhvk force-pushed the masked-representations-allow-different-masks branch from f0a0875 to 5719fd9 Compare August 18, 2024 16:27
@mhvk
mhvk marked this pull request as draft August 18, 2024 16:47
@mhvk
mhvk force-pushed the masked-representations-allow-different-masks branch 2 times, most recently from f340ac3 to de1f7b5 Compare August 18, 2024 18:54
@mhvk
mhvk force-pushed the masked-representations-allow-different-masks branch from de1f7b5 to 236a7f5 Compare September 15, 2024 13:23
@mhvk
mhvk marked this pull request as ready for review September 15, 2024 13:27
@mhvk

mhvk commented Sep 15, 2024

Copy link
Copy Markdown
Contributor Author

@taldcroft, @nstarman (for masking in general) and @StuartLittlefair, @adrn, @eerovaher (coordinate maintainers): this PR introducing masked representations is ready for review. Most important perhaps is the big picture question of whether you think my logic about not sharing masks is correct (and whether, for follow-up on frames and SkyCoord, the mask should not depend on attributes).

@mhvk mhvk mentioned this pull request Sep 15, 2024
1 task done
@mhvk

mhvk commented Sep 15, 2024

Copy link
Copy Markdown
Contributor Author

Follow-up PR using this in coordinate frames and SkyCoord at #17016.

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

Great to see more masked support!


@property
def masked(self):
return isinstance(getattr(self, self.components[0]), Masked)

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 know that it's designed s.t. f one field is masked all are masked, but with early exiting the following should be equivalent speed-wise 🤞🏼

Suggested change
return isinstance(getattr(self, self.components[0]), Masked)
return any(isinstance(getattr(self, c), Masked) for c in self.components)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not sure: if this gets out of sync, there are arguably larger problems than whether .masked is still OK - e.g., any assignments with masked values will silently drop the mask (numpy problem, not something easy to catch...).

But happy to change it too...

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's not a large priority, we're just not built around immutable data structures.

@nstarman

Copy link
Copy Markdown
Member

Most important perhaps is the big picture question of whether you think my logic about not sharing masks is correct

I think so!

@mhvk

mhvk commented Sep 19, 2024

Copy link
Copy Markdown
Contributor Author

It makes sense to have a common mask for coordinates on the sky, but a separate mask for distance, and it also makes sense to have a common mask for the components of proper motion, but a separate mask for radial velocity.

I actually have a separate branch in which I tried to keep the angular masks shared. In the end, I felt it was too fragile, e.g., in having to check for shared masks also in setting, resetting masks after a conversion from cartesian to spherical, etc. Also, I worried I might be too presumptuous about what a representation would look like (though I tried to give flexibility). E.g., should the masks on r and z in cylindrical coordinates also be merged?

In the end, it is probably also clearer for the user if each element simply has its own mask. Coordinates are a bit different from Time in that one actually uses the elements, while the jd1, jd2 for times are more hidden.

@eerovaher

Copy link
Copy Markdown
Member

I still think that the ability to treat the masks of the on-sky coordinates and the masks of proper motion components together would be user-friendly, but a better way to implement that would be to have convenience methods on the specific representation and differential classes and that should be done in a separate pull request to keep the scope of this one manageable.

If your question was whether there should be a single mask for the entire representation or separate masks for the separate components then the nature of astronomical observations dictates that separate masks would be much more useful.

@mhvk

mhvk commented Sep 20, 2024

Copy link
Copy Markdown
Contributor Author

OK, good point that one can separate the concerns: this PR indeed does not preclude later having some sharing of masks between the angular coordinates. Indeed, it may be helpful to rebase my branch that attempted to implement shared masks on this once it is merged; that will make clearer what the differences are.

@eerovaher

Copy link
Copy Markdown
Member

Opening a few small self-contained pull requests instead of a single very large one is usually a good idea. However, in this case it seems to me that the best way to ensure we are coming up with a good API is to ensure SkyCoord.apply_space_motion() works well with masked instances. This makes me hesitant to review representations in isolation.

Large pull requests can be made more manageable by keeping the commit history clear and atomic, and from a quick glance at #17016 it seems like you've been doing that already, so I don't see any value in reviewing this pull request separately.

@mhvk

mhvk commented Oct 2, 2024

Copy link
Copy Markdown
Contributor Author

@eerovaher - if it is easier for you to review the whole (i.e., #17016, which is built on this), that is definitely fine by me! I can add extra tests, etc., wherever is most appropriate.

@eerovaher

Copy link
Copy Markdown
Member

SkyCoord.apply_space_motion() forces representations, differentials and time to interact with each other, so if we have working tests for apply_space_motion() with the masked versions of all of these then we can say with quite some confidence that everything works. Without tests for apply_space_motion() there is a chance we might be overlooking something.

@mhvk

mhvk commented Oct 2, 2024

Copy link
Copy Markdown
Contributor Author

Good point. I'll add an apply_space_motion test to #17016

@mhvk
mhvk force-pushed the masked-representations-allow-different-masks branch from 53fabbd to f720d53 Compare October 10, 2024 17:46

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

Small comments

self._ensure_masked()

if set_mask or clear_mask:
for comp in self.components:

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.

Unrelated to this PR but maybe we should have a _components attribute that provides an iterator for the _-prefixed components.

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

Except the differentials repetition (https://github.com/astropy/astropy/pull/16845/files#r1797307453) which will be fixed, this LGTM.
Obviously the coordinates maintainers should have final say and @eerovaher is making sure space motion is working as expected.
Thanks @mhvk!

@mhvk

mhvk commented Oct 13, 2024

Copy link
Copy Markdown
Contributor Author

Except the differentials repetition (https://github.com/astropy/astropy/pull/16845/files#r1797307453) which will be fixed, this LGTM.

I pushed the fixed version that I already had in #17016 here too, so that this can undergo final review.

@mhvk
mhvk force-pushed the masked-representations-allow-different-masks branch 2 times, most recently from e37b528 to 24db0cb Compare October 14, 2024 15:56
@eerovaher

Copy link
Copy Markdown
Member

Before I start reviewing this in detail I need to ask why should I review this at all if #17016 exists? Shouldn't I review just that?

@mhvk

mhvk commented Oct 14, 2024

Copy link
Copy Markdown
Contributor Author

This PR introducing masks for representations is now ready for final review -- I really hope to get this in before feature freeze! I think it is now independent of the larger outstanding question of how exactly to deal with masks in SkyCoord.

After review of this one, please do look at #17016 (comment) and help decide what is the best path forward (ideally also in time for feature freeze - the choices so far are not difficult in terms of code changes in the PR).

@mhvk

mhvk commented Oct 14, 2024

Copy link
Copy Markdown
Contributor Author

Before I start reviewing this in detail I need to ask why should I review this at all if #17016 exists? Shouldn't I review just that?

You can certainly review #17016 if that works better for you - and I'm happy to "back-port" any suggestions you make there for representations to this PR -- which is here because for my thinking (and perhaps that of others) it really helped to separate the adjustments into ones for the base representations and the frames/SkyCoord that contain them.

@mhvk

mhvk commented Oct 16, 2024

Copy link
Copy Markdown
Contributor Author

Following #17016 (comment), pushed an extra commit with a test showing that transformation of a spherical representation with a matrix properly preserves the angular mask.

mhvk added 5 commits October 23, 2024 16:07
This is in preparation for addings masks, so that if a SphericalDistribution
has a separate mask on the radial coordinate, that will be propagated to the
RadialDistribution.
…e-spot combo.

With the option to get a combination of the masks of selected components.
@mhvk
mhvk force-pushed the masked-representations-allow-different-masks branch from 72c178b to ca5126c Compare October 23, 2024 20:18
@mhvk

mhvk commented Oct 24, 2024

Copy link
Copy Markdown
Contributor Author

@eerovaher - @nstarman already approved, but I'd rather have your OK too before I merge... Will add that I'm sorry that my splitting between representations and frames has made it more difficult instead of simpler (as I thought it would be -- the representation case is much simpler and I thought it would have gone in quickly so we could concentrate on the frames...). While I'm not sure I have addressed all your concerns on the frames, though, I think I did get everything on the representations. Thanks!

@eerovaher

Copy link
Copy Markdown
Member

Dividing work into smaller self-contained chunks is a good idea, but (as I've said multiple times already) SkyCoord.apply_space_motion() forces the representations and differentials to interact. Furthermore, apply_space_motion() and some frame transformations also introduce interactions with frame attributes (e.g. obstime). This pull request is therefore not self-contained and should not be reviewed in isolation.

I don't see why we shouldn't be able to merge #17016 before the feature freeze.

@mhvk

mhvk commented Oct 24, 2024

Copy link
Copy Markdown
Contributor Author

OK, that's fine too!

@mhvk
mhvk deleted the masked-representations-allow-different-masks branch October 24, 2024 16:44
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.

3 participants