]> git.donarmstrong.com Git - biopieces.git/commitdiff
KISS browser working, but slow
authormartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Wed, 28 Oct 2009 17:19:29 +0000 (17:19 +0000)
committermartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Wed, 28 Oct 2009 17:19:29 +0000 (17:19 +0000)
git-svn-id: http://biopieces.googlecode.com/svn/trunk@714 74ccb610-7750-0410-82ae-013aeee3265d

code_perl/Maasha/KISS/Draw.pm
code_perl/Maasha/KISS/IO.pm
code_perl/Maasha/KISS/Track.pm
code_perl/Maasha/XHTML.pm
www/cgi-bin/index.cgi

index 90ed4f66d53a95a6e9d0650a0a1fae74b78b0041..6a8bc52d977eb581b1d44b7e9692604176019b19 100644 (file)
@@ -42,41 +42,13 @@ use vars qw( @ISA @EXPORT );
 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
 
-sub track_text
-{
-    # Given a sequence list add this to
-    # a Cairo::Context object.
-
-    my ( $cr,         # Cairo::Context object
-         $text,       # List of hashrefs { txt =>, x => y => }
-         $color,      # Color of features 
-       ) = @_;
-
-    # Returns nothing.
-
-    $cr->set_source_rgb( color_name2rgb( $color ) );
-
-    my ( $txt );
-
-    $cr->set_font_size( 10 );
-
-    foreach $txt ( @{ $text } )
-    {
-        $cr->move_to( $txt->{ 'x' }, $txt->{ 'y' } );
-        $cr->show_text( $txt->{ 'txt' } );
-        $cr->stroke();
-    }
-}
-
-
-sub track_feature
+sub draw_feature
 {
     # Given a list of features add these to
     # a Cairo::Context object.
 
     my ( $cr,         # Cairo::Context object
          $features,   # List of features
-         $color,      # Color of features 
        ) = @_;
 
     # Returns nothing.
@@ -86,15 +58,27 @@ sub track_feature
     foreach $feature ( @{ $features } )
     {
         $cr->set_source_rgb( color_name2rgb( $feature->{ 'color' } ) );
-        $cr->move_to( $feature->{ 'x1' }, $feature->{ 'y1' } );
 
         if ( $feature->{ 'type' } eq 'line' )
         {
             $cr->set_line_width( $feature->{ 'line_width' } );
+            $cr->move_to( $feature->{ 'x1' }, $feature->{ 'y1' } );
             $cr->line_to( $feature->{ 'x2' }, $feature->{ 'y2' } );
         }
+        elsif ( $feature->{ 'type' } eq 'rect' )
+        {
+            $cr->rectangle(
+                $feature->{ 'x1' },
+                $feature->{ 'y1' },
+                $feature->{ 'x2' } - $feature->{ 'x1' },
+                $feature->{ 'y2' } - $feature->{ 'y1' },
+            );
+
+            $cr->fill;
+        }
         elsif ( $feature->{ 'type' } eq 'text' )
         {
+            $cr->move_to( $feature->{ 'x1' }, $feature->{ 'y1' } );
             $cr->set_font_size( $feature->{ 'font_size' } );
             $cr->show_text( $feature->{ 'txt' } );
         }
index 15f4292e11fda994d635f582456a22b83bd513d6..4c3ac1498dc85292acc8f56ec8e6c95b2544b45b 100644 (file)
@@ -31,6 +31,7 @@ package Maasha::KISS::IO;
 use warnings;
 use strict;
 use Data::Dumper;
+use Maasha::Common;
 use Maasha::Filesys;
 use Maasha::SQL;
 use vars qw( @ISA @EXPORT );
@@ -155,7 +156,7 @@ sub kiss_sql_get
     my ( $sql, $entries );
 
     # $sql = "SELECT * FROM $table WHERE S_BEG >= $s_beg AND S_END <= $s_end ORDER BY S_BEG,S_END";
-    $sql = "SELECT S_BEG,S_END,ALIGN FROM $table WHERE S_BEG >= $s_beg AND S_END <= $s_end";
+    $sql = "SELECT S_BEG,S_END,Q_ID,ALIGN FROM $table WHERE S_BEG >= $s_beg AND S_END <= $s_end";
 
     $entries = Maasha::SQL::query_hashref_list( $dbh, $sql );
 
@@ -163,6 +164,143 @@ sub kiss_sql_get
 }
 
 
+sub kiss_index
+{
+    # Martin A, Hansen, October 2009.
+
+    # Creates an index of a sorted KISS file that
+    # allowing the location of the byte position
+    # from where records can be read given a
+    # specific S_BEG position. The index consists of
+    # triples: [ beg, end, bytepos ], where beg and
+    # end denotes the interval where the next KISS
+    # record begins at bytepos.
+
+    my ( $fh,   # filehandle to KISS file
+       ) = @_;
+
+    # Returns a list.
+
+    my ( $line, @fields, $beg, $end, $pos, @index );
+
+    $beg = 0;
+    $pos = 0;
+
+    while ( $line = <$fh> )
+    {
+        chomp $line;
+
+        @fields = split /\t/, $line, 3;
+        
+        $end = $fields[ S_BEG ];
+
+        if ( $end == 0 )
+        {
+            push @index, [ $beg, $end, $pos ];
+            $beg = 1;
+        }
+        elsif ( $end > $beg )
+        {
+            push @index, [ $beg, $end - 1, $pos ];
+            $beg = $end;
+        }
+        elsif( $end < $beg )
+        {
+            Maasha::Common::error( qq(KISS file not sorted: $end < $beg) );
+        }
+
+        $pos += 1 + length $line;
+    }
+
+    return wantarray ? @index : \@index;
+}
+
+
+sub kiss_index_store
+{
+    my ( $path,
+         $index,
+       ) = @_;
+
+    Maasha::Filesys::file_store( $path, $index );
+}
+
+
+sub kiss_index_retrieve
+{
+    my ( $path,
+       ) = @_;
+
+    my $index;
+
+    $index = Maasha::Filesys::file_retrieve( $path );
+
+    return wantarray ? @{ $index } : $index;
+}
+
+
+sub kiss_index_search
+{
+    my ( $index,
+         $num,
+       ) = @_;
+
+    # Returns a number.
+
+    my ( $high, $low, $try );
+
+    $low  = 0;
+    $high = scalar @{ $index };
+
+    while ( $low <= $high )
+    {
+        $try = int( ( $high + $low ) / 2 );
+    
+        # print "low: $low   high: $high   try: $try\n";
+        
+        if ( $num < $index->[ $try ]->[ 0 ] ) {
+            $high = $try;
+        } elsif ( $num > $index->[ $try ]->[ 1 ] ) {
+            $low = $try + 1;
+        } else {
+            return $index->[ $try ]->[ 2 ];
+        }
+    }
+
+    Maasha::Common::error( "Could not find number->$num in index" );
+}
+
+
+sub kiss_index_get
+{
+    my ( $file,
+         $beg,
+         $end,
+       ) = @_;
+
+    my ( $index, $offset, $fh, $entry, @entries );
+
+    $index = Maasha::KISS::IO::kiss_index_retrieve( "$file.index" );
+
+    $offset = Maasha::KISS::IO::kiss_index_search( $index, $beg );
+
+    $fh = Maasha::Filesys::file_read_open( $file );
+
+    sysseek( $fh, $offset, 0 );
+
+    while ( $entry = kiss_entry_get( $fh ) )
+    {
+        push @entries, $entry;
+
+        last if $entry->{ 'S_END' } > $end;
+    }
+
+    close $fh;
+
+    return wantarray ? @entries : \@entries;
+}
+
+
 sub kiss2biopiece
 {
     my ( $entry,   # KISS entry
index d0c7162ac843717cab73528320e7358b10866222..a815dfef312b3bc9e42524bacd7ca88c8caf86b8 100644 (file)
@@ -42,10 +42,12 @@ use vars qw( @ISA @EXPORT );
 
 sub track_ruler
 {
-    my ( $width,     # draw window width
-         $y_offset,  # y axis draw offset
-         $beg,       # base window beg
-         $end,       # base window end
+    my ( $width,      # draw window width
+         $y_offset,   # y axis draw offset
+         $beg,        # base window beg
+         $end,        # base window end
+         $font_size,  # font size
+         $color,      # font color
        ) = @_;
 
     my ( $factor, $step, $i, $txt, $x, @ruler );
@@ -66,7 +68,17 @@ sub track_ruler
             $txt = "$i|";
             $x   = sprintf( "%.0f", ( $i - $beg - length $txt ) * $factor );
 
-            push @ruler, { txt => $txt, x => $x, y => $y_offset };
+            if ( $x > 0 and $x + ( $font_size * length $txt ) < $width )
+            {
+                push @ruler, {
+                    type      => 'text',
+                    txt       => $txt,
+                    font_size => $font_size,
+                    color     => $color,
+                    x1        => $x,
+                    y1        => $y_offset
+                };
+            }
         }
     }
 
@@ -76,9 +88,11 @@ sub track_ruler
 
 sub track_seq
 {
-    my ( $width,     # draw window width
-         $y_offset,  # y axis draw offset
-         $seq,       # sequence to draw
+    my ( $width,       # draw window width
+         $y_offset,    # y axis draw offset
+         $seq,         # sequence to draw
+         $font_size,   # font size
+         $color,       # font color
        ) = @_;
 
     my ( @chars, $factor, $i, @seq_list );
@@ -88,7 +102,14 @@ sub track_seq
     $factor = $width / @chars;
 
     for ( $i = 0; $i < @chars; $i++ ) {
-        push @seq_list, { txt => $chars[ $i ], x => sprintf( "%.0f", $i * $factor ), y => $y_offset };
+        push @seq_list, {
+            type      => 'text',
+            txt       => $chars[ $i ],
+            font_size => $font_size,
+            color     => $color,
+            x1        => sprintf( "%.0f", $i * $factor ),
+            y1        => $y_offset,
+        };
     }
 
     return wantarray ? @seq_list : \@seq_list;
@@ -130,13 +151,14 @@ sub track_feature
             $y1 = $y_offset + ( $feat_height * $y_step );
 
             push @features, {
-                type       => 'line',
+                type       => 'rect',
                 line_width => $feat_height,
                 color      => 'green',
+                title      => $entry->{ 'Q_ID' },
                 x1         => $x1,
                 y1         => $y1,
                 x2         => $x1 + $w,
-                y2         => $y1,
+                y2         => $y1 + $feat_height,
             };
 
             push @features, feature_align( $entry, $beg, $y1, $factor, $feat_height ) if defined $entry->{ 'ALIGN' };
@@ -184,24 +206,25 @@ sub feature_align
             $x1 = sprintf( "%.0f", ( $entry->{ 'S_BEG' } + $pos - $beg ) * $factor );
 
             push @features, {
-                type       => 'line',
+                type       => 'rect',
                 line_width => $feat_height,
                 color      => 'red',
+                title      => $align,
                 x1         => $x1,
                 y1         => $y_offset,
                 x2         => $x1 + $w,
-                y2         => $y_offset,
+                y2         => $y_offset + $feat_height,
             };
 
-            if ( $w > 5 )
+            if ( $w > $feat_height )
             {
                 push @features, {
                     type       => 'text',
-                    font_size  => $feat_height,
+                    font_size  => $feat_height + 2,
                     color      => 'black',
                     txt        => $nt_after,
                     x1         => $x1 + sprintf( "%.0f", ( $w / 2 ) ) - $feat_height / 2,
-                    y1         => $y_offset,
+                    y1         => $y_offset + $feat_height,
                 };
             }
         }
@@ -267,6 +290,7 @@ sub track_histogram
                         type       => 'line',
                         line_width => $bucket_width,
                         color      => 'green',
+                        title      => "Features: $buckets[ $i ]",
                         x1         => $x,
                         y1         => $y_offset + $hist_height,
                         x2         => $x,
@@ -283,27 +307,6 @@ sub track_histogram
 }
 
 
-sub bucket_round
-{
-    my ( $num,
-         $bucket_size,
-       ) = @_;
-    
-    my ( $div, $int );
-
-    $div = $num / $bucket_size;
-    $int = int $div;
-
-    if ( $div - $int >= 0.5 ) {
-        return $bucket_size * ( $int + 1 );
-    } else {
-        return $bucket_size * $int;
-    }
-}
-
-
 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
 1;
-
-
index 44a72ba182bbc161c0be688ae548833b7dd1e730..3a97af1591ec26c2c25376a43025d356f7db4bdd 100755 (executable)
@@ -734,6 +734,23 @@ sub map_end
 }
 
 
+sub area
+{
+    # Martin A. Hansen, October 2009.
+
+    # HTML <area> element
+
+    my ( %args,
+       ) = @_;
+
+    warn qq(WARNING: no area href given\n)    if not $args{ "href" };
+    warn qq(WARNING: no area shape given \n)  if not $args{ "shape" };
+    warn qq(WARNING: no area coords given \n) if not $args{ "coords" };
+
+    return tag_single( "area", \%args )
+}
+
+
 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PRE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
 
index 15bb1de9e455e397b43061fd49e697849b4b6be1..1b327bc46eeb479037eed886f00e8d06fb08b797 100755 (executable)
@@ -54,18 +54,18 @@ $script = Maasha::Common::get_scriptname();
 push @html, Maasha::XHTML::html_header(
     cgi_header  => 1,
     title       => "KISS Genome Browser",
-#    css_file    => "test.css",
+    css_file    => "kiss.css",
     author      => "Martin A. Hansen, mail\@maasha.dk",
     description => "Biopieces bacterial genome browser - KISS",
     keywords    => [ qw( KISS Biopieces biopiece genome browser viewer bacterium bacteria prokaryote prokaryotes ) ],
     no_cache    => 1,
 );
 
-push @html, Maasha::XHTML::h1( txt => "KISS Genome Browser", class => "center" );
+push @html, Maasha::XHTML::h1( txt => "KISS Genome Browser", class => 'center' );
 push @html, Maasha::XHTML::form_beg( action => $script, method => "get", enctype => "multipart/form-data" );
 
 push @html, sec_navigate( $cgi );
-push @html, sec_browse( $dbh, $cgi->param( 'nav_start' ), $cgi->param( 'nav_end' ) );
+push @html, sec_browse( $dbh, $cgi );
 
 push @html, Maasha::XHTML::form_end;
 push @html, Maasha::XHTML::body_end;
@@ -101,7 +101,7 @@ sub sec_navigate
     $def_start     = nav_def_start( $cgi );
     $def_end       = nav_def_end( $cgi );
 
-    push @html, Maasha::XHTML::table_beg( summary => "Navigation table" );
+    push @html, Maasha::XHTML::table_beg( summary => "Navigation table", align => 'center' );
     push @html, Maasha::XHTML::table_row_simple( tr => [ qw( Clade Genome Assembly Contig Start End ) ], align => 'center' );
     push @html, Maasha::XHTML::table_row_simple( tr => [
         Maasha::XHTML::menu( name => "nav_clade",    options => $list_clade,    selected => $def_clade ),
@@ -114,7 +114,7 @@ sub sec_navigate
     ] );
     push @html, Maasha::XHTML::table_end;
 
-    push @html, Maasha::XHTML::table_beg( summary => "Zoom table" );
+    push @html, Maasha::XHTML::table_beg( summary => "Zoom table", align => 'center' );
     push @html, Maasha::XHTML::table_row_simple( tr => [
         Maasha::XHTML::p( txt => 'Move:' ),
         Maasha::XHTML::submit( name => "move_left3",  value => "<<<", title => "move 95% to the left" ),
@@ -134,22 +134,26 @@ sub sec_navigate
     ] );
     push @html, Maasha::XHTML::table_end;
 
+    @html = Maasha::XHTML::div( txt => join( "\n", @html ), class => 'navigate' );
+
     return wantarray ? @html : \@html;
 }
 
 
 sub sec_browse
 {
-    my ( $dbh,     # Database handle
-         $start,   # Browse start position
-         $end,     # Browse end position
+    my ( $dbh,   # Database handle
+         $cgi,   # CGI object
        ) = @_;
 
     # Returns a list.
 
-    my ( $t0, $t1, $ruler, $index, $index_beg, $index_len, $fh, $seq, $dna, $table, $entries, $features, $surface, $cr, $file, @html );
+    my ( $t0, $t1, @stats, $start, $end, $ruler, $index, $index_beg, $index_len, $fh, $seq, $dna, $table, $entries, $features, $surface, $cr, $file, @html, @img );
+
+    $start = $cgi->param( 'nav_start' );
+    $end   = $cgi->param( 'nav_end' );
 
-    $ruler = Maasha::KISS::Track::track_ruler( 1200, 25, $start, $end );
+    $ruler = Maasha::KISS::Track::track_ruler( 1200, 25, $start, $end, 10, 'black' );
 
     $index = Maasha::Fasta::index_retrieve( "$ENV{ 'BP_DATA' }/genomes/S_aur_COL/fasta/S_aur_COL.index" );
 
@@ -161,7 +165,7 @@ sub sec_browse
 
     close $fh;
 
-    $dna = Maasha::KISS::Track::track_seq( 1200, 50, $seq ) if length $seq <= 220;
+    $dna = Maasha::KISS::Track::track_seq( 1200, 50, $seq, 10, 'black' ) if length $seq <= 220;
 
     $table = 'Solexa';
 
@@ -169,9 +173,8 @@ sub sec_browse
     $entries = Maasha::KISS::IO::kiss_sql_get( $dbh, $table, $start, $end );
     $t1 = Time::HiRes::gettimeofday();
 
-    push @html, Maasha::XHTML::p( txt => "Feature count: " . Maasha::Calc::commify( scalar @$entries ) );
-
-    push @html, Maasha::XHTML::p( txt => "Time SQL: " . ( $t1 - $t0 ) );
+    push @stats, "Feature count: " . Maasha::Calc::commify( scalar @$entries );
+    push @stats, "Time SQL: " . sprintf( "%.4f", $t1 - $t0 );
 
     $t0 = Time::HiRes::gettimeofday();
 
@@ -188,7 +191,7 @@ sub sec_browse
     # push @html, Maasha::KISS::Draw::hdump( $entries );
     # push @html, Maasha::KISS::Draw::hdump( $features );
 
-    push @html, Maasha::XHTML::p( txt => "Time Track: " . ( $t1 - $t0 ) );
+    push @stats, "Time Track: " . sprintf( "%.4f", $t1 - $t0 );
 
     $file = "fisk.png";
 
@@ -197,18 +200,29 @@ sub sec_browse
 
     $t0 = Time::HiRes::gettimeofday();
 
-    Maasha::KISS::Draw::track_text( $cr, $ruler, "black" ) if $ruler;
-    Maasha::KISS::Draw::track_text( $cr, $dna, "black" )   if $dna;
-
-    Maasha::KISS::Draw::track_feature( $cr, $features, 'green' ) if $features;
+    Maasha::KISS::Draw::draw_feature( $cr, $ruler )    if $ruler;
+    Maasha::KISS::Draw::draw_feature( $cr, $dna )      if $dna;
+    Maasha::KISS::Draw::draw_feature( $cr, $features ) if $features;
 
     Maasha::KISS::Draw::file_png( $surface, $file );
 
     $t1 = Time::HiRes::gettimeofday();
 
-    push @html, Maasha::XHTML::p( txt => "Time Draw: " . ( $t1 - $t0 ) );
+    push @stats, "Time Draw: " . sprintf( "%.4f", $t1 - $t0 );
+
+    push @html, Maasha::XHTML::p( txt => join( " ", @stats ) );
+
+    push @img, Maasha::XHTML::img( src => $file, alt => "Browser Tracks", height => 800, width => 1200, id => "browser_map", usemap => "#browser_map" );
+
+    push @img, Maasha::XHTML::map_beg( name => "browser_map", id => "browser_map" );
+
+    map { push @img, Maasha::XHTML::area( href => "www.dmi.dk", shape => "rect", coords => "$_->{ x1 }, $_->{ y1 }, $_->{ x2 }, $_->{ y2 }", title => "$_->{ title }" ) } @{ $features };
+
+    push @img, Maasha::XHTML::map_beg();
+
+    push @html, Maasha::XHTML::p( txt => join( "\n", @img ) );
 
-    push @html, Maasha::XHTML::p( txt => Maasha::XHTML::img( src => $file, alt => "Browser Tracks", height => 800, width => 1200, class => "foo", id => "pix_id", usemap => "map"  ) );
+    @html = Maasha::XHTML::div( txt => join( "\n", @html ), class => 'browse' );
 
     return wantarray ? @html : \@html;
 }