@@ -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
0 commit comments