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:
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
snap.0000.rgb snap.0001.rgb ... snap.0242.rgb i0.rle i1.rle i2.rle i3.rlebut 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.gifAlso, 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) 0005The 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.rgbYou could use a program like xv, ipaste, or display to look at a few of the files and verify they have different images.
convert -delay 10 -loop 4 snap.*.rgb movie.gifThe 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.
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.
# 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 | frameThe 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:| format | \ method | modulo ]} } # to complete the initialization, this must be the first function # called. Do so automatically. take_picture reset
take_picture format image.%05d.rgbYou 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.rgbSuppose 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.
take_picture resetwhich returns all the options to their default values, eg. resets the image number to 0, returns the rendering method to snapshot, etc.
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 surfNow 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 onWhy 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.