#!/usr/bin/perl -w

# Copyright (c) 1999 Robert B. Russell
#  EMBL, Meyerhofstrasse 1, 69917 Heidelberg, Germany
#    Email: russell@embl.de
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
#
#

# Rob Russell 
# Contact: russell@embl-heidelberg.de

# This is a very rough perl CGI program to run COILS
#  as a crude server.  To use you will have to
#  edit things substantially.

use CGI;

$coils_root = "/usr/local/apache/htdocs/coils/";

$coils_exec = "/russell/rg1/lbin/ncoils";
$gnuplot_exec = "/russell/rg1/lbin/gnuplot";
$gs_exec = "/usr/bin/gs";
$ppmtogif_exec = "/usr/bin/ppmtogif";

$header = $coils_root."/header.html";
$footer = $coils_root."/footer.html";
$coilsmat = $coils_root . "/new.mat";
$tmpdir = "/usr/local/apache/htdocs/coils/data/";
$htmldir = "http://www.russell.embl-heidelberg.de/coils/data/";
$junkfile = "/tmp/coilsjunk.".$$;
$query = new CGI;


print $query->header;
print $query->start_html("Rob Russell's COILS Server");

if($query->param()){
   &process($query);
} else {
   &print_prompt($query);
}

print $query->end_html;

sub print_prompt {

   my($query) = @_;

   if(open(INFO,$header)){
      while(<INFO>){
         print;
      }
   } else {
      print "Contact <a href=mailto:russell\@embl-heidelberg.de>Rob Russell</a> for more information. <BR>";
   }

   print $query->startform;
   print "Paste your sequence into this box (raw sequence, or FASTA format):<BR>";
   print $query->textarea(-name=>'sequence',
                          -default=>'',
                          -rows=>10,
                          -columns=>50);
   print "<BR>Enter a name for your query sequence (optional)<BR>\n";
   print $query->textarea(-name=>'Name',
                             -rows=>1,
                             -columns=>30,
                             -default=>'Unknown'
                            );
   print "<BR>\n";

   print "Mode: ";
   print $query->popup_menu(-name=>'Mode',
			     -values=>['fasta','raw','threewin'],
			     -default=>'threewin'
			   );
   print " ";

   print "Weight a&d = b,c,e,f,g?";
   print $query->popup_menu(-name=>'weighted?',
                             -values=>['yes','no'],
                             -default=>'no'
                            );
   print " ";

   print "Matrix:";
   print $query->popup_menu(-name=>'matrix',
                             -values=>['MTIDK','MTK'],
                             -default=>'MTIDK'
                            );
   print "<br>";

   print "Window (fasta/raw only): ";
   print $query->popup_menu(-name=>'Window',
                             -values=>['14','21','28'],
                             -default=>'21'
                            );
   print "<br>";
 
   print $query->submit();
   print $query->reset();

   if(open(INFO,$footer)){
      while(<INFO>){
         print;
      }
   } 
   print $query->endform
}
sub process {


   print "<HTML>\n";
   print "<BODY BGCOLOR=\"FFFFFFFF\">\n";
   $in_seq = $query->param('sequence');
   $in_seq =~ s/^>[^\n].*\n//;
   $in_seq =~ s/^>[^\r].*\n//;
   $in_seq =~ s/[^A-Za-z]//g;
   $mode = $query->param('Mode');
   $id = $query->param('Name'); 
   $win = $query->param('Window');
   if($query->param('weighted?') eq "yes") { $weighted = " -w "; }
   else { $weighted =""; }
   $extra = $weighted;
   if($query->param('matrix') eq "MTK") {
	$extra .= " -m " . $coils_root . "/old.mat";
   }


   $ENV{"COILSDIR"} = "/russell/rg1/apps/coils/";
   $seqfile   = $tmpdir . "coils_svr_" . $$ . ".fasta";
   $gpcomfile = $tmpdir . "coils_svr_" . $$ . "_gp.com";
   $gpdatfile = $tmpdir . "coils_svr_" . $$ . "_gp.dat";
   $gppsfile  = $tmpdir . "coils_svr_" . $$ . "_gp.ps";
   $gpppmfile = $tmpdir . "coils_svr_" . $$ . "_gp.ppm";
   $gpgiffile = $tmpdir . "coils_svr_" . $$ . "_gp.gif";
   $gpgifhtmlfile = $htmldir . "coils_svr_" . $$ . "_gp.gif";

   &write_fasta($seqfile,$id,$in_seq);


   if(($mode eq "fasta") || ($mode eq "raw")) {
     if($mode eq "fasta") { $extra .= " -f "; }
     print "<pre>";
     $command = $coils_exec . $extra .  " < ". $seqfile;
     print "Command is $command<br>\n";
     exit;
     if(open(IN,"$command|")) {
        while(<IN>) {
             print $_;
        }
        close(IN);
     } else {
        print "Error opening output from COILS\n";
        die;
     }
     print "</pre>";
   } elsif($mode eq "threewin") {
      print "<p><HR>What should appear below is the result of running COILS three times with windows of 14,21 & 28.<br>`frame' denotes the predicted position of the heptad repeat for the highest scoring window that overlaps each position.<br>`prob' gives a single integer value representation of P (where 0-9 covers the range 0.0-1.0) <HR>\n";

	print "<pre>";
        # Runs threewin style mode
        # Three windows 14,21,28
        # printf("%4d %c %c %7.3f %7.3f (%7.3f %7.3f)\n",i+1,seq[i],hept_seq[i],score[i],P[i],Gcc,Gg);
        $align = {};
        $align->{file} = "";
        $align->{ids}  = ();
        $align->{list} = ();

        $align->{nseq} = 7;
        $align->{ids}{$id}{seq} = $in_seq;
        $align->{alen} = length($in_seq);
        $align->{list}[0] = $id;

        for($i=14; $i<=28; $i+=7) {
            $j=($i-14)/7;
            $command = $coils_exec . $extra . " -win " . $i . " < " . $seqfile;
#	    print "Command is $command\n";
            open(IN,"$command|");

            $fid = "frame-" . $i;
            $pid = "prob-" . $i;
            $align->{ids}{$fid}{seq} = "";
            $align->{ids}{$pid}{seq} = "";
            $align->{ids}{$pid}{Ps} = ();
            $align->{list}[1+$j] = $fid;
            $align->{list}[4+$j] = $pid;

            $p=0;
            while(<IN>) {
                $_ =~ s/^ *//;
                @t=split(/ +/);
                $align->{ids}{$fid}{seq} .= $t[2];
                $align->{ids}{$pid}{Ps}[$p] = $t[4]; # Raw P value
                $p++;
                $P = $t[4]*10;
                if($P>=10) { $sP = "9"; }
                else { $sP = substr($P,0,1); }
                if($sP eq "0") { $sP = "-"; }
                $align->{ids}{$pid}{seq} .= $sP;
            }
            close(IN);
        }
        write_clustal($align,"-");
	print "</pre>";
        print "<p><HR>What should appear below is an image of the three window lengths as a function of residue number.  Peaks in the graph indicate regions of higher coil probability.<HR>\n";
        # Now we'll try and do a ghostscript plot
        if(!open(OUT,">$gpdatfile")) {
                print "Error running ghostscript\n";
                die;
        }
        for($i=0; $i<$align->{alen}; ++$i) {
                printf(OUT "%4d %s  %s %7.3f %s %7.3f %s %7.3f \n",
                    $i+1,substr($align->{ids}{$id}{seq},$i,1),
                    substr($align->{ids}{"frame-14"}{seq},$i,1),
                    $align->{ids}{"prob-14"}{Ps}[$i],
                    substr($align->{ids}{"frame-21"}{seq},$i,1),
                    $align->{ids}{"prob-21"}{Ps}[$i],
                    substr($align->{ids}{"frame-28"}{seq},$i,1),
                    $align->{ids}{"prob-28"}{Ps}[$i]);
        }
        close(OUT);
        if(!open(OUT,">$gpcomfile")) {
                print "Error running ghostscript\n";
                die;
        }
        print OUT 
"set terminal postscript portrait color solid
set size 0.7,1.0
set output \"/dev/null\"
plot [ ] [0:1.0] \"$gpdatfile\"  using 1:4 title \"P(cc) vs. Seq pos win 14\" with lines
replot \"$gpdatfile\" using 1:6 title \"P win 21\" with lines
set output \"$junkfile\"
replot \"$gpdatfile\" using 1:8 title \" win 28\" with lines
set output
quit";
        close(OUT);
        $command = $gnuplot_exec . " < " . $gpcomfile ;
#	print "Command is $command\n";
        system($command);

        $command = "/bin/mv ".$junkfile." ".$gppsfile;
#	print "Command is $command\n";
        system($command);

        $command = $gs_exec . " -sDEVICE=ppmraw -r72 -q -dNOPAUSE -sOutputFile=\"" . $gpppmfile . "\" -- " . $gppsfile . " >> $gpcomfile ";
#	print "Command is $command\n";
        system($command);
        $command = $ppmtogif_exec . " < " . $gpppmfile  . " > " . $gpgiffile;
#	print "Command is $command\n";
        system($command);
        print "</pre>\n";
        print "<img src=\"" . $gpgifhtmlfile . "\">";
#        printf("HERE running %s <br>\n",$command); exit; 

        system($command);
   }
   unlink $seqfile;
   unlink $junkfile;
   unlink $gpdatfile;
   unlink $gpcomfile;
   unlink $gppsfile;
   unlink $gpppmfile;
   unlink $gpgiffile;
   unlink $gpgifhtmlfile;


}

