Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/887.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add new method, `ndcube.NDCube.to_nddata`, which allows easy conversion of an `~ndcube.NDCube` to a subclass of `~astropy.nddata.NDData`. Users have the option of changing attribute values when doing so by designated the new values via kwargs.
60 changes: 60 additions & 0 deletions ndcube/ndcube.py
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,66 @@ def fill_masked(self, fill_value, uncertainty_fill_value=None, unmask=False, fil
self.mask = False
return None

def to_nddata(self, *, nddata_type=NDData, **kwargs):
"""
Constructs new type instance with the same attribute values as this `~ndcube.NDCube`.

Any attributes not supported by the new class (``nddata_type``), will be discarded.
Values of supported attributes can be altered on the output object by setting a
kwarg with the new value, e.g. ``data=new_data``.

Parameters
----------
nddata_type:
The type of the returned object. Must be a subclass of `~astropy.nddata.NDData`
or a class that behaves like one. Default=`~astropy.nddata.NDData`.

kwargs:
Inputs to the ``nddata_type`` constructor that should differ from the values
stored in attributes of this instance. For example, to set different data values
on the returned object, set a kwarg ``data=new_data``, where ``new_data`` is an
an array of compatible shape and dtype. Note that kwargs given by the user and
attributes on this instance that are not supported by the ``nddata_type``
constructor are ignored.

Returns
-------
new_nddata: object
An object of class given by ``nddata_type`` with the same attribute values as
this `~ndcube.NDCube` instance, except for any alterations specified by the
kwargs.

Examples
--------
To create an `~astropy.nddata.NDData` instance which is a copy of an `~ndcube.NDCube`
(called ``cube``) without a WCS, do:

>>> nddata_without_coords = cube.to_nddata(wcs=None) # doctest: +SKIP
"""
# Build dictionary of new attribute values from this NDCube instance
# and update with user-defined kwargs.
new_kwargs = {key.strip("_"): value for key, value in self.__dict__.items()}
new_kwargs.update(kwargs)
extra_coords, global_coords = None, None
if nddata_type is NDCube:
extra_coords = new_kwargs.pop("extra_coords")
global_coords = new_kwargs.pop("global_coords")
# Inspect call signature of new_nddata class and
# remove unsupported items from new_kwargs.
nddata_sig = inspect.signature(nddata_type).parameters.keys()
new_kwarg_keys = list(new_kwargs.keys())
for key in new_kwarg_keys:
if key not in nddata_sig:
del new_kwargs[key]
# Construct and return new instance.
new_nddata = nddata_type(**new_kwargs)
if extra_coords:
extra_coords._ndcube = new_nddata
new_nddata._extra_coords = extra_coords
if global_coords:
new_nddata._global_coords = global_coords
return new_nddata


def _create_masked_array_for_rebinning(data, mask, operation_ignores_mask):
m = None if (mask is None or mask is False or operation_ignores_mask) else mask
Expand Down
7 changes: 7 additions & 0 deletions ndcube/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
'assert_cubes_equal',
'assert_cubesequences_equal',
'assert_extra_coords_equal',
'assert_global_coords_equal',
'assert_metas_equal',
'assert_wcs_are_equal',
'figure_test',
Expand Down Expand Up @@ -93,6 +94,12 @@ def assert_extra_coords_equal(test_input, extra_coords):
assert_wcs_are_equal(test_input._wcs, extra_coords._wcs)



def assert_global_coords_equal(test_input, global_coords):
assert test_input.items() == global_coords.items()
assert test_input.physical_types == global_coords.physical_types


def assert_metas_equal(test_input, expected_output):
if type(test_input) is not type(expected_output):
raise AssertionError(
Expand Down
21 changes: 21 additions & 0 deletions ndcube/tests/test_ndcube.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import numpy as np
import pytest

import astropy.nddata
import astropy.units as u
import astropy.wcs
from astropy.wcs.wcsapi import BaseHighLevelWCS
Expand Down Expand Up @@ -238,3 +239,23 @@ def test_fill_masked_ndc_uncertainty_none(ndc, fill_value, uncertainty_fill_valu
uncertainty_fill_value=uncertainty_fill_value,
fill_in_place=True
)


def test_to_nddata(ndcube_2d_ln_lt):
ndc = ndcube_2d_ln_lt
new_data = ndc.data * 2
output = ndc.to_nddata(data=new_data, wcs=None)
assert type(output) is astropy.nddata.NDData
assert output.wcs is None
assert (output.data == new_data).all()


def test_to_nddata_type_ndcube(ndcube_2d_ln_lt_uncert_ec):
ndc = ndcube_2d_ln_lt_uncert_ec
ndc.global_coords.add("wavelength", "em.wl", 100*u.nm)
new_data = ndc.data * 2
output = ndc.to_nddata(data=new_data, nddata_type=NDCube)
assert type(output) is NDCube
assert (output.data == new_data).all()
helpers.assert_extra_coords_equal(output.extra_coords, ndc.extra_coords)
helpers.assert_global_coords_equal(output.global_coords, ndc.global_coords)