-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Fix NaN handling in cube fitting #3191
Conversation
Remove debugging prints, add comment for context Codestyle, changelog Remove unit conversion stuff to just fix NaN handling
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3191 +/- ##
==========================================
+ Coverage 88.45% 88.46% +0.01%
==========================================
Files 124 124
Lines 18389 18394 +5
==========================================
+ Hits 16266 16273 +7
+ Misses 2123 2121 -2 ☔ View full report in Codecov by Sentry. |
@@ -190,7 +190,7 @@ def initialize(self, instance, x, y): | |||
|
|||
# width can be estimated by the weighted | |||
# 2nd moment of the X coordinate. | |||
dx = x - np.mean(x) | |||
dx = x - np.nanmean(x) |
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.
But np.nanmean
would still return NaN if x
is all NaNs. Is this something we need to handle?
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.
Honestly this probably didn't need to change to nanmean
since there shouldn't be NaN x (spectral axis) values. The y_mean case above is the important one.
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.
Same question for y
also.
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 don't know why someone would try to fit a cube of all NaNs but I think it's reasonable for it to not work if they do 🤷
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.
But didn't you say multiprocessing would swallow the exception, causing confusion?
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 could imagine someone did a bad subset that encompass all NaNs in the cube and then try to fit it. It is possible?
@@ -917,6 +917,12 @@ def _fit_model_to_cube(self, add_data): | |||
|
|||
# Apply masks from selected spectral subset | |||
spec = self._apply_subset_masks(spec, self.spectral_subset) | |||
# Also mask out NaNs for fitting. Simply adding filter_non_finite to the cube fit | |||
# didn't work out of the box, so doing this for now. | |||
if spec.mask is None: |
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 new logic tested?
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 None
case is, I should probably add a case to test the combination of existing mask and Nan-masking.
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 added a test that should cover the existing spec.mask case as well (that mask would come from a spectral subset).
I have no idea why tests are failing on 3.11 and not 3.10 or 3.12, I'll need to investigate. Also note that I was initially testing the |
The tests are passing locally for me on python 3.11, I don't see any package version differences that should affect them...I restarted the test and am crossing my fingers. |
Hmm still fails. Could it be floating point differences? Maybe use allclose instead of equality? Also did you run with |
Try change assert np.all(result.get_component("flux").data == 1) to np.testing.assert_allclose(result.get_component("flux").data, 1) ❓ |
No, you can see they're all 0s (as was the case before I fixed it) in that test environment rather than all 1s. I just confirmed that it also fails on my local WSL Ubuntu install, while still passing with an env set up the same way on my Mac, so at least I can reproduce it... |
🤯 What do we have that can possibly be so OS specific? |
jdaviz/configs/default/plugins/model_fitting/tests/test_fitting.py
Outdated
Show resolved
Hide resolved
…g.py Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>
Locally the tests pass on Ubuntu if I wrap the fitting call in the test to ignore the |
Looks like warning is not always emitted.
Maybe just a blind ignore instead of pytest.warn with warnings.catch_warnings():
warnings.filterwarnings(...) |
Yup I just realized that's what was in the test above these. |
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.
Assuming CI is green this time, code changes look reasonable. Thanks!
Whew, looks like that did it. Passing locally 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.
I've been following all the comments, and all the new tests look good and give the result I'd expect in a notebook, great work finishing this one off!
This comment was marked as resolved.
This comment was marked as resolved.
@rosteen is this worth backporting manually? If not, please update the milestone. And we also need follow-up PR to move the change log. Thanks! |
I split this out from #3190 so it can be backported to 3.10. Still need to add a test and move the changelog.
Edit: ready for review. Note that simply adding
filter_non_finite
to thespecutils.fit_lines
call like in the 1D case didn't seem to work, so I masked out the NaN locations instead. Why that didn't work might be worth further investigation in the future.