moving stuff around
[cview.git] / lib / CXGN / Cview / VectorViewer.pm
blob867194ed0b296b476679b68bd81211d5c572b4f9
2 =head1 NAME
4 CXGN::Cview::VectorViewer - a class to view and manipulate vectors
6 =head1 DESCRIPTION
8 This class implements a viewer/editor for circular vector sequences.
10 It can either use a genbank record as an input, or its native data format. It can also detect restriction sites in the sequence.
12 A figure is produced that represents the vector.
14 The native format contains a type column (containing either "FEATURE", "NAME", "SEQUENCE" etc.) and has the following comma delimited columns for the type FEATURE:
16 FEATURE
17 name
18 start coord
19 end coord
20 orientation
21 color
23 The columns for the type NAME:
25 NAME
26 the_name
28 Columns for type SEQUENCE:
30 SEQUENCE
31 the_sequence
36 =head1 AUTHOR
38 Lukas Mueller <lam87@cornell.edu>
40 =head1 METHODS
42 This class implements the following methods:
44 =cut
46 use strict;
48 package CXGN::Cview::VectorViewer;
50 use Bio::SeqIO;
51 use Bio::Restriction::Analysis;
53 use CXGN::Cview::MapImage;
54 use CXGN::Cview::Chromosome::Vector;
55 use CXGN::Cview::Marker::VectorFeature;
57 =head2 new
59 Usage: $vv = CXGN::Cview::VectorViewer->
60 new($map_name, $map_width, $map_height);
61 Desc: creates a new vector viewer object
62 Args: a map name, image width, image height
63 Side Effects:
64 Example:
66 =cut
68 sub new {
69 my $class = shift;
70 my $name = shift;
71 my $width = shift;
72 my $height = shift;
73 my $self = bless {}, $class;
75 $self->{map_image} = CXGN::Cview::MapImage->new($name, $width, $height);
77 return $self;
82 =head2 parse_native
84 Usage: $vv->parse_native(@commands)
85 Desc: parses the native commands given in
86 the lines of the list @commands
87 Ret: nothing
88 Args: a list of lines containing the commands
89 Side Effects: stores the commands using set_commands_ref()
90 Example:
92 =cut
94 sub parse_native {
95 my $self = shift;
96 my @input = @_;
98 my @commands = ();
100 foreach my $line (@input) {
101 chomp($line);
102 $line =~ s/\r//g;
103 my @tokens = split /\s*,\s*/, $line;
105 if (!$tokens[0]) { next(); }
106 push @commands, \@tokens;
108 if ($tokens[0] eq "SEQUENCE") { $self->set_sequence($tokens[1]); }
109 if ($tokens[0] eq "LENGTH") { $self->set_seq_length($tokens[1]); }
111 $self->set_commands_ref(\@commands);
117 =head2 parse_genbank
119 Usage: $vv->parse_genbank($fh)
120 Desc: parses the genbank file at $fh.
121 Ret:
122 Args:
123 Side Effects: modifies the internal drawing commands.
124 Example:
126 =cut
128 sub parse_genbank {
129 my $self = shift;
130 my $fh = shift;
132 my $sio = Bio::SeqIO->new( -fh => $fh, -format=>'genbank');
133 my $s = $sio->next_seq();
134 my @commands = ();
135 my @features = $s -> get_SeqFeatures();
136 foreach my $f (@features) {
137 my $dir = "F";
138 if ($f->strand() != 1) { $dir = "R"; }
139 push @commands, [ "FEATURE", $f->primary_tag(), $f->start(), $f->end(), $dir ];
141 $self->set_sequence($s->seq());
142 push @commands, [ "SEQUENCE", $self->get_sequence() ];
144 $self->set_commands_ref(\@commands);
149 =head2 accessors get_commands_ref, set_commands_ref
151 Usage: $c_ref = $vv -> get_commands_ref();
152 Desc: set/get the native drawing commands
153 as a listref.
154 Property: the commands that are used to draw the vector.
156 =cut
158 sub get_commands_ref {
159 my $self = shift;
160 return $self->{commands};
163 sub set_commands_ref {
164 my $self = shift;
165 $self->{commands} = shift;
168 =head2 add_command
170 Usage:
171 Desc:
172 Ret:
173 Args:
174 Side Effects:
175 Example:
177 =cut
179 sub add_command {
180 my $self = shift;
181 my @tokens = @_;
183 if (!$tokens[0]) { return; }
185 if ($tokens[0] eq "SEQUENCE") { $self->set_sequence($tokens[1]); }
186 if ($tokens[0] eq "LENGTH") { $self->set_seq_len($tokens[1]); }
188 push @{$self->{commands}}, \@tokens;
193 =head2 accessors get_seq_length, set_seq_length
195 Usage:
196 Desc:
197 Property
198 Side Effects:
199 Example:
201 =cut
203 sub get_seq_length {
204 my $self = shift;
205 return $self->{seq_length};
208 sub set_seq_length {
209 my $self = shift;
210 $self->{seq_length} = shift;
213 =head2 accessors get_sequence, set_sequence
215 Usage:
216 Desc:
217 Property
218 Side Effects:
219 Example:
221 =cut
223 sub get_sequence {
224 my $self = shift;
225 return $self->{sequence};
228 sub set_sequence {
229 my $self = shift;
230 $self->{sequence} = shift;
233 =head2 restriction_analysis
235 Usage: my $vv->restriction_analysis($ra_type)
236 Desc: performs the restriction analysis on the sequence.
237 $ra_type can be any of the following:
238 "all": all enzymes are shown. Usually overwhelming.
239 "unique": the restriction enzymes that cut the sequence
240 only once are shown.
241 "popular6bp": Popular 6bp restriction enzymes are shown
242 "popular4bp": Popular 4bp restriction enzymes are shown
243 Ret:
244 Args:
245 Side Effects: adds the restriction enzymes found to the drawing
246 commands.
247 Example:
249 =cut
251 sub restriction_analysis {
252 my $self = shift;
253 my $ra_type = shift;
255 my $seq = Bio::Seq->new( -seq=>$self->get_sequence());
256 $seq->is_circular(1);
257 if (!$seq->is_circular()) { die "It is not circular!"; }
258 my $ra = Bio::Restriction::Analysis->new($seq);
259 my $cutters;
260 if ($ra_type eq "unique") {
261 $cutters = $ra->unique_cutters();
263 else {
264 $cutters = $ra->cutters();
266 foreach my $c ($cutters->each_enzyme()) {
267 my $enzyme = $c->name();
268 if ($ra_type eq "popular6bp") {
269 if (!(grep /^$enzyme$/, ($self->popular_6bp_enzymes()))) {
270 next();
273 if ($ra_type eq "popular4bp") {
274 if (!(grep /^$enzyme$/, ($self->popular_4bp_enzymes()))) {
275 next();
279 my @fragments = $ra ->fragment_maps($c->name());
280 foreach my $f (@fragments) {
281 $self->add_command( "FEATURE", $c->name(), $f->{start}, $f->{end}, "F", "gray");
288 =head2 generate_image
290 Usage: $vv->generate_image()
291 Desc: generates the png and html map for the vector
292 Ret: returns the html to display the image and
293 the image map.
294 Args: none
295 Side Effects: none
296 Example: none
298 =cut
300 sub generate_image {
301 my $self = shift;
303 my $vh = CXGN::VHost->new();
305 my $cache = CXGN::Tools::WebImageCache->new();
306 $cache->set_key("abc");
307 $cache->set_force(1);
308 $cache->set_expiration_time(86400); # seconds, this would be a day.
309 $cache->set_map_name("map_name"); # what's in the <map name='map_name' tag.
310 $cache->set_temp_dir($vh->get_conf("tempfiles_subdir")."/cview");
311 $cache->set_basedir($vh->get_conf("basepath"));
313 my %color = ( red => [ 255, 0, 0], blue => [ 0, 0, 255], green=> [0, 255, 0], gray=>[100, 100, 100], yellow=>[255, 255, 0]);
314 my $img_data;
315 if (! $cache->is_valid()) {
317 my ($img_data, $img_map_data) = $self->render();
320 $cache->set_image_data($img_data);
321 $cache->set_image_map_data($img_map_data);
324 my $image_html = $cache->get_image_html();
325 return $image_html;
328 =head2 render
330 Usage: $vv->render()
331 Desc: renders the vector image on a GD::Image
332 Ret:
333 Args:
334 Side Effects:
335 Example:
337 =cut
339 sub render {
340 my $self = shift;
342 my $image_width = $self->{map_image}->get_width();
343 my $image_height = $self->{map_image}->get_height();
345 my $vector = CXGN::Cview::Chromosome::Vector->new(0, $image_height/3, $image_width/2, $image_height/2);
347 $vector->set_width(20);
348 $vector->set_height($image_height/2);
349 $vector->set_X($image_width/2);
350 $vector->set_Y($image_height/2);
351 $vector->set_length(length($self->get_sequence()));
353 my $identifier = 1;
355 foreach my $c (@{$self->get_commands_ref()}) {
356 if ($c->[0] eq "NAME") { $vector->set_name($c->[1]); next(); }
357 if ($c->[0] ne "FEATURE") { next(); }
358 my $marker = CXGN::Cview::Marker::VectorFeature->new($vector);
359 #die " Now adding a marker...";
360 $marker->set_range_coords($c->[2], $c->[3]);
361 my $label = $c->[1] . " (".$c->[2]."-".$c->[3]." ".$c->[4].")" ;
362 if (!$marker->has_range()) { $label = $c->[1]." (".$c->[2].")"; }
363 $marker->get_label()->set_name($label);
364 $marker->set_name($identifier);
365 if ($c->[4] !~ /R|F/i) { $c->[4]="F"; }
366 $marker->set_orientation( $c->[4]);
367 if (!$c->[5]) {
368 if ($marker->has_range()) { $c->[5] = "red"; }
369 else { $c->[5] = "gray"; }
372 $marker->set_color(@{$self->get_color($c->[5])});
373 $marker->get_label()->set_text_color(@{$self->get_color($c->[5])});
374 $marker->get_label()->set_line_color(@{$self->get_color($c->[5])});
375 $marker->get_label()->set_url("");
376 if ($c->[6] eq "hilite") { $marker->get_label()->set_hilited(1); }
377 $vector->add_marker($marker);
378 $vector->set_caption($self->{map_image}->get_name());
379 $identifier++;
382 $self->{map_image}->add_chromosome($vector);
384 $vector->layout();
386 my $img_data = $self->{map_image}->render_png_string();
387 my $img_map_data = $self->{map_image}->get_image_map();
389 return ($img_data, $img_map_data);
392 =head2 popular_6bp_enzymes
394 Usage: my @enzymes = $vv->popular_6bp_enzymes()
395 Desc: returns a list of popular 6bp enzymes
396 Ret:
397 Args:
398 Side Effects:
399 Example:
401 =cut
403 sub popular_6bp_enzymes {
404 return qw | ClaI EcoRI EcoRV SmaI SmaIII HindIII BamHI KpnI SalI ScaI SphI PstI NotI XbaI XhoI SacI |;
407 =head2 popular_4bp_enzymes
409 Usage: my @enzymes = $vv->popular_4bp_enzymes()
410 Desc: returns a list of popular 4bp enzymes
411 Ret:
412 Args:
413 Side Effects:
414 Example:
416 =cut
418 sub popular_4bp_enzymes {
419 return qw | MboI AluI HaeIII Sau3A TaqI |;
423 =head2 get_color
425 Usage:
426 Desc:
427 Ret:
428 Args:
429 Side Effects:
430 Example:
432 =cut
434 sub get_color {
435 my $self = shift;
436 my $color = shift;
437 my %color = ( red => [ 255, 0, 0], blue => [ 0, 0, 255], green=> [0, 255, 0], gray=>[100, 100, 100], yellow=>[255, 255, 0]);
438 return $color{$color};
444 return 1;