Skip to content

Added new features to the ndcube.__add__ method #794

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

Open
wants to merge 110 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
9c38077
Added new features to the ndcube._add_ method
PCJY Dec 11, 2024
1d5d2ab
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Dec 16, 2024
aaa9ef0
Update ndcube/ndcube.py
PCJY Dec 16, 2024
ed4f61e
Update ndcube/ndcube.py
PCJY Dec 16, 2024
ea43a1d
Modified the _add_ method further.
PCJY Dec 18, 2024
a891ff9
Merge branch 'nddataArithmetic' of https://github.com/PCJY/ndcube int…
PCJY Dec 18, 2024
f575e2c
Further modifies the _add_ method.
PCJY Dec 23, 2024
8951635
Added a changelog file for this new feature.
PCJY Dec 23, 2024
58e4363
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Dec 23, 2024
bcf4fb9
Added a new method test_cube_add_uncertainty_and_mask to test_ndcube.py.
PCJY Dec 23, 2024
c4d639a
Modified the test_cube_add_uncertainty_and_mask method in test_ndcube.py
PCJY Dec 23, 2024
bd317e3
Modified the test_cube_add_uncertainty_and_mask further.
PCJY Dec 23, 2024
e0375ec
Fixed how the masks are combined.
PCJY Jan 14, 2025
0158737
Set masked uncertainty entries to 0.
PCJY Jan 18, 2025
9074f45
Moved uncertainty combination out of the mask-combining If Statements.
PCJY Jan 21, 2025
9e267d3
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Jan 21, 2025
d8c2db9
Merge branch 'main' into nddataArithmetic
PCJY Jan 21, 2025
5f422f5
Removed mask-dealing in the add method.
PCJY Jan 22, 2025
3369223
Merge branch 'nddataArithmetic' of https://github.com/PCJY/ndcube int…
PCJY Jan 22, 2025
f17da78
Removed mask-dealing in the Add method.
PCJY Jan 22, 2025
344b6f7
use a conditional statement to still check whether there is a mask.
PCJY Jan 22, 2025
7ff78aa
Changed mask to False and removed mask-checking in test_cube_add_unce…
PCJY Jan 22, 2025
5852daa
Added placeholders for using the new parameters and modified the no-m…
PCJY Jan 22, 2025
5dcb8ff
Set default of operation_ignores_mask to be True.
PCJY Jan 22, 2025
b385643
Make NDCube.__add__ call the NDCube.add method.
PCJY Jan 28, 2025
9941993
tidied up the __add__ method, copied the original test_cube_arithmeti…
PCJY Jan 29, 2025
4568ae2
Only check whether value has unit if it is not an NDData
PCJY Feb 3, 2025
b1cf478
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Feb 3, 2025
bb2c541
Update ndcube/ndcube.py
PCJY Feb 4, 2025
3f6ebed
Update ndcube/ndcube.py
PCJY Feb 4, 2025
3b76d54
Update ndcube/tests/test_ndcube.py
PCJY Feb 4, 2025
e7701b2
Merge branch 'nddataArithmetic' of https://github.com/PCJY/ndcube int…
PCJY Feb 4, 2025
64cc02e
Fix uncertainty propagation and ensure expected_uncertainty is numpy …
PCJY Feb 4, 2025
48b313e
Apply suggestions from code review
PCJY Feb 11, 2025
50d64c1
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Feb 11, 2025
23fef8a
check value and unit of addition
PCJY Feb 11, 2025
ed9d5f1
Update ndcube/ndcube.py
PCJY Feb 11, 2025
02f86b3
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Feb 17, 2025
7ea75f3
change values for uncertainty in a fixture to fixed values.
PCJY Feb 17, 2025
f31768d
Merge branch 'nddataArithmetic' of https://github.com/PCJY/ndcube int…
PCJY Feb 17, 2025
efafb89
Merge branch 'main' into nddataArithmetic
PCJY Feb 17, 2025
a32e474
Merge branch 'nddataArithmetic' of https://github.com/PCJY/ndcube int…
PCJY Feb 17, 2025
83d99cf
added unit in ndcube for kwargs['data'], changed values for uncertainty.
PCJY Feb 18, 2025
3b5a0ce
new test method for units of both objects being None.
PCJY Feb 18, 2025
9fbb9e3
Merge branch 'main' of https://github.com/sunpy/ndcube into nddataAri…
PCJY Feb 20, 2025
1f0ffc6
within a new ndcube-dev env, removed any unit involved for now.
PCJY Feb 20, 2025
fd78f6f
Added new test case for only one of them having a unit.
PCJY Feb 20, 2025
b284e1f
Test case for both objects having the same unit, and causes TypeError.
PCJY Feb 21, 2025
379faac
Fix test for adding nddata and ndcube uncertainties.
DanRyanIrish Feb 24, 2025
c6070c0
Added more test functions for full coverage.
PCJY Feb 24, 2025
d88838d
Fix pytest indirect issue: Added cube(request) fixture to correctly r…
PCJY Feb 26, 2025
f097110
Fix indirect fixture reference.
DanRyanIrish Feb 26, 2025
c920a10
Merge branch 'DanRyanIrish-nddataArithmetic' into nddataArithmetic
PCJY Feb 26, 2025
5565408
Written all tests and fixed an error in ndcube with test results.
PCJY Feb 27, 2025
51d26c1
Fixed a small error in a test function.
PCJY Feb 27, 2025
46cef9d
changed assert_cubes_equal, fixed self-referring of tests.
PCJY Feb 28, 2025
1eb0357
Update ndcube/tests/helpers.py
PCJY Mar 3, 2025
553b1d7
Changed the naming of test functions.
PCJY Mar 3, 2025
8f9baa4
Merge branch 'nddataArithmetic' of https://github.com/PCJY/ndcube int…
PCJY Mar 3, 2025
fdecacd
Changed the way to check whether both objects' uncertainty are None.
PCJY Mar 3, 2025
3ab2ead
Three conditional scenarios.
PCJY Mar 3, 2025
fdee146
Rewrote the uncertainty results checking.
PCJY Mar 4, 2025
d755849
Rewrote the uncertainty checking again.
PCJY Mar 4, 2025
5b9626f
Implementing mask.
PCJY Mar 11, 2025
3f1b8ef
Implementing mask.
PCJY Mar 11, 2025
22a673b
Added Fill() Method's skeleton.
PCJY Mar 14, 2025
8bb8e9f
New PR, copied ndcube.py from the other branch nddataArithmetic.
PCJY Mar 14, 2025
4e5dcd0
Changed the code to be consistent with main/ndcube.py instead.
PCJY Mar 14, 2025
4ffb573
Implementing NDCube.fill().
PCJY Mar 14, 2025
fb36c80
Added changelog, implementing NDCube.fill().
PCJY Mar 14, 2025
e1919fa
Added changelog again
PCJY Mar 14, 2025
b06a1cc
If fill_in_place is False, then return kwargs.
PCJY Mar 14, 2025
73cb945
Update changelog/829.feature.rst
PCJY Mar 16, 2025
1715862
Update ndcube/ndcube.py
PCJY Mar 16, 2025
20945f2
Update ndcube/ndcube.py
PCJY Mar 16, 2025
157f4b3
Update ndcube/ndcube.py
PCJY Mar 16, 2025
41d3b24
Update ndcube/ndcube.py
PCJY Mar 16, 2025
1afe30a
Update ndcube/ndcube.py
PCJY Mar 16, 2025
f280941
Update ndcube/ndcube.py
PCJY Mar 16, 2025
fb00430
Update ndcube/ndcube.py
PCJY Mar 17, 2025
eb3d0e8
Update ndcube/ndcube.py
PCJY Mar 17, 2025
bad2a26
Implementing the fill_masked method.
PCJY Mar 17, 2025
0cd0e60
Merge branch 'main' of https://github.com/sunpy/ndcube into NDCubefill
PCJY Mar 17, 2025
468fcb2
About units.
PCJY Mar 17, 2025
a35feeb
Further implementing, preparing for testing.
PCJY Mar 18, 2025
0cbfbd7
Added test for the fill_masked method.
PCJY Mar 18, 2025
0d4055f
Fixed error about docstring.
PCJY Mar 18, 2025
be4639a
Changed the docstring again.
PCJY Mar 18, 2025
74c648e
Update ndcube/ndcube.py
PCJY Mar 18, 2025
b7e99bd
Update ndcube/conftest.py
PCJY Mar 18, 2025
d422668
Update ndcube/ndcube.py
PCJY Mar 18, 2025
cc65f5d
Update ndcube/tests/helpers.py
PCJY Mar 18, 2025
75bf81a
deal with unmasking after using self.mask
PCJY Mar 24, 2025
be1db6e
Notes from Meeting.
PCJY Mar 23, 2025
68def22
Modified NDCube.fill_masked method and its tests.
PCJY Mar 24, 2025
26811c8
Debugging
PCJY Mar 24, 2025
db285ba
Update ndcube/ndcube.py
PCJY Mar 24, 2025
8b6d9bc
Small changes from previous meeting.
PCJY Apr 3, 2025
1f59a44
Changed test arguments.
PCJY Apr 8, 2025
c26563a
Fixing bugs in tests.
PCJY Apr 9, 2025
c8a86a5
Fixed coverage issue by adding more test cases.
PCJY Apr 9, 2025
e60eb24
Exclude defensive assertions from coverage test.
PCJY Apr 9, 2025
b7b9f9f
Merge branch 'main' of https://github.com/sunpy/ndcube into NDCubefill
PCJY Apr 9, 2025
4983a54
Update ndcube/tests/helpers.py
PCJY Apr 11, 2025
d40e887
Changed code for Single-Bool-True-Mask case.
PCJY Apr 11, 2025
bce2bb3
Merge branch 'NDCubefill' into nddataArithmetic
PCJY Apr 14, 2025
8070808
Change fixture.
PCJY Apr 14, 2025
9c7aa14
Change fixture.
PCJY Apr 14, 2025
9753808
Merge branch 'NDCubefill' into nddataArithmetic
PCJY Apr 14, 2025
6ac02e3
Removed the operation_ignore_mask argument and all the logics using it.
PCJY Apr 21, 2025
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/794.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allows addition of an ``NDCube`` and ``NDData`` (with the WCS of ``NDData`` being set to None), and combines their uncertainties and masks.
2 changes: 2 additions & 0 deletions changelog/829.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Added ``fill_masked`` method to ``NDCube``, a new feature which allows users to replace masked values and uncertainty values with user-given fill values,
to change the mask values back to False or not (Default), and to set whether the new instance is returned (Default) or not.
117 changes: 117 additions & 0 deletions ndcube/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,79 @@ def ndcube_2d_ln_lt_mask_uncert(wcs_2d_lt_ln):
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_mask_false(wcs_2d_lt_ln):
shape = (2, 3)
unit = u.ct
data_cube = data_nd(shape)
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = False
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_one_maskele_true(wcs_2d_lt_ln):
shape = (2, 3)
unit = u.ct
data_cube = data_nd(shape)
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = np.zeros(shape, dtype=bool)
mask[0:1, 0] = True
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_one_maskele_true_expected_unmask_false(wcs_2d_lt_ln):
shape = (2, 3)
unit = u.ct
data_cube = np.array([[1.0, 1.0, 2.0],
[3.0, 4.0, 5.0]])
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = np.zeros(shape, dtype=bool)
mask[0:1, 0] = True
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_one_maskele_true_expected_unmask_true(wcs_2d_lt_ln):
unit = u.ct
data_cube = np.array([[1.0, 1.0, 2.0],
[3.0, 4.0, 5.0]])
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = False
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_mask_true(wcs_2d_lt_ln):
shape = (2, 3)
unit = u.ct
data_cube = data_nd(shape)
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = True
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_mask_true_expected_unmask_true(wcs_2d_lt_ln):
unit = u.ct
data_cube = np.array([[1.0, 1.0, 1.0],
[1.0, 1.0, 1.0]])
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = False
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_mask_uncert_unit_mask_true_expected_unmask_false(wcs_2d_lt_ln):
unit = u.ct
data_cube = np.array([[1.0, 1.0, 1.0],
[1.0, 1.0, 1.0]])
uncertainty = astropy.nddata.StdDevUncertainty(data_cube * 0.1)
mask = True
return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, mask=mask, unit=unit)


