#!/usr/local/bin/perl
###############################################################################
#
#   Name:           contigview
#
#   Description:    mod_perl script to display a virtual contig showing genes,
#                   and a zoomed in virtual contig showing the detailed
#                   features of a region of the first vc.
#
#   History:        *cough*     as2/avc -   original versions
#                   2000-11-02  jws -   changes to work with static_golden_path
#                                       virtual contigs, and also clean up the
#                                       script interface a little.
#                   
#                   2000-11-10  jws     Added SSAHA feature handling.
#                   2000-11-17  jws     Modified SSAHA handling for generic
#                                       "feature" handling.
#		    2001-01-04  avc	Added markers to top vc
#		    2001-01-10	jws	ssaha now works slightly differently...
#		    2001-03-08	jws	Add checks for external feature factory
#					connections to ensure ctgview still 
#					works when they are not available
#		    2001-03-29	jws	Major changes.  Integrated in rmp and 
#					avc new drawing code.
#
###############################################################################

package contigview;

use strict;
use ExtIndex;
use ExtURL;
use Apache;
use EnsWeb;
use SiteDefs;
use CGI qw(:standard :html3 :cookie);
use Bio::EnsEMBL::DrawableContainer;
use Bio::EnsEMBL::DBSQL::ExternalWrapper;
use Bio::EnsEMBL::Map::DBSQL::Map;
use Bio::EnsEMBL::ExternalData::SNPSQL::WebSNPAdaptor;
use Bio::EnsEMBL::ExternalData::TCORESQL::DBAdaptor;
use Bio::EnsEMBL::ExternalData::EXONERATESQL::DBAdaptor;
use Bio::EnsEMBL::ExternalData::GMAPAdaptor;
use WebUserConfig;
use Time::Local;
use Digest::MD5;
use GD;
use Bio::EnsEMBL::Utils::Eprof qw(eprof_start eprof_end eprof_dump);
use GramenePage;
$|=1;

###############################################################################
&eprof_start('contigview');

my $cgi		= new CGI;
my $Config      = new WebUserConfig($cgi, 'contigviewbottom');
my $Config_top  = new WebUserConfig($cgi, 'contigviewtop');
my $r           = Apache->request();
my $cookie 	= undef;
my $img_type;
if (GD::Image->can("gif")){
    $img_type = "gif";
}
else {
    $img_type = "png";
}

#################
# CGI parameters
#################

my $someparam	    = $cgi->param ;

my $geneid          = SiteDefs::idfix($cgi->param('geneid'));    # Gene ID passed from geneview.
my $contigid        = $cgi->param('contig');    # Contig ID passed from <FORM>
my $cloneid         = $cgi->param('clone');     # Clone ID passed from <FORM>.
my $fpc_contigid    = $cgi->param('fpc');	# ID for an FPC contig.
my $chr             = $cgi->param('chr');       # Chromosome name.

my @highlights      = $cgi->param('highlight');	# ();                       # list of IDs for DrawableContainer to highlight
push @highlights, $geneid   if(defined $geneid);
#push @highlights, $contigid if(defined $contigid);
#push @highlights, $cloneid  if(defined $cloneid);

my $imgmap	    	= $cgi->param('imgmap');	# Turn on/off img mapping

#print STDERR " Current imgmap = >>$imgmap<<\n";
#print STDERR " Current cookie = >>",$Config->get('contigviewbottom','_settings','imagemap'),"<<\n";
#print STDERR map { "$_\n"; } sort values %INC;

if ($imgmap eq "1" || $imgmap eq "0"){
	#print STDERR "Setting IMAP cookie param to $imgmap\n";
	$Config->set('contigviewbottom','_settings','imagemap', $imgmap);
	$cookie = $Config->save();
	#print STDERR "Set IMAP cookie param to ",$Config->get('contigviewbottom','_settings','imagemap'),"\n";
} else {
	#print STDERR "Using existing IMAP cookie setting: ", $Config->get('contigviewbottom','_settings','imagemap'), "\n";
}

my $vc_start        = $cgi->param('vc_start');  # Start-point (abs bp) for the
                                                # top virtual contig.
my $vc_end          = $cgi->param('vc_end');    # End-point (abs bp) for the
                                                # top virtual contig.
my $wvc_start       = $cgi->param('wvc_start'); # Start-point (abs bp) for the
                                                # windowed vc (feature vc).
my $wvc_end         = $cgi->param('wvc_end');   # End-point (abs bp) for the
                                                # windowed vc.

if ($wvc_start>$wvc_end){                       # Make sure they are the right
    ($wvc_start,$wvc_end)=($wvc_end,$wvc_start);# way around...
}

if ($vc_start>$vc_end){							# Make sure they are the right
    ($vc_start,$vc_end)=($vc_end,$vc_start);	# way around...
}

my $vc_click = $cgi->param('click_to_move_window.x'); # The click point in pix
                                                # along the featureview line 
                                                # where the windowed vc should
                                                # be positioned.
