-
Notifications
You must be signed in to change notification settings - Fork 74
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 fit_non_finite flag to model_fitting 1D #2437
Conversation
Codecov ReportAttention:
... and 3 files with indirect coverage changes 📢 Thoughts on this report? Let us know!. |
Do we still want an in-plugin warning when there are detected non-finite values that this would affect? |
an AstropyUserWarning will be raised, indicating that non-finite values have been removed from the data before fitting. I was considering adding some additional warnings and if you think that would be useful I can |
that would get buried in the standalone mode, so I think we should try to detect in advance (if it isn't too difficult or add too much computation expense) that there are non-finite values in the selected data/subset and just show some text in the plugin saying they will be ignored. |
ok in that case I have that working in #2429, so I can apply those changes here too. I wasn't sure what the syntax was for displaying a snackbar message here though, who would the 'sender' be in this case? i couldn't find an example in the package of this being done within a function and not a class |
I don't think we want a snackbar unless we can't detect the values in advance and can only catch the warning and pass it on to the user instead. |
3a5116b
to
24a2205
Compare
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 comments from a quick skim. Are there any test cases we can add without introducing large data sets to the tests?
@@ -41,8 +44,9 @@ def specviz_spectrum1d_parser(app, data, data_label=None, format=None, show_in_v | |||
raise TypeError("SpectrumCollection detected." | |||
" Please provide a Spectrum1D or SpectrumList") | |||
elif isinstance(data, Spectrum1D): | |||
data = [data] | |||
# should we make a copy if Spectrum1D is passed in to avoid modifying it when uncerts are reset to 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.
did you test this to see if a copy is needed?
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 you pass in a Spectrum1D with uncertainty=[nan, nan, nan...], the input will be modified without a copy, with uncertainty now being None. What do you think about that, is it worth making a copy to avoid modifying input? Im not sure how it works elsewhere in the package if any modifications are made to the input spectrum
ba37cb8
to
a5298c6
Compare
I think i responded to all of your comments @kecnry. The only open question is should we be making copies so that the input Spectrum1D is not modified? I added some basic tests (which you can use to demo this, as well as the original dataset when you reported this issue @javerbukh ) |
<v-row v-if="non_finite_uncertainty_mismatch"> | ||
<span class="v-messages v-messages__message text--secondary" style="color: red !important"> | ||
Finite values in the selected data will be omitted in the fit due to corresponding non-finite uncertanties. | ||
</span> | ||
</v-row> | ||
|
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'm not seeing this in the plugin. How can I make it appear?
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.
uncertainty=StdDevUncertainty([1, 1, np.nan, np.nan, np.nan, np.nan]*u.Jy)
spec = Spectrum1D(flux=[1, 2, 3, 4, 5, 6]*u.Jy, uncertainty=uncertainty)
specviz = Specviz()
specviz.load_data(spec)
specviz.show()
that should trigger it. it will appear just above the 'fit model' button.
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 tried following the steps of the original ticket and I see the snackbar message "All uncertanties are nonfinite, setting to None". So if no finite values are detected, the uncertainty is set to None. If some non-finite values are detected, this message should show up in the plugin. Do I understand correctly?
I tried and that does in fact make the message appear, thanks!
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.
yep, if the whole array is none then the first snackbar message appears. if its not and there are some non finite uncertainties, then the message in the plugin is displayed
jdaviz/core/template_mixin.py
Outdated
# note! the 'n/a' traitlet doesn't exist. we are watching it here because | ||
# DatasetSpectralSubsetValidMixin is also watching the exact set | ||
# of real traitlets, which creates a bug where only the last inhereted method | ||
# will run, so we need to spoof it like this. | ||
@observe("n/a", "dataset_selected", "spectral_subset_selected") |
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.
Are you sure observing "n/a" is necessary? I don't understand what you mean by "watching the exact set of real traitlets", maybe someone can explain it to me if I'm missing something? I see what you mean by real traitlets, dataset_selected
and spectral_subset_selected
. Still not sure about "n/a".
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 observing "dataset_selected" and "spectral_subset_selected" would conflict with another observe and only the last one added would actually be called. @cshanahan1 - is there an issue for this yet that we can reference?
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.
will post the issue in a sec, i was getting an example code snippet working to create the issue
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.
Has this been resolved? I also don't understand what "n/a" is for.
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 think, somehow miraculously, im not seeing this anymore so i've removed the dummy traitlet.
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.
Sorry for a ton of comments, but they're all quite minor - overall this seems to work well and the code is quite clean, thanks!
CHANGES.rst
Outdated
@@ -58,6 +58,14 @@ Specviz2d | |||
Other Changes and Additions | |||
--------------------------- | |||
|
|||
- Better handling of non-finite uncertainties in model fitting. The | |||
'filter_non_finite' flag (for the LevMarLSQFitter) now filters datapoints with | |||
non-finite weights. In Specviz, if a fully-finite spectrum with non-finite |
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 wonder if this would ever happen for a cube in cubeviz and if its worth generalizing to apply to that case as well (perhaps as part of an eventual parser refactor - not necessarily in this PR)... thoughts?
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 think so, we should open a follow up ticket. we would need to move some things (like get_spectrum_1d) to somewhere more general to make this work
jdaviz/core/template_mixin.py
Outdated
# note! the 'n/a' traitlet doesn't exist. we are watching it here because | ||
# DatasetSpectralSubsetValidMixin is also watching the exact set | ||
# of real traitlets, which creates a bug where only the last inhereted method | ||
# will run, so we need to spoof it like this. | ||
@observe("n/a", "dataset_selected", "spectral_subset_selected") |
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 observing "dataset_selected" and "spectral_subset_selected" would conflict with another observe and only the last one added would actually be called. @cshanahan1 - is there an issue for this yet that we can reference?
15ff2ca
to
854389f
Compare
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.
LGTM (definitely qualifies for squashing though)!
will do! |
if uncerts is not None: | ||
if not np.any(uncerts): | ||
uncerts = None | ||
set_nans_to_none = True |
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.
Can combine nested if
?
if uncerts is not None: | |
if not np.any(uncerts): | |
uncerts = None | |
set_nans_to_none = True | |
if uncerts is not None and not np.any(uncerts): | |
uncerts = None | |
set_nans_to_none = True |
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.
done
# otherwise, data should be a list containing a single [Spectrum1D] | ||
# check just to be safe. | ||
m = 'Only supported for one data entry, if multiple spectra use SpectrumList.' | ||
raise NotImplementedError(m) |
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.
Shouldn't this be checked right at the beginning before all the extra processing is done?
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.
done, moved this to the top
msg = 'All uncertainties are nonfinite, replacing with uncertainty=None.' | ||
info_msg = SnackbarMessage(msg, color="warning", sender=app) | ||
app.hub.broadcast(info_msg) |
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 have been shortening old calls like this one to one line. No reason to assign 2 variables to this one snackbar call, as they will never be used again.
msg = 'All uncertainties are nonfinite, replacing with uncertainty=None.' | |
info_msg = SnackbarMessage(msg, color="warning", sender=app) | |
app.hub.broadcast(info_msg) | |
msg = 'All uncertainties are nonfinite, replacing with uncertainty=None.' | |
info_msg = SnackbarMessage(msg, color="warning", sender=app) | |
app.hub.broadcast(info_msg) |
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 shortened this to two lines, i thought it was nicer looking than splitting the string over two lines
ac57c0f
to
2925479
Compare
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.
Missed some doc indentation.
Otherwise I think in general the diff LGTM, so @javerbukh can do his review now. Thanks for your patience!
p.s. Open a new #2487 for general clean-up of the parser, if we ever get to it in the future. |
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.
LGTM!
2925479
to
7bf2745
Compare
ok thanks everyone! im going to merge this once CI passes |
This PR passes the
filter_non_finite
flag (set to True), tospecutils.fitting.fit_lines
. This allows non-finite values in the uncertainty/weights array to be filtered out before fitting, allowing the fit to proceed without NonFiniteValueError.Closes #2328