#!/usr/bin/perl
package ExpressionConnection;
#######################################################################
##### Author :	Shuai Weng
##### Date   :  Nov. 2002
##### Description :  This package contains all necessary methods for 
#####                searching gene expression data from multiple
#####                microarray studies.
#####              
#######################################################################
use strict;
use DBI;
use CGI qw/:all :html3/;
use GD;

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use ConfigURLdictyBase;
use ConfigPathdictyBase;
use SeqParamTranslator;
use Dataset;
use Feature;
use CreateGD;

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);
use dictyBaseObject;

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects/MAP";
use MapUtil;


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

my $dbh;
my $dblink; 
my $configUrl;
my $configPath;
my $cubeImage;
my $loci;
my @orf;
my @dataset;
my $sortBy;
my $exprtype;
my $fold;
my %datasetTitle;
my %featNo4featNm;
my %featNo4featNmInAll;
my %featNm4geneInAll;
my %maxExprVal4featNm;
my %minExprVal4featNm;
my %gene4featNm;
my %gene4featNmInAll;
my %genes4dataset;
my %expts4dataset;
my %geneNum4dataset;

my $locusUrl;

my $maxDisplayNum = 20;

my $totalGene;


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

	$self = {};

	bless $self;

      	$self->{'_database'} = $args{'database'};
	$self->{'_help'} = $args{'help'};
	$self->{'_title'} = $args{'title'} || "Expression Connection";
	
	$dbh = &ConnectToDatabase($self->{'_database'});

    	return $self;

}

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

sub help { $_[0]->{_help} }
sub database { $_[0]->{_database} }
sub title { $_[0]->{_title} }

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

    	my ($self) = @_;

	$self->setVariables;

	if (!param || param('newSearchSubmit') || param('ORFs')) {

	    $self->printEntryForm;

	    exit;
	}
	if (param('query') && param('noSearch')) {
	    
	    param('loci', param('query'));

	    $self->printEntryForm;

	    exit;
	    
	}

	$self->setHelp;

	$self->choosePageToPrint;

	exit;

}

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

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

	$self->printOption1;

	$self->printOption2;

	$self->printOption3;

#	$self->additionalSearch;

	&printEndPage;
}

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

    if (param('type') =~ /^histogram/i) {
	
	$self->{'_help'} .= "#histograph";

    }
    elsif (param('type') =~ /^graph/i) {

	$self->{'_help'} .= "#graph";

    }
    elsif (param('type') =~ /^Pearson/i) {

	$self->{'_help'} .= "#pearson";

    }

}

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

    &printStartPage($self->database, $self->title, $self->help);
      
    if (param('submit1') || param('option') =~ /option1/i) {

	$self->showResultForOption1;

    }
    elsif (param('orf') && param('dataset') && !param('type')) {

	# $self->showResultForOption1;

	$self->showSimilarResult;

    }
    elsif (param('submit2') || param('option') =~ /option2/i) {

	$self->showResultForOption2;
    
    }
    elsif (param('submit3') || param('option') =~ /option3/i) {

	$self->showResultForOption3;

    }
    elsif (param('downloadSubmit')) {

	$self->showDownloadList;

    }
    elsif (param('type') =~ /^statistic/i) {
	
	$self->showStatisticForDataset;

    }
    elsif (param('type') =~ /^histogram/i) {

	$self->showHistogramForGene;

    }
    elsif (param('type') =~ /^enlarge/i) {

	$self->showEnlargeResult;

    }
    elsif (param('type') =~ /^similar/i) {

	$self->showSimilarResult;

    }
    elsif (param('type') =~ /^graph/i) {

	$self->showGraph;

    }
    elsif (param('type') =~ /^Pearson/i) {

	$self->showPearsonCorrelation;

    }
    elsif (param('type') =~ /^regulatedBy/i) {

	$self->showRegulatorList;

    }
    elsif (param('type') =~ /^regulator/i) {

	$self->showRegulationModuleList;

    }
    elsif (param('more') && param('id')) {
	
	$self->showGeneList;

    }
    elsif (param('sortSubmit') || param('wholeSubmit')) {
	
	$self->sortAndShowResult;

    }
    elsif (param('orf') && param('fold')) {

	$self->showDatasetExpt;

    }
    else {

	print p, "Unknown display parameter.", p;

    }


    if ($self->{'_error'}) {

	print p, $self->{'_error'}, p;

    }

    &printEndPage;

}

########################################################################
sub showResultForOption1 {
########################################################################
    my ($self) = @_;
 
    $self->printSubtitle("Your Search Parameters");

    $self->printSearchParamForOption1;
   
    $self->lineSeparator;

    $self->printSubtitle("Results");

    $self->printScaleEtc1;

#    my $rows;

    foreach my $dataset (@dataset) {

	### in order to associate this link to each table, 
	### we have to print one table at a time

	print "<a name='$dataset'>";

	print table({-border=>'0',
		     -cellspacing=>'1',
		     -cellpadding=>'2'},
		    $self->getResultForDataset($dataset));

	if ($self->{'_noData'}{$dataset}) {

	    $self->{'_noData'}{$dataset} =~ s/^://;

	    $self->{'_noData'}{$dataset} =~ s/\:/, /g;
	    
	    $self->{'_noData'}{$dataset} 
	       =~ s/^(.+, [^\,]+,) ([^\,]+)$/$1 and $2/; 

	    $self->{'_noData'}{$dataset} 
	       =~ s/^([^\,]+), ([^\,]+)$/$1 and $2/; 
	    
	    print p, "No expression data found for ".$self->{'_noData'}{$dataset}." in this dataset.", p;

	}


#	$rows .= $self->getResultForDataset($dataset);

    }
    
#    print table({-border=>'0',
#	         -cellspacing=>'1',
#		 -cellpadding=>'2'},
#		$rows);

    $self->lineSeparator;     
}

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

    $self->printSubtitle("Your Search Parameters");

    $self->printSearchParamForOption2;
   
    $self->lineSeparator;

    $self->printSubtitle("Results");

    if ($exprtype =~ /No Data/i) {

	foreach my $orf (@orf) {

	    $self->printNoDataResultForOrf($orf);

	}

    }
    else {
    
	$self->printScaleEtc2;

	foreach my $orf (@orf) {

	    $self->printResultForOrf($orf);

	}
    
    }
    $self->lineSeparator;   

}

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

    $self->printSubtitle("Your Search Parameters");

#    $self->printSearchParamForOption3;
   
#    $self->lineSeparator;

