see if Bio::DB::Sam package will work for tests
[bioperl-live.git] / Bio / Map / GenePosition.pm
blob87671185b9eb6d7c30ef068d2baefbb92bd9592f
1 # $Id: GenePosition.pm,v 1.19 2006/09/20 10:20:01 sendu Exp $
3 # BioPerl module for Bio::Map::GenePosition
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by Sendu Bala <bix@sendu.me.uk>
9 # Copyright Sendu Bala
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::Map::GenePosition - A typed position, suitable for modelling the various
18 regions of a gene.
20 =head1 SYNOPSIS
22 use Bio::Map::GenePosition;
23 use Bio::Map::GeneMap;
25 # say that the first transcript of a particular gene on a particular map
26 # (species) is 1000bp long
27 my $map = Bio::Map:GeneMap->get(-universal_name => 'BRCA2',
28 -species => 'human');
29 my $gene = $map->gene;
30 Bio::Map::GenePosition->new(-map => $map,
31 -element => $gene,
32 -start => 0,
33 -length => 1000,
34 -type => 'transcript');
36 # say that the coding region of the gene starts 30bp into the first
37 # transcript
38 Bio::Map::GenePosition->new(-map => $map,
39 -element => $gene,
40 -start => 30,
41 -length => 600,
42 -type => 'coding');
44 # A GenePosition isa PositionWithSequence, so can have sequence associated
45 # with it
46 my $exon = Bio::Map::GenePosition->new(-map => $map,
47 -element => $gene,
48 -start => 0,
49 -type => 'exon',
50 -seq => 'ATGGGGTGGG');
51 my $length = $exon->length; # $length is 10
53 =head1 DESCRIPTION
55 Define where various sub-regions (transcripts, exons, introns etc.) of a gene
56 are. Do this so that you can then go onto to model other mappable elements as
57 having positions 20bp upstream of transcript 2, or 10bp into intron 3 etc., all
58 without having to know the absolute position of anything.
60 See Bio::Map::GeneRelative and t/Map/Map.t for more example usage.
62 =head1 FEEDBACK
64 =head2 Mailing Lists
66 User feedback is an integral part of the evolution of this and other
67 Bioperl modules. Send your comments and suggestions preferably to
68 the Bioperl mailing list. Your participation is much appreciated.
70 bioperl-l@bioperl.org - General discussion
71 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
73 =head2 Support
75 Please direct usage questions or support issues to the mailing list:
77 I<bioperl-l@bioperl.org>
79 rather than to the module maintainer directly. Many experienced and
80 reponsive experts will be able look at the problem and quickly
81 address it. Please include a thorough description of the problem
82 with code and data examples if at all possible.
84 =head2 Reporting Bugs
86 Report bugs to the Bioperl bug tracking system to help us keep track
87 of the bugs and their resolution. Bug reports can be submitted via the
88 web:
90 https://redmine.open-bio.org/projects/bioperl/
92 =head1 AUTHOR - Sendu Bala
94 Email bix@sendu.me.uk
96 =head1 APPENDIX
98 The rest of the documentation details each of the object methods.
99 Internal methods are usually preceded with a _
101 =cut
103 # Let the code begin...
105 package Bio::Map::GenePosition;
106 use strict;
108 use Bio::Map::GeneRelative;
110 use base qw(Bio::Map::PositionWithSequence);
112 =head2 new
114 Title : new
115 Usage : my $obj = Bio::Map::GenePosition->new();
116 Function: Builds a new Bio::Map::GenePosition object
117 Returns : Bio::Map::GenePosition
118 Args : -map => Bio::Map::GeneMap object
119 -element => Bio::Map::Gene object
120 -relative => Bio::Map::GeneRelative object
121 -type => 'transcript|coding|exon|intron', REQUIRED
122 -seq => string, length of this string will set the length
123 of this position's range
125 * If this position has no range, or if a single value can describe
126 the range *
127 -value => scalar : something that describes the single
128 point position or range of this
129 Position, most likely an int
131 * Or if this position has a range, at least two of *
132 -start => int : value of the start co-ordinate
133 -end => int : value of the end co-ordinate
134 -length => int : length of the range
136 =cut
138 sub new {
139 my ($class, @args) = @_;
140 my $self = $class->SUPER::new(@args);
142 my ($type) = $self->_rearrange([qw( TYPE )], @args);
143 $type || $self->throw("type must be supplied");
144 $self->type($type);
146 $self->{_relative_not_implicit} = 1;
148 return $self;
151 =head2 map
153 Title : map
154 Usage : my $map = $position->map();
155 $position->map($map);
156 Function: Get/set the map the position is in.
157 Returns : L<Bio::Map::MapI>
158 Args : none to get
159 new L<Bio::Map::MapI> to set
161 =cut
163 sub map {
164 my ($self, $map) = @_;
165 if ($map) {
166 $map->isa('Bio::Map::GeneMap') || $self->throw("This is [$map], not a Bio::Map::GeneMap");
168 return $self->SUPER::map($map);
171 =head2 element
173 Title : element
174 Usage : my $element = $position->element();
175 $position->element($element);
176 Function: Get/set the element the position is for.
177 Returns : L<Bio::Map::MappableI>
178 Args : none to get
179 new L<Bio::Map::MappableI> to set
181 =cut
183 sub element {
184 my ($self, $element) = @_;
185 if ($element) {
186 $element->isa('Bio::Map::Gene') || $self->throw("This is [$element], not a Bio::Map::Gene");
188 return $self->SUPER::element($element);
191 =head2 type
193 Title : type
194 Usage : my $type = $position->type();
195 $position->type($type);
196 Function: Get/set the type of this position.
197 Returns : string
198 Args : none to get, OR
199 string transcript|coding|exon|intron to set
201 =cut
203 sub type {
204 my $self = shift;
205 if (@_) {
206 my $type = shift;
207 if ($type !~ /transcript|coding|exon|intron/i) {
208 $self->throw("type must be supplied and be one of 'transcript', 'coding', 'exon', 'intron'");
210 $self->{type} = $type;
212 return $self->{type};
215 =head2 relative
217 Title : relative
218 Usage : my $relative = $position->relative();
219 $position->relative($relative);
220 Function: Get/set the thing this Position's coordinates (numerical(), start(),
221 end()) are relative to, as described by a RelativeI object.
222 Returns : Bio::Map::GeneRelative. The default GeneRelative returned has a
223 meaning that depends on the type() of GenePosition this is:
224 'transcript' : "relative to the start of the gene on the
225 Position's map"
226 'coding|exon|intron' : "relative to the start of the default
227 transcript of the gene on the Position's map"
228 Args : none to get, OR
229 Bio::Map::GeneRelative to set
231 =cut
233 sub relative {
234 my ($self, $relative) = @_;
235 if ($relative) {
236 $self->throw("Must supply an object") unless ref($relative);
237 $self->throw("This is [$relative], not a Bio::Map::GeneRelative") unless $relative->isa('Bio::Map::GeneRelative');
238 $self->{_relative} = $relative;
240 return $self->{_relative} || $self->_default_relative;
243 =head2 seq
245 Title : seq
246 Usage : my $string = $position->seq();
247 Function: Get/set the sequence as a string of letters. If no sequence is
248 manually set by you, the position's map will be asked for the
249 sequence, and if available, that will be returned.
250 Returns : scalar
251 Args : Optionally on set the new value (a string). An optional second
252 argument presets the alphabet (otherwise it will be guessed).
254 =cut
256 sub seq {
257 # $shortcut is internal-use only by GeneMap
258 my ($self, $str, $alpha, $shortcut) = @_;
260 my $seq = $self->SUPER::seq($str, $alpha);
262 if ($seq) {
263 $self->length(CORE::length($seq));
264 return $seq;
266 elsif (! $shortcut && defined(my $map = $self->map) && ! defined $self->{_getting_seq}) {
267 $self->{_getting_seq} = 1;
268 $seq = $map->subseq($self);
269 delete $self->{_getting_seq};
270 return $seq;
272 return;
275 # return a Relative that is suitable for the type
276 sub _default_relative {
277 my $self = shift;
278 my $type = $self->type;
279 if ($type eq 'transcript') {
280 return Bio::Map::GeneRelative->new(-gene => 0, -description => 'start of gene');
282 else {
283 return Bio::Map::GeneRelative->new(-transcript => 0, -description => 'start of default transcript');