my $vc_pix_len	    = $cgi->param('vc_pix');	# top vc length in pixels
my $vc_left_margin  = $cgi->param('vc_left');	# top vc left margin in pixels

####################################################################
# Extra feature positions - for centering on ssaha, blast hits, etc
####################################################################
my $fpos_start      = $cgi->param('fpos_start');# Relative bp start from fpos
                                                # fpc contig.
my $fpos_end        = $cgi->param('fpos_end');  # Relative bp end from fpos
                                                # fpc contig.
my $fpos_context    = $cgi->param('fpos_context');  # Number of bp either side 
                                                    # of the fpos start and
						    # end to include in the wvc

#print STDERR "cv($contigid,$fpos_start,$fpos_end,$fpos_context)\n";

my $TMP = "${ENSEMBL_SERVERROOT}/htdocs/gfx/image_tmp";

#####################
# Print HTML header
#####################
$r->err_header_out('ensembl_headers_out'=>1);

if (defined $cookie){
    print $cgi->header('-cookie' => $cookie);
} else {
	print $cgi->header();
}

my ($head,$onload,$js_divs)=&EnsWeb::cgi_header_info(('initfocus'=>1,'menus'=>1));
my $grpg=GramenePage->new($r);
print $head,$grpg->start_body(  -ensembl=>1, -bodyattr=>$onload, -bodyfirst=>$js_divs  );
print "<br><br><center>\n";
print EnsWeb::print_form( $cloneid, "vcontig" );

my $vc = undef;	    # Main window (bottom) Virtual Contig
my $top_vc = undef; # Context window (top) Virtual Contig
my $sa = undef;	    # StaticGoldenPathAdaptor
my $dc = undef;	    # Drawable Container
my $db = undef;	    # Ensembl Database


######################################
# Get a hold of the database handles
######################################
eval {
    my $locator = &EnsWeb::get_locator();
    $db =  Bio::EnsEMBL::DBLoader->new($locator);

    $db or print STDERR "cannot open $locator\n"
     and die "cannot open $locator\n";

print STDERR "opened $locator\n";

    if ($ENSEMBL_EMBL){
	my $emblext= Bio::EnsEMBL::DBSQL::DBAdaptor->new(       
			    -driver => $ENSEMBL_DRIVER,
			    -user   => $ENSEMBL_DBUSER,
			    -pass   => $ENSEMBL_DBPASS,
			    -dbname => $ENSEMBL_EMBL,
			    -host   => $ENSEMBL_HOST,
			    -port   => $ENSEMBL_HOST_PORT,
			    ); 
                        
	my $embldb= new Bio::EnsEMBL::DBSQL::ExternalWrapper($emblext);
	$db->add_ExternalFeatureFactory($embldb);
    }

    if ($ENSEMBL_GMAP){
	my $gmapdb= Bio::EnsEMBL::ExternalData::GMAPAdaptor->new(       
			    -driver => $ENSEMBL_DRIVER,
			    -user   => $ENSEMBL_DBUSER,
			    -pass   => $ENSEMBL_DBPASS,
			    -dbname => $ENSEMBL_GMAP,
			    -host   => $ENSEMBL_HOST,
			    -port   => $ENSEMBL_HOST_PORT,
			    ); 
 print STDERR "opened GMAP\n";                       
	$db->add_ExternalFeatureFactory($gmapdb);
 print STDERR "added GMAP EFF\n";                       
    }

    if ($ENSEMBL_SNP){
    my $snpdb = Bio::EnsEMBL::ExternalData::SNPSQL::WebSNPAdaptor->new(   
			     -dbname => $ENSEMBL_SNP,
			     -user   => $ENSEMBL_DBUSER,
			     -pass   => $ENSEMBL_DBPASS,
			     -host   => $ENSEMBL_HOST,
			     -port   => $ENSEMBL_HOST_PORT,
			     );

    $db->add_ExternalFeatureFactory($snpdb);
    }

    if ($ENSEMBL_MOUSE){
	my $mouse = Bio::EnsEMBL::ExternalData::EXONERATESQL::DBAdaptor->new( 
			    -user   => $ENSEMBL_DBUSER,
			    -pass   => $ENSEMBL_DBPASS,
			    -dbname => $ENSEMBL_MOUSE,
			    -host   => $ENSEMBL_HOST,
			    -port   => $ENSEMBL_HOST_PORT,
			    ); 

	my $mouse_ext_feature_factory = $mouse->get_ExonerateAdaptor();
	$db->add_ExternalFeatureFactory($mouse_ext_feature_factory);
    }

    #$db->static_golden_path_type('CUGI');
    $db->static_golden_path_type($ENSEMBL_GOLD);
    $sa = $db->get_StaticGoldenPathAdaptor();
};

if ($@){
    print &ensembl_exception("The Ensembl database is not available. Please contact the webmaster\n",$@);
    print &EnsWeb::make_cgi_footer();
    &Apache::exit();
}

