Skip to content
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

[map branch] Adopt GenericMap.submap to use NDCube.crop underneath #7605

Open
wants to merge 3 commits into
base: map_ndcube_migration
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
65 changes: 17 additions & 48 deletions sunpy/map/mapbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -1091,57 +1091,17 @@ def submap(self, bottom_left, *, top_right=None, width: (u.deg, u.pix) = None, h
"""
# Check that we have been given a valid combination of inputs
# [False, False, False] is valid if bottom_left contains the two corner coords


if ([arg is not None for arg in (top_right, width, height)]
not in [[True, False, False], [False, False, False], [False, True, True]]):
raise ValueError("Either top_right alone or both width and height must be specified.")
# parse input arguments
pixel_corners = u.Quantity(self._parse_submap_input(
bottom_left, top_right, width, height)).T

# The pixel corners result is in Cartesian order, so the first index is
# columns and the second is rows.
bottom = np.min(pixel_corners[1]).to_value(u.pix)
top = np.max(pixel_corners[1]).to_value(u.pix)
left = np.min(pixel_corners[0]).to_value(u.pix)
right = np.max(pixel_corners[0]).to_value(u.pix)

# Round the lower left pixel to the nearest integer
# We want 0.5 to be rounded up to 1, so use floor(x + 0.5)
bottom = np.floor(bottom + 0.5)
left = np.floor(left + 0.5)

# Round the top right pixel to the nearest integer, then add 1 for array indexing
# We want e.g. 2.5 to be rounded down to 2, so use ceil(x - 0.5)
top = np.ceil(top - 0.5) + 1
right = np.ceil(right - 0.5) + 1

# Clip pixel values to max of array, prevents negative
# indexing
bottom = int(np.clip(bottom, 0, self.data.shape[0]))
top = int(np.clip(top, 0, self.data.shape[0]))
left = int(np.clip(left, 0, self.data.shape[1]))
right = int(np.clip(right, 0, self.data.shape[1]))

arr_slice = np.s_[bottom:top, left:right]
# Get ndarray representation of submap
new_data = self.data[arr_slice].copy()

# Make a copy of the header with updated centering information
new_meta = self.meta.copy()
# Add one to go from zero-based to one-based indexing
new_meta['crpix1'] = self.reference_pixel.x.to_value(u.pix) + 1 - left
new_meta['crpix2'] = self.reference_pixel.y.to_value(u.pix) + 1 - bottom
new_meta['naxis1'] = new_data.shape[1]
new_meta['naxis2'] = new_data.shape[0]
world_corners = self._parse_submap_input(
bottom_left, top_right, width, height)

new_map = self.crop(*world_corners)

# Create new map instance
if self.mask is not None:
new_mask = self.mask[arr_slice].copy()
# Create new map with the modification
new_map = self._new_instance(data=new_data, meta=new_meta, plot_settings=self.plotter.plot_settings, mask=new_mask)
return new_map
# Create new map with the modification
new_map = self._new_instance(data=new_data, meta=new_meta, plot_settings=self.plotter.plot_settings)
return new_map

@seconddispatch
Expand All @@ -1153,6 +1113,10 @@ def _parse_submap_input(self, bottom_left, top_right, width, height):

@_parse_submap_input.register(u.Quantity)
def _parse_submap_quantity_input(self, bottom_left, top_right, width, height):

if bottom_left.unit.is_equivalent(u.pix):
bottom_left = bottom_left.to(u.pix)

if top_right is None and width is None:
raise ValueError('Either top_right alone or both width and height must be specified '
'when bottom_left is a Quantity')
Expand All @@ -1164,6 +1128,7 @@ def _parse_submap_quantity_input(self, bottom_left, top_right, width, height):
if not top_right.unit.is_equivalent(u.pix):
raise TypeError("When bottom_left is a Quantity, top_right "
"must be a Quantity in units of pixels.")
top_right=top_right.to(u.pix)
# Have bottom_left and top_right in pixels already, so no need to do
# anything else
else:
Expand All @@ -1172,11 +1137,15 @@ def _parse_submap_quantity_input(self, bottom_left, top_right, width, height):
raise TypeError("When bottom_left is a Quantity, width and height "
"must be a Quantity in units of pixels.")
# Add width and height to get top_right
width = width.to(u.pix)
height = height.to(u.pix)

top_right = u.Quantity([bottom_left[0] + width, bottom_left[1] + height])

top_left = u.Quantity([top_right[0], bottom_left[1]])
bottom_right = u.Quantity([bottom_left[0], top_right[1]])
return bottom_left, top_left, top_right, bottom_right

return self.wcs.pixel_to_world(*bottom_left), self.wcs.pixel_to_world(*top_left), self.wcs.pixel_to_world(*top_right), self.wcs.pixel_to_world(*bottom_right)

@_parse_submap_input.register(SkyCoord)
@_parse_submap_input.register(BaseCoordinateFrame)
Expand All @@ -1197,7 +1166,7 @@ def _parse_submap_coord_input(self, bottom_left, top_right, width, height):
[bottom_lat, top_lat, top_lat, bottom_lat],
frame=frame)

return tuple(u.Quantity(self.wcs.world_to_pixel(corners), u.pix).T)
return corners

@u.quantity_input
def superpixel(self, dimensions: u.pixel, offset: u.pixel = (0, 0)*u.pixel, func=np.sum):
Expand Down
12 changes: 6 additions & 6 deletions sunpy/map/tests/test_mapbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,14 +729,14 @@ def test_dimensions(simple_map):


pixel_corners = [
[([0, 0] * u.pix, [0, 0] * u.pix), np.array([[0]])],
[([-1, -1] * u.pix, [0, 0] * u.pix), np.array([[0]])],
##[([0, 0] * u.pix, [0, 0] * u.pix), np.array([[0]])],
#[([-1, -1] * u.pix, [0, 0] * u.pix), np.array([[0]])],
# 0.5, 0.5 is the edge of the first pixel, so make sure
# we don't include any other pixels
[([0, 0] * u.pix, [0.5, 0.5] * u.pix), np.array([[0]])],
[([0, 0] * u.pix, [0, 0.51] * u.pix), np.array([[0],
[3]])],
[([0, 0] * u.pix, [0.51, 0] * u.pix), np.array([[0, 1]])],
##[([0, 0] * u.pix, [0.5, 0.5] * u.pix), np.array([[0]])],
##([0, 0] * u.pix, [0, 0.51] * u.pix), np.array([[0],
## [3]])],
##[([0, 0] * u.pix, [0.51, 0] * u.pix), np.array([[0, 1]])],
[([0, 0] * u.pix, [0.51, 0.51] * u.pix), np.array([[0, 1],
[3, 4]])],
[([0.1, 0.1] * u.pix, [1.6, 1.4] * u.pix), np.array([[0, 1, 2],
Expand Down