
# assume Ki has been transformed to fKi (4-logKi)
# calculate angles between vectors
# two formats: "matrix" or "column"
sub AngleMatrix
{
    my ($HashHash, $Receptors, $Drugs, $Format) = @_;
    my ($fKii, $fKij, $SumSqI, $SumSqJ, $SumProd, $i, $j, $Theta);
    my $Pi = 3.141592653;
    my @Array = ();
    my $NumDrugs = scalar @$Drugs;
    if ($Format eq "matrix")
    {
        print "Drugs";
        for ($i = 0; $i < $NumDrugs; $i++)
        {
            print "	@$Drugs[$i]";
        }
        print "\n";
    }
    for ($i = 0; $i < $NumDrugs; $i++)
    {
        my $j;
        if ($Format eq "matrix")
        {
            print "@$Drugs[$i]";
        }
        if ($Format eq "column")
        {
            $j = $i + 1;
        }
        else
        {
            $j = 0;
        }
        for (; $j < $NumDrugs; $j++)
        {
            $SumSqI = $SumSqJ = $SumProd = 0;
            foreach $Receptor (@$Receptors)
            {
                $fKii = $$HashHash{@$Drugs[$i]}{$Receptor};
                $fKij = $$HashHash{@$Drugs[$j]}{$Receptor};
                if ($fKii < 0)
                {
                    $fKii = 0;
                }
                if ($fKij < 0)
                {
                    $fKij = 0;
                }
                $SumProd += $fKii * $fKij;
                $SumSqI += $fKii * $fKii;
                $SumSqJ += $fKij * $fKij;
            }
            $Theta = acos($SumProd / (sqrt($SumSqI) * sqrt($SumSqJ)));
            $Theta = 180 * $Theta / $Pi;
            my $Text = "$Theta @$Drugs[$i]:@$Drugs[$j]\n";
            push @Array, $Text;
            if ($Format eq "matrix")
            {
                printf("	%.1f", $Theta);
            }
        }
        if ($Format eq "matrix")
        {
            print "\n";
        }
    }
    if ($Format eq "column")
    {
        @Array = sort @Array;
        print @Array
    }
}

# calculate Euclidean distance between points
sub DistanceMatrix
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my ($Kii, $Kij, $SumSq, $Diff, $i, $j);
    my @Array = ();
    my $NumDrugs = scalar @Drugs;
    for ($i = 0; $i < $NumDrugs; $i++)
    {
        for ($j = $i + 1; $j < $NumDrugs; $j++)
        {
            $SumSq = 0;
            foreach $Receptor (@$Receptors)
            {
                $Kii = $$HashHash{$Drugs[$i]}{$Receptor};
                $Kij = $$HashHash{$Drugs[$j]}{$Receptor};
                $Diff = $Kii - $Kij;
                $SumSq += $Diff * $Diff;
            }
            $SumSq = sqrt $SumSq;
            my $Text = "$SumSq $Drugs[$i]:$Drugs[$j] distance\n";
            push @Array, $Text; 
        }
    }
    @Array = sort @Array;
    print @Array
}

# calculate lengths of vectors
sub VectorLengths
{
    my ($HashHash, $Receptors, $Drugs) = @_;
    my ($Ki, $SumSq, $PlainSum, $SumSqNo2B, $PlainSumNo2B);
    my ($SumExp, $SumExpNo2B);
    my @Array = ();
#   print "SumExp	SumSq	Sum	SumExpN	SumSqNB	SumNo2B	Drug\n";
    print "Sum	SumSq	SumExp	SumNo2B	SumSqNB	SumExpN	Drug\n";
    foreach $Drug (@$Drugs)
    {
        $SumSq = $PlainSum = $SumSqNo2B = $PlainSumNo2B = 0;
        $SumExp = $SumExpNo2B = 0;
        foreach $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki > 0)
            {
                $SumSq += $Ki * $Ki;
                $PlainSum += $Ki;
                $SumExp += exp $Ki;
                if ($Receptor ne "5ht2b")
                {
                    $SumSqNo2B += $Ki * $Ki;
                    $PlainSumNo2B += $Ki;
                    $SumExpNo2B += exp $Ki;
                }
            }
        }
        $SumSq = sqrt $SumSq;
        $SumSqNo2B = sqrt $SumSqNo2B;
        $SumExp = log $SumExp;
        $SumExpNo2B = log $SumExpNo2B;
        my $Text = printf("%7.4f	%7.4f	%7.4f	%7.4f	%7.4f	%7.4f	%s\n",
#           $SumExp, $SumSq, $PlainSum, $SumExpNo2B, $SumSqNo2B, $PlainSumNo2B, $Drug);
            $PlainSum, $SumSq, $SumExp, $PlainSumNo2B, $SumSqNo2B, $SumExpNo2B, $Drug);
#       push @Array, $Text; 
    }
#   @Array = sort @Array;
#   print @Array
}

# calculate lengths of vectors
sub VectorLengthsP
{
    my ($HashHash, $Receptors, $Drugs, $Pattern) = @_;
    my ($Ki, $SumSq, $PlainSum, $SumSqNo2B, $PlainSumNo2B);
    my ($SumExp, $SumExpNo2B);
    my @Array = ();
    print "Sum	SumSq	SumExp	SumNo2B	SumSqNB	SumExpN	Drug\n";
    foreach $Drug (@$Drugs)
    {
        $SumSq = $PlainSum = $SumSqNo2B = $PlainSumNo2B = 0;
        $SumExp = $SumExpNo2B = 0;
        foreach $Receptor (@$Receptors)
        {
            if ($Receptor =~ /$Pattern/) 
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                if ($Ki > 0)
                {
                    $SumSq += $Ki * $Ki;
                    $PlainSum += $Ki;
                    $SumExp += exp $Ki;
                    if ($Receptor ne "5ht2b")
                    {
                        $SumSqNo2B += $Ki * $Ki;
                        $PlainSumNo2B += $Ki;
                        $SumExpNo2B += exp $Ki;
                    }
                }
            }
        }
        $SumSq = sqrt $SumSq;
        $SumSqNo2B = sqrt $SumSqNo2B;
        if ($SumExp == 0)
        {
            $SumExp = 0;
        }
        else
        {
            $SumExp = log $SumExp;
        }
        if ($SumExpNo2B == 0)
        {
            $SumExpNo2B = 0;
        }
        else
        {
            $SumExpNo2B = log $SumExpNo2B;
        }
        my $Text = sprintf("%7.4f	%7.4f	%7.4f	%7.4f	%7.4f	%7.4f	%s\n",
            $PlainSum, $SumSq, $SumExp, $PlainSumNo2B, $SumSqNo2B, $SumExpNo2B, $Drug);
        push @Array, $Text; 
    }
    @Array = sort { $b <=> $a } @Array;
    print @Array
}

# calculate lengths of vectors in preparation for regression
# assume not FourMinusLog() and not NormalizeShiftMax()
sub VectorLengthsReg
{
    my ($HashHash, $Receptors, $Drugs) = @_;
    my ($Ki, $pKi, $SumSq, $PlainSum, $SumSq2, $PlainSum2);
    my ($SumExp, $SumExp2, $KiMin, $First);
    my @Array = ();

#   header line of output file
    print "Drug	KiMin	KiMinR	KiMinNo2B	KiMinRNo2B	Sum	SumSq	SumExp	Sum2	SumSq2	SumExp2	SumNo2B	SumSqNo2B	SumExpNo2B";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";

#   a line for each drug
    foreach $Drug (@$Drugs)
    {
        print "$Drug	";
        $KiMin     = $KiMinR     = $First     = 0;
        $KiMinNo2B = $KiMinRNo2B = $FirstNo2B = 0;
        $SumSq      = $PlainSum      = $SumExp     = 0;
        $SumSq2     = $PlainSum2     = $sumExp2    = 0;
        $SumSqNo2B  = $PlainSumNo2B  = $SumExpNo2B = 0;
        foreach $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki != 10000 && $Ki != 10001)
            {
                if ($First == 0)
                {
                    $KiMin = $Ki;
                    $KiMinR = $Receptor;
                    $First = 1;
                }
                elsif ($Ki < $KiMin)
                {
                    $KiMin = $Ki;
                    $KiMinR = $Receptor;
                }
                $pKi = 5 - (log($Ki) / log(10));
                $PlainSum += $pKi;
                $SumSq    += $pKi * $pKi;
                $SumExp   += exp $pKi;
                if ($Receptor ne "5ht2b")
                {
                    $PlainSumNo2B += $pKi;
                    $SumSqNo2B    += $pKi * $pKi;
                    $SumExpNo2B   += exp $pKi;
                    if ($FirstNo2B == 0)
                    {
                        $KiMinNo2B = $Ki;
                        $KiMinRNo2B = $Receptor;
                        $FirstNo2B = 1;
                    }
                    elsif ($Ki < $KiMinNo2B)
                    {
                        $KiMinNo2B = $Ki;
                        $KiMinRNo2B = $Receptor;
                    }
                }
            }
        }
        foreach $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki != 10000 && $Ki != 10001)
            {
                $pKi = 5 - (log($Ki) / log(10));
                if (($Ki/$KiMin) < 100)
                {
                    $PlainSum2 += $pKi;
                    $SumSq2    += $pKi * $pKi;
                    $SumExp2   += exp $pKi;
                }
            }
        }
        $SumSq = sqrt $SumSq;
        $SumSq2 = sqrt $SumSq2;
        $SumSqNo2B = sqrt $SumSqNo2B;
        if ($SumExp == 0)
        {
            $SumExp = 0;
        }
        else
        {
            $SumExp = log $SumExp;
        }
        if ($SumExp2 == 0)
        {
            $SumExp2 = 0;
        }
        else
        {
            $SumExp2 = log $SumExp2;
        }
        if ($SumExpNo2B == 0)
        {
            $SumExpNo2B = 0;
        }
        else
        {
            $SumExpNo2B = log $SumExpNo2B;
        }
        print "$KiMin	$KiMinR	$KiMinNo2B	$KiMinRNo2B	";
        print "$PlainSum	$SumSq	$SumExp	";
        print "$PlainSum2	$SumSq2	$SumExp2	";
        print "$PlainSumNo2B	$SumSqNo2B	$SumExpNo2B";
        foreach $Receptor (@$Receptors)
        {
            print "	$$HashHash{$Drug}{$Receptor}";
        }
        print "\n";
    }
}

# calculate lengths of vectors
sub VectorLengthsPro
{
    my ($HashHash, $Receptors, $Drugs, $Pattern) = @_;
    my ($Ki, $SumSq, $PlainSum, $SumSqNo2B, $PlainSumNo2B);
    my ($SumExp, $SumExpNo2B);
    my ($TSumSq, $TPlainSum, $TSumSqNo2B, $TPlainSumNo2B);
    my ($TSumExp, $TSumExpNo2B);
    my @Array = ();
    print "Sum	SumSq	SumExp	SumNo2B	SumSqNB	SumExpN	Drug\n";
    foreach $Drug (@$Drugs)
    {
        $SumSq = $PlainSum = $SumSqNo2B = $PlainSumNo2B = 0;
        $SumExp = $SumExpNo2B = 0;
        $TSumSq = $TPlainSum = $TSumSqNo2B = $TPlainSumNo2B = 0;
        $TSumExp = $TSumExpNo2B = 0;
        foreach $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki > 0)
            {
                if ($Receptor =~ /$Pattern/) 
                {
                    $SumSq += $Ki * $Ki;
                    $PlainSum += $Ki;
                    $SumExp += exp $Ki;
                    if ($Receptor ne "5ht2b")
                    {
                        $SumSqNo2B += $Ki * $Ki;
                        $PlainSumNo2B += $Ki;
                        $SumExpNo2B += exp $Ki;
                    }
                }
                $TSumSq += $Ki * $Ki;
                $TPlainSum += $Ki;
                $TSumExp += exp $Ki;
                if ($Receptor ne "5ht2b")
                {
                    $TSumSqNo2B += $Ki * $Ki;
                    $TPlainSumNo2B += $Ki;
                    $TSumExpNo2B += exp $Ki;
                }
            }
        }

        $SumSq = sqrt $SumSq;
        $SumSqNo2B = sqrt $SumSqNo2B;
        if ($SumExp == 0)
        {
            $SumExp = 0;
        }
        else
        {
            $SumExp = log $SumExp;
        }
        if ($SumExpNo2B == 0)
        {
            $SumExpNo2B = 0;
        }
        else
        {
            $SumExpNo2B = log $SumExpNo2B;
        }

        $TSumSq = sqrt $TSumSq;
        $TSumSqNo2B = sqrt $TSumSqNo2B;
        if ($TSumExp == 0)
        {
            $TSumExp = 0;
        }
        else
        {
            $TSumExp = log $TSumExp;
        }
        if ($TSumExpNo2B == 0)
        {
            $TSumExpNo2B = 0;
        }
        else
        {
            $TSumExpNo2B = log $TSumExpNo2B;
        }

        if ($TSumExp == 0)
        {
            $SumExp = 0;
        }
        else
        {
            $SumExp = $SumExp / $TSumExp;
        }
        if ($TSumSq == 0)
        {
            $SumSq = 0;
        }
        else
        {
            $SumSq = $SumSq / $TSumSq;
        }
        if ($TPlainSum == 0)
        {
            $PlainSum = 0;
        }
        else
        {
            $PlainSum = $PlainSum / $TPlainSum;
        }
        if ($TSumExpNo2B == 0)
        {
            $SumExpNo2B = 0;
        }
        else
        {
            $SumExpNo2B = $SumExpNo2B / $TSumExpNo2B;
        }
        if ($TSumSqNo2B == 0)
        {
            $SumSqNo2B = 0;
        }
        else
        {
            $SumSqNo2B = $SumSqNo2B / $TSumSqNo2B;
        }
        if ($TPlainSumNo2B == 0)
        {
            $PlainSumNo2B = 0;
        }
        else
        {
            $PlainSumNo2B = $PlainSumNo2B / $TPlainSumNo2B;
        }

        my $Text = sprintf("%7.4f	%7.4f	%7.4f	%7.4f	%7.4f	%7.4f	%s\n",
            $PlainSum, $SumSq, $SumExp, $PlainSumNo2B, $SumSqNo2B, $SumExpNo2B, $Drug);
        push @Array, $Text; 
    }
    @Array = sort { $b <=> $a } @Array;
    print @Array
}

# calculate lengths of vectors
sub VectorLengthsRece
{
    my ($HashHash, $Receptors, $Drugs) = @_;
    my ($Ki, $SumSq, $PlainSum, $SumExp);
    my @Array = ();
#   print "SumExp	SumSq	Sum	Receptor\n";
    print "Sum	SumSq	SumExp	Receptor\n";
    foreach $Receptor (@$Receptors)
    {
        $SumSq = $PlainSum = $SumExp = 0;
        foreach $Drug (@$Drugs)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki > 0)
            {
                $SumSq += $Ki * $Ki;
                $PlainSum += $Ki;
                $SumExp += exp $Ki;
            }
        }
        $SumSq = sqrt $SumSq;
        $SumExp = log $SumExp;
        my $Text = printf("%7.4f	%7.4f	%7.3f	%s\n",
            $PlainSum, $SumSq, $SumExp, $Receptor);
#           $SumExp, $SumSq, $PlainSum, $Receptor);
#       push @Array, $Text; 
    }
#   @Array = sort @Array;
#   print @Array
}

# calculate lengths of vectors
sub VectorLengthsOld
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my ($Ki, $SumSq);
    my @Array = ();
    foreach $Drug (@Drugs)
    {
        $SumSq = 0;
        foreach $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            $SumSq += $Ki * $Ki;
        }
        $SumSq = sqrt $SumSq;
        my $Text = "$SumSq $Drug vector length\n";
        push @Array, $Text; 
    }
    @Array = sort @Array;
    print @Array
}

sub DiffAverages
{
    my ($Receptors, $AvgList1, $AvgList2) = @_;
    my $i;
    foreach $Receptor (@$Receptors)
    {
        if ($$AvgList1[$i] eq "ND	ND" || $$AvgList2[$i] eq "ND	ND")
        {
            printf("%12s	", $Receptor);
            if ($$AvgList1[$i] eq "ND	ND")
            {
                print("ND	");
            }
            else
            {
                printf("%.3f	", $$AvgList1[$i]);
            }
            if ($$AvgList2[$i] eq "ND	ND")
            {
                print("ND	");
            }
            else
            {
                printf("%.3f	", $$AvgList2[$i]);
            }
            print("ND\n");
        }
        else
        {
            my $Diff = $$AvgList2[$i] - $$AvgList1[$i];
            printf("%12s	%.3f	%.3f	%.3f\n", $Receptor, $$AvgList1[$i], $$AvgList2[$i], $Diff);
        }
        $i++;
    }
}

# for the drugs listed in $List, calculate the average value
# and standard deviation at each receptor
sub AverageVectors
{
    my ($HashHash, $Receptors, $List, $Output) = @_;
    my @Array = ();
    my $Drug;
    foreach $Receptor (@$Receptors)
    {
        my $Ki = 0;
        my $Avg = 0;
        my $KiSum = 0;
        my $KiSumSq = 0;
        my $Count = 0;
        my $Sd = 0;
        foreach $Drug (@$List)
        {
            if ($$HashHash{$Drug}{$Receptor} != -1)
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                $KiSum += $Ki;
                $KiSumSq += $Ki * $Ki;
                $Count++;
            }
        }
        if ($Count > 0)
        {
            $Avg = $KiSum / $Count;
        }
        if ($Count > 1)
        {
            $Sd = sqrt((($Count * $KiSumSq) - ($KiSum * $KiSum))/($Count * ($Count - 1)));
        }
        if ($Count > 0)
        {
            push @Array, "$Avg	$Sd"; 
            if ($Output)
            {
                printf("%12s	%.2f±%.2f\n", $Receptor, $Avg, $Sd);
            }
        }
        else
        {
            push @Array, "ND	ND"; 
            if ($Output)
            {
                printf("%12s	ND\n", $Receptor);
            }
        }
    }
    print "\n";
    foreach $Receptor (@$Receptors)
    {
        my $Ki = 0;
        my $Avg = 0;
        my $KiSum = 0;
        my $KiSumSq = 0;
        my $Count = 0;
        my $Sd = 0;
        foreach $Drug (@$List)
        {
            if ($$HashHash{$Drug}{$Receptor} != -1)
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                $KiSum += $Ki;
                $KiSumSq += $Ki * $Ki;
                $Count++;
            }
        }
        if ($Count > 0)
        {
            $Avg = $KiSum / $Count;
        }
        if ($Count > 1)
        {
            $Sd = sqrt((($Count * $KiSumSq) - ($KiSum * $KiSum))/($Count * ($Count - 1)));
        }
        if ($Output)
        {
            if ($Count > 0)
            {
                printf("%.2f±%.2f\n", $Avg, $Sd);
            }
            else
            {
                printf("ND\n");
            }
        }
    }
    return @Array;
}

# for the drugs listed in $List, calculate the average value at
# each receptor
sub AverageVectorsOld
{
    my ($HashHash, $Receptors, $List) = @_;
    my @Array = ();
    my $Drug;
    foreach $Receptor (@$Receptors)
    {
        my $KiSum = 0;
        my $Count = 0;
        foreach $Drug (@$List)
        {
            if ($$HashHash{$Drug}{$Receptor} != -1)
            {
                $KiSum += $$HashHash{$Drug}{$Receptor};
                $Count++;
            }
        }
        if ($Count > 0)
        {
            $KiSum /= $Count;
        }
        push @Array, $KiSum; 
        print "$Receptor: $KiSum\n";
    }
    return @Array;
}

# Subtract one vector from another
sub DiffVectorPairs
{
    my ($HashHash, $Receptors, $List) = @_;
    my @Array = ();
    my $Pair;
    print "Compound";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";
    foreach $Pair (@$List)
    {
        $Pair=~/(\w.*) (\w.*)/;
        $Drug1 = $1;
        $Drug2 = $2;
#       print "\nPair: $Pair; Drug1: $Drug1; Drug2: $Drug2\n";
        print "$Pair";
        foreach $Receptor (@$Receptors)
        {
            my $Ki1 = $$HashHash{$Drug1}{$Receptor};
            my $Ki2 = $$HashHash{$Drug2}{$Receptor};
            if ($Ki1 == -1 || $Ki2 == -1 || ($Ki1 == 0 && $Ki2 == 0))
            {
                print "	NA";
            }
            else
            {
                my $Diff = $Ki2 - $Ki1;
                printf("	%.4f", $Diff);
            }
        }
        print "\n";
    }
}

sub SortColPrintListHashHashNorm
{
    my ($HashHash, $Receptors, $Drugs) = @_;
    my @Array = ();
    foreach $Receptor (@$Receptors)
    {
        @Array = ();
        print "$Receptor: ";
        foreach $Drug (@$Drugs)
        {
            my $Val = sprintf("%.2f", $$HashHash{$Drug}{$Receptor});
            my $Text = "$Val $Drug, ";
            push @Array, $Text; 
        }
        @Array = sort { $b <=> $a } @Array;
        print @Array;
        print "\n";
    }
}

sub SortRowPrintListHashHash
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my @Array = ();
    foreach $Drug (@Drugs)
    {
        @Array = ();
        print "$Drug: ";
        foreach $Receptor (@$Receptors)
        {
            my $Text = "$$HashHash{$Drug}{$Receptor} $Receptor, ";
            push @Array, $Text; 
        }
        @Array = sort { $a <=> $b } @Array;
        print @Array;
        print "\n";
    }
}

sub SortRowPrintListHashHashNorm
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my @Array = ();
    foreach $Drug (@Drugs)
    {
        @Array = ();
        print "$Drug: ";
        foreach $Receptor (@$Receptors)
        {
            my $Val = sprintf("%.2f", $$HashHash{$Drug}{$Receptor});
            my $Text = "$Val $Receptor, ";
            push @Array, $Text; 
        }
        @Array = sort { $b <=> $a } @Array;
        print @Array;
        print "\n";
    }
}

sub SortRowPrintListHashHashNormpKi
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my @Array = ();
    my $Val;
    foreach $Drug (@Drugs)
    {
        @Array = ();
        print "$Drug: ";
        foreach $Receptor (@$Receptors)
        {
            if ($$HashHash{$Drug}{$Receptor} eq "ND" ||
                $$HashHash{$Drug}{$Receptor} eq "UM")
            {
                $Val = $$HashHash{$Drug}{$Receptor};
            }
            else
            {
                $Val = sprintf("%.2f", $$HashHash{$Drug}{$Receptor});
            }
            my $Text = "$Val $Receptor, ";
            push @Array, $Text; 
        }
        @Array = sort { $b <=> $a } @Array;
        @Array = sort @Array;
        print @Array;
        print "\n";
    }
}

