-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpdb2gif.pl
More file actions
executable file
·275 lines (210 loc) · 7.83 KB
/
pdb2gif.pl
File metadata and controls
executable file
·275 lines (210 loc) · 7.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/env perl
=head1 NAME
pdb2gif.pl - Reads PDB file and create animated GIF showing the molecule rotating.
=head1 SYNOPSIS
perl pdb2gif.pl <file.pdb> -x -y -steps 30 -secs 5 -size 200x200 -r rasmol-classic
=head1 DESCRIPTION
Reads the given PDB file and uses Rasmol and ImageMagick to create an animated GIF of the molecule rotating around on or more axes. Uses the "cartoon" representation of Rasmol with the color by "group" option. The number of axes about which the molecule is rotated can be selected, the number of frames to generate as well as the total duration of the animation are configurable.
=head1 OPTIONS
=head2 -verbose | -v
Print extra debugging information.
=head2 -help | -h | -?
Print this help.
=head2 -x | -y | -z
Which axes of rotation to enable. Any combination of -x -y or -z may be enabled. Rotation is always in the positive direction about the axes. See the Rasmol documentation for further information.
=head2 -size
The size of the output image file. Defaults to 150x150.
=head2 -steps
Number of frames (pictures) in the final animation file. Default 30 frames/steps.
=head2 -seconds | -secs
Number of seconds for the complete animation to run. This simply inserts larger pauses between displays of the frames, it does not make the animation appear "smoother". For that increase the "-steps" option. Default 5 seconds.
=head2 -rasmol | -r
Rasmol program, if it's not in your PATH.
NB if using a newer linux, you might need to pass
-r rasmol-classic
here, as the newer versions seem to handle scripting differently.
=head1 BUGS
o Rasmol does not allow GIF file to be created with a given size. So, all of the files have to be resized as they are processed into the animation. This slows the program significantly.
o Reducing the bitdepth of the generated GIFs may improve performance.
o GIF transparency doesn't seem to work correctly, even with the 'set transparent' option set in Rasmol. ImageMagick can make a color transparent during subsequent conversion. The presents the problem, that animations created from images containing transparent colors don't clear the display between renderings of frames, which results in a blur. Figuring out how to execute some sort of 'clear' between frames in the animation would allow images with black transparent to save on file size.
o Rounding causes problems, such that the number of frames doen't cause a complete rotation back to the starting frame, depending on the number of 'steps' chosen. Sometimes it works, sometimes it doesn't. Currently an empirically derived error estimator is being used, but it's not clear whether this is sufficient.
=head1 REVISION
$Id: pdb2gif.pl,v 1.4 2005/01/22 11:43:26 uid1343 Exp $
=cut
################################################################################
use strict;
use warnings;
use Getopt::Long;
use File::Spec;
# Default command line options
my %opts = (verbose => 0);
GetOptions(\%opts,
'verbose|v',
'help|h|?',
'size=s',
'steps=s',
'seconds|secs=s',
'rasmol|r=s',
'x',
'y',
'z',
) or usage();
# Show help if command line args. weren't what was expected
usage() if $opts{'help'};
usage() unless @ARGV;
$::VERBOSE = $opts{'verbose'};
my $rasmol = $opts{'rasmol'} || 'rasmol';
# Default size of output image
my $size = $opts{'size'} || "150x150";
# Number of seconds before the GIF repeats from 1st frame again
my $secs = $opts{'seconds'} || 5;
# Number of frames in the final animtion
my $steps = $opts{'steps'} || 30;
# Number of axes of rotation
my $axes = 0;
map {$axes++ if defined $opts{$_} } qw(x y z);
$axes or usage();
# Number of degrees to reach the next step/frame, i.e. size of each rotation
# TODOBUG
#my $degrees = (($axes > 1 ? 540.0 : 360.0) / $steps) / $axes;
my $degrees = ((180.0 + $axes * 180.0) / $steps) / $axes;
# Time-delay (pause) for each frame of the animation
my $delay = $secs * (100.0 / $steps);
# PDB file to process
my $file = shift;
$file = File::Spec->rel2abs($file);
die "File not found: $file\n" unless -e $file;
# The parameter could be a PDB ID or the path to a PDB file
#$file = pdb_file($file) unless -f $file;
sub usage {
system("pod2text $0");
exit 1;
}
my $tmpdir = `mktemp -d -t pdb2gif.XXXXX` || '.';
chomp $tmpdir;
print STDERR "tmpdir:$tmpdir:" if $::VERBOSE;
# Save current working directory
my $pwd = $ENV{PWD};
chdir $tmpdir or
die("Cannot chdir to $tmpdir ($!)\n");
`cp $file .`;
$file = <$tmpdir/*>;
print "size:$size:secs:$secs:steps:$steps:axes:$axes:degrees:$degrees:" .
"delay:$delay:file:$file:\n" if $::VERBOSE;
################################################################################
# Basic Rasmol commands
my $script = <<EOF;
#background [0,0,0]
#set ambient 40
#set specular on
#set specpower 8
#reset
#slab off
#set axes off
#set boundingbox off
#set unitcell off
#set bondmode and
#dots off
# Avoid Colour Problems!
#select all
#colour bonds none
#colour backbone none
#colour hbonds none
#colour ssbonds none
#colour ribbons none
#colour white
# Atoms
#select all
#spacefill off
# Bonds
wireframe off
# Ribbons
#set strands 5
#set cartoon on
#set cartoon 100
#ribbons 720
# Backbone
#select all
#backbone off
# Labels
#labels off
# Monitors
#monitors off
#ssbonds off
#hbonds off
cartoons
colour chains
set write on
set transparent on
EOF
################################################################################
# Pipe script into rasmol
open RASMOL, "|$rasmol -nodisplay >/dev/null" or
#open RASMOL, "|$rasmol " or
die "Can't start rasmol. Is it in your PATH?\n$!\n$@\n";
# Display axes, when debugging
print RASMOL "set axes on\n" if $::VERBOSE;
# Clear display and load PDB file
# print RASMOL "load pdb \"$file\"\n";
print RASMOL "load \"$file\"\n";
# Send basic script commands (coloring, etc.)
print RASMOL $script;
# TODOBUG
# Don't know why this is necessary, but as the number of steps increase, the
# the number of extra frames in the animation goes up, but only when more than
# one axis of rotation is selected.
# The following mesurements have been made:
#
# $axes | $steps | $error +/- 1
# 1 10 0
# 1 20 0
# 1 50 0
# 2 15 1
# 2 35 2
# 2 65 4
# 2 85 4
# 3 35 5
# 3 50 8
# 3 65 10
# 3 85 12
my $error = 0;
$error = $steps / 15 if $axes == 2;
$error = $steps / 7 if $axes == 3;
my $imgbase = "$file.$$.";
my $imgext = ".ppm";
for (1 .. $steps - $error ) {
$_ = sprintf "%03d", $_;
# Save one static image (one frame of animation)
# print RASMOL "write $file.$$.$_.gif\n";
print RASMOL "write ${imgbase}${_}${imgext}\n";
# Rotate in all the necessary directions (x y z) by the necessary number of
# degrees
for (qw(x y z)) {
print RASMOL "rotate $_ $degrees\n" if $opts{$_};
}
}
print RASMOL "exit\n";
close RASMOL;
print STDERR "Converting $steps files ...\n";
# First convert the GIFs to the smaller PNG format, resizing along the way
my $convert =
"for i in ${imgbase}*${imgext};" .
"do convert -resize $size \$i \$i.png;" .
"done";
#print STDERR "$convert\n";
#`$convert`;
# Now feed the smaller files back in, to be converted to an animated GIF
# $convert = "convert -delay $delay $file.$$.*png $file.$$.gif";
#$convert = "convert -delay $delay ${imgbase}*${imgext} ${imgbase}gif";
$convert = "convert -resize $size -delay $delay ${imgbase}*.ppm ${imgbase}gif";
print "$convert\n" if $::VERBOSE;
`$convert`;
# Delete static intermediate GIF files that were created
print STDERR "Cleaning up intermediate files ... \n" if $::VERBOSE;
`rm $file.$$.*.*` unless $::VERBOSE;
print "$file.$$.gif\n";
# Return to start dir.
chdir $pwd or
print STDERR "Cannot chdir to $pwd ($!)" and exit;
exit;
################################################################################