NOTE TO READER:

This material is now considered historic, and is superceded by the built-in movie maker plugin for most cases, but is provided as a reference for those individuals that wish to write their own movie making tools

Making a Movie

This section describes how to take a sequence of images from the display and combine them to form a movie. There are several steps to this process, including:

What will you show?

There are many things from which to make a movie of your system. You could, for instance, rotate the model around the Y axis to lend a sense of depth that a single image doesn't give. You can show the results of an MD simulation or change transparancy parameters to dissolve the surface slowly from the display. These examples will be shown below, and there are are many other possible movies you might want to make.

Writing Animation Frames and Merging Them into a Movie

Once you've come up with a method, you'll need some way to schedule the sequence of events. You could try to do it by hand, but that gets very tedious. The best is to come up with a script that does what you want automatically. You could record a log file and play it back, but it is rarely smooth.

For example, here is a simple script to rotate the molecule around the screen vertical (the "Y" axis), 20 degrees at a time, returning to its original position at the beginning.
	for {set i 0} {$i < 360} {incr i 20} {
		rotate y by 20
	}
For each of these rotations, you'll want to save the image on the screen to a file. This is done with the rendering commands. The fastest option is to take the image directly from the screen with the 'snapshot' renderer. After you have the full sequence of images, you can use one of several programs to produce the movie. These programs usually require that the image file names fit the pattern where the prefix and suffix don't change, and the is a zero-filled value starting at 0 and increasing by 1 for each image. In other words, these are valid:

  snap.0000.rgb  snap.0001.rgb ... snap.0242.rgb  
  i0.rle  i1.rle  i2.rle  i3.rle  
but these are usually not
  snap.0000.rgb  snap.0002.rgb ....
  i0.rle  i1.rle  i2.rle  ... i9.rle  i10.rle
  a.gif b.gif c.gif 
Also, if you stay with the recommended form, then you can always sort your list without a problem. For example, you might otherwise get a list of files like "i1.rle, i10.rle, i2.rle, ...." You can get that form with the format command. It uses a convention from C that will automatically generate zero-filled numbers if you tell it how many digits are available. You'll almost never generate more than 9999 images, so assume there are 4. Then


vmd > format "%04d" 5

Info) 0005
The following code adds the code needed to keep track of successive filenames. You can see the original example still in it, but there are four more lines added to keep of the frame number and generate the filename.
	set frame 0
	for {set i 0} {$i < 360} {incr i 20} {
		set filename snap.[format "%04d" $frame].rgb
		render snapshot $filename
		incr frame
		rotate y by 20
	}
If you enter this code into VMD then enter 'ls snap.*.rgb' you should see a list of the 18 images just created.
snap.0000.rgb  snap.0004.rgb  snap.0008.rgb  snap.0012.rgb  snap.0016.rgb
snap.0001.rgb  snap.0005.rgb  snap.0009.rgb  snap.0013.rgb  snap.0017.rgb
snap.0002.rgb  snap.0006.rgb  snap.0010.rgb  snap.0014.rgb  snap.rgb.rgb
snap.0003.rgb  snap.0007.rgb  snap.0011.rgb  snap.0015.rgb
You could use a program like xv, ipaste, or display to look at a few of the files and verify they have different images.

Lets turn this into a QuickTime movie using SGI's "mediaconvert" program. Start it up. Under "File" choose "Select Input File." A file browser will appear. Choose "snap.0000.rgb." Once the browser closes, click on "Numbered Images." New options will be displayed, which are used to select the desired images to turn into a movie.

Here's where the file naming convention comes into play. On the entry box for "File Template:" replace the 0000 with ####. This will tell the program that those characters are the ones that can change. Your 18 images are numbered from 0 to 17, so change the value of "End:" to 17.

