my ($self, $features, $mapper, $slice) = @_;
# check if any remapping is actually needed
if(@$features && (!$features->[0]->isa('Bio::EnsEMBL::Feature') ||
$features->[0]->slice == $slice)) {
return $features;
}
# remapping has not been done, we have to do our own conversion from
# to slice coords
my @out;
my $slice_start = $slice->start();
my $slice_end = $slice->end();
my $slice_strand = $slice->strand();
my $slice_cs = $slice->coord_system();
my ($seq_region, $start, $end, $strand, $seq_region_name);
my $slice_seq_region = $slice->seq_region_name();
foreach my $f (@$features) {
# since feats were obtained in contig coords, attached seq is a contig
my $fslice = $f->slice();
if(!$fslice) {
throw("Feature does not have attached slice.\n");
}
my $fseq_region = $fslice->seq_region_name();
my $fcs = $fslice->coord_system();
if(!$slice_cs->equals($fcs)) {
# slice of feature in different coord system, mapping required
($seq_region, $start, $end, $strand) =
$mapper->fastmap($fseq_region,$f->start(),$f->end(),$f->strand(),$fcs);
# undefined start means gap
next if(!defined $start);
my $slice_adaptor = $self->db()->get_SliceAdaptor();
$seq_region_name = $slice_adaptor->fetch_by_seq_region_id($seq_region)->seq_region_name;
} else {
$start = $f->start();
$end = $f->end();
$strand = $f->strand();
$seq_region_name = $f->slice->seq_region_name();
}
# maps to region outside desired area
next if ($start > $slice_end) || ($end < $slice_start) ||
($slice_seq_region ne $seq_region_name);
# create new copies of successfully mapped feaatures with shifted start,
# end and strand
my ($new_start, $new_end);
my $seq_region_len = $slice->seq_region_length();
if ($slice_strand == 1) { # Positive strand
$new_start = $start - $slice_start + 1;
$new_end = $end - $slice_start + 1;
if ($slice->is_circular()) {
# Handle circular chromosomes.
if ($new_start > $new_end) {
# Looking at a feature overlapping the chromsome origin.
if ($new_end > $slice_start) {
# Looking at the region in the beginning of the chromosome.
$new_start -= $seq_region_len;
}
if ($new_end < 0) {
$new_end += $seq_region_len;
}
} else {
if ( $slice_start > $slice_end && $new_end < 0) {
# Looking at the region overlapping the chromosome
# origin and a feature which is at the beginning of the
# chromosome.
$new_start += $seq_region_len;
$new_end += $seq_region_len;
}
}
} ## end if ($dest_slice->is_circular...)
} else { # Negative strand
$new_start = $slice_end - $end + 1;
$new_end = $slice_end - $start + 1;
if ($slice->is_circular()) {
if ($slice_start > $slice_end) {
# slice spans origin or replication
if ($start >= $slice_start) {
$new_end += $seq_region_len;
$new_start += $seq_region_len if $end > $slice_start;
} elsif ($start <= $slice_end) {
# do nothing
} elsif ($end >= $slice_start) {
$new_start += $seq_region_len;
$new_end += $seq_region_len;
} elsif ($end <= $slice_end) {
$new_end += $seq_region_len if $new_end < 0;
} elsif ($start > $end) {
$new_end += $seq_region_len;
} else {
}
} else {
if ($start <= $slice_end and $end >= $slice_start) {
# do nothing
} elsif ($start > $end) {
if ($start <= $slice_end) {
$new_start -= $seq_region_len;
} elsif ($end >= $slice_start) {
$new_end += $seq_region_len;
} else {
}
}
}
}
} ## end else [ if ($dest_slice_strand...)]
'-dbID' => $f->dbID,
'-start' => $new_start,
'-end' => $new_end,
'-strand' => $strand * $slice_strand,
'-adaptor' => $self,
'-slice' => $slice,
'-alternate_slice' => $f->alternate_slice,
'-type' => $f->type,
);
} # end foreach assembly exception
return \@out;
}