diff --git a/ndcube/mixins/sequence_plotting.py b/ndcube/mixins/sequence_plotting.py index 960bfaf09..fc9936845 100644 --- a/ndcube/mixins/sequence_plotting.py +++ b/ndcube/mixins/sequence_plotting.py @@ -13,6 +13,7 @@ AXES_UNIT_ERRONESLY_SET_MESSAGE = \ "axes_unit element must be None unless corresponding axes_coordinate is None or a Quantity." + class NDCubeSequencePlotMixin: def plot(self, axes=None, plot_axis_indices=None, axes_coordinates=None, axes_units=None, data_unit=None, **kwargs): @@ -83,7 +84,7 @@ def plot(self, axes=None, plot_axis_indices=None, Returns ------- ax: ??? - + """ # Check kwargs are in consistent formats and set default values if not done so by user. naxis = len(self.dimensions) @@ -183,7 +184,7 @@ def plot_as_cube(self, axes=None, plot_axis_indices=None, Returns ------- ax: ??? - + """ # Verify common axis is set. if self._common_axis is None: @@ -392,7 +393,6 @@ def _plot_2D_sequence_as_1Dline(self, axes_coordinates=None, fig, ax = _make_1D_sequence_plot(xdata, ydata, yerror, unit_y_axis, default_xlabel, kwargs) return ax - def _plot_2D_sequence(self, plot_axis_indices=None, axes_coordinates=None, axes_units=None, data_unit=None, **kwargs): """ @@ -530,7 +530,7 @@ def _plot_3D_sequence_as_2Dimage(self, axes=None, plot_axis_indices=None, if sequence_units is not None: data = np.concatenate([(cube.data * sequence_units[i]).to(data_unit).value for i, cube in enumerate(self.data)], - axis=self._common_axis) + axis=self._common_axis) else: data = np.concatenate([cube.data for cube in self.data], axis=self._common_axis) @@ -548,7 +548,7 @@ def _plot_3D_sequence_as_2Dimage(self, axes=None, plot_axis_indices=None, cube_axis_unit = np.array(self[0].wcs.wcs.cunit)[ np.invert(self[0].missing_axis)][0] cube_axis_coords = \ - self[0].axis_world_coords()[cube_axis_index].to(cube_axis_unit).value + self[0].axis_world_coords()[cube_axis_index].to(cube_axis_unit).value cube_axis_name = self.cube_like_world_axis_physical_types[1] else: if isinstance(axes_coordinates[cube_axis_index], str): @@ -610,14 +610,19 @@ def _plot_3D_sequence_as_2Dimage(self, axes=None, plot_axis_indices=None, # Since we can't assume the x-axis will be uniform, create NonUniformImage # axes and add it to the axes object. im_ax = mpl.image.NonUniformImage( - ax, extent=(axes_coordinates[plot_axis_indices[0]][0], axes_coordinates[plot_axis_indices[0]][-1], - axes_coordinates[plot_axis_indices[1]][0], axes_coordinates[plot_axis_indices[1]][-1]), + ax, extent=(axes_coordinates[plot_axis_indices[0]][0], + axes_coordinates[plot_axis_indices[0]][-1], + axes_coordinates[plot_axis_indices[1]][0], + axes_coordinates[plot_axis_indices[1]][-1]), **kwargs) - im_ax.set_data(axes_coordinates[plot_axis_indices[0]], axes_coordinates[plot_axis_indices[1]], data) + im_ax.set_data(axes_coordinates[plot_axis_indices[0]], + axes_coordinates[plot_axis_indices[1]], data) ax.add_image(im_ax) # Set the limits, labels, etc. of the axes. - ax.set_xlim((axes_coordinates[plot_axis_indices[0]][0], axes_coordinates[plot_axis_indices[0]][-1])) - ax.set_ylim((axes_coordinates[plot_axis_indices[1]][0], axes_coordinates[plot_axis_indices[1]][-1])) + ax.set_xlim((axes_coordinates[plot_axis_indices[0]][0], + axes_coordinates[plot_axis_indices[0]][-1])) + ax.set_ylim((axes_coordinates[plot_axis_indices[1]][0], + axes_coordinates[plot_axis_indices[1]][-1])) ax.set_xlabel(axes_labels[plot_axis_indices[0]]) ax.set_ylabel(axes_labels[plot_axis_indices[1]]) @@ -683,14 +688,14 @@ class ImageAnimatorNDCubeSequence(ImageAnimatorWCS): """ def __init__(self, seq, wcs=None, axes=None, plot_axis_indices=None, axes_coordinates=None, axes_units=None, data_unit=None, **kwargs): - self.sequence = seq.data # Required by parent class. + self.sequence = seq.data # Required by parent class. # Set default values of kwargs if not set. if wcs is None: wcs = seq[0].wcs if axes_coordinates is None: axes_coordinates = [None] * len(seq.dimensions) if axes_units is None: - axes_units = [None] * len(seq.dimensions) + axes_units = [None] * len(seq.dimensions) # Determine units of each cube in sequence. sequence_units, data_unit = _determine_sequence_units(seq.data, data_unit) # If all cubes have unit set, create a data quantity from cube's data. @@ -781,14 +786,14 @@ def __init__(self, seq, wcs=None, axes=None, plot_axis_indices=None, if seq._common_axis is None: raise TypeError("Common axis must be set to use this class. " "Use ImageAnimatorNDCubeSequence.") - self.sequence = seq.data # Required by parent class. + self.sequence = seq.data # Required by parent class. # Set default values of kwargs if not set. if wcs is None: wcs = seq[0].wcs if axes_coordinates is None: axes_coordinates = [None] * len(seq.cube_like_dimensions) if axes_units is None: - axes_units = [None] * len(seq.cube_like_dimensions) + axes_units = [None] * len(seq.cube_like_dimensions) # Determine units of each cube in sequence. sequence_units, data_unit = _determine_sequence_units(seq.data, data_unit) # If all cubes have unit set, create a data quantity from cube's data. diff --git a/ndcube/tests/test_sequence_plotting.py b/ndcube/tests/test_sequence_plotting.py index f08c66ac0..54c11cdad 100644 --- a/ndcube/tests/test_sequence_plotting.py +++ b/ndcube/tests/test_sequence_plotting.py @@ -190,13 +190,13 @@ @pytest.mark.parametrize("test_input, test_kwargs, expected_values", [ (seq[:, 0, 0, 0], {}, - (np.arange(len(seq.data)), np.array([ 1, 11, 1, 11]), + (np.arange(len(seq.data)), np.array([1, 11, 1, 11]), "meta.obs.sequence [None]", "Data [None]", (0, len(seq[:, 0, 0, 0].data)-1), (min([cube.data.min() for cube in seq[:, 0, 0, 0].data]), max([cube.data.max() for cube in seq[:, 0, 0, 0].data])))), (seq_with_units[:, 0, 0, 0], {}, - (np.arange(len(seq_with_units.data)), np.array([ 1, 0.011, 1, 0.011]), + (np.arange(len(seq_with_units.data)), np.array([1, 0.011, 1, 0.011]), "meta.obs.sequence [None]", "Data [km]", (0, len(seq_with_units[:, 0, 0, 0].data)-1), (min([(cube.data * cube.unit).to(seq_with_units[:, 0, 0, 0].data[0].unit).value for cube in seq_with_units[:, 0, 0, 0].data]), @@ -204,13 +204,13 @@ for cube in seq_with_units[:, 0, 0, 0].data])))), (seq_with_uncertainty[:, 0, 0, 0], {}, - (np.arange(len(seq_with_uncertainty.data)), np.array([ 1, 11, 1, 11]), + (np.arange(len(seq_with_uncertainty.data)), np.array([1, 11, 1, 11]), "meta.obs.sequence [None]", "Data [None]", (0, len(seq_with_uncertainty[:, 0, 0, 0].data)-1), (min([cube.data for cube in seq_with_uncertainty[:, 0, 0, 0].data]), max([cube.data for cube in seq_with_uncertainty[:, 0, 0, 0].data])))), (seq_with_units_and_uncertainty[:, 0, 0, 0], {}, - (np.arange(len(seq_with_units_and_uncertainty.data)), np.array([ 1, 0.011, 1, 0.011]), + (np.arange(len(seq_with_units_and_uncertainty.data)), np.array([1, 0.011, 1, 0.011]), "meta.obs.sequence [None]", "Data [km]", (0, len(seq_with_units_and_uncertainty[:, 0, 0, 0].data)-1), (min([(cube.data*cube.unit).to(seq_with_units_and_uncertainty[:, 0, 0, 0].data[0].unit).value @@ -219,35 +219,37 @@ for cube in seq_with_units_and_uncertainty[:, 0, 0, 0].data])))), (seq_with_units_and_some_uncertainty[:, 0, 0, 0], {}, - (np.arange(len(seq_with_units_and_some_uncertainty.data)), np.array([ 1, 0.011, 1, 0.011]), + (np.arange(len(seq_with_units_and_some_uncertainty.data)), np.array([1, 0.011, 1, 0.011]), "meta.obs.sequence [None]", "Data [km]", (0, len(seq_with_units_and_some_uncertainty[:, 0, 0, 0].data)-1), - (min([(cube.data*cube.unit).to(seq_with_units_and_some_uncertainty[:, 0, 0, 0].data[0].unit).value - for cube in seq_with_units_and_some_uncertainty[:, 0, 0, 0].data]), - max([(cube.data*cube.unit).to(seq_with_units_and_some_uncertainty[:, 0, 0, 0].data[0].unit).value - for cube in seq_with_units_and_some_uncertainty[:, 0, 0, 0].data])))), + (min([(cube.data*cube.unit).to( + seq_with_units_and_some_uncertainty[:, 0, 0, 0].data[0].unit).value + for cube in seq_with_units_and_some_uncertainty[:, 0, 0, 0].data]), + max([(cube.data*cube.unit).to( + seq_with_units_and_some_uncertainty[:, 0, 0, 0].data[0].unit).value + for cube in seq_with_units_and_some_uncertainty[:, 0, 0, 0].data])))), (seq[:, 0, 0, 0], {"axes_coordinates": "distance"}, - ((seq.sequence_axis_extra_coords["distance"]), np.array([ 1, 11, 1, 11]), + ((seq.sequence_axis_extra_coords["distance"]), np.array([1, 11, 1, 11]), "distance [{0}]".format(seq.sequence_axis_extra_coords["distance"].unit), "Data [None]", (min(seq.sequence_axis_extra_coords["distance"].value), max(seq.sequence_axis_extra_coords["distance"].value)), (min([cube.data.min() for cube in seq[:, 0, 0, 0].data]), - max([cube.data.max() for cube in seq[:, 0, 0, 0].data])))), + max([cube.data.max() for cube in seq[:, 0, 0, 0].data])))), (seq[:, 0, 0, 0], {"axes_coordinates": u.Quantity(np.arange(len(seq.data)), unit=u.cm), "axes_units": u.km}, - (u.Quantity(np.arange(len(seq.data)), unit=u.cm).to(u.km), np.array([ 1, 11, 1, 11]), + (u.Quantity(np.arange(len(seq.data)), unit=u.cm).to(u.km), np.array([1, 11, 1, 11]), "meta.obs.sequence [km]", "Data [None]", (min((u.Quantity(np.arange(len(seq.data)), unit=u.cm).to(u.km).value)), max((u.Quantity(np.arange(len(seq.data)), unit=u.cm).to(u.km).value))), (min([cube.data.min() for cube in seq[:, 0, 0, 0].data]), - max([cube.data.max() for cube in seq[:, 0, 0, 0].data])))) + max([cube.data.max() for cube in seq[:, 0, 0, 0].data])))) ]) def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): # Unpack expected values expected_x_data, expected_y_data, expected_xlabel, expected_ylabel, \ - expected_xlim, expected_ylim = expected_values + expected_xlim, expected_ylim = expected_values # Run plot method output = test_input.plot(**test_kwargs) # Check values are correct @@ -268,18 +270,18 @@ def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): (seq[:, :, 0, 0], {}, (np.array([0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848]), - np.array([ 1, 2, 11, 22, 1, 2, 11, 22]), - "{0} [{1}]".format(seq[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], "deg"), - "Data [None]", tuple(seq_axis1_lim_deg), + np.array([1, 2, 11, 22, 1, 2, 11, 22]), + "{0} [{1}]".format(seq[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], "deg"), + "Data [None]", tuple(seq_axis1_lim_deg), (min([cube.data.min() for cube in seq[:, :, 0, 0].data]), max([cube.data.max() for cube in seq[:, :, 0, 0].data])))), (seq_with_units[:, :, 0, 0], {}, (np.array([0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848]), - np.array([ 1, 2, 0.011, 0.022, 1, 2, 0.011, 0.022]), - "{0} [{1}]".format(seq[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], "deg"), - "Data [km]", tuple(seq_axis1_lim_deg), + np.array([1, 2, 0.011, 0.022, 1, 2, 0.011, 0.022]), + "{0} [{1}]".format(seq[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], "deg"), + "Data [km]", tuple(seq_axis1_lim_deg), (min([min((cube.data * cube.unit).to(u.km).value) for cube in seq_with_units[:, :, 0, 0].data]), max([max((cube.data * cube.unit).to(u.km).value) @@ -288,10 +290,10 @@ def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): (seq_with_uncertainty[:, :, 0, 0], {}, (np.array([0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848]), - np.array([ 1, 2, 11, 22, 1, 2, 11, 22]), + np.array([1, 2, 11, 22, 1, 2, 11, 22]), "{0} [{1}]".format( - seq_with_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], - "deg"), + seq_with_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[ + common_axis], "deg"), "Data [None]", tuple(seq_axis1_lim_deg), (min([cube.data.min() for cube in seq_with_uncertainty[:, :, 0, 0].data]), max([cube.data.max() for cube in seq_with_uncertainty[:, :, 0, 0].data])))), @@ -299,10 +301,10 @@ def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): (seq_with_some_uncertainty[:, :, 0, 0], {}, (np.array([0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848]), - np.array([ 1, 2, 11, 22, 1, 2, 11, 22]), + np.array([1, 2, 11, 22, 1, 2, 11, 22]), "{0} [{1}]".format( - seq_with_some_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], - "deg"), + seq_with_some_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[ + common_axis], "deg"), "Data [None]", tuple(seq_axis1_lim_deg), (min([cube.data.min() for cube in seq_with_some_uncertainty[:, :, 0, 0].data]), max([cube.data.max() for cube in seq_with_some_uncertainty[:, :, 0, 0].data])))), @@ -310,10 +312,10 @@ def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): (seq_with_units_and_uncertainty[:, :, 0, 0], {}, (np.array([0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848]), - np.array([ 1, 2, 0.011, 0.022, 1, 2, 0.011, 0.022]), + np.array([1, 2, 0.011, 0.022, 1, 2, 0.011, 0.022]), "{0} [{1}]".format( - seq_with_units_and_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], - "deg"), + seq_with_units_and_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[ + common_axis], "deg"), "Data [km]", tuple(seq_axis1_lim_deg), (min([min((cube.data * cube.unit).to(u.km).value) for cube in seq_with_units[:, :, 0, 0].data]), @@ -323,10 +325,10 @@ def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): (seq_with_units_and_some_uncertainty[:, :, 0, 0], {}, (np.array([0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848, 0.49998731, 0.99989848]), - np.array([ 1, 2, 0.011, 0.022, 1, 2, 0.011, 0.022]), + np.array([1, 2, 0.011, 0.022, 1, 2, 0.011, 0.022]), "{0} [{1}]".format( - seq_with_units_and_some_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[common_axis], - "deg"), + seq_with_units_and_some_uncertainty[:, :, 0, 0].cube_like_world_axis_physical_types[ + common_axis], "deg"), "Data [km]", tuple(seq_axis1_lim_deg), (min([min((cube.data * cube.unit).to(u.km).value) for cube in seq_with_units[:, :, 0, 0].data]), @@ -335,26 +337,25 @@ def test_sequence_plot_1D_plot(test_input, test_kwargs, expected_values): (seq[:, :, 0, 0], {"axes_coordinates": "pix"}, (seq[:, :, 0, 0].common_axis_extra_coords["pix"].value, - np.array([ 1, 2, 11, 22, 1, 2, 11, 22]), - "pix [pix]", "Data [None]", - (min(seq[:, :, 0, 0].common_axis_extra_coords["pix"].value), - max(seq[:, :, 0, 0].common_axis_extra_coords["pix"].value)), + np.array([1, 2, 11, 22, 1, 2, 11, 22]), "pix [pix]", "Data [None]", + (min(seq[:, :, 0, 0].common_axis_extra_coords["pix"].value), + max(seq[:, :, 0, 0].common_axis_extra_coords["pix"].value)), (min([cube.data.min() for cube in seq[:, :, 0, 0].data]), max([cube.data.max() for cube in seq[:, :, 0, 0].data])))), (seq[:, :, 0, 0], {"axes_coordinates": np.arange(10, 10+seq[:, :, 0, 0].cube_like_dimensions[0].value)}, - (np.arange(10, 10+seq[:, :, 0, 0].cube_like_dimensions[0].value), + (np.arange(10, 10 + seq[:, :, 0, 0].cube_like_dimensions[0].value), np.array([ 1, 2, 11, 22, 1, 2, 11, 22]), - "{0} [{1}]".format("", None), - "Data [None]", (10, 10 + seq[:, :, 0, 0].cube_like_dimensions[0].value - 1), + "{0} [{1}]".format("", None), "Data [None]", + (10, 10 + seq[:, :, 0, 0].cube_like_dimensions[0].value - 1), (min([cube.data.min() for cube in seq[:, :, 0, 0].data]), max([cube.data.max() for cube in seq[:, :, 0, 0].data])))) ]) def test_sequence_plot_as_cube_1D_plot(test_input, test_kwargs, expected_values): # Unpack expected values expected_x_data, expected_y_data, expected_xlabel, expected_ylabel, \ - expected_xlim, expected_ylim = expected_values + expected_xlim, expected_ylim = expected_values # Run plot method output = test_input.plot_as_cube(**test_kwargs) # Check values are correct @@ -402,7 +403,9 @@ def test_sequence_plot_as_cube_error(): (min(seq[0, :, 0, 0].extra_coords["pix"]["value"].value), max(seq[0, :, 0, 0].extra_coords["pix"]["value"].value), min(seq[:, :, 0, 0].sequence_axis_extra_coords["distance"].value), - max(seq[:, :, 0, 0].sequence_axis_extra_coords["distance"].value)))), ## This shows weakness of current extra coord axis values on 2D plotting! + max(seq[:, :, 0, 0].sequence_axis_extra_coords["distance"].value)))), + # This example shows weakness of current extra coord axis values on 2D plotting! + # Only the coordinates from the first cube are shown. (seq[:, :, 0, 0], {"axes_coordinates": [np.arange( 10, 10+seq[:, :, 0, 0].dimensions[-1].value), "distance"], "axes_units": [None, u.m]}, @@ -416,9 +419,9 @@ def test_sequence_plot_as_cube_error(): 10, 10+seq[:, :, 0, 0].dimensions[-1].value)*u.deg, None], "axes_units": [u.arcsec, None]}, (seq_stack[:, :, 0, 0], " [arcsec]", "meta.obs.sequence [None]", - tuple( - list((np.arange(10, 10+seq[:, :, 0, 0].dimensions[-1].value)*u.deg).to(u.arcsec).value) + \ - [0, len(seq.data)-1]))) + tuple(list( + (np.arange(10, 10+seq[:, :, 0, 0].dimensions[-1].value)*u.deg).to(u.arcsec).value) \ + + [0, len(seq.data)-1]))) ]) def test_sequence_plot_2D_image(test_input, test_kwargs, expected_values): # Unpack expected values @@ -507,6 +510,7 @@ def test_sequence_plot_as_cube_2D_image_errors(test_input, test_kwargs, expected with pytest.raises(expected_error): output = test_input.plot_as_cube(**test_kwargs) + @pytest.mark.parametrize("test_input, test_kwargs, expected_data", [ (seq, {}, seq_stack.reshape(4, 1, 2, 3, 4)), (seq_with_units, {}, seq_stack_km.reshape(4, 1, 2, 3, 4)) @@ -548,6 +552,7 @@ def test_determine_sequence_units(): output_seq_unit, output_unit = ndcube.mixins.sequence_plotting._determine_sequence_units( seq.data, u.m) + @pytest.mark.parametrize("test_input, expected", [ ((3, 1, "time", u.s), ([1], [None, 'time', None], [None, u.s, None])), ((3, None, None, None), ([-1, -2], None, None))])