-
-
Notifications
You must be signed in to change notification settings - Fork 38
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
Better handled Spectrum1D images across classes #144
Conversation
11bc150
to
1f03a0a
Compare
ecce188
to
1902445
Compare
Codecov Report
@@ Coverage Diff @@
## main #144 +/- ##
==========================================
+ Coverage 72.60% 75.46% +2.86%
==========================================
Files 9 9
Lines 646 693 +47
==========================================
+ Hits 469 523 +54
+ Misses 177 170 -7
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
As far as I can tell, this approach works with images that are bare numpy arrays, along with Spectrum1D, NDData, and CCDData objects. It doesn't work with images that are Quantity objects due to because various places in our code compare or do arithmetic with the image and another unit-less array. Should the Quantity scenario be fixed or should we mandate that users provide an NDData-inheriting object if they want their image to have units? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few questions on the implementation and then I will try to robustly test and see if I can reproduce any of the previous units issues.
All of the extra logic on how to handle the unit makes me wonder if we should only support passing the unit in with the image (as either a NDData or Spectrum1D or quantity array) and removing the unit
input parameter entirely. Any thoughts on that?
cfe8bb5
to
945fb1c
Compare
c015d73
to
b032d95
Compare
I added a parser to all trace, extraction, and background classes so they can handle input The Some questions:
I will push some new tests of image input typing soon. I'll wait on adjusting the documentation until it's clear that the new approach is acceptable. |
Looks like I have some failures to address before I introduce the new tests. Thoughts on the new approach to typing are still welcome. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The image attribute is now always of type Spectrum1D. I went this route because Spectrum1D has spectral axis information that would be lost with any other type. Inputs that lack spectral axes are just given an arange of values in pixel units.
I think this is a good idea and makes sense with the goal to integrate more tightly with specutils... but share your concerns below.
Before, obj.image was stored in our classes the way it was introduced as an argument. Is it an annoying user experience to have it converted to Spectrum1D?
As a consequence of the image attribute's type change, obj.image is now a conglomerate of information instead of just the flux. This makes getting to the flux for plotting, arithmetic, etc. a bit more cumbersome for those who don't know Spectrum1D (e.g., from plt.imshow(obj.image) before to plt.imshow(obj.image.data) now). Are we OK with that?
An alternative, I suppose, might be to store the user-provided object and then do the conversion (_parse_image
) as part of a (cached) property. That way both formats are accessible to the user, but internally we can rely on a consistent type when calling the property.
specreduce/background.py
Outdated
@@ -86,17 +122,18 @@ def _to_trace(trace): | |||
raise ValueError('trace_object.trace_pos must be >= 1') | |||
return trace | |||
|
|||
self._parse_image() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having to do this to coerce the input is quite related to the discussion in #126 (comment) (nothing that needs to hold up this PR, but something to keep in mind in that discussion and the implementation here might need to be modified down the road depending on any decisions there).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I tried your idea of storing image
as a cached_property
, but I couldn't figure out a way to do it without either a) changing the name of the image
argument, which I think would be unintuitive, or b) including a dummy argument with InitVar
to be converted to image
later on. The dummy argument either shows up in the automatic docstring (confusing to users) or isn't passed to the __init__
.
Maybe there's some potential crossover with #147 on this topic?
Also, it looks like cached_property
requires Python ≥3.8. We currently allow 3.7, but the specutils
requirements I mention in my summary below would give us an implicit requirement of 3.8, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we haven't yet, we should officially update our python requirement to ≥3.8. especially since it's implicitly required by dependencies.
2e9144c
to
ce717f0
Compare
I had more to do since my last messages than I thought:
The notebooks will need edits, but I would like to see #128 merged first to avoid merge conflicts. Questions:
External dependency:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me and works in the cases I've tested. This probably counts as an API break since the output types have changed, but in the past we made similar breaking changes in minor releases since we're still considered in active development and not adhering to semver rules... but just something to keep in mind.
I think so since it's literally called array, but I also am not opposed to removing it (maybe with a deprecation period) and replacing it with something named more appropriately to hold a
I'm a bit torn on this one. I proposed the cached property idea, but that seemed to not play nicely with dataclasses. Perhaps if we decide to abandon dataclasses (see #126 (comment)), then that is a direction we could take in the future (in which case we could have
I think this is out-of-scope for this PR, but maybe worth opening a follow-up issue so that we can discuss and decide. I agree that we should aim to be self-consistent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
impressive amount of work here! i advocated early on for the adoption of NDData
as the standard data structure to use internally. this PR takes that even further by adopting a more appropriate subclass which i 💯 agree with. i appreciate the clean-up by putting the image parsing all in one place. i have a few minor comments to address and note that there are conflicts that need to be resolved before merging. coverage looks good and the tests pass so once that's taken care of, it's gtg to merge. thanks again for all the hard work on this!
CHANGES.rst
Outdated
@@ -7,6 +7,10 @@ New Features | |||
API Changes | |||
^^^^^^^^^^^ | |||
|
|||
- All operations now accept Spectrum1D and Quantity-type images. All accepted | |||
image types are now processed internally as Spectrum1D objects. [#146] | |||
- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i assume this will be filled in a bit more before merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can include that operations' image
attributes will now always be Spectrum1D
objects. Was there anything else you were thinking should be here? I thought many of the changes were too behind the scenes to make the changelog.
image with 2-D spectral image data | ||
trace_object: Trace | ||
image : `~astropy.nddata.NDData`-like or array-like | ||
Image with 2-D spectral image data. Assumes cross-dispersion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is confusing since crossdisp_axis
can still be provided as an input...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but the extraction operations function the same way. I think it's a remnant of the desire to future-proof them for a time when we allow for more flexibility in axis arrangement. Would you agree that a solution to this is outside this PR's scope?
@@ -201,6 +210,7 @@ def one_sided(cls, image, trace_object, separation, **kwargs): | |||
crossdisp_axis : int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this parameter being used or is the assumption hard-coded as implied in the previous docstring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cls
should be of type Background
, so it follows the docstring's implication once the new instance is created at the end of the method.
e50bb51
to
2b89387
Compare
Quantity arrays are now acceptable inputs. After parsing, the attribute is now of type instead of as before.
2b89387
to
4b0bdd5
Compare
89fb30c
to
53fd1a4
Compare
@tepickering, I believe I addressed everything you brought up that's in scope here. The failing test is due to an upstream issue with Astropy that looks like it will be resolved soon. I do feel like this is ready for a merge... but also feel it's bad juju to merge one's own pull request with a failing test and changes requested, so I'll defer to others' judgment or until after the holiday. |
OK, I will merge now to keep things moving. |
I made changes to
Background
and theTrace
classes in particular.I created
ana private method for__init__()
Trace
and put the check forSpectrum1D
there so it can be propagated out to the children classes throughsuper()
. I'm not sure if I should be using__post_init__()
instead.I didn't realize that
Spectrum1D
is a child class ofNDData
, so most of the checks for the latter inBackground
and the extraction classes already captured them. I added code inBackground
to fix #129 and made the docstrings on image typing consistent across all classes.I hope this fixes #130, but I wasn't able to reproduce the strange behavior with units reported there.