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

Add default and set to zero masking option for specreduce operations. #216

Merged
merged 17 commits into from
Dec 16, 2024

Conversation

cshanahan1
Copy link
Contributor

@cshanahan1 cshanahan1 commented Apr 22, 2024

Adds the ability to specify how to handle boolean masks to background, trace, and extract operations. 'filter', 'omit' to drop entire columns that contain any nonfinite data, or zero-fill to replace nonfinite data with zeros.

Copy link

codecov bot commented May 3, 2024

Codecov Report

Attention: Patch coverage is 97.75281% with 2 lines in your changes missing coverage. Please review.

Project coverage is 83.98%. Comparing base (140e817) to head (a52e03f).

Files with missing lines Patch % Lines
specreduce/core.py 96.42% 1 Missing ⚠️
specreduce/tracing.py 97.82% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #216      +/-   ##
==========================================
+ Coverage   83.33%   83.98%   +0.65%     
==========================================
  Files          13       13              
  Lines        1140     1193      +53     
==========================================
+ Hits          950     1002      +52     
- Misses        190      191       +1     

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

@tepickering
Copy link
Contributor

finally got a chance to at least look through the code changes. i like it so far! let me know when it's ready for a fuller review and i'll try playing with it in more depth.

@camipacifici
Copy link

I am pretty sure it is! Please go ahead. Thank you!

@tepickering
Copy link
Contributor

there are a bunch of warnings in the RTD build. they look like malformed references, but need a deeper look to see what's the actual cause.

@tepickering
Copy link
Contributor

i'm confused why python 3.8 and 3.9 tests are being run. a rebase might be needed, though i thought this was forked after those tests were removed.

@@ -32,9 +32,9 @@ class Background(_ImageParser):
----------
image : `~astropy.nddata.NDData`-like or array-like
image with 2-D spectral image data
traces : trace, int, float (single or list)
traces : List, `tracing.Trace`, int, float
Copy link
Contributor

Choose a reason for hiding this comment

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

i think this is one of the RTD complaints. should be ~specreduce.tracing.Trace, i believe.

Individual or list of trace object(s) (or integers/floats to define
FlatTraces) to extract the background. If None, a FlatTrace at the
FlatTraces) to extract the background. If None, a `FlatTrace` at the
Copy link
Contributor

Choose a reason for hiding this comment

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

should be ``FlatTrace`` or a proper sphinx reference

crossdisp_axis : int
cross-dispersion axis
[default: 0]
mask_treatment : string, optional
The method for handling masked or non-finite data. Choice of `filter`,
Copy link
Contributor

Choose a reason for hiding this comment

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

here and elsewhere need to use double single-quotes for inline literal/code. pretty sure this is what RTD has been complaining about...

@cshanahan1 cshanahan1 marked this pull request as ready for review September 18, 2024 19:51
# handled as well. Note that input data may be modified if a fill value
# is chosen to handle masked data. The returned image will always have
# `image.mask` even if there are no nonfinte or masked values.
img, mask = self._mask_and_nonfinite_data_handling(image=img, mask=mask)
Copy link
Contributor

@hpparvi hpparvi Oct 25, 2024

Choose a reason for hiding this comment

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

_get_data_from_image is a static method, so self is not defined. This could be fixed by making _mask_and_nonfinite_data_handling a static method as well and calling it as _ImageParser._mask_and_nonfinite_data_handling(...), but this would require removing the self.image.mask reference in line 144.

Also, _ImageParser never assigns an image to self.image. This could be fixed by changing the line 55

img = self._get_data_from_image(image, disp_axis=disp_axis)
return img

into

self.image = self._get_data_from_image(image, disp_axis=disp_axis)
return self.image

Then again, _ImageParser seems to be meant to be a pure mixin class that provides the image parsing functionality but doesn't store information. The original version of _parse_image in #144 does assume that the object has an image attribute that is returned if no image is given

if image is None:
    # useful for Background's instance methods
    return self.image 

but I think this is quite dangerous since the code assumes that the class inheriting from _ImageParser sets the image attribute by default and that it does this before _ImageParser._parse_image(...) is called.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This has become kind of a mess and i'm trying to figure out how to reorganize. A while back I had to move _get_data_from_image to a static method because some of the 'Background' methods that create Background objects call it before the object is instantiated. I am trying to work off the existing code and avoid refactoring in this PR, but I may have to. This option I'm exploring right now is changing _ImageParser from a mixin class to either just a regular class or set of functions that is called within each step, and the arguments are passed in each time.

Copy link
Contributor

@hpparvi hpparvi Oct 30, 2024

Choose a reason for hiding this comment

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

The only way to avoid refactoring _ImageParser that I can see would be to turn _mask_and_nonfinite_data_handling into a static method as well and to provide mask_treatment as a passed argument (and to handle checking whether the mask treatment method is valid in the calling code.) This way, the _get_data_from_image class method could be used the way it is now.

However, there wouldn't be much advantage to having the image parsing functionality as a class instead of a function, and I think refactoring _ImageParser into a function might make the most sense. Turning it into a regular class would also work, but I'm not sure what would be again the advantage of this over having the image parsing as a function if we want to be able to parse an image inside a class method (as with the Background methods).

Then again, we don't necessarily need to do the image parsing in the Background.two_sided and Background.one_sided class methods since it is done in Background.__post_init__ by default (unless I'm missing something). So, another option would be to leave the image parsing inside Background.__post_init__ and remove it from the two class methods, in which case the Background object would always be instantiated before parsing the image.

If you want to avoid major refactors in this PR, I could open a separate PR where I could refactor the _ImageParser into a function, and we can see how much sense this approach would make. What do you think?

return img

@staticmethod
def _get_data_from_image(image):
Copy link
Contributor

Choose a reason for hiding this comment

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

This method definition overrides the previous _get_data_from_image definition that handles masking.

@cshanahan1 cshanahan1 force-pushed the masking_options branch 4 times, most recently from a52e03f to 4d8ece7 Compare December 12, 2024 17:16
hpparvi and others added 2 commits December 13, 2024 14:49
Modified FitTrace to exclude masked pixels from the fit and fixed the corresponding test.
@hpparvi
Copy link
Contributor

hpparvi commented Dec 16, 2024

Great work, @cshanahan1, I'm merging this now.

@hpparvi hpparvi merged commit ef63350 into astropy:main Dec 16, 2024
9 of 10 checks passed
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.

Improvements to dealing with masked/nonfinite data in Specreduce operations
4 participants