#!/usr/bin/perl
package sdevSacch3d;
#######################################################################
##### Author :	Shuai Weng
##### Date   :  May 2001
##### Description : This package contains all necessary methods for 
#####               displaying sacch3d result to user. 
#####              
#######################################################################
use strict;
use DBI;
use GD;
use CGI qw/:all/;
use CGI::Carp qw(fatalsToBrowser);

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use Locus;
use Feature;
use dictyBaseid;
use Reflink;
use Reference;
use Chromosome;
use Gene_product;
use Pdb_sequence;
use Pdb_alignment;
use ConfigURLdictyBase;
use ConfigPathdictyBase;
use CreateGD;
use Motif;

use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use Login qw (ConnectToDatabase);
use TextUtil qw (DeleteUnwantedChar);
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase";
use dictyBaseCentralMod qw(:formatPage);

#######################################################################
#################### global variables #################################
#######################################################################

my $dbh;
my $dblink; 
my $configUrl;
my $configPath;
my %gene4orf;
my %gp4orf;
my %hits4orf;
my %chain4pdbid;
my $pvalueCutOff = 1e-2;
my $alignCutOff = 0;
my $defaultRulerWidth = 600;
my $defaultBarHeight = 20;
my $lastUpdate;

#######################################################################
sub new {      ############ constructor ###############################
#######################################################################
       
	my ($self, %args) = @_;

	$self = {};
	bless $self;

      	$self->{'_database'} = $args{'database'};
	$self->{'_help'}     = $args{'help'};

	$dbh = &ConnectToDatabase($self->database);

    	return $self;
}

sub help { $_[0]->{_help} }
sub database { $_[0]->{_database} }
sub title { $_[0]->{_title} }
sub featNm { $_[0]->{_featNm} }
sub locusNm { $_[0]->{_locusNm} }
sub showNm { $_[0]->{_showNm} }
sub proteinNm { $_[0]->{_proteinNm} }
sub pdbid { $_[0]->{_pdbid} }
sub pdb { $_[0]->{_pdb} }
sub chrom { $_[0]->{_chrom} }
sub chrnum { $_[0]->{_chrnum} }
sub keyword { $_[0]->{_keyword} }
sub summary { $_[0]->{_summary} }
sub query { $_[0]->{_query} }

######################################################################
sub DESTROY {   ############ destructor ##############################
######################################################################
    if (defined $dbh) {
	$dbh->disconnect;
    }
}

######################################################################
sub start{
######################################################################

    my ($self) = @_;

    $self->{'_title'} = "PDB Homolog Query";
    
    $self->initGlobalVars;
    
    if (!param) {
	$self->printEntryForm;
    }
    elsif (param('refNo')) {
	$self->{'_help'} = "";
	$self->printReferences;
    }
    else {
	$self->setIdentifier;
	if ($self->summary) {
	   $self->setTitle4summary;
	   $self->setHelp4summary;
	   $self->displaySummary; 
	}
	elsif (param('align')) {
	    my ($pdbid, $chain) = split(/\_/, $self->pdb);
	    $self->{'_title'} = "Alignment of ".$self->showNm." and PDB ".uc($pdbid);
	    if ($chain) {
		$self->{'_title'} .= " (chain $chain)";
	    }
	    $self->{'_help'} = "Protein_align.html";
	    $self->displayAlignment;
        }
	else {
	    $self->err_report("Unknown display type.");
	}
    }
}

#######################################################################
sub printEntryForm {
#######################################################################
    my ($self) = shift;

    &printStartPage($self->database, $self->title, $self->help);

    print blockquote(table(Tr(td({-width=>'80%'},
				 font({-size=>'+2'},
				      b("PDB Homolog Query"))).
			      td({-bgcolor=>"#b7d8e4"},
				 "&nbsp;&nbsp;".
				 a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/protein/getDomain"}, b("Protein Motif Query")).
				 "&nbsp;&nbsp;"))).$self->description),p;
		     

    my @chr = ('-chr-', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 
	       'VIII', 'IX', 'X', 'XI', 'XII', 'XIII', 
	       'XIV', 'XV', 'XVI', 'Mito');
    my @pvalueCutoff = ('1e-2', '1e-10', '1e-50', '1e-100', '1e-200', 
			'1e-250');
    my @pctAlignedCutoff = ('0', '5%', '10%', '20%', '30%', '40%', '50%',
			    '60%', '70%', '80%', '90%', '100%');

    print center(table(Tr(td({-colspan=>'3'}, hr)).
		       Tr(td(start_form)).
		       Tr(td({-bgcolor=>"#a4abc2",
			       -width=>150,
			       -align=>'CENTER'},
			      font({size=>'+1'}, b("by Gene/ORF Name"))).
                           td(textfield(-name=>'locus',
				        -size=>'20')).
			   td(submit(-name=>'Submit',
				     -value=>'Search')." ".
			      reset(-name=>'Clear'))).
		       Tr(td(end_form)).
		       Tr(td({-colspan=>'4'}, hr)).		       
		       Tr(td(start_form)).
		       Tr(td({-bgcolor=>"#a4abc2",
			       -width=>150,
			       -align=>'CENTER'},
			      font({size=>'+1'}, b("by Keyword(s)"))).   
			   td(textfield(-name=>'keyword',
				        -size=>'20')).
			   td(submit(-name=>'Submit',
				     -value=>'Search')." ".
			      reset(-name=>'Clear'))).
	      	       Tr(td(end_form)).
		       Tr(td({-colspan=>'4'}, hr)).
		       Tr(td(start_form)).
		       Tr(td({-bgcolor=>"#a4abc2",
			       -width=>150,
			       -align=>'CENTER'},
			      font({size=>'+1'}, 
				   b("by PDB Identifier".br.
				     "(eg: 1yag)"))).
                           td(textfield(-name=>'pdbid',
				        -size=>'20')).
			   td(submit(-name=>'Submit',
				     -value=>'Search')." ".
			      reset(-name=>'Clear'))).
	      	       Tr(td(end_form)).
		       Tr(td({-colspan=>'4'}, hr)).
		       Tr(td(start_form)).
		       Tr(td({-bgcolor=>"#a4abc2",
			       -width=>150,
			       -align=>'CENTER'},
			      font({size=>'+1'}, b("by Chromosome"))).   
			   td(popup_menu(-name=>'chr',
					 -values=>\@chr)).
			   td(submit(-name=>'Submit',
				     -value=>'Search')." ".
			      reset(-name=>'Clear'))).
	      	       Tr(td(end_form))
		));
		     
    &printEndPage;
}