@pytest.fixture
def ndcube_2d_ln_lt_uncert_ec(wcs_2d_lt_ln):
shape = (4, 9)
Expand All @@ -678,6 +751,39 @@ def ndcube_2d_ln_lt_units(wcs_2d_lt_ln):
return NDCube(data_cube, wcs=wcs_2d_lt_ln, unit=u.ct)


@pytest.fixture
def ndcube_2d_ln_lt_no_unit_no_unc(wcs_2d_lt_ln):
shape = (10, 12)
data_cube = data_nd(shape).astype(float)
return NDCube(data_cube, wcs=wcs_2d_lt_ln)


@pytest.fixture
def ndcube_2d_unit_unc(wcs_2d_lt_ln):
shape = (10, 12)
data_cube = data_nd(shape).astype(float)
uncertainty = StdDevUncertainty(np.ones(shape)*0.2, unit=u.ct)

return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty, unit=u.ct)


@pytest.fixture
def ndcube_2d_uncertainty_no_unit(wcs_2d_lt_ln):
shape = (10, 12)
data_cube = data_nd(shape).astype(float)
uncertainty = StdDevUncertainty(np.ones(shape)*0.2)

return NDCube(data_cube, wcs=wcs_2d_lt_ln, uncertainty=uncertainty)


@pytest.fixture
def ndcube_2d_ln_lt_mask(wcs_2d_lt_ln):
shape = (10, 12)
data_cube = data_nd(shape).astype(float)
mask = np.ones(data_cube.shape, dtype=bool)
return NDCube(data_cube, wcs=wcs_2d_lt_ln, mask=mask)


