Thursday, January 23, 2014

GIF with gnuplot

I needed to make a rotating graph in gnuplot. The plot itself was a 3d plot with one axis being time, one being a server name, and one being a mail count. The graph was fine and all but due to using the heat surface look, it was hard to see some things in the back of the graph. So I wanted to make a gif that simply rotated it.

I did some research and this ended up seeming nigh impossible to do within gnuplot alone. I was able to plot the graph how I wanted by controlling the viewpoint. So I figured if there is a way I can make a ton of output png files, I could use those to create a gif. Turns out this method works quite well. And the best part is that it can all be automated with a script needing no human interaction. The only downside is if you want a small gif at the end, you need to resize/resample it. The final gif I use is a rofling 30 megs. It's 360 frames at a full 1400 by 700 a frame. But on an internal network, this is perfectly fine. You can adjust resolution of the individual graphs in the gnuplot config file.



#! /bin/bash
# mark hamsel 1.23.14
# Script for creating a gif from the gnuplot pics.
# You need this for fonts:
sudo apt-get -y install libgd2-xpm-dev build-essential
#This was for starting out without any residual files
rm /var/www/Servers/test/*.png /var/www/Servers/test/*animation*gif

# All the counters and such initiated
count=0
rotation=0
gifnum=0
gifchunk=0
fullcount=0


while [ $fullcount -lt 360 ] # Main loop; 360 degrees for a perfect spin gif
do


# 'convert' is used to make the gif and it uses globbing
# more than 10 pics at a time will mean they get out of order
while [ $count -lt 10 ]
do

# see the gnuplot config file below

# These sed statemnts are adjusting the output picture number and angle per rep through the 10 count 'while' statement
sed s/XNUMX/$count/ /var/www/Servers/test/3dgnuplot.cfg > /var/www/Servers/test/3dgnuplot.cfg.tmp
sed -i s/XVIEWX/$rotation/ /var/www/Servers/test/3dgnuplot.cfg.tmp

# mmake 1 graph
gnuplot /var/www/Servers/test/3dgnuplot.cfg.tmp


# increment the while10 count, full count (up to 360) and rotation degree (last two interchangable really)
count=$(echo $(($count + 1)))
rotation=$(echo $(($rotation + 1)))
fullcount=$(echo $(($fullcount + 1)))
done

# so after making 10 pictures, use convert to make a gif, keeping it at 10 means globbing works fine
# gifnum is just referencing the while10 gif number so I can glob those later
convert -delay 20 -loop 0 /var/www/Servers/test/*.png /var/www/Servers/test/$gifnum.animation.gif
# after making the gif, remove the png's
rm /var/www/Servers/test/*.png
# reset the while10 counter
count=0
# increment the gif counter
gifnum=$(echo $(($gifnum + 1)))


#####################################
# When you get 10 gifs that the while10 loop made, it globs them together for a larger gif
if [[ $gifnum -eq 9 ]]
then

convert -delay 20 -loop 0 /var/www/Servers/test/*animation.gif /var/www/Servers/test/animation.$gifchunk.gif
gifchunk=$(echo $(($gifchunk + 1)))
gifnum=0
rm /var/www/Servers/test/*.animation.gif
fi
#####################################

done
# After all is said and done and you get the 360 degrees (360 pics made),
# remove all gifs except your larger gif chunks you made
# then use convert to combine all your gifs together in to a mega gif
rm /var/www/Servers/test/*.animation.gif
convert -delay 10 -loop 0 /var/www/Servers/test/animation.* /var/www/Servers/test/myfinalform.gif
# myfinalform.gif is the finished product


## gnuplot config used; you can adjust these to adjust the final gnuplot form
#set term png
#set output '/var/www/Servers/test/XNUMXdgraph.png'
#set terminal png size 1400,700
#set title "Messages processed each hour"
#unset border
#unset surface
#set pm3d at bs
#set hidden3d
#set ylabel "Server"
#set xlabel "Time"
#set dgrid3d 100,100,2
#set samples 50
#set isosamples 50
#set view ,XVIEWX
#splot '/var/www/Servers/3dgnuplot.dat' using 2:1:4:xtic(2):ytic(3) title "Message Counts"









So it may seem like a lot but most of that code is purely to get globbing to work. Without it, you get a schizophrenic gif due to the normal ordering of files (1,12,2,22,3,37,etc). So here's a simple breakdown of what's going on.

  • Make 10 graphs at incrementing angles
  • Take those 10 graphs and make a gif
  • Rinse and repeat above
  • If you get 10 gifs, combine to larger gif
  • Once 360 pics are made in to 10-at-a-time gifs, combine all of those gifs in to the final product
Here's a trimmed down sample of it.


See, easy right?



No comments:

Post a Comment