maint: remove Travis stuff which has been replaced with Github actions (#325)
[bioperl-live.git] / lib / Bio / SeqFeature / FeaturePair.pm
blob26fc618023f6e001e9b7427a9c34fa80bef1950e
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;
94 use vars qw($AUTOLOAD);
95 use strict;
97 use Bio::SeqFeatureI;
98 use Bio::Factory::ObjectFactory;
100 use base qw(Bio::SeqFeature::Generic);
102 =head2 new
104 Title : new
105 Usage :
106 Function: Constructor for this module. Accepts the following parameters:
108 -feature1 Bio::SeqFeatureI-compliant object
109 -feature2 Bio::SeqFeatureI-compliant object
110 -feature_factory Bio::Factory::ObjectFactoryI compliant
111 object to be used when feature1 and/or feature2
112 are accessed without explicitly set before. This
113 is mostly useful for derived classes who want to
114 set their preferred class for feature objects.
116 Example :
117 Returns :
118 Args : see above
121 =cut
123 sub new {
124 my ($class, @args) = @_;
127 # We've got a certain problem here that somewhat relates to chicken and
128 # eggs. The problem is, we override a lot of SeqFeatureI methods here
129 # to delegate them to either feature1 or feature2. If we pass along
130 # those attributes right away, we need feature1 or feature2 or the feature
131 # factory in place, or there is no way around the dreaded default, which
132 # is ugly too (as it necessitates subsequent copying if you wanted a
133 # different feature object class).
135 # So I decided to go with the lesser of two evils here: we need to assume
136 # here that we can set all attributes through set_attributes(), which we
137 # assume is no different from setting them through the constructor. This
138 # gives us a window to set the feature objects and the factory, such that
139 # any derived class doesn't have to worry about this any more.
141 # I'm happy to hear a better solution, but I think this one isn't so bad.
143 my $self = $class->SUPER::new();
144 my ($feature1,$feature2,$featfact) =
145 $self->_rearrange([qw( FEATURE1
146 FEATURE2
147 FEATURE_FACTORY )],@args);
149 $self->_register_for_cleanup(\&cleanup_fp);
150 # initialize the feature object factory if not provided
151 if(! $featfact) {
152 $featfact = Bio::Factory::ObjectFactory->new(
153 -type => "Bio::SeqFeature::Generic",
154 -interface => "Bio::SeqFeatureI"
157 $self->feature_factory($featfact);
158 # Store the features in the object
159 $feature1 && $self->feature1($feature1);
160 $feature2 && $self->feature2($feature2);
162 # OK. Now we're setup to store all the attributes, and they'll go right
163 # away into the right objects.
164 $self->set_attributes(@args);
166 # done - we hope
167 return $self;
170 =head2 feature1
172 Title : feature1
173 Usage : $f = $featpair->feature1
174 $featpair->feature1($feature)
175 Function: Get/set for the query feature
176 Returns : Bio::SeqFeatureI
177 Args : Bio::SeqFeatureI
180 =cut
182 sub feature1 {
183 my ($self,$arg) = @_;
184 if ( defined($arg) || !defined $self->{'feature1'} ) {
185 $self->throw("internal error: feature factory not set!")
186 unless $self->feature_factory;
187 $arg = $self->feature_factory->create_object() unless( defined $arg);
188 $self->throw("Argument [$arg] must be a Bio::SeqFeatureI")
189 unless (ref($arg) && $arg->isa("Bio::SeqFeatureI"));
190 $self->{'feature1'} = $arg;
192 return $self->{'feature1'};
195 =head2 feature2
197 Title : feature2
198 Usage : $f = $featpair->feature2
199 $featpair->feature2($feature)
200 Function: Get/set for the hit feature
201 Returns : Bio::SeqFeatureI
202 Args : Bio::SeqFeatureI
205 =cut
207 sub feature2 {
208 my ($self,$arg) = @_;
210 if ( defined($arg) || ! defined $self->{'feature2'}) {
211 $self->throw("internal error: feature factory not set!")
212 unless $self->feature_factory;
213 $arg = $self->feature_factory->create_object() unless( defined $arg);
214 $self->throw("Argument [$arg] must be a Bio::SeqFeatureI")
215 unless (ref($arg) && $arg->isa("Bio::SeqFeatureI"));
216 $self->{'feature2'} = $arg;
218 return $self->{'feature2'};
221 =head2 start
223 Title : start
224 Usage : $start = $featpair->start
225 $featpair->start(20)
226 Function: Get/set on the start coordinate of feature1
227 Returns : integer
228 Args : [optional] beginning of feature
230 =cut
232 sub start {
233 return shift->feature1->start(@_);
236 =head2 end
238 Title : end
239 Usage : $end = $featpair->end
240 $featpair->end($end)
241 Function: get/set on the end coordinate of feature1
242 Returns : integer
243 Args : [optional] ending point of feature
246 =cut
248 sub end {
249 return shift->feature1->end(@_);
252 =head2 strand
254 Title : strand
255 Usage : $strand = $feat->strand()
256 $feat->strand($strand)
257 Function: get/set on strand information, being 1,-1 or 0
258 Returns : -1,1 or 0
259 Args : [optional] strand information to set
262 =cut
264 sub strand {
265 return shift->feature1->strand(@_);
268 =head2 location
270 Title : location
271 Usage : $location = $featpair->location
272 $featpair->location($location)
273 Function: Get/set location object (using feature1)
274 Returns : Bio::LocationI object
275 Args : [optional] LocationI to store
277 =cut
279 sub location {
280 return shift->feature1->location(@_);
283 =head2 score
285 Title : score
286 Usage : $score = $feat->score()
287 $feat->score($score)
288 Function: get/set on score information
289 Returns : float
290 Args : none if get, the new value if set
293 =cut
295 sub score {
296 return shift->feature1->score(@_);
299 =head2 frame
301 Title : frame
302 Usage : $frame = $feat->frame()
303 $feat->frame($frame)
304 Function: get/set on frame information
305 Returns : 0,1,2
306 Args : none if get, the new value if set
309 =cut
311 sub frame {
312 return shift->feature1->frame(@_);
315 =head2 primary_tag
317 Title : primary_tag
318 Usage : $ptag = $featpair->primary_tag
319 Function: get/set on the primary_tag of feature1
320 Returns : 0,1,2
321 Args : none if get, the new value if set
324 =cut
326 sub primary_tag {
327 return shift->feature1->primary_tag(@_);
330 =head2 source_tag
332 Title : source_tag
333 Usage : $tag = $feat->source_tag()
334 $feat->source_tag('genscan');
335 Function: Returns the source tag for a feature,
336 eg, 'genscan'
337 Returns : a string
338 Args : none
341 =cut
343 sub source_tag {
344 return shift->feature1->source_tag(@_);
347 =head2 seqname
349 Title : seqname
350 Usage : $obj->seq_id($newval)
351 Function: There are many cases when you make a feature that you
352 do know the sequence name, but do not know its actual
353 sequence. This is an attribute such that you can store
354 the seqname.
356 This attribute should *not* be used in GFF dumping, as
357 that should come from the collection in which the seq
358 feature was found.
359 Returns : value of seqname
360 Args : newvalue (optional)
363 =cut
365 sub seq_id {
366 return shift->feature1->seq_id(@_);
369 =head2 hseqname
371 Title : hseqname
372 Usage : $featpair->hseqname($newval)
373 Function: Get/set method for the name of
374 feature2.
375 Returns : value of $feature2->seq_id
376 Args : newvalue (optional)
379 =cut
381 sub hseq_id {
382 return shift->feature2->seq_id(@_);
386 =head2 hstart
388 Title : hstart
389 Usage : $start = $featpair->hstart
390 $featpair->hstart(20)
391 Function: Get/set on the start coordinate of feature2
392 Returns : integer
393 Args : none
395 =cut
397 sub hstart {
398 return shift->feature2->start(@_);
401 =head2 hend
403 Title : hend
404 Usage : $end = $featpair->hend
405 $featpair->hend($end)
406 Function: get/set on the end coordinate of feature2
407 Returns : integer
408 Args : none
411 =cut
413 sub hend {
414 return shift->feature2->end(@_);
418 =head2 hstrand
420 Title : hstrand
421 Usage : $strand = $feat->strand()
422 $feat->strand($strand)
423 Function: get/set on strand information, being 1,-1 or 0
424 Returns : -1,1 or 0
425 Args : none
428 =cut
430 sub hstrand {
431 return shift->feature2->strand(@_);
434 =head2 hscore
436 Title : hscore
437 Usage : $score = $feat->score()
438 $feat->score($score)
439 Function: get/set on score information
440 Returns : float
441 Args : none if get, the new value if set
444 =cut
446 sub hscore {
447 return shift->feature2->score(@_);
450 =head2 hframe
452 Title : hframe
453 Usage : $frame = $feat->frame()
454 $feat->frame($frame)
455 Function: get/set on frame information
456 Returns : 0,1,2
457 Args : none if get, the new value if set
460 =cut
462 sub hframe {
463 return shift->feature2->frame(@_);
466 =head2 hprimary_tag
468 Title : hprimary_tag
469 Usage : $ptag = $featpair->hprimary_tag
470 Function: Get/set on the primary_tag of feature2
471 Returns : 0,1,2
472 Args : none if get, the new value if set
475 =cut
477 sub hprimary_tag {
478 return shift->feature2->primary_tag(@_);
481 =head2 hsource_tag
483 Title : hsource_tag
484 Usage : $tag = $feat->hsource_tag()
485 $feat->source_tag('genscan');
486 Function: Returns the source tag for a feature,
487 eg, 'genscan'
488 Returns : a string
489 Args : none
492 =cut
494 sub hsource_tag {
495 return shift->feature2->source_tag(@_);
498 =head2 invert
500 Title : invert
501 Usage : $tag = $feat->invert
502 Function: Swaps feature1 and feature2 around
503 Returns : Nothing
504 Args : none
507 =cut
509 sub invert {
510 my ($self) = @_;
512 my $tmp = $self->feature1;
514 $self->feature1($self->feature2);
515 $self->feature2($tmp);
516 return 1;
519 =head2 feature_factory
521 Title : feature_factory
522 Usage : $obj->feature_factory($newval)
523 Function: Get/set the feature object factory for this feature pair.
525 The feature object factory will be used to create a feature
526 object if feature1() or feature2() is called in get mode
527 without having been set before.
529 The default is an instance of Bio::Factory::ObjectFactory
530 and hence allows the type to be changed dynamically at any
531 time.
533 Example :
534 Returns : The feature object factory in use (a
535 Bio::Factory::ObjectFactoryI compliant object)
536 Args : on set, a Bio::Factory::ObjectFactoryI compliant object
539 =cut
541 sub feature_factory {
542 my $self = shift;
544 return $self->{'feature_factory'} = shift if @_;
545 return $self->{'feature_factory'};
548 #################################################################
549 # aliases for backwards compatibility #
550 #################################################################
552 # seqname() is already aliased in Generic.pm, and we overwrite seq_id
554 sub hseqname {
555 my $self = shift;
556 $self->warn("SeqFeatureI::seqname() is deprecated. Please use seq_id() instead.");
557 return $self->hseq_id(@_);
560 sub cleanup_fp {
561 my $self = shift;
562 $self->{'feature1'} = $self->{'feature2'} = undef;