Forum Moderators: coopster

Message Too Old, No Replies

Need help in refreshing a page periodically for a slow-loading results

         

ktsirig

11:04 pm on Apr 25, 2015 (gmt 0)

10+ Year Member



Hi,

I have an input form for a user to submit some input and then this input is processed by a Perl script, which is called through the PHP index page...

My problem is that this external script takes usually more than 2-3 minutes so there is a risk of the page to hang. How can I modify my PHP page to stay in index.php, but periodically refresh it so, when the perl command is done, it then outputs the results.

Here is the index page (the refresh I wrote on top did not work.


<?php
$max_seqs = 1000;

$page = $_SERVER['PHP_SELF'];
$sec = "10";
header("Refresh: $sec; url=$page");

?>
<html>
<head>

<style>
body
{
font-family: arial;
color: #003965;
font-size: 14px;
}

textarea
{
width: 620px;
height: 120px;
font-family: courier;
}

.whole
{
width: 1000px;
border-collapse: collapse;
margin-top:20px;
margin-bottom:20px;
text-align: center;
background-color: #e8e8e8;
font-size: 12px;
}

.browse_cell
{
background:#d8dada;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 13px;
padding: 3;
border-spacing: 2;
text-align: center;
font-weight: bold;
color:#424d5d;
}

.browse_cell_change1
{
background:#BFBFF6;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
padding: 2;
}

.browse_cell_change2
{
background:#D9D9D9;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
padding: 2;
border-spacing:4px;
}

.headcell
{
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 16px;
font-weight:bold;
line-height: 15px;
text-align: center;
color: #000144;
}


</style>
</head>

<body>
<?php

if( isset ( $_POST['sequence'] ))#run part
{
function readSeqs($text)
{
if( !preg_match( '/^>/m', $text ) )
return readSeqs( ">\n$text" );

$seqs = array();
$text = preg_replace( '/[\n\r]+/', "\n", $text );
preg_match_all( '/^>([^\n]*)\n([^>]*)/ms', $text, $matches );

foreach( $matches[1] as $k=>$name1 )
{
$seqs_number++;
$seq = $matches[2][$k];
$name1 = trim($name1);
$name=substr($name1, 0, 50);#keep only the first 40 characters (if the name is longer)
$name=preg_replace('/\s+/', ' ', $name);
$name=preg_replace('/[\|\s\/\\\%\*&\#\@\(\)\[\]\$\^\!]/', '_', $name);
$seq = preg_replace( '/\s+/', '', $seq );

$seqs[] = array( 'name'=>$name, 'seq'=>$seq );
}
return $seqs;
}

$uniq_number = uniqid();
$input_folder = './tmp_files/myfolder_'.$uniq_number;
mkdir($input_folder);
$input_file = $input_folder.'/'.'input_seqs';
$seqs = readSeqs($_POST['sequence']);
$run_mode = $_POST['mode'];
$signal='';
$phmms='';

if($_POST[sp_pred] == 'on')
{
$signal = $_POST['sp_pred'];
}
else
{
$signal = 'off';
}

if($_POST['pfams'] == 'on')
{
$phmms = $_POST['pfams'];
}
else
{
$phmms = 'off';
}

$seqs_number = count($seqs);

$prior_info1 = $_POST['prior'];
if (preg_match('/Example/', $prior_info1))
{
$prior_info='--';
$prior_info_final='NO_INFO';
}
else
{
$prior_info=$prior_info1;
$prior_info_final=str_replace(';', 'A', $prior_info);
}

if( $seqs_number == 0 )
{
echo "<em>You did not submit any sequences.</em>";
}

elseif( $seqs_number > $max_seqs )
{
echo "<em>You can input no more than $max_seqs sequences at a time.</em>";
}

elseif ( $seqs_number > 1 and $seqs_number <= $max_seqs )
{
$input = '';
foreach($seqs as $v) #create input file for run
{ $input.= ">".$v['name']."\n".$v['seq']."\n"; }#write each FASTA seq in input file
file_put_contents( $input_file, $input );#(if we will allow >1 proteins)

#echo "perl Whole_Program.pl $input_folder $seqs_number $prior_info_final $run_mode $signal $phmms<br>";
exec ("perl Whole_Program.pl $input_folder $seqs_number $prior_info_final $run_mode $signal $phmms", $res_total, $ret);

if($ret==0)
{
$text_file = $input_file.'.txt_res';
$zip_file = 'tmp_files/'.$uniq_number.'.tgz';

echo "<table class=\"whole\">\n";
echo "<tbody>\n";
echo "<tr><td class=\"headcell\" align=\"right\" colspan=\"7\"><br>Results<br><br></td></tr>\n";
echo "<tr>\n";
echo "<td width=\"14%\" class=\"browse_cell\">Entry</td>\n".
"<td width=\"12%\" class=\"browse_cell\">Length</td>\n".
"<td width=\"14%\" class=\"browse_cell\">Signal peptide</td>\n".
"<td width=\"14%\" class=\"browse_cell\">&beta;-score</td>\n".
"<td width=\"38%\" class=\"browse_cell\">OMPdb family</td>\n".
"<td width=\"14%\" class=\"browse_cell\">#TM</td>\n".
"<td width=\"12%\" class=\"browse_cell\">Topology image</td>\n";
echo "</tr>\n";

foreach ($res_total as $line_entry)
{
$counter++;
if ($counter % 2){$colour_class="browse_cell_change1";}
else{$colour_class="browse_cell_change2";}

$all_data = preg_split("/\t/", $line_entry);

$id=$all_data[0];
$seq_len=$all_data[1];
$signal=$all_data[2];
$score=$all_data[3];
$family_name=$all_data[4];
$family_number=$families_array[$family_name];
$tm_num=$all_data[5];
if($tm_num==0) {$tm_num='--';}
$topo_img_link=$all_data[6];

echo "<tr>\n";
echo "<td width=\"14%\" align=\"left\" class=\"".$colour_class."\">".$id."</td>\n".
"<td width=\"12%\" class=\"".$colour_class."\">".$seq_len."</td>\n".
"<td width=\"14%\" class=\"".$colour_class."\">".$signal."</td>\n".
"<td width=\"14%\" class=\"".$colour_class."\">".$score."</td>\n".
"<td width=\"38%\" align=\"left\" class=\"".$colour_class."\">";


if($family_name == "--")
{
echo "$family_name</td>\n";
}

else
{
echo "<a target=\"_blank\" href=\"http://www.ompdb.org/OMPdb/view_family.php?fam_id=".$family_number."\">".
$family_name."</a></td>\n";
}

echo "<td width=\"14%\" class=\"".$colour_class."\">".$tm_num."</td>\n";

if($topo_img_link=='--')
{
echo "<td width=\"12%\" class=\"".$colour_class."\">--</td>\n";
}
else
{
echo "<td width=\"12%\" class=\"".$colour_class."\"><a target=\"_blank\" href=\"".$topo_img_link."\"> Download</a></td>\n";
}

echo "</tr>\n";
}
echo "</tbody></table>\n";
}

else
{
echo "<br /><br />Program error!";

}
}
echo "<br /><a target=\"_blank\" href=\"".$text_file."\">Download</a> results in plain text format\n";
echo "<br /><a target=\"_blank\" href=\"".$zip_file."\">Download</a> all files related to this submission as a tarball\n";
echo "<br /><br /><a href=\"index.php\">Run again</a><br />";
}

else #index initial page
{
echo "Please paste up one or more ".
" - formatted sequences in the textarea below: <br /><br />\n";
echo "<form method=post name=\"seq_form\">".
"<textarea name=\"sequence\"></textarea>
<br /><br />
Select mode:
<input type=\"radio\" name=\"mode\" value=\"1\" checked /> MSA-version (1 sequence)
&nbsp;<input type=\"radio\" name=\"mode\" value=\"2\" /> Single-sequence version (up to $max_seqs sequences)
<br /><br />
Run signal-peptide prediction using <a target=\"_blank\" href=\"http://www.compgen.org/tools/PRED-TAT/\">PRED-TAT</a>:
<input type=\"checkbox\" name=\"sp_pred\" checked>
<br /><br />
Use library in prediction:
<input type=\"checkbox\" name=\"pfams\" checked>
<br /><br />
Prior information (constrained prediction):
<input type=\"text\" name=\"prior\" size=\"33\" style=\"color:#888;\"
value=\"Example: I:1-15;M:20-25;O:30-30\" onfocus=\"inputFocus(this)\" onblur=\"inputBlur(this)\" />
<br /><br />
<input type=\"submit\" value=\"Run prediction\" />
<input type=\"reset\" value=\"Clear fields\" />
<input type=\"button\" value=\"Generate sample input\" onclick=\"example_fill();\">
</form>";
echo "<br /><hr>";
}
?>
</body>
</html>


rainborick

2:40 pm on Apr 26, 2015 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



There are two basic methods to accomplish this. You could use a <meta> 'refresh' tag to have the browser periodically refresh/reload the page, or you can embed some JavaScript to periodically issue an AJAX call to check if your Perl script has run to completion.

But you should certainly do whatever you can to speed up the Perl script. Any script that runs more than 60 seconds is likely to run over the server's maximum execution time limit unless you're running on a dedicated server that you control.

ktsirig

5:46 pm on Apr 26, 2015 (gmt 0)

10+ Year Member



But that is exactly what I am trying to solve... To not have to care if my script takes X time to finish... Just navigate to a page saying for example "Your results will be ready here when they are processed" and then somehow check for the status of the perl script...If it is done, then just refresh the page and output the results to the user...

rainborick

7:57 pm on Apr 26, 2015 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The key problem is that your PHP code is written to expect an immediate result to be returned by the Perl script. You need to eliminate that dependence. It would be possible to use a multi-threaded method in your PHP script that would work. That way you could start an independent thread that would issue the exec() function for your Perl script and notify the parent when it's done. That's not something I've done, so I can't give you any specific suggestions. But there is lots of information online about such scripts.

Another solution would be to modify the Perl script to signal when its done by creating a results file on the server that could be uniquely identified by your software. Then you'd use a JavaScript/AJAX call to periodically check the status of the results file created by the Perl script.

tangor

1:45 am on Apr 27, 2015 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'd also look at the Perl script to see what is taking so long... what are you processing that might take 2-3 minutes? (Generalities, please!)

ktsirig

10:04 am on Apr 27, 2015 (gmt 0)

10+ Year Member



the perl script is needed because it makes some calculations for Hidden Markov Models (mathematical algorithms), plus it runs external software in Java (this is the time-consuming part and I can't touch this code)...

My idea was that, if the user clicks on "Submit", it should take him to a page saying "Your results will be ready in this link when done" and then of course the link would be an empty page in the beginning but then it would be substituted with results page... does this make sense?