Now go over to "File Format:" in the center of the right side and choose "QuickTime." There are different ways of setting up a QuickTime file so click on the arrow to the right of "Video Parameters." A new menu will appear and let you choose the compression method. Choose "RLE" since we believe it compresses best for computer graphics. (Anyone want to suggest otherwise?) There's a slider there that lets you choose the degree of compression -- the more compressed it is, the worse the image but the smaller the final movie file. Don't worry about this now, but you might want to see which values get better or worse results for you.

All that is left is to press the "Start" button in the lower right and wait for the file "outfile.mov" to be created. To view the file, use "mediaplayer" on the SGIs or xanim. The latter is available on most X-based machines. That's it, you've made a movie!

Putting Movies on the World Wide Web

Now that you have put together an interesting movie, you may want to see it on a web page as an inline animated GIF. There are many ways to do this, but the easiest is to use {\sf convert} from the ImageMagick tools.
	convert -delay 10 -loop 4 snap.*.rgb movie.gif
The routine produces a file called movie.gif with the option that when it is finished it will loop back to the beginning. Actually, it will loop four times and stop, except that Netscape doesn't stop looping. The delay value is the amount of time to wait between updates, in 1/100ths of a second, so the delay here is 1/10 of a second.

The file can be used and viewed just like any other GIF file, but the best way to see it is in a web viewer like Netscape Navigator. Create the file "movie.html" and add the line
	This is an image: <img src=movie.gif>
to it. Use the browser to open the HTML file (with the Open->File option), and you should see the rotating image.

The downfall with this image is it is too large, so the display is slow. You can use one of many graphics tools to reduce the size of the images, or you can start the whole process over again but with a smaller display.

Other Helpful Movie Scripts

Here are some other standard scripts you might want to test out. As a note, remember that when you write these scripts you don't have to be too concerned about speed as that can easily be increased when piecing together the final images into the movie.

Suppose you want to make a movie of the complete trajectory for the top molecule. Following is a script that steps through each of the frames, one by one.
	# get the number of frames in the movie
	set num [molinfo top get numframes]
	# loop through the frames
	for {set i 0} {$i < $num} {incr i} {
		# go to the given frame
		animate goto $i
	}
Adding the two lines of commands to save the image on the screen yields,
	# get the number of frames in the movie
	set num [molinfo top get numframes]
	# loop through the frames
	for {set i 0} {$i < $num} {incr i} {
		# go to the given frame
		animate goto $i
		# take the picture
		set filename snap.[format "%04d" $i].rgb
		render snapshot $filename
	}
However, once you start changing your code to take the pictures and save it to disk, you will probably start to wish there was a better way, since otherwise you have to keep track of the current frame number, and the current filename, etc. There is. We've written a routine called "take_picture" which simplifies the example code to
	# get the number of frames in the movie
	set num [molinfo top get numframes]
	# loop through the frames
	for {set i 0} {$i < $num} {incr i} {
		# go to the given frame
		animate goto $i
		# take the picture
		take_picture
	}
