|
5 | 5 | import numpy as np |
6 | 6 |
|
7 | 7 | import astropy.nddata |
| 8 | +import astropy.units as u |
8 | 9 | from astropy.wcs.wcsapi import BaseHighLevelWCS, BaseLowLevelWCS, HighLevelWCSWrapper, SlicedLowLevelWCS |
| 10 | +from astropy.wcs.wcsapi.high_level_api import high_level_objects_to_values |
9 | 11 |
|
10 | 12 | from ndcube.utils import wcs as wcs_utils |
11 | 13 | from ndcube.utils.exceptions import warn_user |
@@ -107,6 +109,33 @@ def sanitize_crop_inputs(points, wcs): |
107 | 109 | return False, points, wcs |
108 | 110 |
|
109 | 111 |
|
| 112 | +def _high_level_objects_to_pixel_values(low_level_wcs, *world_objects): |
| 113 | + """ |
| 114 | + Convert high-level world objects to pixel values. |
| 115 | +
|
| 116 | + Astropy's high-level WCS path can hand low-level WCSes celestial values in |
| 117 | + degrees even when the low-level WCS advertises angular world units such as |
| 118 | + arcsec. Normalize any string-based component units to the WCS world-axis |
| 119 | + units before calling the low-level inverse transform. |
| 120 | + """ |
| 121 | + world_values = list(high_level_objects_to_values(*world_objects, low_level_wcs=low_level_wcs)) |
| 122 | + for i, (_, _, attr) in enumerate(low_level_wcs.world_axis_object_components): |
| 123 | + if not isinstance(attr, str): |
| 124 | + continue |
| 125 | + source_unit_name = attr.rsplit(".", 1)[-1] |
| 126 | + target_unit_name = low_level_wcs.world_axis_units[i] |
| 127 | + if not target_unit_name: |
| 128 | + continue |
| 129 | + try: |
| 130 | + source_unit = u.Unit(source_unit_name) |
| 131 | + target_unit = u.Unit(target_unit_name) |
| 132 | + except Exception: # NOQA: BLE001 |
| 133 | + continue |
| 134 | + if source_unit != target_unit and source_unit.is_equivalent(target_unit): |
| 135 | + world_values[i] = (world_values[i] * source_unit).to_value(target_unit) |
| 136 | + return low_level_wcs.world_to_pixel_values(*world_values) |
| 137 | + |
| 138 | + |
110 | 139 | def get_crop_item_from_points(points, wcs, crop_by_values, keepdims, original_shape): |
111 | 140 | """ |
112 | 141 | Find slice item that crops to minimum cube in array-space containing specified world points. |
@@ -182,7 +211,7 @@ def get_crop_item_from_points(points, wcs, crop_by_values, keepdims, original_sh |
182 | 211 | # in the list corresponding to its axis. |
183 | 212 | # Use the to_pixel methods to preserve fractional indices for future rounding. |
184 | 213 | point_pixel_indices = (sliced_wcs.world_to_pixel_values(*sliced_point) if crop_by_values |
185 | | - else HighLevelWCSWrapper(sliced_wcs).world_to_pixel(*sliced_point)) |
| 214 | + else _high_level_objects_to_pixel_values(sliced_wcs, *sliced_point)) |
186 | 215 | # For each pixel axis associated with this point, place the pixel coords for |
187 | 216 | # that pixel axis into the corresponding list within combined_points_pixel_idx. |
188 | 217 | if sliced_wcs.pixel_n_dim == 1: |
|
0 commit comments