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

Pull common parts of skymatch from romancal and jwst into stcal #310

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

WilliamJamieson
Copy link
Collaborator

@WilliamJamieson WilliamJamieson commented Oct 17, 2024

This PR pulls the common parts of skymatch from romancal and jwst into stcal to be shared.

Note, no tests are included because it is well tested by the step tests in both romancal and jwst.

Tasks

  • update or add relevant tests
  • update relevant docstrings and / or docs/ page
  • Does this PR change any API used downstream? (if not, label with no-changelog-entry-needed)
    • write news fragment(s) in changes/: echo "changed something" > changes/<PR#>.<changetype>.rst (see below for change types)
    • run regression tests with this branch installed ("git+https://github.com/<fork>/stcal@<branch>")
news fragment change types...
  • changes/<PR#>.apichange.rst: change to public API
  • changes/<PR#>.bugfix.rst: fixes an issue
  • changes/<PR#>.general.rst: infrastructure or miscellaneous change

Copy link

codecov bot commented Oct 17, 2024

Codecov Report

Attention: Patch coverage is 69.57774% with 317 lines in your changes missing coverage. Please review.

Project coverage is 85.05%. Comparing base (35726e9) to head (6202d38).
Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
src/stcal/skymatch/skyimage.py 61.09% 270 Missing ⚠️
src/stcal/skymatch/skymatch.py 83.90% 47 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #310       +/-   ##
===========================================
+ Coverage   29.57%   85.05%   +55.47%     
===========================================
  Files          36       53       +17     
  Lines        7949    10028     +2079     
===========================================
+ Hits         2351     8529     +6178     
+ Misses       5598     1499     -4099     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@emolter emolter left a comment

Choose a reason for hiding this comment

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

This looks great, thanks William! I just had a few questions about whether some of the ruff and mypy problems could be fixed instead of ignored.

I also had a few questions about the code itself, but those also exist on jwst main, so they're technically beyond the scope of this PR. But I'm still curious to know the answers to those and I figure now is as good a time as any to ensure the code is written as cleanly as possible

pix_area=1.0,
convf=1.0,
mask=None,
id=None, # noqa: A002
Copy link
Collaborator

Choose a reason for hiding this comment

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

instead of hiding the style complaint could this be renamed?

Copy link
Member

Choose a reason for hiding this comment

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

I suggest sky_id as it would work with both SkyImage and SkyGroup.

Comment on lines +161 to +162
The functionality to support this conversion is not yet
implemented and at this moment `convf` is ignored.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are there plans to implement this? If not, perhaps now is a good time to remove the option

Copy link
Member

Choose a reason for hiding this comment

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

Based on ancient (>9 years old) discussions with relevant people, this feature, in theory, may not be needed for JWST. In practice, however, we don't know. I suggest leaving this alone as is.

Comment on lines +327 to +328
@property
def id(self): # noqa: A003
Copy link
Collaborator

Choose a reason for hiding this comment

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

I know you most likely just copied all of this from JWST, so not strictly in the scope of this PR, but is there a reason that getter-setter methods are being used here for id, pix_area, sky, is_sky_valid, radec, polygon, and skystat? These don't seem to add any functionality.

These do make it so that this class has the same underscore-protected variable names as SkyGroup, but is there any reason that has to be the case?

Copy link
Member

Choose a reason for hiding this comment

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

Since the original code was written ~11-12 years ago (not sure about this but I think so), I no longer remember the intention. Maybe during the development I thought that, for example, pix_area will be computed on demand but ended up storing it for efficiency. It just allows more flexibility. Also, since both SkyImage and SkyGroup can be used as inputs to match, they should have a common set of properties. I do not remember what was the Python version used during the development but it may have been 2.x (due to PyRAF / Tables/ whatever limitations) so I don't think ABC was available at that time and even if it was, I am not sure properties or attributes of classes could be made abstract. Another reason may have been the desire to get these properties documented (in the docstrings).

I do not think anything should be changed in this PR but in the future they could subclass from a BaseSky, ABCSky or something like that.

I do not see what is the harm in using properties.

Copy link
Collaborator

Choose a reason for hiding this comment

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

no harm it's just unnecessarily verbose since neither the getter nor the setter does anything. It's therefore confusing, because when I see those methods, I expect them to do something. But it doesn't matter- I agree with William's comment that these changes shouldn't go into this PR, if they happen at all.


