Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2afe9f8
Implement 1D animations
johnomotani Jul 15, 2019
317420e
Use None as default argument for vmin/vmax in animate functions
johnomotani Jul 16, 2019
48ab357
Animation Writer changed to PillowWriter in animate1D and animate2D
rdoyle45 Sep 10, 2019
283d098
Update xbout/plotting/animate.py
rdoyle45 Sep 11, 2019
6e72dd8
Update xbout/plotting/animate.py
rdoyle45 Sep 12, 2019
ef8f211
Update to required Matplotlib version
rdoyle45 Sep 12, 2019
75ebd07
Python 3.5 doesn't support Matplotlib 3.1.0
rdoyle45 Sep 12, 2019
f9848d0
Test file for animate1D and 2D
rdoyle45 Sep 12, 2019
4836ce4
PEP8 issues fixed
rdoyle45 Sep 12, 2019
1049b02
PEP8 issues fixed
rdoyle45 Sep 12, 2019
72dd9b5
Path to data incorrect
rdoyle45 Sep 12, 2019
33d85a8
Removal of unwanted line
rdoyle45 Sep 12, 2019
8a35031
Pillow required for PillowWriter
rdoyle45 Sep 12, 2019
45245c2
Dependency update
rdoyle45 Sep 15, 2019
88868d0
Improved use of python functions for pytest and added use of pytest f…
rdoyle45 Oct 13, 2019
be183be
PEP8 fixes
rdoyle45 Oct 13, 2019
6447865
PEP8 fixes
rdoyle45 Oct 13, 2019
bfad80e
Remove .gif suffix from test
rdoyle45 Oct 14, 2019
c9d5d2f
Merge pull request #52 from rdoyle45/1d-animations
johnomotani Oct 15, 2019
738c0da
Merge branch 'master' into 1d-animations
johnomotani Oct 21, 2019
6a29502
Add more fake grid data in test_load.create_bout_ds
johnomotani Oct 23, 2019
021dcd2
Unique random data in files created by create_bout_ds_list
johnomotani Oct 23, 2019
1426210
Reorder dimensions in create_bout_ds to ('t','x','y','z')
johnomotani Oct 23, 2019
3ca6274
Implement 'linear' option for create_bout_ds
johnomotani Oct 23, 2019
452e69d
Remove dependence of test_animate on saved binary files
johnomotani Oct 21, 2019
f09f7a7
Bump required Python version to 3.6, test 3.6 and 3.7 with Travis
johnomotani Oct 23, 2019
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: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: python
python:
- "3.5"
- "3.6"
- "3.7"
install:
- pip install --upgrade setuptools pip pytest pytest-cov coverage codecov
- pip install -r requirements.txt
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
xarray >= 0.12.2
dask[array] >= 1.0.0
natsort >= 5.5.0
matplotlib >= 2.2
matplotlib >= 3.0.3
animatplot >= 0.3
netcdf4 >= 1.4.0
Pillow >= 6.1.0
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@
author_email="thomas.nicholas@york.ac.uk",
description='Collect data from BOUT++ runs in python using xarray',
license="Apache",
python_requires='>=3.5',
python_requires='>=3.6',
install_requires=[
'xarray>=v0.12.2',
'dask[array]>=1.0.0',
'natsort>=5.5.0',
'matplotlib>=2.2',
'matplotlib>=3.0.3',
'animatplot>=0.3',
'netcdf4>=1.4.0',
'Pillow>=6.1.0'
],
extras_require={
'tests': ['pytest >= 3.3.0'],
Expand All @@ -42,7 +43,6 @@
"License :: OSI Approved :: Apache License",
"Natural Language :: English",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Topic :: Scientific/Engineering :: Visualization"
Expand Down
3 changes: 1 addition & 2 deletions xbout/boutdataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ def animate1D(self, animate_over='t', x='x', y='y', animate=True,
print("{} data passed has {} dimensions - will use "
"animatplot.blocks.Line()".format(variable, str(n_dims)))
line_block = animate_line(data=data, animate_over=animate_over,
x=x, y=y, sep_pos=sep_pos,
animate=animate, fps=fps,
sep_pos=sep_pos, animate=animate, fps=fps,
save_as=save_as, ax=ax, **kwargs)
return line_block
93 changes: 83 additions & 10 deletions xbout/plotting/animate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import animatplot as amp

from .utils import plot_separatrix

from matplotlib.animation import PillowWriter

def animate_imshow(data, animate_over='t', x='x', y='y', animate=True,
vmin='min', vmax='max', fps=10, save_as=None,
vmin=None, vmax=None, fps=10, save_as=None,
sep_pos=None, ax=None, **kwargs):
"""
Plots a color plot which is animated with time over the specified
Expand Down Expand Up @@ -60,9 +60,9 @@ def animate_imshow(data, animate_over='t', x='x', y='y', animate=True,
image_data = data.values

# If not specified, determine max and min values across entire data series
if vmax is 'max':
if vmax is None:
vmax = np.max(image_data)
if vmin is 'min':
if vmin is None:
vmin = np.min(image_data)

if not ax:
Expand Down Expand Up @@ -93,16 +93,89 @@ def animate_imshow(data, animate_over='t', x='x', y='y', animate=True,

if not save_as:
save_as = "{}_over_{}".format(variable, animate_over)
# TODO save using PillowWriter instead once matplotlib 3.1 comes out
# see https://github.com/t-makaro/animatplot/issues/24
anim.save(save_as + '.gif', writer='imagemagick')
anim.save(save_as + '.gif', writer=PillowWriter(fps=fps))

return imshow_block


def animate_line(data, animate_over='t', x='x', y='y', animate=True,
fps=10, save_as=None, sep_pos=None, ax=None, **kwargs):
def animate_line(data, animate_over='t', animate=True,
vmin=None, vmax=None, fps=10, save_as=None, sep_pos=None, ax=None,
**kwargs):
"""
Plots a line plot which is animated with time.

Currently only supports 1D+1 data, which it plots with xarray's
wrapping of matplotlib's plot.

Parameters
----------
data : xarray.DataArray
animate_over : str, optional
Dimension over which to animate
vmin : float, optional
Minimum value to use for colorbar. Default is to use minimum value of
data across whole timeseries.
vmax : float, optional
Maximum value to use for colorbar. Default is to use maximum value of
data across whole timeseries.
sep_pos : int, optional
Radial position at which to plot the separatrix
save_as: str, optional
Filename to give to the resulting gif
fps : int, optional
Frames per second of resulting gif
kwargs : dict, optional
Additional keyword arguments are passed on to the plotting function
(e.g. imshow for 2D plots).
"""

variable = data.name

# Check plot is the right orientation
t_read, x_read = data.dims
raise NotImplementedError
if (t_read is animate_over):
pass
else:
data = data.transpose(x_read, animate_over)

# Load values eagerly otherwise for some reason the plotting takes
# 100's of times longer - for some reason animatplot does not deal
# well with dask arrays!
image_data = data.values

# If not specified, determine max and min values across entire data series
if vmax is None:
vmax = np.max(image_data)
if vmin is None:
vmin = np.min(image_data)

if not ax:
fig, ax = plt.subplots()

# set range of plot
ax.set_ylim([vmin, vmax])

line_block = amp.blocks.Line(image_data, ax=ax, **kwargs)

timeline = amp.Timeline(np.arange(data.sizes[animate_over]), fps=fps)

if animate:
anim = amp.Animation([line_block], timeline)

# Add title and axis labels
ax.set_title("{} variation over {}".format(variable, animate_over))
ax.set_xlabel(x_read)
ax.set_ylabel(variable)

# Plot separatrix
if sep_pos:
ax.plot_vline(sep_pos, '--')

if animate:
anim.controls(timeline_slider_args={'text': animate_over})

if not save_as:
save_as = "{}_over_{}".format(variable, animate_over)
anim.save(save_as + '.gif', writer=PillowWriter(fps=fps))

return line_block
44 changes: 44 additions & 0 deletions xbout/tests/test_animate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import pytest

from xbout import open_boutdataset
from xbout.boutdataarray import BoutDataArrayAccessor
from .test_load import create_bout_ds_list

from animatplot.blocks import Imshow, Line


@pytest.fixture
def create_test_file(tmpdir_factory):

# Create temp dir for output of animate1D/2D
save_dir = tmpdir_factory.mktemp("test_data")

# Generate some test data
ds_list, file_list = create_bout_ds_list("BOUT.dmp", nxpe=3, nype=3,
syn_data_type="linear")
for ds, file_name in zip(ds_list, file_list):
ds.to_netcdf(str(save_dir.join(str(file_name))))

ds = open_boutdataset(save_dir.join("BOUT.dmp.*.nc")) # Open test data

return save_dir, ds


class TestAnimate:
"""
Set of tests to check whether animate1D() and animate2D() are running properly
and PillowWriter is saving each animation correctly
"""
def test_animate2D(self, create_test_file):

save_dir, ds = create_test_file
animation = ds['n'].isel(y=1).bout.animate2D(y='z', save_as="%s/test" % save_dir)

assert isinstance(animation, Imshow)

def test_animate1D(self, create_test_file):

save_dir, ds = create_test_file
animation = ds['n'].isel(y=2, z=0).bout.animate1D(save_as="%s/test" % save_dir)

assert isinstance(animation, Line)
Loading