#    $self->printSubtitle("Results");

    if ($exprtype =~ /No Data/i) {

	$self->printSearchParamForOption3;
   
	$self->lineSeparator;

	$self->printSubtitle("Results");

	foreach my $dataset (@dataset) {

	    $self->printNoDataResultForDataset($dataset);

	}

    }
    else {

#	$self->printScaleEtc3;

	my %tables;
    
	my $count;
	foreach my $dataset (@dataset) {

	    $count++;

	    my $id = $$.$count.$count;
 
	    $tables{$dataset} = table({-border=>'0',
				       -cellspacing=>'1',
				       -cellpadding=>'2'},
			    $self->getResultForDataset($dataset, $id));

#	    print "Total $totalGene genes found in $dataset",p;

	}

	$self->printSearchParamForOption3;
   
	$self->lineSeparator;

	$self->printSubtitle("Results");

	$self->printScaleEtc3;

	### in order to associate each dataset anchor to 
	### each table, we have to go over the dataset 
	### array one more time ...
	
	foreach my $dataset (@dataset) {

	    print "<a name='$dataset'>";

	    print $tables{$dataset};

	}
	
    }

    $self->lineSeparator;  

}

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

    my $orf = param('orf');
    my $fold = param('fold');

    &DeleteUnwantedChar(\$orf);
    &DeleteUnwantedChar(\$fold);
 
    if (!$orf || !$fold) { 
	
	print "You have to pass the feature_name and expression fold change for displaying the dataset and experiment list.",p;
	
	return;

    }

    my $featObj = Feature->new(dbh=>$dbh,
			       feature_name=>$orf);

    if (!$featObj) {

	print "The feature_name $orf is not found in our database.",p;

	return;

    }

    my $showNm = $featObj->locus_name;

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

    $showNm .= $featObj->feature_name;

    $showNm = a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=".$featObj->feature_name}, $showNm);

    my $arrayRef = Dataset->GetDatasetSampleBYfeatureNo(dbh=>$dbh,
				 feature_no=>$featObj->feature_no);

    if (!@$arrayRef) {
    
	print "No expression data found for feature_name $orf.",p;

	return;

    }
    

    my $rows;

    foreach my $rowRef (@$arrayRef) {

	my ($dataset, $expt, $exprVal) = @$rowRef;

	my ($thisfold, $decimal) = split(/\./, $self->exprFold($exprVal));

	if ($decimal >= 5 && $thisfold >= 0) {

	    $thisfold++;

	}
	elsif ($decimal >= 5 && $thisfold < 0) {

	    $thisfold--;

	}
	
	if ($thisfold != $fold) { next; }

	$rows .= Tr(td($dataset).td($expt));	
	
    }

    my $text;
    if ($fold > 0) {
	$text = "increased ${fold}-fold";
    }
    elsif ($fold < 0) {
	$fold =~ s/^-//;
	$text = "decreased ${fold}-fold";
    }
    else { $text = "not changed"; }

    print center(font({-size=>'+2'}, b("Experiment(s) with expression $text for $showNm"))),p;

    print table({-align=>'center',
		 border=>1,
		 cellpadding=>3},
		Tr({-bgcolor=>'#a4abc2'},
		   th("Dataset").
		   th("Experiment")).
		$rows),p;

}

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

    my $orf = param('orf');
    
    &DeleteUnwantedChar(\$orf);

    if (!$orf) { 
	
	print "You have to pass the feature_name for displaying the histogram",p;
	
	return;

    }

    my $featObj = Feature->new(dbh=>$dbh,
			       feature_name=>$orf);

    if (!$featObj) {

	print "The feature_name $orf is not found in our database.",p;

	return;

    }

    my $arrayRef = Dataset->GetExprValBYfeatureNo(dbh=>$dbh,
				 feature_no=>$featObj->feature_no);

    if (!@$arrayRef) {
    
	print "No expression data found for feature_name $orf.",p;

	return;

    }

    my %count4fold;

    foreach my $rowRef (@$arrayRef) {

	my ($exprVal) = @$rowRef;

	my ($fold, $decimal) = split(/\./, $self->exprFold($exprVal));

	if ($decimal >= 5 && $fold >= 0) {

	    $fold++;

	}
	elsif ($decimal >= 5 && $fold < 0) {

	    $fold--;

	}
	    
	$count4fold{$fold}++;

    }

    my ($maxCount, $minFold, $maxFold);

    foreach my $fold (sort {$a<=>$b} keys %count4fold) {

	if (!$maxCount || $maxCount < $count4fold{$fold}) {

	    $maxCount = $count4fold{$fold};

	}

	if (!$maxFold || $maxFold < $fold) {

	    $maxFold = $fold;

	}

	if (!$minFold || $minFold > $fold) {

	    $minFold = $fold;

	}
	
    }

    my $showNm = $featObj->locus_name;

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

    $showNm .=$featObj->feature_name;

    my $border = 50;
    my $width = ($maxFold - $minFold + 1)*15;
    if ($width < 350) { $width = 350; }
    my $height = 300;
   
    ### Create output image object 
    my $gd = CreateGD->new(width=>$width+2*$border,
			   height=>$height+2*$border);

    print "<MAP NAME='histogramGif'>";
   
    MapUtil->DrawFrameWithLabelAndDate(gd=>$gd,
                                       width=>$width+2*$border,
                                       height=>$height+2*$border,
                                       text=>'dictyBase');

    $self->drawTitle($gd, $showNm, $width, $height, $border);

    $self->drawBorderAndBackground($gd, $width, $height, $border);

    my ($pixelPerFold, $xStartForMinFold) = 
	$self->drawXlabel($gd, $minFold, $maxFold, 
			  $width, $height, $border);

    my $pixelPerCount = 
	$self->drawYlabel($gd, $maxCount, $width, $height, $border);

    $self->drawBars($gd, $pixelPerFold, $xStartForMinFold, $minFold,
		    $pixelPerCount, \%count4fold, $height, $border, 
		    $featObj->feature_name);

    print "</MAP>";

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

    open (OUT, ">".$gifDir.$gifname)||die "Can't create ".$gifDir.$gifname.":$!";
    binmode OUT;
    print OUT $gd->im->gif;
    close OUT;
    
    print center(font({-size=>'+2'}, b("Expression Histogram for ".a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=".$featObj->feature_name}, $showNm)))),p;

#    print center(img({-src=>$gifHttp.$gifname, 
#		      -usemap=>'#histogramGif'})),p;

    print ul(li("This graph shows you how many experiments ".a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=".$featObj->feature_name}, $showNm)." mRNA expression changed by 2 fold, 4 fold, and etc.").
	     li("A negative number means expression is repressed. A positive
number means expression is induced.").
	     li("Click on the bars to see the list of experiments.")),p;

    print center(img({-src=>$gifHttp.$gifname, 
		      -usemap=>'#histogramGif'})),p;

}

########################################################################
sub drawTitle {
########################################################################
    my ($self, $gd, $showNm, $width, $height, $border) = @_;

    my $mapTitle = "Number of Experiments vs. Fold Change in $showNm";
 
    my $nameX = $border + $width/2-length($mapTitle)*4;

    my $nameY = 15;
    
    $gd->im->string(gdLargeFont, $nameX, $nameY, $mapTitle, 
		    $gd->black);

}

########################################################################
sub drawBorderAndBackground {
########################################################################
    my ($self, $gd, $width, $height, $border) = @_;

    $gd->im->filledRectangle($border+1, $border+1, 
		       $width+$border-2, $height+$border-2, 
		       $gd->lightGrey);

    $gd->im->rectangle($border, $border, $width+$border-1, 
		       $height+$border-1, $gd->maroon);
    $gd->im->rectangle($border+1, $border+1, 
		       $width+$border-2, $height+$border-2, 
		       $gd->maroon);
}

########################################################################
sub drawXlabel {
########################################################################
    my ($self, $gd, $minFold, $maxFold, $width, 
	$height, $border) = @_;

    my $foldUnit = 2;

    if ($maxFold - $minFold > 20) { $foldUnit = 5; }
    elsif($maxFold - $minFold <= 6) { $foldUnit = 1; }
 
    my $dx = $width*$foldUnit/($maxFold-$minFold+2*$foldUnit);

    my $fold;
    if ($minFold < 0) {
	$fold = int($minFold/$foldUnit-1)*$foldUnit;
    }
    else { 
	$fold = int($minFold/$foldUnit)*$foldUnit;
    }

    my $xStart = 10;

    my $pixelPerFold = $dx/$foldUnit;
    my $xStartForMinFold = $xStart + ($minFold-$fold)*$pixelPerFold;
	
    for (my $X = $border+$xStart; $X < $width+$border; $X += $dx) {
	
	my $x = $X;

	$gd->im->line($x, $height+$border-1, $x, $height+$border-5, 
		      $gd->black);

	if ($fold <= -10) { $x -= 6; }
	elsif ($fold >= 0 && $fold < 10) { $x += 6; }
	elsif ($fold > 10) { $x += 3; }

	$gd->im->string(gdLargeFont, $x-10, $height+$border, $fold, 
			$gd->black);

	$fold += $foldUnit;

    }

    my $xLabel = "Fold Change";

    my $nameX = $border + $width/2-length($xLabel)*4;

    my $nameY = $height + $border + 20;
    
    $gd->im->string(gdLargeFont, $nameX, $nameY, $xLabel, 
		    $gd->black);

    return ($pixelPerFold, $xStartForMinFold);


}

########################################################################
sub drawYlabel {
########################################################################
    my ($self, $gd, $maxCount, $width, $height, $border) = @_;

    my $countUnit;
    
    if ($maxCount > 200) { $countUnit = 50; }
    if ($maxCount > 100) { $countUnit = 20; }
    elsif ($maxCount > 50) { $countUnit = 10; }
    elsif ($maxCount > 20) { $countUnit = 5; }
    else { $countUnit = 2; }

    my $dy = ($height-25)*$countUnit/$maxCount;

    my $pixelPerCount = $dy/$countUnit;

    my $count = 0;

    for (my $Y = $height+$border; $Y >= $border; $Y -= $dy) {

	my $y = $Y;
	
	if ($count != 0) {
	
	    $gd->im->line($border+1, $y, $border+$width-1, $y, 
			  $gd->darkGrey);
	}

	if ($count < 10) { $y -= 12; }
	elsif ($count < 100) { $y -= 6; }
	
	$gd->im->stringUp(gdLargeFont, $border-15, $y+12, $count, 
			$gd->black);

	$count += $countUnit;

    }

    my $yLabel = "Number of Experiments";

    my $nameY = ($height+2*$border)/2+length($yLabel)*4;

    my $nameX = 10;
    
    $gd->im->stringUp(gdLargeFont, $nameX, $nameY, $yLabel, 
		      $gd->black);

    return $pixelPerCount;

}

########################################################################
sub drawBars {
########################################################################
    my ($self, $gd, $pixelPerFold, $xStartForMinFold, $minFold,
	$pixelPerCount, $count4foldHashRef, $height, $border,
	$orf) = @_;

    foreach my $fold (keys %$count4foldHashRef) {

	my $x = $border + $xStartForMinFold + 
	    ($fold-$minFold)*$pixelPerFold;

	my $x1 = $x - 4;
	my $x2 = $x1 + 8;

	my $y1 = $height + $border - 
	    $$count4foldHashRef{$fold}*$pixelPerCount;
	
	my $y2 = $height+$border-3;

	if ($y1 >= $y2) { $y1 -= 3; }
	
	my $linkUrl = url."?orf=$orf&fold=$fold";

	MapUtil->DrawBar(gd=>$gd,
			 barColor=>$gd->maroon,
			 numX1=>$x1,
			 numX2=>$x2,
			 numY=>$y1,
			 linkUrl=>$linkUrl,
			 barHeight=>$y2-$y1+1);
			 
    }

}



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

    if (!param('id') || !param('orf') || !param('dataset')) {
	
	print "You have to pass id, orf name, and dataset name in order to show the regulator list.",p;

        return;

    }
    
    my $id = param('id');
    my $orf = param('orf');
    my $dataset = param('dataset');

    &DeleteUnwantedChar(\$id);
    &DeleteUnwantedChar(\$orf);
    &DeleteUnwantedChar(\$dataset);

    my $tmpfile = $configPath->tmpDir."regulatorFor$orf.$dataset.$id";

    open(TMP, "$tmpfile") || 
	die "Can't open '$tmpfile' for reading:$!";

    my @featNm;
    while(<TMP>) {
	chomp;

	@featNm = split(/:/);

	last;

    }
    close(TMP);

    my $datasetObj = Dataset->new(dbh=>$dbh,
				  dataset_name=>$dataset);
    my $datasetTitle;

    if ($datasetObj) {
	
	$datasetTitle = $datasetObj->title; 

    }
    else { 

	$datasetTitle = $dataset;

    }

    my $datasetNo = $datasetObj->dataset_no;

    my $list;
    foreach my $featNm (@featNm) {
	
	my $featObj = Feature->new(dbh=>$dbh,
				   feature_name=>$featNm);

	my $showNm;
	
	if ($featObj->locus_name) {

	    $showNm = $featObj->locus_name."/";

	}

	$showNm .= $featNm;

	my $regulatorUrl = $self->getRegulatorModuleUrl($dataset, $datasetNo,
							$featNm, $featObj->feature_no);
	$list .= li(a({-href=>$regulatorUrl, 
                       -target=>'infowin'}, 
		      $showNm));
	
    }


    print b(font({-color=>'red'}, "$orf")." in ".font({-color=>'red'}, $datasetTitle)." dataset is regulated by following genes:"),p;

    print ul($list),p ;

}

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

    if (!param('orf') || !param('dataset')) {
	
	print "You have to orf name and dataset name in order to show the regulation module list.",p;

        return;

    }
   
    my $orf = param('orf');
    my $dataset = param('dataset');

    &DeleteUnwantedChar(\$orf);
    &DeleteUnwantedChar(\$dataset);

    my $datasetObj = Dataset->new(dbh=>$dbh,
				  dataset_name=>$dataset);
    my $datasetTitle;

    if ($datasetObj) {
	
	$datasetTitle = $datasetObj->title; 

    }
    else { 

	$datasetTitle = $dataset;

    }

    my $datasetNo = $datasetObj->dataset_no;

    my $featObj = Feature->new(dbh=>$dbh,
			       feature_name=>$orf);

    if (!$featObj) {

	print "The feature_name = '$orf' is not found in database",p;

	return;

    }

    my $showNm;
	
    if ($featObj->locus_name) {

	$showNm = $featObj->locus_name."/";

    }

    $showNm .= $featObj->feature_name;

    my $regulatorModuleArrayRef = 
	Dataset->RegulatorModuleArrayRef(dbh=>$dbh,
					 dataset_no=>$datasetNo,
					 feature_no=>$featObj->feature_no);
    my $list;

    foreach my $rowRef (@$regulatorModuleArrayRef) {

	my ($module) = @$rowRef;

	my $moduleShowNm = $module;

	$module =~ s/^Module ([0-9]+)$/cluster_${1}\.html/i;

    	$list .= li(a({-href=>$configUrl->wineServerRoot."Dictyostelium/exp_modules/$dataset/$module", 
                       -target=>'infowin'}, 
		      $moduleShowNm));
	
    }

    print b(font({-color=>'red'}, $showNm)." in ".font({-color=>'red'}, $datasetTitle)." dataset belongs to following regulation modules:"),p;

    print ul($list),p ;

}

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

    my $dataset = param('dataset');
    my $orf = param('orf');

    &DeleteUnwantedChar(\$dataset);
    &DeleteUnwantedChar(\$orf);

    my $datasetObj = Dataset->new(dbh=>$dbh,
				  dataset_name=>$dataset);

    $dataset = $datasetObj->dataset_name;

    if (!$dataset || !$orf) {

	print "You have to pass dataset_name and feature_name for displaying similarly expressed genes.",p;
	
	return;

    }

    my $gene = $orf;

    my $seqObj = SeqParamTranslator->new(dbh=>$dbh,
				    query=>$orf);

    if (!$seqObj->error && $seqObj->featureObject) {
	
	$orf = $seqObj->featureObject->feature_name;

    }
    else {

	print "You have to pass dataset_name and feature_name or physically mapped gene name for displaying similarly expressed genes.",p;
	
	return;

    }

    my $tmpfile;

    @orf = $self->getSimilarGenes($dataset, $orf);

    my $downloadUrl = $configUrl->dictyBaseHtmlTmp.$tmpfile;

    my @newORF;
    foreach my $orf (@orf) {

	my $featObj = Feature->new(dbh=>$dbh,
				   feature_name=>$orf);
	if (!$featObj)  { next; }

	$orf = $featObj->feature_name;

	$featNo4featNm{$orf} = $featObj->feature_no;

	$gene4featNm{$orf} = $featObj->locus_name;

	push(@newORF, $orf);

    }

    if (!@newORF) {

	print "No similarly expressed gene found for $gene.";

	return;
    }

    my ($genes, $expts) = $self->createColorStrips($dataset);

    my $width = $expts * 16;
    my $height = 16;
    
    my $rows;

    my $bgcolor = "white";

    my %goTerms4orf;

    foreach my $orf (@newORF) {

	my $gif = $configUrl->dictyBaseHtmlTmp."$orf.$dataset.gif";

	my $dictyBase = dictyBaseObject->new(dbh=>$dbh,
				 query=>$orf);

	my $gene = $gene4featNm{$orf} || '-';

	$rows .= Tr({-bgcolor=>$bgcolor},
		    td(a({-href=>$locusUrl.$orf}, $orf)).
		    td($gene).
		    td(a({-href=>url."?dataset=$dataset&orf=$orf&type=similar"},
			 img({-alt=>'GIF',
			      -width=>$width,
			      -height=>'16',
			      -src=>$gif}))).
		    td(font({-size=>'-1'}, $dictyBase->process)).
		    td(font({-size=>'-1'}, $dictyBase->function)).
		    td(font({-size=>'-1'}, $dictyBase->component)));

	$goTerms4orf{"\U$orf"} = 
	    $dictyBase->process."\t".$dictyBase->function."\t".$dictyBase->component;

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

    }

    my ($datasetTitle, $link) = $self->datasetsTable($dataset);

    print table({-width=>'100%'},
		Tr(td({-bgcolor=>'#a4abc2'},
		      font({-size=>'+2'}, b("Similarly Expressed Genes: $datasetTitle"))." ".$link))),p;
  

    print table(Tr(td(b("Scale"))).
		Tr(td(img({-border=>0,
			   -valign=>'bottom',
			   -width=>400,
		           -src=>$configUrl->dictyBaseImages."scale.1.5.gif"})))),p;


    print b("Click on a color strip to see 20 genes expressed similarly to that gene"),p;
    
    print b("Up to 20 similar genes are shown, with a Pearson correlation of > 0.8 to the query gene"),p;

    print table(Tr(th({-bgcolor=>'#b7d8e4'}, "ORF").
		   th({-bgcolor=>'#b7d8e4'}, "Gene").
		   th({-bgcolor=>'#b7d8e4'}, 
		      img({-src=>$configUrl->dictyBaseImages."$dataset.gif"})).
		   th({-bgcolor=>'#b7d8e4'}, "Go Process term").
		   th({-bgcolor=>'#b7d8e4'}, "Go Function term").
		   th({-bgcolor=>'#b7d8e4'}, "Go Component term")).
		$rows);

    if (@orf > 2) {
    
	$self->manageGeneList(\@orf, $dataset, \%goTerms4orf);

    }

    # $self->createDownLoadLink($dataset, \%goTerms4orf);

}

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

    my $dataset = param('dataset');
    my $id = param('id');
    my $expts = param('expts');
    my $orf = param('orf');

    &DeleteUnwantedChar(\$dataset);
    &DeleteUnwantedChar(\$id);
    &DeleteUnwantedChar(\$expts);
    &DeleteUnwantedChar(\$orf);
    
    my $width;

    if ($expts) { $width = $expts * 16; }
    else { $width = 125; }

    my $height = 16;

    if (!$dataset || (!$id && !$orf)) {

	print "You have to pass dataset_name and feature_name or gene list file id for displaying the big result picture.",p;
	
	return;

    }

    my @loci;

    if ($id) {
    
	my $tmpfile = $configPath->tmpDir."more.".$id;

	open(IN, $tmpfile) || die "Can't open '$tmpfile' for reading:$!";
    
	while(<IN>) {
	
	    chomp;

	    my @gene = split(/\:/);

	    push(@loci,  @gene);

	}
	close(IN);
    }
    else {

	@loci = $orf;

    }

    my ($datasetTitle, $link) = $self->datasetsTable($dataset);

    print table({-width=>'100%'},
		Tr(td({-bgcolor=>'#a4abc2'},
		      font({-size=>'+2'}, b($datasetTitle))." ".$link))),p;

    if (param('showGeneNum')) {

	$maxDisplayNum = param('showGeneNum');

    }

 
    my $rows;
    
    my $bgcolor = "white";

    my %lociHash;

    my %goTerms4orf;
    my @noExpressedLoci;
    my $count;
    my @pearsonORF;

    foreach my $locus (@loci) {

	my $dictyBase = dictyBaseObject->new(dbh=>$dbh,
				 query=>$locus);
	
	my $orf = $dictyBase->featureName;
	my $gene = $dictyBase->locusName || "-";

	if (!$orf && $gene eq "-") { ##### one locus for more than one orf
	                             ##### or the given name is std gene name
                                     ##### and is an alias
	    my $locusObj = Locus->new(dbh=>$dbh,
				      locus_name=>$locus);

	    if (!$locusObj) { next; }

	    my @featNm = split(/\|/, $locusObj->featureNameList);

	    push(@orf, @featNm);

	    foreach my $featNm (@featNm) {

		$dictyBase = dictyBaseObject->new(dbh=>$dbh,
				      query=>$featNm);

		$orf = $featNm;

		$gene = $dictyBase->locusName || "-";

		goto ROW;
	    }

	}
	else { 

	    push(@orf, $orf); 

	    goto ROW;

	}
	
        ROW:{
	
	    $goTerms4orf{"\U$orf"} = 
	        $dictyBase->process."\t".$dictyBase->function."\t".$dictyBase->component;

	    $lociHash{"\U$orf"} = $gene;

	    if (! -e $configPath->tmpDir."$orf.$dataset.gif") {
	    
		push(@noExpressedLoci, $locus);

	    }
	    else { 
	    
		$count++;

		if ($count > $maxDisplayNum) { next; }

		push(@pearsonORF, $orf);
	
		my $gif = $configUrl->dictyBaseHtmlTmp."$orf.$dataset.gif";

		$rows .= Tr({-bgcolor=>$bgcolor},
			    td(a({-href=>$locusUrl.$orf}, $orf)).
			    td($gene).
			    td(img({-alt=>'GIF',
				    -width=>$width,
				    -height=>'16',
				    -src=>$gif})).
			    td(font({-size=>'-1'}, $dictyBase->process)).
			    td(font({-size=>'-1'}, $dictyBase->function)).
			    td(font({-size=>'-1'}, $dictyBase->component)));

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

	    }
      		    
        }
    }


    if ($count == 1) {

	print b("There are no genes in this dataset with a Pearson correlation > 0.8 to the query gene."),p;

    }

    if (param('showGeneNum')) {
 
       
	$self->manageGeneList(\@orf, $dataset, \%goTerms4orf);

	print p;
    }

    print table(Tr(th({-valign=>'bottom',
		       -bgcolor=>'#b7d8e4'}, "ORF").
		   th({-valign=>'bottom',
		       -bgcolor=>'#b7d8e4'}, "Gene").
		   th({-valign=>'bottom',
		       -bgcolor=>'#b7d8e4'}, 
		      img({-src=>$configUrl->dictyBaseImages."$dataset.gif"})).
		   th({-valign=>'bottom',
		       -bgcolor=>'#b7d8e4'}, "Go Process term").
		   th({-valign=>'bottom',
		       -bgcolor=>'#b7d8e4'}, "Go Function term").
		   th({-valign=>'bottom',
		       -bgcolor=>'#b7d8e4'}, "Go Component term")).
		$rows);


#    if (@noExpressedLoci) {
	
#	print p, b("There is no expression data available in $datasetTitle for following genes:"),p;

#	foreach my $locus (@noExpressedLoci) {

#	    print li(a({-href=>$locusUrl.$locus}, $locus));

#	}

#    }

    if (@loci > 2 && !param('showGeneNum')) {
 
       
	$self->manageGeneList(\@orf, $dataset, \%goTerms4orf);

	if ($id && $count > $maxDisplayNum) {

	    print center(b(a({-href=>url."?dataset=$dataset&id=$id&type=enlarge&expts=$expts&showGeneNum=100"},
			     "Show More Genes"))),p;
			      
        }
	$self->showCorrelationGraph($dataset, \%lociHash, \@pearsonORF, 
				    $datasetTitle);

    }

    $self->lineSeparator;

    
}

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

    my $dataset = param('dataset');
    my $id = param('id');
    my $orf = param('orf');
    my @orfs = param('orfs');

    &DeleteUnwantedChar(\$dataset);
    &DeleteUnwantedChar(\$id);
    &DeleteUnwantedChar(\$orf);

    if (!$dataset || (!$id && !$orf)) {

	print "You have to pass dataset_name and feature_name or gene list file id for displaying the graph.",p;
	
	return;

    }

    my @loci;
    if ($id) {

	my $tmpfile = $configPath->tmpDir."more.".param('id');

	open(IN, $tmpfile) || die "Can't open '$tmpfile' for reading:$!";
    
	while(<IN>) {
	
	    chomp;

	    @loci = split(/\:/, $_);

	    last;

	}
	close(IN);

    }
    else { @loci = $orf; }

    my ($datasetTitle, $link) = $self->datasetsTable($dataset);

    print table({-width=>'100%'},
		Tr(td({-bgcolor=>'#a4abc2'},
		      font({-size=>'+2'}, b("Expression Graph: $datasetTitle"))." ".$link))),p;

    my %lociHash;
    my %goTerms4orf;

    # my @orf;

    my $count;

    foreach my $gene (@loci) {

	$count++;

	if (@loci > 50 && $count%20 == 0) {

	    my $count1 = $count - 19;

	    print "Retrieving info for 'Download Data' option, gene No. $count1 to $count, please wait...",br;

	}

	my $dictyBase = dictyBaseObject->new(dbh=>$dbh,
				 query=>$gene);
	
	my $orf = $dictyBase->featureName;
	my $gene = $dictyBase->locusName || "-";

	push(@orf, $orf);


	$goTerms4orf{"\U$orf"} = 
	    $dictyBase->process."\t".$dictyBase->function."\t".$dictyBase->component;

	$lociHash{"\U$orf"} = $gene;

    }

    my $showPopup;

    if (@orf > $maxDisplayNum) {

	    $showPopup = $self->showPopupForGeneList($id, $dataset, \@orf);

    }

    if (!@orfs) { @orfs = @orf; }

    $self->drawGraph($dataset, \%lociHash, \@orfs, 
		     $datasetTitle, $showPopup);    
    

    if (@orf >= 2) {
    
	$self->manageGeneList(\@orf, $dataset, \%goTerms4orf);

    }

    $self->lineSeparator;

}

