[Bio] / FigKernelPackages / FigGFF.pm Repository:
ViewVC logotype

Annotation of /FigKernelPackages/FigGFF.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (view) (download) (as text)

1 : olson 1.1 #
2 :     # FIG GFF utilities.
3 :     #
4 :    
5 :     #
6 :     # A GFFWriter handles the generation of GFF files from SEED data structures.
7 :     #
8 :    
9 :    
10 :     package GFFWriter;
11 :    
12 :     use strict;
13 :     use FIG;
14 :    
15 :     use Carp;
16 :     use URI::Escape;
17 :     use Data::Dumper;
18 :    
19 :     sub new
20 :     {
21 :     my($class, $fig, %options) = @_;
22 :    
23 :     my $default_options = {
24 :     escapespace => 0,
25 :     outputfasta => 1,
26 :     linelength => 60,
27 :     };
28 :    
29 :     map { $default_options->{$_} = $options{$_} } keys(%options);
30 :    
31 :     my $self = {
32 :     options => $default_options,
33 :     contig_length_cache => {},
34 :     fig => $fig,
35 :     };
36 :    
37 :     return bless $self, $class;
38 :     }
39 :    
40 :    
41 :     =head1 gff3_for_feature
42 :    
43 :     Returns the GFF3 information for a given feature.
44 :    
45 :     The return is a pair ($contig_data, $fasta_sequences) that can be passed
46 :     into write_gff3().
47 :    
48 :     $contig_data is a hashref mapping a contig name to a list of GFF3 file lines
49 :     for the sequences in that contig.
50 :    
51 :     =cut
52 :    
53 :     sub gff3_for_feature
54 :     {
55 : olson 1.2 my($self, $fid, $user, $user_note) = @_;
56 : olson 1.1
57 :     #
58 :     # Options we need to figure out somehow.
59 :     #
60 :     my $options = $self->{options};
61 :    
62 :     my $escapespace = $options->{escapespace};
63 :     my $outputfasta = $options->{outputfasta};
64 : olson 1.2
65 :     my %outputtype;
66 :     map { $outputtype{$_} = 1 } @{$options->{outputtype}};
67 : olson 1.1
68 :     my $fastasequences = '';
69 :     my $contig_data;
70 :     my $linelength = $options->{linelength};
71 :    
72 : olson 1.3 my $beg = $self->{options}->{beg};
73 :     my $end = $self->{options}->{end};
74 :    
75 : olson 1.1 my $fig = $self->{fig};
76 :    
77 :     #
78 :     # Do this first to make sure that we really have a feature.
79 :     #
80 :     my @location = $fig->feature_location($fid);
81 :     if (@location == 0 or !defined($location[0]))
82 :     {
83 :     warn "No location found for feature $fid\n";
84 :     return ({}, "");
85 :     }
86 :    
87 :     ###########
88 :     #
89 :     # Begin figuring out the column 9 information about notes and aliases and GO terms
90 :     # All the information is temporarily stored in @alias or @note, and at the end is joined
91 :     # into $allnote
92 :     #
93 :     ###########
94 :    
95 :     #
96 :     # the notes for the last column
97 :     #
98 :     my $note;
99 :     #
100 :     # all the aliases we are going to use
101 :     #
102 :     my @alias;
103 :    
104 : olson 1.2 if ($options->{with_assignments})
105 : olson 1.1 {
106 : olson 1.2 my $func = $fig->function_of($fid, $user);
107 :     if ($func)
108 :     {
109 :     push @$note, ("Note=\"" . uri_escape($func) . '"');
110 :     }
111 : olson 1.1 }
112 : olson 1.2
113 :     if ($options->{with_aliases})
114 :     {
115 : olson 1.1 # now find aliases
116 : olson 1.2 foreach my $alias ($fig->feature_aliases($fid))
117 : olson 1.1 {
118 : olson 1.2 if ($alias =~ /^NP/)
119 :     {
120 :     push @$note, "Dbxref=\"NCBI_genpept:$alias\"";
121 :     }
122 :     elsif ($alias =~ /gi\|/)
123 :     {
124 :     $alias =~ s/^gi\|//;
125 :     push @$note, "Dbxref=\"NCBI_gi:$alias\"";
126 :     }
127 :     elsif ($alias =~ /^kegg/i)
128 :     {
129 :     $alias =~ s/kegg\|/KEGG:/i;
130 :     $alias =~ s/^(.*):/$1+/;
131 :     push @$note, "Dbxref=\"$alias\"";
132 :     }
133 :     elsif ($alias =~ /^uni/)
134 :     {
135 :     $alias =~ s/uni\|/UniProt:/;
136 :     # $note = check_go($note, $alias) if ($go);
137 :     push @$note, "Dbxref=\"$alias\"";
138 :     }
139 :     elsif ($alias =~ /^sp\|/)
140 :     {
141 :     $alias =~ s/sp\|/Swiss-Prot:/;
142 :     push @$note, "Dbxref=\"$alias\"";
143 :     }
144 :     else
145 :     {
146 :     # don't know what it is so keep it as an alias
147 :     $alias = uri_escape($alias); # just in case!
148 :     push @alias, $alias;
149 :     }
150 : olson 1.1 }
151 : olson 1.2 }
152 : olson 1.1
153 :     # now just join all the aliases and put them into @$note so we can add it to the array
154 :     if (@alias)
155 :     {
156 :     push @$note, "Alias=\"". join (",", @alias) . '"';
157 :     }
158 : olson 1.2
159 :     #
160 :     # If we have user note passed in, add it.
161 :     #
162 :    
163 :     if ($user_note)
164 :     {
165 :     push @$note, $user_note;
166 :     }
167 : olson 1.1
168 :     # the LAST thing I am going to add as a note is the FIG id so that I can grep it out easily
169 :     push @$note, "Dbxref=\"SEED:$fid\"";
170 :    
171 :     # finally join all the notes into a long string that can be added as column 9
172 :     my $allnotes;
173 :     $allnotes = join ";", @$note;
174 :    
175 :     # do we want to convert '%20' to ' '
176 :     unless ($escapespace)
177 :     {
178 :     $allnotes =~ s/\%20/ /g;
179 :     }
180 :    
181 :     ###########
182 :     #
183 :     # End figuring out the column 9 information about notes and aliases and GO terms
184 :     #
185 :     ###########
186 :    
187 :     #
188 :     # Cache contig lengths.
189 :     #
190 :     my $len = $self->{contig_length_cache};
191 :    
192 :     my $genome = $fig->genome_of($fid);
193 :    
194 :     foreach my $loc (@location)
195 :     {
196 :     $loc =~ /^(.*)\_(\d+)\_(\d+)$/;
197 :     my ($contig, $start, $stop) = ($1, $2, $3);
198 :     my $original_contig=$contig;
199 :    
200 :     #
201 :     # the contig name must be escaped
202 :     #
203 :     $contig = uri_escape($contig);
204 :    
205 :     #my $contig_key = "$genome:$contig";
206 :     my $contig_key = $contig;
207 :    
208 :     unless (defined $len->{$contig})
209 :     {
210 :     $len->{$contig}=$fig->contig_ln($genome, $original_contig);
211 :     }
212 :     my $strand='+';
213 :    
214 :     #
215 :     # These were bounds-checking for dumping all of a genome.
216 :     #
217 :     #next if (defined $beg && ($start < $beg || $stop < $beg));
218 :     #next if (defined $end && ($start > $end || $stop > $end));
219 :    
220 :     if ($start > $stop)
221 :     {
222 :     ($start, $stop, $strand)=($stop, $start, '-');
223 :     }
224 :     elsif ($start == $stop)
225 :     {
226 :     $strand=".";
227 :     }
228 :    
229 :     my $type=$fig->ftype($fid);
230 :    
231 :     if ($type eq "peg")
232 :     {
233 :     # it is a protein coding gene
234 :     # create an artificial id that is just the fid.(\d+) information
235 :     # we will use this to create ids in the form cds.xxx; trn.xxxx; pro.xxx; gen.xxx;
236 :     $fid =~ /\.peg\.(\d+)/;
237 :     my $geneid=$1;
238 :    
239 :     ############## KLUDGE
240 :     #
241 :     # At the moment the outputs for transcript, gene, CDS, and pro are all the same.
242 :     # This is clearly a kludge and wrong, but it will work at the moment
243 :     #
244 :    
245 :     # defined some truncations
246 :     my %trunc=(
247 :     "transcript" => "trn",
248 :     "gene" => "gen",
249 :     "protein" => "pro",
250 :     "cds" => "cds",
251 :     );
252 :    
253 :     # SO terms:
254 :     # transcript: SO:0000673
255 :     # gene: SO:0000704
256 :     # cds: SO:0000316
257 :     # protein: NOT VALID: should be protein_coding_primary_transcript SO:0000120
258 : olson 1.3
259 :     #
260 :     # For now, we will only output CDS features, and include
261 :     # the translation as an attribute (attribuute name is
262 :     # translation_id, value is a key that corresponds to a FASTA
263 :     # section at the end of the file).
264 :     #
265 :    
266 :     my $type = "cds";
267 :    
268 :     my $protein_id = "pro.$geneid";
269 :     my $cds_id = "cds.$geneid";
270 :    
271 :     # we want to store some sequences to be output
272 :     if ($outputfasta)
273 : olson 1.1 {
274 : olson 1.3 my $addseq = $fig->get_translation($fid);
275 :    
276 :     #
277 :     # the chomp is so that we know for sure to add the line back
278 :     #
279 :     $addseq =~ s/(.{$linelength})/$1\n/g;
280 :     chomp($addseq);
281 :     $fastasequences .= ">$protein_id\n$addseq\n";
282 :    
283 :     my $addseq = uc($fig->dna_seq($genome, $fig->feature_location($fid)));
284 :     $addseq =~ s/(.{$linelength})/$1\n/g; chomp($addseq);
285 :    
286 :     $fastasequences .= ">$cds_id\n$addseq\n";
287 :    
288 :     $allnotes .= ";translation_id=$protein_id";
289 :     }
290 :    
291 :     push (@{$contig_data->{$contig_key}},
292 :     (join "\t",
293 :     ($contig, "The SEED", $type, $start, $stop, ".", $strand, ".", "ID=$cds_id;$allnotes")));
294 :     }
295 : olson 1.1 elsif ($type eq "rna")
296 :     {
297 :     $fid =~ /\.rna\.(\d+)/;
298 :     my $geneid=$1;
299 :     #
300 :     # tRNA is a valid SOFA term == SO:0000253
301 :     #
302 :     my ($id, $type)=("rna.$geneid", "tRNA");
303 :     if ($outputfasta)
304 :     {
305 :     my $addseq = $fig->dna_seq($genome, $fig->feature_location($fid));
306 :     $addseq =~ s/(.{$linelength})/$1\n/g; chomp($addseq);
307 :     $fastasequences .= ">$id\n$addseq\n";
308 :     }
309 : olson 1.2 push (@{$contig_data->{$contig_key}}, (join "\t", ($contig, "The SEED", $type, $start, $stop, ".", $strand, ".", "ID=$id;$allnotes")));
310 : olson 1.1 } # end the if type == rna
311 :     else
312 :     {
313 :     die "Don't know what type: |$type| is";
314 :     }
315 :     }
316 :     return ($contig_data, $fastasequences);
317 :     }
318 :    
319 :     =head1 write_gff3
320 :    
321 :     Write a set of gff3 per-contig data and fasta sequence data to a file or filehandle.
322 :    
323 :     $genome is the genome these contigs are a part of.
324 :     $contig_list is a list of contig-data hashes as returned by gff_for_feature.
325 :     $fast_list is a list of fasta data strings.
326 :    
327 :     =cut
328 :    
329 :     sub write_gff3
330 :     {
331 :     my($self, $output, $genome, $contig_list, $fasta_list) = @_;
332 :    
333 :     my $fig = $self->{fig};
334 :    
335 :     my $len = $self->{contig_length_cache};
336 :     my $fh;
337 :    
338 :     my $beg = $self->{options}->{beg};
339 :     my $end = $self->{options}->{end};
340 :    
341 :     my $close_output;
342 :    
343 :     if (ref($output))
344 :     {
345 :     $fh = $output;
346 :     }
347 :     else
348 :     {
349 :     open($fh, ">$output") or confess "Cannot open output '$output': $!";
350 :     $close_output = 1;
351 :     }
352 :    
353 :     #
354 :     # Build a data structure from the list of contigs
355 :     # that has a list of lists of data per contig name.
356 :     # (Do this so we don't copy all of the contig data itself, as it
357 :     # could be quite large).
358 :     #
359 :     my %contigs;
360 :    
361 :     #
362 :     # iterate over the given list of contig hashes.
363 :     #
364 :     for my $chash (@$contig_list)
365 :     {
366 :     #
367 :     # Then for each contig in the individual contig hashes,
368 :     # add the data list to %contigs.
369 :     #
370 :     for my $contig (keys %$chash)
371 :     {
372 :     push(@{$contigs{$contig}}, $chash->{$contig});
373 :     }
374 :     }
375 :    
376 :     foreach my $contig (sort keys %contigs)
377 :     {
378 :     print $fh "##sequence-region\t$contig\t";
379 :     if (defined $beg) {
380 :     print $fh "$beg\t";
381 :     } else {
382 :     print $fh "1\t";
383 :     }
384 :     if (defined $end) {
385 :     print $fh "$end\n";
386 :     } else {
387 :     print $fh "$len->{$contig}\n";
388 :     }
389 :     for my $list (@{$contigs{$contig}})
390 :     {
391 : olson 1.2 print $fh join("\n", @$list), "\n";
392 : olson 1.1 }
393 :     }
394 :    
395 :     print $fh "##FASTA\n";
396 :     # print out the cds and pro if we need them
397 :    
398 :     if ($self->{options}->{outputfasta})
399 :     {
400 :     for my $fastasequences (@$fasta_list)
401 :     {
402 :     print $fh $fastasequences;
403 :     }
404 :     }
405 :    
406 :     my $ll = $self->{options}->{linelength};
407 :     foreach my $contig (sort keys %contigs)
408 :     {
409 :     my $len=$fig->contig_ln($genome, $contig);
410 :     my $dna_seq=$fig->dna_seq($genome, $contig . "_1_". $len);
411 :     if (defined $beg)
412 :     {
413 :     unless (defined $end) {
414 :     $end=$len;
415 :     }
416 :     $dna_seq = substr($dna_seq, $beg, $end);
417 :     }
418 :     elsif (defined $end)
419 :     {
420 :     $beg=1;
421 :     $dna_seq = substr($dna_seq, $beg, $end);
422 :     }
423 :    
424 :     my $contig=uri_escape($contig);
425 :    
426 :     $dna_seq =~ s/(.{$ll})/$1\n/g;
427 :     chomp($dna_seq); # just remove the last \n if there is one
428 :     print $fh ">$contig\n$dna_seq\n";
429 :     }
430 :    
431 :     close($fh) if $close_output;
432 :     }
433 :    
434 : olson 1.2 package GFFParser;
435 :    
436 :     use strict;
437 :     use URI::Escape;
438 :     use Carp;
439 :     use Data::Dumper;
440 :    
441 :     use base qw(Class::Accessor);
442 :    
443 :     __PACKAGE__->mk_accessors(qw(fig current_file));
444 :    
445 :     my $count;
446 :    
447 :    
448 :     #
449 :     # GFF file parser. Creates GFFFiles.
450 :     #
451 :    
452 :     sub new
453 :     {
454 :     my($class, $fig) = @_;
455 :    
456 :     my $self = {
457 :     fig => $fig,
458 :     };
459 :    
460 :     return bless($self, $class);
461 :     }
462 :    
463 :     sub parse
464 :     {
465 :     my($self, $file) = @_;
466 :    
467 :     my($fh, $close_handle);
468 :    
469 :     my $fobj = GFFFile->new($self->fig);
470 :     $self->current_file($fobj);
471 :    
472 :     if (ref($file) ? (ref($file) eq 'GLOB'
473 :     || UNIVERSAL::isa($file, 'GLOB')
474 :     || UNIVERSAL::isa($file, 'IO::Handle'))
475 :     : (ref(\$file) eq 'GLOB'))
476 :     {
477 :     $fh = $file;
478 :     }
479 :     else
480 :     {
481 :     open($fh, "<$file") or confess "Cannot open $file: $!";
482 :     $fobj->filename($file);
483 :     $close_handle = 1;
484 :     }
485 :    
486 :     #
487 :     # Start parsing by verifying this is a gff3 file.
488 :     #
489 :    
490 :     $_ = <$fh>;
491 :    
492 :     if (m,^\#gff-version\t(\S+),)
493 :     {
494 :     if ($1 != 3)
495 :     {
496 :     confess "Invalid GFF File: version is not 3";
497 :     }
498 :     }
499 :    
500 :     #
501 :     # Now parse.
502 :     #
503 :    
504 :     while (<$fh>)
505 :     {
506 :     chomp;
507 :     #
508 :     # Check first for the fasta directive so we can run off and parse that
509 :     # separately.
510 :     #
511 :    
512 :     if (/^>/)
513 :     {
514 :     $self->parse_fasta($fh, $_);
515 :     last;
516 :     }
517 :     elsif (/^\#\#FASTA/)
518 :     {
519 :     print "Got fasta directive\n";
520 :     $_ = <$fh>;
521 :     chomp;
522 :     $self->parse_fasta($fh, $_);
523 :     last;
524 :     }
525 :     elsif (/^\#\s/)
526 :     {
527 :     #
528 :     # comment.
529 :     #
530 :     next;
531 :     }
532 :     elsif (/^\#\#(\S+)(?:\t(.*))?/)
533 :     {
534 :     #
535 :     # GFF3 directive.
536 :     #
537 :    
538 :     $self->parse_gff3_directive($1, $2);
539 :    
540 :     }
541 :     elsif (/^\#(\S+)(?:\t(.*))?/)
542 :     {
543 :     #
544 :     # Directive.
545 :     #
546 :    
547 :     if ($1 eq "seed")
548 :     {
549 :     $self->parse_seed_directive($2);
550 :     }
551 :     else
552 :     {
553 :     $self->parse_local_directive($1, $2);
554 :     }
555 :    
556 :     }
557 :     elsif (/^([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)$/)
558 :     {
559 :     $self->parse_feature($1, $2, $3, $4, $5, $6, $7, $8, $9);
560 :     }
561 :     else
562 :     {
563 :     die "bad line: '$_'\n";
564 :     }
565 :     }
566 :    
567 :     return $fobj;
568 :     }
569 :    
570 :     sub parse_gff3_directive
571 :     {
572 :     my($self, $directive, $rest) = @_;
573 :    
574 :     print "Have gff3 directive '$directive' rest='$rest'\n";
575 :     }
576 :    
577 :     sub parse_seed_directive
578 :     {
579 :     my($self, $rest) = @_;
580 :    
581 :     my($verb, @rest) = split(/\t/, $rest);
582 :    
583 :     if ($verb eq "anno_start")
584 :     {
585 :     $self->current_file->anno_start($rest[0]);
586 :     }
587 :     elsif ($verb eq "anno_end")
588 :     {
589 :     $self->current_file->anno_start($rest[0]);
590 :     }
591 :     elsif ($verb eq "genome_md5")
592 :     {
593 :     $self->current_file->set_genome_checksum(@rest[0,1]);
594 :     }
595 :     elsif ($verb eq "contig_md5")
596 :     {
597 :     $self->current_file->set_contig_checksum(@rest[0,1,2]);
598 :     }
599 :     }
600 :    
601 :     sub parse_local_directive
602 :     {
603 :     my($self, $directive, $rest) = @_;
604 :    
605 :     print "Have local directive '$directive' rest='$rest'\n";
606 :     }
607 :    
608 :     sub parse_feature
609 :     {
610 :     my($self, $seqid, $source, $type, $start, $end, $score, $strand, $phase, $attributes) = @_;
611 :    
612 :     #print "data: seqid=$seqid source=$source type=$type start=$start end=$end\n";
613 :     #print " score=$score strand=$strand phase=$phase\n";
614 :     #print " $attributes\n";
615 :    
616 :     #
617 :     # Parse this feature, creating a GFFFeature object for it.
618 :     #
619 :    
620 :     my $feature = GFFFeature->new($self->fig);
621 :    
622 :     $feature->seqid($seqid);
623 :     $feature->source($source);
624 :     $feature->type($type);
625 :     $feature->start($start);
626 :     $feature->end($end);
627 :     $feature->score($score);
628 :     $feature->strand($strand);
629 :     $feature->phase($phase);
630 :    
631 :     my $athash = {};
632 :    
633 :     for my $attr (split(/;/, $attributes))
634 :     {
635 :     my($name, $value) = split(/=/, $attr);
636 :    
637 :     #
638 :     # Handle the GFF3-defined attributes
639 :     #
640 :    
641 :     my @values = split(/,/, $value);
642 :    
643 :     if (@values > 1)
644 :     {
645 :     my $vlist = [];
646 :     for my $value (@values)
647 :     {
648 :     $value = uri_unescape($value);
649 :     push(@$vlist, $value);
650 :     }
651 :     $value = $vlist;
652 :     }
653 :    
654 :     $athash->{$name} = $value;
655 :    
656 :     if ($GFFFeature::GFF_Tags{$name})
657 :     {
658 :     $feature->set($name, $value);
659 :     }
660 :    
661 :     }
662 :     $feature->attributes($athash);
663 :    
664 :     $self->current_file->add_feature($feature);
665 :     }
666 :    
667 :     #
668 :     # We come in here with the first line of the fasta already read
669 :     # in order to support the backward-compatiblity syntax that
670 :     # lets a file skip the ##FASTA directive if it wishes.
671 :     #
672 :     sub parse_fasta
673 :     {
674 :     my($self, $fh, $first_line) = @_;
675 :     my($cur, $cur_id);
676 :    
677 :     for ($_ = $first_line; $_; $_ = <$fh>, chomp)
678 :     {
679 :     if (/^>\s*(\S+)/)
680 :     {
681 :     if ($cur)
682 :     {
683 :     $self->handle_fasta_block($cur_id, $cur);
684 :     }
685 :    
686 :     $cur = '';
687 :     $cur_id = $1;
688 :     }
689 :     else
690 :     {
691 :     s/^\s*$//;
692 :     s/\s*$//;
693 :     if (/\s/)
694 :     {
695 :     die "FASTA data had embedded space: $_\n";
696 :     }
697 :     $cur .= $_;
698 :     }
699 :     }
700 :     if ($cur)
701 :     {
702 :     $self->handle_fasta_block($cur_id, $cur);
703 :     }
704 :     }
705 :    
706 :     sub handle_fasta_block
707 :     {
708 :     my($self, $id, $data) = @_;
709 :    
710 :     my $len = length($data);
711 :     $self->current_file->set_fasta_data($id, $data);
712 :     }
713 :    
714 :     package GFFFeature;
715 :    
716 :     use strict;
717 :     use base qw(Class::Accessor);
718 :    
719 :     our @GFF_Tags = qw(ID Name Alias Parent Target Gap Note Dbxref Ontology_term);
720 :     our %GFF_Tags;
721 :    
722 :     map { $GFF_Tags{$_} = 1 } @GFF_Tags;
723 :    
724 :     __PACKAGE__->mk_accessors(qw(fig seqid source type start end score strand phase attributes),
725 :     @GFF_Tags);
726 :    
727 :    
728 :     sub new
729 :     {
730 :     my($class, $fig) = @_;
731 :    
732 :     my $self = {
733 :     fig => $fig,
734 :     };
735 :    
736 :     return bless($self, $class);
737 :     }
738 :    
739 :     package GFFFile;
740 :    
741 :     use strict;
742 :     use base qw(Class::Accessor);
743 :    
744 :     __PACKAGE__->mk_accessors(qw(fig filename features feature_index anno_start anno_end));
745 :    
746 :     #
747 :     # Package to hold the contents of a GFF file, and to hold the code
748 :     # for mapping its contents to the local SEED.
749 :     #
750 :     # Created by GFFParser->parse.
751 :     #
752 :    
753 :     sub new
754 :     {
755 :     my($class, $fig) = @_;
756 :    
757 :     my $self = {
758 :     fig => $fig,
759 :     features => [],
760 :     feature_index => {},
761 :     };
762 :     return bless($self, $class);
763 :     }
764 :    
765 :     sub add_feature
766 :     {
767 :     my($self, $feature) = @_;
768 :    
769 :     push(@{$self->features}, $feature);
770 :     $self->feature_index->{$feature->ID} = $feature;
771 :     }
772 :    
773 :     sub set_genome_checksum
774 :     {
775 :     my($self, $genome, $md5sum) = @_;
776 :     $self->{genome_checksum}->{$genome} = $md5sum;
777 :     }
778 :    
779 :     sub set_contig_checksum
780 :     {
781 :     my($self, $genome, $contig, $md5sum) = @_;
782 :     $self->{contig_checksum}->{$genome}->{$contig} = $md5sum;
783 :     }
784 :    
785 :     sub set_fasta_data
786 :     {
787 :     my($self, $id, $data) = @_;
788 :    
789 :     $self->{fasta_data}->{$id} = $data;
790 :     }
791 :    
792 :    
793 : olson 1.1 1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3