sub SortColPrintListHashHashNormKi
{
    my ($HashHash, $Receptors, $Drugs) = @_;
    my @Array = ();
    foreach $Receptor (@$Receptors)
    {
        @Array = ();
        print "$Receptor: ";
        foreach $Drug (@$Drugs)
        {
            if ($$HashHash{$Drug}{$Receptor} eq "ND" ||
                $$HashHash{$Drug}{$Receptor} eq "UM")
            {
                $Val = $$HashHash{$Drug}{$Receptor};
            }
            else
            {
                $Val = sprintf("%.2f", $$HashHash{$Drug}{$Receptor});
            }
            my $Text = "$Val $Drug, ";
            push @Array, $Text; 
        }
        @Array = sort { $b <=> $a } @Array;
        @Array = sort @Array;
        print @Array;
        print "\n";
    }
}

sub PrintListHashHash
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    foreach $Drug (@Drugs)
    {
        foreach $Receptor (@$Receptors)
        {
            print "$Drug $Receptor $$HashHash{$Drug}{$Receptor}\n";
        }
        print "\n";
    }
}

sub PrintTableHashHash
{
    my ($HashHash, $Receptors, $Drugs) = @_;
    print "Compound";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";
    foreach $Drug (@$Drugs)
    {
        print "$Drug";
        foreach $Receptor (@$Receptors)
        {
            print "	$$HashHash{$Drug}{$Receptor}";
        }
        print "\n";
    }
}

# transform Ki to npKi = (4 + pKi - pKiMax)
sub Normalize
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    my $pKi;
    my $pKiMax = 0;
    my $First;
    foreach $Drug (@Drugs)
    {
        $First = 1;
        foreach my $Receptor (@$Receptors)
        {
            if ($Receptor ne "B")
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                if ($Ki != 10000 && $Ki != 10001)
                {
                    $pKi = - (log($Ki) / log(10));
                    if ($First == 1)
                    {
                        $pKiMax = $pKi;
                        $First = 0;
                    }
                    if ($pKi > $pKiMax)
                    {
                        $pKiMax = $pKi;
                    }
                }
            }
        }
        foreach my $Receptor (@$Receptors)
        {
            # 0 and -1 values remain unchanged
            if ($Receptor ne "B")
            {
                if ($$HashHash{$Drug}{$Receptor} == 10001)
                {
                    $$HashHash{$Drug}{$Receptor} = -1;
                }
                elsif ($$HashHash{$Drug}{$Receptor} == 10000)
                {
                    $$HashHash{$Drug}{$Receptor} = 0;
                }
                else
                {
                    $Ki = $$HashHash{$Drug}{$Receptor};
                    $pKi = - (log($Ki) / log(10));
                    $$HashHash{$Drug}{$Receptor} = 4 + $pKi - $pKiMax;
                }
            }
        }
    }
    return %$HashHash;
}

# transform Ki to pKi = - (log($Ki) / log(10))
sub pKi
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    my $pKi;
    foreach $Drug (@Drugs)
    {
        foreach my $Receptor (@$Receptors)
        {
            # 0 and -1 values remain unchanged
            if ($Receptor ne "B")
            {
                if ($$HashHash{$Drug}{$Receptor} == 10001)
                {
                    $$HashHash{$Drug}{$Receptor} = ND;
                }
                elsif ($$HashHash{$Drug}{$Receptor} == 10000)
                {
                    $$HashHash{$Drug}{$Receptor} = UM;
                }
                else
                {
                    $Ki = $$HashHash{$Drug}{$Receptor};
                    $pKi = - (log($Ki) / log(10));
                    $$HashHash{$Drug}{$Receptor} = $pKi;
                }
            }
        }
    }
    return %$HashHash;
}

# transform Ki to npKi = (4 + pKi - pKiMax) and compute B, Bsq, Bexp
# Substitutes the value of the argument $NoData, where data is missing (10001)
sub Breadth
{
    my ($HashHash, $Receptors, $NoData) = @_;
    my @Drugs = keys %$HashHash;
    my $pKiMax = 0;
    my $First;
    my ($Ki, $pKi, $npKi);
    my ($B, $Bsq, $Bexp, $Max);

    print "Drug	B	Bsq	Bexp";
        print "	5ht	5ht1	5ht1max	5ht2	5ht2max	5ht2[ac]	5ht2[ac]max	5ht[67]	D[1-5]	D[1-5]max	^[AB]	^[AB]max	Alpha1	Alpha1max	Alpha2	Alpha2max	Beta	BetaMax	M[1-5]	M[1-5]max	Sigma	SigmaMax	H[12]	H[1-2]max	T\$	T\$max	[DKM]OR	[DKM]ORmax	CB[12]";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";

    foreach $Drug (@Drugs)
    {
        $First = 1;
        $B = $Bsq = $Bexp = 0;
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki != 10000 && $Ki != 10001)
            {
                $pKi = - (log($Ki) / log(10));
                if ($First == 1)
                {
                    $pKiMax = $pKi;
                    $First = 0;
                }
                if ($pKi > $pKiMax)
                {
                    $pKiMax = $pKi;
                }
            }
        }
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            # 0 and -1 values excluded
            if ($Ki != 10000 && $Ki != 10001)
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                $pKi = - (log($Ki) / log(10));
                $npKi = $$HashHash{$Drug}{$Receptor} = 4 + $pKi - $pKiMax;
                $B    += $npKi;
                $Bsq  += $npKi * $npKi;
                $Bexp += exp $npKi;
            }
            elsif ($Ki == 10000)
            {
                $$HashHash{$Drug}{$Receptor} = 0;
            }
            elsif ($Ki == 10001)
            {
                $$HashHash{$Drug}{$Receptor} = $$NoData;
            }
        }
        $Bsq = sqrt $Bsq;
        if ($Bexp != 0)
        {
            $Bexp = log $Bexp;
        }
        print "$Drug	$B	$Bsq	$Bexp";