########################################################################
sub showPopupForGeneList {
########################################################################
    my ($self, $id, $dataset, $orfArrayRef) = @_;
    
    
    return start_form. 
	   table({-align=>'center'},
		 Tr(td({-nowrap=>'1',
			-valign=>'top'},
		       b("Choose genes from following list to redraw the graph:"),
		       br."(do not choose more than $maxDisplayNum genes)")).
		 Tr(td(popup_menu(-name=>'orfs',
				  -values=>$orfArrayRef,
				  -multiple=>'yes',
				  -size=>'10').p.
		       "Select or unselect multiple gene names".br.
		       "by pressing the Control (PC) or Command".br.
		       "(Mac) key while clicking.".p)).
		 Tr(td(hidden(-name=>'type',
			      -value=>'graph').
		       hidden(-name=>'id',
			      -value=>$id).
		       hidden(-name=>'dataset',
			      -value=>$dataset).
		       submit(-name=>'Redraw graph')))).
	   end_form;

}

########################################################################
sub drawGraph {
########################################################################
    my ($self, $dataset, $lociHashRef, $orfArrayRef, $datasetTitle,
	$showPopup) = @_;


    my $count;
    my $sampleUnit;
    my $minExprVal = 0;
    my $maxExprVal = 0;
    my @data;
    my @expt;

    foreach my $orf (@$orfArrayRef) {

	if (!$orf) { next; }

	my $ecPointArrayRef = Dataset->GetECpointArrayRef(dbh=>$dbh,
					    feature_name=>$orf,
					    dataset_name=>$dataset);
	$count++;

	if ($count > $maxDisplayNum) { last; }
	
	my @row = ($orf);

	foreach my $rowRef (@$ecPointArrayRef) {

	    my ($expt, $unit, $exprVal) = @$rowRef;

	    if ($count == 1) {

		if (!$sampleUnit) { $sampleUnit = $unit; }
		
		push(@expt, $expt);

	    }
	    if ($exprVal > $maxExprVal) { $maxExprVal = $exprVal; }

	    if ($exprVal < $minExprVal) { $minExprVal = $exprVal; }
 
	    push(@row, $exprVal);
	    
	}

	push(@data, \@row);

	print p;

    }

    my $width = 350;
    my $height = 350;
    my $wRatio = ($width-40)/$expt[$#expt];
    my $hRatio = ($height-100)/($maxExprVal-$minExprVal);

    my $border = 60;

    my $legendRow = scalar(@data)/3;
    
    if (scalar(@data)%3 != 0) { $legendRow++; }

    my $bottomH = $legendRow*20;

    if (@data == 1) { undef $bottomH; }

    print "<MAP NAME='graph'>";

    ### Create output image object 
    my $gd = CreateGD->new(width=>$width+2*$border,
			   height=>$height+2*$border+$bottomH);

    MapUtil->DrawFrameWithLabelAndDate(gd=>$gd,
                                       width=>$width+2*$border,
                                       height=>$height+2*$border+$bottomH,
                                       text=>'dictyBase');	
    
    ##### draw y-axis label, border & background

    my $yUnit;
    if ($maxExprVal-$minExprVal > 10) { $yUnit = 2; }
    elsif ($maxExprVal-$minExprVal > 5) { $yUnit = 1; }
    elsif ($maxExprVal-$minExprVal > 1) { $yUnit = 0.5; }
    else { $yUnit = 0.1; }
    
    my $startYunit = int($minExprVal/$yUnit)*$yUnit;

    if ($minExprVal < 0 && $startYunit > $minExprVal) { 
	$startYunit -= $yUnit; 
    }
    
    
    ############### background ##################################

    if ($minExprVal < 0) {
	$gd->im->filledRectangle($border+1, 
				 $height+$border-(0-$startYunit)*$hRatio,
				 $width+$border-1,
				 $height+$border-1,
				 $gd->lightGrey);
    }
						   
    ############### border ######################################
    $gd->im->rectangle($border, $border, 
		       $width+$border, $height+$border,
		       $gd->maroon);
    $gd->im->rectangle($border+1, $border+1, 
		       $width+$border-1, $height+$border-1,
		       $gd->maroon);


    my $unit = $startYunit;

    for (my $Y = $height+$border; $Y > $border; $Y -= $yUnit*$hRatio) {

	my $y = $Y;
	
	if ($y != $height+$border) {

	    $gd->im->line($border+1, $y, $border+5, $y, 
			  $gd->black);

	}

	$y += 4;
	
	if ($unit < 0) { $y += 5; }

	$gd->im->stringUp(gdLargeFont, $border-15, $y, $unit, 
			$gd->black);

	$unit += $yUnit;

    }

    my $yLabel = "log2(ratio)";

    my $nameY = ($height+2*$border)/2+length($yLabel)*4;

    my $nameX = 10;
    
    $gd->im->stringUp(gdLargeFont, $nameX, $nameY, $yLabel, 
		      $gd->black);


    ##### draw x-axis label

    my $maxExpt = int($expt[$#expt]);

    $maxExpt += 1;

    my $xUnit;

    if ($maxExpt > 100) {
	$xUnit = int($maxExpt/100);
	$xUnit *= 10;
    }
    elsif ($maxExpt >= 20) {
	$xUnit = int($maxExpt/10);
    }
    elsif ($maxExpt >= 10) {
	$xUnit = 2;
    }
    else { $xUnit = 1; }

    if ($maxExpt/$xUnit > 10) {
	$xUnit *= 2;
    }

    my $unit = 0;
    my $startX = 10;

    for (my $X = $border+$startX; $X <= $width+$border; $X += $xUnit*$wRatio) {

	my $x = $X;

	$gd->im->line($x, $height+$border-1, $x, $height+$border-5, 
		      $gd->black);
	

	if ($unit >= 0 && $unit < 10) { $x += 6; }
	elsif ($unit > 10 && $unit < 100) { $x += 3; }
       
	$gd->im->string(gdLargeFont, $x-10, $height+$border, $unit, 
			$gd->black);

	$unit += $xUnit;

    }

    my $xLabel = $sampleUnit;

    if ($xLabel =~ /^(hour|hr)/i) {
	
	$xLabel = "Time (hours)";

    }

    my $nameX = $border + $width/2-length($xLabel)*4;

    my $nameY = $height + $border + 20;
    
    $gd->im->string(gdLargeFont, $nameX, $nameY, $xLabel, 
		    $gd->black);


    my @lineColor;
    $self->setLineColor($gd, \@lineColor);

    my $count = 0;

    my $legendYstart = $height + $border + 30;
    my $legendXstart = $border;

    foreach my $rowRef (@data) {

	    my ($orf, @exprVal) = @$rowRef;

	    my ($preX, $preY);

	    for (my $i = 0; $i < @exprVal; $i++) {

		my $x = $border + $startX + $expt[$i]*$wRatio;

		my $y = $height+$border-($exprVal[$i]-$startYunit)*$hRatio;


		if ($preX && $preY) {
		
		    $gd->im->line($preX, $preY, $x, $y, $lineColor[$count]);

		}
		$gd->im->filledRectangle($x-2, $y-2, $x+2, $y+2, $gd->red);

	
		my $mouseOutText = "Move mouse over the red rectangle box to see the gene name";
	    
		my $X1 = int($x - 2);
		my $Y1 = int($y - 2);
		my $X2 = int($x + 2);
		my $Y2 = int($y + 2);
		print "<AREA SHAPE=\"RECT\" COORDS=\"$X1,$Y1,$X2,$Y2\" TITLE=\"$orf\">\n";


		$preX = $x;

		$preY = $y;
	    
	    }

	    if (@data == 1) { next; }

	    if ($count%3 == 0) {

		$legendYstart += 20;

		$legendXstart = $border;

	    }
	    else { $legendXstart += 130; }
	
	    $gd->im->line($legendXstart, 
			  $legendYstart, 
			  $legendXstart+20, 
			  $legendYstart, $lineColor[$count]);
	    $gd->im->filledRectangle($legendXstart-2, $legendYstart-2,
				     $legendXstart+2, $legendYstart+2, 
				     $gd->red);
	    $gd->im->filledRectangle($legendXstart+18, $legendYstart-2,
				     $legendXstart+22, $legendYstart+2, 
				     $gd->red);
	
	    $gd->im->string(gdMediumBoldFont, 
			    $legendXstart+30, 
			    $legendYstart-6, 
			    $orf, 
			    $lineColor[$count]);


	    $count++;

    }
    if (@data == 1) {

	$gd->im->string(gdMediumBoldFont, $border+150, $border+20, 
			$$orfArrayRef[0], $lineColor[0]);

    }

    print "</MAP>";

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

    open (OUT, ">".$gifDir.$gifname)||die "Can't create ".$gifDir.$gifname.":$!";
    binmode OUT;
    print OUT $gd->im->gif;
    close OUT;

    print table({-align=>'center'},
		Tr(td({-valign=>'top'},
		      $showPopup).
		   td({-valign=>'top'},
		      img({-src=>$gifHttp.$gifname,
			   -usemap=>'#graph'})))),p,p;


}

########################################################################
sub setLineColor {
########################################################################
    my ($self, $gd, $lineColorRef) = @_;

    @$lineColorRef = ($gd->blue, 
		      $gd->magenta, 
		      $gd->orange, 
		      $gd->maroon,
		      $gd->darkGreen,
		      $gd->blue2,
		      $gd->sagecolor1,
		      $gd->sagecolor2,
		      $gd->sagecolor3,
		      $gd->sagecolor4,
		      $gd->yellow,
		      $gd->magenta2,
		      $gd->red3,
		      $gd->yellow3,
		      $gd->lightBlue,
		      $gd->green5,
		      $gd->blue3,
		      $gd->blue4,
		      $gd->red2,
		      $gd->green3);


}

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

    my $dataset = param('dataset');
    my $id = param('id');

    &DeleteUnwantedChar(\$dataset);
    &DeleteUnwantedChar(\$id);

    if (!$dataset || !$id) {

	print "You have to pass dataset_name and gene list file id for displaying the Pearson correlation result.",p;
	
	return;

    }

    my $tmpfile = $configPath->tmpDir."more.".param('id');

    open(IN, $tmpfile) || die "Can't open '$tmpfile' for reading:$!";
    
    my @loci;
    while(<IN>) {
	
	chomp;

	@loci = split(/\:/, $_);

	last;

    }
    close(IN);

    my ($datasetTitle, $link) = $self->datasetsTable($dataset);

    my %lociHash;

    my @orf;
    foreach my $gene (@loci) {

	my $dictyBase = dictyBaseObject->new(dbh=>$dbh,
				 query=>$gene);
	
	my $orf = $dictyBase->featureName;
	my $gene = $dictyBase->locusName || "-";

	push(@orf, $orf);

	$lociHash{"\U$orf"} = $gene;
    }

    
    $self->showCorrelationGraph($dataset, \%lociHash, \@orf, 
				    $datasetTitle);

    
    $self->lineSeparator;

}

########################################################################
sub showCorrelationGraph {
########################################################################
    my ($self, $dataset, $lociHashRef, $orfArrayRef, $datasetTitle) 
	= @_;

    my $pcl = $configPath->dataDir4web."dictyBase/$dataset/$dataset.pcl";

    open(IN, $pcl) || die "Can't open '$pcl' for reading:$!";
    
    my $pclTmp = $configPath->tmpDir."$$.pcl";

    open(OUT, ">$pclTmp") || die "Can't open '$pclTmp' for writing:$!";
    
    my $i;
    while(<IN>) {
	
	my ($orf, $others) = split(/\t/);

	$i++;

	if ($i <= 2 || $$lociHashRef{"\U$orf"}) {
	    print OUT;
	}
    }
    close(IN);
    close(OUT);

    my $stdCor = $configPath->tmpDir."$$.stdCor";

    my $tmpfile = $configPath->tmpDir."$$.tmp";

    my $correlations = $configPath->binDir."correlations";

    system("$correlations -f $pclTmp -cutoff 0.4 > $tmpfile");

    open(IN, $stdCor) || die "Can't open '$stdCor' for reading:$!";


    $self->lineSeparator;

    print table({-width=>'100%'},
		Tr(td({-bgcolor=>'#a4abc2'},
		      font({-size=>'+2'}, b("Pearson Correlations for $datasetTitle")))));

    print "The Pearson correlation is a statistical measure of how similar the expression of two gene products is. Pearson = 1.0 represents a perfect correlation.",p;
    print "Click on a square to use GO Term Finder to find common processes, functions, or localizations for the two genes.", p,p;

    if (@$orfArrayRef >= 50) {

	print p, center("Graphic is not displayed if the gene list has more than 50 genes.");

	print p, center(a({-href=>$configUrl->dictyBaseHtmlTmp."$$.stdCor",
			   -target=>'infowin'}, 
			  "Download Pearson Correlation Data")),p;

	return;

    }



    my %Pearson;

    while(<IN>) {

	chomp;
	
	my @list = split(/\t/);

	my $orf1 = shift (@list);

	$orf1 = "\U$orf1";

	if (!@list) { next; }
	
	for (my $i = 0; $i < @list; $i += 2) {

	    my $orf2 = "\U$list[$i]";
	   
	    $Pearson{$orf1.":".$orf2} = $list[$i+1];

	    $Pearson{$orf2.":".$orf1} = $list[$i+1];

	}

    }
    close(IN);

    my ($blockH, $blockW);
    
    if (scalar(@$orfArrayRef) > 40) {

	$blockH = 10;
	$blockW = 10;
	
    }
    elsif (scalar(@$orfArrayRef) > 20) {

	$blockH = 15;
	$blockW = 15;

    }
    else {

	$blockH = 25;
	$blockW = 25;
	
    }
    
    my $border = 65;

    if (@$orfArrayRef <= 3) {

	$border += 20;

    }

    my $width = (scalar(@$orfArrayRef) + 2 )*$blockW;
    my $height = (scalar(@$orfArrayRef) + 1 )*$blockH;
    
    print "<MAP name='pearsonMap'>";
    
    ### Create output image object 
    my $gd = CreateGD->new(width=>$width+2*$border,
			   height=>$height+2*$border);

    MapUtil->DrawFrameWithLabelAndDate(gd=>$gd,
                                       width=>$width+2*$border,
                                       height=>$height+2*$border,
                                       text=>'dictyBase');

    ###### draw blocks

    my $goTermFinderUrl = $configUrl->dictyBaseCGIRoot."$dblink/GO/goTermFinder?orfs=";
    
    my $Xstart = $border + $blockW;
    my $Ystart = $border;

    for (my $i = 0; $i < @$orfArrayRef; $i++) {
	
	my $orf1 = "\U$$orfArrayRef[$i]";

	my $gene = $$lociHashRef{$orf1};

	if ($gene eq "-") { $gene = $orf1; }

	$gd->im->string(gdSmallFont, $Xstart-length($gene)*6-5, 
			$Ystart+$i*$blockH+5, $gene, 
			$gd->black);

	$gd->im->stringUp(gdSmallFont, $Xstart+$i*$blockW+5, 
			$Ystart-5, $gene, 
			$gd->black);

	for (my $j = 0; $j < @$orfArrayRef; $j++) {

	    if ($j > $i) { last; }
	    
	    my $x = $Xstart + $j * $blockW;

	    my $y = $Ystart + $i * $blockH;

	    my $orf2 = "\U$$orfArrayRef[$j]";
	    
	    my $blockColor;

	    if ($orf1 eq $orf2 || $Pearson{$orf1.":".$orf2} >= 1.0) {
		
		# $blockColor = $gd->red3;
		
		$blockColor = $gd->black;

	    }
	    elsif ($Pearson{$orf1.":".$orf2} >= 0.8) {

		$blockColor = $gd->red2;

	    }
	    elsif ($Pearson{$orf1.":".$orf2} >= 0.5) {

		$blockColor = $gd->red1;

	    }
	    else {

		$blockColor = $gd->grey;

	    }
		
	    $gd->im->filledRectangle($x, $y, $x+$blockW, $y+$blockH, 
				     $blockColor);

	    my $numX1 = $x;
	    my $numY1 = $y;
	    my $numX2 = $x+$blockW;
	    my $numY2 = $y+$blockH;

	    if ($orf1 ne $orf2) {

		my $linkUrl = $goTermFinderUrl.$orf1.":".$orf2;

		print "<AREA SHAPE='RECT' COORDS='$numX1,$numY1,$numX2,$numY2' HREF='$linkUrl'>\n";

	    }

	    if ($j == $i) {

		$gd->im->dashedLine($x+$blockW/2, $y-5, 
				    $x+$blockW/2, $Ystart, 
				    $gd->grey);

	    }
	    
	}
	  
    }

    ##### draw keys

    my $Y = $height+$border;

    my $X = ($width+2*$border-240)/2;

    $gd->im->filledRectangle($X, $Y, $X+20, $Y+20, $gd->black);
    $gd->im->string(gdSmallFont, $X+25, $Y+5, "Pearson 1.0", $gd->black);

    $gd->im->filledRectangle($X+130, $Y, $X+150, $Y+20, $gd->red2);
    $gd->im->string(gdSmallFont, $X+155, $Y+5, "Pearson >= 0.8", $gd->black);
    
    $Y += 30;

    $gd->im->filledRectangle($X, $Y, $X+20, $Y+20, $gd->red1);
    $gd->im->string(gdSmallFont, $X+25, $Y+5, "Pearson >= 0.5", $gd->black);

    $gd->im->filledRectangle($X+130, $Y, $X+150, $Y+20, $gd->grey);
    $gd->im->string(gdSmallFont, $X+155, $Y+5, "Pearson < 0.5", $gd->black);
    
    print "</MAP>";

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

    open (OUT, ">".$gifDir.$gifname)||die "Can't create ".$gifDir.$gifname.":$!";
    binmode OUT;
    print OUT $gd->im->gif;
    close OUT;

    print center(img({-src=>$gifHttp.$gifname,
		      -usemap=>'pearsonMap'})),p,p;

}

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

    $loci = param('loci');

    @dataset = param('dataset');
    
    $sortBy = param('sortBy');

    $exprtype = param('exprtype');

    $fold = param('fold');

    if ($sortBy =~ /- Sort genes in datasets -/i) { undef $sortBy; }

    if ($exprtype =~ /-Select/i) { undef $exprtype; }

    if (param('option1')) {

	$self->showResultForOption1;

    }
    elsif (param('option2')) {
	
	$self->showResultForOption2;

    }
    else {

	$self->showResultForOption3;

    }
	   
}

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


    print b("The download files are under construction."),p;

    ### show download file list here




}

