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:
There are many aspects of your research which might benefit from 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 could also show the results of an MD simulation or change transparency parameters to dissolve a molecular surface slowly from the display. These examples will be shown below, and there are are many other possible movies you might want to make.
Once you've come up with a concept, you'll need some way to schedule the sequence of events in your movie. You could try to do it by hand, but that would get very tedious. Another alternative is to record a log file and play it back, but this is rarely smooth. The best bet is to come up with a script that does what you want automatically.
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 then use one of several external programs to produce the movie.
These programs usually require that the image file names fit the
pattern prefix
index
suffix
where the prefix and suffix don't
change, and the
index
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 ... i9.rle i10.rle (i.e. 1 digit to 2)
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, ...." since alphabetically 1 < 10 < 2.
You can write files from VMD in this format using 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 lets assume there are 4. Then an example of
the format command is:
vmd > format "%04d" 5
Info) 0005
The following script adds the code needed to keep track of successive filenames. You can still see the original example in it, but there are four more lines added to keep track 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 and then type 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.0003.rgb snap.0007.rgb snap.0011.rgb snap.0015.rgb
You could also use programs like display, xv, or ipaste to look at a few of the files and verify that 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 so that you may 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 movieplayer on the SGIs or xanim. The latter is available on most X-based machines. That's it, you've made a movie!
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 convert from the ImageMagick tools.
convert -delay 10 -loop 4 snap.*.rgb movie.gif
This 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 image 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, and you should see the rotating image.
The downfall with this image is that 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 could start the whole process over again but with a smaller display.
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. The 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 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 code to take the pictures and save them 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, the current filename, etc. Luckily there is a better way. 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. The default setting of take_picture uses the snapshot renderer option, but it can be made to 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 also be changed if necessary. Below is the script itself, followed by 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 <number>| format <string> | \
method <renderer> | modulo <number>]}
}
# 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 should change the pattern as follows:
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 a Raster3D input file, which itself still needs to be rendered. The third line is used after the Raster3D information is saved to a file so that it will be 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 options to their default values, eg. resets the image number to 0, returns the rendering method to snapshot, etc.
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 that fades away to show an 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.
# if this doesn't work, use one of your own structures
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 opacity of the transparent colors
for {set color 17} {$color < 34} {incr color} {
color change alpha $color [expr $i*$i]
}
# and of the color scale
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
}
# for the color scale as well
for {set color 66} {$color < 98} {incr color} {
color change alpha $color 0.3
}
# turn the normal updating back on
display update on
Experienced script writers may ask why we used "[expr $i*$i]" instead of $i ? This was purely an esthetic choice based on our belief that the colors were not becoming transparent quickly enough.