########################################################################
sub printReferences {
########################################################################
    my ($self) = @_;

    $self->{'_title'} = "dictyBase References for PDB ".param('pdbid');

    &printStartPage($self->database, $self->title, $self->help);
    
    my @refNo = split(/:/, param('refNo'));

    foreach my $refNo (@refNo) {

	my $refObj = Reference->new(dbh=>$dbh,
				    reference_no=>$refNo);
	if ($refObj) {
	    print $refObj->formatedCitation, br;
	}
    }

    &printEndPage;
}

########################################################################
sub displaySummary {
########################################################################
    my ($self) = @_;

    &printStartPage($self->database, $self->title, $self->help);
    if ($self->featNm)  {
	my $seqObj = Pdb_sequence->new(dbh=>$dbh,
				       sequence_name=>$self->featNm);
	if (!$seqObj) {
	    print "No structural information found for ".font({-color=>'red'}, $self->showNm),p;
	    &printEndPage;
	    exit;
	}	

	my $alignInfoArrayRef = 
	    Pdb_alignment->GetAlignInfoArrayRefBYqueryNo(dbh=>$dbh,
				      query_seq_no=>$seqObj->pdb_sequence_no,
				      score_cutoff=>$pvalueCutOff,
				      pct_aligned_cutoff=>$alignCutOff);
	if (!@$alignInfoArrayRef) {
	    print "No structural information found for ".font({-color=>'red'}, $self->showNm)." with ".font({-color=>'red'}, "pscore <= $pvalueCutOff"), p;
	    &printEndPage;
	    exit;
	}
	$self->printSummaryTable4ORF($alignInfoArrayRef);
    }
    elsif ($self->pdbid) {
	my $targetNm = $self->pdbid."%";
	my $queryNmArrayRef = 
	    Pdb_alignment->GetQueryNmArrayRefBYtargetNm(dbh=>$dbh,
				      target_name=>$targetNm,
				      score_cutoff=>$pvalueCutOff,
				      pct_aligned_cutoff=>$alignCutOff);
	if (!@$queryNmArrayRef) {
	    print "No Dictyostelium gene found similar to PDB ".
		font({-color=>'red'}, 
		     $self->pdbid).
		" with ".
		font({-color=>'red'}, 
		     "pscore <= $pvalueCutOff").
		" or ".
		font({-color=>'red'}, 
		     $self->pdbid).
		" is not a valid PDB ID. ", p;
	    &printEndPage;
	    exit;
	}
	
	
	$self->printSummaryTable4PDBID($queryNmArrayRef);
    }
    elsif ($self->chrnum) {
	my $alignInfoArrayRef 
	    = Pdb_alignment->GetAlignInfoArrayRefBYchrnum(dbh=>$dbh,
				       chromosome=>$self->chrnum,
                                       score_cutoff=>$pvalueCutOff,
                                       pct_aligned_cutoff=>$alignCutOff);
        if (!@$alignInfoArrayRef) {
	    print "No structural information found in chromosome ".$self->chrom,p; 
	    &printEndPage;
	    exit;
	}
	$self->printSummaryTable4CHROM($alignInfoArrayRef);
    }
    elsif ($self->keyword) {
	my $keyword = $self->keyword;
	$keyword = "%".$keyword."%";
	my $featNmArrayRef = 
	       Pdb_alignment->GetORFGeneArrayRefBYkeyword(dbh=>$dbh,
					keyword=>$keyword,
					score_cutoff=>$pvalueCutOff,
					pct_aligned_cutoff=>$alignCutOff);
	if (!@$featNmArrayRef) {
	    print "No structural information found for keyword = ".font({-color=>'red'}, $self->query), p;
	    &printEndPage;
	    exit;
	}
	$self->printSummaryTable4KEYWORD($featNmArrayRef);
    }

    print p, table({-width=>'100%'}, 
		   Tr(td({-align=>'center'},  
			 "Last updated on $lastUpdate"))),p;
    
    &printEndPage;
}

