5 CXGN::Cview::Chromosome - a class for drawing chromosomes.
9 Inherits from L<CXGN::Cview::ImageI>. The chromosome can be defined by adding markers as CXGN::Cview::Marker objects, using the add_marker() function. An object defining a ruler (CXGN::Cview::Ruler) can be obtained by calling the get_ruler() function. The length of the chromosome is either defined implicitly by the marker with the highest cM position, or explicitly using the set_length() function. The placement of the chromosome is defined by CXGN::Cview::ImageI defined functions such as set_horizontal_offset(), which defines the mid-line of the chromosome, and set_vertical_offset(), which defines the top edge.
11 Chromosomes can be rendered either in full or in section. The sections can start at cM positions other than 0 and are rendered slightly differently. Use set_section() to define the section.
13 The render() function will render the chromosome on the GD::Image supplied. It calls the subroutines to draw the chromosomes, lays out the marker labels and then calls the render function on each marker object.
15 Certain aspects of the appearance of the chromosome can be changed. For example, the color of the chromosome can be changed using set_color(). Labels can be rendered on the left or on the right of the chromosome, using set_labels_right() or set_labels_left().
17 Markers with the highest LOD score or rendered last, such that they will appear on the chromosome at the expense of lower scoring markers.
19 Chromosome areas can be rendered clickable using the function rasterize().
23 See also the documentation in L<CXGN::Cview> and L<CXGN::Cview::ImageI>.
27 Lukas Mueller (lam87@cornell.edu)
31 CXGN::Cview::Chromosome has the following methods:
36 use CXGN
::Cview
::ImageObject
;
37 use CXGN
::Cview
::Marker
;
38 use CXGN
::Cview
::Marker
::SequencedBAC
;
39 use CXGN
::Cview
::Ruler
;
40 use CXGN
::Cview
::Ruler
::PachyteneRuler
;
41 use CXGN
::Cview
::Chromosome
::BarGraph
;
44 package CXGN
::Cview
::Chromosome
;
46 use base
qw(CXGN::Cview::ImageObject);
52 my $c = CXGN::Cview::Chromosome -> new( chr number, height in pixels, horizontal offset, vertical offset, [start cM], [end cM])
54 Creates a new chromosome object. The horizontal offset denotes the offset of the chromosome mid-line. The vertical offset defines the upper end of the chromosome. Note that some renditions of the chromosome will add round edges on the top and on the bottom, so that the rounded top position will be smaller than the vertical offset.
56 Optionally, start_cM and end_cM can be supplied, which will set the start and end in cM for a chromosome section. The chromosome will be rendered as a section, i.e, the ends will be flat instead of rounded.
70 my $self = $class -> SUPER
::new
($x, $y, $height);
72 $self -> set_start_cM
($start); # if a chromosome section, where the section starts, in cM
73 $self -> set_end_cM
($end); # if a chromosome section, where the section ends, in cM
75 $self -> {markers
} = ();
77 $self->set_labels_right();
78 $self -> set_width
(20); # default width
79 $self -> {curved_height
} = $self->get_width();
81 $self->{chr_nr
}=$chr_nr;
82 $self->set_name($chr_nr);
84 $self -> {font
} = GD
::Font
->Small();
86 $self -> set_horizontal_offset
($x);
87 $self -> set_vertical_offset
($y);
88 $self -> set_color
(200, 150, 150);
89 $self -> set_hilite_color
(255, 255, 0);
90 $self -> set_outline_color
(0,0,0);
91 $self -> set_hide_marker_offset
();
92 $self -> set_units
('cM');
93 $self -> set_ruler
( CXGN
::Cview
::Ruler
->new($self->get_horizontal_offset(), $self->get_vertical_offset(), $self->get_height(), 0, $self->get_length()) );
94 # don't do this - will cause deep recursion... $self -> set_bargraph( CXGN::Cview::Chromosome::BarGraph->new($self->get_horizontal_offset(), $self->get_vertical_offset(), $self->get_height(), 0, $self->get_length()));
95 $self -> hide_bargraph
(); # by default, do not show the bar graph.
99 =head2 function set_height()
101 $chr->set_height($height)
103 Sets the height of the chromosome in pixels. Recalculates all the scaling information.
104 Implemented in superclass.
109 =head2 function get_height()
111 $height = $chr ->get_height()
113 Gets the height of the chromosome in pixels. Implemented in the superclass.
118 =head2 function set_length()
120 sets the length in map units [cM].
122 This can also be automatically determined if not set manually, to the offset of the marker with the highest map unit value.
129 $self->{chromosome_length_cM
}=shift;
132 =head2 function get_length()
134 gets the length of the chromosome in map units.
141 return $self->{chromosome_length_cM
};
145 =head2 function get_units()
157 return $self->{units
};
160 =head2 function set_units()
173 $self->{units
} = $units;
176 =head2 function get_ruler()
188 return $self->{ruler
};
191 =head2 function set_ruler()
203 $self->{ruler
}=shift;
206 =head2 accessors set_bargraph(), get_bargraph()
208 Property: an associated bar graph with this chromosome
209 The bargraph is a CXGN::Cview::Chromosome::BarGraph
210 object. The default is no bar graph, ie, an empty
211 bar graph is initialized in the constructor.
220 return $self->{bargraph
};
225 $self->{bargraph
}=shift;
229 =head2 functions show_bargraph(), hide_bargraph()
241 $self->{show_bargraph
}=1;
246 $self->{show_bargraph
}=0;
249 =head2 function set_section()
251 $chr->set_section($start_in_map_units, $end_in_map_units);
253 Defines the chromosome as a section. The section starts at the start coordinate in map units, and ends at the end coordinate in map units. Chromosomes that are sections are rendered differently than full chromosomes. The section will be rendered so that it fills the entire height of the chromosome as defined with new or set_height, and the top edge will be drawn at the horizontal and vertical offset defined in the new call or with set_horizonatal_offset and set_vertical_offset.
261 $self -> set_start_cM
(shift);
262 $self -> set_end_cM
(shift);
263 $self -> {is_section
} =1;
266 =head2 function get_section()
268 $flag = $chr->is_section()
270 Returns true if the chromosome $chr is a section.
276 return $self -> {is_section
};
279 =head2 function set_hilite()
281 $chr->set_hilite(start_coord, end_coord)
283 Highlights the region of the chromosome between start_coord and end_coord with the hilite_color (which can be set with set_hilite_color, see below).
289 $self->{hilite_start
}=shift;
290 $self->{hilite_end
}=shift;
293 =head2 function set_hilite_color()
295 $chr->set_hilite($red_channel, $green_channel, $blue_channel)
297 Sets the hilite color for chromosome highlighting. Three values between 0 and 255 are required for defining red, green and blue channels. The default color is yellow (255, 255,0)
301 sub set_hilite_color
{
303 $self->{hilite_color
}[0]=shift;
304 $self->{hilite_color
}[1]=shift;
305 $self->{hilite_color
}[2]=shift;
308 sub get_hilite_color
{
310 return @
{$self->{hilite_color
}};
315 =head2 function set_color()
317 Sets the chromosome outline color. Three values between 0 and 255 are required for defining red, green and blue channels. The default color is 0,0,0, which is black. This function is defined in the parent class.
321 sub set_outline_color
{
323 $self->{outline_color
}[0]=shift;
324 $self->{outline_color
}[1]=shift;
325 $self->{outline_color
}[2]=shift;
329 =head2 function set_caption()
331 Sets the caption of the chromosome. The caption will be drawn centered on the top of the chromosome. Usually, the chromosome number should be displayed.
338 $self->{caption
}=shift;
343 return $self->{caption
};
346 =head2 function set_labels_left()
348 Causes the labels to be displayed on the left side of the chromosome.
352 sub set_labels_left
{
354 $self->{label_side
} = "left";
357 =head2 function set_labels_right()
359 Causes the labels to be displayed on the right side of the chromosome.
363 sub set_labels_right
{
365 $self->{label_side
} = "right";
368 =head2 function set_labels_none()
370 Causes the labels not to be displayed for the whole chromosome.
374 sub set_labels_none
{
376 $self -> {label_side
} = "";
379 =head2 function get_label_side()
391 return $self->{label_side
};
395 =head2 function set_display_marker_offset()
397 Causes the marker offsets to be displayed on the opposite side of the labels.
401 sub set_display_marker_offset
{
403 # is set, the marker offset in cM will be displayed on the opposite side of the label
406 $self -> {display_marker_offset
} = 1;
409 sub set_hide_marker_offset
{
411 $self -> {display_marker_offset
} = 0;
414 =head2 function render()
416 $chr-> render($image);
418 This function is called to render the chromosome and recursively calls all the rendering functions of the objects it contains. The image parameter is an GD image object. Usually, you should not have to call this function, but the MapImage object calls this function for you if you render a map.
427 $self -> draw_chromosome
($image);
428 $self -> render_markers
($image);
431 =head2 function render_markers()
437 Description: This function renders the markers of the chromosome object.
438 The important thing is to render the markers such that the highest
439 load score marker is rendererd last.
447 my @markers = $self->get_markers();
449 foreach my $lod (-1,0,1,2,3) {
451 foreach my $m (@markers) {
453 if (!$m->isa("CXGN::Cview::Marker::SequencedBAC")) {
454 if ($m->get_confidence()==$lod) {
455 $m -> render
($image);
464 # render highlighted markers again to prevent clobbering
465 foreach my $m (@markers) {
466 if ($m->is_visible() && $m->get_hilited()) {
472 foreach my $m (@markers) {
473 if ($m->isa("CXGN::Cview::Marker::SequencedBAC")) {
474 $m->get_label()->set_text_color(200,200,80);
475 $m->get_label()->set_line_color(200,200,80);
476 $m->set_color(255,255,0);
484 # =head2 function render_labels
494 # sub render_labels {
497 # foreach my $m ($self->get_markers()) {
498 # if ($m->is_visible() && $m->get_label()->get_hilited()) {
499 # $m->get_label()->render($image);
506 sub get_enclosing_rect
{
508 return (int($self->get_horizontal_offset()-$self->get_width()/2), $self->get_vertical_offset(), $self->get_horizontal_offset()+int($self->get_width()/2), $self->get_vertical_offset()+$self->{height
});
511 =head2 function rasterize()
513 Causes the chromosome to be rasterized in the MapImage tags. A scaffold of rectangular areas is overlaid on the chromosome that can be used to link to something to this part of the chromosome. The link is supplied through set_rasterize_link. The parameter gives the size of the raster in cM. With the parameter set to zero, no rastering occurs.
518 # this function sets the rasterize variable, get_image_map then rasterizes the chromosome if necessary.
521 $self->{rasterize
}=shift;
523 return $self->{rasterize
};
526 sub set_rasterize_link
{
528 $self->{rasterize_link
} = shift;
531 # the rasterize link has to be of the format http://url.domain.etc/etc/program?parameter=values¶meter=values&cM=
532 # rasterizatio will add the number of cM where clicked at the end of the link.
533 sub get_rasterize_link
{
535 if (!exists($self->{rasterize_link
}) || !defined($self->{rasterize_link
})) {
536 $self->{rasterize_link
}="";
538 return $self->{rasterize_link
};
541 =head2 function get_image_map()
543 Gets the image map for the chromosome and all contained objects within chromosome. This is normally called by the MapImage object.
549 my $coords = join ",", ($self -> get_enclosing_rect
());
552 if ($self->get_url()) { $string = "<area shape=\"rect\" coords=\"".$coords."\" href=\"".$self->get_url()."\" alt=\"\" />";}
553 foreach my $m (($self->get_markers())) {
554 if ($m->is_visible()) {
555 $string .= $m -> get_image_map
();
558 if ($self->rasterize() && $self->get_length()>0) {
559 my $raster = $self->get_length()/20;#$self->{rasterize}; # cM
560 my $steps = ($self->get_length()/$raster);
562 my $halfwidth = ($self->get_width()/2);
563 my $x = $self->get_horizontal_offset();
564 my $y = $self->get_vertical_offset();
565 my $box_pixel_height = $self->get_height()/$steps;
567 for (my $i=0; $i<=($steps+1); $i++) {
569 my $pixels = $self->mapunits2pixels($cM)+$y;
571 $string .="<area shape=\"rect\" coords=\"".int($x-$halfwidth).",".int($pixels).",".int($x+$halfwidth).",".int($pixels+$box_pixel_height)."\" href=\"".$self->get_rasterize_link().$cM."\" alt=\"\" />\n";
578 sub _sort_by_position
{
579 return ($a->get_offset() <=> $b->get_offset);
582 =head2 function sort_markers()
584 Synopsis: $c->sort_markers()
587 Side effects: sorts the markers according to their position
588 in the internal datastructure. This is required
589 for proper rendering of the marker labels; if
590 the markers are added in sequence, calling this
600 my @sorted_markers = sort _sort_by_position
($self->get_markers());
601 $self->set_markers(@sorted_markers);
604 sub _calculate_scaling_factor
{
607 $self -> _calculate_chromosome_length
();
608 if ($self->get_length()==0) { return 0; }
610 $self->{scaling_factor
}=($self->get_height()/$self->get_length());
612 #print STDERR "calculating scaling factor. height in pixels: $self->{height} chromosome_length=$self->{chromosome_length_cM} scaling factor: $self->{scaling_factor}\n";
614 return $self->{scaling_factor
};
617 sub get_scaling_factor
{
619 if (!exists($self->{scaling_factor
})) {
620 $self->{scaling_factor
}=0;
621 warn "[CXGN::Cview::Chromosome] WARNING! Scaling factor is 0.\n";
623 return $self->{scaling_factor
};
626 =head2 function add_marker()
628 $chr->add_marker($m);
630 Adds the marker object $m to the chromosome.
637 push @
{$self->{markers
}}, $m;
640 =head2 function get_markers()
642 my @m = $chr -> get_markers();
644 Gets all the markers in the chromosome as an array.
650 if (!defined($self->{markers
})) { return (); }
652 if (defined($self->get_start_cM()) && defined($self->get_end_cM())) {
655 foreach my $m (@
{$self->{markers
}}) {
656 if ( ($m->get_offset() >= $self->get_start_cM()) &&
657 ($m->get_offset() <= $self->get_end_cM()) ) {
663 return @
{$self->{markers
}};
668 @
{$self->{markers
}} = @_;
671 =head2 accessors set_start_cM(), get_start_cM()
684 if (!exists($self->{start_cM
}) || !defined($self->{start_cM
})) { $self->{start_cM
}=0; }
685 return $self->{start_cM
};
690 $self->{start_cM
}=shift;
693 =head2 accessors set_end_cM(), get_end_cM()
706 if (!exists($self->{end_cM
})) { $self->{end_cM
}=0; }
707 return $self->{end_cM
};
712 $self->{end_cM
}=shift;
717 sub get_markers_in_interval
{
719 my $start = shift; # start in cM
720 my $end = shift; # end position in cM
721 if (!$start && !$end) { $start = 0; $end = $self -> get_length
()+1 ; }
723 foreach my $m (@
{$self->{markers
}}) {
724 if ($m -> get_offset
() >= $start && $m->get_offset() <= $end) {
728 return @markers; # returns all the markers in between start and end
731 sub get_frame_markers
{
733 my @framemarkers = ();
734 foreach my $m (@
{$self->{markers
}}) {
735 if ($m->is_frame_marker()) {
736 push @framemarkers, $m;
739 return @framemarkers;
742 sub get_markers_ref
{
744 return \@
{$self->{markers
}};
749 $self->_calculate_chromosome_length();
750 $self->_calculate_scaling_factor();
751 $self -> distribute_labels
();
752 $self -> distribute_label_stacking
();
756 sub _calculate_chromosome_length
{
760 # get chromosome length in cM.
762 # if it is a section, we return the length of the section, as defined by start_cM and end_cM
764 if ($self->is_section()) {
765 if ($self->get_end_cM()>$self->{chromosome_length_cM
}) {
766 $self->get_end_cM($self->{chromosome_length_cM
});
768 $self->{chromosome_length_cM
}=$self->get_end_cM()-$self->get_start_cM();
769 return $self->{chromosome_length_cM
};
772 # it may be that chromosome_length has been manually set with set_length.
774 if ($self->get_length()) {
775 return $self->get_length();
778 # otherwise, we get the marker with the highest cM position.
779 # the length may have been set already by set_length...
781 foreach my $m (@
{$self->{markers
}}) {
782 my $offset = $m -> get_offset
();
783 if ($offset > $length) { $length = $offset; }
785 $self->{chromosome_length_cM
} = $length;
787 return $self->{chromosome_length_cM
};
790 # otherwise return some default length
796 sub get_chromosome_length
{
797 # same as get_length. Deprecated.
799 return $self->{chromosome_length_cM
};
802 =head2 function mapunits2pixels()
804 my $pixels = $chr->mapunits2pixels($cM_pos);
806 Gets the number of pixels the cM value corresponds to. Note that you have to add the vertical chromosome offset (get_vertical_offset) to this number the get the actual image coordinates.
811 sub mapunits2pixels
{
815 if (! $cM) { $cM=0; }
816 my $pixels = ($cM - $self->get_start_cM()) * $self->get_scaling_factor();
817 #print STDERR "Scaling factor: $self->{scaling_factor} cM: $cM = $pixels pixels\n";
821 =head2 function get_pixels_cM()
823 my $cM = $chr->get_pixels_cM($pixels);
825 Gets the number of cM that the number of $pixels correspond to. Note that you have to substract the vertical chromosome offset (get_vertical_offset) from the pixels this number the get the correct number of cM.
832 my $cM = ($pixels / $self->{scaling_factor
}) + $self->get_start_cM();
841 if ($self->is_section()) {
842 if ($cM >= $self->get_start_cM() && $cM <= $self ->get_end_cM()) {
851 =head2 function distribute_labels()
853 Synopsis: $c->distribute_labels()
855 Returns: distributes the labels nicely along the chromosome
856 Side effects: changes the positions of the labels
857 Description: first it calculates label positions by setting the first label
858 to be equal to the top of the chromosome, then adjusts
859 all following label positions not to overlap with the
860 previous label, pushing them down if necessary.
861 Second, it calculates the label positions by setting the last
862 label to be equal to the end of the chromosome, and iterates
863 through all labels not to overlap with the previous label, if
864 necessary, pushing it up. To calculate the final label
865 position, it takes the average of the downwards and the
866 upwards iterations through the labels. Note that the labels need
867 to be ordered for this to work.
868 this function was renamed slightly (_ omitted) and refactored
869 such that left labels and right labels are distributed
874 sub distribute_labels
{
876 $self->_distribute_labels("left");
877 $self->_distribute_labels("right");
882 sub _distribute_labels
{
886 my @m = $self->get_markers();
887 my $lastlabelpos = 0;
889 # calculate the downwards offsets
896 #if ($m->get_label_side() !~ /right|left/i) { die "Label side is not set correctly for marker ".$m->get_name()."\n"; }
897 if ($m->is_visible() && $m->is_label_visible() && ($m->get_label_side() eq "$side")) { # || !$m->get_label_side())) {
898 my $cM= $m->get_offset();
899 my $labelpos = $self->mapunits2pixels($cM)+$self->get_vertical_offset();
900 my $labelheight = $m -> get_label_height
();
901 #print STDERR "label height: $labelheight\n";
903 if (($labelpos-$labelheight)<$lastlabelpos) {
904 $labelpos = $lastlabelpos+$labelheight;
905 if (exists($downwards{$m->get_name()})) { warn "CATASTROPHE: Duplicate marker name ".($m->get_name())."\n"; }
906 $downwards{$m->get_name()} = $labelpos;
909 $downwards{$m->get_name()}=$labelpos;
911 $lastlabelpos = $labelpos;
915 # calculate the upwards offsets
918 my $toplabelpos = $self->get_vertical_offset()+$self->get_height()+12+$m[-1]->get_label_height();
919 foreach my $m (reverse(@m)) {
920 if($m->is_visible() && $m->is_label_visible() && $m->get_label_side() eq "$side") {
921 my $cM=$m->get_offset();
922 my $labelpos = $self->mapunits2pixels($cM)+$self->get_vertical_offset();
923 #print STDERR "VERTICAL OFFSET = ".$self->get_vertical_offset()."\n";
924 my $labelheight= $m->get_label_height();
925 # print STDERR $m->get_name()." offset = $cM ID=".$m->get_id()."\n";
926 if (($labelpos+$labelheight)>$toplabelpos) {
927 $labelpos = $toplabelpos-$labelheight;
928 if (!$m->get_name()) { warn "CATASTROPHE: Didn't get name on marker ".$m->get_id()."\n"; }
929 if (exists($upwards{$m->get_name})) { warn "CATASTHROPHE: duplicate marker name ".$m->get_name()."\n"; }
930 $upwards{$m->get_name()} = $labelpos;
933 $upwards{$m->get_name()}=$labelpos;
935 $toplabelpos = $labelpos;
939 # load into marker objects
942 if ($m->get_label_side() eq "$side") {
943 my $marker_name = $m -> get_name
();
944 # test to prevent warnings...
945 if (! $downwards{$marker_name}) { $downwards{$marker_name}=0; }
946 if (! $upwards{$marker_name}) { $upwards{$marker_name} = 0; }
948 my $pixels = int(($downwards{$marker_name}+$upwards{$marker_name})/2);
949 #print STDERR "Vertical pixels for marker ".$m->get_marker_name()." : $pixels.\n";
950 $m->get_label()->set_vertical_offset($pixels);
955 =head2 function distribute_label_stacking()
960 Side effects: distributes the labels of the markers of type
961 RangeMarker such that they do not collide
962 vertically, and does this for each side
968 sub distribute_label_stacking
{
970 $self->_distribute_label_stacking("left");
971 $self->_distribute_label_stacking("right");
974 sub _distribute_label_stacking
{
978 my $maximum_stacking_level = 0;
980 my $TRACK_LIMIT = 20000; # exit the loop if we exceed this number of tracks.
982 # the @tracks array keeps track of which positions are already occupied by giving the
983 # lower boundary to which the track has been filled.
984 # it is important that the markers are sorted by position in some way
985 # for this to look good (currently, for physical map, BACs are sorted by status, association_type
986 # and offset, which forces sequenced BACs to be rendered next to the chromosome
987 # and other BACs further away). All other maps should just be sorted by position.
989 foreach my $m ($self->get_markers()) {
990 if ($m->is_visible() && $m->get_label_side() eq $side) {
992 # define the position of the marker
993 my $upper_edge = $m->get_offset()-$m->get_north_range(); # the position of the top of the marker
994 if ($upper_edge < 0 || !defined($upper_edge)) { $upper_edge = 0; }
995 my $lower_edge = $m->get_offset()+$m->get_south_range(); # the position of the bottom of the marker
996 if ($lower_edge < 0 || !defined($lower_edge)) { $lower_edge = 0; }
999 my $current_track = 1;
1002 while (defined($tracks[$current_track]) && ($tracks[$current_track]>($upper_edge - $m->get_label()->get_vertical_stacking_spacing()))) {
1004 if (!exists($tracks[$current_track]) || !defined($tracks[$current_track])) { $tracks[$current_track]=0; }
1007 # under certain conditions an infinite loop may be created. To prevent it, we set
1008 # an arbitrary limit on the number of tracks supported.
1009 if ($current_track>$TRACK_LIMIT) {
1011 # if ($m->get_marker_name() =~ /Lpen/) {
1012 # print STDERR "Skipping pennellii bac ".($m->get_marker_name())." at position ".($m->get_offset())."\n";
1016 if ($current_track > $maximum_stacking_level) {
1017 $maximum_stacking_level = $current_track;
1022 # print STDERR "TRACK $current_track has lower bound $tracks[$current_track]. \n";
1023 $tracks[$current_track] = $lower_edge;
1025 $m->get_label()->set_stacking_level($current_track);
1027 #print STDERR "TRACKS: ".($m->get_marker_name())." [$current_track] = $tracks[$current_track], $upper_edge\n";
1031 # here we adjust the label_spacer property of the label to be higher than the highest track.
1032 # seems like a good idea but it may produce weird effects on some maps. Maybe this should
1033 # be factored out into another subroutine so that it could be called only if desired.
1035 foreach my $m ($self->get_markers()) {
1036 if ( ($m->get_label_side() eq "$side") && ($m->get_label()->get_stacking_height()>0)) {
1037 my $label_spacer = $m->get_label()->get_label_spacer();
1038 my $dynamic_spacer = ($maximum_stacking_level+1) * $m->get_label()->get_stacking_height()+10;
1039 if ($dynamic_spacer > $label_spacer ) {
1040 $m->get_label()->set_label_spacer( $dynamic_spacer );
1045 warn "Skipped $skipped because of space constraints (max $TRACK_LIMIT tracks).\n";
1049 =head2 function draw_chromosome()
1051 $chr->draw_chromosome($image, $type);
1053 Draws the chromosome on $image. Image is a GD image. The default chromosome rendering is as a 'sausage' type chromosome. A line model is available by supplying the type parameter "line". This is usually called by the MapImage object.
1057 sub draw_chromosome
{
1061 # draw chromosome outline
1063 if (! $self->{style
}) { $self->{style
}=""; }
1064 if ($self->{style
} eq "line") {
1065 $self->draw_chromosome_line($image);
1067 elsif ($self->{style
} eq "sausage") {
1068 $self->draw_chromosome_sausage($image);
1070 else { $self->draw_chromosome_sausage($image); }
1073 sub draw_chromosome_line
{
1077 my $color = $image -> colorResolve
($self->{color
}[0], $self->{color
}[1], $self->{color
}[2]);
1078 #print STDERR "$self->{x}, $self->get_vertical_offset(), $self->{x}, $self->get_vertical_offset()+$self->{height}, $color\n";
1079 $image -> line
($self->get_horizontal_offset(), $self->get_vertical_offset(), $self->get_horizontal_offset(), $self->get_vertical_offset()+$self->{height
}, $color);
1082 sub draw_chromosome_sausage
{
1088 my $outline_color = $image -> colorResolve
($self->{outline_color
}[0], $self->{outline_color
}[1], $self->{outline_color
}[2]);
1089 my $hilite_color = $image -> colorResolve
($self->{hilite_color
}[0], $self->{hilite_color
}[1], $self->{hilite_color
}[2]);
1090 my $color = $image -> colorResolve
($self->{color
}[0], $self->{color
}[1], $self->{color
}[2]);
1092 my $halfwidth = $self ->{width
}/2;
1094 $image -> line
($self->get_horizontal_offset() - $halfwidth, $self->get_vertical_offset() , $self->get_horizontal_offset()-$halfwidth, $self->get_vertical_offset()+$self->{height
}, $outline_color);
1095 $image -> line
($self->get_horizontal_offset() + $halfwidth, $self->get_vertical_offset() , $self->get_horizontal_offset()+$halfwidth, $self->get_vertical_offset()+$self->{height
}, $outline_color);
1096 if ($self->is_section()) {
1097 my $text_color = $image -> colorResolve
(50, 50, 50);
1098 $image -> line
($self->get_horizontal_offset()-$halfwidth, $self->get_vertical_offset(), $self->get_horizontal_offset()+$halfwidth, $self->get_vertical_offset(), $outline_color);
1099 $image -> line
($self->get_horizontal_offset()-$halfwidth, $self->get_vertical_offset()+$self->{height
}, $self->get_horizontal_offset()+$halfwidth, $self->get_vertical_offset()+$self->{height
}, $outline_color);
1100 $image -> fill
($self->get_horizontal_offset(), $self->get_vertical_offset()+1, $color);
1101 my $top_label = int($self->get_start_cM()).$self->get_units();
1102 my $bottom_label = int($self ->{end_cM
}).$self->get_units();
1103 $image -> string
($self->{font
}, $self->get_horizontal_offset()-$self->{font
}->width()* length($top_label)/2, $self->get_vertical_offset()-$self->{font
}->height()-3, $top_label, $text_color);
1104 $image -> string
($self->{font
}, $self->get_horizontal_offset() - $self->{font
}->width() * length($bottom_label)/2, $self->get_vertical_offset()+$self->get_height()+3, $bottom_label,$text_color);
1107 $image -> setAntiAliased
($outline_color);
1108 $image -> arc
($self->get_horizontal_offset(), $self->get_vertical_offset(), $self->{width
}, $self->{curved_height
}, 180, 0, GD
::gdAntiAliased
);
1109 $image -> arc
($self->get_horizontal_offset(), $self->get_vertical_offset()+$self->{height
}, $self->{width
}, $self->{curved_height
}, 0, 180, GD
::gdAntiAliased
);
1110 $image -> fill
($self->get_horizontal_offset(), $self->get_vertical_offset(), $color);
1115 if ($self->{hilite_start
} || $self->{hilite_end
}) {
1117 # if we are dealing with a section, don't hilite more than the section...
1119 if ($self->is_section()) {
1120 if ($self->{hilite_start
} < $self->get_start_cM()) {
1121 $self->{hilite_start
} = $self->get_start_cM();
1123 if ($self->{hilite_end
} > $self->get_end_cM()) {
1124 $self->{hilite_end
} = $self->get_end_cM;
1128 my $start = $self->get_vertical_offset()+$self->mapunits2pixels($self->{hilite_start
});
1129 my $end = $self->get_vertical_offset()+$self->mapunits2pixels($self->{hilite_end
});
1130 $image -> rectangle
($self->get_horizontal_offset()-$halfwidth,
1132 $self->get_horizontal_offset()+$halfwidth,
1135 $image -> fill
($self->get_horizontal_offset(), $start+1, $hilite_color);
1139 $self->draw_caption($image);
1146 my $outline_color = $image -> colorResolve
(
1147 $self->{outline_color
}[0],
1148 $self->{outline_color
}[1],
1149 $self->{outline_color
}[2]
1151 my $bigfont = GD
::Font
->Large();
1154 $self->get_horizontal_offset()- $bigfont->width() * length($self->get_caption())/2,
1155 $self->get_vertical_offset()-$bigfont->height()-$self->{curved_height
}/2,
1156 $self->get_caption(), $outline_color );