########################################################################
sub printNoDataResultForDataset {
########################################################################
    my ($self, $dataset) = @_;

    print hr({-size=>1,
	      -width=>'100%'});

    my $datasetObj = Dataset->new(dbh=>$dbh,
				 dataset_name=>$dataset);

    my $arrayRef = $datasetObj->getNoDataFeatureArrayRef;

    my $hits = scalar(@$arrayRef);

    my ($datasetTitle, $link) = $self->datasetsTable($dataset);

    print p, b($datasetTitle." ".$link),p;
    
    print "$hits ORFs are found with No Expression or No Data in $datasetTitle.",p;


    my $tmpfile = "NoDataFor$dataset.$$.xls";

    open(TMP, ">".$configPath->tmpDir.$tmpfile) ||
	die "Can't open '".$configPath->tmpDir.$tmpfile."' for writing:$!";
   
    foreach my $rowRef (@$arrayRef) {

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

	print TMP "$featNm\t$locusNm\n";

    }
    close(TMP);

    print b(a({-href=>$configUrl->dictyBaseHtmlTmp.$tmpfile,
	       -target=>'infowin'}, 
	      "Download Gene List with No Expression/No Data")),p;

}

########################################################################
sub printNoDataResultForOrf {
########################################################################
    my ($self, $orf) = @_;

    print hr({-size=>1,
	      -width=>'100%'}), p;

    my $arrayRef = 
	Dataset->GetDatasetArrayRefBYfeatureNo(dbh=>$dbh,
			feature_no=>$featNo4featNm{$orf});

    my $showNm;

    if ($gene4featNm{$orf}) {
	
	$showNm = $gene4featNm{$orf}."/";
	
    }
    $showNm .= $orf;

    print b(a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=$orf",
	       -target=>'infowin'},
	      $showNm)), p;
	      
    if (!@$arrayRef) {
	
	print "No dataset is found with 'No Expression/No Data' for $showNm.",p;

    }

    my $datasetList;

    foreach my $rowRef (@$arrayRef) {
	
	my ($dataset) = @$rowRef;

	my ($datasetTitle, $link) = $self->datasetsTable($dataset);

	$datasetList .= li($datasetTitle." ".$link);

    }

    my $desc;
    if (@$arrayRef == 1) { $desc = "One dataset "; }
    else { $desc = scalar(@$arrayRef)." datasets "; }
    $desc .= "found with 'No Expression/No Data' for $showNm";

    print b($desc),p, ul($datasetList),p;
}

########################################################################
sub getResultForDataset {
########################################################################
    my ($self, $dataset, $id) = @_;

    if ($id) {

	$self->setGeneList($dataset, $id);

    }

    if (!$id) { $id = $$; }

    my $datasetObj = Dataset->new(dbh=>$dbh,
				  dataset_name=>$dataset);

    if (!$datasetObj) { return; }

    my $datasetNo = $datasetObj->dataset_no;

    foreach my $featNm (keys %featNo4featNm) {

	if (!$featNo4featNm{$featNm}) {
	    # print $featNm, br;
	    next;
	}

	my $max = Dataset->MaxExprValBYdatasetNofeatureNo(dbh=>$dbh,
				      dataset_no=>$datasetNo,
				      feature_no=>$featNo4featNm{$featNm});

	my $min = Dataset->MinExprValBYdatasetNofeatureNo(dbh=>$dbh,
				      dataset_no=>$datasetNo,
				      feature_no=>$featNo4featNm{$featNm});

	if (!$max && !$min) { next; }

	if ($max =~ /^[0\.]+$/) {
	    $maxExprVal4featNm{$featNm} = 1;
	}
	elsif ($max > 0) { 
	    $maxExprVal4featNm{$featNm} = $self->exprFold($max);
	}
	elsif ($max) {
	    $maxExprVal4featNm{$featNm} = -1000;
	}
	else { next ; }

	if ($min =~ /^[0\.]+$/) {
	    $minExprVal4featNm{$featNm} = 1;
	}
	elsif ($min < 0) { 
	    $minExprVal4featNm{$featNm} = $self->exprFold($min);
	}
	elsif ($min) {
	    $minExprVal4featNm{$featNm} = 1000;
	}

    }

    my ($genes, $expts) = 
	$self->createColorStrips($dataset);

    my ($rows, $geneNum);
    
    my @featNm;

    if ($sortBy =~ /by ORF name/i) {

	@featNm = sort (keys %maxExprVal4featNm);
	
    }
    elsif ($sortBy =~ /Greatest to least Max Increase/i) {

	@featNm = sort ({$maxExprVal4featNm{$b} <=> $maxExprVal4featNm{$a}} keys %maxExprVal4featNm);

    }
    elsif ($sortBy =~ /least to greatest Max Increase/i) {

	@featNm = sort ({$maxExprVal4featNm{$a} <=> $maxExprVal4featNm{$b}} keys %maxExprVal4featNm);

    }
    elsif ($sortBy =~ /Greatest to least Max Decrease/i) {

	@featNm = sort ({$minExprVal4featNm{$a} <=> $minExprVal4featNm{$b}} keys %maxExprVal4featNm);

    }
    elsif ($sortBy =~ /least to greatest Max Decrease/i) {

	@featNm = sort ({$minExprVal4featNm{$b} <=> $minExprVal4featNm{$a}} keys %maxExprVal4featNm);

    }
    else { @featNm = @orf; }
    
    my $showLongList;

    if (@featNm > $maxDisplayNum && $maxDisplayNum < 100) { 

	$showLongList++; 

    }

    my $tmpfile = "$dataset.$id.tmp";

    my $downloadFile = $configPath->tmpDir.$tmpfile;

    open(OUT, ">$downloadFile") ||
	die "Can't open '$downloadFile' for writing:$!";

    print OUT "ORF\tGene\tMax_Increase\tMax_Decrease\n";

    $geneNum4dataset{$dataset} = scalar(@featNm);

    my $bgcolor = 'white';

    foreach my $featNm (@featNm) {

	if (!$featNo4featNm{$featNm}) {
	    next;
	}
	
	if (!$minExprVal4featNm{$featNm} && !$maxExprVal4featNm{$featNm}) {

	    $self->{'_noData'}{$dataset} .= ":".$featNm;

	    next;
	}


	my $gene = $gene4featNm{$featNm} || br;
	my $max = $maxExprVal4featNm{$featNm};
	my $min = $minExprVal4featNm{$featNm};

	
	if ($max == -1000) { $max = "-"; }
	if ($min == 1000) { $min = "-"; }

	print OUT "$featNm\t$gene4featNm{$featNm}\t$max\t$min\n";

	if ($geneNum >= $maxDisplayNum) { 

	    next; 

	}
	
	$geneNum++;

	my $linkNm = a({-href=>$locusUrl.$featNm,
		     -target=>'infowin'}, 
		    $featNm);
	
	my $regulatorUrl = 
	    $self->getRegulatorModuleUrl($dataset, 
					 $datasetNo, 
					 $featNm, 
					 $featNo4featNm{$featNm});

	my $regulator;
	if ($regulatorUrl) {
	    $regulator = a({-href=>$regulatorUrl,
			    -target=>'infowin'},
			   img({-border=>'0',
				-width=>'32',
				-height=>'20',
				-alt=>'regulator',
				-src=>$configUrl->dictyBaseImages."reg.PNG"}));


	}
	else { $regulator = br; }
	
       

	my $regulatorArrayRef = Dataset->GetRegulatorArrayRef(dbh=>$dbh,
				    dataset_no=>$datasetNo,
				    feature_no=>$featNo4featNm{$featNm});

	my $regulatedBy;
	
	my $regulatorList;

	my $count;
	foreach my $rowRef (@$regulatorArrayRef) {

	    my ($orfname) = @$rowRef;
	    
	    if ($regulatorList) { $regulatorList .= ":"; }

	    $regulatorList .= $orfname;
   
	    $count++;

	    if ($count > 2) { next; }

	    if (!$regulatedBy) {
		
		my $featObj = Feature->new(dbh=>$dbh,
					   feature_name=>$orfname);

		my $regulatorUrl = 
		    $self->getRegulatorModuleUrl($dataset, 
						 $datasetNo, 
						 $orfname, 
						 $featObj->feature_no);

		my $regulatorShowNm;

		if ($featObj->locus_name) { 
		    $regulatorShowNm = $featObj->locus_name."/";
		}

		$regulatorShowNm .= $orfname;

		$regulatedBy = a({-href=>$regulatorUrl,
				  -target=>'infowin'}, 
				  $regulatorShowNm);
		   
	    }
	    else {
		$regulatedBy .= "+".
		    a({-href=>url."?id=$id&orf=$featNm&dataset=$dataset&type=regulatedBy",
		       -target=>'infowin'}, 
		      "More");
	    }

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

	if (@$regulatorArrayRef >= 2) {
	    
	    my $tmpfile = $configPath->tmpDir."regulatorFor$featNm.$dataset.$id";

	    open(TMP, ">$tmpfile") || die "Can't open '$tmpfile' for writing:$!";

	    print TMP $regulatorList, "\n";

	    close(TMP);

	}

	my @similarGenes = $self->getSimilarGenes($dataset, $featNm);

	my $similar;

	if (@similarGenes) {
	    
	    $similar = a({-href=>url."?orf=$featNm&dataset=$dataset&type=similar",
		          -target=>'infowin'}, 
			 img({-border=>'0',
			      -size=>'10',
			      -alt=>'similar genes',
			      -src=>$configUrl->dictyBaseImages."rd_ball.PNG"}));

	}
	else { $similar = br; }

	
	$rows .= Tr({-bgcolor=>$bgcolor},
		    td($linkNm).
		    td($gene).
		    td($max).
		    td($min).
		    td({-align=>'center'},
		       a({-href=>url."?orf=$featNm&type=histogram",
		          -target=>'infowin'}, 
			 img({-border=>'0',
			      -size=>'10',
			      -alt=>'Histogram',
			      -src=>$configUrl->dictyBaseImages."cy_ball.gif"}))).
		    td({-align=>'center'},
		       img({-border=>'0',
			    -width=>'55',
			    -height=>'8',
			    -alt=>'GIF',
			    -src=>$configUrl->dictyBaseHtmlTmp.$featNm.".".$dataset.".gif"})).
		    td({-align=>'center'},
		       $similar).
	            td({-align=>'center'}, 
		       $regulator).
		    td($regulatedBy));

#		    td({-align=>'center'},
       #	       a({-href=>$configUrl->dictyBaseCGIRoot."dictyBase/geneXplorer/geneXplorer.pl?dataset=$dataset&genes=$genes&expts=$expts",
#		          -target=>'infowin'}, 
#			 img({-border=>'0',
#			      -size=>'10',
#			      -alt=>'clustered',
#			      -src=>$configUrl->dictyBaseImages."bl_ball.gif"}))).

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

	}
	else { $bgcolor = 'white'; }

    }

    close(OUT);

    my $rowspan= $geneNum + 2;

    my ($graph, $pearson, $golink);

    if ($datasetObj->hasECpoint && !param('showGeneNum')) {

	$graph = th("Expression Graph".br.
		    a({-href=>url."?id=$id&dataset=$dataset&type=graph",
		       -target=>'infowin'},
		      img({-width=>30,
			   -border=>0,
			   -alt=>'graph',
			   -src=>$configUrl->dictyBaseImages."graph2.gif"})));

    }

    my $downloadUrl = $configUrl->dictyBaseHtmlTmp.$tmpfile;

    my $downloadLink = b(a({-href=>$downloadUrl,
			    -target=>'infowin'}, 
			   "Download Data")).br.br.br;

    if (@featNm >= 2 && !param('showGeneNum')) {

	$pearson = th("&nbsp&nbsp&nbsp").
		   th("Pearson Correlation".br.
		      a({-href=>url."?id=$id&dataset=$dataset&type=Pearson",
			 -target=>'infowin'}, 
			img({-width=>35,
			     -border=>0,
			     -alt=>'Pearson Correlations',
			     -src=>$configUrl->dictyBaseImages."correlation.PNG"})));

	$golink = th("Analyze Gene List with:".br.blockquote($self->golinks(\@featNm, $dataset, $downloadLink)));

	undef $downloadLink;
    }
    else { $downloadLink = br."&nbsp&nbsp&nbsp".$downloadLink; }

    if ($showLongList) {

	#### To force it to overwrite the old dataset list
	param('dataset', $dataset);

	if (param('submit1') || param('option') =~ /option1/i) {

	    #### To force it to overwrite the old locus list
	    param('loci', $loci);

	    $downloadLink .= 
		         start_form.
		         hidden(-name=>'loci',
			        -value=>$loci).
	                 hidden(-name=>'dataset',
			        -value=>$dataset).
			 hidden(-name=>'sortBy',
			        -value=>$sortBy).
			 hidden(-name=>'showGeneNum',
			        -value=>'100').
			 hidden(-name=>'option',
			        -value=>'option1').
			 submit(-name=>'submit',
			        -value=>'Show More Genes').
			 end_form;

	    

	}
	else {
   
	    #### To force it to overwrite the old value
	    param('showGeneNum', '100');

	    $downloadLink .= 
		         start_form.
			 hidden(-name=>'showGeneNum',
			        -value=>'100').
	                 hidden(-name=>'dataset',
			        -value=>$dataset).
			 hidden(-name=>'exprtype',
			        -value=>$exprtype).
			 hidden(-name=>'fold',
			        -value=>$fold).
    			 hidden(-name=>'sortBy',
			        -value=>$sortBy).
			 hidden(-name=>'option',
			        -value=>'option3').
			 submit(-name=>'submit',
			        -value=>'Show More Genes').
			 end_form;

	    param('showGeneNum', '');
	}

    }

    undef %maxExprVal4featNm;
    undef %minExprVal4featNm;

    
    my ($datasetTitle, $link) = $self->datasetsTable($dataset);

    my $totalGeneNum = $geneNum4dataset{$dataset} || $totalGene;

    my $geneNumShown;

    if ($geneNum < $totalGeneNum) {

	$geneNumShown = Tr(td({-colspan=>12,
			       -align=>'center'},
			      b("$geneNum of $totalGeneNum genes are displayed")));

    }

    return Tr(td({-colspan=>12},
		 hr({-size=>1,
		     -width=>'100%'}))).
	   $geneNumShown.
	   Tr(th({-bgcolor=>'#a4abc2',
		  -align=>'left',
		  -valign=>'top',
		  -rowspan=>$rowspan}, 
		 b($datasetTitle).br.$link.
		 br.br.
		 table(Tr($graph.$pearson)).
		 table(Tr($golink)).
		 $downloadLink).		  
	      th({-bgcolor=>'#b7d8e4',
		  -rowspan=>'2'}, "ORF").
	      th({-bgcolor=>'#b7d8e4',
		  -rowspan=>'2'}, "Gene").
	      th({-bgcolor=>'#b7d8e4',
		  -colspan=>'3'}, "Change in dataset").
	      th({-bgcolor=>'#b7d8e4',
		  -rowspan=>'2'}, 
		 "Thumbnail Display ".br.
		 a({-href=>url."?dataset=$dataset&id=$id&type=enlarge&expts=$expts",
		    -target=>'infowin'}, 
		   "(Enlarge)")).
	      th({-bgcolor=>'#b7d8e4',
		  -rowspan=>'2'}, "Similarly".br."expressed genes"). 
#	      th({-bgcolor=>'#b7d8e4',
#	      	  -rowspan=>'2'}, "Browse".br."Clustered".br."Data")).
	      th({-bgcolor=>'#b7d8e4',
	      	  -colspan=>'2'}, "Regulation Module")).
           Tr(td({-bgcolor=>"#b7d8e4"}, 
		 "Max ".img({-border=>0,
			     -src=>$configUrl->dictyBaseImages."up.gif"})).
	      td({-bgcolor=>"#b7d8e4"},
		 "Max ".img({-border=>0,
			     -src=>$configUrl->dictyBaseImages."down.gif"})).
	      td({-bgcolor=>"#b7d8e4"},
		 "vs. other".br."datasets").
	      td({-bgcolor=>"#b7d8e4"},
		 "Regulator of").
	      td({-bgcolor=>"#b7d8e4"},
		 "Regulated by")).$rows;

}

########################################################################
sub printResultForOrf {
########################################################################
    my ($self, $featNm) = @_;

    if (!$featNm) {

	return;

    }
    if (!$featNo4featNm{"\U$featNm"}) {

	print "$featNm is not found in database.",p;
	return;

    }


    my $arrayRef = Dataset->GetDatasetMaxExprChangeArrayRefBYfeatureNo(
                                   dbh=>$dbh,
				   feature_no=>$featNo4featNm{"\U$featNm"});

    my @dataset;
    my %maxFoldUp4dataset;
    my %maxFoldDown4dataset;

    foreach my $rowRef (@$arrayRef) {

	my ($dataset, $maxExprVal, $minExprVal) = @$rowRef;

	my $maxFoldUp = $self->exprFold($maxExprVal);

	my $maxFoldDown = $self->exprFold($minExprVal);

	if ($exprtype =~ /^Increased$/i && 
	    $maxFoldUp < $fold) {

	    next;

	}
	elsif ($exprtype =~ /^Decreased$/i && 
	       $maxFoldDown*(-1) < $fold) {

	    next;

	}
	elsif ($exprtype =~ /^Increased or Decreased$/i &&
	       $maxFoldUp < $fold && $maxFoldDown*(-1) < $fold) {

	    next;
		
	}
	elsif ($exprtype =~ /^Not changed/i && 
	       ($maxFoldUp >= 2 || $maxFoldDown <= -2)) {
	    
	    next;

        }

	push(@dataset, $dataset);

	$maxFoldUp4dataset{$dataset} = $maxFoldUp;
	
	$maxFoldDown4dataset{$dataset} = $maxFoldDown;

    }

    if ($exprtype =~ /No Data/i) {
	
	undef @dataset;
	foreach my $dataset (keys %datasetTitle) {

	    if (!$maxFoldUp4dataset{$dataset} && 
		!$maxFoldDown4dataset{$dataset}) {

		push(@dataset, $dataset);

	    }

	}
       
    }

    print hr({-size=>1,
	      -width=>'100%'});

    my $showNm;

    if ($gene4featNm{"\U$featNm"}) {
	
	$showNm = $gene4featNm{"\U$featNm"}."/"; 

    }
    $showNm .= $featNm;

    if (!@dataset) {
	
	print b("No dataset found for $showNm for expression : "), 
	      b($self->getExpressionChange), p;

	return;
	
    }

    $showNm =~ s/\//\/<br>/;

 #   print h2("Results for $showNm"),p;

    my $rows;

    my $rowspan = 2*scalar(@dataset) + 1;

    ######## sort dataset #####################################
 
    if ($sortBy =~ /Greatest to least Max Increase/i) {
	
	undef @dataset;
	
	foreach my $dataset (sort ({$maxFoldUp4dataset{$b} <=> $maxFoldUp4dataset{$a}} keys %maxFoldUp4dataset)) {

	    push(@dataset, $dataset);

	}
	
    }
    elsif ($sortBy =~ /least to greatest Max Increase/i) {

	undef @dataset;
	
	foreach my $dataset (sort ({$maxFoldUp4dataset{$a} <=> $maxFoldUp4dataset{$b}} keys %maxFoldUp4dataset)) {

	    push(@dataset, $dataset);

	}

    }
    elsif ($sortBy =~ /Greatest to least Max Decrease/i) {

	undef @dataset;
	
	foreach my $dataset (sort ({$maxFoldDown4dataset{$a} <=> $maxFoldDown4dataset{$b}} keys %maxFoldDown4dataset)) {

	    push(@dataset, $dataset);

	}

    }
    elsif ($sortBy =~ /least to greatest Max Decrease/i) {

	undef @dataset;
	
	foreach my $dataset (sort ({$maxFoldDown4dataset{$b} <=> $maxFoldDown4dataset{$a}} keys %maxFoldDown4dataset)) {

	    push(@dataset, $dataset);

	}

    }

    
    my $bgcolor = 'white';

    foreach my $dataset (@dataset) {

	my ($datasetTitle, $link) = $self->datasetsTable($dataset);

	if (!$genes4dataset{$dataset} || 
	    !$expts4dataset{$dataset}) {

	    ($genes4dataset{$dataset}, $expts4dataset{$dataset}) 
		= $self->createColorStrips($dataset);

	}
	my $genes = $genes4dataset{$dataset};
	my $expts = $expts4dataset{$dataset};

	my $datasetObj = Dataset->new(dbh=>$dbh,
				      dataset_name=>$dataset);

	my $graph = td(br);
	if ($datasetObj->hasECpoint) {
	    
	    $graph = td({-align=>'center'}, 
			a({-href=>url."?orf=$featNm&dataset=$dataset&type=graph",
			   -target=>'infowin'},
			  img({-size=>10,
			       -border=>0,
			       -alt=>'GIF',
			       -src=>$configUrl->dictyBaseImages."cy_ball.gif"})));

	}

	my $regulatorUrl = $self->getRegulatorModuleUrl($dataset,
							$datasetObj->dataset_no,
							$featNm,
							$featNo4featNm{$featNm});

	my $regulator;

	if ($regulatorUrl) {
	    
	    $regulator = a({-href=>$regulatorUrl,
			    -target=>'infowin'}, 
			 img({-border=>'0',
			      -width=>'30',
			      -height=>'20',
			      -alt=>'regulator',
			      -src=>$configUrl->dictyBaseImages."reg.PNG"}));
	}
	else { $regulator = br; }

	my @similarGenes = $self->getSimilarGenes($dataset, $featNm);

	my $similar;

	if (@similarGenes) {
	    
	    $similar = a({-href=>url."?orf=$featNm&dataset=$dataset&type=similar",
		          -target=>'infowin'}, 
			 img({-border=>'0',
			      -size=>'10',
			      -alt=>'similar genes',
			      -src=>$configUrl->dictyBaseImages."rd_ball.PNG"}));

	}
	else { $similar = br; }

    
	$rows .= Tr(td({-colspan=>9})).
	         Tr({-bgcolor=>$bgcolor},
		    td(b($datasetTitle).br.$link).
		    td({-align=>'center'},
		       $maxFoldUp4dataset{$dataset}).
		    td({-align=>'center'},
		       $maxFoldDown4dataset{$dataset}).
		    td({-align=>'center'},
		       a({-href=>url."?dataset=$dataset&orf=$featNm&type=enlarge&expts=$expts",
		          -target=>'infowin'},
			 img({-border=>'0',
			      -width=>'55',
			      -height=>'8',
			      -alt=>'GIF',
			      -src=>$configUrl->dictyBaseHtmlTmp.$featNm.".".$dataset.".gif"}))).
		    td({-align=>'center'},
		       $similar).
		       $graph.
		    td({-align=>'center'}, $regulator));

#		    td({-align=>'center'},
#		       a({-href=>$configUrl->dictyBaseCGIRoot."dictyBase/geneXplorer/geneXplorer.pl?dataset=$dataset&genes=$genes&expts=$expts",
#		          -target=>'infowin'}, 
#			 img({-border=>'0',
#			      -size=>'10',
#			      -alt=>'clustered',
#			      -src=>$configUrl->dictyBaseImages."bl_ball.gif"}))));

#		    td({-align=>'center'},
#		       a({-href=>url."?orf=$featNm&type=histogram",
#		          -target=>'infowin'}, 
#			 img({-border=>'0',
#			      -size=>'10',
#			      -alt=>'Histogram',
#			      -src=>$configUrl->dictyBaseImages."cy_ball.gif"}))).
		   # td($regulator));
		    
	if ($bgcolor eq "white") {

	    $bgcolor = "#d8d8d8";

	}
	else {

	    $bgcolor = "white";

	}

    }

    print table({-border=>0,
		 -cellpadding=>1,
		 -cellspacing=>1},
		Tr(th({-bgcolor=>'#a4abc2',
		       -rowspan=>$rowspan,
		       -valign=>'top'}, 
		      $showNm.br.br.br.
		      a({-href=>url."?orf=$featNm&type=histogram",
		         -target=>'infowin'}, 
			"Histogram")).
		   th({-bgcolor=>'#b7d8e4'}, 
		      "Dataset").
		   th({-bgcolor=>'#b7d8e4'},
		      "Max Fold Increase").
		   th({-bgcolor=>'#b7d8e4'},
		      "Max Fold Decrease").
		   th({-bgcolor=>'#b7d8e4'},
		      "Display").
		   th({-bgcolor=>'#b7d8e4'},
		      "See more genes with similar expression").
		   th({-bgcolor=>'#b7d8e4'},
		      "Expression Graph").
		   th({-bgcolor=>'#b7d8e4'},
		      "Regulator of")).
		$rows);

#		   th({-bgcolor=>'#b7d8e4'},
#		      "Browse Clustered Data")).$rows);

#		   th({-bgcolor=>'#b7d8e4'},
#		      "Histogram").
#		   th({-bgcolor=>'#b7d8e4'},
#		      "Regulator of")).
#		$rows);
    
   
}

########################################################################
sub createDownLoadLink {
########################################################################
    my ($self, $dataset, $goTerms4orfHashRef) = @_;

    my $tmpfile = "$dataset.$$.tmp";

    my $downloadUrl = $configUrl->dictyBaseHtmlTmp.$tmpfile;

    my $tmpDir = $configPath->tmpDir;

    if (-e $tmpDir.$tmpfile && param('orfs')) {

	return a({-href=>$downloadUrl,
		  -target=>'infowin'},
		 "Download Data");

    }
    my $dataDir = $configPath->dataDir4web."dictyBase/";

    my $stem = $dataDir.$dataset."/".$dataset;

    my $datafile = $stem.".data";

    open(IN, "$datafile") || 
	die "Can't open '$datafile' for reading: $!";

    my %exprData4orf;

    my ($count, $exptNms);

    while (<IN>){

	chomp;

	$count++;

	my ($orf, $exprValues);
 
	if ($_ =~ /^([^\t]+)\t(.+)$/) {

	    $orf = $1;

	    $exprValues = $2;

	    if ($count == 1) {

		$exptNms = $exprValues;

	    }
	    elsif ($$goTerms4orfHashRef{"\U$orf"}) {

		$exprData4orf{"\U$orf"} = $exprValues;

	    }
	}

    }
    close(IN);

    open(OUT, ">".$tmpDir.$tmpfile) || 
	die "Can't open '${tmpDir}$tmpfile' for writing:$!";

    print OUT "ORF\tGENE\tGO_process\tGO_function\tGO_component\t$exptNms\n";

    foreach my $orf (@orf) {

	my $gene = $gene4featNm{"\U$orf"};

	my $goTerms = $$goTerms4orfHashRef{"\U$orf"};

	my $exprValues = $exprData4orf{"\U$orf"};

	print OUT "$orf\t$gene\t$goTerms\t$exprValues\n";

    }
    close(OUT);

    return a({-href=>$downloadUrl,
	      -target=>'infowin'},
	     "Download Data");

}

########################################################################
sub createColorStrips {
########################################################################
    my ($self, $dataset) = @_;

    my $dataDir = $configPath->dataDir4web."dictyBase/";

    my $tmpDir = $configPath->tmpDir;
    
    my $stem = $dataDir.$dataset."/".$dataset;

    my $datafile = $stem.".data";

    my $giffile = $stem.".cdt.gif";

    ###### identify the position of the color strip in the gif file 
    ###### for each orf.
    
    open(IN, "$datafile") || 
	die "Can't open '$datafile' for reading: $!";

    my %position4featNm;
    my ($expts, $genes);
    while (<IN>){

	chomp;

	my @line = split("\t", $_, -1);

	my $featNm = shift(@line);

	if (!$expts) {

	    $expts = @line;

	}
	
	$genes++;

	if (!$featNo4featNm{$featNm}) { next; }

	$position4featNm{$featNm}=$.-1; # record line (-2)

	
    }
    close(IN);
 
    $genes--;

    ###### create color strips

    open(GIF, "$giffile") ||
	die "Can't open '$giffile' for reading:$!";

    my $im = new GD::Image($expts,$genes);

    $im = newFromGif GD::Image(\*GIF) || die "can't make new image : $!";

    close(GIF);

    my $newIm = new GD::Image($expts,1);

    foreach (keys %featNo4featNm){

	$newIm->copy($im, 0, 0, 0, $position4featNm{$_}, $expts, 1);

	open(OUT, ">$tmpDir$_.$dataset.gif")||
	    die "Can't make $tmpDir$_.$dataset.gif: $!";

	binmode OUT;

	print OUT $newIm->gif;
    
	close OUT;

    }
    
    return ($genes, $expts);

}


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

    my $tmpfile = $configPath->tmpDir."more.".param('id');

    open(IN, $tmpfile) || die "Can't open '$tmpfile' for reading:$!";
    
    my @loci;
    while(<IN>) {
	
	chomp;

	@loci = split(/\:/, $_);

	last;

    }
    close(IN);

    my $loci;
    foreach my $locus (@loci) {

	$locus = "\U$locus";

	$loci .= li(a({-href=>$locusUrl.$locus}, $locus));
	
    }
       
    print ul($loci), p;

}

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

    # my $totalSpot = 6200; ### it should come from database...

    if (!param('dataset')) {

	print "You have to pass a dataset name for displaying the statistics.", p;
	return;

    }

    my $dataset = param('dataset');
    &DeleteUnwantedChar(\$dataset);

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

    my $datasetObj = Dataset->new(dbh=>$dbh,
				  dataset_name=>$dataset);
    
    my $totalSpot = $datasetObj->getFeatureNum;

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


    my $totalSpotWithDataArrayRef = Dataset->GetSpotNumArrayRef(dbh=>$dbh,
					        dataset_name=>$dataset);
    my %totalSpotWithData4expt;

    foreach my $rowRef (@$totalSpotWithDataArrayRef) {

	my ($expt, $count) = @$rowRef;

	$totalSpotWithData4expt{$expt} = $count;

    }

    ### 2-fold change => log($fold)/log(2)  => 1

    my $fold = 2;

    my $exprVal = log($fold)/log(2);

    my $increasedSpotArrayRef = Dataset->GetSpotNumArrayRef(dbh=>$dbh,
					        dataset_name=>$dataset,
						sample_value_cutoff=>$exprVal,
						type=>'increased');
    my %increasedSpot4expt;

    foreach my $rowRef (@$increasedSpotArrayRef) {

	my ($expt, $count) = @$rowRef;

	$increasedSpot4expt{$expt} = $count;

    }

    my $decreasedSpotArrayRef = Dataset->GetSpotNumArrayRef(dbh=>$dbh,
					        dataset_name=>$dataset,
						sample_value_cutoff=>$exprVal,
                                                type=>'decreased');
    
    my %decreasedSpot4expt;

    foreach my $rowRef (@$decreasedSpotArrayRef) {

	my ($expt, $count) = @$rowRef;

	$decreasedSpot4expt{$expt} = $count;

    }

   
    my $sampleArrayRef = Dataset->GetSamplesArrayRef(dbh=>$dbh,
						     dataset_name=>$dataset);

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

    my $linkUrl = url."?dataset=$dataset&fold=2&option=option3&exprtype=";
    my $rows;
    foreach my $rowRef (@$sampleArrayRef) {
      
	my ($expt, $unit) = @$rowRef;

	my $increased = 
	    $self->percentCal($increasedSpot4expt{$expt}*100/$totalSpot);

	my $decreased = 
	    $self->percentCal($decreasedSpot4expt{$expt}*100/$totalSpot);

	my $changed = $increased + $decreased; 

	my $notChanged = 
	    $self->percentCal($totalSpotWithData4expt{$expt}*100/$totalSpot 
	                      - $changed);

	my $noData = $self->percentCal(100 - $notChanged - $changed);

	$rows .= Tr(td({-bgcolor=>'#b7d8e4'},
		       $expt." ".$unit).
		    td({-align=>'center'}, 
		       a({-href=>$linkUrl."Increased",
			  -target=>'infowin'},
			 $increased.'%')).
		    td({-align=>'center'}, 
		       a({-href=>$linkUrl."Decreased",
			  -target=>'infowin'},
			 $decreased.'%')).
		    td({-align=>'center'}, 
		       a({-href=>$linkUrl."Increased+or+Decreased",
			  -target=>'infowin'},
			 $changed.'%')).
		    td({-align=>'center'}, 
		       a({-href=>$linkUrl."Not+changed",
			  -target=>'infowin'},
			 $notChanged.'%')).
		    td({-align=>'center'}, 
		       a({-href=>$linkUrl."No+Data",
			  -target=>'infowin'},
			 $noData.'%')).
		    td({-align=>'center'}, $totalSpot));

    }
    
    my $datasetTitle = $datasetObj->title;

    print center(font({-size=>'+2'}, b("Global Statistics for Dataset: $datasetTitle"))),p;

    print table({-align=>'center',
		 -border=>1,
		 -cellpadding=>2},
		Tr({-bgcolor=>'#a4abc2'},
		   td({-colspan=>'7'},
		      font({-size=>'+2'},
			   b("Percent of Spots Changing, By Experiment")))).
		Tr(th({-rowspan=>2},
		      "Experiment").
		   th({-colspan=>6},
		      "Expression")).
		Tr({-bgcolor=>'#b7d8e4',
		    -align=>'center'},
		   th("Increased").
		   th("Decreased").
		   th("Increased".br."or".br."Decreased").
		   th("No Change").
		   th("Not Expressed/".br."No Data").
		   th("Number of".br."spots in".br."experiments")).
		$rows),p;
		   
    print center("* Increased or Decreased relative to control by $fold-fold or greater."),p;

}

########################################################################
sub percentCal {
########################################################################
    my ($self, $percent) = @_;

    if ($percent =~ /^([0-9]+\.[0-9])([0-9])/) {
	$percent = $1;
	if ($2 >= 5) { $percent += 0.1; }
    }

    if ($percent < 0.001) { $percent = 0; }

    return $percent;

}

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

    my $locusList = $self->getGeneList;
    
    my $datasetList = $self->getDatasetList;

    print table({-width=>'100%'},
		Tr(td(b("Search: ")."Find how a single gene's or multiple gene's expression changes in one or more datasets")).
		Tr(td(b("Gene Name(s): ").$locusList)).
		Tr(td(b("Datasets selected").ul($datasetList))));


}

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

    my $locusList = $self->getGeneList;
    
    my $expressionChange = $self->getExpressionChange;

    print table({-width=>'100%'},
		Tr(td(b("Search: ")."Find datasets where the expression of one or more genes changes by an amount you define.")).
		Tr(td(b("Gene Name(s): ").$locusList)).
		Tr(td(b("Expression change: ").$expressionChange)));


}

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

    my $datasetList = $self->getDatasetList;
    
    my $expressionChange = $self->getExpressionChange;

    print table({-width=>'100%'},
		Tr(td(b("Search: ")."Find genes where the expression changes in one or more datasets by an amount you define.")).
		Tr(td(b("Expression change: ").$expressionChange)).
		Tr(td(b("Datasets selected").ul($datasetList))));

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

    my $fold = param('fold') || "2 (by default)";

    if (param('exprtype') =~ /^(Increased|Decreased)/i) {

	return param('exprtype')." ".b("by")." ".$fold." ".b("fold");
    
    }
    else {

	return param('exprtype');

    }
	
}

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

    $loci =~ s/[\t\n\r]+/ /g;
    $loci =~ s/ +/\:/g;

    my @loci = split(/:/, $loci);

    my $locusList;
    my $count;
    my $moreList;
    foreach my $gene (@loci) {
	
	my $locus = $gene4featNm{$gene} || $gene;

	$count++;

	if ($count <= 10) {
	    $locus = "\U$locus";
	    if ($locusList) {
		$locusList .= ", ";
	    }
	    $locusList .= a({-href=>$locusUrl.$gene}, $locus);
	}
	if ($moreList) { $moreList .= ":"; }

	$moreList .= $locus;

    }

    if ($count > 10) {
   	$locusList .= ", ".a({-href=>url."?more=1&id=$$",
			      -target=>'infowin'}, 
			      "More");
    }

    open(OUT, ">".$configPath->tmpDir."more.$$") || 
	    die "Can't open '".$configPath->tmpDir."more.$$' for writing:$!";
    print OUT $moreList, "\n";
    close(OUT);

    return $locusList;
}

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

    foreach my $dataset (@dataset) {
	
	my $geneNum;

	if (param('submit3') || param('option') =~ /option3/i) {

	    $geneNum = $geneNum4dataset{$dataset}; 

	}
	else {

	    $geneNum = $totalGene;

	}
	if ($geneNum > 1) { $geneNum .= " genes"; }
	else { $geneNum .= " gene"; }

	$geneNum = " ($geneNum)";

	$datasetList .= li(a({-href=>"#$dataset"}, 
			     $datasetTitle{$dataset}).$geneNum);

    }

    return $datasetList;

}

