-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmake_video_pymol.sh
executable file
·173 lines (122 loc) · 4.73 KB
/
make_video_pymol.sh
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
#!/bin/bash
#check that five arguments have been given
if [ "$#" -ne 6 ] && [ "$#" -ne 7 ]
then
echo "usage: $0 video_width video_height frame_rate path_with_pdb_files destination_file_name_and_path video_codec [pymol_command_file]"
exit -1
fi
#arguments:
#PDB_PATH is where to find the PDBs which must begin 'tmp_froda_'.
#DEST_FILE is the name (and location) of the video to generate
#OTIONAL_COMMAND_FILE is optional, and allows extra instructions to be given to pymol before generation of frames
VIDEO_WIDTH=$1
VIDEO_HEIGHT=$2
FPS=$3
PDB_PATH=$4
DEST_FILE=$5
VIDEO_CODEC=$6
OTIONAL_COMMAND_FILE=$6
TMP_PATH=$PDB_PATH/pymol_temp
#calculate how many seconds each frame lasts, rounded to ensure ffmpeg does the right thing
FRAME_LENGTH=$(awk -v fps=$FPS 'BEGIN { printf "%.6f", 1.0 / fps }')
#make a temporary folder for the temporary files
rm -rf $TMP_PATH
mkdir $TMP_PATH
#command file to give to pymol, to generate all necessary frames (in png format)
CMD_FILE=$TMP_PATH/pymol.py
PDB_FILES=$PDB_PATH/tmp_froda_*.pdb
#array of all pdb files
arr=(`ls $PDB_FILES`)
###
echo "make_video_pymol.sh: generating command file to give pymol - ${PDB_PATH}"
####
#setting up the pymol visuals
echo 'from pymol import cmd' > $CMD_FILE
echo 'import sys' >> $CMD_FILE
echo "cmd.load(\"${arr[0]}\", 'original')" >> $CMD_FILE
echo 'cmd.spectrum()' >> $CMD_FILE
echo "cmd.viewport($VIDEO_WIDTH, $VIDEO_HEIGHT)" >> $CMD_FILE
echo 'cmd.hide()' >> $CMD_FILE
echo 'cmd.show("cartoon")' >> $CMD_FILE
echo 'cmd.bg_color("grey")' >> $CMD_FILE
#if an optional file with extra instructions for pymol has been included, use it
if [ "$OPT_SETTINGS_FILE" != "" ]
then
cat $OTIONAL_COMMAND_FILE >> $CMD_FILE
fi
echo "cmd.save(\"$PDB_PATH/cartoon.pse\")" >> $CMD_FILE
COUNTER=0
for i in `ls $PDB_FILES`
do
#id of the next frame (png file) to generate
id=$(printf "%08d" $COUNTER)
#copy the original (initial) pdb to mov
echo 'cmd.copy("mov", "original")' >> $CMD_FILE
#load the next pdb into mov
echo "cmd.load(\"$i\", 'mov')" >> $CMD_FILE
#display every currently loaded object in cartoon form
echo 'cmd.show("cartoon")' >> $CMD_FILE
#hide (undisplay) the original (initial) pdb
echo 'cmd.hide("everything", "original")' >> $CMD_FILE
#go to frame 2 of mov (the frame containing the pdb to be rendered next)
echo "cmd.frame(2)" >> $CMD_FILE
#render the next frame (png file)
echo "cmd.mpng(\"$TMP_PATH/$id\", 2, 2, 0, 0, 2, 0, $VIDEO_WIDTH, $VIDEO_HEIGHT)" >> $CMD_FILE
#remove (unload) mov (including the pdb just used)
echo 'cmd.delete("mov")' >> $CMD_FILE
((COUNTER+=1))
done
echo 'cmd.quit()' >> $CMD_FILE
###
echo "make_video_pymol.sh: running pymol with generated command file to create frames (png files) - ${PDB_PATH}"
###
#run pymol without the GUI, suppressing the startup output, giving it the command file to run
( set -x ; pymol -c -q $CMD_FILE )
###
echo "make_video_pymol.sh: generating concat file to give ffmpeg - ${PDB_PATH}"
###
#file to give to ffmpeg, stating ordering and repeating of frames (1s freezeframe, forwards, 1s freezeframe, backwards)
CONCAT_FILE=$TMP_PATH/concat
#hold the first png file for one second
echo "file $TMP_PATH/000000000002.png" > $CONCAT_FILE
echo "duration 1" >> $CONCAT_FILE
#use each png file in forward order, holding each for the length of a frame
((COUNTER-=2))
for ((i=1; i<=COUNTER; i++))
do
id=$(printf "%08d" $i)
echo "file $TMP_PATH/${id}0002.png" >> $CONCAT_FILE
echo "duration $FRAME_LENGTH" >> $CONCAT_FILE
done
#hold the last png file for one second
echo "file $TMP_PATH/$(printf "%08d" $((COUNTER+1)))0002.png" >> $CONCAT_FILE
echo "duration 1" >> $CONCAT_FILE
#use each png file in reverse order, holding each for the length of a frame
for ((i=COUNTER; i>=0; i--))
do
id=$(printf "%08d" $i)
echo "file $TMP_PATH/${id}0002.png" >> $CONCAT_FILE
echo "duration $FRAME_LENGTH" >> $CONCAT_FILE
done
###
echo "make_video_pymol.sh: running ffmpeg with generated concat file to create video from frames using $VIDEO_CODEC codec - ${PDB_PATH}"
###
#encode video from frames (png files) using ffmpeg and the specified codec
if [ "$VIDEO_CODEC" == "mp4" ]
then
(
set -x
ffmpeg -hide_banner -loglevel warning -f concat -safe 0 -i $TMP_PATH/concat -framerate $FPS -r $FPS -c:v libx264 -pix_fmt yuv420p -crf 20 -maxrate 6M -bufsize 1M -threads 1 -movflags faststart -y ${DEST_FILE}
)
fi
if [ "$VIDEO_CODEC" == "hevc" ]
then
(
set -x
ffmpeg -hide_banner -loglevel warning -f concat -safe 0 -i $TMP_PATH/concat -framerate $FPS -r $FPS -c:v libx265 -pix_fmt yuv420p -crf 25 -maxrate 6M -bufsize 1M -threads 1 -movflags faststart -y ${DEST_FILE}
)
fi
#set the correct permissions
chmod 744 $DEST_FILE
#remove all the temporary files/folders made in this script, leaving only the video
rm -rf $TMP_PATH