@pytest.fixture
def ndcube_2d_dask(wcs_2d_lt_ln):
shape = (8, 4)
Expand Down Expand Up @@ -719,6 +825,9 @@ def ndcube_1d_l(wcs_1d_l):
"ndcube_2d_ln_lt_units",
"ndcube_2d_dask",
"ndcube_1d_l",
"ndcube_2d_ln_lt_no_unit_no_unc",
"ndcube_2d_uncertainty_no_unit",
"ndcube_2d_unit_unc",
])
def all_ndcubes(request):
"""
Expand All @@ -735,6 +844,14 @@ def ndc(request):
return request.getfixturevalue(request.param)


@pytest.fixture
def expected_cube(request):
"""
A fixture for use with indirect to lookup other fixtures.
"""
return request.getfixturevalue(request.param)


################################################################################
# NDCubeSequence Fixtures
################################################################################
Expand Down
132 changes: 127 additions & 5 deletions ndcube/ndcube.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import abc
import copy
import inspect
import numbers
import textwrap
Expand All @@ -11,6 +12,7 @@

import astropy.nddata
import astropy.units as u
from astropy.nddata import NDData
from astropy.units import UnitsError
from astropy.wcs.utils import _split_matrix

Expand Down Expand Up @@ -964,24 +966,81 @@
def __neg__(self):
return self._new_instance(data=-self.data)

def __add__(self, value):
if hasattr(value, 'unit'):
def add(self, value, handle_mask=np.logical_and):
"""
Users are allowed to choose whether they want handle_mask to be AND / OR .
"""
kwargs = {}

if isinstance(value, NDData) and value.wcs is None:
if self.unit is not None and value.unit is not None:
value_data = (value.data * value.unit).to_value(self.unit)
elif self.unit is None and value.unit is None:
value_data = value.data
else:
raise TypeError("Adding objects requires both have a unit or neither has a unit.") # change the test as well.

# check whether there is a mask.
# Neither self nor value has a mask
self_unmasked = self.mask is None or self.mask is False or not self.mask.any()
value_unmasked = value.mask is None or value.mask is False or not value.mask.any()

if (self_unmasked and value_unmasked):
# addition
kwargs["data"] = self.data + value_data

# combine the uncertainty;
if self.uncertainty is not None and value.uncertainty is not None:
result_data = kwargs["data"]
if self.unit is not None:
result_data *= self.unit
new_uncertainty = self.uncertainty.propagate(
np.add, value, result_data=result_data, correlation=0
)
kwargs["uncertainty"] = new_uncertainty
elif self.uncertainty is not None:
new_uncertainty = self.uncertainty
kwargs["uncertainty"] = new_uncertainty
elif value.uncertainty is not None:
new_uncertainty = value.uncertainty
kwargs["uncertainty"] = new_uncertainty
else:
new_uncertainty = None

elif hasattr(value, 'unit'):
if isinstance(value, u.Quantity):
# NOTE: if the cube does not have units, we cannot
# perform arithmetic between a unitful quantity.
# This forces a conversion to a dimensionless quantity
# so that an error is thrown if value is not dimensionless
cube_unit = u.Unit('') if self.unit is None else self.unit
new_data = self.data + value.to_value(cube_unit)
kwargs["data"] = self.data + value.to_value(cube_unit)
else:
# NOTE: This explicitly excludes other NDCube objects and NDData objects
# which could carry a different WCS than the NDCube
return NotImplemented
elif self.unit not in (None, u.Unit("")):
raise TypeError("Cannot add a unitless object to an NDCube with a unit.")
else:
new_data = self.data + value
return self._new_instance(data=new_data)
kwargs["data"] = self.data + value

Check warning on line 1025 in ndcube/ndcube.py

View check run for this annotation

Codecov / codecov/patch

ndcube/ndcube.py#L1025

Added line #L1025 was not covered by tests

# return the new NDCube instance
return self._new_instance(**kwargs)

def __add__(self, value):
# when value has a mask, raise error and point user to the add method. TODO
#
# check whether there is a mask.
# Neither self nor value has a mask

self_masked = not(self.mask is None or self.mask is False or not self.mask.any())
value_masked = not(value.mask is None or value.mask is False or not value.mask.any()) if hasattr(value, "mask") else False

if (value_masked or (self_masked and hasattr(value,'uncertainty') and value.uncertainty is not None)): # value has a mask,
# let the users call the add method
raise TypeError('Please use the add method.')

return self.add(value) # the mask keywords cannot be given by users.

def __radd__(self, value):
return self.__add__(value)
Expand Down Expand Up @@ -1330,6 +1389,69 @@
return self[tuple(item)]


def fill_masked(self, fill_value, uncertainty_fill_value=None, unmask=False, fill_in_place=False):
"""
Replaces masked data values with input value.

