#!/usr/bin/env bash

#
#Version: 2.4.0
#Author:  Sebastien Moretti
#Lab.    : Information Genomique et Structurale - IGS
#          CNRS - Life Sciences
#          Marseille, France
#E-mail:  moretti.sebastien [AT] gmail.com
#

echo -e "
############################################################################################
#                                                                                          #
#This script, and the ones it contains, are developed under the GNU General Public License.#
#So, you are free to                                                                       #
# - execute this program, whatever the usage                                               #
# - study this program and to adapt it for your needs                                      #
# - copy this program                                                                      #
# - enhance this program and to publish these enhancements                                 #
#                                                                                          #
#Nevertheless, you MUST always retain the original authorship with every copy you could    #
#make of this program.                                                                     #
############################################################################################
"

#Test if 'perl' is set
PERL=`which perl`
if [ -z $PERL ]; then
    echo -e "Perl has not been found in your regular PATH\nIt must be set to be able to use this plugin\n"
    exit
fi
WGET=`which wget`
if [ -z $WGET ]; then
    echo -e "wget has not been found in your regular PATH\nIt must be set to be able to use this plugin\n"
    exit
fi


#Get the most probable pymol.com location
EXEC='pymol'
PYMOL=`which $EXEC 2>/dev/null`
if [ -z "$PYMOL" ]; then
    EXEC='pymol.com'
    PYMOL=`which $EXEC 2>/dev/null`
fi
if [ -z "$PYMOL" ]; then
    EXEC='pymol.exe'
    PYMOL=`which $EXEC 2>/dev/null`
fi
if [ -z "$PYMOL" ]; then
    echo -e "'pymol', or 'pymol.com', script cannot be reached\n"
fi
PYMOL_PATH=`perl -e 'while(<>){print $1 if $_ =~ /^PYMOL_PATH=(.*)$/;}' $PYMOL`


#Ask where the plugin must be set
echo -e "Where is PyMOL home directory, the location of '$EXEC' ?\n[${PYMOL_PATH}]"
read WHERE


#Set PyMOL plugins directory
if [ -z "$WHERE" ]; then
    WHERE="${PYMOL_PATH}/modules/pmg_tk/startup/"
else
    WHERE="${WHERE}/modules/pmg_tk/startup/"
fi
#Test if the directory exists and is writable
if [ -d "$WHERE" ] && [ -w "$WHERE" ]; then
    echo -e "Processing ...\n"
else
    echo -e "\n\nThe directory doesn't seem to be useable:\n\tThat is possible it doesn't exist,\n\tis unwritable for you,\n\tor the whole PyMOL repository is altered\n\n"
    exit
fi


#Extract scripts from the installation program
tail -448 $0 |head -394 >rasmol2pymol.pl
tail -51 $0 >remote_ConSurf_load.py


#Change the path for the perl scripts
perl -p -e 's/\047*rasmol2pymol/\047${ARGV[0]}rasmol2pymol/' remote_ConSurf_load.py $WHERE >remote_ConSurf_load.pyt
mv -f remote_ConSurf_load.pyt remote_ConSurf_load.py
perl -p -e 's/PYMOLHOME/${ARGV[0]}/' rasmol2pymol.pl $WHERE >rasmol2pymol.plt
mv -f rasmol2pymol.plt rasmol2pymol.pl


#Copy the scripts and remove the former ones
rm -f ${WHERE}remote_ConSurf_load.py ${WHERE}remote_ConSurf_load.pyc
rm -f ${WHERE}rasmol2pymol.pl
rm -f ${WHERE}Legend.dx
mv -f rasmol2pymol.pl remote_ConSurf_load.py ${WHERE}
touch ${WHERE}Legend.dx
chmod ug+x ${WHERE}rasmol2pymol.pl


echo -e 'ConSurf-HSSP plugin for PyMOL has been set '
exit


######@###
#!/usr/bin/env perl

use strict;
use warnings;
use diagnostics;
use Getopt::Long;
use File::Basename;


=head1 SYNOPSIS

Rasmol script converter for ConSurf results

rasmol2pymol.pl --ras=rasmol_script.ras --pdbFile=pdb_file

