$Bio::EnsEMBL::DBSQL::MiscFeatureAdaptor::VERSION
=
'112.0_56'
;
$Bio::EnsEMBL::DBSQL::MiscFeatureAdaptor::VERSION
=
'112.056'
;
@ISA
=
qw(Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor)
;
sub
fetch_all_by_Slice_and_set_code {
my
$self
=
shift
;
my
$slice
=
shift
;
throw(
'Set code argument is required.'
)
unless
@_
;
my
$msa
=
$self
->db->get_MiscSetAdaptor();
my
@sets
= ();
my
$max_len
= 0;
foreach
my
$set_code
(
@_
) {
my
$set
=
$msa
->fetch_by_code(
$set_code
);
if
(
$set
) {
$max_len
=
$set
->longest_feature
if
$set
->longest_feature >
$max_len
;
push
@sets
,
$set
->dbID;
}
else
{
warning(
"No misc_set with code [$set_code] exists"
);
}
}
my
$constraint
;
if
(
@sets
> 1 ) {
$constraint
=
" mfms.misc_set_id in ( @{[join ',',@sets]} ) "
;
}
elsif
(
@sets
== 1 ) {
$constraint
=
" mfms.misc_set_id = $sets[0] "
;
}
else
{
return
[];
}
$self
->_max_feature_length(
$max_len
);
my
$results
=
$self
->fetch_all_by_Slice_constraint(
$slice
,
$constraint
);
$self
->_max_feature_length(
undef
);
return
$results
;
}
sub
fetch_all_by_attribute_type_value {
my
$self
=
shift
;
my
$attrib_type_code
=
shift
;
my
$attrib_value
=
shift
;
throw(
"Attrib type code argument is required."
)
if
( !
$attrib_type_code
);
my
$sql
=
qq(
SELECT DISTINCT
ma.misc_feature_id
FROM misc_attrib ma,
attrib_type at,
misc_feature mf,
seq_region sr,
coord_system cs
WHERE ma.attrib_type_id = at.attrib_type_id
AND at.code = ?
AND ma.misc_feature_id = mf.misc_feature_id
AND mf.seq_region_id = sr.seq_region_id
AND sr.coord_system_id = cs.coord_system_id
AND cs.species_id = ?)
;
if
(
$attrib_value
) {
$sql
.=
" AND ma.value = ?"
;
}
my
$sth
=
$self
->prepare(
$sql
);
$sth
->bind_param( 1,
$attrib_type_code
, SQL_VARCHAR );
$sth
->bind_param( 2,
$self
->species_id(), SQL_INTEGER );
if
(
$attrib_value
) {
$sth
->bind_param( 3,
$attrib_value
, SQL_VARCHAR );
}
$sth
->execute();
my
@ids
=
map
{
$_
->[0] } @{
$sth
->fetchall_arrayref() };
$sth
->finish();
my
@constraints
;
while
(
@ids
) {
my
@subset
=
splice
(
@ids
, 0, 1000 );
if
(
@subset
== 1 ) {
push
@constraints
,
"mf.misc_feature_id = $subset[0]"
;
}
else
{
my
$id_str
=
join
(
','
,
@subset
);
push
@constraints
,
"mf.misc_feature_id in ($id_str)"
;
}
}
my
@results
;
foreach
my
$constraint
(
@constraints
) {
push
@results
, @{
$self
->generic_fetch(
$constraint
) };
}
return
\
@results
;
}
sub
fetch_by_attribute_set_value {
my
$self
=
shift
;
my
$attrib_type_code
=
shift
;
my
$attrib_value
=
shift
;
my
$misc_set
=
shift
;
throw(
"Attrib type code argument is required."
)
if
( !
$attrib_type_code
);
my
$sql
=
qq(
SELECT DISTINCT
ma.misc_feature_id
FROM misc_attrib ma,
attrib_type at,
misc_feature mf,
misc_feature_misc_set mfs,
misc_set ms,
seq_region sr,
coord_system cs
WHERE ma.attrib_type_id = at.attrib_type_id
AND at.code = ?
AND ma.misc_feature_id = mf.misc_feature_id
AND mf.misc_feature_id = mfs.misc_feature_id
AND mfs.misc_set_id = ms.misc_set_id
AND mf.seq_region_id = sr.seq_region_id
AND sr.coord_system_id = cs.coord_system_id
AND ma.value = ?
AND ms.code = ?
AND cs.species_id = ?)
;
my
$sth
=
$self
->prepare(
$sql
);
$sth
->bind_param( 1,
$attrib_type_code
, SQL_VARCHAR );
$sth
->bind_param( 2,
$attrib_value
, SQL_VARCHAR );
$sth
->bind_param( 3,
$misc_set
, SQL_VARCHAR );
$sth
->bind_param( 4,
$self
->species_id(), SQL_INTEGER );
$sth
->execute();
my
(
$id
) =
$sth
->fetchrow_array();
if
(!
$id
) {
return
;
}
$sth
->finish();
my
$constraint
=
"mf.misc_feature_id = $id"
;
my
(
$result
) = @{
$self
->generic_fetch(
$constraint
)};
return
$result
;
}
sub
_tables {
my
$self
=
shift
;
return
([
'misc_feature'
,
'mf'
],
[
'misc_feature_misc_set'
,
'mfms'
],
[
'misc_attrib'
,
'ma'
],
[
'attrib_type'
,
'at'
]);
}
sub
_columns {
my
$self
=
shift
;
return
qw (mf.misc_feature_id
mf.seq_region_id
mf.seq_region_start
mf.seq_region_end
mf.seq_region_strand
ma.value
at.code
mfms.misc_set_id
at.name
at.description);
}
sub
_default_where_clause {
my
$self
=
shift
;
return
''
;
}
sub
_left_join {
my
$self
=
shift
;
return
(
[
'misc_feature_misc_set'
,
'mf.misc_feature_id = mfms.misc_feature_id'
],
[
'misc_attrib'
,
'mf.misc_feature_id = ma.misc_feature_id'
],
[
'attrib_type'
,
'ma.attrib_type_id = at.attrib_type_id'
]);
}
sub
_final_clause {
my
$self
=
shift
;
return
" ORDER BY mf.misc_feature_id"
;
}
sub
_objs_from_sth {
my
(
$self
,
$sth
,
$mapper
,
$dest_slice
) =
@_
;
my
$sa
=
$self
->db()->get_SliceAdaptor();
my
$msa
=
$self
->db()->get_MiscSetAdaptor();
my
@features
;
my
%ms_hash
;
my
%slice_hash
;
my
%sr_name_hash
;
my
%sr_cs_hash
;
my
(
$misc_feature_id
,
$seq_region_id
,
$seq_region_start
,
$seq_region_end
,
$seq_region_strand
,
$attrib_value
,
$attrib_type_code
,
$misc_set_id
,
$attrib_type_name
,
$attrib_type_description
);
$sth
->bind_columns( \
$misc_feature_id
, \
$seq_region_id
, \
$seq_region_start
,
\
$seq_region_end
, \
$seq_region_strand
,
\
$attrib_value
, \
$attrib_type_code
,\
$misc_set_id
,
\
$attrib_type_name
, \
$attrib_type_description
);
my
$dest_slice_start
;
my
$dest_slice_end
;
my
$dest_slice_strand
;
my
$dest_slice_length
;
my
$dest_slice_cs
;
my
$dest_slice_sr_name
;
my
$dest_slice_sr_id
;
my
$asma
;
if
(
$dest_slice
) {
$dest_slice_start
=
$dest_slice
->start();
$dest_slice_end
=
$dest_slice
->end();
$dest_slice_strand
=
$dest_slice
->strand();
$dest_slice_length
=
$dest_slice
->
length
();
$dest_slice_cs
=
$dest_slice
->coord_system();
$dest_slice_sr_name
=
$dest_slice
->seq_region_name();
$dest_slice_sr_id
=
$dest_slice
->get_seq_region_id();
$asma
=
$self
->db->get_AssemblyMapperAdaptor();
}
my
$current
= -1;
my
$throw_away
= -1;
my
$feat
;
my
$feat_misc_sets
;
my
$feat_attribs
;
my
$seen_attribs
;
FEATURE:
while
(
$sth
->fetch()) {
next
if
(
$throw_away
==
$misc_feature_id
);
if
(
$current
==
$misc_feature_id
) {
if
(
$misc_set_id
) {
my
$misc_set
=
$ms_hash
{
$misc_set_id
} ||=
$msa
->fetch_by_dbID(
$misc_set_id
);
if
( !
exists
$feat_misc_sets
->{
$misc_set
->{
'code'
}} ) {
$feat
->add_MiscSet(
$misc_set
);
$feat_misc_sets
->{
$misc_set
->{
'code'
}} =
$misc_set
;
}
}
if
(
$attrib_value
&&
$attrib_type_code
&& !
$seen_attribs
->{
"$attrib_type_code:$attrib_value"
}) {
my
$attrib
= Bio::EnsEMBL::Attribute->new
(
-CODE
=>
$attrib_type_code
,
-NAME
=>
$attrib_type_name
,
-DESC
=>
$attrib_type_description
,
-VALUE
=>
$attrib_value
);
$feat_attribs
||= [];
push
@$feat_attribs
,
$attrib
;
$seen_attribs
->{
"$attrib_type_code:$attrib_value"
} = 1;
}
}
else
{
if
(
$feat
) {
$feat
= {};
$feat_attribs
= [];
$feat_misc_sets
= {};
$seen_attribs
= {};
}
$current
=
$misc_feature_id
;
$seq_region_id
=
$self
->get_seq_region_id_internal(
$seq_region_id
);
my
$slice
=
$slice_hash
{
"ID:"
.
$seq_region_id
};
if
(!
$slice
) {
$slice
=
$sa
->fetch_by_seq_region_id(
$seq_region_id
);
$slice_hash
{
"ID:"
.
$seq_region_id
} =
$slice
;
$sr_name_hash
{
$seq_region_id
} =
$slice
->seq_region_name();
$sr_cs_hash
{
$seq_region_id
} =
$slice
->coord_system();
}
if
(!
$mapper
&&
$dest_slice
&& !
$dest_slice_cs
->equals(
$slice
->coord_system)) {
$mapper
=
$asma
->fetch_by_CoordSystems(
$dest_slice_cs
,
$slice
->coord_system);
}
my
$sr_name
=
$sr_name_hash
{
$seq_region_id
};
my
$sr_cs
=
$sr_cs_hash
{
$seq_region_id
};
if
(
$mapper
) {
if
(
defined
$dest_slice
&&
$mapper
->isa(
'Bio::EnsEMBL::ChainedAssemblyMapper'
) ) {
(
$seq_region_id
,
$seq_region_start
,
$seq_region_end
,
$seq_region_strand
) =
$mapper
->
map
(
$sr_name
,
$seq_region_start
,
$seq_region_end
,
$seq_region_strand
,
$sr_cs
, 1,
$dest_slice
);
}
else
{
(
$seq_region_id
,
$seq_region_start
,
$seq_region_end
,
$seq_region_strand
) =
$mapper
->fastmap(
$sr_name
,
$seq_region_start
,
$seq_region_end
,
$seq_region_strand
,
$sr_cs
);
}
if
(!
defined
(
$seq_region_id
)) {
$throw_away
=
$misc_feature_id
;
next
FEATURE;
}
$slice
=
$slice_hash
{
"ID:"
.
$seq_region_id
} ||=
$sa
->fetch_by_seq_region_id(
$seq_region_id
);
}
if
(
$dest_slice
) {
my
$seq_region_len
=
$dest_slice
->seq_region_length();
if
(
$dest_slice_strand
== 1) {
$seq_region_start
=
$seq_region_start
-
$dest_slice_start
+ 1;
$seq_region_end
=
$seq_region_end
-
$dest_slice_start
+ 1;
if
(
$dest_slice
->is_circular()) {
if
(
$seq_region_start
>
$seq_region_end
) {
if
(
$seq_region_end
>
$dest_slice_start
) {
$seq_region_start
-=
$seq_region_len
;
}
if
(
$seq_region_end
< 0) {
$seq_region_end
+=
$seq_region_len
;
}
}
else
{
if
(
$dest_slice_start
>
$dest_slice_end
&&
$seq_region_end
< 0) {
$seq_region_start
+=
$seq_region_len
;
$seq_region_end
+=
$seq_region_len
;
}
}
}
}
else
{
my
$start
=
$dest_slice_end
-
$seq_region_end
+ 1;
my
$end
=
$dest_slice_end
-
$seq_region_start
+ 1;
if
(
$dest_slice
->is_circular()) {
if
(
$dest_slice_start
>
$dest_slice_end
) {
if
(
$seq_region_start
>=
$dest_slice_start
) {
$end
+=
$seq_region_len
;
$start
+=
$seq_region_len
if
$seq_region_end
>
$dest_slice_start
;
}
elsif
(
$seq_region_start
<=
$dest_slice_end
) {
}
elsif
(
$seq_region_end
>=
$dest_slice_start
) {
$start
+=
$seq_region_len
;
$end
+=
$seq_region_len
;
}
elsif
(
$seq_region_end
<=
$dest_slice_end
) {
$end
+=
$seq_region_len
if
$end
< 0;
}
elsif
(
$seq_region_start
>
$seq_region_end
) {
$end
+=
$seq_region_len
;
}
}
else
{
if
(
$seq_region_start
<=
$dest_slice_end
and
$seq_region_end
>=
$dest_slice_start
) {
}
elsif
(
$seq_region_start
>
$seq_region_end
) {
if
(
$seq_region_start
<=
$dest_slice_end
) {
$start
-=
$seq_region_len
;
}
elsif
(
$seq_region_end
>=
$dest_slice_start
) {
$end
+=
$seq_region_len
;
}
}
}
}
$seq_region_start
=
$start
;
$seq_region_end
=
$end
;
$seq_region_strand
*= -1;
}
if
(
$seq_region_end
< 1 ||
$seq_region_start
>
$dest_slice_length
||
$dest_slice_sr_id
!=
$seq_region_id
) {
$throw_away
=
$misc_feature_id
;
next
FEATURE;
}
$slice
=
$dest_slice
;
}
if
(
$attrib_value
&&
$attrib_type_code
) {
my
$attrib
= Bio::EnsEMBL::Attribute->new
(
-CODE
=>
$attrib_type_code
,
-NAME
=>
$attrib_type_name
,
-DESC
=>
$attrib_type_description
,
-VALUE
=>
$attrib_value
);
$feat_attribs
= [
$attrib
];
$seen_attribs
->{
"$attrib_type_code:$attrib_value"
} = 1;
}
$feat
=
$self
->_create_feature_fast(
'Bio::EnsEMBL::MiscFeature'
, {
'start'
=>
$seq_region_start
,
'end'
=>
$seq_region_end
,
'strand'
=>
$seq_region_strand
,
'slice'
=>
$slice
,
'adaptor'
=>
$self
,
'dbID'
=>
$misc_feature_id
,
'attributes'
=>
$feat_attribs
||= []
} );
push
@features
,
$feat
;
if
(
$misc_set_id
) {
my
$misc_set
=
$ms_hash
{
$misc_set_id
} ||=
$msa
->fetch_by_dbID(
$misc_set_id
);
if
( !
exists
$feat_misc_sets
->{
$misc_set
->{
'code'
}} ) {
$feat
->add_MiscSet(
$misc_set
);
$feat_misc_sets
->{
$misc_set
->{
'code'
}} =
$misc_set
;
}
}
}
}
return
\
@features
;
}
sub
list_dbIDs {
my
(
$self
,
$ordered
) =
@_
;
return
$self
->_list_dbIDs(
"misc_feature"
,
undef
,
$ordered
);
}
sub
store {
my
$self
=
shift
;
my
@misc_features
=
@_
;
my
$db
=
$self
->db();
my
$feature_sth
=
$self
->prepare(
q{INSERT INTO misc_feature (
seq_region_id,
seq_region_start,
seq_region_end,
seq_region_strand
) VALUES (?, ?, ?, ?)
}
);
my
$insert_ignore
=
$self
->insert_ignore_clause();
my
$feature_set_sth
=
$self
->prepare(
qq{${insert_ignore}
INTO misc_feature_misc_set (
misc_feature_id,
misc_set_id
) VALUES (?, ?)
});
my
$msa
=
$db
->get_MiscSetAdaptor();
my
$aa
=
$db
->get_AttributeAdaptor();
FEATURE:
foreach
my
$mf
(
@misc_features
) {
if
(!
ref
(
$mf
) || !
$mf
->isa(
'Bio::EnsEMBL::MiscFeature'
)) {
throw(
"List of MiscFeature arguments expeceted"
);
}
if
(
$mf
->is_stored(
$db
)) {
warning(
"MiscFeature ["
.
$mf
->dbID.
"] is already stored in database."
);
next
FEATURE;
}
my
$original
=
$mf
;
my
$seq_region_id
;
(
$mf
,
$seq_region_id
) =
$self
->_pre_store(
$mf
);
$feature_sth
->bind_param(1,
$seq_region_id
,SQL_INTEGER);
$feature_sth
->bind_param(2,
$mf
->start,SQL_INTEGER);
$feature_sth
->bind_param(3,
$mf
->end,SQL_INTEGER);
$feature_sth
->bind_param(4,
$mf
->strand,SQL_TINYINT);
$feature_sth
->execute();
my
$dbID
=
$self
->last_insert_id(
'misc_feature_id'
,
undef
,
'misc_feature'
);
$mf
->dbID(
$dbID
);
$mf
->adaptor(
$self
);
my
$attribs
=
$mf
->get_all_Attributes();
$aa
->store_on_MiscFeature(
$mf
,
$attribs
);
my
$sets
=
$mf
->get_all_MiscSets();
foreach
my
$set
(
@$sets
) {
$msa
->store(
$set
)
if
(!
$set
->is_stored(
$db
));
$feature_set_sth
->bind_param(1,
$dbID
,SQL_INTEGER);
$feature_set_sth
->bind_param(2,
$set
->dbID,SQL_INTEGER);
$feature_set_sth
->execute();
}
}
return
;
}
1;