Data Animation Creation Using Python and ffmpeg Tool

Data Animation Creation Using Python and ffmpeg Tool

Postby yiboj » Mon Jan 21, 2019 10:54 pm

Data animation is an efficient way to visulize the dataset quickly and may sometime inspire the new ideas from it.

Next we will show how to create the animation of global sea surface salinity (SSS) over the period 27-03-2015 to 16-04-2018 based on the 8-day running mean version 3.0 SMAP product from Remote Sensing Systems at a spatial resolution of 70km. The animation is published in PODAAC YouTube channel at https://www.youtube.com/watch?v=wadOEbvjl9s. The data set can be downloaded from PODAAC Portal at https://podaac.jpl.nasa.gov/dataset/SMAP_RSS_L3_SSS_SMI_8DAY-RUNNINGMEAN_V3_70KM.

Here is the python code which creates all the animation frames from the downloaded SSS data files. Each frame represents one day of data for this dataset.
Code: Select all
#! /usr/bin/env python
#
# Caution: This is a Python script, and Python takes indentation seriously.
# DO NOT CHANGE INDENTATION OF ANY LINE BELOW!

from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap
from netCDF4 import Dataset
import matplotlib
import os.path
from os import path
import os
import glob
import datetime

# Data Files Directory
data_dir = './8day_running/70KM/'

# set up map projection
parallels = np.arange(-90,90+30,30)
meridians = np.arange(0,360+60,60)

# setup contour levels and colarmap
clevs = np.linspace(32, 40, 101)
cmap=plt.get_cmap("jet")

cmap.set_under("black")
cmap.set_over("DarkViolet")

# setup figure object
plt.figure(figsize=(6, 3.375), dpi=300)

# read each data file in the list
nf = 0
for k in range(2015, 2019):
 for j in range(1, 367):
  strtemp = data_dir+str(k)+'/'+"{0:0>3}".format(j)+'/RSS_smap_SSS_L3_8day_running*v03.0.nc'
  for filename in glob.glob(strtemp):
    print(filename)
    ncin = Dataset(filename, 'r')
    lon = ncin.variables['lon'][:]
    lat = ncin.variables['lat'][:]
    data = ncin.variables['sss_smap'][:]
    ncin.close()
    lons,lats = np.meshgrid(lon,lat)

    m = Basemap(projection='cyl', llcrnrlon=0.0, llcrnrlat=-90.0,
        urcrnrlon=360, urcrnrlat=90.0)
    m.bluemarble()
    m.drawparallels(parallels,labels=[1,0,0,0],fontsize=6)
    meri = m.drawmeridians(meridians,labels=[1,0,0,1],fontsize=6)

    xx, yy = m(lons, lats)

    cs=m.contourf(lons,lats, data, clevs, cmap=cmap, extend='both')
    cb = m.colorbar(cs, 'right', size='2%', pad='0.5%')
    cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=6)
    cb.set_label('SSS (PSU)', fontsize=7,fontweight="bold")
    cb.set_ticks(range(32,41,1))

    d = datetime.date(k,1,1) + datetime.timedelta(j-1)

    plt.title(str(k)+"-"+'{0:02d}'.format(d.month) + "-"+'{0:02d}'.format(d.day)+" (RSS SMAP 70km 8Day)", fontsize=8, fontname="Times New Roman",fontweight="bold")

    nf = nf + 1

    plt.subplots_adjust(left=0.05, right=0.92, top=0.95, bottom=0.01)

    plt.savefig("frame{0}".format(str(nf).rjust(4, "0")), dpi = 300)

    plt.clf()

The python script creates a series of picture frames starting from frame0001.png. Here we show the first three frames:
frame0001.png
First Frame
frame0001.png (197.32 KiB) Viewed 510 times

frame0002.png
Second Frame
frame0002.png (193.77 KiB) Viewed 510 times

frame0003.png
Third Frame
frame0003.png (191.82 KiB) Viewed 510 times

frame0004.png
Fourth Frame
frame0004.png (190.88 KiB) Viewed 510 times

Next the ffmpeg command is used to aggregate all the picture frames into the video animation from the following command:
Code: Select all
%> ffmpeg -framerate 25 -i frame%04d.png -c:v libx264 -crf 23 -pix_fmt yuv420p -qp 0 sss_animation.mp4


The ffmpeg documentation can be found from the website https://ffmpeg.org/ffmpeg.html.
yiboj
 
Posts: 88
Joined: Mon Mar 30, 2015 11:22 am

Return to Visualization