sub write_fasta {
   my($fn,$id,$seq) = @_;
   open(SEQ,">$fn") || die "$fn wouldn't open\n";
   print SEQ ">$id\n";
   $i=0;
   while($i<length($seq)) {
      $aa = substr($seq,$i,1);
      print SEQ $aa;
      if((($i+1)%60)==0){ print SEQ "\n" }
      $i++;
   }
   print SEQ "\n";
   close SEQ;
}
sub write_clustal {

        my($align) = $_[0];
        my($i,$j,$k,$id);

        my($outfile) = $_[1];
        open(OUT,">$outfile") || die "Error opening output file $outfile\n";



#        print OUT "CLUSTAL W(1.60) multiple sequence alignment\n\n";

        foreach $id (keys %{$align->{ids}}) {
                if(defined($align->{ids}{$id}{start})) {
                        $align->{ids}{$id}{newid} = $id . "/" . ($align->{ids}{$id}{start}+1) . "-" . ($align->{ids}{$id}{end}+1);
                        if(defined($align->{ids}{$id}{ranges})) {
                                $align->{ids}{$id}{newid} .= $align->{ids}{$id}{ranges};
                        }
                } else {
                        $align->{ids}{$id}{newid} = $id;
                }
        }
        $i=0;
        while($i<$align->{alen}) {      
                for($k=0; $k<$align->{nseq}; ++$k) {
                        $id = $align->{list}[$k];
                        printf(OUT "%-10s ",$align->{ids}{$id}{newid});
                        for($j=0; $j<60; ++$j) {
                                last if(($i+$j)>=$align->{alen});
                                print OUT substr($align->{ids}{$id}{seq},($i+$j),1);
                        }
                        printf(OUT "\n");
                }
                $i+=60;
                printf(OUT "\n");
        }
        close(OUT);
}