########################################################################
sub getRegulatorModuleUrl {
########################################################################
    my ($self, $dataset, $datasetNo, $featNm, $featNo) = @_;
    
    my $regulatorModuleArrayRef = 
	    Dataset->RegulatorModuleArrayRef(dbh=>$dbh,
					     dataset_no=>$datasetNo,
					     feature_no=>$featNo);
        
    if (!@$regulatorModuleArrayRef) { return ; }
	  
    if (@$regulatorModuleArrayRef == 1) {

	my $rowRef = $$regulatorModuleArrayRef[0];

	my ($module) = @$rowRef;
 
	$module =~ s/^Module ([0-9]+)$/cluster_${1}\.html/i;

        return $configUrl->wineServerRoot."Dictyostelium/exp_modules/$dataset/$module";
			
    }
        
    return url."?dataset=$dataset&orf=$featNm&type=regulator";

           
}

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

    my $cubeImage = $configUrl->dictyBaseImages."redcube.PNG";

    print "<a name='top'>";

    print table({-align=>'center',
		 -border=>'0',
		 -cellpadding=>'0',
		 -cellspacing=>'0',
		 -width=>'100%'},
		Tr(td({-align=>'center'},
		      h2("Expression Connection allows you to search gene expression data from multiple microarray studies."))).
		Tr(td(table({-align=>'center',
			     -width=>'80%'},
			    Tr(td({-align=>'left'},
				  blockquote(b(a({-href=>'#Option1'},
						 img({-width=>'10',
						      -alt=>'bullet',
						      -src=>$cubeImage})).
					       " ".a({-href=>'#Option1'}, "Search I").": Find the expression of one or more genes in one or more datasets. ".
					       br.br.
					       a({-href=>'#Option2'},
						 img({-width=>'10',
						      -alt=>'bullet',
						      -src=>$cubeImage})).
					       " ".a({-href=>'#Option2'}, "Search II").": Find datasets where the expression of one or more genes changes by an amount you define. ".
					       br.br.
					       a({-href=>'#Option3'},
						 img({-width=>'10',
						      -alt=>'bullet',
						      -src=>$cubeImage})).
					       " ".a({-href=>'#Option3'}, "Search III").": Find all genes that change expression in a manner you define in one or more datasets (eg. increase by 10-fold). ".
					       br.br.
					       a({-href=>$configUrl->breadServerRoot."webminer/"},
						 img({-width=>'10',
						      -alt=>'bullet',
						      -src=>$cubeImage})).
					       " ".a({-href=>$configUrl->breadServerRoot."webminer/"}, "Webminer").": Search microarray datasets on an experiment by experiment basis ".
					       br.br.
					       a({-href=>'#Additional'},
						 img({-width=>'10',
						      -alt=>'bullet',
						      -src=>$cubeImage})).
					       " ".a({-href=>$configUrl->dictyBaseHelp.'Expression.html#other'}, "Other Resources").": Go to websites outside of dictyBase. ")))))))),p;

}

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

    my $subtitle = " Search I: Find the expression of one or more genes in one or more datasets.";
    
    print start_multipart_form;

    print hidden(-name=>'option',
		 -value=>'option1');

    print "<a name='Option1'>";

    print table({-border=>'0',
		 -cellpadding=>'10',
		 -cellspacing=>'0',
		 -width=>'100%'},
		$self->subtitleRow($subtitle).
		Tr(td({-colspan=>'3'},
		      blockquote($self->option1)))
		);

    print end_form;
    
}

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

    my $subtitle = " Search II: Find datasets where the expression of one or more genes changes by an amount you define.";
    
    print "<a name='Option2'>";

    print start_multipart_form;

    print hidden(-name=>'option',
		 -value=>'option2');

    print table({-border=>'0',
		 -cellpadding=>'10',
		 -cellspacing=>'0',
		 -width=>'100%'},
		$self->subtitleRow($subtitle).
		Tr(td({-colspan=>'3'},
		      blockquote($self->option2)))
		);

    print end_form;

}

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

    my $subtitle = " Search III: Find all genes that change expression in a manner you define in one or more datasets (eg. increase by 10-fold).";
    
    print "<a name='Option3'>";

    print start_form;

    print hidden(-name=>'option',
		 -value=>'option3');

    print table({-border=>'0',
		 -cellpadding=>'10',
		 -cellspacing=>'0',
		 -width=>'100%'},
		$self->subtitleRow($subtitle).
		Tr(td({-colspan=>'3'},
		      blockquote($self->option3)))
		);

    print end_form;
    
}

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

    my @orf = param('ORFs');
    my $loci = join('  ', @orf);

    return table({-border=>'1',
		  -cellpadding=>'10',
		  -width=>'100%'},
		 $self->stepRow("Step 1. Specify gene name(s):").
		 Tr(td(table({-border=>'0'},
			     Tr(td({-width=>'40%',
				     -valign=>'top'},
				    b("Enter gene name(s) separated by \"Return\":").br.
				    textarea(-name=>'loci',
					     -value=>$loci,
					     -cols=>'10',
					     -rows=>'10')).
				 td({-valign=>'top'},
				    font({-color=>'red',
					  -size=>'+2'},
					 b("OR"))).
				 td({-width=>'40%',
				     -valign=>'top'},
				    b("Select TEXT file with list of ORF or gene names, one per line. WORD Documents do not work unless saved as TEXT:").br.
				    filefield(-name=>'uploadfile')))))).
		 $self->stepRow("Step 2. Select datasets you wish to query:").
		 Tr(td(table({-border=>'0'},
			     Tr(td($self->datasetsTable))))).
		 $self->stepRow("Step 3. ".
				submit(-name=>'submit1',
				       -value=>'Submit').' '.
				reset(-name=>'Reset'))

	    );

}

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

    my @orf = param('ORFs');
    my $loci = join('  ', @orf);

    return table({-border=>'1',
		  -cellpadding=>'10',
		  -width=>'100%'},
		 $self->stepRow("Step 1. Specify gene name(s):").
		 Tr(td(table({-border=>'0'},
			     Tr(td({-width=>'40%',
				     -valign=>'top'},
				    b("Enter gene name(s) separated by \"Return\":").br.
				    textarea(-name=>'loci',
					     -value=>$loci,
					     -cols=>'10',
					     -rows=>'10')).
				 td({-valign=>'top'},
				    font({-color=>'red',
					  -size=>'+2'},
					 b("OR"))).
				 td({-width=>'40%',
				     -valign=>'top'},
				    b("Select TEXT file with list of ORF or gene names, one per line. WORD Documents do not work unless saved as TEXT:").br.
				    filefield(-name=>'uploadfile')))))).
		 $self->stepRow("Step 2. Choose expression change:").
		 Tr(td(table({-border=>'0'},
			     Tr(td(b("Get experiments where gene expression is").br.
				   $self->popup))))).
		 $self->stepRow("Step 3. ".
				submit(-name=>'submit2',
				       -value=>'Submit').' '.
				reset(-name=>'Reset'))

	    );

}

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

    return table({-border=>'1',
		  -cellpadding=>'10',
		  -width=>'100%'},
		 $self->stepRow("Step 1. Choose expression change:").
		 Tr(td(table({-border=>'0'},
			     Tr(td(b("Get all genes that are ").br.
				   $self->popup))))).
		 $self->stepRow("Step 2. Select datasets you wish to query:").
		 Tr(td(table({-border=>'0'},
			     Tr(td($self->datasetsTable))))).
		 $self->stepRow("Step 3. ".
				submit(-name=>'submit3',
				       -value=>'Submit').' '.
				reset(-name=>'Reset'))

	    );

}

########################################################################
sub datasetsTable {
########################################################################
    my ($self, $dataset) = @_;

    my $refUrl = $configUrl->dictyBaseCGIRoot."$dblink/reference/reference.pl?refNo=";
    my $statisticUrl = url."?type=statistic&dataset=";

    my $datasetArrayRef = Dataset->GetDatasetInfoArrayRef(dbh=>$dbh);

    my ($rows, $preDatasetNm, $datasetSrc, $datasetTitle, 
	$authors, $link, $reflist);
    
    foreach my $rowRef (@$datasetArrayRef) {

	my ($datasetNo, $datasetNm, $source, $title, $refNo, 
	    $citation) = @$rowRef;

	if ($dataset && "\U$datasetNm" ne "\U$dataset") { next; }

	$citation =~ s/^(.+)\([0-9]{4}\) [A-Z].+$/$1/;

	$citation = b($citation). 
	            a({-href=>$refUrl.$refNo,
		       -target=>'infowin'},
		      img({-src=>$configUrl->dictyBaseImages."dictyBaserefsml.gif",
		           -border=>0}));

	if ($datasetNm eq $preDatasetNm) {
	    
	    #$authors .= " | ".$citation;

	    $reflist .= br.$citation." ".$link;

	    next;
	    
	}
	if ($datasetTitle) {
	    
	#   $rows .= Tr(td(checkbox(-name=>'dataset',
	#			    -value=>$preDatasetNm,
	#			    -label=>'')." ".
	#	      b($datasetTitle).", ".$datasetSrc).
	#		td($authors." | ".$link));
	    $rows .= Tr(td(checkbox(-name=>'dataset',
				    -value=>$preDatasetNm,
				    -label=>'')." ".
		      b($datasetTitle).", ".$datasetSrc).
			td($reflist));
	    
	}
	
	$datasetTitle = $title;

	$datasetSrc = $source;

	# $authors = $citation;

	my $datasetObj = Dataset->new(dbh=>$dbh,
				      dataset_no=>$datasetNo);

	my $website = br;

	if ($datasetObj) {

	    $website = a({-href=>$datasetObj->web_site_url,
			  -target=>'infowin'},
			 img({-src=>$configUrl->dictyBaseImages."webSupplement.gif",
			      -border=>0}));

	}
	
	my $statistics = a({-href=>$statisticUrl.$datasetNm,
		           -target=>'infowin'},
			  img({-src=>$configUrl->dictyBaseImages."statsg2.PNG",
			       -width=>45,
			       -border=>0}));

        $link = $website." ".$statistics;

	if ($datasetObj->isInDatasetGroup) {

	    $link .= " ".a({-href=>$configUrl->wineServerRoot."Dictyostelium/exp_modules/$dataset/index.html",
			   -target=>'infowin'},
			  img({-src=>$configUrl->dictyBaseImages."reg.PNG",
			       -width=>32,
			       -border=>0}));

	}

	if ($citation =~ /Spellman/i) {

		$link .= br.font({-size=>'-1'}, "The analysis in Spellman et al included data from ".a({-href=>$refUrl.'19633'}, "Cho et al"));

	}

	$reflist = $citation." ".$link;

	$preDatasetNm = $datasetNm;

    }
    if ($dataset) {

	# return ($datasetTitle, $authors." | ".$link); 
	return ($datasetTitle, $reflist); 

    }

    $rows .= Tr(td(checkbox(-name=>'dataset',
				    -value=>$preDatasetNm,
				    -label=>'')." ".
		   b($datasetTitle).", ".$datasetSrc).
		td($reflist));

    return table({-bgcolor=>'#FFFFFF',
		  -border=>'2',
		  -cellpadding=>'5',
		  -cellspacing=>'0',
		  -width=>'100%'},
		 $rows);

}

########################################################################
sub golinks {
########################################################################
    my ($self, $orfArrayRef, $dataset, $downloadLink) = @_;

    my $formName1 = "goTermMapperForm_".$dataset;
    my $formName2 = "goTermFinderForm_".$dataset;
    my $formName3 = "goSummary_".$dataset;

    return start_form(-action=>$configUrl->dictyBaseCGIRoot."$dblink/GO/goTermMapper",
		      -name=>$formName1,
		      -target=>"infowin"). 
	   hidden(-name=>'ORFs',
		  -value=>$orfArrayRef).
	   a({-href=>"javascript:document.$formName1.submit()"},
	    "GO Term Mapper").end_form.br.
	   start_form(-action=>$configUrl->dictyBaseCGIRoot."$dblink/GO/goTermFinder",
		      -name=>$formName2,
		      -target=>"infowin"). 
	   hidden(-name=>'ORFs',
		  -value=>$orfArrayRef).
	   a({-href=>"javascript:document.$formName2.submit()"},
	    "GO Term Finder").end_form.br.
	   start_form(-action=>$configUrl->dictyBaseCGIRoot."$dblink/GO/GOreport.pl",
		      -name=>$formName3,
		      -target=>"infowin"). 
	   hidden(-name=>'similarORFs',
		  -value=>$orfArrayRef).
	   a({-href=>"javascript:document.$formName3.submit()"},
	    "View GO Annotation Summary").end_form.br.
	   $downloadLink;
  
}

########################################################################
sub manageGeneList {
########################################################################
    my ($self, $orfArrayRef, $dataset, $goTerm4orfHashRef) = @_;


    my $download = $self->createDownLoadLink($dataset, $goTerm4orfHashRef);

    my $formName1 = "goTermMapperForm_".$dataset.$$;
    my $formName2 = "goTermFinderForm_".$dataset.$$;
    my $formName3 = "goSummaryForm_".$dataset.$$;

    print p, table({-align=>'center',
	          -border=>'2',
	          -width=>'100%'},
		 Tr(th({-bgcolor=>'#b7d8e4'},
		       "Analyze gene list with:").
		    td({-align=>'center'},
		       br.start_form(-action=>$configUrl->dictyBaseCGIRoot."$dblink/GO/goTermFinder",
				    -name=>$formName1,
				    -target=>"infowin"). 
			 hidden(-name=>'ORFs',
				-value=>$orfArrayRef).
			 a({-href=>"javascript:document.$formName1.submit()"},
			   "GO Term Finder").end_form).
		    td({-align=>'center'},
		       br.start_form(-action=>$configUrl->dictyBaseCGIRoot."$dblink/GO/goTermMapper",
				    -name=>$formName2,
				    -target=>"infowin"). 
			 hidden(-name=>'ORFs',
				-value=>$orfArrayRef).
			 a({-href=>"javascript:document.$formName2.submit()"},
			   "GO Term Mapper").end_form)).
		 Tr(th({-bgcolor=>'#b7d8e4'},
		       "Manage gene list with:").
		    td({-align=>'center'},
		       br.start_form(-action=>$configUrl->dictyBaseCGIRoot."$dblink/GO/GOreport.pl",
				    -name=>$formName3,
				    -target=>"infowin"). 
			 hidden(-name=>'similarORFs',
				-value=>$orfArrayRef).
			 a({-href=>"javascript:document.$formName3.submit()"},
			   "View GO Annotation Summary").end_form).
		    td({-align=>'center'},
		       $download)));    

}

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

    return popup_menu(-name=>'exprtype',
		      -value=>['-Select-',
			       'Increased',
			       'Decreased',
			       'Increased or Decreased',
			       'Not Changed',
			       'Not Expression/No Data']).
	   b(" by ").
	   textfield(-name=>'fold',
		     -size=>'10').
	   b(" fold. (Enter a positive integer greater than or equal to 2)");
	   
}

########################################################################
sub stepRow {
########################################################################
    my ($self, $stepTitle) = @_;

    return Tr(td({-bgcolor=>'#b7d8e4',
		  -colspan=>'3'},
		 font({-size=>'+1'}, 
		      $stepTitle)));

}

########################################################################
sub subtitleRow {
########################################################################
    my ($self, $subtitle) = @_;

    return Tr({-width=>'100%',
	       -bgcolor=>'#a4abc2'},
	      td(font({-size=>'+2'},
		      a({-href=>'#top'},
			img({-width=>'17',
			     -alt=>'bullet',
			     -src=>$cubeImage})).
		      $subtitle)).
	      td(a({-href=>'#top'},
		   "Back to top")));
		
}