if (!$sa){
    print &ensembl_exception("Assembly table is not available. Please contact the webmaster\n",$@);
    print STDERR "Static Golden Path of type $ENSEMBL_GOLD is not available. Please contact the webmaster\n",$@;
    print &EnsWeb::make_cgi_footer();
    &Apache::exit();
}

########################
# Clean-up entry params
########################
if ($chr){      
    $chr=~s/\s//g;              # Fix up the chromosome if
    unless($chr=~/^chr/){       # necessary - ensembl calls
    #$chr="chr".$chr;            # take "chrn", but we need to
    }				# be able to pass in just "n"
}


###############################################################################
# OLD NAVIGATION COMPATABILITY
#
#   Used to come in by vc_start/end and also wvc_start/end, where vc referred
#   to the top vc and wvc to the bottom.  We are now navigating solely by the
#   bottom VC, so we need to change old nav into new nav.
###############################################################################
if (defined $wvc_start && defined $wvc_end){
    ($vc_start, $vc_end) = ($wvc_start, $wvc_end);
}

###############################################################################
# SET-UP FOR VIRTUAL CONTIG
#
# We can come into contigview by reposition click, clone, contig, contig & 
#   featureposition or by # chr, start, and end.  Also by geneid.
#
# The precedence order is:
#   vc_click
#   chr, start, end
#   fpos_start, fpos_end, contig
#   Geneid
#   Contig
#   Clone.
#
#   NB fpos_start and fpos_end are offsets from a RAW contig start/end
#
###############################################################################

##############################################################################
# Find out how we've been initialised, and build the vc.  At the end of this
# conditional block we will have a virtual contig ($vc) and will have defined
# $vc_size, $chr, $vc_start, and $vc_end
##############################################################################
my $vc_size;
my $default_vc_size	= $Config->get('contigviewtop','_settings','default_vc_size');
my $default_top_vc_size	= $Config->get('contigviewtop','_settings','default_top_vc_size');

