简体   繁体   中英

Python matplotlib animation output differs from the displayed figure

I'm trying to create a video by using matplotlib.animation on a figure with subplots. One of subplot uses cartopy to show a map.

The code I wrote is:

import pandas as pd
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cfeature
import matplotlib as mpl
import matplotlib.animation as animation
from IPython.display import HTML


data = pd.DataFrame({'data': np.sin(np.arange(0, 2, 0.2))}, index=pd.date_range(start='1/1/2018', periods=10))

extent = [-16, 10, 36, 48] 

#create the figure
fig = plt.figure(figsize=(7,12))

#add subplots
ax = plt.subplot(211, projection=ccrs.PlateCarree())
ax_t = plt.subplot(212)

ax.coastlines(resolution='50m')
ax.add_feature(cfeature.BORDERS.with_scale('50m'))
ax.set_extent(extent, ccrs.PlateCarree())

sm = plt.cm.ScalarMappable(cmap=mpl.cm.Reds,norm=plt.Normalize(0,1))
sm._A = []
cb = plt.colorbar(sm, ax=ax, fraction=0.022, pad=0.02)
cb.set_label('Values')

color = (1.0, 1.0, 1.0)
hpoint = ax.plot(-3, 40, color=color, linewidth=2, marker='o', markersize=30, transform=ccrs.PlateCarree() ) 

#ax_t.plot(meanRMS)
data.plot(ax=ax_t)
ax_t.margins(x=0, tight=True)
ax_t.grid(True)

box1 = ax.get_position()
box2 = ax_t.get_position()
deltaheigh = box2.height * 0.3
ax_t.set_position([box1.x0, box1.y0 - deltaheigh*1.1 , box1.width  , deltaheigh])

This code gives the output that I want and expect:

image in output

while creating a video animation:

frames = 1
iter_data = data.iterrows()
ndays = data.shape[0]

def makemap(n):
    if n % frames == 0:
        time, val = next(iter_data)
        color = (1.0, 1.0-val[0], 1.0-val[0])
        hpoint[0].set_color(color)
        ax.set_title(time.strftime("%d %b %Y"), fontsize=20)




ani = animation.FuncAnimation(fig, makemap, frames=frames*(ndays-2), interval=100)


HTML(ani.to_html5_video())

I get a video with a different shape/format (bigger white canvas with the image not even centered): enter image description here

How can I fix this unexpected result?

So it looks like you're running using the Jupyter notebook. In the notebook, when matplotlib figures are displayed inline, it's saving images using an option bbox_inches='tight' . You can see this in a matplotlib example . Unfortunately, this option is not compatible with saving animations because it can make the size of animation frames vary from image to image.

The way to deal with this is to adjust your figure and axes sizes manually and not rely on the tight bbox to eliminate the whitespace for you. You can check how an individual frame would actually look by saving the figure manually rather than relying on Jupyter's inline display, like this:

fig.savefig('myfig.png')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM