# Execute with: R --slave -f draw.r library(maps) library(mapdata) library(foreach) library(doParallel) # Use the GoCardless font par(family="Gotham-Book") # Set colours gocardless_blue = rgb(0.31,0.57,0.85) gocardless_blue_translucent = rgb(0.31,0.57,0.85,0.1) gocardless_dark_grey = rgb(0.298, 0.308, 0.394) gocardless_dark_red = rgb(0.753, 0.361, 0.361) # Set variables width = 2000 height = 3000 output_directory = "/Users/petehamilton/projects/gocardless-map/output/gc-customers" # Initialize parallel cl <- makeCluster(detectCores() - 1) registerDoParallel(cl, cores = detectCores() - 1) # Read in the data all_customers <- read.csv("/Users/petehamilton/projects/gocardless-map/data/customers-export.csv", header = TRUE) # Make dates actual dates rather than strings (for comparison) all_customers$date <- as.Date(as.character(all_customers$date),format="%Y-%m-%d") # Get a list of all days from first to last customer first_record = head(all_customers, 1) last_record = tail(all_customers, 1) all_days = seq(from=as.Date(first_record$date), to=as.Date(last_record$date), "days") # Helper functions draw_map <- function(border_color) { map('worldHires', c('UK', 'Ireland', 'Isle of Man','Isle of Wight'), xlim=c(-11,3), ylim=c(49,60.9), fill=FALSE, col=border_color, mar=rep(1,4)) } plot_customers <- function(customers, point_color, point_size_cex) { points(customers$lon,customers$lat, col=point_color, pch=20, cex=point_size_cex) } set_title <- function(text, color) { title(text, col.main=color) } print(paste("Num. Customers:", nrow(all_customers))) print(paste("Total Days:", length(all_days))) main_frame_count = length(all_days) foreach(i = 1:main_frame_count, .packages = c("maps","mapdata")) %dopar% { setwd(output_directory) png(sprintf("frame_%06d.png", i), height=height, width=width, pointsize = 80) # Split customers added prior to and on the current date historic_customers <- all_customers[all_customers$date < all_days[i],] new_customers <- all_customers[all_customers$date == all_days[i],] draw_map("white") plot_customers(historic_customers, gocardless_blue_translucent, 0.2) plot_customers(new_customers, gocardless_dark_red, 0.3) set_title(format(all_days[i], format="%Y-%m-%d"), gocardless_blue) dev.off(dev.cur()) } final_frame_count = 60 # 2s @ 30fps foreach(i = 1:final_frame_count, .packages = c("maps","mapdata")) %dopar% { setwd(output_directory) png(sprintf("frame_%06d.png", main_frame_count + i), height=height, width=width, pointsize = 80) opacity = i/final_frame_count draw_map(rgb(0.31,0.57,0.85, opacity)) plot_customers(all_customers, gocardless_blue_translucent, 0.2) set_title("GoCardless", rgb(0.31,0.57,0.85, opacity)) dev.off(dev.cur()) } stopCluster(cl) # Then in the images dir: # ffmpeg -r 30 -i frame_%06d.png -b:v 2048k customer-growth.mpg # avconv -f image2 -i %06d.png -c:v h264 -crf 1 -r 30 out.mpg # For making a .mov, I found I needed to change a few things: # See http://superuser.com/questions/820134/why-cant-quicktime-play-a-movie-file-encoded-by-ffmpeg # ffmpeg -f image2 -r 30 -i frame_%06d.png -vcodec libx264 -pix_fmt yuv420p out.mov