if (defined $vc_click && defined $vc_left_margin && defined $vc_pix_len){
    ##############################
    # Going in by click on top vc
    ##############################
    my ($old_top_start, $old_top_end) = get_top_vc_coords_from_vc($vc_start, $vc_end,$default_top_vc_size);
    $vc_click = $vc_click - $vc_left_margin;
    $vc_click = 0 if $vc_click < 0; 
    $vc_click = $vc_pix_len if $vc_click > $vc_pix_len;
    my $old_top_len = $old_top_end - $old_top_start;

    my $bp_click = int(($old_top_len/$vc_pix_len) * $vc_click) + $old_top_start;
    
    $vc_size = $vc_end - $vc_start;
    if ($vc_size > $default_top_vc_size){
	$vc_size = $default_vc_size;
    }
    $vc_start = $bp_click - int($vc_size/2);
    $vc_start = 1 if $vc_start < 0;
    $vc_end = $vc_start + $vc_size;
    
    eval {  
	$vc = $sa->fetch_VirtualContig_by_chr_start_end($chr, 
							$vc_start, 
							$vc_end
							);
    };
    if ($@){
	print &ensembl_exception("Cannot create virtual contig from chromosome $chr, start $vc_start, end $vc_end",$@);
	&EnsWeb::ensembl_exit();
    }
}
elsif (defined $chr && defined $vc_start && defined $vc_end){
    ##############################
    # Going in by Chr, Start, End
    ##############################
    $vc_start=1 if($vc_start<1);
    $vc_size=$vc_end-$vc_start;
    if ($vc_size <= 10){$vc_end = $vc_start + 10};

    eval {  
	$vc = $sa->fetch_VirtualContig_by_chr_start_end($chr, 
							$vc_start, 
							$vc_end
							);
    };
    if ($@){
	print &ensembl_exception("Cannot create virtual contig from chromosome $chr, start $vc_start, end $vc_end",$@);
	&EnsWeb::ensembl_exit();
    }
}
elsif (defined $fpos_start && defined $fpos_end && defined $contigid){
    ############################
    # Going in by FPOS & Contig
    ############################
    my $temp_vc;
    eval {
	$temp_vc = $sa->fetch_VirtualContig_of_contig($contigid);
    };
    if ($@){
	print &ensembl_exception("Cannot create virtual contig by contig $contigid",$@);
	&ensembl_exit();
    }

    $chr = $temp_vc->_chr_name();
    
    ######################################################################
    # Have to adjust for fpos_start/end being raw offsets, not golden ones
    # i.e. need to subtract the difference between the rawcontig start
    # and the virtual contig start
    ######################################################################
    
    my( $mapcontig,$raw_start,$ori) = $temp_vc->raw_contig_position(1,1);
    if ($ori == 1){
	$fpos_start = $temp_vc->_global_start + $fpos_start - $raw_start;
	$fpos_end   = $temp_vc->_global_start + $fpos_end - $raw_start;
    }
    else {
	my $fpos_start2 = $temp_vc->_global_start + $raw_start - $fpos_end;
	my $fpos_end2   = $temp_vc->_global_start + $raw_start - $fpos_start;
	$fpos_start = $fpos_start2;
	$fpos_end = $fpos_end2;
    }
	    
    ##########################################################################
    # Want to focus this whole thing on the fpos region
    ##########################################################################
    
    ###########################################
    # Alter fpos start and end to incorporate
    # any context basepairs on either side.
    # If the context is larger than the fpos
    # length, then just return the context, but
    # if fpos > context, return fpos length.
    ###########################################
    
    my $fpos_length=$fpos_end-$fpos_start;
    my $fpos_centre = int($fpos_length/2) + $fpos_start;

    if ($fpos_length<($fpos_context*2)){
        $fpos_start	= $fpos_centre - $fpos_context; 
        $fpos_end	= $fpos_centre + $fpos_context - 1;
	$fpos_length    = $fpos_end-$fpos_start;
    }
    
    ############
    # Set-up VC
    ############
    $vc_size    = $fpos_length;
    $vc_start   = $fpos_start;
    $vc_end     = $fpos_end;
    
    ###########
    # Build VC
    ###########
    eval {  
        $vc = $sa->fetch_VirtualContig_by_chr_start_end($chr, 
                                                        $vc_start, 
                                                        $vc_end
                                                        );
    };
    if ($@){
        print &ensembl_exception("Cannot create feature-based virtual contig",$@);
	&EnsWeb::ensembl_exit();
    }
}
elsif (defined $geneid) {
    #####################
    # Going in by Gene
    #####################
    $vc_size=$default_vc_size;

    unless ($geneid=~/${ENSEMBL_PREFIXG}\d+$/){ # /${ENSEMBL_PREFIX}G\d{11}/
        my @genes=$db->gene_Obj->get_Gene_by_DBLink($geneid);
        unless($genes[0]){
            print &ensembl_exception( "Cannot find Ensembl entry for gene $geneid","No gene from \$db->gene_Obj->get_Gene_by_DBLink(\$geneid)",1);
	    &EnsWeb::ensembl_exit();
        }
        $geneid=$genes[0]->id;
    }
    eval {
        $vc = $sa->fetch_VirtualContig_by_gene($geneid, $vc_size);
    };
    if ($@){
	print &ensembl_exception("Cannot create virtual contig by this gene",$@);
	&ensembl_exit();
    }
    $chr	= $vc->_chr_name;
    $vc_start	= $vc->_global_start;
    $vc_end	= $vc->_global_end;
}
elsif (defined $contigid) {
    #####################
    # Going in by Contig
    #####################
    $vc_size=$default_vc_size;
       
    print STDERR "contig $contigid, $vc_size\n";
    eval {
            $vc = $sa->fetch_VirtualContig_by_contig($contigid, $vc_size);
        };
    if ($@){
        print &ensembl_exception("Cannot create virtual contig by contig $contigid",$@);
        &ensembl_exit();
    }
    $chr	= $vc->_chr_name;
    $vc_start	= $vc->_global_start;
    $vc_end	= $vc->_global_end;
}
elsif (defined $cloneid){
    ####################
    # Going in by Clone
    ####################
    $vc_size    = $default_vc_size;

    eval {
        $vc = $sa->fetch_VirtualContig_by_clone($cloneid, $vc_size);
    };
    if ($@){
		print &ensembl_exception("Sorry, the sequence viewer can only display phase 2 or higher clones where the fragments have been ordered.  $cloneid is a phase 1 clone.",$@,1);

		
		#Sorry, Cannot display clone $cloneid. Its pieces are not ordered
		&ensembl_exit();
    }
print STDERR "Got vc for $cloneid of $vc_size\n";
    $chr        = $vc->_chr_name;
    $vc_start   = $vc->_global_start;
    $vc_end     = $vc->_global_end;
}
else {
    #$db->stats();
    #######################################################################
    # Presumably either no params have been passed, or the chr, start, end
    # params are incomplete, or some other catastrophe has arisen.
    # Whatever, we are going no further, so let's hit it and quit.
    #######################################################################
    if($someparam) {
    print &ensembl_exception("Not enough information has been provided to build a virtual contig","",1);
	&ensembl_exit();
    } else {
	print "No clone or contig specified.";
	print "</center>";
	print $grpg->end_body;
	&eprof_end('contigview');
	return 1;
    }
}

