From dc72409505150a99242da0efa3165c71d6b4633b Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Fri, 4 May 2018 12:04:54 +0200 Subject: [PATCH 01/11] First version of explode along axis --- ndcube/ndcube.py | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py index 1014898ee..cb1ec2af3 100644 --- a/ndcube/ndcube.py +++ b/ndcube/ndcube.py @@ -9,6 +9,7 @@ from astropy.utils.misc import InheritDocstrings from ndcube import utils +from ndcube.ndcube_sequence import NDCubeSequence from ndcube.utils.wcs import wcs_ivoa_mapping from ndcube.mixins import NDCubeSlicingMixin, NDCubePlotMixin @@ -525,7 +526,50 @@ def __repr__(self): class NDCube(NDCubeBase, NDCubePlotMixin, astropy.nddata.NDArithmeticMixin): - pass + + def explode_along_axis(self, axis): + """ + Separates slices of NDCubes in sequence along a given cube axis into a NDCubeSequence + of (N-1)DCubes. + + Parameters + ---------- + axis : `int` + The axis along which the data is to be changed. + + Returns + ------- + result : `ndcube_sequence.NDCubeSequence` + + """ + # If axis is -ve then calculate the axis from the length of the dimensions of one cube + if axis < 0: + axis = len(self.dimensions) + axis + # the range of the axis that needs to be sliced + range_of_axis = self.data.shape[axis] + # To store the resultant cube + result_cubes = [] + # We need to convert extra_coords dictionnary to a liste of tuple to create a new NDCube + extra_coords_formated = utils.cube.convert_extra_coords_dict_to_input_format( + self.extra_coords, missing_axis=[False, False, True]) + # Creating a (N-1)Dcube list + for i in range(range_of_axis): + cube = self._new_instance( + self[i].data, self[i].wcs, uncertainty=self[i].uncertainty, unit=self.unit, + meta=self.meta, mask=self[i].mask, missing_axis=[False, False, True], + extra_coords=extra_coords_formated) + result_cubes.append(cube) + return NDCubeSequence(result_cubes, meta=self.meta) + + @classmethod + def _new_instance(cls, data, wcs, uncertainty, unit, meta, + mask, extra_coords, missing_axis=None): + """ + Instantiate a new instance of this class using given data. + """ + return cls(data=data, wcs=wcs, uncertainty=uncertainty, unit=unit, + meta=meta, mask=mask, extra_coords=extra_coords, + missing_axis=missing_axis) class NDCubeOrdered(NDCube): From 2b4b1a188f6359491e5a586ce12c8a60a1133427 Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Fri, 4 May 2018 12:09:31 +0200 Subject: [PATCH 02/11] Removing blank line --- ndcube/ndcube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py index cb1ec2af3..e0e91998c 100644 --- a/ndcube/ndcube.py +++ b/ndcube/ndcube.py @@ -540,7 +540,7 @@ def explode_along_axis(self, axis): Returns ------- result : `ndcube_sequence.NDCubeSequence` - + """ # If axis is -ve then calculate the axis from the length of the dimensions of one cube if axis < 0: From 4f98fb314b587b075e7fc212de49b532e6c9d4cd Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Mon, 7 May 2018 12:21:22 +0200 Subject: [PATCH 03/11] Some code modifications --- ndcube/ndcube.py | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py index e0e91998c..f13f35d84 100644 --- a/ndcube/ndcube.py +++ b/ndcube/ndcube.py @@ -524,12 +524,9 @@ def __repr__(self): """.format(wcs=self.wcs.__repr__(), lengthNDCube=self.dimensions, axis_type=self.world_axis_physical_types)) - -class NDCube(NDCubeBase, NDCubePlotMixin, astropy.nddata.NDArithmeticMixin): - def explode_along_axis(self, axis): """ - Separates slices of NDCubes in sequence along a given cube axis into a NDCubeSequence + Separates slices of NDCubes along a given cube axis into a NDCubeSequence of (N-1)DCubes. Parameters @@ -542,34 +539,24 @@ def explode_along_axis(self, axis): result : `ndcube_sequence.NDCubeSequence` """ - # If axis is -ve then calculate the axis from the length of the dimensions of one cube + # is axis is -ve then calculate the axis from the length of the dimensions of one cube if axis < 0: axis = len(self.dimensions) + axis - # the range of the axis that needs to be sliced - range_of_axis = self.data.shape[axis] # To store the resultant cube result_cubes = [] - # We need to convert extra_coords dictionnary to a liste of tuple to create a new NDCube - extra_coords_formated = utils.cube.convert_extra_coords_dict_to_input_format( - self.extra_coords, missing_axis=[False, False, True]) - # Creating a (N-1)Dcube list - for i in range(range_of_axis): - cube = self._new_instance( - self[i].data, self[i].wcs, uncertainty=self[i].uncertainty, unit=self.unit, - meta=self.meta, mask=self[i].mask, missing_axis=[False, False, True], - extra_coords=extra_coords_formated) - result_cubes.append(cube) - return NDCubeSequence(result_cubes, meta=self.meta) - - @classmethod - def _new_instance(cls, data, wcs, uncertainty, unit, meta, - mask, extra_coords, missing_axis=None): - """ - Instantiate a new instance of this class using given data. - """ - return cls(data=data, wcs=wcs, uncertainty=uncertainty, unit=unit, - meta=meta, mask=mask, extra_coords=extra_coords, - missing_axis=missing_axis) + # All slices are initially initialised as slice(None, None, None) + cube_slices = [slice(None, None, None)] * len(self.data.ndim) + # Slicing the cube inside result_cube + for i in range(self.data.shape[axis]): + # Setting the slice value to the index so that the slices are done correctly. + cube_slices[axis] = i + # Appending the sliced cubes in the result_cube list + result_cubes.append(self[cube_slices]) + # Creating a new NDCubeSequence with the result_cubes and common axis as axis + return NDCubeSequence(result_cubes, common_axis=axis) + +class NDCube(NDCubeBase, NDCubePlotMixin, astropy.nddata.NDArithmeticMixin): + pass class NDCubeOrdered(NDCube): From b12fa3b09bfe69960dcb12850418e8b904162797 Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Mon, 7 May 2018 15:20:08 +0200 Subject: [PATCH 04/11] Removing metadata from sliced cubes --- ndcube/ndcube.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py index f13f35d84..6e69f324d 100644 --- a/ndcube/ndcube.py +++ b/ndcube/ndcube.py @@ -539,7 +539,7 @@ def explode_along_axis(self, axis): result : `ndcube_sequence.NDCubeSequence` """ - # is axis is -ve then calculate the axis from the length of the dimensions of one cube + # If axis is -ve then calculate the axis from the length of the dimensions of one cube if axis < 0: axis = len(self.dimensions) + axis # To store the resultant cube @@ -550,10 +550,13 @@ def explode_along_axis(self, axis): for i in range(self.data.shape[axis]): # Setting the slice value to the index so that the slices are done correctly. cube_slices[axis] = i + # Set to None the metadata of sliced cubes. + sliced_cube = self[cube_slices] + sliced_cube.meta = None # Appending the sliced cubes in the result_cube list result_cubes.append(self[cube_slices]) # Creating a new NDCubeSequence with the result_cubes and common axis as axis - return NDCubeSequence(result_cubes, common_axis=axis) + return NDCubeSequence(result_cubes, common_axis=axis, meta=self.meta) class NDCube(NDCubeBase, NDCubePlotMixin, astropy.nddata.NDArithmeticMixin): pass From ad658d3aeecd91959f880de2007f44e1754e47cc Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Tue, 8 May 2018 12:10:16 +0200 Subject: [PATCH 05/11] Test for explode_along_axis --- ndcube/ndcube.py | 7 ++++--- ndcube/tests/test_ndcube.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py index 6e69f324d..0f2a818a7 100644 --- a/ndcube/ndcube.py +++ b/ndcube/ndcube.py @@ -545,16 +545,17 @@ def explode_along_axis(self, axis): # To store the resultant cube result_cubes = [] # All slices are initially initialised as slice(None, None, None) - cube_slices = [slice(None, None, None)] * len(self.data.ndim) + cube_slices = [slice(None, None, None)] * self.data.ndim # Slicing the cube inside result_cube for i in range(self.data.shape[axis]): # Setting the slice value to the index so that the slices are done correctly. cube_slices[axis] = i # Set to None the metadata of sliced cubes. - sliced_cube = self[cube_slices] + item = tuple(cube_slices) + sliced_cube = self[item] sliced_cube.meta = None # Appending the sliced cubes in the result_cube list - result_cubes.append(self[cube_slices]) + result_cubes.append(self[item]) # Creating a new NDCubeSequence with the result_cubes and common axis as axis return NDCubeSequence(result_cubes, common_axis=axis, meta=self.meta) diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 8e6e39581..36a19ab1c 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -13,6 +13,7 @@ from ndcube import NDCube, NDCubeOrdered from ndcube.utils.wcs import WCS, _wcs_slicer from ndcube.tests import helpers +from ndcube.ndcube_sequence import NDCubeSequence # sample data for tests # TODO: use a fixture reading from a test file. file TBD. @@ -910,3 +911,12 @@ def test_axis_world_coords_without_input(test_input, expected): for i in range(len(all_coords)): np.testing.assert_allclose(all_coords[i].value, expected[i].value) assert all_coords[i].unit == expected[i].unit + + +@pytest.mark.parametrize("test_input,expected", [ + (cubem.explode_along_axis(0), (2*u.pix, 3*u.pix, 4*u.pix)), + (cubem.explode_along_axis(1), (3*u.pix, 2*u.pix, 4*u.pix)), + (cubem.explode_along_axis(-2), (3*u.pix, 2*u.pix, 4*u.pix)) +]) +def test_explode_along_axis(test_input, expected): + assert test_input.dimensions == expected From a588c348a39c8e83e0b4e6513536752ca58b0f8a Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Tue, 8 May 2018 16:12:24 +0200 Subject: [PATCH 06/11] Improving tests --- ndcube/ndcube.py | 2 +- ndcube/tests/test_ndcube.py | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py index 0f2a818a7..f154e5ee8 100644 --- a/ndcube/ndcube.py +++ b/ndcube/ndcube.py @@ -555,7 +555,7 @@ def explode_along_axis(self, axis): sliced_cube = self[item] sliced_cube.meta = None # Appending the sliced cubes in the result_cube list - result_cubes.append(self[item]) + result_cubes.append(sliced_cube) # Creating a new NDCubeSequence with the result_cubes and common axis as axis return NDCubeSequence(result_cubes, common_axis=axis, meta=self.meta) diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 36a19ab1c..33afc5fb4 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -3,6 +3,7 @@ Tests for NDCube ''' from collections import namedtuple +from collections import OrderedDict import datetime import pytest @@ -914,9 +915,12 @@ def test_axis_world_coords_without_input(test_input, expected): @pytest.mark.parametrize("test_input,expected", [ - (cubem.explode_along_axis(0), (2*u.pix, 3*u.pix, 4*u.pix)), - (cubem.explode_along_axis(1), (3*u.pix, 2*u.pix, 4*u.pix)), - (cubem.explode_along_axis(-2), (3*u.pix, 2*u.pix, 4*u.pix)) + (cubem.explode_along_axis(0).dimensions, (2*u.pix, 3*u.pix, 4*u.pix)), + (cubem.explode_along_axis(1).dimensions, (3*u.pix, 2*u.pix, 4*u.pix)), + (cubem.explode_along_axis(-2).dimensions, (3*u.pix, 2*u.pix, 4*u.pix)), + (cubem.explode_along_axis(0)[0].meta, OrderedDict()), + (type(cubem.explode_along_axis(0)), NDCubeSequence), + (type(cubem.explode_along_axis(0)[0]), NDCube) ]) def test_explode_along_axis(test_input, expected): - assert test_input.dimensions == expected + assert test_input == expected From 4a68b34170b2e0131c3223edcdaa9baeb24c4625 Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Wed, 9 May 2018 16:17:00 +0200 Subject: [PATCH 07/11] Improving tests --- ndcube/tests/test_ndcube.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 33afc5fb4..88ab10616 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -915,12 +915,20 @@ def test_axis_world_coords_without_input(test_input, expected): @pytest.mark.parametrize("test_input,expected", [ - (cubem.explode_along_axis(0).dimensions, (2*u.pix, 3*u.pix, 4*u.pix)), - (cubem.explode_along_axis(1).dimensions, (3*u.pix, 2*u.pix, 4*u.pix)), - (cubem.explode_along_axis(-2).dimensions, (3*u.pix, 2*u.pix, 4*u.pix)), - (cubem.explode_along_axis(0)[0].meta, OrderedDict()), - (type(cubem.explode_along_axis(0)), NDCubeSequence), - (type(cubem.explode_along_axis(0)[0]), NDCube) + (cubem.explode_along_axis(0), ((2*u.pix, 3*u.pix, 4*u.pix), NDCubeSequence)), + (cubem.explode_along_axis(1), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence)), + (cubem.explode_along_axis(-2), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence)), ]) def test_explode_along_axis(test_input, expected): - assert test_input == expected + expected_dimensions, expected_type = expected + assert test_input.dimensions == expected_dimensions + assert isinstance(test_input, expected_type) + + +@pytest.mark.parametrize("test_input,expected", [ + (cubem.explode_along_axis(0)[0], (NDCube, OrderedDict)) +]) +def test_explode_along_axis_meta(test_input, expected): + expected_type, expected_meta = expected + assert isinstance(test_input, expected_type) + assert isinstance(test_input.meta, expected_meta) From e86598453aa316ce5a0d6c135b9330105eb5a4ad Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Mon, 14 May 2018 14:28:07 +0200 Subject: [PATCH 08/11] Improving tests v2 --- ndcube/tests/test_ndcube.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 88ab10616..90cec985a 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -915,20 +915,13 @@ def test_axis_world_coords_without_input(test_input, expected): @pytest.mark.parametrize("test_input,expected", [ - (cubem.explode_along_axis(0), ((2*u.pix, 3*u.pix, 4*u.pix), NDCubeSequence)), - (cubem.explode_along_axis(1), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence)), - (cubem.explode_along_axis(-2), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence)), + (cubem.explode_along_axis(0), ((2*u.pix, 3*u.pix, 4*u.pix), NDCubeSequence, dict)), + (cubem.explode_along_axis(1), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict)), + (cubem.explode_along_axis(-2), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict)), + (cubem.explode_along_axis(0)[0], ([3., 4.]*u.pix, NDCube, OrderedDict)) ]) -def test_explode_along_axis(test_input, expected): - expected_dimensions, expected_type = expected - assert test_input.dimensions == expected_dimensions - assert isinstance(test_input, expected_type) - - -@pytest.mark.parametrize("test_input,expected", [ - (cubem.explode_along_axis(0)[0], (NDCube, OrderedDict)) -]) -def test_explode_along_axis_meta(test_input, expected): - expected_type, expected_meta = expected +def test_explode_along_axis_v2(test_input, expected): + expected_dimensions, expected_type, expected_meta = expected + assert tuple(test_input.dimensions) == tuple(expected_dimensions) assert isinstance(test_input, expected_type) assert isinstance(test_input.meta, expected_meta) From b9c09d9b1345c4ce5648498c666e0c1de37dc370 Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Tue, 15 May 2018 12:17:14 +0200 Subject: [PATCH 09/11] Improving test v3 --- ndcube/tests/test_ndcube.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 90cec985a..01bfbbcb2 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -915,13 +915,17 @@ def test_axis_world_coords_without_input(test_input, expected): @pytest.mark.parametrize("test_input,expected", [ - (cubem.explode_along_axis(0), ((2*u.pix, 3*u.pix, 4*u.pix), NDCubeSequence, dict)), - (cubem.explode_along_axis(1), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict)), - (cubem.explode_along_axis(-2), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict)), - (cubem.explode_along_axis(0)[0], ([3., 4.]*u.pix, NDCube, OrderedDict)) + ((cubem, 0, 0), ((2*u.pix, 3*u.pix, 4*u.pix), NDCubeSequence, dict, NDCube, OrderedDict)), + ((cubem, 1, 0), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict, NDCube, OrderedDict)), + ((cubem, -2, 0), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict, NDCube, OrderedDict)) ]) -def test_explode_along_axis_v2(test_input, expected): - expected_dimensions, expected_type, expected_meta = expected - assert tuple(test_input.dimensions) == tuple(expected_dimensions) - assert isinstance(test_input, expected_type) - assert isinstance(test_input.meta, expected_meta) +def test_explode_along_axis(test_input, expected): + output = test_input[0].explode_along_axis(test_input[1]) + exp_dimensions, exp_type_seq, exp_meta_seq, exp_type_cube, exp_meta_cube = expected + assert tuple(output.dimensions) == tuple(exp_dimensions) + assert any(output[test_input[2]].dimensions == \ + u.Quantity((exp_dimensions[1], exp_dimensions[2]), unit='pix')) + assert isinstance(output, exp_type_seq) + assert isinstance(output[test_input[2]], exp_type_cube) + assert isinstance(output.meta, exp_meta_seq) + assert isinstance(output[test_input[2]].meta, exp_meta_cube) From 37dd4ef3394737ab5ac63c1d6686dce212fbe53f Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Wed, 16 May 2018 11:27:38 +0200 Subject: [PATCH 10/11] Inputs extraction in test --- ndcube/tests/test_ndcube.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 01bfbbcb2..203d6f832 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -920,12 +920,13 @@ def test_axis_world_coords_without_input(test_input, expected): ((cubem, -2, 0), ((3*u.pix, 2*u.pix, 4*u.pix), NDCubeSequence, dict, NDCube, OrderedDict)) ]) def test_explode_along_axis(test_input, expected): - output = test_input[0].explode_along_axis(test_input[1]) + inp_cube, inp_axis, inp_slice = test_input exp_dimensions, exp_type_seq, exp_meta_seq, exp_type_cube, exp_meta_cube = expected + output = inp_cube.explode_along_axis(inp_axis) assert tuple(output.dimensions) == tuple(exp_dimensions) - assert any(output[test_input[2]].dimensions == \ + assert any(output[inp_slice].dimensions == \ u.Quantity((exp_dimensions[1], exp_dimensions[2]), unit='pix')) assert isinstance(output, exp_type_seq) - assert isinstance(output[test_input[2]], exp_type_cube) + assert isinstance(output[inp_slice], exp_type_cube) assert isinstance(output.meta, exp_meta_seq) - assert isinstance(output[test_input[2]].meta, exp_meta_cube) + assert isinstance(output[inp_slice].meta, exp_meta_cube) From dcf15400123a9e4ca528ce7e26b0c036602c132e Mon Sep 17 00:00:00 2001 From: Baptiste PELLORCE Date: Fri, 18 May 2018 13:35:31 +0200 Subject: [PATCH 11/11] Trying solve Travis error --- ndcube/ndcube_sequence.py | 2 -- ndcube/tests/test_ndcube.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/ndcube/ndcube_sequence.py b/ndcube/ndcube_sequence.py index 50deadb66..2b14feb58 100644 --- a/ndcube/ndcube_sequence.py +++ b/ndcube/ndcube_sequence.py @@ -1,8 +1,6 @@ import numpy as np import astropy.units as u -import sunpy.map -from sunpy.map import MapCube from ndcube import utils from ndcube.mixins.sequence_plotting import NDCubeSequencePlotMixin diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py index 203d6f832..93ee12407 100644 --- a/ndcube/tests/test_ndcube.py +++ b/ndcube/tests/test_ndcube.py @@ -2,12 +2,10 @@ ''' Tests for NDCube ''' -from collections import namedtuple from collections import OrderedDict import datetime import pytest -import sunpy.map import numpy as np import astropy.units as u