maint: restructure to use Dist::Zilla
[bioperl-live.git] / lib / Bio / SeqFeature / FeaturePair.pm
blob2a39489000732930a6e96bd74d2b900faad8b8f5
2 # BioPerl module for Bio::SeqFeature::FeaturePair
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Ewan Birney <birney@sanger.ac.uk>
8 # Copyright Ewan Birney
10 # You may distribute this module under the same terms as perl itself
12 # POD documentation - main docs before the code
14 =head1 NAME
16 Bio::SeqFeature::FeaturePair - hold pair feature information e.g. blast hits
18 =head1 SYNOPSIS
20 my $feat = Bio::SeqFeature::FeaturePair->new(
21 -feature1 => $f1,
22 -feature2 => $f2,
25 # Bio::SeqFeatureI methods can be used
27 my $start = $feat->start;
28 my $end = $feat->end;
30 # Bio::FeaturePair methods can be used
31 my $hstart = $feat->hstart;
32 my $hend = $feat->hend;
34 my $feature1 = $feat->feature1; # returns feature1 object
36 =head1 DESCRIPTION
38 A sequence feature object where the feature is itself a feature on
39 another sequence - e.g. a blast hit where residues 1-40 of a protein
40 sequence SW:HBA_HUMAN has hit to bases 100 - 220 on a genomic sequence
41 HS120G22. The genomic sequence coordinates are used to create one
42 sequence feature $f1 and the protein coordinates are used to create
43 feature $f2. A FeaturePair object can then be made
45 my $fp = Bio::SeqFeature::FeaturePair->new(
46 -feature1 => $f1, # genomic
47 -feature2 => $f2, # protein
50 This object can be used as a standard Bio::SeqFeatureI in which case
52 my $gstart = $fp->start # returns start coord on feature1 - genomic seq.
53 my $gend = $fp->end # returns end coord on feature1.
55 In general standard Bio::SeqFeatureI method calls return information
56 in feature1.
58 Data in the feature 2 object are generally obtained using the standard
59 methods prefixed by h (for hit!)
61 my $pstart = $fp->hstart # returns start coord on feature2 = protein seq.
62 my $pend = $fp->hend # returns end coord on feature2.
64 If you wish to swap feature1 and feature2 around :
66 $feat->invert
68 so...
70 $feat->start # etc. returns data in $feature2 object
73 No sub_SeqFeatures or tags can be stored in this object directly. Any
74 features or tags are expected to be stored in the contained objects
75 feature1, and feature2.
77 =head1 CONTACT
79 Ewan Birney E<lt>birney@sanger.ac.ukE<gt>
81 =head1 APPENDIX
83 The rest of the documentation details each of the object
84 methods. Internal methods are usually preceded with a _
86 =cut
89 # Let the code begin...
92 package Bio::SeqFeature::FeaturePair;
93 use vars qw($AUTOLOAD);
94 use strict;
96 use Bio::SeqFeatureI;
97 use Bio::Factory::ObjectFactory;
99 use base qw(Bio::SeqFeature::Generic);
101 =head2 new
103 Title : new
104 Usage :
105 Function: Constructor for this module. Accepts the following parameters:
107 -feature1 Bio::SeqFeatureI-compliant object
108 -feature2 Bio::SeqFeatureI-compliant object
109 -feature_factory Bio::Factory::ObjectFactoryI compliant
110 object to be used when feature1 and/or feature2
111 are accessed without explicitly set before. This
112 is mostly useful for derived classes who want to
113 set their preferred class for feature objects.
115 Example :
116 Returns :
117 Args : see above
120 =cut
122 sub new {
123 my ($class, @args) = @_;
126 # We've got a certain problem here that somewhat relates to chicken and
127 # eggs. The problem is, we override a lot of SeqFeatureI methods here
128 # to delegate them to either feature1 or feature2. If we pass along
129 # those attributes right away, we need feature1 or feature2 or the feature
130 # factory in place, or there is no way around the dreaded default, which
131 # is ugly too (as it necessitates subsequent copying if you wanted a
132 # different feature object class).
134 # So I decided to go with the lesser of two evils here: we need to assume
135 # here that we can set all attributes through set_attributes(), which we
136 # assume is no different from setting them through the constructor. This
137 # gives us a window to set the feature objects and the factory, such that
138 # any derived class doesn't have to worry about this any more.
140 # I'm happy to hear a better solution, but I think this one isn't so bad.
142 my $self = $class->SUPER::new();
143 my ($feature1,$feature2,$featfact) =
144 $self->_rearrange([qw( FEATURE1
145 FEATURE2
146 FEATURE_FACTORY )],@args);
148 $self->_register_for_cleanup(\&cleanup_fp);
149 # initialize the feature object factory if not provided
150 if(! $featfact) {
151 $featfact = Bio::Factory::ObjectFactory->new(
152 -type => "Bio::SeqFeature::Generic",
153 -interface => "Bio::SeqFeatureI"
156 $self->feature_factory($featfact);
157 # Store the features in the object
158 $feature1 && $self->feature1($feature1);
159 $feature2 && $self->feature2($feature2);
161 # OK. Now we're setup to store all the attributes, and they'll go right
162 # away into the right objects.
163 $self->set_attributes(@args);
165 # done - we hope
166 return $self;
169 =head2 feature1
171 Title : feature1
172 Usage : $f = $featpair->feature1
173 $featpair->feature1($feature)
174 Function: Get/set for the query feature
175 Returns : Bio::SeqFeatureI
176 Args : Bio::SeqFeatureI
179 =cut
181 sub feature1 {
182 my ($self,$arg) = @_;
183 if ( defined($arg) || !defined $self->{'feature1'} ) {
184 $self->throw("internal error: feature factory not set!")
185 unless $self->feature_factory;
186 $arg = $self->feature_factory->create_object() unless( defined $arg);
187 $self->throw("Argument [$arg] must be a Bio::SeqFeatureI")
188 unless (ref($arg) && $arg->isa("Bio::SeqFeatureI"));
189 $self->{'feature1'} = $arg;
191 return $self->{'feature1'};
194 =head2 feature2
196 Title : feature2
197 Usage : $f = $featpair->feature2
198 $featpair->feature2($feature)
199 Function: Get/set for the hit feature
200 Returns : Bio::SeqFeatureI
201 Args : Bio::SeqFeatureI
204 =cut
206 sub feature2 {
207 my ($self,$arg) = @_;
209 if ( defined($arg) || ! defined $self->{'feature2'}) {
210 $self->throw("internal error: feature factory not set!")
211 unless $self->feature_factory;
212 $arg = $self->feature_factory->create_object() unless( defined $arg);
213 $self->throw("Argument [$arg] must be a Bio::SeqFeatureI")
214 unless (ref($arg) && $arg->isa("Bio::SeqFeatureI"));
215 $self->{'feature2'} = $arg;
217 return $self->{'feature2'};
220 =head2 start
222 Title : start
223 Usage : $start = $featpair->start
224 $featpair->start(20)
225 Function: Get/set on the start coordinate of feature1
226 Returns : integer
227 Args : [optional] beginning of feature
229 =cut
231 sub start {
232 return shift->feature1->start(@_);
235 =head2 end
237 Title : end
238 Usage : $end = $featpair->end
239 $featpair->end($end)
240 Function: get/set on the end coordinate of feature1
241 Returns : integer
242 Args : [optional] ending point of feature
245 =cut
247 sub end {
248 return shift->feature1->end(@_);
251 =head2 strand
253 Title : strand
254 Usage : $strand = $feat->strand()
255 $feat->strand($strand)
256 Function: get/set on strand information, being 1,-1 or 0
257 Returns : -1,1 or 0
258 Args : [optional] strand information to set
261 =cut
263 sub strand {
264 return shift->feature1->strand(@_);
267 =head2 location
269 Title : location
270 Usage : $location = $featpair->location
271 $featpair->location($location)
272 Function: Get/set location object (using feature1)
273 Returns : Bio::LocationI object
274 Args : [optional] LocationI to store
276 =cut
278 sub location {
279 return shift->feature1->location(@_);
282 =head2 score
284 Title : score
285 Usage : $score = $feat->score()
286 $feat->score($score)
287 Function: get/set on score information
288 Returns : float
289 Args : none if get, the new value if set
292 =cut
294 sub score {
295 return shift->feature1->score(@_);
298 =head2 frame
300 Title : frame
301 Usage : $frame = $feat->frame()
302 $feat->frame($frame)
303 Function: get/set on frame information
304 Returns : 0,1,2
305 Args : none if get, the new value if set
308 =cut
310 sub frame {
311 return shift->feature1->frame(@_);
314 =head2 primary_tag
316 Title : primary_tag
317 Usage : $ptag = $featpair->primary_tag
318 Function: get/set on the primary_tag of feature1
319 Returns : 0,1,2
320 Args : none if get, the new value if set
323 =cut
325 sub primary_tag {
326 return shift->feature1->primary_tag(@_);
329 =head2 source_tag
331 Title : source_tag
332 Usage : $tag = $feat->source_tag()
333 $feat->source_tag('genscan');
334 Function: Returns the source tag for a feature,
335 eg, 'genscan'
336 Returns : a string
337 Args : none
340 =cut
342 sub source_tag {
343 return shift->feature1->source_tag(@_);
346 =head2 seqname
348 Title : seqname
349 Usage : $obj->seq_id($newval)
350 Function: There are many cases when you make a feature that you
351 do know the sequence name, but do not know its actual
352 sequence. This is an attribute such that you can store
353 the seqname.
355 This attribute should *not* be used in GFF dumping, as
356 that should come from the collection in which the seq
357 feature was found.
358 Returns : value of seqname
359 Args : newvalue (optional)
362 =cut
364 sub seq_id {
365 return shift->feature1->seq_id(@_);
368 =head2 hseqname
370 Title : hseqname
371 Usage : $featpair->hseqname($newval)
372 Function: Get/set method for the name of
373 feature2.
374 Returns : value of $feature2->seq_id
375 Args : newvalue (optional)
378 =cut
380 sub hseq_id {
381 return shift->feature2->seq_id(@_);
385 =head2 hstart
387 Title : hstart
388 Usage : $start = $featpair->hstart
389 $featpair->hstart(20)
390 Function: Get/set on the start coordinate of feature2
391 Returns : integer
392 Args : none
394 =cut
396 sub hstart {
397 return shift->feature2->start(@_);
400 =head2 hend
402 Title : hend
403 Usage : $end = $featpair->hend
404 $featpair->hend($end)
405 Function: get/set on the end coordinate of feature2
406 Returns : integer
407 Args : none
410 =cut
412 sub hend {
413 return shift->feature2->end(@_);
417 =head2 hstrand
419 Title : hstrand
420 Usage : $strand = $feat->strand()
421 $feat->strand($strand)
422 Function: get/set on strand information, being 1,-1 or 0
423 Returns : -1,1 or 0
424 Args : none
427 =cut
429 sub hstrand {
430 return shift->feature2->strand(@_);
433 =head2 hscore
435 Title : hscore
436 Usage : $score = $feat->score()
437 $feat->score($score)
438 Function: get/set on score information
439 Returns : float
440 Args : none if get, the new value if set
443 =cut
445 sub hscore {
446 return shift->feature2->score(@_);
449 =head2 hframe
451 Title : hframe
452 Usage : $frame = $feat->frame()
453 $feat->frame($frame)
454 Function: get/set on frame information
455 Returns : 0,1,2
456 Args : none if get, the new value if set
459 =cut
461 sub hframe {
462 return shift->feature2->frame(@_);
465 =head2 hprimary_tag
467 Title : hprimary_tag
468 Usage : $ptag = $featpair->hprimary_tag
469 Function: Get/set on the primary_tag of feature2
470 Returns : 0,1,2
471 Args : none if get, the new value if set
474 =cut
476 sub hprimary_tag {
477 return shift->feature2->primary_tag(@_);
480 =head2 hsource_tag
482 Title : hsource_tag
483 Usage : $tag = $feat->hsource_tag()
484 $feat->source_tag('genscan');
485 Function: Returns the source tag for a feature,
486 eg, 'genscan'
487 Returns : a string
488 Args : none
491 =cut
493 sub hsource_tag {
494 return shift->feature2->source_tag(@_);
497 =head2 invert
499 Title : invert
500 Usage : $tag = $feat->invert
501 Function: Swaps feature1 and feature2 around
502 Returns : Nothing
503 Args : none
506 =cut
508 sub invert {
509 my ($self) = @_;
511 my $tmp = $self->feature1;
513 $self->feature1($self->feature2);
514 $self->feature2($tmp);
515 return 1;
518 =head2 feature_factory
520 Title : feature_factory
521 Usage : $obj->feature_factory($newval)
522 Function: Get/set the feature object factory for this feature pair.
524 The feature object factory will be used to create a feature
525 object if feature1() or feature2() is called in get mode
526 without having been set before.
528 The default is an instance of Bio::Factory::ObjectFactory
529 and hence allows the type to be changed dynamically at any
530 time.
532 Example :
533 Returns : The feature object factory in use (a
534 Bio::Factory::ObjectFactoryI compliant object)
535 Args : on set, a Bio::Factory::ObjectFactoryI compliant object
538 =cut
540 sub feature_factory {
541 my $self = shift;
543 return $self->{'feature_factory'} = shift if @_;
544 return $self->{'feature_factory'};
547 #################################################################
548 # aliases for backwards compatibility #
549 #################################################################
551 # seqname() is already aliased in Generic.pm, and we overwrite seq_id
553 sub hseqname {
554 my $self = shift;
555 $self->warn("SeqFeatureI::seqname() is deprecated. Please use seq_id() instead.");
556 return $self->hseq_id(@_);
559 sub cleanup_fp {
560 my $self = shift;
561 $self->{'feature1'} = $self->{'feature2'} = undef;