#############################################################################
# DECISION POINT
#   If the vc is above the default_top_vc_size then we don't want to show
#   the detailed vc.  Instead, we let the top_vc take over, and show the
#   amount requested.  Rather than the buttons and detailed vc we will
#   instead show some sort of "no detail at this zoom level" type thing.
#############################################################################
my ($top_vc_start, $top_vc_end);
if ($vc_size > $default_top_vc_size){
    $top_vc = $vc;
    $top_vc_start= $top_vc->_global_start;
    $top_vc_end  = $top_vc->_global_end;
    $vc = undef;
}
else {
    ($top_vc_start, $top_vc_end) = get_top_vc_coords_from_vc($vc_start, $vc_end, $default_top_vc_size);

    eval {  
	$top_vc = $sa->fetch_VirtualContig_by_chr_start_end($chr, 
							    $top_vc_start, 
							    $top_vc_end
							    );
    };

    if ($@){
	print &ensembl_exception("Cannot create virtual contig from chromosome $chr, start $top_vc_start, end $top_vc_end",$@);
	&EnsWeb::ensembl_exit();
    }
}


$Config_top->container_width($top_vc->length());
$Config_top->{'_wvc_start'} = $vc_start;
$Config_top->{'_wvc_end'}   = $vc_end;
my $top_dc = Bio::EnsEMBL::DrawableContainer->new("contigviewtop", $top_vc, $Config_top, \@highlights);

############################
# Generate image for top_vc
############################
my $image    = undef;
my $imagemap = undef;

if(defined $top_dc) {
    $image = $top_dc->render($img_type);
}

my $top_filename = &Digest::MD5::md5_hex(rand());
$top_filename .= "top.$img_type";

open(IMG_OUT, qq(>$TMP/$top_filename)) || die qq(cannot open temporary image file $TMP/$top_filename: $!\n);

binmode IMG_OUT;
print IMG_OUT $image;
close(IMG_OUT);

print qq(<br>);		#<center> was above already
print qq(<span class="h3">Genome View BAC/PAC&nbsp;)
      ,join(", ",map { $_->name } $top_vc->get_all_clones)
      ,qq(&nbsp;</span>\n);

#############################################################################
# Generate information about the image that we can pass with the click data
# to allow the click point to be recalculated on the receiving page
#############################################################################
my $top_leftmargin = $top_dc->config->transform->{'translatex'};
my $top_contig_pix_bp = $top_dc->config->transform->{'scalex'};
my $top_contig_pix = int($top_contig_pix_bp * ($top_vc_end-$top_vc_start)); 

print <<EOF;
    <form action="$ENV{'SCRIPT_NAME'}" method="GET">
    <INPUT TYPE="hidden" NAME="chr" VALUE="$chr">
    <INPUT TYPE="hidden" NAME="vc_start" VALUE="$vc_start">
    <INPUT TYPE="hidden" NAME="vc_end" VALUE="$vc_end">
    <INPUT TYPE="hidden" NAME="vc_pix" VALUE="$top_contig_pix">
    <INPUT TYPE="hidden" NAME="vc_left" VALUE="$top_leftmargin">
    <table cellspacing="0" cellpadding="0" border="0">
        <tr>
	    <td align="left" valign="top"><span class="h4">&nbsp;&nbsp;Overview</span> </td>
     <td>
	     <td ><a target="config" href="/perl/config?script=contigviewtop">
     <img src="/gfx/buttons/changefeatures.png" border="0" alt="Change overview features" hspace="2" vspace="2">
	     </a>
	    </td>
	    <td>&nbsp;</td>
        </tr>
	<tr>
	    <td colspan=3><INPUT TYPE="IMAGE" NAME="click_to_move_window" SRC="/gfx/image_tmp/$top_filename" BORDER="0"  ALT="Click to center detailed display at this point"></td>
	</tr>
    </table>
EOF
     #<img src="/gfx/buttons/config.gif" width="70" height="25" border="0" alt="Customise this overview" hspace="2" vspace="2">
	     #this broke netscape:
	     #<p class="redbutton">
	     #Change Features
	     #</p>


###############################################################################
#   Draw navigation icons and bottom vc if appropriate
###############################################################################

