Merge pull request #5 from solgenomics/topic/fix_il_maps
[cview.git] / lib / CXGN / Cview / Map.pm
blob598240a961e5a81349a5bdf290fede1abfe72da6
2 =head1 NAME
4 CXGN::Cview::Map - an abstract class to deal with maps for the SGN comparative viewer.
6 =head1 DESCRIPTION
8 The SGN mapviewer traditionally used a Perl module called CXGN::Cview::Cview_data_adapter to interface to different data sources. However, this approach was not scalable and was replaced with the CXGN::Cview::Map abstract interface approach.
10 Every Map represented in the SGN comparative viewer version 2.0 needs a corresponding Map object. It needs to inherit from CXGN::Cview::Map, and implement its functions. Each map should be identifyable by an identifier, which is used by CXGN::Cview::MapFactory to create the appropriate map object. If a new map type is added, corresponding code has to be added to the MapFactory to create the map object.
12 The inherited classes should be placed in the CXGN::Cview::Map::<DATABASE>:: namespace, where <DATABASE> signifies the website these interfaces are specific to. For SGN, <DATABASE> equals "SGN".
14 See L<CXGN::Cview::MapFactory> for the current list of supported identifiers and which types of maps they will generate.
16 =head1 AUTHOR(S)
18 Lukas A. Mueller <lam87@cornell.edu>
20 =head1 VERSION
22 part of the compatibility layer of version 2.0 of the SGN mapviewer
24 =head1 FUNCTIONS
26 This class implements the following functions:
28 =cut
30 package CXGN::Cview::Map;
31 use strict;
32 use warnings;
34 use CXGN::DB::Object;
35 use CXGN::Cview::Chromosome;
36 use CXGN::Cview::Chromosome::IL;
37 use CXGN::Cview::Chromosome::PachyteneIdiogram;
38 use CXGN::Cview::Legend;
39 use CXGN::Tools::Text qw | trim |;
41 use base qw | CXGN::DB::Object |;
43 =head2 function new()
45 Synopsis: constructor
46 Arguments: should take a database handle and a parameter identifying a map.
47 Returns:
48 Side effects:
49 Description:
51 =cut
53 sub new {
54 my $class = shift;
55 my $dbh = shift;
56 my $self = $class->SUPER::new($dbh);
58 # set some defaults
60 $self->set_preferred_chromosome_width(20);
61 $self->set_type("genetic");
62 $self->set_units("cM");
63 $self->set_short_name("unknown map");
64 $self->set_long_name("");
65 $self->set_chromosome_names(());
66 $self->set_chromosome_lengths(1);
67 $self->set_chromosome_count(1);
68 $self->set_organism("Solanum lycopersicum");
69 $self->set_common_name("Tomato");
70 $self->set_marker_link("/maps/physical/clone_info.pl?id=");
71 $self->set_legend(CXGN::Cview::Legend->new()); # an empty legend.
73 return $self;
76 =head2 accessors set_id(), get_id()
78 Property: the primary id of the map object
79 Side Effects:
80 Description:
82 =cut
84 sub get_id {
85 my $self=shift;
86 return $self->{id};
89 sub set_id {
90 my $self=shift;
91 $self->{id}=shift;
96 =head2 function get_chromosome()
98 Synopsis: my $chr = $map -> get_chromosome( $chr_nr);
99 Arguments: a legal linkage group name (usually a number, but could also
100 be alphanumeric for certain linkage groups).
101 Returns: a CXGN::Cview::Chromosome object, or a derived class thereof.
102 Side effects: in most implementations, this function will likely access
103 the databases and generate the chromosome object anew for
104 each call, such that there is considerable overhead calling
105 this function on complex chromosomes.
106 Description:
108 =cut
110 sub get_chromosome {
111 my $self = shift;
112 my $chr_nr = shift;
113 # this function should return a CXGN::Cview::Chromosome object
114 # or subclass thereof
115 my $empty_chr = CXGN::Cview::Chromosome->new($chr_nr, 100, 40, 40);
116 #$emtpy_chr -> set_height(1);
117 #$emtpy_chr -> set_length(1);
118 #$emtpy_chr -> set_color(255, 255, 255);
119 return $empty_chr;
123 =head2 accessors get_map_items, set_map_items
125 Usage: $map->set_map_items(@map_items);
126 Desc: provides additional items to be overlayed on the map
127 Property array of string, of the form "$chr $offset $name"
128 Side Effects: will be displayed as an overlay on the map, if implemented
129 in the map subclass (test with can_overlay())
130 Example:
132 =cut
134 sub get_map_items {
135 my $self = shift;
136 if(!exists($self->{map_items}) || !defined($self->{map_items})) { @{$self->{map_items}}=(); }
137 return @{$self->{map_items}};
140 sub set_map_items {
141 my $self = shift;
142 my @map_items = map { trim($_) } @_;
143 @{$self->{map_items}} = @map_items;
147 =head2 function get_linkage_group()
149 Synopsis: this is a synonym for get_chromosome()
150 Arguments: see get_chromosome()
151 Returns: see get_chromosome()
152 Side effects: etc.
153 Description:
155 =cut
157 sub get_linkage_group {
158 my $self = shift;
159 return $self->get_chromosome(@_);
163 =head2 function get_chromosome_section()
165 Synopsis: my $chr_section = $map->
166 get_chromosome_section($chr_nr, $start, $end, $comparison);
167 Arguments: the chromosome name, the start offset in map units,
168 and the end offset in map units. The $comparison bit
169 tells the function that there is a comparison present
170 in the viewer, which can be used to subtly change the
171 appearance of the zoomed in section.
172 Returns: a chr_section.
173 Side effects:
174 Note: the default implementation just calls get_chromosome, ignoring the
175 start and end parameters. This is probably a useful behaviour if the
176 Map does not support sections.
178 =cut
180 sub get_chromosome_section {
181 my $self = shift;
182 my $chr_nr = shift;
184 return $self->get_chromosome($chr_nr);
188 =head2 function get_chromosomes()
190 Synopsis: my @lg = $map->get_chromosomes()
191 Arguments: none
192 Returns: a list of the linkage groups in the order
193 defined by lg_order (in the case of genetic maps anyway)
194 Side effects: accesses the database, if the map is db-based.
195 Description: calls get_chromosome_names and then get_chromosome on
196 each name
198 Synopsis:
199 Arguments:
200 Returns:
201 Side effects:
202 Description:
204 =cut
206 sub get_chromosomes {
207 my $self = shift;
208 my @linkage_groups = ();
209 foreach my $lg ($self->get_chromosome_names()) {
210 push @linkage_groups, $self->get_chromosome($lg);
212 return @linkage_groups;
218 =head2 function get_linkage_groups()
220 Synopsis: a synonym for get_chromosomes()
221 Arguments: none
222 Returns:
223 Side effects: calls get_chromosomes()
224 Description: see get_chromosomes().
227 =cut
229 sub get_linkage_groups {
230 my $self = shift;
231 return $self->get_chromosomes(@_);
234 =head2 function get_overview_chromosome()
236 Synopsis:
237 Arguments:
238 Returns:
239 Side effects:
240 Description:
242 =cut
244 sub get_overview_chromosome {
245 my $self =shift;
246 my $chr_nr = shift;
247 my $chr = $self->get_chromosome($chr_nr);
248 return $chr;
251 =head2 function get_chromosome_connections()
253 Synopsis: my @chr_links = $map->get_chromosome_connections($chr_name);
254 Arguments: a chromosome name
255 Returns: a list of hashrefs, containing 4 keys
256 map_version_id, lg_name, marker_count, short_name
257 and the corresponding values
258 Side effects: most implementations will query the database
259 Description: the default implementation does nothing and returns
260 an empty list.
262 =cut
264 sub get_chromosome_connections {
265 my $self = shift;
266 my @connections = ();
267 return @connections;
271 =head2 accessors set_chromosome_count(), get_chromosome_count()
273 Synopsis: my $chr_count = $map->get_chromosome_count();
274 Property: the number of chromosomes in the Map (integer).
275 Side Effects:
276 Notes: The constructor should set this property
277 in subclasses.
279 =cut
281 sub get_chromosome_count {
282 my $self=shift;
283 return $self->{chromosome_count};
287 sub set_chromosome_count {
288 my $self=shift;
289 $self->{chromosome_count}=shift;
293 =head2 accessors set_chromosome_names(), get_chromosome_names()
295 Property: an ordered list of chromosome names
296 Side Effects: names will be used on the display to identify the
297 chromosomes.
298 Description: This property should be set in the constructor of the
299 Map object.
301 =cut
303 sub get_chromosome_names {
304 my $self=shift;
305 return @{$self->{chromosome_names}};
308 sub set_chromosome_names {
309 my $self=shift;
310 @{$self->{chromosome_names}}= @_;
314 =head2 get_chromosome_by_name
316 Usage: my $c = $map->get_chromosome_by_name("7b")
317 Desc: returns a Cview chromosome object
318 Args: the name of the chromosome
319 Side Effects:
320 Example:
322 =cut
324 sub get_chromosome_by_name {
325 my $self = shift;
326 my $name = shift;
328 # a hash would be useful internally...
329 my @chromosomes = $self->get_chromosomes();
330 my @names = $self->get_chromosome_names();
331 for (my $i=0; $i<@chromosomes; $i++) {
332 if ($name eq $names[$i]) {
333 return $chromosomes[$i];
336 die "The chromosome $name does not exist!\n";
340 =head2 accessors set_chromosome_lengths(), get_chromosome_lengths()
342 Synopsis: an ordered list of chromosomes lengths in the Map units.
343 Arguments: none.
344 Returns:
345 Side effects:
346 Description: Note: the first chromosome is in list element 0.
348 =cut
350 sub get_chromosome_lengths {
351 my $self = shift;
352 return @{$self->{chromosome_lengths}};
356 sub set_chromosome_lengths {
357 my $self = shift;
358 @{$self->{chromosome_lengths}} = @_;
362 =head2 get_chr_length_by_name
364 Usage:
365 Desc:
366 Ret:
367 Args:
368 Side Effects:
369 Example:
371 =cut
373 sub get_chr_len_by_name {
374 my $self = shift;
375 my $chr_name = shift;
376 my @names = $self->get_chromosome_names();
377 for (my $i=0; $i<@names; $i++) {
378 if ($names[$i] eq $chr_name) {
379 return ($self->get_chromosome_lengths())[$i];
382 return undef;
387 =head2 function has_linkage_group()
389 Synopsis: if ($map->has_linkage_group("7F")) { ... }
390 Arguments: a chromosome or linkage group name
391 Returns: returns a true value if a linkage group
392 of that name exists, a false value if it does
393 not exist. This default implementation should
394 work for all subclasses that set the chromosome_names
395 in the constructor.
396 Side effects:
397 Description:
399 =cut
401 sub has_linkage_group {
402 my $self = shift;
403 my $linkage_group = shift;
404 foreach my $lg ($self->get_chromosome_names()) {
405 if ($lg eq $linkage_group) {
406 return 1;
409 return 0;
412 =head2 function get_marker_count()
414 Synopsis: $map->get_marker_count($chr_nr)
415 Arguments: a chromosome number
416 Returns: the number of markers on that chr in the map
417 Side effects: depending on implementation, may access db
418 Description: this function needs to be implemented in sub-
419 classes for the map statistics in the SGN
420 mapviewer to work.
422 =cut
424 sub get_marker_count {
425 my $self = shift;
426 return "?";
429 =head2 function get_marker_type_stats()
431 Synopsis:
432 Arguments:
433 Returns:
434 Side effects:
435 Description:
437 =cut
439 sub get_marker_type_stats {
444 =head2 accessors set_short_name(), get_short_name()
446 Property:
447 Setter Args:
448 Getter Args:
449 Getter Ret:
450 Side Effects:
451 Description:
453 =cut
455 sub get_short_name {
456 my $self=shift;
457 return $self->{short_name};
460 sub set_short_name {
461 my $self=shift;
462 $self->{short_name}=shift;
465 =head2 accessors set_long_name(), get_long_name()
467 Property:
468 Setter Args:
469 Getter Args:
470 Getter Ret:
471 Side Effects:
472 Description:
474 =cut
476 sub get_long_name {
477 my $self=shift;
478 return $self->{long_name};
481 sub set_long_name {
482 my $self=shift;
483 $self->{long_name}=shift;
486 =head2 accessors set_abstract(), get_abstract()
488 Property:
489 Setter Args:
490 Getter Args:
491 Getter Ret:
492 Side Effects:
493 Description:
495 =cut
497 sub get_abstract {
498 my $self=shift;
499 return $self->{abstract};
502 sub set_abstract {
503 my $self=shift;
504 $self->{abstract}=shift;
508 =head2 accessors set_centromere(), get_centromere()
510 Synopsis: my ($north, $south, $center) = $map->get_centromere($lg_name)
511 Arguments: a valid linkage group name
512 Returns: this function should return a three member list, the first
513 element corresponds to the north boundary of the centromere in cM
514 the second corresponds to the south boundary of
515 the centromere in cM, the third is the arithmetic mean
516 of the two first values.
517 Side effects: none
518 Description: this property should be set in the constructor. The setter takes
519 the north and the south position as parameters.
520 $map->set_centromere($lg_name, $north, $south)
522 =cut
524 sub get_centromere {
525 my $self=shift;
526 my $chr_name = shift;
527 return ($self->{centromere}->{$chr_name}->{north}, $self->{centromere}->{$chr_name}->{south}, ($self->{centromere}->{$chr_name}->{north}+$self->{centromere}->{$chr_name}->{south})/2);
530 sub set_centromere {
531 my $self = shift;
532 my $chr_name = shift;
533 ($self->{centromere}->{$chr_name}->{north}, $self->{centromere}->{$chr_name}->{south}) = @_;
538 =head2 accessors set_deprecated_by(), get_deprecated_by()
540 Property: some maps will support deprecation information,
541 such as the maps in the SGN database. This
542 property returns the id of the map that supercedes
543 the current map.
544 Side Effects:
545 Description:
547 =cut
549 sub get_deprecated_by {
550 my $self=shift;
551 return $self->{deprecated_by};
554 sub set_deprecated_by {
555 my $self=shift;
556 $self->{deprecated_by}=shift;
561 =head2 accessors set_type(), get_type()
563 Property: the map type, which is defined for
564 the database-based maps. Types include
565 FISH and Genetic
566 Side Effects:
567 Description:
569 =cut
571 sub get_type {
572 my $self=shift;
573 return $self->{type};
576 sub set_type {
577 my $self=shift;
578 $self->{type}=shift;
582 =head2 accessors set_units(), get_units()
584 Property: the unit measure of the map, such
585 as cM or MB
586 Side Effects:
587 Description:
589 =cut
591 sub get_units {
592 my $self=shift;
593 return $self->{units};
596 sub set_units {
597 my $self=shift;
598 $self->{units}=shift;
603 =head2 accessors set_preferred_chromosome_width(), get_preferred_chromosome_width()
605 Synopsis:
606 Arguments:
607 Returns:
608 Side effects:
609 Description:
611 =cut
613 sub set_preferred_chromosome_width {
614 my $self = shift;
615 $self->{preferred_chromosome_width}= shift;
618 sub get_preferred_chromosome_width {
619 my $self = shift;
620 return $self->{preferred_chromosome_width};
623 =head2 function can_zoom()
625 Synopsis: if ($map->can_zoom()) { ...
626 Arguments: none
627 Returns: 1 if the map supports zooming in, 0 if it
628 doesn\'t
629 Side effects: none
630 Description: default is zooming not supported.
632 =cut
634 sub can_zoom {
635 return 0;
638 =head2 show_ruler
640 Usage: should return 0 or 1, depending whether the ruler
641 should be shown on a map overview.
642 Desc: default is 1, show ruler.
643 Ret:
644 Args:
645 Side Effects:o
646 Example:
648 =cut
650 sub show_ruler {
651 return 1;
656 =head2 function show_stats()
658 Synopsis: whether to show the stats on the overview page for
659 this map. Override if default of 1 is not appropriate.
660 Arguments:
661 Returns:
662 Side effects:
663 Description:
665 =cut
667 sub show_stats {
668 return 1;
672 =head2 function get_map_stats()
674 Synopsis: my $marker_type_html = $map->get_map_stats()
675 Returns: a HTML snippet with marker type information on this map.
676 Side effects: this will be displayed on the map overview page.
678 =cut
680 sub get_map_stats {
684 =head2 function collapsed_marker_count()
686 Synopsis:
687 Arguments:
688 Returns:
689 Side effects:
690 Description: the comparative viewer displays the reference chromosome
691 with only a small number of markers shown. This function
692 should give a number for the number of markers shown.
693 The default is 12.
695 =cut
697 sub collapsed_marker_count {
698 my $self = shift;
699 return 12;
702 =head2 function initial_zoom_height()
704 Synopsis: the initial zoom level, in map units.
705 Arguments:
706 Returns:
707 Side effects:
708 Description:
710 =cut
712 sub initial_zoom_height {
713 my $self = shift;
714 if ($self->get_units() eq "MB") {
715 return 4;
717 return 20;
721 =head2 accessors set_marker_link(), get_marker_link()
723 Synopsis: returns the appropriate link for marker $m
724 Arguments: a marker name
725 Returns:
726 Side effects: will be used to link that marker from the map
727 Description:
729 =cut
731 sub get_marker_link {
732 my $self=shift;
733 my $id = shift;
734 if ($id) {
735 return $self->{marker_link}.$id;
737 return "";
740 sub set_marker_link {
741 my $self=shift;
742 $self->{marker_link}=shift;
745 =head2 function has_IL()
747 Synopsis: if the map has an associated IL map.
748 Arguments:
749 Returns:
750 Side effects:
751 Description:
753 =cut
755 sub has_IL {
758 =head2 function has_physical()
760 Synopsis: if the map has an associated physical map.
761 Arguments:
762 Returns:
763 Side effects:
764 Description: soon to be deprecated but still used...
766 =cut
768 sub has_physical {
771 =head2 accessors set_organism(), get_organism()
773 Property: the organism name
775 Getter Args:
776 Getter Ret:
777 Side Effects:
778 Description:
779 to do: this should be expanded the two parents...
781 =cut
783 sub get_organism {
784 my $self=shift;
785 return $self->{organism};
788 sub set_organism {
789 my $self=shift;
790 $self->{organism}=shift;
793 =head2 accessors set_common_name(), get_common_name()
795 Property: the common name
796 Setter Args:
797 Getter Args:
798 Getter Ret:
799 Side Effects:
800 Description:
802 =cut
804 sub get_common_name {
805 my $self=shift;
806 return $self->{common_name};
809 sub set_common_name {
810 my $self=shift;
811 $self->{common_name}=shift;
814 =head2 function append_messages()
816 Synopsis:
817 Arguments:
818 Returns:
819 Side effects:
820 Description: appends a message string that can be displayed by the
821 chromosome viewer to tell the user about unexpected
822 conditions or errors. The messages can be retrieved
823 using get_messages().
825 =cut
827 sub append_messages {
828 my $self = shift;
829 $self->{messages} .= shift;
833 =head2 function get_messages()
835 Synopsis:
836 Arguments:
837 Returns:
838 Side effects:
839 Description: gets the message string that has been constructed using
840 the append_messages() function.
842 =cut
844 sub get_messages {
845 my $self = shift;
846 return $self->{messages};
849 =head2 map_id2map_version_id
851 Usage: $map_version_id = $map->map_id2map_version_id($map_id)
852 Desc: converts the $map_id to its corresponding $map_version_id
853 if the map supports versioning of maps. The default
854 implementation returns the same id that is fed to it
855 (no versioning).
856 Note: Needs to be over-ridden in a subclass for maps that
857 support versioning. The most recent, current version
858 should be returned.
859 Side Effects:
860 Example:
862 =cut
864 sub map_id2map_version_id {
865 my $self = shift;
866 my $map_id = shift;
867 return $map_id;
870 =head2 map_version_id2map_id
872 Usage: $map_id = $map->map_version_id2map_id($map_version_id)
873 Desc: converts the $map_version_id to its corresponding $map_id
874 if the map supports versioning of maps. The default
875 implementation returns the same id that is fed to it
876 (no versioning).
877 Note: Needs to be over-ridden in a subclass for maps that
878 support versioning.
879 Side Effects:
880 Example:
882 =cut
884 sub map_version_id2map_id {
885 my $self = shift;
886 my $map_version_id = shift;
887 return $map_version_id;
890 =head2 accessors get_legend, set_legend
892 Usage: $m->set_legend($legend_object)
893 Desc: the legend object defines the legend that
894 will be displayed in the viewer.
895 Property: a CXGN::Cview::Legend object
896 Side Effects:
897 Example:
899 =cut
901 sub get_legend {
902 my $self = shift;
903 return $self->{legend};
906 sub set_legend {
907 my $self = shift;
908 $self->{legend} = shift;
911 =head2 accessors get_temp_dir, set_temp_dir
913 Usage: $m->get_temp_dir()
914 Desc: Accessors for the temp dir [string]
915 Property
916 Side Effects: temporary files generated by this object will
917 be stored in the specified dir
918 Example:
920 =cut
922 sub get_temp_dir {
923 my $self = shift;
924 return $self->{temp_dir};
927 sub set_temp_dir {
928 my $self = shift;
929 $self->{temp_dir} = shift;
933 =head2 function can_overlay()
935 Usage: my $f = $map->can_overlay();
936 Desc: whether the map implements overlay function.
937 overlay information can be set using the
938 set_map_items() accessors.
939 Ret:
940 Args:
941 Side Effects:
942 Example:
944 =cut
946 sub can_overlay {
947 return 0;
950 =head2 accessors get_parent1_stock_id, set_parent1_stock_id
952 Usage:
953 Desc:
954 Property
955 Side Effects:
956 Example:
958 =cut
960 sub get_parent1_stock_id {
961 my $self = shift;
962 return $self->{parent1_stock_id};
965 sub set_parent1_stock_id {
966 my $self = shift;
967 $self->{parent1_stock_id} = shift;
970 =head2 accessors get_parent2_stock_id, set_parent2_stock_id
972 Usage:
973 Desc:
974 Property
975 Side Effects:
976 Example:
978 =cut
980 sub get_parent2_stock_id {
981 my $self = shift;
982 return $self->{parent2_stock_id};
985 sub set_parent2_stock_id {
986 my $self = shift;
987 $self->{parent2_stock_id} = shift;
990 =head2 accessors get_parent1_stock_name, set_parent1_stock_name
992 Usage:
993 Desc:
994 Property
995 Side Effects:
996 Example:
998 =cut
1000 sub get_parent1_stock_name {
1001 my $self = shift;
1002 return $self->{parent1_stock_name};
1005 sub set_parent1_stock_name {
1006 my $self = shift;
1007 $self->{parent1_stock_name} = shift;
1010 =head2 accessors get_parent2_stock_name, set_parent2_stock_name
1012 Usage:
1013 Desc:
1014 Property
1015 Side Effects:
1016 Example:
1018 =cut
1020 sub get_parent2_stock_name {
1021 my $self = shift;
1022 return $self->{parent2_stock_name};
1025 sub set_parent2_stock_name {
1026 my $self = shift;
1027 $self->{parent2_stock_name} = shift;
1030 =head2 accessors get_link_by_name, set_link_by_name
1032 Usage:
1033 Desc: set to true if the marker link should be constructed
1034 using the marker name instead of the marker id
1035 (useful for linking to gbrowse etc).
1036 The map subclass needs to support this.
1037 Property
1038 Side Effects:
1039 Example:
1041 =cut
1043 sub get_link_by_name {
1044 my $self = shift;
1045 return $self->{link_by_name};
1048 sub set_link_by_name {
1049 my $self = shift;
1050 $self->{link_by_name} = shift;