########################################################################
sub printSummaryTable4ORF {
########################################################################
    my ($self, $alignInfoArrayRef) = @_;
    my %chains4pdbid;
    my %rows4pdbid;
    my %count4pdbid;
    my $showNm = $self->locusNm || $self->featNm;
    
    foreach my $rowRef (@$alignInfoArrayRef) {
	my ($pdb, $organism, $note, $identical, $similar, $score) 
	    = @$rowRef;
	my ($pdbid, $chain) = split(/\_/, $pdb);

	if (!$chain) { next; }

	##### chain
	if (!$chains4pdbid{$pdbid}) {
	    $chains4pdbid{$pdbid} = " Chain: $chain";
	}
	else {
	    $chains4pdbid{$pdbid} .= ", ".$chain;
	}
      	
	$count4pdbid{$pdbid}++;

	if ($count4pdbid{$pdbid} == 1) { next; }

	$rows4pdbid{$pdbid} .= Tr(td({-align=>'center'},
				     b("Chain $chain = ").
				     $self->convertScore($score)).
				  td({-align=>'center'}, b($identical)).
				  td({-align=>'center'}, b($similar)).
				  td({-align=>'center'},
				     $self->alignmentLink($self->featNm, $pdb, "View alignment")));
	    
    }
    my %pdbidFound;
    my $rows = Tr(th({-colspan=>'2',
		      -rowspan=>'2',
		      -align=>'center',
		      -width=>'30%',
		      -bgcolor=>'#CCCFFF'}, 
		     "PDB protein structure(s) homologous to $showNm").
		  th({-rowspan=>'2',
		      -align=>'center',
		      -width=>'20%',
		      -bgcolor=>'#CCCFFF'}, 
		     "Homolog Source (per PDB)").
		  th({-colspan=>'4',
		      -align=>'center',
		      -width=>'40%',
		      -bgcolor=>'#CCCFFF'}, 
		     "Protein Alignment: $showNm vs. Homolog").
		  th({-rowspan=>'2',
		      -align=>'center',
		      -width=>'10%',
		      -bgcolor=>'#CCCFFF'}, "External Links")).
	       Tr(th({-align=>'center',
		      -bgcolor=>'#b7d8e4'}, "P-Value").
		  th({-align=>'center',
		      -bgcolor=>'#b7d8e4'}, "%Identical").
		  th({-align=>'center',
		      -bgcolor=>'#b7d8e4'}, "%Similar").
		  th({-align=>'center',
		      -bgcolor=>'#b7d8e4'}, "Alignment")); 

    my $bgcolor = "white";
    foreach my $rowRef (@$alignInfoArrayRef) {
	my ($pdb, $organism, $note, $identical, $similar, $score) 
	    = @$rowRef;

	my ($pdbid, $chain) = split(/\_/, $pdb);
	if ($pdbidFound{$pdbid}) { next; }
	my ($source, $desc) = $self->getSourceDesc($organism, $note);
	my $count = $count4pdbid{$pdbid} || '1';
	my $alignLink = $self->alignmentLink($self->featNm, $pdb, "View alignment"); 
	$score = $self->convertScore($score);
	if ($rows4pdbid{$pdbid}) {
	    $score = b("Chain $chain = ").$score;
	}
	else { $score = b($score); }

	my $pdbDesc = b($pdbid." (".$chains4pdbid{$pdbid}.")").br.$desc;

	my $rows4pdbid = $rows4pdbid{$pdbid};
	$rows4pdbid =~ s/<TR>/<TR BGCOLOR=\"$bgcolor\">/g;
	$rows .= Tr({-bgcolor=>"$bgcolor"},
		    td({-rowspan=>"$count"},
		       $pdbDesc).
		    td({-rowspan=>"$count"},
		       $self->pdbInfoLink($pdb)).
		    td({-rowspan=>"$count"}, $source).
		    td({-align=>'center'}, $score).
		    td({-align=>'center'}, b($identical)).
		    td({-align=>'center'}, b($similar)).
		    td({-align=>'center'}, $alignLink).
		    td({-rowspan=>"$count",
			-align=>'left'}, $self->externalDbLink($pdbid))).
		 $rows4pdbid;

        $pdbidFound{$pdbid}++;

	if ($bgcolor eq "white") {
	    $bgcolor = "#d8d8d8";
	}
	else { $bgcolor = "white"; }

    }

    my $count = keys(%pdbidFound);

    $self->printText($count);
    print table({-align=>'center',
                 -border=>1,
                 -cellpadding=>4,
                 -cellspacing=>2},
		$rows);
}

########################################################################
sub printSummaryTable4PDBID {
########################################################################
    my ($self, $queryNmArrayRef) = @_;
        
    my $rows = Tr({-bgcolor=>'#CCCFFF'},
		  th({-align=>'center'}, 
		     "Dictyostelium Gene Name").
		  th({-align=>'center'}, "Gene Product Description").
		  th({-align=>'center'}, "PDB Homologs"));
    foreach my $rowRef (@$queryNmArrayRef) {

	my ($featNm, $locusNm) = @$rowRef;

	my $gp = $self->getGP($locusNm);

	if (!$gp) { $gp = br; }

	my $showNm;
	if ($locusNm) {
	    $showNm = $locusNm."/";
	}
	$showNm .= $featNm;

	$rows .=  Tr(td(b($self->locusLink($featNm, $showNm))).
		     td($gp).
		     td({-align=>'center'}, 
			b($self->homologLink($featNm, "View List"))));

    }
    my $count = @$queryNmArrayRef;
    $self->printText($count);
    print table({-align=>'center',
		 -width=>'600',
                 -border=>3,
                 -cellpadding=>4,
                 -cellspacing=>4},
		$rows);
}


########################################################################
sub printSummaryTable4CHROM {
########################################################################
    my ($self, $alignInfoArrayRef) = @_;
        my %hitnum4Orf;
    my %foundEntry;
    foreach my $rowRef (@$alignInfoArrayRef) {
	my ($featNm, $locusNm, $pdb, $organism, $note, 
	    $identical, $similar, $score) = @$rowRef;
	my ($pdbid, $chain) = split(/\_/, $pdb);
	if ($foundEntry{$featNm.":".$pdbid}) { next; } 
	$hitnum4Orf{$featNm}++;
	$foundEntry{$featNm.":".$pdbid}++;
    }
    
    my $text = "chromosome ".$self->chrom." Gene Name"; 
    if ($self->chrom =~ /Mito/i) {
	$text = "mitochondrial chromosome Gene Name";
    }
    my $rows = Tr({-bgcolor=>'#CCCFFF'},
		  th({-align=>'center'}, $text).
		  th({-align=>'center'}, "Gene Product Description").
		  th({-align=>'center'}, "PDB Homologs"));
    my %foundOrf;
    foreach my $rowRef (@$alignInfoArrayRef) {
	my ($featNm, $locusNm, $pdb, $organism, $note, 
	    $identical, $similar, $score) = @$rowRef;

	if ($foundOrf{$featNm}) { next; }

	my $gp = $self->getGP($locusNm);

	if (!$gp) { $gp = br; }

	my $showNm;
	if ($locusNm) {
	    $showNm = $locusNm."/";
	}
	$showNm .= $featNm;

	$rows .= Tr(td(b($self->locusLink($featNm, $showNm))).
		    td($gp).
		    td({-align=>'center'}, 
			b($self->homologLink($featNm, "View List"))));

	$foundOrf{$featNm}++;
    }
##################
    my $count = keys(%hitnum4Orf);
    $self->printText($count);
    print table({-align=>'center',
		 -width=>'600',
                 -border=>3,
                 -cellpadding=>4,
                 -cellspacing=>4},
		$rows);
}


########################################################################
sub printSummaryTable4KEYWORD {
########################################################################
    my ($self, $featNmArrayRef) = @_;
    my %text4Orf;
    foreach my $rowRef (@$featNmArrayRef) {
	my ($featNm, $locusNm, $matchText) = @$rowRef;
	$text4Orf{$featNm} .= li($matchText);
    }
   
    my $rows = Tr({-bgcolor=>'#CCCFFF'},
		  th({-align=>'center'}, 
		     "Dictyostelium Gene Name").
		  th({-align=>'center'}, "Matching Text").
		  th({-align=>'center'}, "PDB Homologs"));
    my %foundOrf;
    my $kw = $self->keyword;
    foreach my $rowRef (@$featNmArrayRef) {

	my ($featNm, $locusNm, $matchText) = @$rowRef;

	if ($foundOrf{$featNm}) { next; }

       	my $matchText = $text4Orf{$featNm};
	$matchText =~ s/$kw/<B style="color:black;background-color:#ffff66">$kw<\/B>/gi;
	my $showNm;
	if ($locusNm) {
	    $showNm = $locusNm."/";
	}
	$showNm .= $featNm;

    	$rows .= Tr(td(b($self->locusLink($featNm, $showNm))).
		    td($matchText).
		    td($self->homologLink($featNm, b("View List"))));
	$foundOrf{$featNm}++;
    }
    my $count = keys(%text4Orf);
    $self->printText($count);
    print table({-align=>'center',
		 -width=>'600',
                 -border=>3,
                 -cellpadding=>4,
                 -cellspacing=>4},
		$rows);
}



########################################################################
sub displayAlignment {
########################################################################
    my ($self) = @_;

    &printStartPage($self->database, $self->title, $self->help);

    my $alignInfoArrayRef 
	= Pdb_alignment->GetAlignInfoArrayRefBYqueryNmTargetNm(
				  dbh=>$dbh,
				  query_name=>$self->featNm,
				  target_name=>$self->pdb,
				  score_cutoff=>$pvalueCutOff,
                                  pct_aligned_cutoff=>$alignCutOff);
    if (!@$alignInfoArrayRef) {
	print "No match found for Dictyostelium gene ".font({-color=>'red'}, $self->featNm)." and PDB ".font({-color=>'red'}, $self->pdb), p;
	&printEndPage;
	exit;
    }

    my $row = Tr(td(blockquote("This page compares a protein of known structure to the ".i("Dictyostelium discoideum")." protein ".font({-color=>'red'}, $self->showNm).". ".$self->analysisDesc)));

    my ($pdbid, $chain) = split(/\_/, $self->pdb);
    my $pdbShowNm = uc($pdbid);
    if ($chain) { $pdbShowNm .= " (chain ".uc($chain).")"; }

    $row .= Tr(td(table({-width=>'90%',
			 -cellpadding=>'4'},
			Tr(th({-align=>'left'},
			      font({-size=>'+1'},
				   "Alignment of Dictyostelium gene ".
				   font({-color=>'red'}, $self->showNm).
				   " and PDB protein ".
				   a({-href=>'#structure'}, 
				     $pdbShowNm))).
			   td({-align=>'center'},
			      a({-href=>"#structure"}, "Jump to".br."Structure"))))));

    my $Sobj = Pdb_sequence->new(dbh=>$dbh,
				 sequence_name=>$self->featNm);
    if (!$Sobj) { return;} 
    my $Qlen = $Sobj->sequence_length; 
    
    foreach my $rowRef (@$alignInfoArrayRef) {
	my ($Qbeg, $Qend, $Tbeg, $Tend, $pctAligned, $pctIdentical, 
	    $pctSimilar, $score, $Qseq, $Tseq, $symbol, $Torganism,
	    $Tnote) = @$rowRef;
	$score = $self->convertScore($score);
	my ($pdbid, $chain) = split(/\_/, $self->pdb);
	my $Updbid = "\U$pdbid";
	my $pdbGif = $configUrl->pdbImages."${Updbid}x300.jpg";
	my ($source, $desc) = $self->getSourceDesc($Torganism, $Tnote);

	my $exploreUrl = $configUrl->pdbCGIRoot."explore.cgi?pdbId=$pdbid";

	my $pdbDesc = $pdbid;
	if ($chain) { $pdbDesc .= " (Chain $chain)"; }
	$pdbDesc = b($pdbDesc).br.$desc;

	my $alignLen = $Qend - $Qbeg + 1;
	my $alignPercent = $alignLen*100/$Qlen;
	if ($alignPercent =~ /^([0-9]+)\.([0-9])/) {
	    $alignPercent = $1;
	    if ($2 >= 5) { $alignPercent += 1; }
	}
	my $geneNm = $self->locusNm || $self->featNm;

	$row .= Tr(th({-bgcolor=>'#CCCFFF',
		       -width=>'100%',
		       -align=>'left'}, 
		      "Alignment Details")).
		Tr(td(table({-align=>'center',
			     -width=>'90%',
			     -cellpading=>'4',
			     -cellspacing=>'4',
			     -border=>'0'},
			    Tr(td({-align=>'left',
				   -bgcolor=>'#d8d8d8'},
				  $geneNm." length = $Qlen aa").
			       td({-align=>'left',
				   -bgcolor=>'#d8d8d8'},
				  "Alignment Length = $alignLen aa  (${alignPercent}%)").
			       td({-align=>'left',
				   -bgcolor=>'#d8d8d8'},
				  "P-value = $score").
			       td({-align=>'left',
				   -bgcolor=>'yellow'},
				  "%Identity = $pctIdentical").
			       td({-align=>'left',
				   -bgcolor=>'lightgreen'},
				  "%Similar = $pctSimilar")))));
	
	$row .= Tr(th({-bgcolor=>'#CCCFFF',
		       -width=>'100%',
		       -align=>'left'},
		      "Alignment Position"));

	$row .= Tr(td($self->printBarGraph(@$alignInfoArrayRef->[0])));

	$row .= Tr(td(br)).
		Tr(th({-bgcolor=>'#CCCFFF',
		       -width=>'100%',
		       -align=>'left'},
		      a({-name=>'alignment'},
			"Sequence Alignment"))).
		Tr(td(br)).
		Tr(td($self->printHtmlAlignment(@$alignInfoArrayRef->[0])));
	
	$row .= Tr(th({-bgcolor=>'#CCCFFF',
		       -width=>'100%',
		       -align=>'left'},
		      a({-name=>'structure'},
			"Homolog Structure")));
	$row .= Tr(td(table({-align=>'center',
			     -cellspacing=>'4',
			     -border=>'0',
			     -cellpadding=>'4'},
			    Tr(td({-colspan=>'2',
				   -align=>'left'},
				  "Information provided by ".
				  a({-href=>$configUrl->pdbRoot}, 
				    "The RCSB Protein Databank (PDB)")).
			       td({-align=>'right'},
				  a({-href=>'#alignment'},
				    "Jump to ".br."alignment"))).
			    Tr(td({-valign=>'top',
				   -rowspan=>'2',
				   -bgcolor=>'lightsteelblue'},
				  "PDB protein").
			       td({-valign=>'top'},
				  $pdbDesc).
			       td({-align=>'center',
				   -width=>'300',
				   -rowspan=>'5'},
				  a({-href=>$exploreUrl,
				     -target=>'infowin'},
				    img({-src=>$pdbGif})))).
			    Tr(td($self->pdbInfoLink($self->pdb, 'quick'))).
			    Tr(td({-align=>'left',
				   -valign=>'top',
				   -bgcolor=>'lightsteelblue'}, 
				  "Homolog Source").
			       td($source)).
			    Tr(td({-align=>'left',
				   -valign=>'top',
				   -bgcolor=>'lightsteelblue'},
				  "External Links").
			       td({-valign=>'top'},
				  $self->externalDbLink($pdbid)))
			    )));


	print table({-celpading=>'4',
		     -cellspacing=>'2',
		     -border=>'0'},
		    $row);

	last;
    }

    print p, table({-width=>'100%'}, 
		   Tr(td({-align=>'center'}, 
			 "Last updated on $lastUpdate"))),p;

    &printEndPage;
}