# Receptor subgroups, based on pattern matches

        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "5ht");
        print "	$Bsq";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "5ht1");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "5ht2");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "5ht2[ac]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "5ht[67]");
        print "	$Bsq";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "D[1-5]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "^[AB]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "Alpha1");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "Alpha2");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "Beta");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "M[1-5]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "Sigma");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "H[12]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "T\$");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "[DKM]OR");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRtNeg1($HashHash, $Receptors, $Drug, "CB[12]");
        print "	$Bsq";

# Print receptors
        foreach my $Receptor (@$Receptors)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            print "	$npKi";
        }
        print "\n";
    }
    return %$HashHash;
}

sub PatternSumSqRtNeg1
{
    my ($HashHash, $Receptors, $Drug, $Pattern) = @_;
    my ($npKi, $SumSq, $Max, $Negative, $None);
    my $First = 1;
    $Max = -1;
    $SumSq = $Negative = 0;
    $None = 1;
    foreach $Receptor (@$Receptors)
    {
        if ($Receptor =~ /$Pattern/) 
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi >= 0)
            {
                $None = 0;
                if ($First == 1)
                {
                    $Max = $npKi;
                    $First = 0;
                }
                if ($npKi > $Max)
                {
                    $Max = $npKi;
                }
                $SumSq += $npKi * $npKi;
            }
            elsif ($npKi == -1)
            {
                $Negative = 1;
            }
        }
    }
    $SumSq = sqrt $SumSq;
    if ($Negative)
    {
        $SumSq = -1;
        if ($Max < 4.0)
        {
            $Max = -1;
        }
    }
    if ($None)
    {
        $SumSq = $Max = -1;
    }
    return $SumSq, $Max;
}


# transform Ki to npKi = (4 + pKi - pKiMax) and compute B, Bsq, Bexp
# substitute zeros for missing data (10001)
sub BreadthZeros
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $pKiMax = 0;
    my $First;
    my ($Ki, $pKi, $npKi);
    my ($B, $Bsq, $Bexp, $Max);

    print "Drug	B	Bsq	Bexp";
        print "	5ht	5ht1	5ht1max	5ht2	5ht2max	5ht2[ac]	5ht2[ac]max	5ht[67]	D[1-5]	D[1-5]max	^[AB]	^[AB]max	Alpha1	Alpha1max	Alpha2	Alpha2max	Beta	BetaMax	M[1-5]	M[1-5]max	Sigma	SigmaMax	H[12]	H[1-2]max	T\$	T\$max	[DKM]OR	[DKM]ORmax	CB[12]";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";

    foreach $Drug (@Drugs)
    {
        $First = 1;
        $B = $Bsq = $Bexp = 0;
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki != 10000 && $Ki != 10001)
            {
                $pKi = - (log($Ki) / log(10));
                if ($First == 1)
                {
                    $pKiMax = $pKi;
                    $First = 0;
                }
                if ($pKi > $pKiMax)
                {
                    $pKiMax = $pKi;
                }
            }
        }
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            # 0 and -1 values excluded
            if ($Ki != 10000 && $Ki != 10001)
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                $pKi = - (log($Ki) / log(10));
                $npKi = $$HashHash{$Drug}{$Receptor} = 4 + $pKi - $pKiMax;
                $B    += $npKi;
                $Bsq  += $npKi * $npKi;
                $Bexp += exp $npKi;
            }
            else
            {
                $npKi = $$HashHash{$Drug}{$Receptor} = 0;
            }
        }
        $Bsq = sqrt $Bsq;
        if ($Bexp != 0)
        {
            $Bexp = log $Bexp;
        }
        print "$Drug	$B	$Bsq	$Bexp";

# Receptor subgroups, based on pattern matches

        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "5ht");
        print "	$Bsq";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "5ht1");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "5ht2");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "5ht2[ac]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "5ht[67]");
        print "	$Bsq";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "D[1-5]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "^[AB]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "Alpha1");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "Alpha2");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "Beta");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "M[1-5]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "Sigma");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "H[12]");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "T\$");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "[DKM]OR");
        print "	$Bsq	$Max";
        ($Bsq, $Max) = PatternSumSqRt($HashHash, $Receptors, $Drug, "CB[12]");
        print "	$Bsq";

# Print receptors
        foreach my $Receptor (@$Receptors)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            print "	$npKi";
        }
        print "\n";
    }
    return %$HashHash;
}

sub PatternSumSqRt
{
    my ($HashHash, $Receptors, $Drug, $Pattern) = @_;
    my ($npKi, $SumSq, $Max);
    my $First = 1;
    $Max = $SumSq = 0;
    foreach $Receptor (@$Receptors)
    {
        if ($Receptor =~ /$Pattern/) 
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi > 0)
            {
                if ($First == 1)
                {
                    $Max = $npKi;
                    $First = 0;
                }
                if ($npKi > $Max)
                {
                    $Max = $npKi;
                }
                $SumSq += $npKi * $npKi;
            }
        }
    }
    $SumSq = sqrt $SumSq;
    return $SumSq, $Max;
}

