BioPerl

 view release on metacpan or  search on metacpan

Bio/Map/GeneMap.pm  view on Meta::CPAN

    if (defined($value)) {
        $value >= 0 || $self->throw("Supplied value must be a positive integer");
        $pos->start($value + 1);
    }
    
    return $pos->start - 1;
}

=head2 downstream

 Title   : downstream
 Usage   : my $distance = $map->downstream;
           $map->downstream($distance);
 Function: Get/set the nominal end of the map relative to the end of the
           Bio::Map::Gene object on this map.
 Returns : int
 Args    : none to get, OR int to set (the number of bases the map extends
           beyond the end of the gene)

=cut

sub downstream {
    my $self = shift;
    if (@_) { $self->{_downstream} = shift }
    return $self->{_downstream} || 0;
}

=head2 length

 Title   : length
 Usage   : my $length = $map->length();
 Function: Retrieves the length of the map. This is normally the length of the
           upstream region + length of the gene + length of the downstream
           region, but may be longer if positions have been placed on the map
           beyond the end of the nominal downstream region.
 Returns : int
 Args    : none

=cut

sub length {
	my $self = shift;
	my $expected_length = $self->gene->position($self)->length + $self->upstream + $self->downstream;
    my $actual_length = $self->SUPER::length;
    return $actual_length > $expected_length ? $actual_length : $expected_length;
}

=head2 seq

 Title   : seq
 Usage   : $string = $obj->seq()
 Function: Get/set the sequence as a string of letters. When getting, If the
           GeneMap object didn't have sequence attached directly to it for the
           region requested, the map's gene's database will be asked for the
           sequence, and failing that, the map's gene's positions will be asked
           for their sequences. Areas for which no sequence could be found will
           be filled with Ns, unless no sequence was found anywhere, in which
           case undef is returned.
 Returns : string
 Args    : Optionally on set the new value (a string). An optional second
           argument presets the alphabet (otherwise it will be guessed).

=cut

sub seq {
    my ($self, @args) = @_;
    my $seq = $self->SUPER::seq(@args);
    my $expected_length = $self->length;
    if (! $seq || CORE::length($seq) < $expected_length) {
        my @have = split('', $seq || '');
        my @result;
        for (0..($expected_length - 1)) {
            $result[$_] = shift(@have) || 'N';
        }
        
        # build map sequence by asking gene or positions
        my @slice_stuff = $self->gene->_get_slice($self);
        if (@slice_stuff) {
            my ($slice_adaptor, $slice, $strand) = @slice_stuff;
            my ($start, $end, $gene_start) = (CORE::length($seq || '') + 1, $expected_length, $self->upstream + 1);
            
            # convert map coords to genomic coords
            my $adjust = $strand == -1 ? $slice->end : $slice->start;
            my $adjustment = sub { return $strand == -1 ? $adjust - shift() : shift() + $adjust; };
            my $converted_start = &$adjustment($start - $gene_start);
            my $converted_end = &$adjustment($end - $gene_start);
            ($converted_start, $converted_end) = ($converted_end, $converted_start) if $converted_start > $converted_end;
            
            # get sequence from a new slice of desired region
            #*** what happens if desired region starts or ends off end of chromo?...
            my $new_slice = $slice_adaptor->fetch_by_region($slice->coord_system_name, $slice->seq_region_name, $converted_start, $converted_end);
            if ($new_slice && (my $seq_str = $new_slice->seq)) {
                if ($strand == -1) {
                    $seq_str = $self->_revcom($seq_str);
                }
                splice(@result, CORE::length($seq || ''), CORE::length($seq_str), split('', $seq_str));
            }
        }
        else {
            foreach my $pos ($self->get_positions) {
                next unless $pos->can('seq');
                my @pos_seq = split('', $pos->seq(undef, undef, 1) || next);
                for my $i ($pos->start($pos->absolute_relative)..$pos->end($pos->absolute_relative)) {
                    $i--;
                    my $base = shift(@pos_seq);
                    if ($result[$i] eq 'N') {
                        $result[$i] = $base;
                    }
                }
            }
        }
        
        $seq = join('', @result);
    }
    return $seq;
}

=head2 subseq

 Title   : subseq
 Usage   : $substring = $obj->subseq(10, 40);



( run in 2.235 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )