def test_array_animator_wcs_2d_colorbar_buttons(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) bf = [lambda x: x] * 10 bl = ['h'] * 10 a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'y', 'x'], colorbar=True, button_func=bf, button_labels=bl) a.update_plot(1, a.im, a.sliders[0]._slider) return a.fig
def _animate_cube(self, wcs, plot_axes=None, axes_coordinates=None, axes_units=None, data_unit=None, **kwargs): try: from sunpy.visualization.animator import ArrayAnimatorWCS # isort:skip except ImportError: raise ImportError("Sunpy is required for animated " "cube plots.") # If data_unit set, convert data to that unit if data_unit is None: data = self.data else: data = u.Quantity(self.data, unit=self.unit).to_value(data_unit) # Combine data values with mask. if self.mask is not None: data = np.ma.masked_array(data, self.mask) coord_params = {} if axes_units is not None: for axis_unit, coord_name in zip(axes_units, wcs.world_axis_physical_types): coord_params[coord_name] = {'format_unit': axis_unit} # TODO: Add support for transposing the array. if 'y' in plot_axes and plot_axes.index('y') < plot_axes.index('x'): warnings.warn( "Animating a NDCube does not support transposing the array. The world axes " "may not display as expected because the array will not be transposed.", UserWarning) plot_axes = [p if p is not None else 0 for p in plot_axes] ax = ArrayAnimatorWCS(data, wcs, plot_axes, coord_params=coord_params, **kwargs) # We need to modify the visible axes after the axes object has been created. # This call affects only the initial draw self._apply_axes_coordinates(ax.axes, axes_coordinates) # This changes the parameters for future iterations for hidden in self._not_visible_coords(ax.axes, axes_coordinates): if hidden in ax.coord_params: param = ax.coord_params[hidden] else: param = {} param['ticks'] = False ax.coord_params[hidden] = param return ax
def test_array_animator_wcs_2d_extra_sliders(wcs_4d): def vmin_slider(val, im, slider): im.set_clim(vmin=val) def vmax_slider(val, im, slider): im.set_clim(vmax=val) data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'y', 'x'], colorbar=True, slider_functions=[vmin_slider, vmax_slider], slider_ranges=[[0, 100], [0, 100]]) a.update_plot(1, a.im, a.sliders[0]._slider) return a.fig
def test_constructor_errors(wcs_4d): # WCS is not BaseLowLevelWCS with pytest.raises(ValueError, match="provided that implements the astropy WCS API."): ArrayAnimatorWCS(np.arange(25).reshape((5, 5)), {}, ['x', 'y']) # Data has wrong number of dimensions with pytest.raises(ValueError, match="Dimensionality of the data and WCS object do not match."): ArrayAnimatorWCS(np.arange(25).reshape((5, 5)), wcs_4d, ['x', 'y']) # Slices is wrong length with pytest.raises(ValueError, match="slices should be the same length"): ArrayAnimatorWCS(np.arange(16).reshape((2, 2, 2, 2)), wcs_4d, ['x', 'y']) # x not in slices with pytest.raises(ValueError, match="slices should contain at least"): ArrayAnimatorWCS(np.arange(16).reshape((2, 2, 2, 2)), wcs_4d, [0, 0, 0, 'y'])
def test_array_animator_wcs_coord_params_grid(wcs_4d): coord_params = { 'hpln': { 'format_unit': u.deg, 'major_formatter': 'hh:mm:ss', 'axislabel': 'Longitude', 'grid': True } } data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'x', 'y'], coord_params=coord_params) return a.fig
def test_array_animator_wcs_2d_clip_interval_change(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) pclims = [5, 95] a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'x', 'y'], clip_interval=pclims * u.percent) lims0 = a._get_2d_plot_limits() a.update_plot(1, a.im, a.sliders[0]._slider) lims1 = a._get_2d_plot_limits() assert np.all(lims0 != lims1) assert np.all(lims0 == np.percentile(data[..., 0, 0], pclims)) assert np.all(lims1 == np.percentile(data[..., 1, 0], pclims))
def test_array_animator_wcs_1d_update_plot_masked(wcs_3d): """ This test ensures the x axis of the line plot is correct even if the whole of the initial line plotted at construction of the animator is masked out. """ nelem = np.prod(wcs_3d.array_shape) data = np.arange(nelem, dtype=np.float64).reshape(wcs_3d.array_shape) data = np.ma.MaskedArray(data, data < nelem / 2) # Check that the generated data satisfies the test condition assert data.mask[0, 0].all() a = ArrayAnimatorWCS(data, wcs_3d, ['x', 0, 0], ylabel="Y axis!") a.sliders[0]._slider.set_val(wcs_3d.array_shape[0] / 2) return a.fig
def test_construct_array_animator(wcs_4d, data, slices, dim): array_animator = ArrayAnimatorWCS(data, wcs_4d, slices) assert isinstance(array_animator, ArrayAnimatorWCS) assert array_animator.plot_dimensionality == dim assert array_animator.num_sliders == data.ndim - dim for i, (wslice, arange) in enumerate(zip(slices, array_animator.axis_ranges[::-1])): if wslice not in ['x', 'y']: assert callable(arange) a = arange(0) if "pos" in wcs_4d.world_axis_physical_types[i]: assert isinstance(a, u.Quantity) assert u.allclose(a, 0 * u.pix) else: assert isinstance(a, u.Quantity) assert a.value == wcs_4d.pixel_to_world_values(*[0] * wcs_4d.world_n_dim)[i] assert a.unit == wcs_4d.world_axis_units[i] else: assert arange is None
wcs.wcs.crval = [0, m._reference_longitude.value, m._reference_latitude.value] wcs.wcs.ctype = ['TIME'] + list(m.coordinate_system) wcs.wcs.cunit = ['s'] + list(m.spatial_units) wcs.rsun = m.rsun_meters wcs.heliographic_observer = m.observer_coordinate # Now the resulting WCS object will look like: print(wcs) ############################################################################### # Now we can create the animation. # `~sunpy.visualization.animator.ArrayAnimatorWCS` requires you to select which # axes you want to plot on the image. All other axes should have a ``0`` and # sliders will be created to control the value for this axis. wcs_anim = ArrayAnimatorWCS(sequence_array, wcs, [0, 'x', 'y'], vmax=1000) plt.show() ############################################################################### # You might notice that the animation could do with having the axes look # neater. `~sunpy.visualization.ArrayAnimatorWCS` provides a way of setting # some display properties of the `~astropy.visualization.wcsaxes.WCSAxes` # object on every frame of the animation via use of the ``coord_params`` dict. # They keys of the ``coord_params`` dict are either the first half of the # ``CTYPE`` key, the whole ``CTYPE`` key or the entries in # ``wcs.world_axis_physical_types`` here we use the short ctype identifiers for # the latitude and longitude axes. coord_params = {
def test_array_animator_wcs_1d_update_plot(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'x', 0], ylabel="Y axis!") a.sliders[0]._slider.set_val(1) return a.fig
def test_array_animator_wcs_2d_transpose_update_plot(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'y', 'x'], colorbar=True) a.update_plot(1, a.im, a.sliders[0]._slider) return a.fig
def test_to_axes(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, ['x', 'y', 0, 0]) assert isinstance(a.axes, WCSAxes)
def test_array_animator_wcs_2d_celestial_sliders(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, ['x', 'y', 0, 0]) return a.fig
def test_array_animator_wcs_2d_clip_interval(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'x', 'y'], clip_interval=(1, 99)*u.percent) return a.fig
def test_array_animator_wcs_2d_simple_plot(wcs_4d): data = np.arange(120).reshape((5, 4, 3, 2)) a = ArrayAnimatorWCS(data, wcs_4d, [0, 0, 'x', 'y']) return a.fig