Show GeneView.pm syntax highlighted
#!/usr/bin/perl -w
package GeneView;
#use strict;
use FileHandle;
use CGI;
use GD;
do 'SITEDEF.pl';
do 'xGDB_SUPPORTED_COLORS.pl';
############# Defaults #################
my $StartX=20;
my $Margin=10;
my $LabelHeight=4;
my $LabelSpace=10;
my $HeightInc=150;
my $HalfLabelHeight=$LabelHeight/2;
my $StartY=50;
my $RulerHeight=3;
my $IDHeight=15;
#########################################
############################## Constructor ################################
# new GeneView($imgWidth,$imgHeight,$begPos,$endPos);
sub new {
my ($class,@param) = @_;
my $self = {};
bless $self, ref($class) || $class;
$self->_initialize(@param);
return $self;
}
sub _initialize{
my $self = shift;
my ($imgWidth,$imgHeight,$begPos,$endPos,$noRULER,$scale)=@_;
$noRULER = 0 if(!defined($noRULER));
$self->{'imgWidth'}= $imgWidth;
$self->{'imgHeight'}=$imgHeight;
$self->{'imgHeight'}=$imgHeight;
$self->{'begPos'}=$begPos;
$self->{'endPos'}=$endPos;
# assign some variables for the image;
my $unit=1000;
my $len=$endPos-$begPos+1;
if($len<1000){
$unit=10;
}elsif($len<10000){
$unit=100;
}
if($noRULER == 1){
$StartY=10;
$HeightInc=1;
$self->{'zeroPos'}=int($begPos);
$self->{'seqLen'}=$endPos- $self->{'zeroPos'} + 1;
my $ratio=$self->{'seqLen'}/($self->{'imgWidth'}-$StartX-2*$Margin);
$ratio = $scale if($scale);
$self->{'rulerLen'}=$self->{'seqLen'}/$ratio;
$self->{'scale'}=$self->{'seqLen'}/$self->{'rulerLen'};
$self->{'currHeight'}=10;
$self->{'img'} = new GD::Image($imgWidth,$imgHeight);
$self->{'isLabeled'}= ($self->{'scale'}<100)?1:0;
$self->_defColor($self->{'img'});
}else{
$self->{'zeroPos'}=int($begPos);
$self->{'tickStart'}=(int($begPos/$unit))*$unit;
$self->{'seqLen'}=$endPos- $self->{'zeroPos'} + 1;
my $ratio=$self->{'seqLen'}/($self->{'imgWidth'}-$StartX-2*$Margin);
$self->{'rulerLen'}=$self->{'seqLen'}/$ratio + 0.5;
$self->{'scale'}=$self->{'seqLen'}/$self->{'rulerLen'};
$self->{'currHeight'}=10;
$self->{'img'} = new GD::Image($imgWidth,$imgHeight);
$self->{'isLabeled'}= ($self->{'scale'}<100)?1:0;
$self->_defColor($self->{'img'});
$self->_drawRuler();
}
}
sub setLabelOn{
my $self = shift;
$self->{'isLabeled'} = shift;
}
sub _clear{
#do nothing
}
#draw the ruler
sub _drawRuler{
my $self= shift;
my $nextPower=0.001;
my $MinDist=100;
my $ruler;
my $im=$self->{'img'};
# get the resolution of the ruler
my $minDist=$MinDist*$self->{'scale'};
while($nextPower<$minDist){
$nextPower*=10;
}
if($minDist<$nextPower/5.0){
$ruler=($nextPower+0.5)/5.0;
}elsif($minDist<$nextPower/4.0){
$ruler=($nextPower+0.5)/4.0;
}elsif($minDist<$nextPower/2){
$ruler=($nextPower+0.5)/2.0;
}else{
$ruler=$nextPower+0.5;
}
$im->filledRectangle(min($self->_pos2x($self->{'zeroPos'}),($self->_pos2x($self->{'tickStart'}))),
$self->{'currHeight'},$self->_pos2x($self->{'endPos'}),
$self->{'currHeight'}+$RulerHeight,$self->{'black'});
{
use integer;
my($tick_len,$x_pos,$pos,$i);
$self->{'currHeight'}+=$RulerHeight;
$ruler=$ruler/10;
for($pos=$self->{'tickStart'},$i=0;
$pos<=$self->{'endPos'};
$pos+=$ruler,$i++){
$tick_len=($i%5==0)?6:3;
$x_pos=$self->_pos2x($pos);
if($i%5==0){
$im->string(gdTinyFont,
$x_pos-(gdTinyFont->width)*length($pos)/2,
$self->{'currHeight'}+10,$pos,$self->{'black'});
}
$im->line($x_pos,$self->{'currHeight'},$x_pos,
$self->{'currHeight'}+$tick_len,$self->{'black'});
}
}
}
sub _pos2x{
my $self=shift;
my($pos)=@_;
return int(( $pos - $self->{'zeroPos'} )/$self->{'scale'} + $StartX);
}
sub drawPNG{
my ($self, $outfn) = @_;
open (IMG,"> $outfn") or die "Cannot open file $outfn!";
binmode IMG;
print IMG $self->{'img'}->png;
close IMG;
}
# to find the specified region is occupied or not
sub _isEmpty{
my $self = shift;
my($x1,$x2,$h)=@_;
my $c;
my $i;
for($i=$x1-8;$i<=$x2+8;$i+=2){
$c= $self->{'img'}->getPixel($i,$h);
return 0 if($c != $self->{'white'});
}
return 1;
}
sub _defColor{
my $self = shift;
my ($img) = @_;
$self->{'white'}=$img->colorAllocate(255, 255, 255);
$self->{'black'}=$img->colorAllocate(0, 0, 0);
$self->{'red'}=$img->colorAllocate(255, 0, 0);
$self->{'green'}=$img->colorAllocate(0, 255, 0);
$self->{'blue'}=$img->colorAllocate(0, 0, 255);
}
sub _GV_addColor{
my $self = shift;
my ($colorname) = @_;
if(exists($SUPPORTED_COLORS{lc($colorname)})){
# print STDERR "Resolving color $colorname\n";
return $self->{img}->colorResolve(@{$SUPPORTED_COLORS{lc($colorname)}});
}else{
print STDERR "[GeneView.pm] The color $colorname is NOT SUPPORTED!\n";
return undef;
}
}
sub _getHeight{
my $self = shift;
my($x1,$x2,$height)=@_;
my $labelSpace=$LabelSpace+(($self->{'isLabeled'})?$IDHeight:0);
while(!(($self->_isEmpty($x1,$x2,$height)) &&
($self->_isEmpty($x1,$x2,$height + $HalfLabelHeight + 8)) &&
($self->_isEmpty($x1,$x2,$height + 5)) &&
($self->_isEmpty($x1,$x2,$height - 5)))){
$height+=$labelSpace;
}
if($height+$LabelHeight+$labelSpace>$self->{'imgHeight'}){
#$HeightInc = $height;
#resize the image
#my $newPicHeight=$self->{'imgHeight'}+$HeightInc;
my $newPicHeight=$height+$LabelHeight+$labelSpace;
my $tmpIm=new GD::Image($self->{'imgWidth'},$newPicHeight);
$self->_defColor($tmpIm);
$tmpIm->copy($self->{'img'},0,0,0,0,
$self->{'imgWidth'},$self->{'imgHeight'});
$self->{'img'}=$tmpIm;
$self->{'imgHeight'}=$newPicHeight;
}
return $height;
}
sub _drawBar{
my $self = shift;
my($a,$b,$height,$c)=@_;
my $x1=$self->_pos2x($a);
my $x2=$self->_pos2x($b);
return undef if((($x1 < 0)&&($x2 < 0))||(($x1 > $self->{imgWidth})&&($x2 > $self->{imgWidth})));
$x2=$x1+2 if($x2-$x1<2);
{
use integer;
$self->{'img'}->filledRectangle($x1,$height-$HalfLabelHeight,$x2,
$height+$HalfLabelHeight,$c);
}
}
sub _drawStartBar{
my $self = shift;
my($a,$b,$height,$c,$c_s,$isReversed)=@_;
my $x1=$self->_pos2x($a);
my $x2=$self->_pos2x($b);
return undef if((($x1 < 0)&&($x2 < 0))||(($x1 > $self->{imgWidth})&&($x2 > $self->{imgWidth})));
if($x2-$x1<2){
$x2 = $x1+2;
use integer;
$self->{'img'}->filledRectangle($x1,$height-$HalfLabelHeight,$x2,
$height+$HalfLabelHeight,$c_s);
}elsif($isReversed){
use integer;
$self->{'img'}->filledRectangle($x2-4,$height-$HalfLabelHeight,$x2,
$height+$HalfLabelHeight,$c_s);
$self->{'img'}->filledRectangle($x1,$height-$HalfLabelHeight,$x2-4,
$height+$HalfLabelHeight,$c);
}else{
use integer;
$self->{'img'}->filledRectangle($x1,$height-$HalfLabelHeight,$x1+4,
$height+$HalfLabelHeight,$c_s);
$self->{'img'}->filledRectangle($x1+4,$height-$HalfLabelHeight,$x2,
$height+$HalfLabelHeight,$c);
}
}
sub _drawArrow{
my $self = shift;
my($a,$b,$height,$c,$c_a,$dir)=@_;
my $x1=$self->_pos2x($a);
my $x2=$self->_pos2x($b);
return undef if((($x1 < 0)&&($x2 < 0))||(($x1 > $self->{imgWidth})&&($x2 > $self->{imgWidth})));
my $poly=new GD::Polygon;
$x2=$x1+2 if($x2-$x1<2);
{ use integer;
if($dir){
$poly->addPt($x1,$height);
$poly->addPt(&max(&min($x1+5,$x2),$x1+2),$height-5);
$poly->addPt(&max(&min($x1+5,$x2),$x1+2),$height+5);
$self->{'img'}->filledPolygon($poly,$c_a);
if($x2-$x1>5){#draw a bar
$self->{'img'}->filledRectangle($x1+5,$height-$HalfLabelHeight,$x2,$height+$HalfLabelHeight,$c);
}
}else{
$poly->addPt($x2,$height);
$poly->addPt(&min(&max($x1,$x2-5),$x2-2),$height-5);
$poly->addPt(&min(&max($x1,$x2-5),$x2-2),$height+5);
$self->{'img'}->filledPolygon($poly,$c_a);
if($x2-$x1>5){#draw a bar
$self->{'img'}->filledRectangle($x1,$height-$HalfLabelHeight,$x2-5,$height+$HalfLabelHeight,$c);
}
}
}
}
sub _drawSEdot{
my $self = shift;
my($a,$b,$height,$c)=@_;
my $x1=$self->_pos2x($a);
my $x2=$self->_pos2x($b);
return undef if((($x1 < 0)&&($x2 < 0))||(($x1 > $self->{imgWidth})&&($x2 > $self->{imgWidth})));
my $mid=($x1+$x2)/2;
if((($mid - 2) > 0)&&(($mid + 2) < $self->{'imgWidth'})){
$self->{'img'}->filledRectangle($mid - 2,$height-$HalfLabelHeight,$mid + 2,$height+$HalfLabelHeight,$c);
}
}
sub drawPair{
my $self = shift;
my($x1,$h1,$x2,$h2,$color) = @_;
my $c=$self->_GV_addColor($color);
$self->{'img'}->rectangle($x1-2,$h1+$HalfLabelHeight-5,$x2+2,$h2-$HalfLabelHeight+5,$c);
}
sub drawFLAG{
my($self,$FLAG_filename,$x,$y) = @_;
open(FLAGfile,"$FLAG_filename") || die "couldn't open flag file <$FLAG_filename>\n";
my $FLAGimg = GD::Image->new(FLAGfile);
$self->{'img'}->rectangle($x,$y,$x+22,$y+22,$self->{'grey'});
$self->{'img'}->copy($FLAGimg,$x+2,$y+2,0,0,20,20);
close(FLAGfile);
return $x + 24;
}
sub descFLAG{
my($self,$FLG_DESC,$oc_url,@coords) = @_;
#$FLG_DESC = CGI::escape($FLG_DESC);
my $areaTAG = "<AREA SHAPE=\"RECT\" COORDS=\"".join(',',@coords)."\" HREF=\"$oc_url\"".
" onmouseover=\"document.guiFORM.defline.value='$FLG_DESC';\"".
" onmouseout=\"document.guiFORM.defline.value='Mouse over for description. Click to retrieve individual record.';\">\n";
return $areaTAG;
}
sub addFLAGS{
my($self,$startHeight,$info,$utr5,$cov,$utr3,$props,$oc_url) = @_;
my $strand = ($info =~ /comp/)? 1:0;
$info =~ s/[^\d\.,]//g;
my @pgs = split(/[\D\.,]+/,$info);
my $initHeight=($startHeight)?$startHeight+$HalfLabelHeight:$StartY;
my $x1=$self->_pos2x($pgs[0]);
my $x2=$self->_pos2x($pgs[$#pgs]);
my $height=$self->_getHeight(&min($x1,$x2),&max($x2,$x1),$initHeight);
my ($curX,$FLAGdesc,$imap,@props);
if(($x2 - $x1) > 74){
## Enough room for at least utr5/cov/utr3 flags
$curX = $x1+2;
if($strand){
$curX = drawFLAG($self,$FLAG_UTR3[$utr3],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_UTR3[$utr3],$oc_url,$x1,$height-6,$curX-1,$height+20);
}else{
$curX = drawFLAG($self,$FLAG_UTR5[$utr5],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_UTR5[$utr5],$oc_url,$x1,$height-6,$curX-1,$height+20);
}
$curX = drawFLAG($self,$FLAG_COV[$cov],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_COV[$cov],$oc_url,$curX-24,$height-6,$curX-1,$height+20);
if($strand){
$curX = drawFLAG($self,$FLAG_UTR5[$utr5],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_UTR5[$utr5],$oc_url,$curX-24,$height-6,$curX-1,$height+20);
}else{
$curX = drawFLAG($self,$FLAG_UTR3[$utr3],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_UTR3[$utr3],$oc_url,$curX-24,$height-6,$curX-1,$height+20);
}
if(($x2 - $curX) > 24){
## Draw props flags as space allows
chop($props) if($props =~ /:$/);
@props = split(':',$props);
while((($x2 - $curX) > 50)&&(scalar @props)){
$props = shift @props;
if($FLAG_PROP[$props] ne ""){
$curX = drawFLAG($self,$FLAG_PROP[$props],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_PROP[$props],$oc_url,$curX-24,$height-6,$curX-1,$height+20);
}
}
if(scalar @props){
## draw FLAG_GAEVAL_MORE to show that more props remain unseen
$curX = drawFLAG($self,$FLAG_GAEVAL_MORE,$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_GAEVAL_MORE,$oc_url,$curX-24,$height-6,$curX-1,$height+20);
$FLAGdesc = $FLAGdesc_GAEVAL_MORE;
}else{
## draw FLAG_GAEVAL to show all props are displayed
$curX = drawFLAG($self,$FLAG_GAEVAL,$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_GAEVAL,$oc_url,$curX-24,$height-6,$curX-1,$height+20);
$FLAGdesc = $FLAGdesc_GAEVAL;
}
}
}else{
## Only enough room for cov flag
$curX = $x1+2;
$curX = drawFLAG($self,$FLAG_COV[$cov],$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_COV[$cov],$oc_url,$x1,$height-6,$curX-1,$height+20);
if(($x2 - $curX) > 24){
## draw FLAG_GAEVAL_MORE to show that more props remain unseen
$curX = drawFLAG($self,$FLAG_GAEVAL_MORE,$curX,$height-4);
$imap .= descFLAG($self,$FLAGdesc_GAEVAL_MORE,$oc_url,$curX-24,$height-6,$curX-1,$height+20);
}
$FLAGdesc = $FLAGdesc_GAEVAL_MORE;
}
$x2 = $curX if ($curX > $x2);
$self->{'img'}->rectangle($x1,$height-6,$x2,$height+20,$self->{'india red'});
$imap .= descFLAG($self,$FLAGdesc,$oc_url,$curX,$height-6,$x2,$height+20);
return ($x1,$height-6,$x2,$height+20,$imap);
}
sub addMarker{
my $self = shift;
my($argHR,@posArray)=@_;
my ($i,$pos,@label);
my $c=(exists($argHR->{color}))?$argHR->{color}:"grey";
my $c_a = (exists($argHR->{arrowColor}))?$argHR->{arrowColor}:$c;
my $c_s = (exists($argHR->{startColor}))?$argHR->{startColor}:$c;
my $c_d = (exists($argHR->{dotColor}))?$argHR->{dotColor}:$c;
my $idHalfLen=($self->{'isLabeled'})?(gdTinyFont->width)*length($argHR->{label})/2:0;
my $initHeight=(exists($argHR->{startHeight}))?$argHR->{startHeight}+$HalfLabelHeight:$StartY;
my $isReversed = ($posArray[0] > $posArray[$#posArray])?1:0;
my $x1 = min(max($self->_pos2x($posArray[0]),0),$self->{imgWidth});
my $x2 = min(max($self->_pos2x($posArray[$#posArray]),0),$self->{imgWidth});
my $mid=($x1+$x2)/2;
&swap(\$x1,\$x2) if $isReversed;
my $height=$self->_getHeight(&min($x1,$mid-$idHalfLen),&max($x2,$mid+$idHalfLen),$initHeight);
$self->{'img'}->line($x1+1,$height,$x2-1,$height,$self->_GV_addColor($c));
if(($self->{'isLabeled'})&&(exists($argHR->{label}))){ #draw ID
$self->{'img'}->string(gdTinyFont,$mid-$idHalfLen,$height+$HalfLabelHeight+5,$argHR->{label},$self->_GV_addColor('black'));
@label = ($mid - $idHalfLen,$height + $HalfLabelHeight + 5 ,$mid + $idHalfLen,$height + $HalfLabelHeight + 15);
}else{
@label = (-1,-1,-1,-1);
}
for($pos=0;$pos<=$#posArray;$pos++){
if($posArray[$pos] < $self->{'zeroPos'}){
$posArray[$pos] = $self->_pos2x($self->{'zeroPos'});
}elsif($posArray[$pos] > $self->{'endPos'}){
$posArray[$pos] = $self->_pos2x($self->{'endPos'});
}else{
$posArray[$pos] = $self->_pos2x($posArray[$pos]);
}
}
return ([@label],[$height-$HalfLabelHeight,$height+$HalfLabelHeight,@posArray]);
}
sub addCDS{
my($self,$startHeight,$cstart,$cend) = @_;
my $x1=$self->_pos2x($cstart);
my $x2=$self->_pos2x($cend);
my $poly=new GD::Polygon;
my $poly2=new GD::Polygon;
if(($cstart >= $self->{begPos})&&($cstart <= $self->{endPos})){
#draw CDS start triangle
$poly->addPt($x1,$startHeight);
$poly->addPt($x1 - 2,$startHeight - 5);
$poly->addPt($x1 + 2,$startHeight - 5);
$self->{'img'}->filledPolygon($poly,$self->{'green'});
}
if(($cend >= $self->{begPos})&&($cend <= $self->{endPos})){
#draw CDS stop triangle
$poly2->addPt($x2,$startHeight);
$poly2->addPt($x2 - 2,$startHeight - 5);
$poly2->addPt($x2 + 2,$startHeight - 5);
$self->{'img'}->filledPolygon($poly2,$self->{'red'});
}
}
sub addGseg{
my $self = shift;
my($argHR,@posArray)=@_;
my(@label);
my $c = (exists($argHR->{color}))?$argHR->{color}:"green";;
my $c_l = (exists($argHR->{leftColor}))?$argHR->{leftColor}:$c;
my $c_r = (exists($argHR->{rightColor}))?$argHR->{rightColor}:$c;
my $idHalfLen=($self->{'isLabeled'})?(gdTinyFont->width)*length($argHR->{label})/2:0;
my $initHeight=(exists($argHR->{startHeight}))?$argHR->{startHeight}+$HalfLabelHeight:$StartY;
my $isReversed = ($posArray[0] > $posArray[$#posArray])?1:0;
@posArray = reverse @posArray if($isReversed);
my $x1=$self->_pos2x(&max($posArray[0],$self->{'zeroPos'}));
my $x2=$self->_pos2x(&min($posArray[$#posArray],$self->{'endPos'}));
my $mid=($x1+$x2)/2;
my $height=$self->_getHeight(&min($x1,$mid-$idHalfLen),&max($x2,$mid+$idHalfLen),$initHeight);
$height += 8; ## Adding room for IDs on top
my $nextPower = 0.001;
my $MinDist = 100;
my $halfStroke = 1;
my $ruler;
my $minDist=$MinDist*$self->{'scale'};
while($nextPower<$minDist){$nextPower*=10;}
if($minDist<$nextPower/5.0){
$ruler=($nextPower+0.5)/5.0;
}elsif($minDist<$nextPower/4.0){
$ruler=($nextPower+0.5)/4.0;
}elsif($minDist<$nextPower/2){
$ruler=($nextPower+0.5)/2.0;
}else{
$ruler=$nextPower+0.5;
}
if($#posArray > 1){
if($posArray[1] > $self->{'zeroPos'}){
$self->{'img'}->rectangle($x1,$height - $halfStroke,$self->_pos2x($posArray[1]),$height + $HalfLabelHeight,$self->_GV_addColor($c_l));
}
if($posArray[2] < $self->{'endPos'}){
$self->{'img'}->rectangle($self->_pos2x($posArray[2]),$height - $halfStroke,$x2,$height + $HalfLabelHeight,$self->_GV_addColor($c_r));
}
$self->{'img'}->filledRectangle($self->_pos2x($posArray[1]),$height - $halfStroke,$self->_pos2x($posArray[2]),$height + $halfStroke,$self->_GV_addColor($c));
}else{
$self->{'img'}->filledRectangle($x1,$height - $halfStroke,$x2,$height + $halfStroke,$self->_GV_addColor($c));
}
{
use integer;
my($show_coords,$tick_len,$x_pos,$pos,$bpos,$i);
$ruler=$ruler/10;
## This hides the coords if the drawing is too small unless overridden by argHR!
$show_coords = (exists($argHR->{showCoords}))?$argHR->{showCoords}:(($posArray[0] + (2 * $ruler)) < $posArray[$#posArray]);
for($pos=&max($posArray[0],$self->{'zeroPos'}),$i=0;
$pos<=&min($posArray[$#posArray],$self->{'endPos'});
$pos+=$ruler,$i++){
$bpos = ($isReversed)?$posArray[$#posArray] - $pos + 1 : $pos - $posArray[0] + 1;
$tick_len=($i%5==0)?$HalfLabelHeight:($HalfLabelHeight / 2);
$x_pos=$self->_pos2x($pos);
if($show_coords && ($i%5==0)&&(($pos + (2* $ruler))<$posArray[$#posArray])){
$self->{'img'}->string(gdTinyFont,
$x_pos-(gdTinyFont->width)*length($bpos)/2,
$height + 5,
$bpos,
$self->_GV_addColor('black'));
}
$self->{'img'}->line($x_pos,$height - $tick_len,$x_pos,$height + $tick_len,$self->_GV_addColor('black'));
}
## Add final tick mark for fully contained structures
if($posArray[$#posArray] < $self->{'endPos'}){
$bpos = ($isReversed)? 1 : $posArray[$#posArray] - $posArray[0];
$x_pos=$self->_pos2x($posArray[$#posArray]); $tick_len=$HalfLabelHeight;
$self->{'img'}->string(gdTinyFont,$x_pos-(gdTinyFont->width)*length($bpos)/2,$height + 5,$bpos,$self->_GV_addColor('black')) if($show_coords);
$self->{'img'}->line($x_pos,$height - $tick_len,$x_pos,$height + $tick_len,$self->_GV_addColor('black'));
}
}
if(($self->{'isLabeled'})&&(exists($argHR->{label}))){
$self->{'img'}->string(gdTinyFont,
$mid - $idHalfLen,$height - 10,
$argHR->{label},$self->_GV_addColor('black'));
@label = ($mid - $idHalfLen,$height - 10,$mid + $idHalfLen,$height);
}else{
@label = (-1,-1,-1,-1);
}
for($pos=0;$pos<=$#posArray;$pos++){
if($posArray[$pos] < $self->{'zeroPos'}){
$posArray[$pos] = $self->_pos2x($self->{'zeroPos'});
}elsif($posArray[$pos] > $self->{'endPos'}){
$posArray[$pos] = $self->_pos2x($self->{'endPos'});
}else{
$posArray[$pos] = $self->_pos2x($posArray[$pos]);
}
}
@posArray = reverse @posArray if($isReversed);
return ([@label],[$height-$HalfLabelHeight,$height+$HalfLabelHeight,@posArray]);
}
sub addGene{
my $self = shift;
my($argHR,@posArray)=@_;
my ($i,$pos,@label);
my $c=(exists($argHR->{color}))?$argHR->{color}:"red";
my $c_a = (exists($argHR->{arrowColor}))?$argHR->{arrowColor}:$c;
my $c_s = (exists($argHR->{startColor}))?$argHR->{startColor}:$c;
my $c_d = (exists($argHR->{dotColor}))?$argHR->{dotColor}:$c;
my $idHalfLen=($self->{'isLabeled'})?(gdTinyFont->width)*length($argHR->{label})/2:0;
my $initHeight=(exists($argHR->{startHeight}))?$argHR->{startHeight}+$HalfLabelHeight:$StartY;
my $isReversed = ($posArray[0] > $posArray[$#posArray])?1:0;
my $x1 = min(max($self->_pos2x($posArray[0]),0),$self->{imgWidth});
my $x2 = min(max($self->_pos2x($posArray[$#posArray]),0),$self->{imgWidth});
my $mid=($x1+$x2)/2;
&swap(\$x1,\$x2) if $isReversed;
my $height=$self->_getHeight(&min($x1,$mid-$idHalfLen),&max($x2,$mid+$idHalfLen),$initHeight);
$self->{'img'}->line($x1+1,$height,$x2-1,$height,$self->_GV_addColor($c));
if($isReversed){
if(($#posArray > 1)||(exists($argHR->{drawArrowhead}))){
if(($#posArray == 1)&&(exists($argHR->{drawArrowhead}))){
$self->_drawArrow($posArray[$#posArray],$posArray[$#posArray-1],$height,$self->_GV_addColor($c),$self->_GV_addColor($c_a),$isReversed);
}else{
$self->_drawStartBar($posArray[1],$posArray[0],$height,$self->_GV_addColor($c),$self->_GV_addColor($c_s),$isReversed);
for($i=2;$i<@posArray-2;$i+=2){
$self->_drawBar($posArray[$i+1],$posArray[$i],$height,$self->_GV_addColor($c));
}
$self->_drawArrow($posArray[$#posArray],$posArray[$#posArray-1],$height,$self->_GV_addColor($c),$self->_GV_addColor($c_a),$isReversed);
}
}else{
$self->_drawStartBar($posArray[1],$posArray[0],$height,$self->_GV_addColor($c),$self->_GV_addColor($c),$isReversed);
$self->_drawSEdot($posArray[1],$posArray[0],$height,$self->_GV_addColor($c_d));
}
}else{
if(($#posArray > 1)||(exists($argHR->{drawArrowhead}))){
if(($#posArray == 1)&&(exists($argHR->{drawArrowhead}))){
$self->_drawArrow($posArray[$#posArray-1],$posArray[$#posArray],$height,$self->_GV_addColor($c),$self->_GV_addColor($c_a),$isReversed);
}else{
$self->_drawStartBar($posArray[0],$posArray[1],$height,$self->_GV_addColor($c),$self->_GV_addColor($c_s),$isReversed);
for($i=2;$i<@posArray-2;$i+=2){
$self->_drawBar($posArray[$i],$posArray[$i+1],$height,$self->_GV_addColor($c));
}
$self->_drawArrow($posArray[$#posArray-1],$posArray[$#posArray],$height,$self->_GV_addColor($c),$self->_GV_addColor($c_a),$isReversed);
}
}else{
$self->_drawStartBar($posArray[0],$posArray[1],$height,$self->_GV_addColor($c),$self->_GV_addColor($c),$isReversed);
$self->_drawSEdot($posArray[0],$posArray[1],$height,$self->_GV_addColor($c_d));
}
}
#draw ID
if(($self->{'isLabeled'})&&(exists($argHR->{label}))){
$self->{'img'}->string(gdTinyFont,$mid-$idHalfLen,$height+$HalfLabelHeight+5,
$argHR->{label},$self->_GV_addColor('black'));
@label = ($mid - $idHalfLen,$height + $HalfLabelHeight + 5 ,$mid + $idHalfLen,$height + $HalfLabelHeight + 15);
}else{
@label = (-1,-1,-1,-1);
}
for($pos=0;$pos<=$#posArray;$pos++){
if($posArray[$pos] < $self->{'zeroPos'}){
$posArray[$pos] = $self->_pos2x($self->{'zeroPos'});
}elsif($posArray[$pos] > $self->{'endPos'}){
$posArray[$pos] = $self->_pos2x($self->{'endPos'});
}else{
$posArray[$pos] = $self->_pos2x($posArray[$pos]);
}
}
return ([@label],[$height-$HalfLabelHeight,$height+$HalfLabelHeight,@posArray]);
}
sub showSplicePattern{
my $self = shift;
my($argHR,@cds)=@_;
my ($a,$x,$c,$diff);
$c=(exists($argHR->{color}))?$argHR->{color}:'red';
if($cds[0] > $cds[$#cds]){
## reverse strand PGS
$a = $cds[0];
$x = $cds[$#cds];
for(my $y=0;$y<=$#cds;$y++){
$cds[$y] = ($a + $x) - $cds[$y];
}
}
$diff=0;
for($x=1;$x<$#cds;$x+=2){
$diff += ($cds[$x+1] - $cds[$x]);
}
$self->_drawArrow($cds[0],($cds[$#cds] - $diff),$StartY,$self->_GV_addColor($c),$self->_GV_addColor($c),0);
$a=0; $diff=0;
for($x=1;$x<$#cds;$x+=2){
$a = $self->_pos2x($cds[$x] - $diff);
$self->{'img'}->filledRectangle($a,$StartY-$LabelHeight,$a+2,$StartY+$LabelHeight,$self->_GV_addColor('green'));
$diff += ($cds[$x+1] - $cds[$x]);
}
}
sub swap{
my($x,$y)=@_;
if($$x>$$y){
my $temp=$$x;
$$x=$$y;
$$y=$temp;
}
}
sub min{return ($_[0] < $_[1])?$_[0]:$_[1];}
sub max{return ($_[0] > $_[1])?$_[0]:$_[1];}
sub DESTROY {
my $self=shift;
$self->_clear();
}
##################### End of Package #########################
1;
See more files for this project here