or rasmol2pymol.pl --pdbCode=pdb_ID

or rasmol2pymol.pl --pdbCode=pdb_IDCHAIN (if several chains)

e.g.: rasmol2pymol.pl --pdbCode=1hcl

e.g.: rasmol2pymol.pl --pdbCode=1cdkB (for chainB)

=head1 DESCRIPTION

=over 4

=item    ConSurf

=item Server for the Identification of Functional Regions in Proteins

=item Identification of functional regions in proteins by surface-mapping of phylogenetic information.

=item http://consurf-hssp.tau.ac.il/

=item Cyan    => Variable positions

=item .

=item .

=item .

=item White   => mid-variable positions

=item .

=item .

=item .

=item Violin  => Conserved positions

=back

=head1 VERSION

=over 4

=item Version: 2.4.0

=item License: GNU General Public License

=back

=head1 AUTHOR

=over 8

=item Sebastien MORETTI

=item moretti.sebastien [AT] gmail.com

=item Lab. Information Genomique et Structurale - IGS

=item CNRS - Life Sciences

=item Marseille, France

=back

=cut


#Options
my $pdb_code='';
my $pdb_file='';
my $rasmol_file='';
GetOptions("pdbCode=s"      => \$pdb_code,
           "pdbFile=s"      => \$pdb_file,
           "ras=s"          => \$rasmol_file);

