Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions changelog/57.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Adds :class:`~sunkit_pyvista.background_plotter.SunpyBackgroundPlotter` which allows for animations to be performed by defining a separate animator class for the required
animations.
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ install_requires =
pfsspy>=0.6.6
pyvista>=0.31.3
sunpy[map]>=3.0.1
pyvistaqt>=0.5.0
pyqt5

[options.extras_require]
tests =
Expand Down
1 change: 1 addition & 0 deletions sunkit_pyvista/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
__version__ = "0.0.0.0"

from .plotter import *
from .background_plotter import *
from .utils import *
97 changes: 97 additions & 0 deletions sunkit_pyvista/background_plotter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import time
from functools import partial

import pyvistaqt as pvq

from sunpy.map import GenericMap
from sunpy.util import expand_list

from sunkit_pyvista import SunpyPlotter

__all__ = ['SunpyBackgroundPlotter']


class SunpyBackgroundPlotter(SunpyPlotter):
def __init__(self, coordinate_frame=None):
super().__init__(coordinate_frame=coordinate_frame)
self._plotter = pvq.BackgroundPlotter()

@property
def coordinate_frame(self):
"""
Coordinate frame of the plot.
"""
return self._coordinate_frame

@property
def plotter(self):
"""
`pyvistaqt.BackgroundPlotter`.
"""
return self._plotter

def _toggle_animation(self, state, animate):
animate.animation_state = state

def plot_map_sequence(self, *args, interval=2, **kwargs):
"""
Plot a sequence of maps as an animation.

Parameters
----------
m : `sunpy.map.Map`
Map(s) to be plotted.
**kwargs :
Keyword arguments are handed to `pyvistaq.BackGroundplotter.add_mesh`.
"""
map_meshes = []
color_maps = []

maps = expand_list(args)
for m in maps:
if not isinstance(m, GenericMap):
raise ValueError(
'MapSequence expects pre-constructed map objects.')
for m in maps:
mesh = self._pyvista_mesh(m)
map_meshes.append(mesh)
color_maps.append(m.cmap)
animate = SequenceAnimator(time=interval, map_meshes=map_meshes,
color_maps=color_maps)

self.plotter.add_mesh(map_meshes[0], cmap=color_maps[0], **kwargs)
self.plotter.add_checkbox_button_widget(
partial(self._toggle_animation, animate=animate),
value=False, color_on='green')
self.plotter.add_callback(partial(animate,
bg_plotter=self.plotter,
**kwargs), interval=16)
self.plotter.add_text("Play", position=(70, 10))
self.plotter.enable_anti_aliasing()
self.plotter.hide_axes()


class SequenceAnimator(object):
def __init__(self, time, map_meshes, color_maps):
self.angle = 0
self.animation_state = False
self.start_time = 0
self.time = time
self.map_meshes = map_meshes
self.time_flag = False
self.pos = 0
self.color_maps = color_maps

def __call__(self, bg_plotter, **kwargs):
if self.animation_state:
if int(self.start_time+time.time()) % self.time == 0:
if self.time_flag:
bg_plotter.clear()
self.pos += 1
map_pos = self.pos%len(self.map_meshes)
bg_plotter.add_mesh(self.map_meshes[map_pos], cmap=self.color_maps[map_pos], **kwargs)
self.time_flag = False
else:
self.time_flag = True
else:
self.start_time = time.time()
19 changes: 18 additions & 1 deletion sunkit_pyvista/tests/test_pyvista.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pfsspy
import pytest
import pyvista as pv
import pyvistaqt as pvq
from pfsspy import tracing
from pfsspy.sample_data import get_gong_map

Expand All @@ -14,7 +15,7 @@
from astropy.coordinates import SkyCoord
from sunpy.coordinates import HeliocentricInertial, HeliographicStonyhurst

from sunkit_pyvista import SunpyPlotter
from sunkit_pyvista import SunpyBackgroundPlotter, SunpyPlotter


@pytest.fixture
Expand All @@ -27,12 +28,21 @@ def plotter():
return SunpyPlotter()


@pytest.fixture
def bg_plotter():
return SunpyBackgroundPlotter()


@pytest.mark.display_server
def test_basic(plotter):
assert isinstance(plotter.plotter, pv.Plotter)
plotter.show()


def test_basic_animator(bg_plotter):
isinstance(bg_plotter.plotter, pvq.plotting.BackgroundPlotter)


def test_coordinate_frame(plotter):
assert isinstance(plotter.coordinate_frame, HeliocentricInertial)

Expand Down Expand Up @@ -183,7 +193,14 @@ def test_loop_through_meshes(plotter):
assert plotter.plotter.mesh.center == [0, 1, 1]


<<<<<<< HEAD
@pytest.mark.display_server
def test_animator(aia171_test_map, bg_plotter):
bg_plotter.plot_map_sequence(aia171_test_map, aia171_test_map)
bg_plotter.plotter.close()
=======
def test_plot_limb(aia171_test_map, plotter):
plotter.plot_limb(aia171_test_map)
assert plotter.plotter.mesh.n_cells == 22
assert plotter.plotter.mesh.n_points == 20040
>>>>>>> 4338edbfa3642adc060f89acc3f4bfb9baa37e0b