JWS-112 Bumping version of Mafft to version 7.310.
[jabaws.git] / binaries / src / mafft / core / mafftash_premafft.tmpl
1 #!/usr/bin/perl
2
3 #####################################################################
4 # Author:  KM Amada (kmamada@ifrec.osaka-u.ac.jp)
5 #
6 # Ver. Date      Changelog
7 #####################################################################
8 # 1.0  07.26.13  Initial release
9 # 2.0  09.03.13  Added extensive warnings and error messages
10 # 3.0  10.28.13  Fix for retrieving large files. Added STDERR logs
11 # 3.1  11.08.13  Added LWP failsafe. Made hat3 not a required output
12 # 3.2  12.08.14  Removed 5-char restriction for own structure files
13 #
14 #####################################################################
15
16 use strict;
17 use Getopt::Long;
18 use File::Path qw(make_path remove_tree);
19 use LWP::Simple;
20 use LWP::UserAgent;
21
22 # to prevent error 'Header line too long (limit is 8192)' [v3.1]
23 use LWP::Protocol::http;
24 push(@LWP::Protocol::http::EXTRA_SOCK_OPTS, MaxLineLength => 0);
25
26
27
28 my $BASEURL = "http://sysimm.ifrec.osaka-u.ac.jp/MAFFTash/REST/service.cgi/premafft";
29
30 my ( $WORKDIR, $PDBLIST, $OWNLIST, $HAT3FILE, $INSTRFILE );
31
32 GetOptions
33 (
34     'd=s' => \$WORKDIR,
35     'p=s' => \$PDBLIST,
36     'o=s' => \$OWNLIST,
37     'h=s' => \$HAT3FILE,
38     'i=s' => \$INSTRFILE,
39 );
40
41 print STDERR "[MAFFTash-premafft]\n";
42
43 # set temp directory
44 my $TMP = "/tmp/mapremafft$$";
45 make_path($TMP) unless -d $TMP;
46
47
48
49 ######
50 # validation
51 &help("Required parameter : atleast one of either '-p' or '-o'") unless ( defined $PDBLIST || defined $OWNLIST);
52 &help("Required parameter : '-d'") if defined $OWNLIST && ! defined $WORKDIR;
53
54 $HAT3FILE = "hat3" unless defined $HAT3FILE;
55 $INSTRFILE = "instr" unless defined $INSTRFILE;
56 chop $WORKDIR if defined $WORKDIR && $WORKDIR =~ m/\/$/g;
57
58
59 ######
60 # prepare inputs
61 print STDERR "Preparing inputs for service request...\n";
62
63 my @files = ();
64 push(@files, "strweight" => "0.5");
65 push(@files, "premafft" => "1");
66
67
68 # pdb entries
69 if ( defined $PDBLIST )
70 {
71     print STDERR "PDB List defined!\n";
72     &bail("Error: Input file $PDBLIST does not exists!") unless -e $PDBLIST;
73     my $listfile = "$TMP/pdblist.inp";
74
75
76     open(INPF,"<$PDBLIST") or &bail("Error: Cannot open file $PDBLIST for reading!");
77     open(OUTF,">$listfile") or &bail("Error: Cannot open temporary file $listfile for writing!");
78
79     while(<INPF>)
80     {
81         chomp;
82         if ( /^(\w{5})$/ )
83         {
84             print OUTF ">PDBID\n$1\n";
85         }
86     }
87
88     close OUTF;
89     close INPF;
90
91     push(@files, "inputfile" => ["$listfile"]);
92 }
93
94
95
96 # upload own structures
97 my %ownids = ();
98
99 if ( defined $OWNLIST  )
100 {
101     print STDERR "OWN List defined!\n";
102     &bail("Error: Input file $OWNLIST does not exists!") unless -e $OWNLIST;
103
104
105     open(OWNINPF,"<$OWNLIST") or &bail("Error: Cannot open file $OWNLIST for reading!");
106
107     while(<OWNINPF>)
108     {
109         chomp;
110
111         if ( /^(\S+)$/ )
112         {
113             my $fileref = "$WORKDIR/$1.pdb";
114
115             unless (-e $fileref)
116             {
117                 close OWNINPF;
118                 &bail("Error: File $fileref does not exists!");
119             }
120
121             push(@files, "inputownfile[]" => ["$fileref"]);
122             $ownids{$1} = 1;
123         }
124     }
125
126     close OWNINPF;
127 }
128
129
130
131 ######
132 # start rest service
133 print STDERR "Sending service request...\n";
134
135 my $browser = LWP::UserAgent->new;
136 $browser->timeout(0);
137
138
139 # post: running a mafftash job
140 my $postResponse = $browser->post( $BASEURL, \@files, 'Content_Type' => 'form-data' );
141 &bail(sprintf("[%d] %s\n", $postResponse->code, &parseError($postResponse->content))) unless($postResponse->is_success);
142
143
144 # get response from post request
145 my ($status, $mafftashid) = &parseResponse($postResponse->content);
146
147
148
149 my $MAXTRIES = 3;
150 my $STIMER = 4;
151 my $longtimer = 0;
152
153 print STDERR "Request sent! Waiting for response...[$mafftashid]\n";
154
155
156 # wait for results until it becomes available
157 while(1)
158 {
159     $longtimer = $longtimer <= ($STIMER*3) ? $longtimer+$STIMER : $STIMER;
160     sleep $longtimer;
161
162
163     # get: get results for mafftash job
164     my $getResponse = $browser->get("$BASEURL/$mafftashid");
165
166     if ( $getResponse->is_success )
167     {
168
169         # get response from get request
170         ($status, $mafftashid) = &parseResponse($getResponse->content);
171         next unless ( $status eq "done" );
172
173
174         # if job is finished and ready
175         print STDERR "Results found!\n";
176         my $csfile = "$TMP/checksum.tar.gz";
177         my $try1 = 1;
178
179
180         while(1)
181         {
182             print STDERR "Fetching Results... [Trial $try1]\n";
183
184             if ( is_success(getstore("$BASEURL/getmdlist/$mafftashid", $csfile)) && -e $csfile && -s $csfile )
185             {
186                 # get response from get request
187                 my $checklist = &extractchecksum($csfile);
188                 &bail("Error retrieving list of compressed files!") unless ( scalar %$checklist > 0 );
189
190
191                 foreach my $id ( keys %$checklist )
192                 {
193                     my $checkfile = "$TMP/$id";
194                     my $checkid = $checklist->{$id};
195                     my $try2 = 1;
196
197                     while(1)
198                     {
199                         unlink $checkfile if -e $checkfile;
200
201                         if ( is_success(getstore("$BASEURL/get/$mafftashid/$id", $checkfile)) && -e $checkfile && -s $checkfile )
202                         {
203                             my $hashid = &getchecksum($checkfile);
204                             #print STDERR "[hashid]$hashid [checkid]$checkid\n";
205
206                             if ($hashid ne "" && $hashid ne $checkid )
207                             {
208                                 unlink $checkfile if -e $checkfile;
209                                 &bail("Error retrieving compressed file from server! [Checksum Failed]") if $try2 >= $MAXTRIES;
210                                 $try2++;
211                                 sleep $STIMER;
212                             }
213                             else
214                             {
215                                 last;
216                             }
217                         }
218                         else
219                         {
220                             &bail("Error retrieving compressed file from server!") if $try2 >= $MAXTRIES;
221                             $try2++;
222                             sleep $STIMER;
223                         }
224                     }
225                 }
226
227                 last;
228             }
229             else
230             {
231                 &bail("Error retrieving list of compressed files from server!") if $try1 >= $MAXTRIES;
232                 $try1++;
233                 sleep $STIMER;
234             }
235         }
236
237         last;
238
239     }
240     else
241     {
242         &bail(sprintf("[%d] %s\n", $getResponse->code, &parseError($getResponse->content)));
243     }
244
245 }
246
247
248 # make sure outputs were generated
249 # decompress
250 print STDERR "Assembling final results...\n";
251
252 &backticks("cat $TMP/archive.tar.gz* | tar -zxf - -C $TMP/");
253 &backticks("mv -f $TMP/instr $INSTRFILE") if -e "$TMP/instr";
254 &backticks("mv -f $TMP/hat3 $HAT3FILE") if -e "$TMP/hat3";
255
256 # sometimes no hat3 file is generated [v3.1]
257 #&bail("Error: Output file $HAT3FILE not found!") unless -e $HAT3FILE;
258 &bail("Error: Output file $INSTRFILE not found!") unless -e $INSTRFILE;
259
260
261 # warn if some ownids were ommitted
262 if ( scalar keys(%ownids) > 0 )
263 {
264     my %instrids = ();
265
266     open(INSTRF,"<$INSTRFILE") or &bail("Error: Cannot open file $INSTRFILE for reading!");
267
268     while(<INSTRF>)
269     {
270         chomp;
271
272         if ( /^>\d+_(\S+)$/ )
273         {
274             $instrids{$1} = 1;
275         }
276     }
277
278     close INSTRF;
279
280     foreach my $id ( keys %ownids )
281     {
282         warn "Warning: Own structure $id was excluded from instr/hat3.\n" unless $instrids{$id};
283     }
284
285 }
286
287
288
289 &cleanup();
290
291
292
293 ####################
294 ####################
295
296
297
298 sub parseResponse
299 {
300     my $response = shift;
301
302     #"status":"wait","mafftashid":"Ma8211432R"
303
304     my $status = "";
305     my $mafftashid = "";
306
307     if ( $response =~ /^([^\s:]+):([^\s:]+)$/ )
308     {
309         $mafftashid = $1;
310         $status = $2;
311     }
312
313     return ($status, $mafftashid);
314
315 }
316
317
318 sub extractchecksum
319 {
320     my $infile = shift;
321     my %dataset = ();
322
323     open CSUM, "tar -zxf $infile -O|" or return \%dataset;
324
325     while(<CSUM>)
326     {
327         chomp;
328         if ( /^(\S+)\s+(\S+)$/ )
329         {
330             $dataset{$2} = $1;
331         }
332
333     }
334
335     close CSUM;
336
337     return \%dataset;
338
339 }
340
341
342 sub parseError
343 {
344     my $response = shift;
345
346     #"error":"Invalid number of inputs found."
347     my $errorstr = ( $response =~ /\"error\"\s*:\s*\"([^\"]+)\"/ ) ? $1 : "";
348     return $errorstr;
349 }
350
351
352 sub getchecksum
353 {
354     my $infile = shift;
355
356     # md5 binary check
357     my $MD5BIN = "";
358
359     if ( -x "/usr/bin/md5sum" )
360     {
361         $MD5BIN = "/usr/bin/md5sum";
362     }
363     elsif ( -x "/sbin/md5" )
364     {
365         $MD5BIN = "/sbin/md5 -q";
366     }
367
368     return "" if $MD5BIN eq "";
369
370
371     my $checksum = "";
372     open MD5EXE, "$MD5BIN $infile|" or return "";
373
374     while(<MD5EXE>)
375     {
376         if (/^(\S+)\s+(\S+)$/)
377         {
378             $checksum = $1;
379             last;
380         }
381         elsif (/^(\S+)$/)
382         {
383             $checksum = $1;
384             last;
385         }
386     }
387
388     close MD5EXE;
389
390     return $checksum;
391
392 }
393
394
395 sub backticks
396 {
397     my $command = shift;
398
399     `$command`;
400     return ($? == -1) ? 0 : 1;
401 }
402
403
404 sub bail
405 {
406     my $str = shift;
407     print STDERR "$str\n" if defined $str;
408
409     &cleanup();
410     exit(1);
411 }
412
413
414 sub cleanup
415 {
416     return if ($TMP eq "" || !-d $TMP);
417
418     opendir(MAINDIR, $TMP);
419     my @files = readdir(MAINDIR);
420     closedir(MAINDIR);
421
422     foreach my $file (@files)
423     {
424         unlink "$TMP/$file" if -e "$TMP/$file";
425     }
426
427     remove_tree($TMP);
428
429 }
430
431
432 sub help
433 {
434     my $str = shift;
435
436     print <<'HELPME';
437
438 USAGE
439   ./mafftash_premafft.pl -p [FILE]
440   ./mafftash_premafft.pl -o [FILE] -d [DIRECTORY]
441   ./mafftash_premafft.pl -p [FILE] -o [FILE] -d [DIRECTORY]
442
443
444 PARAMETERS
445   -p [FILE]
446      FILE contains a list of PDBIDs (one entry per line); make sure that the PDBIDs are in the standard 5-character pdbid+chain naming format
447
448   -o [FILE] -d [DIRECTORY]
449      FILE contains a list of IDs from your own structure/pdb files (one entry per line)
450      for each ID in the list make sure that a corresponding structure file (same ID with .pdb extension) is stored in DIRECTORY
451
452   -h [HATFILE]
453      save the output hat3 file in HATFILE; if not set, the output is written to a file named 'hat3' in your current directory
454
455   -i [INSTRFILE]
456      save the output instr file in INSTRFILE; if not set, the output is written to a file named 'instr' in your current directory
457
458 HELPME
459
460     &bail($str);
461 }
462
463
464