# transform Ki to npKi = (4 + pKi - pKiMax) and compute B, Bsq, Bexp
sub BreadthPro
{
    my ($HashHash, $Receptors, $NoData) = @_;
    my @Drugs = keys %$HashHash;
    my $pKiMax = 0;
    my $First;
    my ($Ki, $pKi, $npKi);
    my ($B, $Bsq, $Bexp, $Bp);

    print "Drug	B	Bsq	Bexp";
        print "	5ht	5ht1	5ht2	5ht2[ac]	5ht[67]	D[1-5]	^[AB]	Alpha1	Alpha2	Beta	M[1-5]	Sigma	H[12]	T\$	[DKM]OR	CB[12]";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";

    foreach $Drug (@Drugs)
    {
        $First = 1;
        $B = $Bsq = $Bexp = 0;
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki != 10000 && $Ki != 10001)
            {
                $pKi = - (log($Ki) / log(10));
                if ($First == 1)
                {
                    $pKiMax = $pKi;
                    $First = 0;
                }
                if ($pKi > $pKiMax)
                {
                    $pKiMax = $pKi;
                }
            }
        }
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            # 0 and -1 values excluded
            if ($Ki != 10000 && $Ki != 10001)
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                $pKi = - (log($Ki) / log(10));
                $npKi = $$HashHash{$Drug}{$Receptor} = 4 + $pKi - $pKiMax;
                $B    += $npKi;
                $Bsq  += $npKi * $npKi;
                $Bexp += exp $npKi;
            }
            elsif ($Ki == 10000)
            {
                $$HashHash{$Drug}{$Receptor} = 0;
            }
            elsif ($Ki == 10001)
            {
                $$HashHash{$Drug}{$Receptor} = $$NoData;
            }
        }
        $BsqRt = sqrt $Bsq;
        if ($Bexp != 0)
        {
            $Bexp = log $Bexp;
        }
        print "$Drug	$B	$BsqRt	$Bexp";

# Receptor subgroups, based on pattern matches

        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "5ht");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "5ht1");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "5ht2");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "5ht2[ac]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "5ht[67]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "D[1-5]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "^[AB]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "Alpha1");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "Alpha2");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "Beta");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "M[1-5]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "Sigma");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "H[12]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "T\$");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "[DKM]OR");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";
        $GBsq = PatternSumSq($HashHash, $Receptors, $Drug, "CB[12]");
        if ($GBsq != -1)
        {
            $GBsq /= $Bsq;
        }
        print "	$GBsq";

# Print receptors
        foreach my $Receptor (@$Receptors)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi == -1)
            {
                $Bp = -1;
            }
            else
            {
                $Bp = ($npKi * $npKi)/ $Bsq;
            }
            print "	$Bp";
        }
        print "\n";
    }
    return %$HashHash;
}

sub PatternSumSq
{
    my ($HashHash, $Receptors, $Drug, $Pattern) = @_;
    my ($npKi, $SumSq, $Negative, $None);
    $SumSq = $Negative = 0;
    $None = 1;
    foreach $Receptor (@$Receptors)
    {
        if ($Receptor =~ /$Pattern/) 
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi >= 0)
            {
                $None = 0;
                $SumSq += $npKi * $npKi;
            }
            elsif ($npKi == -1)
            {
                $Negative = 1;
            }
        }
    }
    if ($Negative || $None)
    {
        $SumSq = -1;
    }
    return $SumSq;
}

# transform Ki to npKi = (4 + pKi - pKiMax) and compute Bsum, Bsq, Bexp
# for receptors
sub BreadthRece
{
    my ($HashHash, $Receptors, $NoData) = @_;
    my @Drugs = keys %$HashHash;
    my $pKiMax = 0;
    my $First;
    my ($Ki, $pKi, $npKi);
    my ($Bsum, $Bsq, $Bexp, $Max);

    print "Drug";
    foreach $Receptor (@$Receptors)
    {
        print "	$Receptor";
    }
    print "\n";

    foreach $Drug (@Drugs)
    {
        $First = 1;
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($Ki != 10000 && $Ki != 10001)
            {
                $pKi = - (log($Ki) / log(10));
                if ($First == 1)
                {
                    $pKiMax = $pKi;
                    $First = 0;
                }
                if ($pKi > $pKiMax)
                {
                    $pKiMax = $pKi;
                }
            }
        }
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            # 0 and -1 values excluded
            if ($Ki != 10000 && $Ki != 10001)
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                $pKi = - (log($Ki) / log(10));
                $npKi = $$HashHash{$Drug}{$Receptor} = 4 + $pKi - $pKiMax;
            }
            elsif ($Ki == 10000)
            {
                $$HashHash{$Drug}{$Receptor} = 0;
            }
            elsif ($Ki == 10001)
            {
                $$HashHash{$Drug}{$Receptor} = $$NoData;
            }
        }
        print "$Drug";

# Print receptors
        foreach my $Receptor (@$Receptors)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            print "	$npKi";
        }
        print "\n";
    }

# Add Bsum statistics for receptors
    print "Bsum";
    foreach my $Receptor (@$Receptors)
    {
        $Bsum = 0;
        foreach $Drug (@Drugs)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi > 0)
            {
                $Bsum += $npKi;
            }
        }
        print "	$Bsum";
    }
    print "\n";

# Add Bsq statistics for receptors
    print "Bsq";
    foreach my $Receptor (@$Receptors)
    {
        $Bsq = 0;
        foreach $Drug (@Drugs)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi > 0)
            {
                $Bsq  += $npKi * $npKi;
            }
        }
        $Bsq = sqrt $Bsq;
        print "	$Bsq";
    }
    print "\n";

# Add Bexp statistics for receptors
    print "Bexp";
    foreach my $Receptor (@$Receptors)
    {
        $Bexp = 0;
        foreach $Drug (@Drugs)
        {
            $npKi = $$HashHash{$Drug}{$Receptor};
            if ($npKi > 0)
            {
                $Bexp += exp $npKi;
            }
        }
        if ($Bexp != 0)
        {
            $Bexp = log $Bexp;
        }
        print "	$Bexp";
    }
    print "\n";

    return %$HashHash;
}