"""

def __init__(self, images, id=None, sky=0.0): # noqa: A002
Copy link
Collaborator

Choose a reason for hiding this comment

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

again here can id be renamed instead?

Copy link
Member

Choose a reason for hiding this comment

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

I suggest sky_id as it would work with both SkyImage and SkyGroup.

for im in self._images:
im.sky += sky

@property
Copy link
Collaborator

Choose a reason for hiding this comment

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

same question here RE why id, polygon, and radec go through the trouble to use @property

log.setLevel(logging.DEBUG)


def match(images, skymethod="global+match", match_down=True, subtract=False):
Copy link
Collaborator

Choose a reason for hiding this comment

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

this name also violates https://docs.astral.sh/ruff/rules/builtin-variable-shadowing/ and will likely be changed in JWST by spacetelescope/jwst#9053 to be skymatch()

Copy link
Member

Choose a reason for hiding this comment

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

I would suggest something along the lines do_match or perform_match, or match_sky. The intent for the name of this function was for it to be a verb. skymatch does not sound to me (a non-native English speaker) as a verb but I may be wrong.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm happy with whatever name

from copy import deepcopy

# THIRD PARTY
from stsci.imagestats import ImageStats # type: ignore[import-untyped]
Copy link
Collaborator

Choose a reason for hiding this comment

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

might be worth considering making the relevant third-party type ignores global by putting them here

[[tool.mypy.overrides]]

Comment on lines +17 to +18
This is a superclass build on top of
:py:class:`stsci.imagestats.ImageStats`. Compared to
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment is confusing because the class doesn't actually inherit from ImageStats

Copy link
Member

Choose a reason for hiding this comment

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

Docs could be changed to explain that SkyStats delegates calls to an ImageStats object if that is more clear but the comment about persistence of settings is important as it is what differentiates it from ImageStats and I think it helps with performance.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree that the comment itself explains an important distinction, and yes the simple wording change from "superclass built on top of" to "delegates calls to" would be clearer

@WilliamJamieson
Copy link
Collaborator Author

This looks great, thanks William! I just had a few questions about whether some of the ruff and mypy problems could be fixed instead of ignored.

I also had a few questions about the code itself, but those also exist on jwst main, so they're technically beyond the scope of this PR. But I'm still curious to know the answers to those and I figure now is as good a time as any to ensure the code is written as cleanly as possible

I agree they should be fixed. However, as you said they are beyond the scope of this PR. I think for making it possible to trace the history of changes it makes sense to move the code in as close a state as possible from JWST to stcal and then do a follow on PR making cleanups and addressing the issues uncovered here.


# "bottom" points:
borderx[:nptx] = xs
bordery[:nptx] = -0.5
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest a comment explaining the -0.5 number or the use of a descriptive constant detailing what this number is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree, and I believe this has something to do with all the pixel offsetting. However this is largely just a copy of the stuff from JWST with minimal changes. If someone knows exactly what this is I would be happy to add a comment here.

Really, we should be maintaining a common "constants" object/module to document these and back reference that as opposed to having a bunch of ad hoc magic numbers some of which are documented with comments. This however, is something to consider later.

Copy link
Member

Choose a reason for hiding this comment

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

Centers of pixels have integer image coordinates. Edges of the pixels are located +/- 0.5 pixels away from centers. I think this convention is explained somewhere in the docs. IMO, it does not make sense to add a comment like this every single time we see a 0.5 in the code.

Copy link
Member

Choose a reason for hiding this comment

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

and -0.5 is shorter than coordinate_of_left_pixel_border(_relative_to_center)

Copy link
Collaborator

@emolter emolter Jan 14, 2025

Choose a reason for hiding this comment

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

I agree with Mihai that in the context of pixels it's relatively clear what a 0.5 offset is doing.
However it looks to me like calc_bounding_polygon is the only function where this is really relevant, so would it work to add a note to the docstring saying something like,

Notes
-----
The bounding polygon is defined from corners of pixels
whereas the reference pixel is defined at the center of a pixel
and therefore the lower-left corner is located at (-0.5, -0.5)

or whatever you want, I'm sure I made some small inaccuracies in describing that but you get the idea

@emolter
Copy link
Collaborator

emolter commented Jan 13, 2025

I agree they should be fixed. However, as you said they are beyond the scope of this PR.

IMO making the code adhere to the more stringent style rules in stcal remains within the scope. I don't much like ignoring them. I think the downstream testing should assuage any concerns that those changes might break something.

I agree that my comment RE the potentially unnecessary use of @property can be ignored for now though.

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