if (defined $vc){

    #####################################
    # Print navigation and zoomer images
    #####################################
    my %zoomgifs = (
		    zoom1	=>  50,
		    zoom2	=>  5000,
		    zoom3	=>  10000,
		    zoom4	=>  50000,
		    zoom5	=>  100000,
		    zoom6	=>  200000,
		    zoom7	=>  500000,
		    zoom8	=>  1000000,
		   );

    my $dump_url = qq(javascript:void(window.open('/perl/dumpcfgview?type=region&chr=${chr}&start=${vc_start}&end=${vc_end}','dumpview','width=540,height=500,resizable,scrollbars')););
								#width="700"
    print qq(
	<table align="center" cellpadding="0" cellspacing="0" border="0" >
	    <tr>
		<td><img src="/gfx/blank.gif" height="8" width="1" border="0" alt=""></td>
	    </tr>
	    <tr>
	    <td colspan="12" align="left"><span class="h4">&nbsp;&nbsp;Detailed View</span></td>
	    </tr>
	    <tr>
		<td><img src="/gfx/blank.gif" height="3" width="1" border="0" alt=""></td>
	    </tr>
	    <tr>
	     <td align="right"><a href="$dump_url"><img src="/gfx/buttons/dump.gif" border="0" width="70" height="25" hspace="2" vspace="2" alt="View a text dump of this region"></a></td>
	    <td><img src="/gfx/blank.gif" height="30" width="25" border="0" alt=""></td>
);

    my $pan_left_5_meg  = url_to_pan_vc($chr, $vc_start, $vc_end, 5000000);
    my $pan_left_2_meg  = url_to_pan_vc($chr, $vc_start, $vc_end, 2000000);
    my $pan_left_1_meg  = url_to_pan_vc($chr, $vc_start, $vc_end, 1000000);
    my $pan_left_1_win  = url_to_pan_vc($chr, $vc_start, $vc_end, int(($vc_end - $vc_start)*0.8));
    my $pan_right_1_win  = url_to_pan_vc($chr, $vc_start, $vc_end, int(($vc_end - $vc_start)*-0.8));
    my $pan_right_1_meg = url_to_pan_vc($chr, $vc_start, $vc_end, -1000000);
    my $pan_right_2_meg = url_to_pan_vc($chr, $vc_start, $vc_end, -2000000);
    my $pan_right_5_meg = url_to_pan_vc($chr, $vc_start, $vc_end, -5000000);

    #print qq(<td><a href="$pan_left_2_meg"><img src = "/gfx/buttons/nav_left_2.gif" border="0" width="70" height="25" alt="Left 2 Mb"></td>); 
    #print qq(<td><a href="$pan_left_1_meg"><img src = "/gfx/buttons/nav_left_1.gif" border="0" width="70" height="25" alt="Left 1 Mb"></td>); 
    print qq(<td><a href="$pan_left_1_win"><img src = "/gfx/buttons/win_left.gif" border="0" width="70" height="25" alt="Left one window"></a></td>); 
    print qq(<td><img src="/gfx/blank.gif" height="30" width="25" border="0" alt=""></td>);
    print qq(<td nowrap>);
    my $selected;
    for my $zoom (sort keys %zoomgifs){
	my $zoombp = $zoomgifs{$zoom};
	if ($vc_size <= $zoombp && !$selected){
	    $zoom .= "on";
	    $selected = "1";
	}
	
	my $zoomurl = url_to_zoom_vc($chr, $vc_start, $vc_end, $zoombp);
	
	my $unit_str = bp_to_nearest_unit ($zoombp);
	print qq(<a href="$zoomurl"><img src="/gfx/buttons/${zoom}.gif" width="13" height="30" alt="show $unit_str in detail" border="0"></a>);
    }
    print qq(</td>\n);
    print qq(<td><img src="/gfx/blank.gif" height="30" width="25" border="0" alt=""></td>);
    print qq(<td><a href="$pan_right_1_win"><img src="/gfx/buttons/win_right.gif"   border="0" width="70" height="25" alt="Right one window"></a></td>\n); 
    #print qq(<td><a href="$pan_right_1_meg"><img src="/gfx/buttons/nav_right_1.gif" border="0" width="70" height="25" alt="Right 1 Mb"></a></td>); 
    #print qq(<td><a href="$pan_right_2_meg"><img src="/gfx/buttons/nav_right_2.gif" border="0" width="70" height="25" alt="Right 2 Mb"></a></td>); 

    print qq(
	    <td><img src="/gfx/blank.gif" height="30" width="25" border="0" alt=""></td>
	     <td align="left"><a name="cvconfig" target="config" href="/perl/config?script=contigviewbottom">
     <img src="/gfx/buttons/changefeatures.png" border="0" alt="Change detailed view features" hspace="2" vspace="2">
	     </a></td>
	    </tr>
	    <tr>
		<td><img src="/gfx/blank.gif" height="8" width="1" border="0" alt=""></td>
	    </tr>
	</table>
);
	     #<img src="/gfx/buttons/config.gif" width="70" height="25" border="0" alt="Customise this view" hspace="2" vspace="2">

    #################################
    # Generate image/imagemap for vc
    #################################
    $Config->container_width($vc->length());
    $Config->{'image_frame_colour'} = 'red';

    #$vc->_use_cext_get(1);
    $dc = Bio::EnsEMBL::DrawableContainer->new("contigviewbottom", $vc, $Config, \@highlights);

    $image    = undef;
    $imagemap = undef;

    $image = $dc->render($img_type); # always call the image first!

    if($Config->get('contigviewbottom','_settings','imagemap') == 1) {
	$imagemap = $dc->render("imagemap");
    }

    my $vc_filename = &Digest::MD5::md5_hex(rand());
    $vc_filename .= ".$img_type";

    open(IMG_OUT, qq(>$TMP/$vc_filename)) || die qq(cannot open temporary image file $TMP/$vc_filename: $!\n);

    binmode IMG_OUT;
    print IMG_OUT $image;
    close(IMG_OUT);
    #############################
    # Print vc at bottom of page
    #############################
print <<EOT;
    <center><img border="0" src="/gfx/image_tmp/$vc_filename" usemap="#ctgbottom"></center>
    <br />
    <map name="ctgbottom">\n$imagemap</map>
EOT

}
else {	    
    #########################################################
    # vc not defined, therefore we are just doing the top vc
    #########################################################

    #####################
    # Scroll nav buttons
    #####################
    my $pan_left_1_win  = url_to_pan_vc($chr, $vc_start, $vc_end, int(($vc_end - $vc_start)*0.8));
    my $pan_right_1_win  = url_to_pan_vc($chr, $vc_start, $vc_end, int(($vc_end - $vc_start)*-0.8));

    print <<EOT;
	<table align="center" cellpadding="0" cellspacing="0" border="0">
	    <tr>
		<td><img src="/gfx/blank.gif" height="40" width="53" border="0" alt=""></td>
		<td><a href="$pan_left_1_win"><img  src="/gfx/buttons/scroll_left.gif"  border="0" width="70" height="25" alt="Scroll Left"></td> 
		<td><a href="$pan_right_1_win"><img src="/gfx/buttons/scroll_right.gif" border="0" width="70" height="25" alt="Scroll Right"></td> 
		<td><img src="/gfx/blank.gif" height="40" width="53" border="0" alt=""></td>
		 <td align="left"><a name="cvconfig" target="config" href="/perl/config?script=contigviewbottom">
     <img src="/gfx/buttons/changefeatures.png" border="0" alt="Change detailed view features" hspace="2" vspace="2">
		 </a></td>
	    </tr>
	</table>
EOT
		 #<img src="/gfx/buttons/config.gif" width="70" height="25" border="0" alt="Customise this view" hspace="2" vspace="2">

    my $top_vc_size = $top_vc_end - $top_vc_start;

    print qq(<br><p>Detailed view is not available for the current );
    print bp_to_nearest_unit($top_vc_size,1)." view.</p><p>";
    print qq(Click anywhere on the overview above to zoom back in to a detailed view.</p><br>\n);
}


