more synonym shoehorning.
[cview.git] / lib / CXGN / Cview / ViewMaps.pm
blob20637dd0517c5de74c63c00d8e0e81e7cc130fb9
1 package CXGN::Cview::ViewMaps;
3 use strict;
4 use warnings;
6 use CXGN::Page::FormattingHelpers qw | page_title_html info_table_html |;
7 use CXGN::Cview::MapFactory;
8 use CXGN::Cview::ChromosomeViewer;
9 use CXGN::Cview::ChrLink;
10 use CXGN::Cview::Utils qw | set_marker_color |;
11 use CXGN::Cview::MapImage;
12 use CXGN::Tools::WebImageCache;
13 use CXGN::Map;
15 use base qw | CXGN::DB::Object |;
18 =head2 function new()
20 Synopsis:
21 Arguments: a database handle [ DBI object or CXGN::DB::Connection object]
22 the base dir [ file path ]
23 the temp_dir [ relative path ]
24 Returns: a handle to a view_maps object
25 Side effects:
26 Description: constructor
28 =cut
30 sub new {
31 my $class = shift;
32 my $dbh = shift;
33 my $basepath = shift;
34 my $temp_dir = shift;
35 my $db_backend = shift;
37 my $self = bless {}, $class;
38 $self->set_dbh($dbh);
39 # set some defaults...
41 $self->{unzoomedheight} = 20; # how many cM are seen at zoom level 1
43 # create an set the cache file in the constructor,
44 # such that we can define the temp dirs before
45 # we generate the image using generate_image()
47 my $cache = CXGN::Tools::WebImageCache->new();
48 $self->set_cache($cache);
49 $self->set_db_backend($db_backend);
51 $cache->set_basedir($basepath);
52 $cache->set_temp_dir($temp_dir);
54 return $self;
57 sub adjust_parameters {
58 my $self = shift;
60 # adjust input arguments
66 =head2 accessors set_maps(), get_maps()
68 Property:
69 Setter Args:
70 Getter Args:
71 Getter Ret:
72 Side Effects:
73 Description:
75 =cut
77 sub get_maps {
78 my $self=shift;
79 return @{$self->{maps}};
82 sub set_maps {
83 my $self=shift;
84 @{$self->{maps}}=@_;
87 =head2 accessors set_cache(), get_cache()
89 Property: the CXGN::Tools::WebImageCache object
90 Args/Ret: the same
91 Side Effects: this is the object used to generate the
92 cache image.
93 Description:
95 =cut
97 sub get_cache {
98 my $self=shift;
99 return $self->{cache};
102 sub set_cache {
103 my $self=shift;
104 $self->{cache}=shift;
107 =head2 accessors get_db_backend, set_db_backend
109 Usage:
110 Desc:
111 Property
112 Side Effects:
113 Example:
115 =cut
117 sub get_db_backend {
118 my $self = shift;
119 return $self->{db_backend};
122 sub set_db_backend {
123 my $self = shift;
124 $self->{db_backend} = shift;
129 =head2 function generate_page()
131 Arguments: none
132 Returns: nothing
133 Side effects: generates the CXGN::Cview::MapImage and stores it
134 to the cache if necessary, or reads just reads
135 the image cache if it is still valid.
137 =cut
139 sub generate_image {
140 my $self = shift;
142 # define a key for the cache. lets just use the name of the
143 # script and the map_version_ids of the maps being displayed
145 $self->get_cache()->set_key("view_maps".(join "-", map { $_->get_id() } ($self->get_maps())));
147 $self->get_cache()->set_expiration_time(86400);
150 if (! $self->get_cache()->is_valid()) {
151 my $map_width = $self->{map_width} = 720;
152 my $x_distance = $map_width/4; # the number of pixels the different elements are spaced
153 my $row_count = 0;
154 my $row_height = 120; # the height of a row (vertical space for each chromosome image)
155 my $y_distance = $row_height * (1/3);
156 my $chr_height = $row_height * (2/3);
157 my $map_height;
159 # determine the maximum chromosome count among all maps
160 # so that we can accommodate it
162 my $max_chr = 0;
163 foreach my $m ($self->get_maps()) {
164 my $chr_count = 0;
165 if ($m) {
166 $chr_count = $m->get_chromosome_count();
168 if ($chr_count > $max_chr) { $max_chr=$chr_count; }
171 $map_height = $row_height * $max_chr+2*$y_distance;
172 # show the ruler if requested
174 # if ($self->{show_ruler}) {
175 # my $r = ruler->new($x_distance-20, $row_height * $row_count + $y_distance, $chr_height, 0, $self->{c}{$track}[$i]->get_chromosome_length());
176 # $self->{map}->add_ruler($r);
178 $row_count++;
180 $self->{map} = CXGN::Cview::MapImage -> new("", $map_width, $map_height);
182 # get all the chromosomes and add them to the map
184 my $track = 0;
185 foreach my $map ($self->get_maps()) {
186 my @chr_names = $map->get_chromosome_names();
187 for (my $i=0; $i<$map->get_chromosome_count(); $i++) {
189 $self->{c}{$track}[$i] = ($self->get_maps())[$track]->get_chromosome($i+1);
190 $self->{c}{$track}[$i] -> set_vertical_offset($row_height*$i+$y_distance);
191 $self->{c}{$track}[$i] -> set_horizontal_offset($x_distance + $x_distance * ($track));
192 $self->{c}{$track}[$i] -> set_height($chr_height);
193 $self->{c}{$track}[$i] -> set_caption( $chr_names[$i] );
194 $self->{c}{$track}[$i] -> set_width(16);
195 $self->{c}{$track}[$i] -> set_url("/cview/view_chromosome.pl?map_version_id=".($self->get_maps())[$track]->get_id()."&amp;chr_nr=$chr_names[$i]");
197 $self->{c}{$track}[$i] -> set_labels_none();
198 $self->{map}->add_chromosome($self->{c}{$track}[$i]);
200 $track++;
204 # get the connections between the chromosomes
206 my %find = ();
208 for (my $track=0; $track<($self->get_maps()); $track++) {
209 for (my $i =0; $i< ($self->get_maps())[$track]->get_chromosome_count(); $i++) {
210 foreach my $m ($self->{c}{$track}[$i]->get_markers()) {
211 $m->hide_label();
212 # make entry into the find hash and store corrsponding chromosomes and offset
213 # (for drawing connections)
214 # if the map is the reference map ($compare_to_map is false).
216 $find{$m->get_id()}->{$track}->{chr}=$i;
217 $find{$m->get_id()}->{$track}->{offset}=$m->get_offset();
219 # set the marker colors
221 set_marker_color($m, "marker_types");
226 foreach my $f (keys(%find)) {
227 foreach my $t (keys %{$find{$f}}) {
228 my $chr = $find{$f}->{$t}->{chr};
229 my $offset = $find{$f}->{$t}->{offset};
231 if (exists($find{$f}->{$t-1}) || defined($find{$f}->{$t-1})) {
232 my $comp_chr = $find{$f}->{$t-1}->{chr};
233 my $comp_offset = $find{$f}->{$t-1}->{offset};
234 #print STDERR "Found on track $t: Chr=$chr offset=$offset, links to track ".($t-1)." Chr=$comp_chr offset $comp_offset\n";
235 if ($comp_chr) {
236 my $link1 = CXGN::Cview::ChrLink->new($self->{c}{$t}[$chr], $offset, $self->{c}{$t-1}[$comp_chr], $comp_offset);
237 $self->{map}->add_chr_link($link1);
240 if (exists($find{$f}->{$t+1})) {
241 my $comp_chr = $find{$f}->{$t+1}->{chr};
242 my $comp_offset = $find{$f}->{$t+1}->{offset};
243 my $link2 = CXGN::Cview::ChrLink->new($self->{c}{$t}[$chr], $offset, $self->{c}{$t+1}[$comp_chr], $comp_offset);
244 $self->{map}->add_chr_link($link2);
251 $self->get_cache()->set_map_name("viewmap");
252 $self->get_cache()->set_image_data($self->{map}->render_png_string());
253 $self->get_cache()->set_image_map_data($self->{map}->get_image_map("viewmap"));
259 sub get_select_toolbar {
260 my $self = shift;
262 my @names = ("left_map_version_id", "center_map_version_id", "right_map_version_id");
263 my @selects = ();
264 for (my $i=0; $i< 3; $i++) {
265 if ( defined(($self->get_maps())[$i])) {
266 push @selects, CXGN::Cview::Utils::get_maps_select($self->get_dbh(), ($self->get_maps())[$i]->get_id(), $names[$i], $self->get_db_backend());
268 else {
269 push @selects, CXGN::Cview::Utils::get_maps_select($self->get_dbh(), undef, $names[$i], $self->get_db_backend());
273 return join '', map "$_\n", (
274 '<form action="#">',
275 info_table_html(
276 'Left' => $selects[0],
277 'Center' => $selects[1],
278 'Right' => $selects[2],
279 __border => 0,
281 '<input style="width: 10em; line-height: 2; font-size: 120%" type="submit" value="set" />',
282 '</form>',
287 =head2 function error_message_page()
289 Synopsis:
290 Arguments:
291 Returns:
292 Side effects:
293 Description:
295 =cut
297 sub error_message_page {
298 my $self = shift;
300 my $title = page_title_html("Error: No center map defined");
302 print <<HTML;
304 $title
306 A center map needs to be defined for this page to work. Please supply
307 a center_map_version_id as a parameter. If this was the result of a link,
308 please inform SGN about the error.
309 </p>
311 Contact SGN at <a href="mailto:sgn-feedback\@sgn.cornell.edu">sgn-feedback\@sgn.cornell.edu</a>
313 HTML
315 exit();
319 sub clean_up {
320 my $self = shift;