## Sunday, 21 April 2013

### Making animated gifs

This is a short post in my series of "write it up in a blog post so that I don't forget how to do it":
In this post I'm going to briefly show how to create animated "gifs" easily on a *nix system. I've recently stumbled upon how easy it is to do this and here's one from this blog post:

This is all done very easily using the convert command from the imagemagick command line tool.
In this post I showed how to carry out a simple linear regression on a date stamped data set in python. Here's a slightly modified version of the code from that post:

#!/usr/bin/env python
from scipy import stats
import csv
import datetime
import matplotlib.pyplot as plt
import os

# Import data
outfile = open("Data.csv", "rb")
data = [row for row in data]
outfile.close()

dates = []
numbers = {}
for e in data[1:]:
dates.append(e[0])
numbers[e[0]] = eval(e[1])

# Function to fit line
def fit_line(dates, numbers):
x = [(e - min(dates)).days for e in dates]  # Convert dates to numbers for linear regression
gradient, intercept, r_value, p_value, std_err = stats.linregress(x, numbers)

# Function for projection
def project_line(dates, numbers, extra_days):
extra_date = min(dates) + datetime.timedelta(days=extra_days)
projection = gradient * (extra_date - min(dates)).days + intercept

# Function to plot data and projection
def plot_projection(dates, numbers, extra_days):
extra_date, projection, gradient = project_line(dates, numbers, extra_days)
plt.figure(1, figsize=(15, 6))
plt.plot_date(dates, numbers, label="Data")
plt.plot_date(dates + [extra_date], numbers + [projection], '-', label="Linear fit (%.2f join per day)" % gradient)
plt.legend(loc="upper left")
plt.grid(True)
plt.title("Rugby Union Google Plus Community Member Numbers")
now = max(dates)
plt.savefig('Rugby_Union_Community_Numbers-%d-%.02d-%.02d.png' % (now.year, now.month, now.day))
plt.close()

print "Projecting and plotting for all data points"
for i in range(3, len(dates) + 1):
dates_to_plot = [datetime.datetime.strptime(e, '%Y-%m-%d') for e in dates[-i:]]
numbers_to_plot = [numbers[e] for e in dates[-i:]]
plot_projection(dates_to_plot, numbers_to_plot, 365)

The output of this script (if anything is unclear in there just ask) is a series of png files each of which represents a fitted line to for the quantity of data available up to a given date (made using matplotlib). Here are a few of them:
1st 2nd last

Here's the imagemagik convert command to take all these png files to gif:


convert *.png animation.gif

Which gives:

If we want to delay the transition slightly we write:


convert -delay 50 *.png animation.gif

Which gives:

Here's an extremely short screencast demonstrating this: