Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure Masked scalars print the same way as regular array scalars #15451

Merged
merged 1 commit into from Oct 10, 2023

Conversation

mhvk
Copy link
Contributor

@mhvk mhvk commented Oct 7, 2023

Description

This pull request is to ensured that str(masked_array) looks like str(unmasked_array) also for array scalars. Thus, like regular array scalars, the precision is ignored for float, and strings do not include extra quoting.

Found in #15231

I think this should not be backported, since it is not nice if str(anything) changes in a bug-fix release. But I do consider it more of a bug-fix than an API change (though happy to change it if need be).

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

@mhvk mhvk added this to the v6.0 milestone Oct 7, 2023
@github-actions
Copy link

github-actions bot commented Oct 7, 2023

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?
  • 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
Copy link
Member

pllim commented Oct 9, 2023

Who should review this?

@mhvk
Copy link
Contributor Author

mhvk commented Oct 9, 2023

@nstarman - would you be able to review this PR as well as #15450? Both are very small and I'm not sure who else has as much experience with Masked... Thanks!

Copy link
Member

@nstarman nstarman left a comment

Choose a reason for hiding this comment

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

Looks good! 1 question and 1 request for more detailed comments.

return self.maybe_mask_string(self.format_function(x.unmasked[()]), x.mask)

@staticmethod
def maybe_mask_string(string, mask):
Copy link
Member

Choose a reason for hiding this comment

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

Should this be public?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wondered about separating it out at least if the function is used outside of the class, but looking at it again, realized I could just use the class, which for this bug-fix PR seems cleaner. So, this change is now reverted.

# Override to change special treatment of array scalars, since the numpy
# code turns the masked array scalar into a regular array scalar.
if a.shape == () and a.dtype.names is None:
return MaskedFormat.maybe_mask_string(np.array_str(a.unmasked), a.mask)
Copy link
Member

Choose a reason for hiding this comment

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

that would follow through to here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I now use MaskedFormat explicitly, with np.array_str as the format function. That seems cleaner.

Eventually, I'd like to give the option of using different ways to indicate masked - in particular, with strikethrough! (but it is tricky since not all terminals support the utf-8 way of doing it; see line 965)

Comment on lines 1300 to 1310
assert str(msa) == "[3.14159265 ———]"
assert str(msa[0]) == "3.141592653589793" == str(sa[0])
assert str(msa[1]) == " ———"
with np.printoptions(precision=3, floatmode="fixed"):
assert str(msa) == "[3.142 ———]"
assert str(msa[0]) == "3.141592653589793" == str(sa[0])
assert repr(msa) == "MaskedNDArray([3.14159265, ———])"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assert str(msa) == "[3.14159265 ———]"
assert str(msa[0]) == "3.141592653589793" == str(sa[0])
assert str(msa[1]) == " ———"
with np.printoptions(precision=3, floatmode="fixed"):
assert str(msa) == "[3.142 ———]"
assert str(msa[0]) == "3.141592653589793" == str(sa[0])
assert repr(msa) == "MaskedNDArray([3.14159265, ———])"
# Test masking the array works as expected, including truncating digits
assert str(msa) == "[3.14159265 ———]"
# Test the digits are kept
assert str(msa[0]) == "3.141592653589793" == str(sa[0])
# Or appropriately masked
assert str(msa[1]) == " ———"
# Test the precision can be changed temporarily.
with np.printoptions(precision=3, floatmode="fixed"):
assert str(msa) == "[3.142 ———]"
assert str(msa[0]) == "3.141592653589793" == str(sa[0])
assert repr(msa) == "MaskedNDArray([3.14159265, ———])"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, good idea. Implemented.

Copy link
Member

@nstarman nstarman left a comment

Choose a reason for hiding this comment

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

One suggestion to speed up by avoiding the lambda, otherwise 🚀

astropy/utils/masked/function_helpers.py Outdated Show resolved Hide resolved
@mhvk mhvk enabled auto-merge October 10, 2023 13:38
@mhvk mhvk merged commit 01a63e7 into astropy:main Oct 10, 2023
24 of 26 checks passed
@taldcroft taldcroft mentioned this pull request Oct 20, 2023
4 tasks
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.

None yet

3 participants