########################################################################
sub printSubtitle {
########################################################################
    my ($self, $subtitle) = @_;

    print table({-width=>'100%'},
		Tr({-bgcolor=>'#a4abc2'},
		   td({-align=>'left'},
		      h2($subtitle))));

}

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

    ##### force it to overwrite the value for loci parameter
    param('loci', $loci);

    print table(Tr(td(b("Scale"))).
		Tr(td(img({-border=>0,
			   -valign=>'bottom',
			   -width=>350,
		           -src=>$configUrl->dictyBaseImages."scale.1.5.gif"})." ").
		   td({-valign=>'bottom'},
		      start_form.
		      popup_menu(-name=>'sortBy',
				 -values=>['- Sort genes in datasets -',
					   'Alphabetically, by ORF name',
					   'Greatest to least Max Increase',
					   'Least to greatest Max Increase',
					   'Greatest to least Max Decrease',
					   'Least to greatest Max Decrease'],
				 -default=>param('sortBy')).

		      hidden(-name=>'dataset',
			     -value=>\@dataset).
		      hidden(-name=>'loci',
			     -value=>$loci).
		      hidden(-name=>'option',
			     -value=>'option1').
		      hidden(-name=>'showGeneNum',
			     -value=>param('showGeneNum')).
		      submit(-name=>'sortSubmit',
			     -value=>'Go').
		      end_form).
		   td({-valign=>'bottom',
		       -align=>'right'},
		      start_form.
#		      submit(-name=>'downloadSubmit',
#			     -value=>'Download Data').
		      submit(-name=>'newSearchSubmit',
			     -value=>'New Search').
		      end_form)));
		      

}

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

    print table(Tr(td(b("Scale"))).
		Tr(td(img({-border=>0,
			   -valign=>'bottom',
			   -width=>350,
		           -src=>$configUrl->dictyBaseImages."scale.1.5.gif"})." ").
		   td({-valign=>'bottom'},
		      start_form.
		      popup_menu(-name=>'sortBy',
				 -values=>['- Sort datasets -',
				     'Greatest to least Max Increase',
				     'Least to greatest Max Increase',
				     'Greatest to least Max Decrease',
				     'Least to greatest Max Decrease'],
				 -default=>param('sortBy')).
		      hidden(-name=>'loci',
			     -value=>$loci).
		      hidden(-name=>'exprtype',
			     -value=>param('exprtype')).
		      hidden(-name=>'fold',
			     -value=>param('fold')).
		      hidden(-name=>'option',
			     -value=>'option2').
		      submit(-name=>'sortSubmit',
			     -value=>'Go').
		      end_form).
		   td({-valign=>'bottom',
		       -align=>'right'},
		      start_form.
#		      submit(-name=>'downloadSubmit',
#			     -value=>'Download Data').
		      submit(-name=>'newSearchSubmit',
			     -value=>'New Search').
		      end_form)));
		      

}

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

    print table(Tr(td(b("Scale"))).
		Tr(td(img({-border=>0,
			   -valign=>'bottom',
			   -width=>350,
		           -src=>$configUrl->dictyBaseImages."scale.1.5.gif"})." ").
		   td({-valign=>'bottom'},
		      start_form.
		      popup_menu(-name=>'sortBy',
				 -values=>['- Sort genes in datasets -',
					   'Alphabetically, by ORF name',
					   'Greatest to least Max Increase',
					   'Least to greatest Max Increase',
					   'Greatest to least Max Decrease',
					   'Least to greatest Max Decrease'],
				 -default=>param('sortBy')).

		      hidden(-name=>'dataset',
			     -value=>\@dataset).
		      hidden(-name=>'exprtype',
			     -value=>param('exprtype')).
		      hidden(-name=>'fold',
			     -value=>param('fold')).
		      hidden(-name=>'option',
			     -value=>'option3').
		      hidden(-name=>'showGeneNum',
			     -value=>param('showGeneNum')).
		      submit(-name=>'sortSubmit',
			     -value=>'Go').
		      end_form).
		   td({-valign=>'bottom',
		       -align=>'right'},
		      start_form.
#		      submit(-name=>'downloadSubmit',
#			     -value=>'Download Data').
		      submit(-name=>'newSearchSubmit',
			     -value=>'New Search').
		      end_form)));
		      

}

########################################################################
sub moreLink {
########################################################################
    my ($self, @loci) = @_;

    my $formName = "excn".$$;

    return
        start_form(-action=>url,
                   -name=>$formName,
                   -target=>'infowin').
        hidden(-name=>'more',
	       -value=>1).
        hidden(-name=>'gene',
               -value=>\@loci).
        a({-href=>"javascript:document.$formName.submit()"},
          "More").
	end_form;
      
}

########################################################################
# sub additionalSearch {
########################################################################
#    my ($self) = @_;
    
#    print "<a name='Additional'>";

#    print table({-width=>'100%'},
#		Tr(td(b("Additional searches can be found at these sites:").
#		      br.
#		      a({-href=>'http://transcriptome.ens.fr/ymgv/'}, 
#			"Dictyostelium Microarray Global Viewer").
#		      " at the Laboratories de genetique moleculaire, Paris, France").
#		   td(a({-href=>'#top'},
#			"Back to top"))));
    

# }

########################################################################
sub lineSeparator {
########################################################################
    
    print hr({-noshade=>1,
	      -size=>5,
              -color=>'#000000'});
}

########################################################################
sub exprFold {
########################################################################
    my ($self, $exprLogVal) = @_;

    if (!$exprLogVal) {
	return "1.0";
    }

    my ($sign, $exprFold);

    if ($exprLogVal < 0) {

	$sign = "-";

	$exprLogVal =~ s/^\-//;
    }

    $exprFold = 2**$exprLogVal;

    if ($exprFold =~ /^([0-9]+\.[0-9])([0-9])/) {

	$exprFold = $1;
 
	if ($2 >= 5) { $exprFold += 0.1; }
	
    }
    else { 
	
	$exprFold .= ".0";

    }

    return $sign.$exprFold;

}

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

    $configUrl = ConfigURLdictyBase->new;
    $dblink = $configUrl->dblink($self->database);
    $configPath = ConfigPathdictyBase->new;    
    $cubeImage = $configUrl->dictyBaseImages."redcube.PNG";

    if (!param) { return; }

    if (param('showGeneNum')) {

	$maxDisplayNum = param('showGeneNum');

    }

    $locusUrl = $configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=";

    if (param('loci') && param('uploadfile')) {

	$self->err_report("You can enter gene names OR select a file to upload for search option 1 or 2.");
	exit;

    }


    if (param('loci')) {
	$loci = param('loci');
	$loci =~ s/[\n\r\f\t ]/\:/g;
    }
    elsif (param('uploadfile')) {
      
	my $fh = upload('uploadfile');

	while(<$fh>) {
	    chomp;
	    $_ =~ s/\t/ /g;
	    my ($locus, $others) = split(/ /);
	    
	    $locus =~ s/\15/:/g;
	    $locus =~ s/\:+/\:/g;

	    &DeleteUnwantedChar(\$locus);

	    if (!$locus) { next; }
	    
	    $loci .= ":".$locus;
	}
	
    }
    elsif (param('dataset') && param('orf')) {
	
	$loci = param('orf');

	&DeleteUnwantedChar(\$loci);
	
    }
	
    $loci =~ s/\:+/\:/g;
    $loci =~ s/^\://;

    if ( (param('submit1') || param('submit2') ||
	  param('option') =~ /option(1|2)/i) && !$loci ) {

	$self->err_report("You must enter one or more genes for search option 1 or 2.");

	exit;

    }
    
    @dataset = param('dataset');

    if ( (param('submit1') || param('submit3') ||
	  param('option') =~ /option(1|3)/i) && !@dataset ) {

	$self->err_report("You have to choose one or more datasets for search option 1 or 3.");

	exit;

    }

    $exprtype = param('exprtype');

    $exprtype =~ s/^-Select-.*$//;

    $fold = param('fold');

    &DeleteUnwantedChar(\$fold);

#    if ($fold < 2) { 

#	$self->err_report("You have to enter a positive integer greater than or equal to 2 for search option 2 or 3.");

#	exit;

#    }
         
    if ( param('submit2') || param('submit3') || 
	 param('option') =~ /option(2|3)/i) {
	    
	if (!$exprtype) {

	    $self->err_report("You have to select the expression change pattern for search option 2 or 3.");

	    exit;

	}
	elsif ($exprtype =~ /(Increased|Decreased)/i && 
	       ($fold !~ /^[0-9]+$/ || $fold < 2) ) {

	    $self->err_report("You have to enter a positive integer greater than or equal to 2 for the expression increased/decreased fold.");
	    
	    exit;

	}

    }

    $sortBy = param('sortBy');

    my $datasetArrayRef = Dataset->GetDatasetInfoArrayRef(dbh=>$dbh);

    foreach my $rowRef (@$datasetArrayRef) {

	my ($datasetNo, $datasetNm, $source, $title, $others) = @$rowRef;
    
	$datasetTitle{$datasetNm} = $title;

    }

 
    if (param('submit1') || param('option') =~ /^option1/i || 
	param('submit3') || param('option') =~ /^option3/i) {

	my $arrayRef = Feature->GetAllFeatInfoArrayRef(dbh=>$dbh);

	foreach my $rowRef (@$arrayRef) {
	    
	    my ($featNm, $featNo, $locus, $others) = @$rowRef;

	    $featNo4featNmInAll{"\U$featNm"} = $featNo;
	    
	    $gene4featNmInAll{"\U$featNm"} = $locus;

	    $featNm4geneInAll{"\U$locus"} = $featNm;

	}

    }

    if (!$loci) { return; }

    my @loci = split(/:/, $loci);

    
    my $count;

    my @validLoci;

    foreach my $query (@loci) {
	
	my ($featNm, $featNo, $locusNm);

	if ($featNm4geneInAll{"\U$query"}) {

	    $locusNm = "\U$query";

	    $featNm = $featNm4geneInAll{$locusNm};

	    $featNo = $featNo4featNmInAll{"\U$featNm"};
	   
	}
	elsif ($gene4featNmInAll{"\U$query"}) {

	    $featNm = "\U$query";
	    
	    $locusNm = $gene4featNmInAll{$featNm};

	    $featNo = $featNo4featNmInAll{$featNm};

	}
	else {
	
	    my $seqObj = SeqParamTranslator->new(dbh=>$dbh,
						 query=>$query);
	    if ($seqObj->error) { 

		if ($self->{'_notFound'}) {
		    $self->{'_notFound'} .= ", ";
		}
		$self->{'_notFound'} .= $query;
		
		next; 

	    }
	    if ($seqObj->featureObject) {
		$featNm = $seqObj->featureObject->feature_name;
		$featNo = $seqObj->featureObject->feature_no;
		$locusNm = $seqObj->featureObject->locus_name;
	    }
	    else {

		if ($self->{'_noORFassociated'}) {
		    $self->{'_noORFassociated'} .= ", ";
		}
		$self->{'_noORFassociated'} .= $query;

	    }
	}
	if ($featNm) {
	    $featNo4featNm{$featNm} = $featNo;
	    $gene4featNm{$featNm} = $locusNm;
	    push(@orf, $featNm);
	    push(@validLoci, $query);
	}
    }

    $totalGene = scalar(@validLoci);

    $loci = join(':', @validLoci);


    $self->{'_noORFassociated'} =~ s/^(.+, .+,) ([^\,]+)$/$1 and $2/;
    $self->{'_notFound'} =~ s/^(.+, .+,) ([^\,]+$)/$1 and $2/;

    $self->{'_noORFassociated'} =~ s/^([^\,]+), ([^\,]+)$/$1 and $2/;
    $self->{'_notFound'} =~ s/^([^\,]+), ([^\,]+)$/$1 and $2/;
	
					
    if ($self->{'_noORFassociated'}) {
	    
	$self->{'_error'} = "No feature_name associated with gene ".$self->{'_noORFassociated'}.". ";

    }
    if ($self->{'_notFound'}) {

	$self->{'_error'} .= p."The ".$self->{'_notFound'};

	if ($self->{'_notFound'} !~ / and /) {
  
	    $self->{'_error'} .= " is not a valid gene name.";  

	}
	else {  

	    $self->{'_error'} .= " are not valid gene names.";  

	}

    }
    if (!$totalGene) {

	$self->{'_error'} .= p."Please enter a valid gene/ORF name. See ".a({-href=>$configUrl->breadServerRoot."Dictyostelium/gene_guidelines.html"}, "Gene Naming Guidelines")." for more help.".p;

	$self->err_report($self->{'_error'});
	
	exit;						       
        
    }


}

########################################################################
sub getSimilarGenes {
########################################################################
    my ($self, $dataset, $featNm) = @_;

    my $dataDir = $configPath->dataDir4web."dictyBase/";
    
    my $stem = $dataDir.$dataset."/".$dataset;

    my $corFile = $stem.".stdCor";

    open(COR, $corFile) ||
	die "Can't open '$corFile' for reading:$!";

    my @similarGenes;

    while(<COR>) {

	chomp;

	next unless (/^$featNm\t/i || /^$featNm$/i);

	@similarGenes = split(/\t/);

	last;

    }
    return @similarGenes;
    
}


########################################################################
sub setGeneList {
########################################################################
    my ($self, $dataset, $id) = @_;

    undef %featNo4featNm;
    undef %gene4featNm;
    undef @orf;
    undef $loci;

    my $arrayRef = Dataset->GetGeneNameArrayRefBYdataset(dbh=>$dbh,
							 dataset_name=>$dataset);

    $totalGene = scalar(@$arrayRef);

    my $count;
    foreach my $rowRef (@$arrayRef) {

	my ($featNm, $maxExprVal, $minExprVal) = @$rowRef;

	my $maxFoldUp = $self->exprFold($maxExprVal);

	my $maxFoldDown = $self->exprFold($minExprVal);

	if ($exprtype =~ /^Increased$/i && 
	    $maxFoldUp < $fold) {

	    next;

	}
	elsif ($exprtype =~ /^Decreased$/i && 
	       $maxFoldDown*(-1) < $fold) {

	    next;

	}
	elsif ($exprtype =~ /^Increased or Decreased$/i &&
	       $maxFoldUp < $fold && $maxFoldDown*(-1) < $fold) {

	    next;
		
	}
	elsif ($exprtype =~ /^Not changed/i && 
	       ($maxFoldUp > 2 || $maxFoldDown < -2)) {
	    
	    next;

        }
	
	$count++;

#	if ($count > $maxDisplayNum && !param('whole')) { last; }

	if ($loci) { $loci .= ":"; }
	$loci .= $featNm;
	
	push(@orf, $featNm);
	
	$featNo4featNm{$featNm} = $featNo4featNmInAll{"\U$featNm"};
	$gene4featNm{$featNm} = $gene4featNmInAll{"\U$featNm"};

    }
  
    my $tmpfile = $configPath->tmpDir."more.$id";

    open(TMP, ">$tmpfile") || die "Can't open '$tmpfile' for writing:$!";

    print TMP $loci;

    close(TMP);

}

########################################################################
sub err_report {
########################################################################
    my ($self, $err) = @_;

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

    exit;
}


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



















