Skip to content

Commit 26675f6

Browse files
committed
Another go that failed
1 parent 0a9c19c commit 26675f6

File tree

2 files changed

+39
-51
lines changed

2 files changed

+39
-51
lines changed

ndcube/ndcube.py

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,7 @@ def quantity(self):
481481
"""Unitful representation of the NDCube data."""
482482
return u.Quantity(self.data, self.unit, copy=_NUMPY_COPY_IF_NEEDED)
483483

484-
485-
def _generate_independent_world_coords(self, pixel_corners, wcs, pixel_axes, units):
484+
def _generate_independent_world_coords(self, pixel_corners, wcs, needed_axes, units):
486485
"""
487486
Generate world coordinates for independent axes.
488487
@@ -495,8 +494,8 @@ def _generate_independent_world_coords(self, pixel_corners, wcs, pixel_axes, uni
495494
If one needs pixel corners, otherwise pixel centers.
496495
wcs : astropy.wcs.WCS
497496
The WCS.
498-
pixel_axes : array-like
499-
The pixel axes.
497+
needed_axes : array-like
498+
The required pixel axes.
500499
units : bool
501500
If units are needed.
502501
@@ -505,29 +504,19 @@ def _generate_independent_world_coords(self, pixel_corners, wcs, pixel_axes, uni
505504
array-like
506505
The world coordinates.
507506
"""
508-
naxes = len(self.data.shape)
509-
pixel_indices = [np.array([0], dtype=int).reshape([1] * naxes).squeeze()] * naxes
510-
for pixel_axis in pixel_axes:
511-
len_axis = self.data.shape[::-1][pixel_axis]
512-
# Define limits of desired pixel range based on whether corners or centers are desired
513-
lims = (-0.5, len_axis + 1) if pixel_corners else (0, len_axis)
514-
pix_ind = np.arange(lims[0], lims[1])
515-
shape = [1] * naxes
516-
shape[pixel_axis] = len(pix_ind)
517-
pixel_indices[pixel_axis] = pix_ind.reshape(shape)
518-
world_coords = wcs.pixel_to_world_values(*pixel_indices)
519-
# TODO: Remove NaNs??? These should not be here
520-
if np.isnan(world_coords).any():
521-
if isinstance(world_coords, tuple| list):
522-
world_coords = [world_coord[~np.isnan(world_coord)] for world_coord in world_coords]
523-
else:
524-
world_coords = world_coords[~np.isnan(world_coords)]
507+
needed_axes = np.array(needed_axes).squeeze()
508+
if self.data.ndim in needed_axes:
509+
required_axes = needed_axes - 1
510+
else:
511+
required_axes = needed_axes
512+
lims = (-0.5, self.data.shape[::-1][required_axes] + 1) if pixel_corners else (0, self.data.shape[::-1][required_axes])
513+
indices = [np.arange(lims[0], lims[1]) if wanted else [0] for wanted in wcs.axis_correlation_matrix[required_axes]]
514+
world_coords = wcs.pixel_to_world_values(*indices)
525515
if units:
526-
mod = abs(wcs.world_n_dim - naxes) if wcs.world_n_dim > naxes else 0
527-
world_coords = world_coords << u.Unit(wcs.world_axis_units[np.squeeze(pixel_axes)+mod])
516+
world_coords = world_coords << u.Unit(wcs.world_axis_units[needed_axes])
528517
return world_coords
529518