#if(defined $vc) {
#    my $ucsc_url = qq(http://genome.cse.ucsc.edu/cgi-bin/hgTracks?position=${chr}%3A${vc_start}-${vc_end}&Submit=Submit&db=hg6);
#	my $trace_url = qq(/perl/dumpview?type=trace&chr=${chr}&start=${vc_start}&end=${vc_end});
#
#}

##################################
#   Print dial-in navigation box
##################################
my $formstring = '';

if ($Config->get('contigviewbottom','_settings','imagemap') == 1){
    $formstring = qq(On <input type="radio" name="imgmap" value="1" checked>&nbsp;&nbsp;)
		. qq(Off <input type="radio" name="imgmap" value="0">);	
} 
else {
    $formstring = qq(On <input type="radio" name="imgmap" value="1">&nbsp;&nbsp;)
		. qq(Off <input type="radio" name="imgmap" value="0" checked>);
}

#$chr=~/chr(.*)/;

print <<EOHEAD;
</form>
<form action="$ENV{'SCRIPT_NAME'}" method="GET">
    <table align="center" cellspacing="0" cellpadding="0" class="yellow1" border="0">
    <tr>
        <td rowspan="3" class="black"><img src="/gfx/blank.gif" width="1" height="1" alt=""></td>
        <td colspan="4" class="black"><img src="/gfx/blank.gif" width="698" height="1" alt=""></td>
        <td rowspan="3" class="black"><img src="/gfx/blank.gif" width="1" height="1" alt=""></td>
    </tr>
    <tr valign="middle">
        <td>&nbsp;&nbsp;Chr: <input name="chr" value="$chr" size="3" ></td>
        <td>&nbsp;&nbsp;Nucleotides: <input name="vc_start" value="$vc_start" size="10" maxlength="11">&nbsp;&nbsp;to&nbsp;&nbsp;<input name="vc_end" value="$vc_end" size="10" maxlength="11"></td>
        <td align="center"><small>Turn menus</small> &nbsp;$formstring</td>
        <td><INPUT TYPE="image" src="/gfx/buttons/refresh.gif" border="0" width="70" height="25" hspace="2" vspace="2" alt="refresh"></td> 
    </tr>
    <tr>
        <td colspan="4" class="black"><img src="/gfx/blank.gif" width="200" height="1" alt=""></td>
    </tr>
    </table>
    </form>
EOHEAD
        ##<td><BUTTON name="submit" value="submit" type="submit"><IMG src="/gfx/buttons/refresh.gif" border="0" width="70" height="25" hspace="2" vspace="2" alt="refresh"></BUTTON></td> #doesn't work on Netscape 4.7
        ##<td><INPUT TYPE="image" src="/gfx/buttons/refresh.gif" border="0" width="70" height="25" hspace="2" vspace="2"></td> #extra tags#extra tags seem to do something for Netscape