####################################################################
sub printBarGraph {
####################################################################
    my ($self, $alignInfoRowRef) = @_;

    my ($Qbeg, $Qend, $Tbeg, $Tend, $pctAligned, $pctIdentical, 
	$pctSimilar, $score, $Qseq, $Tseq, $symbol, $Torganism,
	$Tnote) = @$alignInfoRowRef;
    
    my $Sobj = Pdb_sequence->new(dbh=>$dbh,
				 sequence_name=>$self->featNm);
    if (!$Sobj) { return;} 
    my $Qlen = $Sobj->sequence_length; 

    my $yStart = 30;
    my $rulerHeight = 3;
    my $barGap = 5;;

    my $height = $yStart + $rulerHeight + 2*$barGap + 
	         2*$defaultBarHeight + 5;

    my $gd = CreateGD->new(width=>$defaultRulerWidth+25,
			   height=>$height);
    ### draw ruler
    
    $gd->im->filledRectangle(1, $yStart, $defaultRulerWidth, 
			 $yStart+$rulerHeight, 
			 $gd->black);    
    my $tickNum = $Qlen/100;
    my $pixelNum = $defaultRulerWidth*100/$Qlen; 
    my $i;
    for ($i = 0; $i <= $tickNum; $i++) {
	$gd->im->line($i*$pixelNum+1, $yStart-4, $i*$pixelNum+1, $yStart,
		  $gd->black);
	$gd->im->string(gdSmallFont, $i*$pixelNum, $yStart-17, 
		  $i*100, $gd->black);	
	
    }
    if ($Qlen - ($i-1)*100 > 30) {
	$gd->im->line($defaultRulerWidth, $yStart-4, 
		      $defaultRulerWidth, $yStart,
		      $gd->black);
	$gd->im->string(gdSmallFont, $defaultRulerWidth-1, 
			$yStart-17, $Qlen,
			$gd->black);	
    }

    ### draw query bar

    $yStart = $yStart + $rulerHeight + $barGap;

    my $Qx1 = 1;
    my $Qx2 = $defaultRulerWidth;
    my $Qy1 = $yStart;
    my $Qy2 = $yStart+$defaultBarHeight;

    $gd->im->filledRectangle($Qx1, $Qy1, $Qx2, $Qy2, $gd->blue);    
    $gd->im->string(gdMediumBoldFont, $defaultRulerWidth/2-40, 
		$Qy1+($defaultBarHeight-10)/2, 
		$self->proteinNm, $gd->white);

    ### draw target bar

    $yStart = $yStart + $defaultBarHeight + $barGap;

    my $Tx1 = $defaultRulerWidth*$Qbeg/$Qlen;
    my $Tx2 = $defaultRulerWidth*$Qend/$Qlen;
    my $Ty1 = $yStart;
    my $Ty2 = $yStart + $defaultBarHeight;

    $gd->im->filledRectangle($Tx1, $Ty1, $Tx2, $Ty2, $gd->red); 
    $gd->im->string(gdMediumBoldFont, $Tx1+($Tx2-$Tx1)/2-40, 
		$Ty1+($defaultBarHeight-10)/2, 
		$self->pdb, $gd->white);

    my $gifDir = $configPath->tmpDir;
    my $gifHttp = $configUrl->dictyBaseHtmlTmp;
    my $gifname = $self->featNm.".".$self->pdb.".gif";

    open (OUT, ">".$gifDir.$gifname)||die "Can't create ".$gifDir.$gifname.":$!";
    binmode OUT;
    print OUT $gd->im->gif;
    close OUT;
    return center(img({-src=>$gifHttp.$gifname}));
}

