# circularGenome.pm # package RG::circularGenome; # If this WERE a module, the boilerplate would look something like this: # # require Block; # # our @ISA = qw(Exporter); # our @EXPORT = qw( # ... # ); 1; package main; use strict; # DEBUG use warnings; # DEBUG use Data::Dumper; # DEBUG sub create_circularGenome { # # Create a circular genome canvas. # # Open window, set org. # # Input: $c source canvas # Output: - # Global: %global main::trace_me(); my ($c) = @_; our (%global,$canvas); # our $scale = $global{$c}->{SCALE}; $canvas = create_canvas(-type => 'circular', -org => $global{$c}->{org_name}, -buttons => \&scatterplot_buttonbar); ############# Create window elements ####################### our $label_status = 0; our $cvh = 500; # canvas height our $cvw = 700; # canvas width our $org = $global{$c}->{org_name}; # my $label_toggle = $canvas->Checkbutton(-text=>'Turn on gene names', # -onvalue=>1, # -offvalue=>0, # -variable=> \$label_status, # -command=> [\&drawGenome, $canvas, $cvh, $cvw, $label_status, $scale ] # )->pack(-side=>'bottom'); &drawGenome($canvas,$cvh,$cvw,$label_status,$org); # Graph Label } #$mw->deiconify(); #$mw->raise(); #MainLoop; ######################################################################## sub drawGenome { my ($canvas,$cvh,$cvw,$label_status,$org) = @_; print"label status=$label_status\n"; # print"scale=$scale\n"; my ($circumference,$pi,$genome_length,$radius,$message,$deg2rad,$drawn_angle); my @colors = qw/grey purple pink blue turquoise green chartreuse yellow gold orange/; our($dbh,$sth,@myorfs,@orfids,$gene_name); ########################### Database section ################ # Define database connection $dbh = DBI->connect('dbi:mysql:genomatik','genomatik','3369',{ RaiseError => 1,AutoCommit => 1 }); # grab protein positions $sth = $dbh->prepare("select id from org where full_name='$org'") or die "Can't prepare SQL statement ", $dbh->errstr(),"\n"; $sth->execute() or die "Can't execute SQL statement: ", $sth->errstr(), "\n"; my($orgid) = $sth->fetchrow_array(); print"org=$org\torgid=$orgid\n"; $sth = $dbh->prepare ("select text_id,gene_name,protein5, protein3 from protein where org_id=$orgid order by protein5 desc") or die "Can't prepare SQL statement ", $dbh->errstr(),"\n"; $sth->execute() or die "Can't execute SQL statement: ", $sth->errstr(), "\n"; my $count=0; while (my($text_id,$gene_name,$protein5,$protein3) = $sth->fetchrow_array()) { $myorfs[$count]= [$text_id,$gene_name,$protein5,$protein3]; $count++; } my $orfcount = $#myorfs+1; print" There are $orfcount orfs in $org\n"; # Mathmatical Basis # # For a circle with central angle A, arc length S and circumference C, # S/C = A/360 degrees. Therefore A = 360(S/2*pi*radius) # # Since we draw the longest arc (last orf) first, we just draw a full circle. After that, # the calculated central_angle is added to drawn_angle. As we draw the other orfs, the arc that is drawn # is 360 - drawn_angle. The central_angle is added to drawn_angle so that the next one will be placed # correctly. $pi = 3.1416; $deg2rad = $pi/180; $radius = 230; # define radius $circumference = 2 * $pi * $radius; # define circumference $drawn_angle=0; $genome_length=0; for (my $i=0;$i<$orfcount;$i++) { my $distance = $myorfs[$i][3] - $myorfs[$i][2]; # calc orf length $genome_length = $genome_length + $distance; # calc total genome length } $canvas->createText(350, 250, -fill => 'black', -text => "$org Genome"); $canvas->createText(350, 265, -fill => 'black', -text => "$genome_length bp"); $drawn_angle=0; for (my $i=0;$i<$orfcount;$i++) { my $color = int($i % 10); my $orig_dist = $myorfs[$i][3] - $myorfs[$i][2]; # calc original orf length my $orf_pct = $orig_dist/$genome_length; # convert orf length to pct of genome length my $graph_arc_length = $circumference * $orf_pct; # calc equivalent arc length corresponding to same pct of circum. my $central_angle = 360 * ($graph_arc_length / $circumference); # calc central angle for that arc # $message = "label status = $label_status"; if ($i == 0) { $canvas->createArc($cvw / 2 - $radius, # draw first arc all the way around circle $cvh / 2 - $radius, # set drawn_angle = angle you want this orf to be $cvw / 2 + $radius, # It will be used to set the extent for the next arc $cvh / 2 + $radius, # drawn, leaving the right arc length exposed for this orf. -width=> 10, -fill=> $colors[$color], -outline=> $colors[$color], -style=> 'arc', -start=>90, -extent=> -359.99999999, -tags=>$myorfs[$i][1]); $drawn_angle = 360 - $central_angle; $gene_name = $myorfs[$i][1]; } else { $canvas->createArc($cvw / 2 - $radius, # draw all of the other arcs on top of the first arc $cvh / 2 - $radius, $cvw / 2 + $radius, $cvh / 2 + $radius, -width=> 10, -fill=> $colors[$color], -outline=> $colors[$color], -style=> 'arc', -start=>90, -extent=> -$drawn_angle, -tags=>$myorfs[$i][1]); $drawn_angle = $drawn_angle - $central_angle; $gene_name = $myorfs[$i][1]; } # if ($scale < 1) # { # &drawLabels($drawn_angle,$gene_name); my $tick_length = 15; my $real_angle = 360-$drawn_angle+90; my $xstart = $cvw/2.0 + $radius * cos($real_angle*$deg2rad); my $ystart = $cvh/2.0 - $radius * sin($real_angle*$deg2rad); my $xstop = $xstart + $tick_length * cos($real_angle*$deg2rad); my $ystop = $ystart - $tick_length * sin($real_angle*$deg2rad); $canvas->createLine($xstart,$ystart,$xstop,$ystop); if (89< $real_angle && $real_angle <= 112.5) { $canvas->createText($xstop,$ystop, -anchor=>'s', -text=>"$gene_name"); } elsif ((112.5 < $real_angle) && ($real_angle <= 157.5)) { $canvas->createText($xstop,$ystop, -anchor=>'se', -text=>"$gene_name"); } elsif ((157.5 < $real_angle) && ($real_angle <= 202.5)) { $canvas->createText($xstop,$ystop, -anchor=>'e', -text=>"$gene_name"); } elsif ((202.5 < $real_angle) && ($real_angle <= 247.5)) { $canvas->createText($xstop,$ystop, -anchor=>'ne', -text=>"$gene_name"); } elsif ((247.5 < $real_angle) && ($real_angle <= 292.5)) { $canvas->createText($xstop,$ystop, -anchor=>'n', -text=>"$gene_name"); } elsif ((292.5 < $real_angle) && ($real_angle <= 337.5)) { $canvas->createText($xstop,$ystop, -anchor=>'nw', -text=>"$gene_name"); } elsif ((337.5 < $real_angle) && ($real_angle <= 382.5)) { $canvas->createText($xstop,$ystop, -anchor=>'w', -text=>"$gene_name"); } elsif ((382.5 < $real_angle) && ($real_angle < 427.5)) { $canvas->createText($xstop,$ystop, -anchor=>'sw', -text=>"$gene_name"); } elsif ((427.5 < $real_angle) && ($real_angle < 475)) { $canvas->createText($xstop,$ystop, -anchor=>'s', -text=>"$gene_name"); } # } } } ##################################################### # Displays value of $message in lower box when mouse is over item, goes back to null when mouse leaves. #sub bind_message #{ # my($widget, $msg) = @_; # $widget->Tk::bind('', [ sub { $message = $_[1]; }, $msg ]); # $widget->Tk::bind('', sub { $message = ""; }); #}