From aaf15a2193b1d4e58c71d0c0a6eff2d2ae09cee8 Mon Sep 17 00:00:00 2001
From: Magali Ruffier <mr6@ebi.ac.uk>
Date: Tue, 4 Aug 2015 11:33:05 +0100
Subject: [PATCH] ENSCORESW-1393: fetch by misc set method added

---
 .../Bio/EnsEMBL/DBSQL/MiscFeatureAdaptor.pm   | 84 +++++++++++++++++++
 modules/Bio/EnsEMBL/DBSQL/SliceAdaptor.pm     | 39 +++++++++
 modules/t/miscFeatureAdaptor.t                | 17 ++++
 modules/t/sliceAdaptor.t                      |  9 ++
 4 files changed, 149 insertions(+)

diff --git a/modules/Bio/EnsEMBL/DBSQL/MiscFeatureAdaptor.pm b/modules/Bio/EnsEMBL/DBSQL/MiscFeatureAdaptor.pm
index f1e89f369a..8357fc9878 100644
--- a/modules/Bio/EnsEMBL/DBSQL/MiscFeatureAdaptor.pm
+++ b/modules/Bio/EnsEMBL/DBSQL/MiscFeatureAdaptor.pm
@@ -226,6 +226,90 @@ sub fetch_all_by_attribute_type_value {
 } ## end sub fetch_all_by_attribute_type_value
 
 
+=head2 fetch_by_attribute_set_value
+
+  Arg [1]    : string $attrib_type_code
+               The code of the attribute type to fetch features for
+  Arg [2]    : (optional) string $attrib_value
+               The value of the attribute to fetch features for
+  Arg [3]    : (optional) string $misc_set
+               The name of the set to which the feature belongs
+  Example    :
+         $feat = $mfa->fetch_by_attribute_set_value('clone', 'RP11-411G9', 'tilepath');
+         # Get the clone belonging to the tilepath
+  Description: Retrieves MiscFeatures which have a particular attribute.
+               If the attribute value argument is also provided only
+               features which have the attribute AND a particular value
+               are returned.  The features are returned in their native
+               coordinate system (i.e. the coordinate system that they
+               are stored in).
+  Returntype : listref of Bio::EnsEMBL::MiscFeatures
+  Exceptions : throw if attrib_type code arg is not provided
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+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 );
+
+  # Need to do 2 queries so that all of the ids come back with the
+  # features.  The problem with adding attrib constraints to filter the
+  # misc_features which come back is that not all of the attributes will
+  # come back
+
+  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;
+} ## end sub fetch_by_attribute_set_value
+
+
 #_tables
 #
 #  Arg [1]    : none
diff --git a/modules/Bio/EnsEMBL/DBSQL/SliceAdaptor.pm b/modules/Bio/EnsEMBL/DBSQL/SliceAdaptor.pm
index 761c59c8cc..37c2ff4802 100644
--- a/modules/Bio/EnsEMBL/DBSQL/SliceAdaptor.pm
+++ b/modules/Bio/EnsEMBL/DBSQL/SliceAdaptor.pm
@@ -1838,6 +1838,45 @@ sub fetch_by_misc_feature_attribute {
   return $self->fetch_by_Feature($feat, $size);
 }
 
+=head2 fetch_by_misc_feature_set
+
+  Arg [1]    : string $attribute_type
+               The code of the attribute type
+  Arg [2]    : (optional) string $attribute_value
+               The value of the attribute to fetch by
+  Arg [3]    : (optional) the name of the set
+  Arg [4]    : (optional) int $size
+               The amount of flanking region around the misc feature desired.
+  Example    : $slice = $sa->fetch_by_misc_feature_set('clone',
+                                                        'RP11-411G9'
+                                                        'tilepath');
+  Description: Fetches a slice around a MiscFeature with a particular
+               attribute type, value and set. If no value is specified then
+               the feature with the particular attribute is used.
+               A size can be specified to include flanking region
+               If no size is specified then 0 is used.
+  Returntype : Bio::EnsEMBL::Slice
+  Exceptions : Throw if no feature with the specified attribute type, value and set
+               exists in the database
+               Warning if multiple features with the specified attribute type, set
+               and value exist in the database.
+  Caller     : webcode
+  Status     : Stable
+
+=cut
+
+sub fetch_by_misc_feature_set {
+  my ($self, $attrib_type_code, $attrib_value, $misc_set, $size) = @_;
+
+  my $mfa = $self->db()->get_MiscFeatureAdaptor();
+
+  my $feat = $mfa->fetch_by_attribute_set_value($attrib_type_code,
+                                                $attrib_value,
+                                                $misc_set);
+
+  return $self->fetch_by_Feature($feat, $size);
+}
+
 =head2 fetch_normalized_slice_projection
 
   Arg [1]    : Bio::EnsEMBL::Slice $slice
diff --git a/modules/t/miscFeatureAdaptor.t b/modules/t/miscFeatureAdaptor.t
index ec0732c226..3eeef570c4 100644
--- a/modules/t/miscFeatureAdaptor.t
+++ b/modules/t/miscFeatureAdaptor.t
@@ -94,6 +94,23 @@ $features = $mfa->fetch_all_by_attribute_type_value('embl_acc');
 ok(@$features == 1);
 print_features($features);
 
+#
+# Test fetch_by_attribute_set_value method
+#
+my $feature = $mfa->fetch_by_attribute_set_value('embl_acc', 'AL000001', 'ntctgs');
+debug('--- fetch_by_attribute_set_value ---');
+ok($feature->dbID() == 2);
+print_features([$feature]);
+
+$feature = $mfa->fetch_by_attribute_set_value('embl_acc', 'rubbish', 'ntctgs');
+ok(!defined $feature);
+
+$feature = $mfa->fetch_by_attribute_set_value('embl_acc', 'AL000001', 'rubbish');
+ok(!defined $feature);
+
+$feature = $mfa->fetch_by_attribute_set_value('rubbish', 'AL000001', 'ntctgs');
+ok(!defined $feature);
+
 
 $multi->hide('core', 'misc_feature', 'misc_feature_misc_set', 'meta_coord',
             'misc_attrib', 'attrib_type', 'misc_set');
diff --git a/modules/t/sliceAdaptor.t b/modules/t/sliceAdaptor.t
index c0daefa8e3..fc7e906139 100644
--- a/modules/t/sliceAdaptor.t
+++ b/modules/t/sliceAdaptor.t
@@ -169,6 +169,15 @@ ok($slice->seq_region_name eq '20');
 ok($slice->start == 59707812 - $flanking);
 ok($slice->end   == 60855021 + $flanking);
 
+# 
+# fetch_by_misc_feature_set
+#
+$slice = $slice_adaptor->fetch_by_misc_feature_set('superctg', 'NT_030871', 'tilepath');
+
+ok($slice->seq_region_name eq '20');
+ok($slice->start == 59707812);
+ok($slice->end   == 60855021);
+
 
 #
 # normalized projected slice
-- 
GitLab