####################################################################
sub printHtmlAlignment {
####################################################################
    my ($self, $alignInfoRowRef) = @_;

    my ($Qbeg, $Qend, $Tbeg, $Tend, $pctAligned, $pctIdentical, 
	$pctSimilar, $score, $Qseq, $Tseq, $symbol, $Torganism,
	$Tnote) = @$alignInfoRowRef;
    my $geneNm = $self->locusNm || $self->featNm;
    my $orf = $self->locusLink($geneNm, $geneNm);
    my ($pdbid, $chain) = split(/\_/, $self->pdb);
    my $pdbShowNm = "\U$pdbid";
    if ($chain) { $pdbShowNm .= "_($chain)"; }
    my $pdb = $self->pdblink($pdbid, $pdbShowNm);
    
    my @symbolChars = split(//, $symbol);
    my @queryChars = split(//, $Qseq);
    my @targetChars = split(//, $Tseq);
    my $rows;
    while (@queryChars) {
	my ($queryLine, $symbolLine, $targetLine);
	$queryLine = td({-align=>'right'}, $Qbeg).td(br).td(br);
	$symbolLine = td(br).td(br).td(br);
	$targetLine = td({-align=>'right'}, $Tbeg).td(br).td(br);
	$Qbeg--;
	$Tbeg--;
	for (my $i = 0; $i < 60; $i++) {
	    # if (!@queryChars) { last; }
	    my $queryChar = shift (@queryChars);
	    my $symbolChar = shift (@symbolChars);
	    my $targetChar = shift (@targetChars);
	    if ($queryChar && $queryChar !~ /\-/) { $Qbeg++;}
	    if ($targetChar && $targetChar !~ /\-/) { $Tbeg++; }
	    my $bgcolor = "white";
	    if ($symbolChar =~ /\:/) {
		$bgcolor= "yellow";
	    }
	    elsif ($symbolChar =~ /\./) {
		$bgcolor= "lightgreen";
	    }
	    else {
		$bgcolor= "white";
	    }
	    $queryLine .= td({-bgcolor=>"$bgcolor"},
			     (tt($queryChar)));
	    $symbolLine .= td({-bgcolor=>"$bgcolor"},
			      (tt($symbolChar)));
	    $targetLine .= td({-bgcolor=>"$bgcolor"},
			      (tt($targetChar)));
	}
	$queryLine .= td(br).td(br).td($Qbeg);
	$targetLine .= td(br).td(br).td($Tbeg);
	$symbolLine .= td(br).td(br).td(br);
	$Qbeg++;
	$Tbeg++;
	$rows .= Tr(th({-align=>'right'},
		       font({-color=>'blue'}, $orf)).td(br).td(br).
		    $queryLine).
		 Tr(td(br).td(br).td(br).
		    $symbolLine).
		 Tr(th({-align=>'right'},
		       font({-color=>'red'}, $pdb)).td(br).td(br).
		    $targetLine).
		 Tr(td({-colspan=>'70'}, br));
    }

    return table({-align=>'center',
		    -border=>'0',
		    -cellspacing=>'0',
		    -cellpading=>'0'},
		    $rows);
}


########################################################################
sub homologLink {
########################################################################
    my ($self, $orf, $showNm) = @_;
    return a({-href=>url."?locus=$orf"},
	     $showNm);
}

########################################################################
sub alignmentLink {
########################################################################
    my ($self, $orf, $pdb, $showNm) = @_;
    return a({-href=>url."?locus=$orf&pdb=$pdb&align=1"},
	     $showNm);
}

########################################################################
sub locusLink {
########################################################################
    my ($self, $featNm, $showNm) = @_;
    return a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=$featNm",
	      -target=>'infowin'},
	     $showNm);
}

########################################################################
sub pdblink {
########################################################################
    my ($self, $pdbid, $showNm) = @_;
    if (!$showNm) { $showNm = $pdbid; }
    return a({-href=>$configUrl->pdbCGIRoot."explore.cgi?pdbId=$pdbid", 
	      -target=>'infowin'}, 
	     $showNm);
}

########################################################################
sub convertScore {
########################################################################
    my ($self, $score) = @_;
    $score = exp($score);
    $score =~ s/^([^\.])\.([0-9]).+(e-.+)$/$1\.$2$3/;
    if ($score !~ /e/i) {
	$score = substr($score, 0, 8);
    }
    return $score;
}

########################################################################
sub getSourceDesc {
########################################################################
    my ($self, $organism, $note) = @_;
    $note =~ s/\$//g;
    my ($source, $desc);
    if ($organism !~ /^(unknown|other)$/i) {
	$source = $organism;
    }
    elsif ($note =~ /organism_scientific: /) {
	lc($note);
	my @note = split(/organism_scientific: /, $note);
	shift @note;
	my %foundOrg;
	foreach my $thisNote (@note) {
	    if ($thisNote =~ /^([^\;]+)/) {
		my $thisOrg = $1;
		if (!$foundOrg{"\U$thisOrg"}) {
		    $thisOrg = "\u$thisOrg";
		    if ($source) { $source .= " | "; }
		    $source .= $thisOrg;
		}
		$foundOrg{"\U$thisOrg"}++;
	    }
	}
    }
    elsif ($note =~ /SOURCE: (.+)$/i) {
	$source = "\u$1";
    }
    else {
	$source = "Unknown";
    }
    if ($note =~ /^(.+)\; SOURCE: /i) {
	$desc = $1;
    }
    else {
	$desc = $note;
    }
    if ($source =~ /^\((.+)\)$/) {
	$source = "\u$1";
    }
    return ($source, $desc);
}

########################################################################
sub getGP {
########################################################################
    my ($self, $locusNm) = @_;
    if (!$locusNm) { return; }
    my $locusObj = Locus->new(dbh=>$dbh,
			      locus_name=>$locusNm);
    if (!$locusObj) { return; }
    my $gpList = $locusObj->gene_product;
    my @gp = split(/\t/, $gpList);
    my $gp;
    foreach my $gpItem (@gp) {
       $gp .= li($gpItem);
    }
    return $gp;
}

########################################################################
sub printText {
########################################################################
    my ($self, $count) = @_;
    my $text;
    if ($self->featNm) {
	my $geneLinks = b($self->showNm." links").br.li(a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=".$self->featNm, -target=>'infowin'}, 
			     "Locus Info"));
	my $motifObj = Motif->new(seqname=>$self->featNm);
	if ($motifObj->hasMotif) {
	    $geneLinks .= li(a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/protein/getDomain?locus=".$self->featNm, -target=>'infowin'},
			    "Protein Motifs"));
	}

	$text = table({-width=>'100%',
		       -cellpadding=>'4',
		       -cellspacing=>'2',
		       -border=>'0'}, 
		      Tr(td(b(blockquote("This page presents information for the proteins of known structure with sequence similarity to the ".i("Dictyostelium discoideum")." protein ".font({-color=>'red'}, $self->showNm).". ".$self->analysisDesc))).
			 td("&nbsp;")).
		      Tr(td({-align=>'left',
			     -width=>'80%'},
			    blockquote("Last updated on $lastUpdate").p.
			    b(font({-size=>'+1'}, 
				   $count." PDB homolog(s) found for Dictyostelium gene ".font({-color=>'red'}, $self->showNm)))).
			 th({-width=>'20%',
			     -align=>'left',
			     -bgcolor=>'#b7d8e4'},
			    $geneLinks)));
    }
    elsif ($self->pdbid) {
	$text = "$count Dictyostelium gene(s) similar to PDB ".font({-color=>'red'}, $self->pdbid);
    }
    elsif ($self->chrom) {
	$text = "$count Dictyostelium genes in "; 
	if ($self->chrom =~ /Mito/i) {
	    $text .= "mitochondrial chromosome";
	}
	else {
	    $text .= "chromosome ".$self->chrom;
	}
        $text .= " have PDB structural info";
    }
    elsif ($self->keyword) {
	$text = "$count Dictyostelium gene(s) match keyword(s) ".font({-color=>'red'}, $self->keyword);
    }
    print p, center(b($text)),p;
}