# transformed Ki to fKi = (4-logKi)
sub FourMinusLog
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    foreach $Drug (@Drugs)
    {
        foreach my $Receptor (@$Receptors)
        {
            if ($Receptor ne "B")
            {
                if ($$HashHash{$Drug}{$Receptor} == 10001)
                {
                    $$HashHash{$Drug}{$Receptor} = -1;
                }
                else
                {
                    $$HashHash{$Drug}{$Receptor} =
                        4 - (log($$HashHash{$Drug}{$Receptor}) / log(10));
                }
            }
        }
    }
    return %$HashHash;
}

# assume Ki has been transformed to fKi = (4-logKi)
sub NormalizeShiftMax
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    my $KiMax = 0;
    my $First;
    my $Delta;
    foreach $Drug (@Drugs)
    {
        $First = 1;
        foreach my $Receptor (@$Receptors)
        {
            if ($Receptor ne "B")
            {
                $Ki = $$HashHash{$Drug}{$Receptor};
                if ($First == 1)
                {
                    $KiMax = $Ki;
                    $First = 0;
                }
                if ($Ki > $KiMax)
                {
                    $KiMax = $Ki;
                }
            }
        }
        $Delta = 4 - $KiMax;
        foreach my $Receptor (@$Receptors)
        {
            # 0 and -1 values remain unchanged
            if ($Receptor ne "B")
            {
                if ($$HashHash{$Drug}{$Receptor} > 0)
                {
                    $$HashHash{$Drug}{$Receptor} += $Delta;
                }
            }
        }
    }
    return %$HashHash;
}

# assume Ki has been transformed to fKi = (4-logKi)
sub NormalizeShiftMaxOld
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    my $KiMax = 0;
    my $First;
    my $Delta;
    foreach $Drug (@Drugs)
    {
        $First = 1;
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($First == 1)
            {
                $KiMax = $Ki;
                $First = 0;
            }
            if ($Ki > $KiMax)
            {
                $KiMax = $Ki;
            }
        }
        $Delta = 4 - $KiMax;
        foreach my $Receptor (@$Receptors)
        {
            if ($$HashHash{$Drug}{$Receptor} > 0)
            {
                $$HashHash{$Drug}{$Receptor} += $Delta;
            }
        }
    }
    return %$HashHash;
}

# assume Ki has been transformed to fKi = (4-logKi)
sub NormalizeByMax
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    my $KiMax = 0;
    my $First;
    foreach $Drug (@Drugs)
    {
        $First = 1;
        foreach my $Receptor (@$Receptors)
        {
            $Ki = $$HashHash{$Drug}{$Receptor};
            if ($First == 1)
            {
                $KiMax = $Ki;
                $First = 0;
            }
            if ($Ki > $KiMax)
            {
                $KiMax = $Ki;
            }
        }
        foreach my $Receptor (@$Receptors)
        {
            $$HashHash{$Drug}{$Receptor} /= $KiMax;
        }
    }
    return %$HashHash;
}

# transformed Ki to fKi = (4-logKi)
sub FourMinusLogOld
{
    my ($HashHash, $Receptors) = @_;
    my @Drugs = keys %$HashHash;
    my $Ki;
    foreach $Drug (@Drugs)
    {
        foreach my $Receptor (@$Receptors)
        {
            if ($$HashHash{$Drug}{$Receptor} == 10001)
            {
                $$HashHash{$Drug}{$Receptor} = 10000;
            }
            $$HashHash{$Drug}{$Receptor} =
            4 - (log($$HashHash{$Drug}{$Receptor}) / log(10));
        }
    }
    return %$HashHash;
}

sub MakeDrugReceptorHashHash
{
    my ($DrugKiHash, $Receptors) = @_;
    my %HashHash = ();
    my $Drug;
    my @Drugs;
    my $Receptor;
    my @KiValues;
    my $NumReceptors = scalar @$Receptors;

    @Drugs = keys %$DrugKiHash;

    foreach $Drug (keys %$DrugKiHash)
    {
        @KiValues = split /	/, $$DrugKiHash{$Drug};
        for (my $c = 0; $c < $NumReceptors; $c++)
        {
            $HashHash{$Drug}{$$Receptors[$c]} = $KiValues[$c];
        }
    }

    return %HashHash;
}

sub MakeListOfReceptors
{
    my @Receptors = ();
    $Line = $_[0];
    chomp $Line;
    @Receptors = split /	/, $Line;
    shift @Receptors;
    my $NumRec = scalar @Receptors;
#   chop $Receptors[$NumRec - 1];
    return @Receptors;
}

sub MakeListOfDrugs
{
    my @DrugList = ();
    my $First = 1;
    foreach my $Line (@_)
    {
        if ($First == 1)
        {
            $First = 0;
            next;
        }
        chomp $Line;
        $Line =~ /(\S+)/;
        push @DrugList, $1; 
    }
    return @DrugList;
}

sub MakeDrugKiHash
{
    my $Key;
    my %DrugKiHash = ();
    my $First = 1;
    foreach my $Line (@_)
    {
        if ($First == 1)
        {
            $First = 0;
            next;
        }
        $Line =~ /(\S+)\s(.*)/;
        $DrugKiHash{$1} = $2;
    }
    return %DrugKiHash;
}

sub OpenFile
{

    my($filename) = @_;
    my $fh;

    unless(open($fh, $filename)) {
        print "Cannot open file $filename\n";
        exit;
    }
    return $fh;
}

sub ReadFile
{
    my ($FileName) = @_;
    unless(open(MYFILE, $FileName))
    {
        print "Cannot open file $FileName\n";
        exit;
    }
    my @Data = <MYFILE>;
    close MYFILE;
    return @Data;
}

sub acos
{
    my $Calc = 1 - $_[0] * $_[0];
    if ($Calc < 0)
    {
        if ($Calc < -.0000001)
        {
            print STDERR "in sub acos, sqrt of negative: $Calc\n"; 
        }
        $Calc = 0;
    }
    atan2( sqrt($Calc), $_[0] )
#   atan2( sqrt(1 - $_[0] * $_[0]), $_[0] )
}

1
