-
-
Notifications
You must be signed in to change notification settings - Fork 49
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
Faster shortcut for working out coordinates values for non-correlated WCS #780
base: main
Are you sure you want to change the base?
Changes from all commits
ea5b801
9ef334a
d2edf70
774eb02
ed25cac
70ad715
941216f
9d2bb0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Added an internal method to shortcut non-correlated axes avoiding the creation of a full coordinate grid, reducing memory use in specific circumstances. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -444,8 +444,25 @@ | |
return u.Quantity(self.data, self.unit, copy=_NUMPY_COPY_IF_NEEDED) | ||
|
||
def _generate_world_coords(self, pixel_corners, wcs, needed_axes=None, *, units): | ||
# Create meshgrid of all pixel coordinates. | ||
# If user wants pixel_corners, set pixel values to pixel corners. | ||
# This will generate only the coordinates that are needed if there is no correlation within the WCS | ||
# This bypasses the entire rest of the function below which works out the full set of coordinates | ||
# This only works for WCS that have the same number of world and pixel dimensions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This probably shouldn't be a limitation but right now I can't work out a good idea. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate on what the difficulty is here? This is probably related to the comment below There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too stupid to work out the line of code to overcome this limitation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. Put another way, why does enforcing this limitation make the problem simpler? If you just remove this condition, so long as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the one case in the test suite, no this is not enough.
There is no direct translation between the needed world coordinate and the corresponding pixel coordinate in this block. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this util function solve that problem? |
||
if needed_axes is not None and not isinstance(wcs, ExtraCoords) and np.sum(wcs.axis_correlation_matrix[needed_axes]) == 1: | ||
# Account for non-pixel axes affecting the value of needed_axes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you better explain this comment. Are you trying to convert world axes to pixel axes here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the passed in needed_axes is given in world indices but the loop below works on the data shape, so I made a random guess at modifying the needed axes to give a variable which does not error. It isn't correct |
||
# Only works for one axis | ||
if np.max(wcs.axis_correlation_matrix[needed_axes][0].shape) == needed_axes[0]: | ||
needed_axis = needed_axes[0] - 1 | ||
else: | ||
needed_axis = needed_axes[0] | ||
lims = (-0.5, self.data.shape[::-1][needed_axis] + 1) if pixel_corners else (0, self.data.shape[::-1][needed_axis]) | ||
indices = [np.arange(lims[0], lims[1]) if wanted else [0] for wanted in wcs.axis_correlation_matrix[needed_axis]] | ||
world_coords = wcs.pixel_to_world_values(*indices) | ||
if units: | ||
world_coords = world_coords << u.Unit(wcs.world_axis_units[needed_axis]) | ||
return world_coords | ||
|
||
# Create a meshgrid of all pixel coordinates. | ||
# If the user wants pixel corners, set pixel values to pixel corners. | ||
# Else make pixel centers. | ||
pixel_shape = self.data.shape[::-1] | ||
if pixel_corners: | ||
|
@@ -544,6 +561,8 @@ | |
orig_wcs = wcs | ||
if isinstance(wcs, ExtraCoords): | ||
wcs = wcs.wcs | ||
if not wcs: | ||
return () | ||
Comment on lines
+564
to
+565
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was missing and is included in the other version of this method, so I added it. |
||
|
||
world_indices = utils.wcs.calculate_world_indices_from_axes(wcs, axes) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -235,13 +235,32 @@ | |
assert u.allclose(coords[0], [1.02e-09, 1.04e-09, 1.06e-09, 1.08e-09] * u.m) | ||
|
||
|
||
def test_axis_world_coords_combined_wcs(ndcube_3d_wave_lt_ln_ec_time): | ||
# This replicates a specific NDCube test in the visualization.rst | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So my understanding of this and I don't know if this is correct. This NDCube has a 3D WCS, which is Wavelength, Space, Space and has time as an extra coord. We pass to
Time here while in the WCS is not a pixel dimension. So I think that
gives me the time axis but its number 3 in the list. So I need a way to get the correct axis and work out how many coords there are so I can get it from pixel to world. But I don't see that information in the WCS. This feels like it shouldn't hit this code path at all. |
||
coords = ndcube_3d_wave_lt_ln_ec_time.axis_world_coords('time', wcs=ndcube_3d_wave_lt_ln_ec_time.combined_wcs) | ||
assert len(coords) == 1 | ||
assert isinstance(coords[0], Time) | ||
assert np.all(coords[0] == Time(['2000-01-01T00:00:00.000', '2000-01-01T00:01:00.000', '2000-01-01T00:02:00.000'])) | ||
|
||
# This fails and returns the wrong coords | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This operation returns very very wrong values. I failed to work out why. |
||
coords = ndcube_3d_wave_lt_ln_ec_time.axis_world_coords_values('time', wcs=ndcube_3d_wave_lt_ln_ec_time.combined_wcs) | ||
assert len(coords) == 1 | ||
assert isinstance(coords.time, Time) | ||
assert np.all(coords.time == Time(['2000-01-01T00:00:00.000', '2000-01-01T00:01:00.000', '2000-01-01T00:02:00.000'])) | ||
|
||
|
||
@pytest.mark.parametrize("axes", [[-1], [2], ["em"]]) | ||
def test_axis_world_coords_single_pixel_corners(axes, ndcube_3d_ln_lt_l): | ||
|
||
# We go from 4 pixels to 6 pixels when we add pixel corners | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this correct at all. Going to lean towards no. |
||
coords = ndcube_3d_ln_lt_l.axis_world_coords_values(*axes, pixel_corners=False) | ||
assert u.allclose(coords[0], [1.02e-09, 1.04e-09, 1.06e-09, 1.08e-09] * u.m) | ||
|
||
coords = ndcube_3d_ln_lt_l.axis_world_coords_values(*axes, pixel_corners=True) | ||
assert u.allclose(coords, [1.01e-09, 1.03e-09, 1.05e-09, 1.07e-09, 1.09e-09] * u.m) | ||
assert u.allclose(coords[0], [1.01e-09, 1.03e-09, 1.05e-09, 1.07e-09, 1.09e-09, 1.11e-09] * u.m) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This grew another dim but I do not know why. |
||
|
||
coords = ndcube_3d_ln_lt_l.axis_world_coords(*axes, pixel_corners=True) | ||
assert u.allclose(coords, [1.01e-09, 1.03e-09, 1.05e-09, 1.07e-09, 1.09e-09] * u.m) | ||
assert u.allclose(coords[0], [1.01e-09, 1.03e-09, 1.05e-09, 1.07e-09, 1.09e-09, 1.11e-09] * u.m) | ||
|
||
|
||
@pytest.mark.parametrize(("ndc", "item"), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: Better changelog.