530-
def _generate_dependent_world_coords(self, pixel_corners, wcs, pixel_axes, units):
519+
def _generate_dependent_world_coords(self, pixel_corners, wcs, needed_axes, units):
531520
"""
532521
Generate world coordinates for dependent axes.
533522
@@ -540,8 +529,8 @@ def _generate_dependent_world_coords(self, pixel_corners, wcs, pixel_axes, units
540529
If one needs pixel corners, otherwise pixel centers.
541530
wcs : astropy.wcs.WCS
542531
The WCS.
543-
pixel_axes : array-like
544-
The pixel axes.
532+
needed_axes : array-like
533+
The required pixel axes.
545534
units : bool
546535
If units are needed.
547536
@@ -556,13 +545,19 @@ def _generate_dependent_world_coords(self, pixel_corners, wcs, pixel_axes, units
556545
ranges = [np.arange(i) - 0.5 for i in pixel_shape]
557546
else:
558547
ranges = [np.arange(i) for i in pixel_shape]
548+
# Limit the pixel dimensions to the ones present in the ExtraCoords
549+
if isinstance(wcs, ExtraCoords):
550+
ranges = [ranges[i] for i in wcs.mapping]
551+
wcs = wcs.wcs
552+
if wcs is None:
553+
return []
559554
# This value of zero will be returned as a throwaway for unneeded axes, and a numerical value is
560555
# required so values_to_high_level_objects in the calling function doesn't crash or warn
561556
world_coords = [0] * wcs.world_n_dim
562557
for (pixel_axes_indices, world_axes_indices) in _split_matrix(wcs.axis_correlation_matrix):
563-
if (pixel_axes is not None
564-
and len(pixel_axes)
565-
and not any(world_axis in pixel_axes for world_axis in world_axes_indices)):
558+
if (needed_axes is not None
559+
and len(needed_axes)
560+
and not any(world_axis in needed_axes for world_axis in world_axes_indices)):
566561
# needed_axes indicates which values in world_coords will be used by the calling
567562
# function, so skip this iteration if we won't be producing any of those values
568563
continue
@@ -592,7 +587,6 @@ def _generate_dependent_world_coords(self, pixel_corners, wcs, pixel_axes, units
592587
world_coords[i] = coord << u.Unit(unit)
593588
return world_coords
594589

595-
596590
def _generate_world_coords(self, pixel_corners, wcs, *, needed_axes=None, units=None):
597591
"""
598592
Private method to generate world coordinates.
@@ -615,32 +609,21 @@ def _generate_world_coords(self, pixel_corners, wcs, *, needed_axes=None, units=
615609
array-like
616610
The world coordinates.
617611
"""
618-
# TODO: Workout why I need this twice now.
619612
if isinstance(wcs, ExtraCoords):
620613
wcs = wcs.wcs
621-
if not wcs:
622-
return ()
623-
if needed_axes is None or len(needed_axes) == 0:
624-
needed_axes = np.array(list(range(wcs.world_n_dim)),dtype=int)
625614
axes_are_independent = []
626615
pixel_axes = set()
627616
for world_axis in needed_axes:
628617
pix_ax = world_axis_to_pixel_axes(world_axis, wcs.axis_correlation_matrix)
629618
axes_are_independent.append(len(pix_ax) == 1)
630619
pixel_axes = pixel_axes.union(set(pix_ax))
631-
if len(pixel_axes) == 1:
632-
pixel_axes = list(pixel_axes)
633-
if all(axes_are_independent) and len(pixel_axes) == len(needed_axes):
634-
world_coords = self._generate_independent_world_coords(pixel_corners, wcs, pixel_axes, units)
635-
else:
636-
world_coords = self._generate_dependent_world_coords(pixel_corners, wcs, pixel_axes, units)
637-
if len(world_coords) > 1 and isinstance(world_coords, tuple | list):
638-
world_coords = [np.squeeze(world_coord) for world_coord in world_coords]
620+
pixel_axes = list(pixel_axes)
621+
if all(axes_are_independent) and len(pixel_axes) == len(needed_axes) and len(needed_axes) != 0:
622+
world_coords = self._generate_independent_world_coords(pixel_corners, wcs, needed_axes, units)
639623
else:
640-
world_coords = np.squeeze(world_coords)
624+
world_coords = self._generate_dependent_world_coords(pixel_corners, wcs, needed_axes, units)
641625
return world_coords
642626

643-
644627
@utils.cube.sanitize_wcs
645628
def axis_world_coords(self, *axes, pixel_corners=False, wcs=None):
646629
# Docstring in NDCubeABC.
@@ -664,8 +647,6 @@ def axis_world_coords(self, *axes, pixel_corners=False, wcs=None):
664647
[world_index_to_object_index[world_index] for world_index in world_indices]
665648
)
666649
axes_coords = self._generate_world_coords(pixel_corners, orig_wcs, needed_axes=world_indices, units=False)
667-
if not isinstance(axes_coords, list):
668-
axes_coords = [axes_coords]
669650
axes_coords = values_to_high_level_objects(*axes_coords, low_level_wcs=wcs)
670651
if not axes:
671652
return tuple(axes_coords)
@@ -698,8 +679,7 @@ def axis_world_coords_values(self, *axes, pixel_corners=False, wcs=None):
698679
identifier = identifier.replace("-", "__")
699680
identifiers.append(identifier)
700681
CoordValues = namedtuple("CoordValues", identifiers)
701-
flag = len(axes_coords) == 1 or isinstance(axes_coords, tuple | list)
702-
return CoordValues(*axes_coords[::-1]) if flag else CoordValues(axes_coords)
682+
return CoordValues(*axes_coords[::-1])
703683

704684
def crop(self, *points, wcs=None, keepdims=False):
705685
# The docstring is defined in NDCubeABC

ndcube/tests/test_ndcube.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,19 @@ def test_axis_world_coords_wave_ec(ndcube_3d_l_ln_lt_ectime):
178178

179179
coords = cube.axis_world_coords()
180180
assert len(coords) == 2
181+
assert isinstance(coords[0], SkyCoord)
182+
assert coords[0].shape == (5, 8)
183+
assert isinstance(coords[1], SpectralCoord)
184+
assert coords[1].shape == (10,)
181185

182186
coords = cube.axis_world_coords(wcs=cube.combined_wcs)
183187
assert len(coords) == 3
188+
assert isinstance(coords[0], SkyCoord)
189+
assert coords[0].shape == (5, 8)
190+
assert isinstance(coords[1], SpectralCoord)
191+
assert coords[1].shape == (10,)
192+
assert isinstance(coords[2], Time)
193+
assert coords[2].shape == (5,)
184194

185195
coords = cube.axis_world_coords(wcs=cube.extra_coords)
186196
assert len(coords) == 1
@@ -200,8 +210,6 @@ def test_axis_world_coords_empty_ec(ndcube_3d_l_ln_lt_ectime):
200210
# slice the cube so extra_coords is empty, and then try and run axis_world_coords
201211
awc = sub_cube.axis_world_coords(wcs=sub_cube.extra_coords)
202212
assert awc == ()
203-
sub_cube._generate_world_coords(pixel_corners=False, wcs=sub_cube.extra_coords, units=True)
204-
assert awc == ()
205213

206214

207215
@pytest.mark.xfail(reason=">1D Tables not supported")

0 commit comments

Comments
 (0)