Returns a new instance or alters values in place.

Parameters
----------
fill_value: `numbers.Number` or scalar `astropy.units.Quantity`
The value to replace masked data with.
unmask: `bool`, optional
If True, the newly filled masked values are unmasked. If False, they remain masked
Default=False
uncertainty_fill_value: `numbers.Number` or scalar `astropy.units.Quantity`, optional
The value to replace masked uncertainties with.
fill_in_place: `bool`, optional
If `True`, the masked values are filled in place. If `False`, a new instance is returned
with masked values filled. Default=False.
"""
# variable creations for later use.
# If fill_in_place is true, do: assign data and uncertainty to variables.
if fill_in_place:
new_data = self.data
new_uncertainty = self.uncertainty
# Unmasking in-place should be handled later.

# If fill_in_place is false, do: create new storage place for data and uncertainty and mask.
# TODO: is the logic repetitive? this else is the same with the if not fill_in_place below? No because the order matters.
else:
new_data = copy.deepcopy(self.data)
new_uncertainty = copy.deepcopy(self.uncertainty)
new_mask = False if unmask else copy.deepcopy(self.mask) # self.mask still exists.

masked = (
False if self.mask is None or self.mask is False
else self.mask is True if isinstance(self.mask, bool)
else self.mask.any()
)
if masked:
idx_mask = slice(None) if self.mask is True else self.mask # Ensure indexing mask can index the data array.
if hasattr(fill_value, "unit"):
fill_value = fill_value.to_value(self.unit)
new_data[idx_mask] = fill_value # python will error based on whether data array can accept the passed value.

if uncertainty_fill_value is not None:
if not self.uncertainty: # or new_uncertainty
raise TypeError("Cannot fill uncertainty as uncertainty is None.")
if hasattr(uncertainty_fill_value, "unit"):
uncertainty_fill_value = uncertainty_fill_value.to_value(self.unit)
new_uncertainty.array[idx_mask] = uncertainty_fill_value

if not fill_in_place:
# Create kwargs dictionary and return a new instance.
kwargs = {}
kwargs['data'] = new_data
kwargs['uncertainty'] = new_uncertainty
kwargs['mask'] = new_mask
return self._new_instance(**kwargs)
if unmask:
self.mask = False
return None


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
if m is None:
Expand Down
22 changes: 19 additions & 3 deletions ndcube/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,31 @@
assert test_input[key] == expected_output[key]


def assert_cubes_equal(test_input, expected_cube, check_data=True):
def assert_cubes_equal(test_input, expected_cube, check_data=True, check_uncertainty_values=False):
assert isinstance(test_input, type(expected_cube))
assert np.all(test_input.mask == expected_cube.mask)
if isinstance(test_input.mask, bool) and isinstance(expected_cube.mask, bool):
assert test_input.mask == expected_cube.mask
else:
assert np.all(test_input.mask == expected_cube.mask)
if check_data:
np.testing.assert_array_equal(test_input.data, expected_cube.data)
assert_wcs_are_equal(test_input.wcs, expected_cube.wcs)
if test_input.uncertainty:
if check_uncertainty_values:
# Check output and expected uncertainty are of same type. Remember they could be None.
# If the uncertainties are not None,...
# Check units, shape, and values of the uncertainty.
if (test_input.uncertainty is not None and expected_cube.uncertainty is not None):
assert type(test_input.uncertainty) is type(expected_cube.uncertainty)
assert np.allclose(test_input.uncertainty.array, expected_cube.uncertainty.array), \
f"Expected uncertainty: {expected_cube.uncertainty}, but got: {test_input.uncertainty.array}"
elif test_input.uncertainty is None:

Check warning on line 142 in ndcube/tests/helpers.py

View check run for this annotation

Codecov / codecov/patch

ndcube/tests/helpers.py#L142

Added line #L142 was not covered by tests
assert expected_cube.uncertainty is None, "Test uncertainty should not be None." # pragma: no cover
elif expected_cube.uncertainty is None:

Check warning on line 144 in ndcube/tests/helpers.py

View check run for this annotation

Codecov / codecov/patch

ndcube/tests/helpers.py#L144

Added line #L144 was not covered by tests
assert test_input.uncertainty is None, "Test uncertainty should be None." # pragma: no cover
elif test_input.uncertainty:
assert test_input.uncertainty.array.shape == expected_cube.uncertainty.array.shape
assert np.all(test_input.shape == expected_cube.shape)

assert_metas_equal(test_input.meta, expected_cube.meta)
if type(test_input.extra_coords) is not type(expected_cube.extra_coords):
raise AssertionError(f"NDCube extra_coords not of same type: "
Expand Down
Loading