-
-
Notifications
You must be signed in to change notification settings - Fork 64
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
Speed up adaptive reprojection #275
Conversation
9e3b570
to
bff3167
Compare
@svank - could you rebase this, which will remove the first commit since that is now merged? |
Explicitly checking for inputs to the Hann function that will produce zero-value weights, rather than clamping the inputs to one and then calculating the cosines, offers significant speed gains---both because calculating the cosines seems to be relatively expensive, and because this case of zero-weighted pixels seems to be relatively common.
bff3167
to
5dc745f
Compare
@astrofrog 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.
Looks great! Just a minor comment relating to docs syntax below
docs/celestial.rst
Outdated
how the corresponding input-image coordinate varies as you move between output | ||
pixels (or d(input image coordinate) / d(output image coordinate)), and serves | ||
as a local linearization of the coordinate transformation. When this flag is | ||
True, the Jacobian is calculated at pixel grid points by calculating the |
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 you write True and False in this paragraph with backticks to get proper syntax highlighting/linking?
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.
Good call, I've fixed and force-pushed. (The other PRs need to be rebased now, but I'll wait until after this PR is merged.)
reproject/adaptive/high_level.py
Outdated
A Jacobian matrix is calculated, representing | ||
d(input image coordinate) / d(output image coordinate), | ||
a local linearization of the coordinate transformation. When this flag | ||
is True, the Jacobian is calculated at pixel grid points by calculating |
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.
As above
This reduces the number of coordinate transformations that need to be done by 2/3. In my test configuration, this is worthwhile speed increase with a vanishingly small loss in accuracy. For the test case with an AIA image, the largest few per-pixel changes are a few percent where the transformation is most extreme, while 99.6% of non-NaN pixels change by less than 1%, and 97% by less than 0.1%. This loss of accuracy should be small for any case where the transformation varies smoothly between output pixels, which should be the case for many common real-world transformations.
This is in two parts: For each output pixel, a region of the input image is iterated through. The input pixels of interest are, in general, a parallelogram at an arbitrary orientation angle, and so a rectangular region surrounding this parallelogram is scanned through. This update reduces the size of that rectangular region to the smallest bounding box containing all the pixels of interest. This comes with significant speed gains. Second, as each row of the bounding box is scanned along, we now end the iteration once we've scanned into and out of the parallelogram, skipping any consideration of the remaining pixels in the row. This is a small but simple gain in speed.
When an output image pixel is sampling input-image coordinates that actually fall outside the input image, we can detect that early and do less work for those cases. This offers significant speedups for transformations where this case is common (e.g. a 45-degree rotation, where the corners of the output image map to out-of-bounds input coordinates).
5dc745f
to
0db3db2
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.
Thanks!
commit bc88deb Merge: 1df0d8e a9ea69a Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Thu Aug 25 11:33:10 2022 +0100 Merge pull request astropy#279 from svank/boundaries Add boundary handling options for adaptive resampling commit a9ea69a Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Tue Aug 23 10:52:53 2022 -0600 Update CHANGES.md for adaptive algo changes commit 9a0575b Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Wed Feb 2 18:18:39 2022 -0700 Add boundary handling modes for adaptive algorithm commit 1df0d8e Merge: 748a8aa f191a3b Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Aug 23 16:32:56 2022 +0100 Merge pull request astropy#299 from astrofrog/fix-linux-wheels Explicitly specify wheel targets commit f191a3b Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Aug 23 15:04:00 2022 +0100 Explicitly specify wheel targets commit 748a8aa Merge: d61edf6 cf40c3c Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Aug 23 14:54:28 2022 +0100 Merge pull request astropy#276 from svank/validation Add Gaussian kernel, achieve flux conservation in adaptive algorithm commit d61edf6 Merge: 3cfc7a8 8f80a65 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Aug 23 14:52:24 2022 +0100 Merge pull request astropy#292 from pllim/unpin-coverage TST: Unpin coverage to grab 6.4 commit cf40c3c Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Mon Aug 22 11:15:48 2022 -0600 Raise a deprecation warning if the 'order' argument is passed in commit 8f80a65 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Mon May 23 12:26:39 2022 -0400 TST: Unpin coverage to grab 6.4 commit 7f20896 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Tue Jan 18 16:00:35 2022 -0700 Documentation updates for adaptive resampling commit e1d4190 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Fri Jan 14 18:48:25 2022 -0700 Expand adaptive resampling tests Now that flux-conservation can be achieved to a high degree, we can run a grid of transforms on a simple input, and check for correctness by checking for flux conservation. commit 960da0b Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Wed Jan 12 16:51:18 2022 -0700 Add Gaussian filter kernel for adaptive resampling commit a5aee3f Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Fri Jan 7 11:00:00 2022 -0700 Remove extra interpolation step in adaptive resampling commit 0347b71 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Fri Jan 7 11:05:58 2022 -0700 Expose the 'conserve_flux' flag in adaptive API commit 3153721 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Tue Jan 4 17:38:03 2022 -0700 Reverse sign of Jacobian values This doesn't seem to affect anything, since both the linearized transform and the Hann window are symmetric, but this buts the Jacobian values in the normal finite-difference form of [f(x+dx) - f(x)] / dx commit 0187ad6 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Mon Jan 3 18:51:20 2022 -0700 Use padded singular values for building J matrix The matrix J was being built using the un-padded values, whereas the padded values ought to be used (as called for by DeForest (2004)). This caused incorrect averaging weights to be computed for some sample values, in transformations where the padding of singular values is required. For the implemented test cases, the effect of this fix is quite small. commit 4a1a492 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Mon Jan 3 11:49:49 2022 -0700 Remove incorrect normalization in Hann window The window should carry a factor of 1/2 for each of the two cosine terms being multiplied together, for a combined factor of 1/4. However, the normalization factor comes out anyway when output pixel values are divided by the sum of the weights, so it's a micro-optimization to just remove the factor rather than correcting it. commit 3cfc7a8 Merge: 4f5e943 4f11ad4 Author: Stuart Mumford <stuart@cadair.com> Date: Wed May 18 09:34:31 2022 +0100 Merge pull request astropy#290 from Cadair/python310 Add CI jobs for Python 3.10 and Drop Python 3.7 commit 4f11ad4 Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 17:04:02 2022 +0100 newer rtd config commit 28e5e5a Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 16:55:01 2022 +0100 Refector oldestdeps a lot commit 1e7b1dc Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 15:43:31 2022 +0100 Drop support for Python 3.7 commit f24c4f7 Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 15:28:53 2022 +0100 Add Python 3.10 to the CI commit 4f5e943 Merge: 19c81e1 29bc336 Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 11:51:21 2022 +0100 Merge pull request astropy#287 from pllim/fix-ci TST: Fix CI commit 29bc336 Merge: eb76a88 19c81e1 Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 11:37:20 2022 +0100 Merge branch 'main' into fix-ci commit 19c81e1 Merge: 3b5bb62 e6284bf Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 11:36:28 2022 +0100 Merge pull request astropy#289 from Cadair/fix_ci Fix CI by ignoring sunpy warning commit e6284bf Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 11:20:31 2022 +0100 Cancel running builds on new push commit 956165b Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 11:19:57 2022 +0100 Don't build wheels on PRs commit 3d064b2 Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 17 11:07:59 2022 +0100 Ignore the sunpy warning See sunpy/sunpy#6158 commit 3b5bb62 Merge: ea8a388 070520e Author: Stuart Mumford <stuart@cadair.com> Date: Tue May 10 15:05:23 2022 +0100 Merge pull request astropy#283 from astropy/actions Use OpenAstronomy GitHub actions workflows commit 070520e Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Sat Apr 23 00:16:33 2022 +0100 Skip Python 3.10 on 32-bit Windows as no scipy wheels are available commit eb76a88 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Fri Apr 22 14:44:34 2022 -0400 TST: Freeze 32-bit Docker image commit c33c781 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Fri Apr 22 14:37:35 2022 -0400 TST: Revert astropy#272 commit 985c157 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Fri Apr 22 14:32:29 2022 -0400 Fix PEP 8 warnings commit 9e473cb Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Fri Apr 22 16:51:41 2022 +0100 Remove the before-build step for cibuildwheel commit f17a068 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Apr 5 17:12:36 2022 +0100 Fix code style issues commit 2d6382e Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Apr 5 17:09:26 2022 +0100 Skip musllinux builds commit 7fd25ba Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Apr 5 17:08:24 2022 +0100 Skip PyPy builds commit 60bb273 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Thu Mar 31 14:16:05 2022 +0100 Don't set codecov token commit 3fac4bf Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Mar 29 16:57:08 2022 +0100 Configure cibuildwheel via pyproject.toml and remove explicit 32-bit testing, relying instead on wheel building commit 068faa7 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Fri Mar 25 00:23:37 2022 +0000 Added missing | commit aa61dca Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Thu Mar 24 16:39:47 2022 +0000 Simplify on: section commit bf8f5b8 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Thu Mar 24 16:36:45 2022 +0000 Use OpenAstronomy publish template commit b26fc72 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Thu Mar 24 16:32:43 2022 +0000 Use OpenAstronomy tox workflow commit ea8a388 Merge: 734665b 0db3db2 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Tue Apr 5 14:59:58 2022 +0100 Merge pull request astropy#275 from svank/adaptive-but-faster Speed up adaptive reprojection commit 0db3db2 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Tue Dec 21 14:54:05 2021 -0700 Add option to disable roundtrip-checking of transforms commit 3bae9f8 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Fri Dec 17 17:32:38 2021 -0700 Optimize out-of-bounds cases When an output image pixel is sampling input-image coordinates that actually fall outside the input image, we can detect that early and do less work for those cases. This offers significant speedups for transformations where this case is common (e.g. a 45-degree rotation, where the corners of the output image map to out-of-bounds input coordinates). commit 6c14e9d Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Fri Dec 17 10:36:27 2021 -0700 Reduce size of sampled input region to only what's needed This is in two parts: For each output pixel, a region of the input image is iterated through. The input pixels of interest are, in general, a parallelogram at an arbitrary orientation angle, and so a rectangular region surrounding this parallelogram is scanned through. This update reduces the size of that rectangular region to the smallest bounding box containing all the pixels of interest. This comes with significant speed gains. Second, as each row of the bounding box is scanned along, we now end the iteration once we've scanned into and out of the parallelogram, skipping any consideration of the remaining pixels in the row. This is a small but simple gain in speed. commit 89d26c8 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Fri Dec 10 10:56:45 2021 -0700 Add support for un-centered Jacobians, make default This reduces the number of coordinate transformations that need to be done by 2/3. In my test configuration, this is worthwhile speed increase with a vanishingly small loss in accuracy. For the test case with an AIA image, the largest few per-pixel changes are a few percent where the transformation is most extreme, while 99.6% of non-NaN pixels change by less than 1%, and 97% by less than 0.1%. This loss of accuracy should be small for any case where the transformation varies smoothly between output pixels, which should be the case for many common real-world transformations. commit e2792a9 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Thu Dec 9 15:32:52 2021 -0700 Improve handling of zero-weight pixels Explicitly checking for inputs to the Hann function that will produce zero-value weights, rather than clamping the inputs to one and then calculating the cosines, offers significant speed gains---both because calculating the cosines seems to be relatively expensive, and because this case of zero-weighted pixels seems to be relatively common. commit 734665b Merge: 43b8289 ffc5919 Author: Thomas Robitaille <thomas.robitaille@gmail.com> Date: Thu Mar 24 16:26:01 2022 +0000 Merge pull request astropy#274 from svank/fix-jacobian-use Fix Jacobian calculation in the adaptive algorithm commit 43b8289 Merge: 41dbdf3 ceebae7 Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Mon Feb 7 10:28:41 2022 -0500 Merge pull request astropy#277 from pllim/pin-coverage TST: Pin coverage for now commit ffc5919 Author: Sam Van Kooten <vankooten.sam@gmail.com> Date: Mon Dec 20 15:38:40 2021 -0700 Fix Jacobian calculation in the adaptive algorithm The Jacobian matrix Ji was being calculated as the transpose of what it should be, if it's to be used as a standard transformation-as-a-matrix. Its inverse, J, was then also transposed. When this J is eventually used, it was used in the transform-as-a-matrix manner. The effect of this transposition appears to have been minor. If the Jacobian matrix is decomposed into a scaling, a shearing, and a rotation, the scaling is unaffected, x and y shearings are swapped, and the rotation's direction is reversed. When thinking of circles in the output plane being mapped to ellipses in the input plane, within which to sample pixels to form the output pixel value, those ellipses would be oriented differently than they should be, but they would have the same overall area. For the tests currently implemented, the differences in the output images before and after this fix tend to be small and are not visually apparent. commit ceebae7 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Mon Jan 31 09:41:13 2022 -0500 TST: Pin coverage for now commit 41dbdf3 Merge: ca95519 c92f0ef Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Thu Jan 13 12:59:31 2022 -0500 Merge pull request astropy#273 from pllim/minor-cleanups MNT: General clean-up commit c92f0ef Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Thu Jan 13 12:19:27 2022 -0500 MNT: General clean-up from astropy#271 because that PR might take a while and these should be uncontroversial commit ca95519 Merge: e8cb2dc 7b47641 Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Thu Jan 13 12:12:27 2022 -0500 Merge pull request astropy#272 from pllim/fix-ci-devdeps TST: Ignore asdf warning for devdeps commit 7b47641 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Thu Jan 13 11:50:46 2022 -0500 TST: Ignore asdf warning for devdeps commit e8cb2dc Merge: 891be7d 66ab9fb Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Thu Jan 13 00:30:57 2022 -0500 Merge pull request astropy#267 from pllim/last-actions-hero-2 TST: Fix and update CI commit 66ab9fb Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 23:49:17 2022 -0500 TST: Use dev sunpy for devdeps job commit b7c01db Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 23:30:06 2022 -0500 TST: Install dev asdf-astropy for devdeps commit 5ca5833 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 23:21:04 2022 -0500 TST: Also use dev asdf and gwcs for devdeps. commit 5720164 Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 17:22:48 2022 -0500 BUG: Fix workflow. DOC: Update badges. TST: Clean up interpolation/test_core.py . TST: Turn all unhandled warnings into exceptions. TST: Turn relative imports to absolute for some test files. commit 891be7d Merge: 43cba33 602f8cc Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 17:16:26 2022 -0500 Merge pull request astropy#266 from pllim/last-actions-hero TST: Move CI from Azure to Actions commit 602f8cc Author: Pey Lian Lim (Github) <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 17:13:26 2022 -0500 TST: Move CI from Azure to Actions commit 43cba33 Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 10:22:42 2022 -0500 Intermediate 0.8.1 changelog entry [ci skip] commit 7af8ae9 Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 10:20:05 2022 -0500 Changelog section for v0.9 [ci skip] commit 7397af2 Merge: fe925be f1e874f Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 10:12:31 2022 -0500 Merge pull request astropy#257 from dstansby/interp-doc Add some more docs for reproject_interp commit fe925be Merge: 4356e35 79fa247 Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 10:11:29 2022 -0500 Merge pull request astropy#263 from pllim/deprecation-deprecated MNT: Stop using distutils commit 4356e35 Merge: 43b0d8a 369e0a1 Author: P. L. Lim <2090236+pllim@users.noreply.github.com> Date: Wed Jan 12 10:10:43 2022 -0500 Merge pull request astropy#248 from pllim/replace-with-main MNT: Replace master with main commit 79fa247 Author: Pey Lian Lim <2090236+pllim@users.noreply.github.com> Date: Thu Dec 30 22:09:36 2021 -0500 MNT: Stop using distutils commit f1e874f Author: David Stansby <dstansby@gmail.com> Date: Sat Nov 6 11:21:21 2021 +0000 Add some more docs for reproject_interp commit 369e0a1 Author: Pey Lian Lim <2090236+pllim@users.noreply.github.com> Date: Tue Mar 9 14:22:40 2021 -0500 Revert out-of-scope changes Dunno why still point to astrofrog repo but ok commit 5bafa7d Author: Pey Lian Lim <2090236+pllim@users.noreply.github.com> Date: Tue Mar 9 14:20:24 2021 -0500 MNT: Replace master with main
This PR applies on top of PR #274 and is the second of three I'll be submitting.
These commits provide very significant speed-ups to the adaptive resampling algorithm. In my test case (which arose naturally from real-world use but was unintentionally a bit pathological [1]), runtime decreased from 972 seconds to 3.3 seconds (comparing well to the 'exact' algorithm, at 15 seconds). The final commit also benefits the interpolation algorithm, reducing its runtime for my test case from 7s to 2.6s.
Here's some quick discussion on each change:
The first commit here is "Improve handling of zero-weight pixels". The algorithm computes an averaging weight for each input sample. It's frequently the case that the computed weight is zero (since sampling must be done across a region larger that the "non-zero weight" region to be sure to include everything). This commit adds an explicit and cheap check for that condition, and the weighting function returns 0 directly rather than computing out the zero weight the long way. This alone took my test case runtime from 972s to 160s.
The next commit trades a very small amount of accuracy in computing the Jacobian matrix in order to reduce the amount of coordinate transforms done by two thirds. This is described in the documentation additions in this commit. I've made this speedier option the default, but left the option to use the slower, more accurate calculations. For real-world situations, where the coordinate transformation doesn't change much between neighboring output pixels, the loss in accuracy from the faster version should be negligible. For my PSP/WISPR test case, the output image changes by less than 0.002% per pixel, and the runtime drops from 160s to 145s. For the implemented test case with an AIA image, the largest few per-pixel changes are a few percent where the transformation is most extreme, while 99.6% of non-NaN pixels change by less than 1%, and 97% by less than 0.1%.
The next commit reduces the number of input pixels sampled by cropping out many zero-weight pixels from the sampling region. The region where the filter function produces non-zero weights is a square in the output plane, so I transform the corners of that square to the input plane with the Jacobian, and sample through a bounding box containing the transformed corners. This is the commit that depends on the previous PR, as it makes use of that Jacobian. This cuts down on the number of zero-weight pixels that are iterated over, and reduces my runtime from 145s to 49s.
The next commit clamps the sampling region in the input plane to the bounds of the input image. This prevents attempts to sample non-existent input pixels---those attempts didn't cause any problems, but they did waste time. An extra benefit is that in cases where the output image has many pixels that map to regions outside the input image, zero sampling has to be done for those output pixels. This was significant in my test case, bringing runtime from 49s to 7.7s.
The last commit adds a flag to disable roundtrip checking of the coordinate transforms. By default, for every output pixel coordinate that's transformed to input-image coordinates, that coordinate is immediately transformed back to the output plane to verify that the transform is defined in both directions. In my case, that check isn't necessary, and using this flag to disable the check cuts my runtime from 7.7s to 3.3s. I've set the default to keep doing the check, to ensure that situations that need the check get correct behavior by default. The interpolation algorithm,
reproject_interp
, does this same check, and so I've added the same flag to that function, where it takes my test case from 7.0s to 2.6s.The commit speeding up the Jacobian calculation is the only one that changes the outputs of the test cases, since the speedier behavior is on by default. The other commits have no effect on the output images, and do not change the reference images for the tests.
[1] I'm using Parker Solar Probe's WISPR instrument, which includes two cameras, providing an inner (more Sun-ward) and outer field of view. Combining images from the two to form a composite field of view requires reprojecting the images into a common projection. My test case is reprojecting the inner FOV image into an array the size of the composite FOV, which leaves about half of the output array empty. (The reprojected outer-FOV image would then be pasted into this space.) The coordinate transform is well-behaved for the portion of the output image that maps to the inner FOV, but for the pixels on the far side of the output array, the coordinate transform produces some extreme warping and causes each output pixel to attempt to sample thousands of (non-existent) pixels from the input image. My runtimes could have been reduced quite a bit by reprojecting the image into an output array sized for just the inner-FOV image, but after this PR, that sort of care isn't required from the user.