Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/893.doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added an example (:ref:`sphx_glr_generated_gallery_changing_resolution_via_reproject.py`) showing how to change resolution of an NDCube using `~ndcube.NDCube.reproject_to`.
64 changes: 64 additions & 0 deletions examples/changing_resolution_via_reproject.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
=====================================
Changing the resolution of an NDCube
=====================================

This example shows how to change the resolution of an NDCube by reprojecting to a finer grid.
"""

import matplotlib.pyplot as plt

from astropy.io import fits
from astropy.wcs import WCS

from sunpy.data.sample import AIA_171_IMAGE
from sunpy.visualization.colormaps import cm

from ndcube import NDCube

############################################################################
# We start by creating an NDCube from sample solar data provided by SunPy.
# Here we use an AIA 171 image, but the same approach can be applied to other datasets, including those with non celestial axes.

image_data = fits.getdata(AIA_171_IMAGE)
image_header = fits.getheader(AIA_171_IMAGE)
cube = NDCube(image_data, WCS(image_header))

###########################################################################
# Next, we define a new WCS with a finer pixel scale, note that while it is obvious that the CDELT values are changed to reflect the finer scale,
# the CRPIX values also need to be adjusted as the reference pixel position is different on the new pixel scale.
# You can scale the axes by any amount, including non-integer values, greater or less than 1.
# You can also scale each axis independently.
# Here we scale both spatial axes by a factor of 1.5.

scale_factor = 1.5

new_wcs = cube.wcs.deepcopy()
new_wcs.wcs.cdelt /= scale_factor
new_wcs.wcs.crpix *= scale_factor
new_shape = tuple(int(s * scale_factor) for s in cube.data.shape)

###########################################################################
# We reproject the original cube to the new WCS.
reprojected_cube = cube.reproject_to(new_wcs, shape_out=new_shape)

###########################################################################
# Our new NDCube now has a higher resolution.
print(cube.data.shape, reprojected_cube.data.shape)

###########################################################################
# We can plot the original and reprojected cubes side by side.

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 8))

ax1.imshow(cube.data, origin='lower', cmap=cm.sdoaia171, vmin=10, vmax=10000)
ax1.set_title('Original')
ax1.set_xlabel('X [pixel]')
ax1.set_ylabel('Y [pixel]')

ax2.imshow(reprojected_cube.data, origin='lower', cmap=cm.sdoaia171, vmin=10, vmax=10000)
ax2.set_title('Reprojected (Upscaled)')
ax2.set_xlabel('X [pixel]')
ax2.set_ylabel('Y [pixel]')
plt.tight_layout()
plt.show()
4 changes: 3 additions & 1 deletion ndcube/ndcube.py
Original file line number Diff line number Diff line change
Expand Up @@ -1267,9 +1267,11 @@ def my_propagate(uncertainty, data, mask, **kwargs):
bin_shape[bin_shape == -1] = np.array(data_shape)[bin_shape == -1]
if (bin_shape < 0).any():
raise ValueError("bin_shape should not be less than -1.")
if np.any(bin_shape > data_shape):
raise ValueError("bin_shape cannot be larger than data shape in any dimension.")
if (np.mod(data_shape, bin_shape) != 0).any():
raise ValueError(
"bin shape must be an integer fraction of the data shape in each dimension. "
"bin_shape must be an integer fraction of the data shape in each dimension. "
f"data shape: {data_shape}; bin shape: {bin_shape}"
)

Expand Down
11 changes: 9 additions & 2 deletions ndcube/tests/test_ndcube_reproject_and_rebin.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,20 @@ def test_rebin_some_masked_uncerts_exclude_masked_values(ndcube_2d_ln_lt_mask_un
def test_rebin_errors(ndcube_3d_l_ln_lt_ectime):
cube = ndcube_3d_l_ln_lt_ectime
# Wrong number of axes in bin_shape)
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="bin_shape must have an entry for each"):
cube.rebin((2,))

# bin shape shouldn't have any negatives
with pytest.raises(ValueError, match="bin_shape should not be less than -1"):
cube.rebin((2, -2, 1))
# bin_shape not integer multiple of data shape.
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="bin_shape must be an integer fraction"):
cube.rebin((9, 2, 1))

# bin_shape larger than data shape.
with pytest.raises(ValueError, match="bin_shape cannot be larger than data shape"):
cube.rebin((20, 2, 1))


def test_rebin_no_propagate(ndcube_2d_ln_lt_mask_uncert):
# Execute rebin.
Expand Down