1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
From: Nabil Freij <nabil.freij@gmail.com>
Date: Tue, 6 Sep 2022 10:27:23 +0100
Subject: Fix compatibility with reproject 0.10
---
ndcube/ndcube.py | 104 ++++++++++++++++++--------------------------
ndcube/tests/test_ndcube.py | 1 +
2 files changed, 44 insertions(+), 61 deletions(-)
diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py
index b78e593..5c883b8 100644
--- a/ndcube/ndcube.py
+++ b/ndcube/ndcube.py
@@ -597,64 +597,36 @@ class NDCubeBase(NDCubeSlicingMixin, NDCubeABC):
# Creating a new NDCubeSequence with the result_cubes and common axis as axis
return NDCubeSequence(result_cubes, meta=self.meta)
- def _validate_algorithm_and_order(self, algorithm, order):
- order_compatibility = {
- 'interpolation': ['nearest-neighbor', 'bilinear', 'biquadratic', 'bicubic'],
- 'adaptive': ['nearest-neighbor', 'bilinear'],
- 'exact': []
- }
-
- if algorithm in order_compatibility:
- if order_compatibility[algorithm] and order not in order_compatibility[algorithm]:
- raise ValueError(f"For '{algorithm}' algorithm, the 'order' argument must be "
- f"one of {', '.join(order_compatibility[algorithm])}.")
-
- else:
- raise ValueError(f"The 'algorithm' argument must be one of "
- f"{', '.join(order_compatibility.keys())}.")
-
- def reproject_to(self, target_wcs, algorithm='interpolation', shape_out=None, order='bilinear',
- output_array=None, parallel=False, return_footprint=False):
+ def reproject_to(self, target_wcs, algorithm='interpolation', shape_out=None, return_footprint=False, **reproject_args):
"""
- Reprojects this NDCube to the coordinates described by another WCS object.
+ Reprojects this `~nducbe.NDCube` to the coordinates described by another WCS object.
Parameters
----------
- algorithm: `str`
- The algorithm to use for reprojecting. This can be any of: 'interpolation', 'adaptive',
- and 'exact'.
-
target_wcs : `astropy.wcs.wcsapi.BaseHighLevelWCS`, `astropy.wcs.wcsapi.BaseLowLevelWCS`,
or `astropy.io.fits.Header`
The WCS object to which the ``NDCube`` is to be reprojected.
+ algorithm: `str` {'interpolation', 'adaptive', 'exact'}
+ The algorithm to use for reprojecting.
+ When set to 'interpolation' ~`reproject.reproject_interp` is used,
+ when set to 'adaptive' ~`reproject.reproject_adaptive` is used and
+ when set to 'exact' ~`reproject.reproject_exact` is used.
+
shape_out: `tuple`, optional
The shape of the output data array. The ordering of the dimensions must follow NumPy
ordering and not the WCS pixel shape.
If not specified, `~astropy.wcs.wcsapi.BaseLowLevelWCS.array_shape` attribute
(if available) from the low level API of the ``target_wcs`` is used.
- order: `int` or `str`
- The order of the interpolation (used only when the 'interpolation' or 'adaptive'
- algorithm is selected).
- For 'interpolation' algorithm, this can be any of: 'nearest-neighbor', 'bilinear',
- 'biquadratic', and 'bicubic'.
- For 'adaptive' algorithm, this can be either 'nearest-neighbor' or 'bilinear'.
-
- output_array: `numpy.ndarray`, optional
- An array in which to store the reprojected data. This can be any numpy array
- including a memory map, which may be helpful when dealing with extremely large files.
-
- parallel: `bool` or `int`
- Flag for parallel implementation (used only when the 'exact' algorithm is selected).
- If ``True``, a parallel implementation is chosen and the number of processes is
- selected automatically as the number of logical CPUs detected on the machine.
- If ``False``, a serial implementation is chosen.
- If the flag is a positive integer n greater than one, a parallel implementation
- using n processes is chosen.
+ return_footprint : `bool`
+ If `True`` the footprint is returned in addition to the new `~ndcube.NDCube`.
+ Defaults to `False`.
- return_footprint: `bool`
- Whether to return the footprint in addition to the output NDCube.
+ **reproject_args
+ All other arguments are passed through to the reproject function
+ being called. The function being called depends on the
+ ``algorithm=`` keyword argument, see that for more details.
Returns
-------
@@ -662,13 +634,21 @@ class NDCubeBase(NDCubeSlicingMixin, NDCubeABC):
A new resultant NDCube object, the supplied ``target_wcs`` will be the ``.wcs`` attribute of the output ``NDCube``.
footprint: `numpy.ndarray`
- Footprint of the input array in the output array. Values of 0 indicate no coverage or
- valid values in the input image, while values of 1 indicate valid values.
+ Footprint of the input array in the output array.
+ Values of 0 indicate no coverage or valid values in the input
+ image, while values of 1 indicate valid values.
+
+ See Also
+ --------
+
+ * `reproject.reproject_interp`
+ * `reproject.reproject_adaptive`
+ * `reproject.reproject_exact`
Notes
-----
This method doesn't support handling of the ``mask``, ``extra_coords``, and ``uncertainty`` attributes yet.
- However, ``meta`` and ``global_coords`` are copied to the output ``NDCube``.
+ However, ``meta`` and ``global_coords`` are copied to the output `ndcube.NDCube`.
"""
try:
from reproject import reproject_adaptive, reproject_exact, reproject_interp
@@ -676,6 +656,15 @@ class NDCubeBase(NDCubeSlicingMixin, NDCubeABC):
except ModuleNotFoundError:
raise ImportError("The NDCube.reproject_to method requires the optional package `reproject`.")
+ algorithms = {
+ "interpolation": reproject_interp,
+ "adaptive": reproject_adaptive,
+ "exact": reproject_exact,
+ }
+
+ if algorithm not in algorithms.keys():
+ raise ValueError(f"{algorithm=} is not valid, it must be one of {', '.join(algorithms.keys())}.")
+
if isinstance(target_wcs, Mapping):
target_wcs = WCS(header=target_wcs)
@@ -693,27 +682,20 @@ class NDCubeBase(NDCubeSlicingMixin, NDCubeABC):
if not utils.wcs.compare_wcs_physical_types(self.wcs, target_wcs):
raise ValueError('Given target_wcs is not compatible with this NDCube, the physical types do not match.')
- # If shape_out is not specified explicity, try to extract it from the low level WCS
+ # TODO: Upstream this check into reproject
+ # If shape_out is not specified explicitly,
+ # try to extract it from the low level WCS
if not shape_out:
if hasattr(low_level_target_wcs, 'array_shape') and low_level_target_wcs.array_shape is not None:
shape_out = low_level_target_wcs.array_shape
else:
raise ValueError("shape_out must be specified if target_wcs does not have the array_shape attribute.")
- self._validate_algorithm_and_order(algorithm, order)
-
- if algorithm == 'interpolation':
- data = reproject_interp(self, output_projection=target_wcs, shape_out=shape_out,
- order=order, output_array=output_array,
- return_footprint=return_footprint)
-
- elif algorithm == 'adaptive':
- data = reproject_adaptive(self, output_projection=target_wcs, shape_out=shape_out,
- order=order, return_footprint=return_footprint)
-
- elif algorithm == 'exact':
- data = reproject_exact(self, output_projection=target_wcs, shape_out=shape_out,
- parallel=parallel, return_footprint=return_footprint)
+ data = algorithms[algorithm](self,
+ output_projection=target_wcs,
+ shape_out=shape_out,
+ return_footprint=return_footprint,
+ **reproject_args)
if return_footprint:
data, footprint = data
diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py
index a80f6b0..64b30c1 100644
--- a/ndcube/tests/test_ndcube.py
+++ b/ndcube/tests/test_ndcube.py
@@ -808,6 +808,7 @@ def test_reproject_invalid_algorithm(ndcube_4d_ln_l_t_lt, wcs_4d_lt_t_l_ln):
shape_out=(5, 10, 12, 8))
+@pytest.mark.skip(reason="Incompatible with reproject; removed in #552")
def test_reproject_invalid_order(ndcube_2d_ln_lt, wcs_2d_lt_ln):
shape_out = (10, 12)
|