my $counteur=0;
if ($pdb_code =~ /^\d\w\w\w$/){
    my $pdbID=lc($pdb_code);
    my ${PDB_CODE}=uc($pdbID);
    unlink("${PDB_CODE}.pml");
###On whole structure
    $counteur=0;
    for(my $rep=0;$rep < 1; $rep++){
        $counteur++;
        `wget -O ${pdbID}.list 'http://consurf-hssp.tau.ac.il/cgi-bin/consurf-hsspNew.cgi?TMPL=indexPDB&pdb_ID=${pdbID}'`;
        last if ($counteur > 10);
        $rep=$rep-1 if ( -z "${pdbID}.list" );
    }
    if ( -z "${pdbID}.list" ){
	`touch pdb${pdbID}.ent`;
	open(PYMOL,">${PDB_CODE}.pml");
	print PYMOL "cls\nprint \"The structure is not reachable from ConSurf server\"\n";
	close PYMOL;
	exit;
    }
    open(LIST,"${pdbID}.list");
    my $flagg=0;
    my @chain_list;
    while(<LIST>){
	if ($flagg==0 and $_ =~ />${pdbID}</){
	    $flagg=1;
	}
	elsif ($flagg==1 and $_ =~ /NAME=\"chainRB\" CHECKED VALUE=/){
	    while(/VALUE=\"([_\w]+)\"/g){
		my $chainchainchain=$1;
		$chainchainchain='_' if ($1 eq 'NULL');
		@chain_list=(@chain_list,$chainchainchain);
	    }
	}
    }
    close LIST;
    unlink("${pdbID}.list");
    if ( ! exists($chain_list[0]) ){
	`touch pdb${pdbID}.ent`;
	open(PYMOL,">${PDB_CODE}.pml");
	print PYMOL "cls\nprint \"The structure you seek for is not currently available on ConSurf\"\n";
	close PYMOL;
	exit;
    }
    print STDERR "[@chain_list]\n";
    for(my $t=0; $t <= $#chain_list; $t++){
	if ( !-e "pdb${pdbID}.ent" ){
            $counteur=0;
            for(my $rep=0;$rep < 1; $rep++){
                $counteur++;
	        `wget -O pdb${pdbID}.ent 'http://consurf.tau.ac.il/results/HSSP_ML_${pdbID}${chain_list[$t]}/pdb${pdbID}.ent'`;
                last if ($counteur > 10);
                $rep=$rep-1 if ( -z "pdb${pdbID}.ent" );
            }
	    if ( -z "pdb${pdbID}.ent" and $t<$#chain_list){
		unlink("pdb${pdbID}.ent");
	    }
	    elsif ( -z "pdb${pdbID}.ent" and $t==$#chain_list){
		open(PYMOL,">${PDB_CODE}.pml");
		print PYMOL "cls\nprint \"The structure you seek for is not currently available on ConSurf\"\n";
		close PYMOL;
		exit;
	    }
	}
        $counteur=0;
        for(my $rep=0;$rep < 1; $rep++){
            $counteur++;
	    `wget -O colors.txt 'http://consurf.tau.ac.il/results/HSSP_ML_${pdbID}${chain_list[$t]}/colors.txt'`;
            last if ($counteur > 10);
            $rep=$rep-1 if ( -z 'colors.txt' );
        }
	if ( -z 'colors.txt' ){
	    open(PYMOL,">>${PDB_CODE}.pml");
	    print PYMOL "cls\nprint \"ConSurf has planed ${pdbID}${chain_list[$t]} to process but it is not currently available\"\n";
	    close PYMOL;
	}

	my $rasmol_script='colors.txt';
	my $pdb_file="pdb${pdbID}.ent";
	${chain_list[$t]}='' if (${chain_list[$t]} eq '_');
	&header_script($pdb_file) if ($t==0);
	&split_chains($pdb_file,${chain_list[$t]});
	&script($rasmol_script,$pdb_file,${chain_list[$t]}) if ( ! -z 'colors.txt' );
	&footer_script($pdb_file) if ($t==$#chain_list);
    }
    unlink('colors.txt');
###
}
elsif ($pdb_code =~ /^\d\w\w\w\w$/){
    my $pdbID=lc($pdb_code);
    my ${PDB_CODE}=uc($pdbID);
    unlink("${PDB_CODE}.pml");
    my $chain=$pdbID;
    $pdbID =~ s/\w$//;
    $chain =~ s/(\w)$/\U$1/;
    my $name=lc($chain);
    $counteur=0;
    for(my $rep=0;$rep < 1; $rep++){
        $counteur++;
        `wget -O pdb${name}.ent 'http://consurf.tau.ac.il/results/HSSP_ML_${chain}/pdb${pdbID}.ent'`;
        last if ($counteur > 10);
        $rep=$rep-1 if ( -z "pdb${pdbID}.ent" );
    }
    if ( -z "pdb${name}.ent" ){
	open(PYMOL,">${PDB_CODE}.pml");
	print PYMOL "cls\nprint \"The structure you seek for is not currently available on ConSurf\"\n";
	close PYMOL;
	exit;
    }
    $counteur=0;
    for(my $rep=0;$rep < 1; $rep++){
        $counteur++;
        `wget -O colors.txt 'http://consurf.tau.ac.il/results/HSSP_ML_${chain}/colors.txt'`;
        last if ($counteur > 10);
        $rep=$rep-1 if ( -z 'colors.txt' );
    }
    if ( -z 'colors.txt' ){
	open(PYMOL,">>${PDB_CODE}.pml");
	print PYMOL "cls\nprint \"ConSurf has planed this structure to process but it is not currently available\"\n";
	close PYMOL;
	unlink('colors.txt');
	exit;
    }

    $chain =~ s/^....//;
    $chain='' if ($chain eq '_');
    my $rasmol_script='colors.txt';
    my $pdb_file="pdb${name}.ent";
    &header_script($pdb_file);
    &split_chains($pdb_file,$chain);
    &script($rasmol_script,$pdb_file,$chain);
    &footer_script($pdb_file);
    unlink('colors.txt');
}
elsif ($pdb_code eq '' and -e $rasmol_file and -e $pdb_file){
    &header_script($pdb_file);
    &script($rasmol_file,$pdb_file,'');
    &footer_script($pdb_file);
}
else{
    system("perldoc $0");
    exit;
}





sub header_script{
    my ($pdb_file)=@_;

    my $PDB_ID=$pdb_file;
    $PDB_ID=basename($PDB_ID);
    $PDB_ID =~ s/^(.+)\..*$/$1/;

    my $PDB_CODE=$PDB_ID;
    $PDB_CODE =~ s/^pdb//;
    $PDB_CODE=uc($PDB_CODE);
    open(PYMOL,">${PDB_CODE}.pml");
    print PYMOL "load $pdb_file\ndss $PDB_ID\nhide all\ncreate nt, resn a+c+g+t+u+n+r+y+m+k+s+w+h+b+v+d\nshow cartoon, nt\nshow sticks, nt\n";
    print PYMOL "create aa, ${PDB_ID} and ! resn a+c+g+t+u+n+r+y+m+k+s+w+h+b+v+d\nshow surface, aa\ncolor gray, aa\nshow stick, het\nhide (solvent)\n";
    print PYMOL "set_color Cons_9c = [0.6, 0.1, 0.4]\nset_color Cons_8c = [0.9, 0.5, 0.7]\nset_color Cons_7c = [1.0, 0.8, 0.9]\nset_color Cons_6c = [1.0, 0.9, 1.0]\nset_color Cons_5c = [1.0, 1.0, 1.0]\nset_color Cons_4c = [0.9, 1.0, 1.0]\nset_color Cons_3c = [0.8, 1.0, 1.0]\nset_color Cons_2c = [0.5, 1.0, 1.0]\nset_color Cons_1c = [0.1, 0.8, 0.8]\nset_color allc = [0.8, 0.8, 0.8]\ncolor allc, all\nset_color C9 = [0.6, 0.1, 0.4]\nset_color C1 = [0.1, 0.8, 0.8]\n";
    close PYMOL;
}

sub split_chains{
    my ($pdb_file,$chain)=@_;

    my $PDB_ID=$pdb_file;
    $PDB_ID=basename($PDB_ID);
    $PDB_ID =~ s/^(.+)\..*$/$1/;

    my $PDB_CODE=$PDB_ID;
    $PDB_CODE =~ s/^pdb//;
    $PDB_CODE=uc($PDB_CODE);
    open(PYMOL,">>${PDB_CODE}.pml");
#    print PYMOL "#\ncreate ${PDB_CODE}$chain, aa and chain $chain\n";
    print PYMOL "#\n";
    close PYMOL;
}

sub script {
    my ($rasmol_script,$pdb_file,$chain)=@_;

    my $PDB_ID=$pdb_file;
    $PDB_ID=basename($PDB_ID);
    $PDB_ID =~ s/^(.+)\..*$/$1/;

    my $PDB_CODE=$PDB_ID;
    $PDB_CODE =~ s/^pdb//;
    $PDB_CODE=uc($PDB_CODE);
    open(RAS,"$rasmol_script");

    open(PYMOL,">>${PDB_CODE}.pml");
    my $selection="select trUc, /${PDB_CODE}//${chain}/";
    my $largeSelect=$selection;
    $largeSelect =~ s/trUc,/trUc, trUc or/;
    my $residueNbr=0;
    while(<RAS>){
	if ($_ =~ /^spacefill/ or $_ =~ /^$/){
	    $selection="select trUc, /aa//${chain}/";
            $largeSelect=$selection;
            $largeSelect =~ s/trUc,/trUc, trUc or/;
            $residueNbr=0;
	}
	elsif ($_ =~ /^select /){
	    while(/[A-Z]+([0-9]+):?\w*/g){
		my $locus=$1;
                $residueNbr++;
                if ($residueNbr >= 80){
                    $selection=$selection."\n".$largeSelect.$locus;
                    $residueNbr=0;
                    next;
                }
		if ($selection !~ /\/\/\w*\/\d+/){
		    $selection=$selection."$locus";
		}
		else{
		    $selection=$selection."+$locus";
		}
	    }
	}
	elsif ($_ =~ /^color \[(\d+),(\d+),(\d+)\]/ and $_ !~ /^color \[200,200,200\]/){
	    my $rang=&rang($1,$2,$3);
	    my $name="Cons_$rang";
	    $name=$name.$chain if ($chain ne '');
	    $selection =~ s/trUc/$name/g;
	    print PYMOL $selection."\ncolor Cons_${rang}c, $name\n";
            $residueNbr=0;
	}
    }
    close PYMOL;
    close RAS;
}

sub footer_script{
    my ($pdb_file)=@_;

    my $PDB_ID=$pdb_file;
    $PDB_ID=basename($PDB_ID);
    $PDB_ID =~ s/^(.+)\..*$/$1/;

    my $PDB_CODE=$PDB_ID;
    $PDB_CODE =~ s/^pdb//;
    $PDB_CODE=uc($PDB_CODE);
    open(PYMOL,">>${PDB_CODE}.pml");
    print PYMOL "color yellow, het\ncolor slate, nt\ndelete ${PDB_ID}\nzoom aa\ncenter aa\nset_name aa, $PDB_CODE\nselect AaA, none\ndelete AaA\n";
    print PYMOL "if cmd.count_atoms\(\"nt\"\) == 0: cmd.delete\(\"nt\"\)\n"; #remove nt object if there is no nucleotides in the structure
    print PYMOL "load PYMOLHOME/Legend.dx, map\nzoom $PDB_CODE\nramp_new legend, map, [1.0,5.0,9.0], color=['C1',[1.0,1.0,1.0],'C9']\ncmd.delete\(\"map\"\)\n"; #Add a legend box with defined ConSurf Colors
    close PYMOL;
}

sub rang{
    my ($uno,$duo,$trio)=@_;
    my $rang=0;
    if ($uno==160 and $duo==37 and $trio==96){
	$rang=9;
    }
    elsif ($uno==240 and $duo==125 and $trio==171){
	$rang=8;
    }
    elsif ($uno==250 and $duo==201 and $trio==222){
	$rang=7;
    }
    elsif ($uno==252 and $duo==237 and $trio==244){
	$rang=6;
    }
    elsif ($uno==255 and $duo==255 and $trio==255){
	$rang=5;
    }
    elsif ($uno==234 and $duo==255 and $trio==255){
	$rang=4;
    }
    elsif ($uno==215 and $duo==255 and $trio==255){
	$rang=3;
    }
    elsif ($uno==140 and $duo==255 and $trio==255){
	$rang=2;
    }
    elsif ($uno==16 and $duo==200 and $trio==209){
	$rang=1;
    }

    return $rang;
}

#sub color{
#    my ($red,$green,$blue)=@_;
#    $red=($red/255);
#    $green=($green/255);
#    $blue=($blue/255);
#    $red=sprintf("%.1f, ", $red);
#    $green=sprintf("%.1f, ", $green);
#    $blue=sprintf("%.1f", $blue);
#
#    return ($red,$green,$blue);
#}

exit;

######@###

###@######
#
# This simple plugin will automatically load a ConSurf phylogenetic information file from the
# web given the pdb code.  It does error handling as well.
# 
# To get color.txt, rasmol script result, files from ConSurf for a pdb accession number.
#
# Charles Moad (cmoad@indiana.edu)
# Scientific Data Analysis Lab
# Indiana University
#
# Modifications for ConSurf, Sebastien Moretti (moretti.sebastien [AT] gmail.com)
# Structural and Genomic Informations lab (IGS)
# CNRS, Life Sciences, France
#

from Tkinter import *
from pymol import cmd

def __init__(self):
   # Simply add the menu entry and callback
   self.menuBar.addmenuitem('Plugin', 'command',
                            'ConSurf - Surface-mapping of phylogenetic information Loader Service 2.4.0',
                            label = 'ConSurf - Surface-mapping of phylogenetic information Loader Service 2.4.0',
                            command = lambda s=self : FetchConSurf(s))


# Class that simply takes the pdbcode from a dialog and retrieves the files from ConSurf and RCSB
class FetchConSurf:
   def __init__(self, app):
      import tkSimpleDialog
      import tkMessageBox
      import urllib
#      import gzip
      import os
      import string

      pdbCode = tkSimpleDialog.askstring('ConSurf - Surface-mapping of phylogenetic information Loader Service 2.4.0',
                                         'Please enter a 4-digit pdb code: (or 5 to specify only one chain)',
                                         parent=app.root)
      
      if pdbCode: # None is returned for user cancel
         pdcCode = string.upper(pdbCode)
         pdbID = string.lower(pdbCode)

         os.system('rasmol2pymol.pl --pdbCode=' + pdbID ) # Execute the rasmol script parser to build pymol script
         cmd.do("@" + os.environ['PWD'] + os.sep + pdcCode + ".pml")     # Load the structure with its annotation

         os.remove(os.environ['PWD'] + os.sep + pdcCode + ".pml")
         os.remove(os.environ['PWD'] + os.sep + 'pdb' + pdbID + ".ent")

