Repository navigation
Fix convolve_fft nan_treatment='fill' handling - #8122
Conversation
|
Check results are now reported in the status checks at the bottom of this page. |
|
It's not super clear to me how useful the |
2005274 to
c36af00
Compare
|
@keflavich , |
|
I suppose this is a bugfix, but if it's not, please move to milestone 3.2 |
Codecov Report
@@ Coverage Diff @@
## master #8122 +/- ##
==========================================
+ Coverage 86.36% 86.91% +0.55%
==========================================
Files 405 383 -22
Lines 60859 57859 -3000
Branches 1096 1056 -40
==========================================
- Hits 52559 50291 -2268
+ Misses 7676 6954 -722
+ Partials 624 614 -10
Continue to review full report at Codecov.
|
| AstropyUserWarning) | ||
| rifft[arrayslices][nanmaskarray] = np.nan | ||
| elif nan_treatment == 'fill': | ||
| rifft[arrayslices][nanmaskarray] = fill_value |
There was a problem hiding this comment.
@keflavich I'm pretty confused. Why are the values being filled post convolution?
There was a problem hiding this comment.
This needs to happen pre-convolution.
There was a problem hiding this comment.
Good catch. This already happens pre-convolution, but not with the intended fill_value.
|
|
||
| if preserve_nan: | ||
| if nan_treatment == 'fill': | ||
| warnings.warn("preserve_nan was set, which overrides the " |
There was a problem hiding this comment.
This is not semantically true. Whilst preserve_nan=True will persist the NaN values that get filled, it doesn't/shouldn't "override" nan_treatment='fill' functionality. The values should be filled pre-convolution and therefore contribute to their surrounding convolutions regardless of whether they remain as the convolved values or revert to their original NaN values.
jamienoss
left a comment
There was a problem hiding this comment.
This doesn't implement nan_treatment='fill'. The values need to be filled pre-convolution.
| AstropyUserWarning) | ||
| rifft[arrayslices][nanmaskarray] = np.nan | ||
| elif nan_treatment == 'fill': | ||
| rifft[arrayslices][nanmaskarray] = fill_value |
There was a problem hiding this comment.
This needs to happen pre-convolution.
| if nan_treatment == 'fill': | ||
| array[nanmaskarray] = fill_value | ||
| else: | ||
| array[nanmaskarray] = 0 |
There was a problem hiding this comment.
@jamienoss this line replaced the values with the default fill_value of zero. So, the behavior was "always (kinda) correct" for fill_value=0, and we never had a test for other cases.
There was a problem hiding this comment.
(this comment is the answer to #8122 (comment))
There was a problem hiding this comment.
Ok, cool, thanks. It was right in front of me after all.
| else: | ||
| rifft = ifftn(fftmult) | ||
|
|
||
| if preserve_nan: |
There was a problem hiding this comment.
I think this condition needs to stay.
|
@jamienoss thanks for the review. There's a real chance I messed something up further; I clearly did not put in enough thought the first time around. It would be helpful to check that the tests are doing the right thing, i.e., coming up with the right numbers for all 3 elements in the array for the simple 1D convolutions. |
|
@keflavich I'll take a look at the tests tomorrow. |
| fill_value=np.nan) | ||
|
|
||
| with warnings.catch_warnings(): | ||
| warnings.simplefilter('ignore', RuntimeWarning) |
There was a problem hiding this comment.
Prob needs a comment outlining its intent.
There was a problem hiding this comment.
this is just a c&p from a previous test, so you're right.
There was a problem hiding this comment.
I dropped the catching; it's not needed when filling.
| warnings.simplefilter('ignore', RuntimeWarning) | ||
| result = convolve_fft(masked_array, kernel, boundary='fill', | ||
| nan_treatment='interpolate', | ||
| fill_value=np.nan) |
There was a problem hiding this comment.
Ok, so I've been trying to figure out the point to this test, specifically why fill_value=np.nan. In fact, I think it points out another bug. I'll open an issue.
In the meantime, what is the intent of this test and why fill_value=np.nan?
There was a problem hiding this comment.
The original intent was to test that convolution could successfully ignore edge padding by setting the external pixels to NaN, I believe. However, that might be an outdated use case now that we have two different nan_treatment approaches.
|
|
||
| result = convolve_fft(masked_array, kernel, boundary='fill', | ||
| nan_treatment='interpolate', | ||
| fill_value=np.nan) |
There was a problem hiding this comment.
Ok, so I've been trying to figure out the point to this test, specifically why fill_value=np.nan. In fact, I think it points out another bug. I'll open an issue.
In the meantime, what is the intent of this test and why fill_value=np.nan?
| array = np.array([1., np.nan, 3.], dtype='float64') | ||
| kernel = np.array([1, 1, 1]) | ||
|
|
||
| with warnings.catch_warnings(): |
There was a problem hiding this comment.
Right, again, in the fill cases, we shouldn't need to catch div-by-zero errors because there shouldn't be any. Fix incoming.
| array = np.array([1., np.nan, 3.], dtype='float64') | ||
| kernel = np.array([1, 1, 1]) | ||
|
|
||
| with warnings.catch_warnings(): |
| fill_value=0) | ||
|
|
||
| # note that, because fill_value also affects boundary='fill', the edge | ||
| # pixels are treated as zero rather than being ignored. |
There was a problem hiding this comment.
Right, this is the bug, it shouldn't happen this way.
There was a problem hiding this comment.
Yeah, this isn't so much a bug as a design failure, as highlighted in #8127
There was a problem hiding this comment.
Probably, however, it's not always the case that the developer gets to define what is and isn't a bug. I.e. the artist of modern abstract art doesn't get to completely define its interpretation.
If the behaviour and functionality don't intuitively match the semantics (or the documentation (loophole)) then it is a bug. Even if the fix is just readjusting the semantics by documenting it as a feature (hence the loophole), it's still a bug until fixed.
There was a problem hiding this comment.
I'm going to stick with "design failure" because neither the documentation nor the implementation actually make sense. As you pointed out, fill_value is incorrectly tied to both boundary and nan_treatement, which results in some nonsense parameter combinations.
That's said, this is all semantics, we have a bunch of crap that needs to be cleaned up, and I'm just arguing for punting the fixes related to this particular line to #8127, since it more accurately and completely describes the problem.
There is an open question here, though - should this PR be merged before dealing with the bigger issues in 8127, or should we try to get everything right all at once? I'm open to suggestions; I don't believe there are many/any users trying to use this corner of the convolution code yet, which gives us some flexibility, but we want it all to be right as soon as possible...
There was a problem hiding this comment.
I'm cool to defer this particular point to #8127. I think it might be better and safer to address this piece by piece. I'm already trying to untangle the normalization and nan treatment as I did for convolve, so we already have a few parallel jobs.
There was a problem hiding this comment.
👍 Thanks for doing this.
Just to give you some background: these problems mostly come from convolve and convolve_fft being developed fully independently (convolve by Tom, convolve_fft by me), then trying to match their call specifications. In trying to make convolve_fft match convolve's arguments more closely, I clearly missed/ignored several use cases that I had never considered. It's looking more likely that I caught all of the inverse, i.e., things convolve_fft did that needed to be ported over to convolve.
| nan_treatment=nan_treatment, | ||
| fill_value=np.nan if normalize_kernel else 0, | ||
| # you cannot fill w/nan, you can only interpolate over it | ||
| fill_value=np.nan if normalize_kernel and nan_treatment=='interpolate' else 0, |
There was a problem hiding this comment.
Even though this was already conditional on normalize_kernel, I don't think it should be constraining the test space. The addition of nan_treatment=='interpolate' also constrains the test and I don't think it is a good idea to do so. We should be trying to test all parameter space and just deal with the outcome appropriately in the test.
There was a problem hiding this comment.
I've lost the thread of this conversation... are you saying we should run this test with both np.nan and 0 for fill values, and just check the returns for each case are correct? That's reasonable, and I think the expected outcome is:
if np.isnan(fill_value) and not (normalize_kernel and nan_treatment=='interpolate'): an exception should be raised, but all cases should be allowed with fill_value=0.
I'm not certain of this, though, I should go check....
| z = convolve_fft(x, y, boundary=boundary, | ||
| nan_treatment=nan_treatment, | ||
| fill_value=np.nan if normalize_kernel else 0, | ||
| # you cannot fill w/nan, you can only interpolate over it |
|
|
||
| import itertools | ||
|
|
||
| import warnings |
There was a problem hiding this comment.
When the other warnings are removed, don't forget to remove this also.
|
From the Astropy Coordination Meeting notes for 3.2 release, this is one of the items listed but looks like it is already milestoned as 3.1.x. |
|
@keflavich - This seems to be very close to be finished. Do you have time to finalize it? |
|
@bsipocz it might be further from done than I realized... |
|
@keflavich - sadly those test failures are coming from master. Anyway, if it's indeed further from done, please remilestone to 3.2.1 |
|
@keflavich , try a rebase. |
there's still more to go
likely to break some tests)
e836462 to
13694b1
Compare
|
@keflavich , change log needs fixing. FYI. |
|
I'm happy to fix changelogs if they're the only leftover stuff in a PR (I need to do it anyway already). |
|
@larrybradley @adonath - Could either of you please review and approve it if you're happy with it? |
|
@keflavich Is this PR ready for final review. It looks like there are several unresolved conversations and your last comment of "I don't know the current state" suggests to me that this may need more work? If that's the case, I'll re-milestone for 4.1. |
|
@larrybradley It needs a review. I don't believe it needs more work, though. |
larrybradley
left a comment
There was a problem hiding this comment.
Thanks, @keflavich.
fix: #8121
|
@bsipocz This needs a new changelog entry. |
is it a bugfix or a feature? I could argue for either of those... |
|
I'd call it a bugfix. The |
Fix for issue #8121
WIP: needs a test
cc @jamienoss