print clone_info($top_vc);
#print qq([<A target="new" href="http://www.ensembl.org/perl/contigview?chr=$chr&vc_start=$vc_start&vc_end=$vc_end&wvc_start=$vc_start&wvc_end=$vc_end">View this on public site</A>]<BR><BR>);

print "</center>";
print $grpg->end_body;

&eprof_end('contigview');
#
#&eprof_dump(\*STDERR);

#$db->stats();

1;

###############################################################################
################################## EXEUNT #####################################
###############################################################################

###############################################################################
# get_top_vc_coords_from_vc
#   Takes vc_start and vc_end and returns top_vc_start and top_vc_end
#   If the vc is less than the default top vc, then build to the default length
#   but if not, build to the vc_length
###############################################################################
sub get_top_vc_coords_from_vc {
    my ($vc_start, $vc_end, $default_top_vc_size) = @_;
    
    if (($vc_end - $vc_start) > $default_top_vc_size){
	return ($vc_start, $vc_end);
    }

    my $top_vc_length = $default_top_vc_size;

    my $vc_centre = int(($vc_start+$vc_end)/2);
    my $top_vc_start = $vc_centre - int($top_vc_length/2);
    $top_vc_start=1 if($top_vc_start<1);
    my $top_vc_end = $top_vc_start + $top_vc_length;
    
    return ($top_vc_start, $top_vc_end);
}


###############################################################################
# bp_to_nearest_unit
#   Takes a number in basepairs and returns a formatted string rounding the 
#   number to the nearest useful unit.
###############################################################################
sub bp_to_nearest_unit {
    my $bp = shift;
    my @units = qw( bp Kb Mb Gb Tb );
    
    my $power_ranger = int( ( length( abs($bp) ) - 1 ) / 3 );
    my $unit = $units[$power_ranger];
    my $unit_str;

    my $value = int( $bp / ( 10 ** ( $power_ranger * 3 ) ) );
      
    if ( length( $value ) <= 2 && $unit ne "bp" ){
	$unit_str = sprintf( "%.1f%s", $bp / ( 10 ** ( $power_ranger * 3 ) ), " $unit" );
    }else{
	$unit_str = "$value $unit";
    }

    return $unit_str;
}


###############################################################################
# url_to_pan_vc
#   Takes chr, vc_start, vc_end, and a distance in bp(+/-) to pan the vc by.
#   Returns url to generate the required movement.
###############################################################################
sub url_to_pan_vc {
    my ($chr, $vc_start, $vc_end, $pan) = @_; 
    my $vc_length = $vc_end - $vc_start;
    my $new_vc_start = $vc_start - $pan;
    my $new_vc_end = $new_vc_start + $vc_length;
    
    my $url = "/perl/contigview?chr=$chr";
    $url .= "&vc_start=${new_vc_start}&vc_end=${new_vc_end}";

    return $url;
}

###############################################################################
# url_to_zoom_vc
#   Takes chr, vc_start, vc_end, and a length in bp to zoom the vc to.
#   Returns url to generate the required zoom.
###############################################################################
sub url_to_zoom_vc {
    my ($chr, $vc_start, $vc_end, $zoombp) = @_; 
    my $vc_length = $vc_end - $vc_start;
    my $new_vc_start = int($vc_start + ($vc_length/2) - ($zoombp/2));
    my $new_vc_end = $new_vc_start + $zoombp;

    my $url = "/perl/contigview?chr=$chr";
    $url .= "&vc_start=${new_vc_start}&vc_end=${new_vc_end}";

    return $url;
}

sub clone_info {
my($vc)=@_;
#	$oldclone = $old_db->get_Clone($self->cloneid);
#   $acc = $self->cloneid();
#would like  Bio::EnsEMBL::Virtual::StaticContig::clones()
       #foreach my $contig ( $self->_vmap->get_all_RawContigs) {    $db->get_Clone( $contig->cloneid)

#print STDERR "clone_info\n";


my $urls = ExtURL->new;

    my @clones=$vc->get_all_clones;
    my $clone_info;

    my $db=$vc->dbobj;

    foreach my $clone (@clones) {
	my $acc = $clone->id;
	my $embl_url = $clone->gi ? $urls->get_url('ENTREZPRO',$clone->gi)
			      : $urls->get_url('EMBL', $acc);

	$clone_info .=
	      qq(<a href="/perl/seqentryview?seqentry=$acc">$acc</a>).
	      "Version ".$clone->version."&nbsp;&nbsp;" .
	      ( $clone->name ? qq(BAC/PAC <a href="$embl_url"> ).$clone->name
							. qq(</a>&nbsp;&nbsp;) 
	                     :'') .
	      "Sequencing Phase ".$clone->htg_phase."&nbsp;&nbsp;" .
	      ($db->seqsite_html($clone->site)
		  ?"Sequenced by ".$db->seqsite_html($clone->site)
		  :""
	      )
	      ."<BR>\n";

    }     
    return $clone_info;
}
