forked from gasperTheGhost/covid-solver-unix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
covid-solver.sh
executable file
·463 lines (459 loc) · 16.8 KB
/
covid-solver.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
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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
#!/bin/bash
#
cd "${0%/*}"
exec > >(tee -ia last_run.log) 2>&1
start_time=$(date +%s)
#
# This is prototype script for OPENSCIENCE project
# Prototipna skripta za Citizen Science COVID-19 drug search
# 30.3.2020
#
ziptest=$(zip --help)
if [[ "$ziptest" = *"zip: command not found"* ]]; then
echo "zip command not found, please install it from the appropriate"
echo "package manager, then restart the software."
echo "Exiting..."
exit
fi
#
#
#
Version="<Version Tag>" # Same as in GitHub
operatingsys="<mac/linux>" # Only valid options are mac or linux
github_user="<GitHub User>"
github_repo="<GitHub Repo>"
#
FirstLoopFinished=0
#
# Set variables according to selected OS
#
versionCheckAPI="https://api.github.com/repos/$github_user/$github_repo/releases/latest"
if [[ $operatingsys = "mac" ]]; then
threadCheckCommand="sysctl -n hw.ncpu"
machineid=$(ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s\n", line[4]); }')
elif [[ $operatingsys = "linux" ]]; then
threadCheckCommand="nproc"
machineid=$(cat /etc/machine-id)
else
echo "Operating system not specified or invalid!"
echo "Exiting..."
exit
fi
# Set environment variables
export RBT_ROOT="$PWD/RxDock"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$RBT_ROOT/lib"
export PATH="$PATH:$RBT_ROOT/bin"
export PERL5LIB="$RBT_ROOT/lib:$PERL5LIB"
export RBT_HOME="$PWD"
# Set API key var
apikey="<API Key>"
if [[ "$1" = "-test" ]]; then
server="<Test API URL>" # DO NOT END WITH A SLASH!!!!!!!!!!!
else
server="<Production API URL>" # DO NOT END WITH A SLASH!!!!!!!!!!!
fi
#
# Check for updates
#
auto_update() {
if [[ $FirstLoopFinished -eq 1 ]]; then
echo "Saving settings..."
echo $parallels > settings.update
echo $savdel >> settings.update
echo $operatingsys >> settings.update
echo $niceNum >> settings.update
echo $autoupdate >> settings.update
fi
echo "Attempting auto-update..."
mv lib/update.sh update.sh
chmod +x update.sh
/bin/bash update.sh $github_user $github_repo
exit
}
version_check() {
if ! [ -e no.update ]; then
currentVersion="$(curl -s $versionCheckAPI | grep tag_name | cut -d '"' -f 4)"
if ! [[ $Version = $currentVersion ]] && ! [[ $currentVersion = *DOCTYPE* ]]; then
echo "Newer version of script found."
if [[ "$autoupdate" = "true" ]]; then
auto_update
else
while true; do
read -t 10 -p "Would you like to update? ([Y]es/[n]o) " update_confirmation
case $update_confirmation in
[Yy]* ) auto_update; break;;
[Nn]* ) main_func; break;;
* ) echo "Please answer yes or no.";;
esac
done
fi
elif [[ $currentVersion = *DOCTYPE* ]]; then
echo "Error checking for updates!"
echo "Continuing..."
elif [[ $Version = $currentVersion ]]; then
echo "You are running the newest version of the script"
fi
if [ -e update.sh ]; then
rm -f update.sh
fi
else
echo "Update block enabled, skipping check..."
fi
}
legal_disc() {
clear
echo "# Copyright Notice and Disclaimer"
echo "# ==============================="
echo "# This software (COVID Solver, win, linux, mac versions) along with its"
echo "# source code is released under the terms of the"
echo "# GNU General Public License version 3 (GPL v3)."
echo "# A full copy of the GNU General Public License can be found at:"
echo "# <https://www.gnu.org/licenses/>."
echo "#"
echo "# Permission to use, copy, modify and distribute"
echo "# versions of this software and its documentation for any purpose and"
echo "# without fee is hereby granted, provided that the above copyright"
echo "# notice appear in all copies and that both the copyright notice and"
echo "# this permission notice appear in supporting documentation, and that"
echo "# the name(s) of the author(s) not be used in advertising or publicity"
echo "# pertaining to distribution of the software without specific, written"
echo "# prior permission."
echo "#"
echo "# This program is distributed in the hope that it will be useful,"
echo "# but WITHOUT ANY WARRANTY; without even the implied warranty of"
echo "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
echo "# GNU General Public License for more details."
echo "#"
echo "# THE AUTHORS (Žan Pevec, Gašper Tomšič, Marko Jukić, Črtomir Podlipnik"
echo "# Boštjan Laba and supporting organisations at the COVID.si project)"
echo "# DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,"
echo "# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN"
echo "# NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR"
echo "# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF"
echo "# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR"
echo "# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR"
echo "# PERFORMANCE OF THIS SOFTWARE."
echo "# ----------------------------------------------------------------------"
echo "# Running this software means you have read the licence in full conscience"
echo "# and agree to the terms described above."
read -p "Press enter to continue running the software..."
clear
}
#
# Declare main function
#
main_func() {
#
# STEP 0. CHECK UPDATES IF TWELVE HOURS HAVE PASSED
#
if ! [[ $FirstLoopFinished -eq 0 ]]; then
let time_elapsed=$end_time-$start_time
fi
if [[ $time_elapsed -gt 43200 ]]; then
version_check
start_time=$(date +%s)
fi
#
# STEP 1. CHECK THE COUNTER
#
# Get target counter value
t=$(curl -s --request POST -d "apikey=$apikey" -d "ClientGUID=$machineid" -d "ThreadCount=$parallels" -d "Client=$operatingsys-CLI-$Version" $server/target)
if [[ $t -eq $t ]]; then
let tnum=$t
else
echo "Error getting current target number!"
echo "Retrying in 5 seconds or enter A to abort"
read -t 5 terror
case $terror in
[Aa]*) exit;;
*) main_func;;
esac
fi
# Check if there's any targets left on server
while [[ $tnum -eq -1 ]]; do
echo "Ran out of targets for docking"
echo "We are constantly adding targets to our database"
echo "The program will continue checking for new targets every 30mins"
read -t 1800 -p "Press T to [t]erminate script or enter to recheck now..." empty
case $empty in
[Tt]*) rm -rf TARGET_PRO_$tnum.mol2 TARGET_REF_$tnum.sdf $fx *.as *.prm T$tnum-P$cnum; exit;;
*) echo "Rechecking..."; main_func;;
esac
done
# Get structure counter value
while :; do
c=$(curl -s --request POST -d "apikey=$apikey" -d "ClientGUID=$machineid" -d "ThreadCount=$parallels" -d "Client=$operatingsys-CLI-$Version" $server/$tnum/counter)
if [[ $c -eq $c ]]; then
let cnum=$c
break
else
echo "Error getting current package number!"
echo "Retrying in 5 seconds or enter A to abort"
read -t 5 cerror
case $cerror in
[Aa]*) exit;;
*) main_func;;
esac
fi
done
# Check if there's any structures left on server
while [[ $cnum -eq -1 ]]; do
echo "Ran out of structures to calculate"
echo "We are constantly adding structures to our database"
echo "The program will continue checking for new structures every 30mins"
read -t 1800 -p "Press T to [t]erminate script or enter to recheck now..." empty
case $empty in
[Tt]*) rm -rf TARGET_PRO_$tnum.mol2 TARGET_REF_$tnum.sdf $fx *.as *.prm T$tnum-P$cnum; exit;;
*) echo "Rechecking..."; main_func;;
esac
done
fx="3D_structures_$cnum.sdf"
#
# STEP 2. DOWNLOAD A PACKAGE WITH LIGANDS
#
while true; do
curl -s --request POST -d "apikey=$apikey" -d "ClientGUID=$machineid" -d "ThreadCount=$parallels" -d "Client=$operatingsys-CLI-$Version" $server/$tnum/file/down/$cnum/?zipFlag=1 --output $fx.zip
health=$(head -n 1 $fx.zip) # Check if file is healthy
if [[ -e $fx.zip ]] && ! [[ "$health" = *DOCTYPE* ]]; then
unzip -o $fx.zip
rm -f $fx.zip
break # Continue if file is healthy
else
echo "Error downloading structure!"
read -t 5 -p "Retrying in 5 sec... [A]bort " hp
case $hp in
[Aa]*) rm -rf TARGET_PRO_$tnum.mol2 TARGET_REF_$tnum.sdf $fx *.as *.prm T$tnum-P$cnum; exit;;
*) echo "Retrying...";;
esac
fi
done
#
# STEP 3. DOWNLOAD TARGET
#
if ! [ -e TARGET_REF_$tnum.sdf -a -e TARGET_PRO_$tnum.mol2 -a -e TARGET_$tnum.as -a -e TARGET_$tnum.prm -a -e htvs.ptc ]; then
rm -f TARGET_PRO_$tnum_old.mol2 TARGET_REF_$tnum_old.sdf TARGET_$tnum_old.* htvs.ptc
while true; do
curl -s --request POST -d "apikey=$apikey" -d "ClientGUID=$machineid" -d "ThreadCount=$parallels" -d "Client=$operatingsys-CLI-$Version" $server/$tnum/file/target/archive --output TARGET_$tnum.zip
health=$(head -n 1 TARGET_$tnum.zip) # Check if file is healthy
if [ -e TARGET_$tnum.zip ] && ! [[ "$health" = *DOCTYPE* ]]; then
unzip -o TARGET_$tnum.zip
rm -f TARGET_$tnum.zip
break # Continue if file is healthy
else
echo "Error downloading target!"
read -t 5 -p "Retrying in 5 sec... [A]bort " hp
case $hp in
[Aa]*) rm -rf TARGET_PRO_$tnum.mol2 TARGET_REF_$tnum.sdf $fx *.as *.prm T$tnum-P$cnum htvs.ptc; exit;;
*) echo "Retrying...";;
esac
fi
done
fi
#
# STEP 4. RUNNING DOCKING WITH RxDock
#
echo "Docking package $cnum into target $tnum"
mkdir -p output
outfx="output/OUT_T$tnum"'_'"$cnum"
target_prm=TARGET_$tnum.prm
# Split the compound file for multiple threads
mkdir -p T$tnum-P$cnum/temp
RxDock/splitMols $cnum $parallels $PWD/T$tnum-P$cnum/temp #| tee split.log
rm 3D_structures_$cnum.sdf
# Run RxDock
unix=1
for file in T$tnum-P$cnum/temp/temp*sdf
do
if ! [[ $(tail -1 $file) = '$$$$' ]]; then
echo '$$$$' >> $file
fi
RxDock/bin/to_unix $file T$tnum-P$cnum/temp/unix_$unix.sd
rm -f "$file"
let unix=$unix+1
done
unix=1
for file in T$tnum-P$cnum/temp/unix*sd
do
nice -n $niceNum RxDock/bin/rbdock -r $target_prm -p dock.prm -f htvs.ptc -i $file -o T$tnum-P$cnum/temp/$unix\_out &
pids+=" $!"
let unix=$unix+1
done
wait $pids
cat T$tnum-P$cnum/temp/*_out* > $outfx.sdf
#
# STEP 5. UPLOAD RESULTS TO SERVER
#
if [ -s "$outfx.sdf" ]; then
echo "Uploading package $cnum for target $tnum"
zip - $outfx.sdf | curl -s --request POST -F "data=@-" -F "apikey=$apikey" -F "ClientGUID=$machineid" -F "ThreadCount=$parallels" -F "Client=$operatingsys-CLI-$Version" $server/$tnum/file/$cnum/?zipFlag=1
else
echo "Error: Writing output failed..."
fi
#
# STEP 6. CLEANUP
#
rm -rf $fx T$tnum-P$cnum
if [ "$savdel" = "d" ]; then
rm -f $outfx.sdf
fi
end_time=$(date +%s)
FirstLoopFinished=1
redo
} # End main function
redo() {
read -t 10 -p "Would you like to calculate the next package? (Y/n) " yn
case $yn in
[Yy]* ) tnum_old=$tnum; main_func;;
[Nn]* ) rm -rf TARGET_PRO_$tnum.mol2 TARGET_REF_$tnum.sdf $fx *.as *.prm T$tnum-P$cnum htvs.ptc; exit;;
* ) main_func;;
esac
main_func
}
#
# User input dialogue
#
start_dialogue() {
echo "Welcome to COVID Solver $Version for Citizens Science!"
echo "Your Client ID is: $machineid"
# Check threads
threads=$($threadCheckCommand)
if [ "$threads" -gt 0 ]; then
echo "Your current machine has $threads available threads"
while true; do
read -p "Please enter how many threads you would like this software to use (1-$threads/[A]ll) " thread_count
if [ "$thread_count" = "A" ] || [ "$thread_count" = "All" ] || [ "$thread_count" = "all" ] || [ "$thread_count" = "a" ]; then
parallels="$threads"
break;
elif [ "$thread_count" = "" ]; then
parallels="$threads"
break;
elif ! [ "$thread_count" -gt "$threads" ] && [ "$thread_count" -gt 0 ]; then
parallels="$thread_count"
break;
else
echo "Please enter a valid number of cores"
fi
done
else
while true; do
read -p "Cannot determine available threads, would you like to continue with all processing power? (Y/n) " yn
case $yn in
[Yy]* ) parallels=""; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
fi
if [ $FirstLoopFinished -eq 0 ]; then
while true; do
echo "You can set a priority for this software, to make it less obtrusive"
read -p "Enter a number between -20 (highest) and 19 (lowest priority); default is 0 " nice_level
if [ "$nice_level" -gt -21 ] && [ "$nice_level" -lt 20 ]; then
if [ "$nice_level" -lt 0 ] && [ "$usr_root"="true" ] || ! [ "$nice_level" -lt 0 ]; then
niceNum=$nice_level
break
elif [ "$nice_level" -lt 0 ] && [ "$usr_root"="false" ]; then
echo "Negative nice value can only be set with root permissions!"
echo "Setting nice to 0"
niceNum=0
break
fi
else
niceNum=0
break
fi
done
while true; do
read -p "Would you like to keep the RxDock output files? ([Y]es/[n]o) " savdel
case $savdel in
[Yy]* ) savdel="s"; main_func; break;;
[Nn]* ) savdel="d"; main_func; break;;
* ) echo "Please answer yes or no.";;
esac
done
fi
}
#
# *** PROGRAM START *** #
#
# Trap Ctrl-C
#
ctrlC() {
echo "Terminating all RxDock instances..."
for process in "${pids[@]}"; do
killall rbdock >> last_run.log
done
rm -rf $fx T$tnum-P$cnum
if [ "$savdel" = "d" ]; then
rm -f $outfx.sdf
fi
rm -rf TARGET_PRO_$tnum.mol2 TARGET_REF_$tnum.sdf $fx *.as *.prm T$tnum-P$cnum htvs.ptc *.zip
exit
}
trap ctrlC SIGINT
version_check
end_time=
# Check if user is root for negative nice
if ! [[ "$EUID" -eq 0 ]]; then
echo "Script is running as root!"
usr_root="true"
else
usr_root="false"
fi
# Check if script was run by update.sh
if [ -e settings.update ]; then
FirstLoopFinished=1
parallels="$(head -n 1 settings.update)"
savdel="$(sed '2q;d' settings.update)"
niceNum="$(sed '3q;d' settings.update)"
autoupdate="$(sed '4q;d' settings.update)"
rm -f settings.update
main_func
# Check if theres a config file
elif [ -e rxdock.config ]; then
echo "" > last_run.log
legal_disc
parallels="$(cat rxdock.config | grep threads | cut -d '=' -f 2)"
if [[ "$parallels" =~ ^[0-9]+$ ]] && ! [[ "$parallels" -gt $(threadCheckCommand) ]]; then
if [[ "$(cat rxdock.config | grep save_output | cut -d '=' -f 2)" = [Tt][Rr][Uu][Ee] ]]; then
savdel="s"
else
savdel="d"
fi
if [[ "$(cat rxdock.config | grep auto_update | cut -d '=' -f 2)" = [Tt][Rr][Uu][Ee] ]]; then
autoupdate="true"
else
autoupdate="false"
fi
nice_level="$(cat rxdock.config | grep nice_level | cut -d '=' -f 2)"
if [[ "$nice_level" -gt -21 ]] && [[ "$nice_level" -lt 20 ]]; then
if [[ "$nice_level" -lt 0 ]] && [[ "$usr_root"="true" ]] || ! [[ "$nice_level" -lt 0 ]]; then
niceNum=$nice_level
main_func
elif [[ "$nice_level" -lt 0 ]] && [[ "$usr_root"="false" ]]; then
echo "Negative nice value can only be set with root permissions!"
echo "Setting nice to 0"
niceNum=0
main_func
fi
else
niceNum=0
main_func
fi
else
parallels="$(threadCheckCommand)"
if [[ "$parallels" =~ ^[0-9]+$ ]]; then
main_func
else
echo "Error in config file!"
exit
fi
fi
else
echo "" > last_run.log
legal_disc
start_dialogue
fi
#
#
# EoF