sub
new {
my
(
$class
,
@args
) =
@_
;
my
$self
=
$class
->SUPER::new(
@args
);
my
(
$in
,
$out
) =
$self
->_rearrange([
qw(IN
OUT
)
],
@args
);
$in
&&
$self
->in(
$in
);
$out
&&
$self
->out(
$out
);
return
$self
;
}
sub
in {
my
(
$self
,
$value
) =
@_
;
if
(
defined
$value
) {
$self
->throw(
"Not a valid input Bio::Location [$value] "
)
unless
$value
->isa(
'Bio::LocationI'
);
$self
->{
'_in'
} =
$value
;
}
return
$self
->{
'_in'
};
}
sub
out {
my
(
$self
,
$value
) =
@_
;
if
(
defined
$value
) {
$self
->throw(
"Not a valid output coordinate Bio::Location [$value] "
)
unless
$value
->isa(
'Bio::LocationI'
);
$self
->{
'_out'
} =
$value
;
}
return
$self
->{
'_out'
};
}
sub
swap {
my
(
$self
) =
@_
;
(
$self
->{
'_in'
},
$self
->{
'_out'
}) = (
$self
->{
'_out'
},
$self
->{
'_in'
});
return
1;
}
sub
strand {
my
(
$self
) =
@_
;
$self
->
warn
(
"Outgoing coordinates are not defined"
)
unless
$self
->out;
$self
->
warn
(
"Incoming coordinates are not defined"
)
unless
$self
->in;
return
(
$self
->in->strand || 0) * (
$self
->out->strand || 0);
}
sub
test {
my
(
$self
) =
@_
;
$self
->
warn
(
"Outgoing coordinates are not defined"
)
unless
$self
->out;
$self
->
warn
(
"Incoming coordinates are not defined"
)
unless
$self
->in;
return
(
$self
->in->end -
$self
->in->start) == (
$self
->out->end -
$self
->out->start);
}
sub
map
{
my
(
$self
,
$value
) =
@_
;
$self
->throw(
"Need to pass me a value."
)
unless
defined
$value
;
$self
->throw(
"I need a Bio::Location, not [$value]"
)
unless
$value
->isa(
'Bio::LocationI'
);
$self
->throw(
"Input coordinate system not set"
)
unless
$self
->in;
$self
->throw(
"Output coordinate system not set"
)
unless
$self
->out;
if
(
$value
->isa(
"Bio::Location::SplitLocationI"
)) {
my
$result
= new Bio::Coordinate::Result;
my
$split
= new Bio::Location::Split(
-seq_id
=>
$self
->out->seq_id);
foreach
my
$loc
(
$value
->sub_Location(1) ) {
my
$res
=
$self
->_map(
$loc
);
map
{
$result
->add_sub_Location(
$_
) }
$res
->each_Location;
}
return
$result
;
}
else
{
return
$self
->_map(
$value
);
}
}
sub
_map {
my
(
$self
,
$value
) =
@_
;
my
$result
= new Bio::Coordinate::Result;
my
$offset
=
$self
->in->start -
$self
->out->start;
my
$start
=
$value
->start -
$offset
;
my
$end
=
$value
->end -
$offset
;
my
$match
= Bio::Location::Simple->new;
$match
->location_type(
$value
->location_type);
$match
->strand(
$self
->strand);
if
(
$start
>=
$self
->out->start and
$end
<=
$self
->out->end) {
$match
->seq_id(
$self
->out->seq_id);
$result
->seq_id(
$self
->out->seq_id);
if
(
$self
->strand >= 0) {
$match
->start(
$start
);
$match
->end(
$end
);
}
else
{
$match
->start(
$self
->out->end -
$end
+
$self
->out->start);
$match
->end(
$self
->out->end -
$start
+
$self
->out->start);
}
if
(
$value
->strand) {
$match
->strand(
$match
->strand *
$value
->strand);
$result
->strand(
$match
->strand);
}
bless
$match
,
'Bio::Coordinate::Result::Match'
;
$result
->add_sub_Location(
$match
);
}
elsif
( (
$end
<
$self
->out->start or
$start
>
$self
->out->end ) or
(
$value
->location_type eq
'IN-BETWEEN'
and
(
$end
=
$self
->out->start or
$start
=
$self
->out->end))) {
$match
->seq_id(
$self
->in->seq_id);
$result
->seq_id(
$self
->in->seq_id);
$match
->start(
$value
->start);
$match
->end(
$value
->end);
$match
->strand(
$value
->strand);
bless
$match
,
'Bio::Coordinate::Result::Gap'
;
$result
->add_sub_Location(
$match
);
}
elsif
(
$start
<
$self
->out->start and
$end
<=
$self
->out->end ) {
$result
->seq_id(
$self
->out->seq_id);
if
(
$value
->strand) {
$match
->strand(
$match
->strand *
$value
->strand);
$result
->strand(
$match
->strand);
}
my
$gap
= Bio::Location::Simple->new;
$gap
->start(
$value
->start);
$gap
->end(
$self
->in->start - 1);
$gap
->strand(
$value
->strand);
$gap
->seq_id(
$self
->in->seq_id);
bless
$gap
,
'Bio::Coordinate::Result::Gap'
;
$result
->add_sub_Location(
$gap
);
$match
->seq_id(
$self
->out->seq_id);
if
(
$self
->strand >= 0) {
$match
->start(
$self
->out->start);
$match
->end(
$end
);
}
else
{
$match
->start(
$self
->out->end -
$end
+
$self
->out->start);
$match
->end(
$self
->out->end);
}
bless
$match
,
'Bio::Coordinate::Result::Match'
;
$result
->add_sub_Location(
$match
);
}
elsif
(
$start
>=
$self
->out->start and
$end
>
$self
->out->end ) {
$match
->seq_id(
$self
->out->seq_id);
$result
->seq_id(
$self
->out->seq_id);
if
(
$value
->strand) {
$match
->strand(
$match
->strand *
$value
->strand);
$result
->strand(
$match
->strand);
}
if
(
$self
->strand >= 0) {
$match
->start(
$start
);
$match
->end(
$self
->out->end);
}
else
{
$match
->start(
$self
->out->start);
$match
->end(
$self
->out->end -
$start
+
$self
->out->start);
}
bless
$match
,
'Bio::Coordinate::Result::Match'
;
$result
->add_sub_Location(
$match
);
my
$gap
= Bio::Location::Simple->new;
$gap
->start(
$self
->in->end + 1);
$gap
->end(
$value
->end);
$gap
->strand(
$value
->strand);
$gap
->seq_id(
$self
->in->seq_id);
bless
$gap
,
'Bio::Coordinate::Result::Gap'
;
$result
->add_sub_Location(
$gap
);
}
elsif
(
$start
<
$self
->out->start and
$end
>
$self
->out->end ) {
$result
->seq_id(
$self
->out->seq_id);
if
(
$value
->strand) {
$match
->strand(
$match
->strand *
$value
->strand);
$result
->strand(
$match
->strand);
}
my
$gap1
= Bio::Location::Simple->new;
$gap1
->start(
$value
->start);
$gap1
->end(
$self
->in->start - 1);
$gap1
->strand(
$value
->strand);
$gap1
->seq_id(
$self
->in->seq_id);
bless
$gap1
,
'Bio::Coordinate::Result::Gap'
;
$result
->add_sub_Location(
$gap1
);
$match
->seq_id(
$self
->out->seq_id);
$match
->start(
$self
->out->start);
$match
->end(
$self
->out->end);
bless
$match
,
'Bio::Coordinate::Result::Match'
;
$result
->add_sub_Location(
$match
);
my
$gap2
= Bio::Location::Simple->new;
$gap2
->start(
$self
->in->end + 1);
$gap2
->end(
$value
->end);
$gap2
->strand(
$value
->strand);
$gap2
->seq_id(
$self
->in->seq_id);
bless
$gap2
,
'Bio::Coordinate::Result::Gap'
;
$result
->add_sub_Location(
$gap2
);
}
else
{
$self
->throw(
"Should not be here!"
);
}
return
$result
;
}
1;