########################################################################
sub QuickPDB {
########################################################################
    my ($self, $pdbid) = @_;
    
#    if ($ENV{'HTTP_USER_AGENT'} !~ /MSIE/i) {
#	return a({-href=>$configUrl->pdbCGIRoot."explore.cgi?job=graphics&pdbId=$pdbid", 
#		  -target=>'infowin'}, 
#		 "PDB_Structure_Explorer");
#    }
#    else {
	my $codebase = $configUrl->rcsbRoot.'java/classes/';
	my $quickpdb = $configUrl->pdbRoot.'quickpdb';
	my $pdbcgi = $configUrl->pdbCGIRoot;
	my $exploreUrl = $pdbcgi."explore.cgi?pdbId";
	return "<APPLET CODE='QuickPDB.class' WIDTH='65' HEIGHT='25' CODEBASE='$codebase' VALIGN='TOP'><PARAM name='moose_db' value='/misc/rcsb/prod/servers/www/../../data/pdb/db/pom/pdbplus'> <PARAM name='html_url' value='$quickpdb'> <PARAM name='cgi_url' value='$pdbcgi'> <PARAM name='struc_id' value='$pdbid'><PARAM name='rcsb_explore_url' value='$exploreUrl'> </APPLET>";

#    }
}

########################################################################
sub pdbInfoLink {
########################################################################
    my ($self, $pdb, $quick) = @_; 
    my ($pdbid, $chain) = split(/\_/, $pdb);
    my $pdbInfoLink = li(a({-href=>$configUrl->pdbCGIRoot."explore.cgi?pdbId=$pdbid",
			    -target=>'infowin'},
			   "PDB_Info"));
    my $seqObj = Pdb_sequence->new(dbh=>$dbh,
				   sequence_name=>$pdb);
    
    if (!$quick) {
	$pdbInfoLink .= li(a({-href=>$configUrl->pdbCGIRoot."explore.cgi?job=graphics&pdbId=$pdbid",
			      -target=>'infowin'},
			     "PDB_Structure"));
    }
    if ($seqObj) {  
	my $refNoList = Reflink->GetRefNoListBYtabNmPrikeyPrikeycol(
		           dbh=>$dbh,
			   tab_name=>'PDB_SEQUENCE',
                           primary_key=>$seqObj->pdb_sequence_no,
			   primary_key_col=>'PDB_SEQUENCE_NO');
	my @refNo = split(/\:/, $refNoList);
	if (@refNo == 1) {
	    $pdbInfoLink .= li(a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/reference/reference.pl?refNo=$refNo[0]",
				  -target=>'infowin'}, "Reference"));
	}
	elsif (@refNo > 1) { 
	    $pdbInfoLink .= li(a({-href=>url."?pdbid=$pdbid&refNo=$refNoList",
				  -target=>'infowin'}, "References"));
	       
	}
    }
    if ($quick) {
	$pdbInfoLink .= li($self->QuickPDB($pdbid));
    }
    return $pdbInfoLink;
}

########################################################################
sub externalDbLink {
########################################################################
    my ($self, $pdbid) = @_;
    return li(a({-href=>"http://scop.mrc-lmb.cam.ac.uk/scop/search.cgi?pdb=$pdbid", -target=>'infowin'}, "SCOP")).
	   li(a({-href=>"http://www.ncbi.nlm.nih.gov/Structure/mmdb/mmdbsrv.cgi?db=t&form=6&Dopt=s&uid=$pdbid", -target=>'infowin'}, "MMDB")).
	   li(a({-href=>"http://www.biochem.ucl.ac.uk/cgi-bin/cath/SearchPdb.pl?query=$pdbid&type=PDB", -target=>'infowin'}, "CATH"));

}


########################################################################
sub initGlobalVars {
########################################################################
    my ($self) = @_;
    $configUrl = ConfigURLdictyBase->new;
    $dblink = $configUrl->dblink($self->database);
    $configPath = ConfigPathdictyBase->new;
}

