sync with trunk (to r15946)
[bioperl-live.git] / Bio / SeqIO / FTHelper.pm
blob07e2d173ce2954c8c90cc1c4948c3343f75402c0
1 # $Id$
3 # BioPerl module for Bio::SeqIO::FTHelper
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by Ewan Birney <birney@ebi.ac.uk>
9 # Copyright Ewan Birney
11 # You may distribute this module under the same terms as perl itself
13 # POD documentation - main docs before the code
15 =head1 NAME
17 Bio::SeqIO::FTHelper - Helper class for Embl/Genbank feature tables
19 =head1 SYNOPSIS
21 Used by Bio::SeqIO::EMBL,Bio::SeqIO::genbank, and Bio::SeqIO::swiss to
22 help process the Feature Table
24 =head1 DESCRIPTION
26 Represents one particular Feature with the following fields
28 key - the key of the feature
29 loc - the location string of the feature
30 <other fields> - other fields
32 =head1 FEEDBACK
34 =head2 Mailing Lists
36 User feedback is an integral part of the evolution of this and other
37 Bioperl modules. Send your comments and suggestions preferably to one
38 of the Bioperl mailing lists. Your participation is much appreciated.
40 bioperl-l@bioperl.org - General discussion
41 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
43 =head2 Support
45 Please direct usage questions or support issues to the mailing list:
47 L<bioperl-l@bioperl.org>
49 rather than to the module maintainer directly. Many experienced and
50 reponsive experts will be able look at the problem and quickly
51 address it. Please include a thorough description of the problem
52 with code and data examples if at all possible.
54 =head2 Reporting Bugs
56 Report bugs to the Bioperl bug tracking system to help us keep track
57 the bugs and their resolution. Bug reports can be submitted via the web:
59 http://bugzilla.open-bio.org/
61 =head1 AUTHOR - Ewan Birney
63 Email birney@ebi.ac.uk
65 =head1 CONTRIBUTORS
67 Jason Stajich jason@bioperl.org
69 =head1 APPENDIX
71 The rest of the documentation details each of the object
72 methods. Internal methods are usually preceded with a _
74 =cut
77 # Let the code begin...
80 package Bio::SeqIO::FTHelper;
81 use strict;
83 use Bio::SeqFeature::Generic;
84 use Bio::Location::Simple;
85 use Bio::Location::Fuzzy;
86 use Bio::Location::Split;
90 use base qw(Bio::Root::Root);
92 sub new {
93 my ($class, @args) = @_;
95 # no chained new because we make lots and lots of these.
96 my $self = {};
97 bless $self,$class;
98 $self->{'_field'} = {};
99 return $self;
102 =head2 _generic_seqfeature
104 Title : _generic_seqfeature
105 Usage : $fthelper->_generic_seqfeature($annseq, "GenBank")
106 Function: processes fthelper into a generic seqfeature
107 Returns : TRUE on success and otherwise FALSE
108 Args : The Bio::Factory::LocationFactoryI object to use for parsing
109 location strings. The ID (e.g., display_id) of the sequence on which
110 this feature is located, optionally a string indicating the source
111 (GenBank/EMBL/SwissProt)
114 =cut
116 sub _generic_seqfeature {
117 my ($fth, $locfac, $seqid, $source) = @_;
118 my ($sf);
120 # set a default if not specified
121 if(! defined($source)) {
122 $source = "EMBL/GenBank/SwissProt";
125 # initialize feature object
126 $sf = Bio::SeqFeature::Generic->direct_new();
128 # parse location; this may cause an exception, in which case we gently
129 # recover and ignore this feature
132 my $loc;
133 eval {
134 $loc = $locfac->from_string($fth->loc);
137 if(! $loc) {
138 $fth->warn("exception while parsing location line [" . $fth->loc .
139 "] in reading $source, ignoring feature " .
140 $fth->key() . " (seqid=" . $seqid . "): " . $@);
141 return;
144 # set additional location attributes
145 if($seqid && (! $loc->is_remote())) {
146 $loc->seq_id($seqid); # propagates if it is a split location
150 # set attributes of feature
151 $sf->location($loc);
152 $sf->primary_tag($fth->key);
153 $sf->source_tag($source);
154 $sf->seq_id($seqid);
155 foreach my $key ( keys %{$fth->field} ){
156 foreach my $value ( @{$fth->field->{$key}} ) {
157 $sf->add_tag_value($key,$value);
160 return $sf;
164 =head2 from_SeqFeature
166 Title : from_SeqFeature
167 Usage : @fthelperlist = Bio::SeqIO::FTHelper::from_SeqFeature($sf,
168 $context_annseq);
169 Function: constructor of fthelpers from SeqFeatures
171 : The additional annseq argument is to allow the building of FTHelper
172 : lines relevant to particular sequences (ie, when features are spread over
173 : enteries, knowing how to build this)
174 Returns : an array of FThelpers
175 Args : seq features
178 =cut
180 sub from_SeqFeature {
181 my ($sf, $context_annseq) = @_;
182 my @ret;
185 # If this object knows how to make FThelpers, then let it
186 # - this allows us to store *really* weird objects that can write
187 # themselves to the EMBL/GenBank...
190 if ( $sf->can("to_FTHelper") ) {
191 return $sf->to_FTHelper($context_annseq);
194 my $fth = Bio::SeqIO::FTHelper->new();
195 my $key = $sf->primary_tag();
196 my $locstr = $sf->location->to_FTstring;
198 # ES 25/06/01 Commented out this code, Jason to double check
199 #The location FT string for all simple subseqfeatures is already
200 #in the Split location FT string
202 # going into sub features
203 #foreach my $sub ( $sf->sub_SeqFeature() ) {
204 #my @subfth = &Bio::SeqIO::FTHelper::from_SeqFeature($sub);
205 #push(@ret, @subfth);
208 $fth->loc($locstr);
209 $fth->key($key);
210 $fth->field->{'note'} = [];
211 #$sf->source_tag && do { push(@{$fth->field->{'note'}},"source=" . $sf->source_tag ); };
213 ($sf->can('score') && $sf->score) && do { push(@{$fth->field->{'note'}},
214 "score=" . $sf->score ); };
215 ($sf->can('frame') && $sf->frame) && do { push(@{$fth->field->{'note'}},
216 "frame=" . $sf->frame ); };
217 #$sf->strand && do { push(@{$fth->field->{'note'}},"strand=" . $sf->strand ); };
219 foreach my $tag ( $sf->get_all_tags ) {
220 # Tags which begin with underscores are considered
221 # private, and are therefore not printed
222 next if $tag =~ /^_/;
223 if ( !defined $fth->field->{$tag} ) {
224 $fth->field->{$tag} = [];
226 foreach my $val ( $sf->get_tag_values($tag) ) {
227 push(@{$fth->field->{$tag}},$val);
230 push(@ret, $fth);
232 unless (@ret) {
233 $context_annseq->throw("Problem in processing seqfeature $sf - no fthelpers. Error!");
235 foreach my $ft (@ret) {
236 if ( !$ft->isa('Bio::SeqIO::FTHelper') ) {
237 $sf->throw("Problem in processing seqfeature $sf - made a $fth!");
241 return @ret;
245 =head2 key
247 Title : key
248 Usage : $obj->key($newval)
249 Function:
250 Example :
251 Returns : value of key
252 Args : newvalue (optional)
255 =cut
257 sub key {
258 my ($obj, $value) = @_;
259 if ( defined $value ) {
260 $obj->{'key'} = $value;
262 return $obj->{'key'};
266 =head2 loc
268 Title : loc
269 Usage : $obj->loc($newval)
270 Function:
271 Example :
272 Returns : value of loc
273 Args : newvalue (optional)
276 =cut
278 sub loc {
279 my ($obj, $value) = @_;
280 if ( defined $value ) {
281 $obj->{'loc'} = $value;
283 return $obj->{'loc'};
287 =head2 field
289 Title : field
290 Usage :
291 Function:
292 Example :
293 Returns :
294 Args :
297 =cut
299 sub field {
300 my ($self) = @_;
302 return $self->{'_field'};
305 =head2 add_field
307 Title : add_field
308 Usage :
309 Function:
310 Example :
311 Returns :
312 Args :
315 =cut
317 sub add_field {
318 my ($self, $key, $val) = @_;
320 if ( !exists $self->field->{$key} ) {
321 $self->field->{$key} = [];
323 push( @{$self->field->{$key}} , $val);