Every time take_picture is called, it takes a picture and saves it to a file using the current picture number. It then increments that value by 1. You can also have it save only every nth image, so the pictures it saves might be numbers 0, 5, 10, 15, ... . Its default setting uses the 'snapshot' renderer option, but it can be made call any of the other renderers. Since some of these renderers require another step to turn the information into an image, another parameter lets you run a unix command to process the output file. Finally, the default parameter for the 'format' command is "animate.%04d.rgb" but that can be changed as need be. Following is the script itself, then will be some examples of how to use the different parameters. You'll want to copy and paste this into the VMD text window, or save it in a file and source it when needed.
proc take_picture {args} {
  global take_picture

  # when called with no parameter, render the image
  if {$args == {}} {
    set f [format $take_picture(format) $take_picture(frame)]
    # take 1 out of every modulo images
    if { [expr $take_picture(frame) % $take_picture(modulo)] == 0 } {
      render $take_picture(method) $f
      # call any unix command, if specified
      if { $take_picture(exec) != {} } {
        set f [format $take_picture(exec) $f $f $f $f $f $f $f $f $f $f]
        eval "exec $f"
      }
    }
    # increase the count by one
    incr take_picture(frame)
    return
  }
  lassign $args arg1 arg2
  # reset the options to their initial stat
  # (remember to delete the files yourself
  if {$arg1 == "reset"} {
    set take_picture(frame)  0
    set take_picture(format) "./animate.%04d.rgb"
    set take_picture(method) snapshot
    set take_picture(modulo) 1
    set take_picture(exec)    {}
    return
  }
  # set one of the parameters
  if [info exists take_picture($arg1)] {
    if { [llength $args] == 1} {
      return "$arg1 is $take_picture($arg1)"
    }
    set take_picture($arg1) $arg2
    return
  }
  # otherwise, there was an error
  error {take_picture: [ | reset | frame | format  | \
method  | modulo ]}
}
# to complete the initialization, this must be the first function
# called.  Do so automatically.
take_picture reset
The current pattern for the file format is "./animate.%04d.rgb" but if you need more than 9999 images you should change the 4 to be the maximum number of digits you'll need (and we would like to know if you are making any movies with that many images). For instance, if the files should be called "image.00000.rgb" through "image.12345.rgb" then you can change the pattern like this:
	take_picture format image.%05d.rgb
You can also use this option to specify the directory for the output files. This is important because the images might take up a lot of space and you'll want to use a scratch space with more room.
	take_picture format /scratch/disk2/snap.%04d.rgb
Suppose you wanted to use Raster3D to make the images instead of just taking the snapshot. Before any of the other calls to take_picture, you'll want to do something like:
	take_picture format animate.%04d.r3d
	take_picture method Raster3d
	take_picture exec {render < %s -sgi %s.rgb}
The first line changes the file extension to .r3d so it is less confusing when you see the file name some time in the future. The second line changes the rendering method to Raster3D.

Of course, this just produces Raster3D input file, which needs to be rendered. The third line is used after the Raster3D information is saved to a file so it is automatically converted to an image file. The %s is automatically replaced by the current filename (just like in the Render form) and the whole string is executed by the unix shell. In this case, it calls the Raster3D renderer to convert the ".r3d" file into a ".rgb" file. There are several other options, but the only other one you might use is,
	take_picture reset
which returns all the options to their default values, eg. resets the image number to 0, returns the rendering method to snapshot, etc.

Examples

Now that the take_picture script has been explained, here are a couple more interesting ways to make movies that might prove useful.

Here's something I thought was fun. It starts off with a full surface representation then causes that to fade away and show the underlying tube representation. It works by changing the value of the transparency from 1 to 0. The surface color is "transparent," but since the value is 1, it is really opaque. As the value decreases, the opaque tube in the center appears.

Since this depends on having two different representations, here is the code to set up the example structure. It uses the remote downloading feature of VMD to get the BPTI structure from the PDB FTP server. If this doesn't work, just use any structure you have handy.
	mol pdbload 9pti
	mol modselect 0 top protein
	mol modcolor 0 top index
	mol modstyle 0 top tube

	mol addrep top
	mol modselect 1 top protein
	mol modcolor 1 top resname transparent
	mol modstyle 1 top surf
Now that everything is loaded, here's the script to make the movie
	# take control of the updating
	display update off
	for {set i 1.0} {$i >= 0.0} {set i [expr $i - 0.05]} {
		# change the opaquicity of the transparent colors
		for {set color 17} {$color < 34} {incr color} {
			color change alpha $color [expr $i*$i]
		}
		# and the transparent color scale (66 to 97)
		for {set color 66} {$color < 98} {incr color} {
			color change alpha $color [expr $i*$i]
		}
		# force the update
		display update
		# and take the picture
		take_picture
	}
	# return the alpha values to the default value
	for {set color 17} {$color < 34} {incr color} {
		color change alpha $color 0.3
	}
	# turn the normal updating back on
	display update on
Why is there a "[expr $i*$i]" instead of just using $i ? Because the colors didn't seem to get transparent fast enough. It was purely an esthetic choice.