This Notebook demonstrates how to create animations in VCS
Animations are rendered via FFMPEG
The CDAT software was developed by LLNL. This tutorial was written by Charles Doutriaux. This work was performed under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.
We need some sample data
import requests
r = requests.get("https://uvcdat.llnl.gov/cdat/sample_data/clt.nc",stream=True)
with open("clt.nc","wb") as f:
for chunk in r.iter_content(chunk_size=1024):
if chunk: # filter local_filename keep-alive new chunks
f.write(chunk)
import cdms2
f=cdms2.open("clt.nc")
clt = f("clt")
# make directory for pngs if not present
import os
if not os.path.exists("pngs"):
os.makedirs("pngs")
import vcs
x=vcs.init(bg=True)
for i in range(clt.shape[0]):
x.clear()
x.plot(clt[i])
x.png("pngs/2d_%s.png" % str(i).zfill(6))
import glob
name = "2d_animation.mp4"
# Create animation into file
x.ffmpeg(name,sorted(glob.glob("pngs/2d*png")))
In this example we will show a fix 1D target dataset and a moving red dataset in the back
import cdutil
import numpy
# Open data file
f=cdms2.open("clt.nc")
# reads in data
s=f("clt")
# Computes time serie
ts=cdutil.averager(s,axis="xy")
# remove the mean
mean = ts.mean()
ts -= mean
# create some random data with some extra points to fake the move
Nextra = 120
ts2 = numpy.random.rand(len(ts)+Nextra)*4.-2.
# When plotting we will get data for 2 extra years than our target grid
# Prepare the "faxe time" axis
fake_time_axis = cdms2.createAxis(numpy.arange(-12,132))
fake_time_axis.designateTime()
fake_time_axis.id = "time"
fake_time_axis.units="months since 1979"
# Create a "blank" template
blank = vcs.createtemplate()
blank.blank()
blank.data.priority=1 # turn only data area
# Create the "black" 1D line
black = vcs.create1d()
black.linecolor ="black"
black.markercolor = [0,0,0,0]
black.linewidth = 4
black.datawc_y1= -3
black.datawc_y2 = 3
black.datawc_x1 = -12
black.datawc_x2 = 132
# And from it let's create the "red" moving one
red = vcs.create1d(source=black.name)
red.linecolor="red"
red.linewidth=2
red.linetype = "dot"
x=vcs.init(bg=True)
for i in range(Nextra-24):
# Get some subset of data
tsub = cdms2.MV2.array(ts2[i:i+len(ts)+24]) # Two years worth of extra data
# Aplly fake axis to make it look like it moves
tsub.setAxis(0,fake_time_axis)
# clear and plot
x.clear()
x.plot(ts,black)
x.plot(tsub,red,blank)
# save data to a png file
x.png("pngs/1d_%s.png" % str(i).zfill(6))
name = "1d_animation.mp4"
# Create animation into file
x.ffmpeg(name,sorted(glob.glob("pngs/1d*png")))
import glob
name = "1d_animation_slow.mp4"
# Create animation into file
x.ffmpeg(name,sorted(glob.glob("pngs/1d*png")),rate=2)
import glob
name = "1d_animation_fast.mp4"
# Create animation into file
x.ffmpeg(name,sorted(glob.glob("pngs/1d*png")),rate=200)
In this example we will display a rotating earth Back to top
f=cdms2.open("clt.nc")
clt=f("clt",time=slice(0,1),longitude=(0,361),squeeze=1) # Read the time slice and squeeze it out
# create new canvas
x = vcs.init(bg=True)
# Create projection
polar = vcs.createprojection("rotate")
polar.type = "orthographic"
polar.centerlongitude=0.
polar.centerlatitude=45.
# Create isofill method
iso = vcs.createisofill()
iso.levels = [a for a in range(0,110,10)]
iso.fillareacolors = vcs.getcolors(iso.levels)
iso.projection = polar
for centerLongitude in range(0,366,5):
polar.centerlongitude = centerLongitude
x.clear()
x.plot(clt,iso)
x.png("pngs/rotate_%s.png" % str(centerLongitude).zfill(6))
name = "rot_animation.mp4"
# Create animation into file
print("files used",glob.glob("pngs/rotate_*png"))
x.ffmpeg(name,sorted(glob.glob("pngs/rotate_*png")), rate=15)
But it is rotating THE WRONG WAY!!!*
Why?
FFMPEG uses the images passed by the list in the order passed.
Look above the order is with growing centerLongitude
Let's fix this by passing the image sequence in reversed order
name = "rot_animation_correct_order.mp4"
# Create animation into file
x.ffmpeg(name,sorted(glob.glob("pngs/rotate_*png"))[::-1], rate=15)
# Create pngs
clt = f("clt",longitude=(0,361))
for i,centerLongitude in enumerate(range(0,361,4)):
polar.centerlongitude = centerLongitude
x.clear()
x.plot(clt[i],iso)
x.png("pngs/all_%s.png" % str(centerLongitude).zfill(6))
name = "rot_animation_all.mp4"
# Create animation into file
x.ffmpeg(name,sorted(glob.glob("pngs/all_*png"))[::-1], rate=10)