1 package CXGN
::Cview
::Map
::SGN
::Genetic
;
5 CXGN::Cview::Map::SGN::Genetic - a class implementing a genetic map
9 This class implements a genetic map populated from the SGN database. This class inherits from L<CXGN::Cview::Map>.
11 Note: the common name (available through get_common_name()) for the map organism is now taken through the following join: sgn.accession -> public.organism -> sgn.organismgroup_member ->sgn.organism_group (July 2010).
15 Lukas Mueller <lam87@cornell.edu>
19 This class implements the following functions (for more information, see L<CXGN::Cview::Map>):
26 use CXGN
::Cview
::Legend
::Genetic
;
28 use CXGN
::Cview
::Map
::Tools
;
30 use base qw
| CXGN
::Cview
::Map
|;
34 Synopsis: my $genetic = CXGN::Cview::Map::SGN::Genetic->
35 new( $dbh, $map_version_id);
36 Arguments: (1) a database handle, preferably generated with
38 (2) the map version id for the desired map.
39 Returns: a Genetic map object
40 Side effects: accesses the database
48 my $map_version_id = shift;
50 my $self = $class->SUPER::new
($dbh);
51 $self->set_id($map_version_id);
55 $self->set_preferred_chromosome_width(20);
57 # fetch the chromosome lengths
59 my $query = "SELECT lg_name, max(position) FROM sgn.linkage_group JOIN sgn.marker_location USING(lg_id) WHERE linkage_group.map_version_id=? GROUP BY lg_name, lg_order ORDER BY lg_order";
60 my $sth = $self->get_dbh()->prepare($query);
61 $sth->execute($self->get_id());
62 my @chromosome_lengths = ();
63 while (my ($lg_name, $length) = $sth->fetchrow_array()) {
64 push @chromosome_lengths, $length;
66 $self->set_chromosome_lengths(@chromosome_lengths);
68 if ($self->get_chromosome_count() == 0) { return undef; }
70 my $legend = CXGN
::Cview
::Legend
::Genetic
->new($self);
71 # $legend->set_mode("marker_types");
72 $self->set_legend($legend);
80 # get the map metadata
83 SELECT map_version_id, map_type, short_name, long_name,
84 parent1_stock_id, parent2_stock_id,
85 abstract, public.organism.species, organismgroup.name
86 FROM sgn.map JOIN sgn.map_version using(map_id)
87 LEFT JOIN public.stock on(parent1_stock_id=stock.stock_id)
88 LEFT JOIN public.organism on (stock.organism_id=public.organism.organism_id)
89 LEFT JOIN sgn.organismgroup_member on (stock.organism_id=organismgroup_member.organism_id)
90 LEFT JOIN sgn.organismgroup using(organismgroup_id)
91 WHERE map_version_id=?";
93 my $sth = $self->get_dbh()->prepare($query);
94 $sth->execute($self->get_id());
95 my ($map_version_id, $map_type, $short_name, $long_name, $parent1_stock_id, $parent2_stock_id, $abstract, $organism_name, $common_name) = $sth->fetchrow_array();
96 $self->set_id($map_version_id);
97 $self->set_type($map_type);
98 $self->set_short_name($short_name);
99 $self->set_long_name($long_name);
100 $self->set_parent1_stock_id($parent1_stock_id);
101 $self->set_parent2_stock_id($parent2_stock_id);
102 $self->set_abstract($abstract);
103 $self->set_organism($organism_name);
104 $self->set_common_name($common_name);
105 $self->set_units("cM");
107 # get information about associated linkage_groups
109 my $chr_name_q = "SELECT distinct(linkage_group.lg_name), lg_order FROM sgn.linkage_group WHERE map_version_id=? ORDER BY lg_order";
110 my $chr_name_h = $self->get_dbh()->prepare($chr_name_q);
111 $chr_name_h->execute($self->get_id());
113 while (my ($lg_name) = $chr_name_h->fetchrow_array()) {
114 push @names, $lg_name;
116 $self->set_chromosome_names(@names);
117 $self->set_chromosome_count(scalar(@names));
118 $self->set_preferred_chromosome_width(20);
120 # get the location of the centromeres
122 my $centromere_q = "SELECT lg_name, min(position) as north_centromere, max(position) as south_centromere FROM linkage_group left join marker_location on (north_location_id=location_id or south_location_id=location_id) where linkage_group.map_version_id=? group by linkage_group.lg_id, linkage_group.map_version_id, lg_order, lg_name order by lg_order";
123 my $centromere_h = $self->get_dbh()->prepare($centromere_q);
124 $centromere_h->execute($self->get_id());
125 while (my ($lg_name, $north, $south) = $centromere_h->fetchrow_array()) {
126 $self->set_centromere($lg_name, $north, $south);
132 =head2 function get_chromosome
133 Synopsis: see L<CXGN::Cview::Map>
144 # my $marker_confidence_cutoff = shift; # the confidence cutoff. 3=frame 2=coseg 1=interval LOD=2 0=interval
146 # if (!$marker_confidence_cutoff) { $marker_confidence_cutoff=-1; }
148 my $chromosome = CXGN
::Cview
::Chromosome
->new();
149 $chromosome->set_name($chr_nr);
150 $chromosome->set_caption($chr_nr);
154 my $physical = 'physical';
156 if ($self->get_id() == CXGN
::Cview
::Map
::Tools
::find_current_version
($self->get_dbh(), CXGN
::Cview
::Map
::Tools
::current_tomato_map_id
())) {
158 # get the sequenced BACs
160 my $Sequenced_BAC_query =
163 distinct $physical.bac_marker_matches.bac_id,
164 $physical.bac_marker_matches.cornell_clone_name,
165 $physical.bac_marker_matches.marker_id,
166 $physical.bac_marker_matches.position
168 $physical.bac_marker_matches
169 LEFT JOIN sgn.linkage_group USING (lg_id)
170 LEFT JOIN sgn_people.bac_status USING (bac_id)
172 sgn.linkage_group.lg_name=?
173 AND sgn_people.bac_status.status='complete'
175 my $sth2 = $self->get_dbh->prepare($Sequenced_BAC_query);
176 $sth2->execute($chr_nr);
177 while (my ($bac_id, $name, $marker_id, $offset)=$sth2->fetchrow_array()) {
178 # print STDERR "Sequenced BAC for: $bac_id, $name, $marker_id, $offset...\n";
179 $name = CXGN
::Genomic
::Clone
->retrieve($bac_id)->clone_name();
181 my $m = CXGN
::Cview
::Marker
::SequencedBAC
->new($chromosome, $bac_id, $name, "", "", "", "", $offset);
182 $m->get_label()->set_text_color(200,200,80);
183 $m->get_label()->set_line_color(200,200,80);
184 $seq_bac{$marker_id}=$m;
188 # get the "normal" markers
192 marker_experiment.marker_id,
202 inner join sgn.linkage_group using (map_version_id)
203 inner join sgn.marker_location using (lg_id)
204 inner join sgn.marker_experiment using (location_id)
205 inner join sgn.marker_alias using (marker_id)
206 inner join sgn.marker_confidence using (confidence_id)
207 left join sgn.marker_collectible using (marker_id)
208 left join sgn.marker_collection using (mc_id)
210 map_version.map_version_id=?
218 #print STDERR "MY ID: ".$self->get_id()." MY CHR NR: ".$chr_nr."\n";
220 my $sth = $self->get_dbh -> prepare
($query);
221 $sth -> execute
($self->get_id(), $chr_nr);
223 while (my ($marker_id, $marker_name, $marker_type, $confidence, $order_in_loc, $location_subscript, $offset, $loc_type) = $sth->fetchrow_array()) {
224 #print STDERR "Marker Read: $marker_id\t$marker_name\t$marker_type\t$offset\n";
225 my $m = CXGN
::Cview
::Marker
-> new
($chromosome, $marker_id, $marker_name, $marker_type, $confidence, $order_in_loc, $location_subscript, $offset, undef , $loc_type, 0);
226 #print STDERR "dataadapter baccount = $bac_count!\n";
227 if ($loc_type == 100) { $m -> set_frame_marker
(); }
228 $m -> set_url
( $self->get_marker_link($m->get_id()));
229 $self->set_marker_color($m, $self->get_legend()->get_mode());
231 #print STDERR "CURRENT MODE IS: ".$self->get_legend()->get_mode()."\n";
232 $chromosome->add_marker($m);
234 if (exists($seq_bac{$marker_id})) {
235 #print STDERR "Adding Sequenced BAC [".($seq_bac{$marker_id}->get_name())."] to map...[$marker_id]\n";
236 $chromosome->add_marker($seq_bac{$marker_id});
241 foreach my $mi ($self->get_map_items()) {
243 my ($chr, $offset, $name) = split /\s+/, $mi;
246 if (!$chr || !$offset || !$name) { next; }
248 if ($chr ne $chr_nr) { next; }
250 my $m = CXGN
::Cview
::Marker
->new($chromosome);
252 $m->get_label()->set_label_text($name);
253 $m->set_offset($offset);
254 $m->get_label()->set_hilited(1);
256 $m->get_label()->set_url('');
257 $m->set_marker_name($name); # needed for proper marker ordering in the chromosome
258 $chromosome->add_marker($m);
263 $chromosome->sort_markers();
265 $chromosome -> _calculate_chromosome_length
();
271 =head2 function get_chromosome_section
273 Synopsis: my $chr_section = $map->get_chromosome_section(5, 120, 180);
274 Arguments: linkage group number, start offset, end offset
281 sub get_chromosome_section
{
283 my $chr_nr = shift; # the chromosome number
284 my $start = shift; # the start of the section in cM
285 my $end = shift; # the end of the section in cM
287 my $chromosome = CXGN
::Cview
::Chromosome
->new();
289 # main query to get the marker data, including the BACs that
290 # are associated with this marker -- needs to be refactored to
291 # work with the materialized views for speed improvements.
296 marker_experiment.marker_id,
304 min(physical.probe_markers.overgo_probe_id),
305 count(distinct(physical.overgo_associations.bac_id)),
306 max(physical.oa_plausibility.plausible)
309 inner join linkage_group using (map_version_id)
310 inner join marker_location using (lg_id)
311 inner join marker_experiment using (location_id)
312 inner join marker_alias using (marker_id)
313 inner join marker_confidence using (confidence_id)
314 left join marker_collectible using (marker_id)
315 left join marker_collection using (mc_id)
316 LEFT JOIN physical.probe_markers ON (marker_experiment.marker_id=physical.probe_markers.marker_id)
317 LEFT JOIN physical.overgo_associations USING (overgo_probe_id)
318 LEFT JOIN physical.oa_plausibility USING (overgo_assoc_id)
320 map_version.map_version_id=?
323 -- and current_version='t'
327 marker_experiment.marker_id,
336 max(physical.oa_plausibility.plausible),
337 max(physical.probe_markers.overgo_probe_id)
341 my $sth = $self->get_dbh()-> prepare
($query);
342 # print STDERR "START/END: $start/$end\n";
343 $sth -> execute
($self->get_id(), $chr_nr, $start, $end);
345 # for each marker, look if there is a associated fully sequenced BAC, and add that
346 # as a marker of type Sequenced_BAC to the map at the right location
354 physical.bac_marker_matches
355 JOIN sgn_people.bac_status using (bac_id)
357 physical.bac_marker_matches.marker_id=?
358 AND sgn_people.bac_status.status='complete'
361 my $bac_status_h = $self->get_dbh()->prepare($bac_status_q);
364 while (my ($marker_id, $marker_name, $marker_type, $confidence, $order_in_loc, $location_subscript, $offset, $loc_type, $overgo, $bac_count, $plausible, $status, $bac_name, $bac_id) = $sth->fetchrow_array()) {
365 #print STDERR "Marker Read: $marker_id\t$marker_name\t$marker_type\toffset: $offset\tovergo: $overgo\tbac_count: $bac_count\tplausible: $plausible\n";
369 if (!$plausible || $plausible == 0) { $bac_count = 0; }
370 my $m = CXGN
::Cview
::Marker
-> new
($chromosome, $marker_id, $marker_name, $marker_type, $confidence, $order_in_loc, $location_subscript, $offset, , $loc_type, 0, $overgo, $bac_count);
371 $m->set_url($self->get_marker_link($m->get_id()));
372 $self->set_marker_color($m, $self->get_legend()->get_mode());
373 #print STDERR "dataadapter baccount = $bac_count!\n";
374 if ($loc_type == 100) { $m -> set_frame_marker
(); }
376 # only add the sequenced BAC information to the F2-2000.
378 if ($self->get_id() == CXGN
::Cview
::Map
::Tools
::find_current_version
($self->get_dbh(), CXGN
::Cview
::Map
::Tools
::current_tomato_map_id
())) {
380 $bac_status_h->execute($marker_id);
381 ($seq_bac_name, $seq_bac_id) = $bac_status_h->fetchrow_array();
383 # change the name to look more standard
386 if ($seq_bac_name =~ m/(\d+)([A-Z])(\d+)/i) {
387 $seq_bac_name = sprintf ("%3s%04d%1s%02d", "HBa",$1,$2,$3);
389 $seq_bac = CXGN
::Cview
::Marker
::SequencedBAC
->new($chromosome, $seq_bac_id, $seq_bac_name, "", "", "", "", $offset);
393 # add the marker $m to the chromosome
395 $chromosome->add_marker($m);
397 if ($m->has_overgo()) {
398 $m->set_mark_color(100, 100, 100); # draw a gray circle for overgos
399 $m->set_show_mark(1);
400 $m->set_mark_link( "/tools/seedbac/sbfinder.pl?marker=".$m->get_marker_name() );
402 #print STDERR "# BACS: ".($m2[$i]->has_bacs())."\n";
403 if ($m->has_bacs()) {
404 $m->set_mark_color(180, 0, 0); # draw a red circle for associated bacs
405 $m->set_show_mark(1);
406 $m->set_mark_link("/tools/seedbac/sbfinder.pl?marker=".$m->get_marker_name());
408 if (!$m->is_visible()) {
409 $m->set_show_mark(0);
412 # add the sequenced BAC to the chromosome
413 # -url link needs to be changed
414 # -add a confidence level of 3 so that it is always displayed.
417 $seq_bac->set_confidence(3);
418 $seq_bac->set_url("/maps/physical/clone_info.pl?id=$seq_bac_id");
419 $chromosome->add_marker($seq_bac);
422 $chromosome->set_section($start, $end);
423 $chromosome -> _calculate_chromosome_length
();
430 =head2 function get_overview_chromosome
440 sub get_overview_chromosome
{
443 my $chr = $self->get_chromosome($chr_nr);
444 $chr->set_width( $self->get_preferred_chromosome_width()/2 );
445 foreach my $m ($chr->get_markers()) {
452 =head2 get_chromosome_connections()
454 Usage: @list = $map->get_chromosome_connections($lg_name)
455 Args: a linkage group name from the current map
456 Returns: a list of hashrefs, containing 4 keys
457 map_version_id, lg_name, marker_count, short_name
458 and the corresponding values
459 Side Effects: the information will be used to populate the
460 drop down menu in the comparative viewer.
465 sub get_chromosome_connections
{
472 c_map_version.map_version_id,
474 c_linkage_group.lg_name,
475 count(distinct(marker.marker_id)) as marker_count
478 join marker_experiment using(marker_id)
479 join marker_location using (location_id)
480 join linkage_group on (marker_location.lg_id=linkage_group.lg_id)
481 join map_version on (linkage_group.map_version_id=map_version.map_version_id)
483 join marker_experiment as c_marker_experiment on
484 (marker.marker_id=c_marker_experiment.marker_id)
485 join marker_location as c_marker_location on
486 (c_marker_experiment.location_id=c_marker_location.location_id)
487 join linkage_group as c_linkage_group on (c_marker_location.lg_id=c_linkage_group.lg_id)
488 join map_version as c_map_version on
489 (c_linkage_group.map_version_id=c_map_version.map_version_id)
490 join map as c_map on (c_map.map_id=c_map_version.map_id)
492 map_version.map_version_id=?
493 and linkage_group.lg_name=?
494 and c_map_version.map_version_id !=map_version.map_version_id
495 and c_map_version.current_version='t'
497 c_map_version.map_version_id,
498 c_linkage_group.lg_name,
504 my $sth = $self->get_dbh() -> prepare
($query);
505 $sth -> execute
($self->get_id(), $chr_nr);
508 #print STDERR "***************** Done with query..\n";
509 while (my $hashref = $sth->fetchrow_hashref()) {
510 #print STDERR "READING----> $hashref->{map_version_id} $hashref->{lg_name} $hashref->{marker_count}\n";
511 push @chr_list, $hashref;
515 # hard code some connections to agp and fish maps.
517 my $tomato_version_id = CXGN
::Cview
::Map
::Tools
::find_current_version
($self->get_dbh(), CXGN
::Cview
::Map
::Tools
::current_tomato_map_id
());
518 ###print STDERR $self->get_id()." VERSUS $tomato_version_id\n\n";
520 if ($self->get_id() == $tomato_version_id) {
522 ##print STDERR "***** Map ".$self->get_id(). " pushing agp and fish map!\n\n";
523 push @chr_list, { map_version_id
=> "agp",
524 short_name
=> "Tomato AGP map",
528 push @chr_list, { map_version_id
=> 25,
529 short_name
=> "FISH map",
535 warn $self->get_id()." has no other associated maps...\n\n";
541 =head2 function has_linkage_group
551 sub has_linkage_group
{
553 my $candidate = shift;
554 foreach my $lg ($self->get_chromosome_names()) {
555 if ($lg eq $candidate) {
562 =head2 function get_marker_count
564 accesses the database to count the marker on the given map/chromosome.
568 sub get_marker_count
{
570 my $chr_name = shift;
571 my $query = "SELECT count(distinct(location_id)) FROM sgn.map_version JOIN marker_location using (map_version_id)
572 JOIN linkage_group using (lg_id)
573 WHERE linkage_group.lg_name=? and map_version.map_version_id=?";
574 my $sth = $self->get_dbh()->prepare($query);
575 $sth->execute($chr_name, $self->get_id());
576 my ($count) = $sth->fetchrow_array();
587 count(distinct(marker.marker_id))
589 marker join marker_collectible using (marker_id)
590 join marker_collection using(mc_id)
591 join marker_experiment on (marker.marker_id=marker_experiment.marker_id)
592 join marker_location on (marker_experiment.location_id=marker_location.location_id)
594 marker_location.map_version_id=?
603 <tr
><td colspan
="2"><b
>Marker collections
</b></td
></tr
>
605 my $sth = $self->get_dbh() -> prepare
($query);
606 $sth -> execute
($self->get_id());
608 my $map_name = $self->get_short_name();
609 $map_name =~ s/ /\+/g;
611 while (my ($type, $count)= $sth->fetchrow_array()) {
616 <a href
="/search/markers/markersearch.pl?types=$type&maps=$map_name">$count</a
>
620 $total_count += $count;
623 <tr
><td
> 
;</td><td> </td
></tr
>
625 <td
><b
>Total
</b>:</td
>
627 <a style
="font-weight: bold" href
="/search/markers/markersearch.pl?maps=$map_name">$total_count</a
>
632 my $protocol_q = "SELECT distinct(marker_experiment.protocol), count(distinct(marker_experiment.marker_experiment_id))
634 JOIN marker_experiment using (marker_id)
635 JOIN marker_location using (location_id)
636 JOIN linkage_group using (map_version_id)
637 WHERE map_version_id=?
638 GROUP BY marker_experiment.protocol";
639 my $pqh = $self->get_dbh()->prepare($protocol_q);
640 $pqh ->execute($self->get_id());
642 my $total_protocols = 0;
647 <td colspan
="2"><b
>Protocols
</b></td
>
650 while (my ($protocol, $count) = $pqh->fetchrow_array()) {
651 $s.= qq { <tr
><td
>$protocol</td><td align="right">$count</td
></tr
> };
652 $total_protocols += $count;
656 <tr
><td colspan
="2"> 
;</td></tr
>
658 <td
><b
>Total
:</b></td
>
659 <td align
="right"><b
>$total_protocols</b></td
>
668 =head2 function has_IL
681 if ($self->get_short_name()=~/1992|2000/) {
682 #print STDERR "Map ".$self->get_short_name()." has an associated IL map.\n";
685 #print STDERR "Map ".$self->get_short_name()." does not have an associated IL map.\n";
689 =head2 function has_physical
701 if ($self->get_short_name()=~/2000/) {
707 =head2 function can_zoom
709 Whether this map support zooming in. These ones do.
717 =head2 function get_marker_link
727 sub get_marker_link
{
730 return "/search/markers/markerinfo.pl?marker_id=$id";
734 =head2 function set_marker_color()
737 Parameters: marker object [CXGN::Cview::Marker], color model [string]
739 Side effects: sets the marker color according to the supplied marker color model
740 the color model is a string from the list:
741 "marker_types", "confidence"
744 Note: this function was moved to Utils from ChromosomeViewer, such that
745 it is available for other scripts, such as view_maps.pl
749 sub set_marker_color
{
752 my $color_model = shift || '';
754 if ($color_model eq "marker_types") {
755 if ($m->get_marker_type() =~ /RFLP/i) {
756 $m->set_color(255, 0, 0);
757 $m->set_label_line_color(255, 0,0);
758 $m->set_text_color(255,0,0);
760 elsif ($m->get_marker_type() =~ /SSR/i) {
761 $m->set_color(0, 255, 0);
762 $m->set_label_line_color(0, 255,0);
763 $m->set_text_color(0,255,0);
765 elsif ($m->get_marker_type() =~ /CAPS/i) {
766 $m->set_color(0, 0, 255);
767 $m->set_label_line_color(0, 0,255);
768 $m->set_text_color(0,0,255);
770 elsif ($m->get_marker_type() =~ /COS/i) {
771 $m->set_color(255,0 , 255);
772 $m->set_label_line_color(255,0, 255);
773 $m->set_text_color(255,0,255);
776 $m->set_color(0, 0, 0);
777 $m->set_label_line_color(0, 0,0);
778 $m->set_text_color(0,0,0);
783 my $c = $m -> get_confidence
();
785 $m->set_color(0,0,0);
786 $m->set_label_line_color(0,0,0);
787 $m->set_text_color(0,0,0);
790 $m->set_color(0,0,255);
791 $m->set_label_line_color(0,0,255);
792 $m->set_text_color(0,0,255);
796 $m->set_color(0,255, 0);
797 $m->set_label_line_color(0,255,0);
798 $m->set_text_color(0,255,0);
801 $m->set_color(255, 0, 0);
802 $m->set_label_line_color(255, 0,0);
803 $m->set_text_color(255, 0,0);
806 $m->set_color(128, 128, 128);
807 $m->set_label_line_color(128, 128, 128);
808 $m->set_text_color(128, 128, 128);
820 my $q = "SELECT name FROM stock WHERE stock_id=?";
821 my $h = $self->get_dbh()->prepare($q);
823 my ($name) = $h->fetchrow_array();
827 sub get_parent1_stock_name
{
829 return $self->get_stock_name($self->get_parent1_stock_id);
832 sub get_parent2_stock_name
{
834 return $self->get_stock_name($self->get_parent2_stock_id);