########################################################################
sub setIdentifier {
########################################################################
    my ($self) = @_;

    ### get last updated date: 
    my $seqObj = Pdb_sequence->new(dbh=>$dbh,
				   sequence_name=>'YFL039C');

    if ($seqObj) { $lastUpdate = $seqObj->date_created; }

    ############################

    if (param('chr')) {
	my %chr2num = ('I'=>'1', 'II'=>'2', 'III'=>'3', 'IV'=>'4', 
		       'V'=>'5', 'VI'=>'6', 'VII'=>'7', 'VIII'=>'8',
		       'IX'=>'9', 'X'=>'10', 'XI'=>'11', 'XII'=>'12',
		       'XIII'=>'13', 'XIV'=>'14', 'XV'=>'15', 'XVI'=>'16',
		       'Mito'=>'17');
	my %num2chr = ('1'=>'I', '2'=>'II', '3'=>'III', '4'=>'IV',
		       '5'=>'V', '6'=>'VI', '7'=>'VII', '8'=>'VIII',
		       '9'=>'IX', '10'=>'X', '11'=>'XI', '12'=>'XII',
		       '13'=>'XIII', '14'=>'XIV', '15'=>'XV', '16'=>'XVI',
		       '17'=>'Mito');
	if (param('chr') =~ /^[0-9]+$/) {
	    $self->{'_chrnum'} = param('chr');
	    $self->{'_chrom'} = $num2chr{$self->chrnum};
	}
	elsif (param('chr') =~ /^[IVXMTO]+$/i) {
	    $self->{'_chrom'} = uc(param('chr'));
	    if ($self->{'_chrom'} =~ /^MITO/i) {
		$self->{'_chrom'} = "Mito";
	    }
	    $self->{'_chrnum'} = $chr2num{$self->chrom};
	}
	else {
	    $self->err_report("You must choose a chromosome before press 'Search' button.");
	    exit;
	}
	$self->{'_summary'} = 1;
	return;
    }	  
    if (param('dictyBaseid')) {
	my $dictyBaseid = param('dictyBaseid');
	&DeleteUnwantedChar(\$dictyBaseid);
	my $dictyBaseidObj = dictyBaseid->new(dbh=>$dbh,
				  dictyBaseid=>$dictyBaseid);
	if (!$dictyBaseidObj) {
	    $self->err_report("The dictyBaseid = $dictyBaseid is not found in our database.");
	    exit;
	}
	$self->{'_featNm'} = $dictyBaseidObj->feature_name;
	if (!$self->{'_featNm'}) {
	    $self->err_report("The dictyBaseid = $dictyBaseid is not associated with any feature name in database.");
	    exit;
	}
	$self->{'_locusNm'} = $dictyBaseidObj->locus_name;
	$self->setShowNm;
	$self->{'_summary'} = 1;
	return;
    }
    if (param('gi')) {
	my $gi = param('gi');
	&DeleteUnwantedChar(\$gi);
	my ($featNm, $locusNm) = Feature->GetFeatNmLocusNmBYgiNo(dbh=>$dbh,
					      gi=>$gi);		
	if (!$featNm) {
	   $self->err_report("The NCBI gi number = $gi is not associated with any feature/gene in database.");
	    exit; 
	}
	$self->{'_featNm'} = $featNm;
	$self->{'_locusNm'} = $locusNm;
	$self->setShowNm;
	$self->{'_summary'} = 1;
	return;
    }
    if (param('keyword')) {
	my $keyword = param('keyword');
	&DeleteUnwantedChar(\$keyword);
	$self->{'_keyword'} = $keyword;
	$self->{'_summary'} = 1;
	return;
    } 
    if (param('locus')) {
	my $locus = param('locus');
	&DeleteUnwantedChar(\$locus);
	my $featObj = Feature->new(dbh=>$dbh,
				   feature_name=>$locus);
	if ($featObj) {
	    $self->{'_featNm'} = $featObj->feature_name;
	    $self->{'_locusNm'} = $featObj->locus_name;
	}
	else {
	    my $locusObj = Locus->new(dbh=>$dbh,
				      locus_name=>$locus);
	    if ($locusObj) {
		$self->{'_locusNm'} = $locusObj->locus_name;
		$self->{'_featNm'} = $locusObj->featureNameList;
	    }
	    else {
		$self->err_report("The feature/locus = ".font({-color=>'red'}, $locus)." is not found in database.");
		exit;
	    }
	}
	$self->setShowNm;
	if (!param('align')) {
	    $self->{'_summary'} = 1;
	}
	else { 
	    $self->{'_pdb'} = param('pdb');
	}
	return;
    }
    if (param('pdbid')) {
	my $pdbid = param('pdbid');
	&DeleteUnwantedChar(\$pdbid);
	$self->{'_pdbid'} = $pdbid;
	$self->{'_summary'} = 1;
	return;
    } 
}

########################################################################
sub setShowNm {
########################################################################
    my ($self) = @_;
    if ($self->locusNm) {
	$self->{'_showNm'} = $self->locusNm."/";
	my $proteinNm = $self->locusNm;
	$proteinNm = "\L$proteinNm";
	$proteinNm = "\u$proteinNm"."p";
	$self->{'_proteinNm'} = $proteinNm;
    }
    else {
	$self->{'_proteinNm'} =$self->featNm."p"; 
    }
    $self->{'_showNm'} .= $self->featNm;
}

########################################################################
sub setHelp4summary {
########################################################################
    my ($self) = @_;
    if ($self->featNm) {
	$self->{'_help'} = "PDB_Homolog.html";
    }
    elsif ($self->pdbid) {
	$self->{'_help'} = "PDB_query.html";
    }
    elsif ($self->chrnum) {
	$self->{'_help'} = "Chrom_query.html";
    }
    elsif ($self->keyword) {
	$self->{'_help'} = "keyword_query.html";
    }

}

########################################################################
sub setTitle4summary {
########################################################################
    my ($self) = @_;
    if ($self->keyword) {
	$self->{'_title'} = "Search results for "."'".$self->keyword."'";
    }
    elsif ($self->chrom) {
	$self->{'_title'} = "Dictyostelium Proteins in Chromosome ".$self->chrom;
    }
    elsif ($self->featNm) {
	my $showNm;
	if ($self->locusNm) { $showNm = $self->locusNm."/"; }
	$showNm .= $self->featNm;
	$self->{'_title'} = "PDB Homolog: ".$showNm;
    }
    elsif ($self->pdbid) {
	$self->{'_title'} = "Dictyostelium Genes Similar to PDB ".$self->pdbid;
    }
    else {
	$self->err_report("Unknown class type. The class type should be 'identifier', 'keyword' or 'chromosome'. Please change it and try again.");
	exit;
    }
}

########################################################################
sub description {
########################################################################
    my ($self) = @_;
    return "This query page allows you to search for structural information on ".i("Dictyostelium discoideum")." proteins. The search will retrieve both the Dictyostelium protein structure (if it has been solved) and other proteins of known structure, regardless of source, that have sequence similarity to the query protein.".$self->analysisDesc.p."Search for PDB homologs using one of the following parameters. See ".a({-href=>$configUrl->dictyBaseHelp."pdbhelp.html"}, "HELP")." for detailed descriptions of each search parameter.";

}

########################################################################
sub analysisDesc {
########################################################################
    return "The analysis was performed by comparing Dictyostelium protein sequences against protein sequences in ".a({-href=>$configUrl->pdbRoot, -target=>'infowin'}, "The RCSB Protein Databank (PDB)")." using Smith-Waterman analysis program.";

}

########################################################################
sub err_report {
########################################################################
    my ($self, $err) = @_;
    
    $self->{'_title'} = "Dictyostelium Protein Structural Information: Error Report";
    &printStartPage($self->database, $self->title, $self->help);
   
    print b($err);
    
    &printEndPage;

    exit;
}

########################################################################
1;
########################################################################






























