ensembl-hive  2.8.1
MiscFeatureAdaptor.pm
Go to the documentation of this file.
1 =head1 LICENSE
2 
3 See the NOTICE file distributed with this work for additional information
4 regarding copyright ownership.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 =cut
19 
20 
21 =head1 CONTACT
22 
23  Please email comments or questions to the public Ensembl
24  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 
26  Questions may also be sent to the Ensembl help desk at
27  <http://www.ensembl.org/Help/Contact>.
28 
29 =cut
30 
31 =head1 NAME
32 
34 
35 =head1 SYNOPSIS
36 
37  $mfa = $database_adaptor->get_MiscFeatureAdaptor();
38 
39  # retrieve a misc feature by its dbID
40  my $misc_feat = $mfa->fetch_by_dbID(1234);
41 
42  # retrieve all misc features in a given region
43  my @misc_feats = @{ $mfa->fetch_all_by_Slice($slice) };
44 
45  # retrieve all misc features in a given region with a given set code
46  my @misc_clones =
47  @{ $mfa->fetch_all_by_Slice_and_set_code('cloneset') };
48 
49  # store some misc features in the database
50  $mfa->store(@misc_features);
51 
52 =head1 DESCRIPTION
53 
54 This is an adaptor for the retrieval and storage of MiscFeatures.
55 Misc Features are extremely generic features that can be added with
56 minimal effort to the database. Currently misc features are used to
57 describe the locations of clone sets and tiling path information,
58 but arbitrary features can be stored. Misc features are grouped
59 into sets and can be fetched according to their grouping using the
60 fetch_all_by_Slice_and_set_code and fetch_all_by_set_code methods.
61 MiscFeatures may belong to more than one set.
62 
63 =head1 METHODS
64 
65 =cut
66 
67 package Bio::EnsEMBL::DBSQL::MiscFeatureAdaptor;
68 
69 use strict;
74 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
75 
76 use vars qw(@ISA);
77 
79 
80 
81 
82 =head2 fetch_all_by_Slice_and_set_code
83 
84  Arg [1] : Bio::EnsEMBL::Slice $slice
85  A slice representing the region to fetch from
86  Arg [2...] : string $set_code
87  The code of the set to retrieve features from
88  Example : @feats = @{$mfa->fetch_all_by_Slice_and_set_code('cloneset')};
89  Description: Retrieves a set of MiscFeatures which have a particular set code
90  and which lie in a particular region. All features with the
91  provide set code and which overlap the given slice are returned.
92  Returntype : listref of Bio::EnsEMBL::MiscFeatures
93  Exceptions : throw if set_code is not provided
94  warning if no set for provided set code exists
95  Caller : general
96  Status : Stable
97 
98 =cut
99 
100 sub fetch_all_by_Slice_and_set_code {
101  my $self = shift;
102  my $slice = shift;
103 
104  throw('Set code argument is required.') unless @_;
105 
106  my $msa = $self->db->get_MiscSetAdaptor();
107  my @sets = ();
108  my $max_len = 0;
109  foreach my $set_code (@_) {
110  my $set = $msa->fetch_by_code($set_code);
111  if($set) {
112  $max_len = $set->longest_feature if $set->longest_feature > $max_len;
113  push @sets, $set->dbID;
114  } else {
115  warning("No misc_set with code [$set_code] exists");
116  }
117  }
118  my $constraint;
119  if( @sets > 1 ) {
120  $constraint = " mfms.misc_set_id in ( @{[join ',',@sets]} ) ";
121  } elsif( @sets == 1 ) {
122  $constraint = " mfms.misc_set_id = $sets[0] ";
123  } else {
124  return [];
125  }
126 
127  $self->_max_feature_length($max_len);
128 
129  my $results = $self->fetch_all_by_Slice_constraint($slice, $constraint);
130 
131  $self->_max_feature_length(undef);
132 
133  return $results;
134 }
135 
136 
137 
138 =head2 fetch_all_by_attribute_type_value
139 
140  Arg [1] : string $attrib_type_code
141  The code of the attribute type to fetch features for
142  Arg [2] : (optional) string $attrib_value
143  The value of the attribute to fetch features for
144  Example :
145  #get all misc features that have an embl accession
146  @feats = @{$mfa->fetch_all_by_attrib_type_value('embl_acc')};
147  #get the misc feature with synonym 'AL014121'
148  ($feat)=@{$mfa->fetch_all_by_attrib_type_value('synonym','AL014121');
149  Description: Retrieves MiscFeatures which have a particular attribute.
150  If the attribute value argument is also provided only
151  features which have the attribute AND a particular value
152  are returned. The features are returned in their native
153  coordinate system (i.e. the coordinate system that they
154  are stored in).
155  Returntype : listref of Bio::EnsEMBL::MiscFeatures
156  Exceptions : throw if attrib_type code arg is not provided
157  Caller : general
158  Status : Stable
159 
160 =cut
161 
162 sub fetch_all_by_attribute_type_value {
163  my $self = shift;
164  my $attrib_type_code = shift;
165  my $attrib_value = shift;
166 
167  throw("Attrib type code argument is required.")
168  if ( !$attrib_type_code );
169 
170  # Need to do 2 queries so that all of the ids come back with the
171  # features. The problem with adding attrib constraints to filter the
172  # misc_features which come back is that not all of the attributes will
173  # come back
174 
175  my $sql = qq(
176  SELECT DISTINCT
177  ma.misc_feature_id
178  FROM misc_attrib ma,
179  attrib_type at,
180  misc_feature mf,
181  seq_region sr,
182  coord_system cs
183  WHERE ma.attrib_type_id = at.attrib_type_id
184  AND at.code = ?
185  AND ma.misc_feature_id = mf.misc_feature_id
186  AND mf.seq_region_id = sr.seq_region_id
187  AND sr.coord_system_id = cs.coord_system_id
188  AND cs.species_id = ?);
189 
190  if ($attrib_value) {
191  $sql .= " AND ma.value = ?";
192  }
193 
194  my $sth = $self->prepare($sql);
195 
196  $sth->bind_param( 1, $attrib_type_code, SQL_VARCHAR );
197  $sth->bind_param( 2, $self->species_id(), SQL_INTEGER );
198  if ($attrib_value) {
199  $sth->bind_param( 3, $attrib_value, SQL_VARCHAR );
200  }
201 
202  $sth->execute();
203 
204  my @ids = map { $_->[0] } @{ $sth->fetchall_arrayref() };
205 
206  $sth->finish();
207 
208  # Construct constraints from the list of ids. Split ids into groups
209  # of 1000 to ensure that the query is not too big.
210  my @constraints;
211  while (@ids) {
212  my @subset = splice( @ids, 0, 1000 );
213  if ( @subset == 1 ) {
214  push @constraints, "mf.misc_feature_id = $subset[0]";
215  } else {
216  my $id_str = join( ',', @subset );
217  push @constraints, "mf.misc_feature_id in ($id_str)";
218  }
219  }
220 
221  my @results;
222  foreach my $constraint (@constraints) {
223  push @results, @{ $self->generic_fetch($constraint) };
224  }
225 
226  return \@results;
227 } ## end sub fetch_all_by_attribute_type_value
228 
229 
230 =head2 fetch_by_attribute_set_value
231 
232  Arg [1] : string $attrib_type_code
233  The code of the attribute type to fetch features for
234  Arg [2] : (optional) string $attrib_value
235  The value of the attribute to fetch features for
236  Arg [3] : (optional) string $misc_set
237  The name of the set to which the feature belongs
238  Example :
239  $feat = $mfa->fetch_by_attribute_set_value('clone', 'RP11-411G9', 'tilepath');
240  # Get the clone belonging to the tilepath
241  Description: Retrieves MiscFeatures which have a particular attribute.
242  If the attribute value argument is also provided only
243  features which have the attribute AND a particular value
244  are returned. The features are returned in their native
245  coordinate system (i.e. the coordinate system that they
246  are stored in).
247  Returntype : listref of Bio::EnsEMBL::MiscFeatures
248  Exceptions : throw if attrib_type code arg is not provided
249  Caller : general
250  Status : Stable
251 
252 =cut
253 
254 sub fetch_by_attribute_set_value {
255  my $self = shift;
256  my $attrib_type_code = shift;
257  my $attrib_value = shift;
258  my $misc_set = shift;
259 
260  throw("Attrib type code argument is required.")
261  if ( !$attrib_type_code );
262 
263  # Need to do 2 queries so that all of the ids come back with the
264  # features. The problem with adding attrib constraints to filter the
265  # misc_features which come back is that not all of the attributes will
266  # come back
267 
268  my $sql = qq(
269  SELECT DISTINCT
270  ma.misc_feature_id
271  FROM misc_attrib ma,
272  attrib_type at,
273  misc_feature mf,
274  misc_feature_misc_set mfs,
275  misc_set ms,
276  seq_region sr,
277  coord_system cs
278  WHERE ma.attrib_type_id = at.attrib_type_id
279  AND at.code = ?
280  AND ma.misc_feature_id = mf.misc_feature_id
281  AND mf.misc_feature_id = mfs.misc_feature_id
282  AND mfs.misc_set_id = ms.misc_set_id
283  AND mf.seq_region_id = sr.seq_region_id
284  AND sr.coord_system_id = cs.coord_system_id
285  AND ma.value = ?
286  AND ms.code = ?
287  AND cs.species_id = ?);
288 
289  my $sth = $self->prepare($sql);
290 
291  $sth->bind_param( 1, $attrib_type_code, SQL_VARCHAR );
292  $sth->bind_param( 2, $attrib_value, SQL_VARCHAR );
293  $sth->bind_param( 3, $misc_set, SQL_VARCHAR );
294  $sth->bind_param( 4, $self->species_id(), SQL_INTEGER );
295 
296  $sth->execute();
297 
298  my ($id) = $sth->fetchrow_array();
299 
300  if (!$id) {
301  return;
302  }
303 
304  $sth->finish();
305 
306  my $constraint = "mf.misc_feature_id = $id";
307 
308  my ($result) = @{$self->generic_fetch($constraint)};
309 
310  return $result;
311 } ## end sub fetch_by_attribute_set_value
312 
313 
314 #_tables
315 #
316 # Arg [1] : none
317 # Example : none
318 # Description: PROTECTED Implementation of abstract superclass method to
319 # provide the name of the tables to query
320 # Returntype : string
321 # Exceptions : none
322 # Caller : internal
323 
324 
325 sub _tables {
326  my $self = shift;
327 
328  return (['misc_feature', 'mf'],
329  ['misc_feature_misc_set', 'mfms'],
330  ['misc_attrib', 'ma'],
331  ['attrib_type', 'at']);
332 }
333 
334 
335 #_columns
336 
337 # Arg [1] : none
338 # Example : none
339 # Description: PROTECTED Implementation of abstract superclass method to
340 # provide the name of the columns to query
341 # Returntype : list of strings
342 # Exceptions : none
343 # Caller : internal
344 
345 sub _columns {
346  my $self = shift;
347 
348  #warning _objs_from_sth implementation depends on ordering
349  return qw (mf.misc_feature_id
350  mf.seq_region_id
351  mf.seq_region_start
352  mf.seq_region_end
353  mf.seq_region_strand
354  ma.value
355  at.code
356  mfms.misc_set_id
357  at.name
358  at.description);
359 }
360 
361 
362 
363 # _default_where_clause
364 
365 # Arg [1] : none
366 # Example : none
367 # Description: Overrides superclass method to provide an additional
368 # table joining constraint before the SQL query is performed.
369 # Returntype : string
370 # Exceptions : none
371 # Caller : generic_fetch
372 
373 sub _default_where_clause {
374  my $self = shift;
375 
376  return '';
377 }
378 
379 
380 sub _left_join {
381  my $self = shift;
382 
383  return(
384  ['misc_feature_misc_set','mf.misc_feature_id = mfms.misc_feature_id'],
385  ['misc_attrib', 'mf.misc_feature_id = ma.misc_feature_id'],
386  ['attrib_type','ma.attrib_type_id = at.attrib_type_id']);
387 }
388 
389 
390 sub _final_clause {
391  my $self = shift;
392 
393  return " ORDER BY mf.misc_feature_id";
394 }
395 
396 
397 # _objs_from_sth
398 
399 # Arg [1] : StatementHandle $sth
400 # Example : none
401 # Description: PROTECTED implementation of abstract superclass method.
402 # responsible for the creation of MiscFeatures from a
403 # hashref generated from an SQL query
404 # Returntype : listref of Bio::EnsEMBL::MiscFeatures
405 # Exceptions : none
406 # Caller : internal
407 
408 sub _objs_from_sth {
409  my ($self, $sth, $mapper, $dest_slice) = @_;
410 
411  #
412  # This code is ugly because an attempt has been made to remove as many
413  # function calls as possible for speed purposes. Thus many caches and
414  # a fair bit of gymnastics is used.
415  #
416 
417  my $sa = $self->db()->get_SliceAdaptor();
418  my $msa = $self->db()->get_MiscSetAdaptor();
419 
420  my @features;
421  my %ms_hash;
422  my %slice_hash;
423  my %sr_name_hash;
424  my %sr_cs_hash;
425 
426  my(
427  $misc_feature_id, $seq_region_id, $seq_region_start,
428  $seq_region_end, $seq_region_strand,
429  $attrib_value, $attrib_type_code, $misc_set_id,
430  $attrib_type_name, $attrib_type_description );
431 
432  $sth->bind_columns( \$misc_feature_id, \$seq_region_id, \$seq_region_start,
433  \$seq_region_end, \$seq_region_strand,
434  \$attrib_value, \$attrib_type_code,\$misc_set_id,
435  \$attrib_type_name, \$attrib_type_description );
436 
437  my $dest_slice_start;
438  my $dest_slice_end;
439  my $dest_slice_strand;
440  my $dest_slice_length;
441  my $dest_slice_cs;
442  my $dest_slice_sr_name;
443  my $dest_slice_sr_id;
444  my $asma;
445 
446  if ($dest_slice) {
447  $dest_slice_start = $dest_slice->start();
448  $dest_slice_end = $dest_slice->end();
449  $dest_slice_strand = $dest_slice->strand();
450  $dest_slice_length = $dest_slice->length();
451  $dest_slice_cs = $dest_slice->coord_system();
452  $dest_slice_sr_name = $dest_slice->seq_region_name();
453  $dest_slice_sr_id = $dest_slice->get_seq_region_id();
454  $asma = $self->db->get_AssemblyMapperAdaptor();
455  }
456 
457  my $current = -1;
458  my $throw_away = -1;
459  my $feat;
460  my $feat_misc_sets;
461  my $feat_attribs;
462  my $seen_attribs;
463 
464  FEATURE: while($sth->fetch()) {
465  #if this feature is not being used, skip all rows related to it
466  next if($throw_away == $misc_feature_id);
467 
468  if ($current == $misc_feature_id) {
469  #still working on building up attributes and sets for current feature
470 
471  #if there is a misc_set, add it to the current feature
472  if ($misc_set_id) {
473  my $misc_set = $ms_hash{$misc_set_id} ||=
474  $msa->fetch_by_dbID($misc_set_id);
475  if ( ! exists $feat_misc_sets->{$misc_set->{'code'}} ) {
476  $feat->add_MiscSet( $misc_set );
477  $feat_misc_sets->{$misc_set->{'code'}} = $misc_set;
478  }
479  }
480 
481  #if there is a new attribute add it to the current feature
482  if ($attrib_value && $attrib_type_code && !$seen_attribs->{"$attrib_type_code:$attrib_value"}) {
483  my $attrib = Bio::EnsEMBL::Attribute->new
484  ( -CODE => $attrib_type_code,
485  -NAME => $attrib_type_name,
486  -DESC => $attrib_type_description,
487  -VALUE => $attrib_value
488  );
489 
490 
491  $feat_attribs ||= [];
492  push @$feat_attribs, $attrib;
493  $seen_attribs->{"$attrib_type_code:$attrib_value"} = 1;
494  }
495 
496  } else {
497  if ($feat) {
498  #start working on a new feature, discard references to last one
499  $feat = {};
500  $feat_attribs = [];
501  $feat_misc_sets = {};
502  $seen_attribs = {};
503  }
504 
505  $current = $misc_feature_id;
506  #need to get the internal_seq_region, if present
507  $seq_region_id = $self->get_seq_region_id_internal($seq_region_id);
508  my $slice = $slice_hash{"ID:".$seq_region_id};
509 
510  if (!$slice) {
511  $slice = $sa->fetch_by_seq_region_id($seq_region_id);
512  $slice_hash{"ID:".$seq_region_id} = $slice;
513  $sr_name_hash{$seq_region_id} = $slice->seq_region_name();
514  $sr_cs_hash{$seq_region_id} = $slice->coord_system();
515  }
516 
517  if(!$mapper && $dest_slice && !$dest_slice_cs->equals($slice->coord_system)) {
518  $mapper = $asma->fetch_by_CoordSystems($dest_slice_cs, $slice->coord_system);
519  }
520 
521  my $sr_name = $sr_name_hash{$seq_region_id};
522  my $sr_cs = $sr_cs_hash{$seq_region_id};
523 
524  #
525  # remap the feature coordinates to another coord system
526  # if a mapper was provided
527  #
528  if ($mapper) {
529 
530  if (defined $dest_slice && $mapper->isa('Bio::EnsEMBL::ChainedAssemblyMapper') ) {
531  ($seq_region_id, $seq_region_start,$seq_region_end, $seq_region_strand) =
532  $mapper->map($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs, 1, $dest_slice);
533 
534  } else {
535  ($seq_region_id, $seq_region_start,$seq_region_end, $seq_region_strand) =
536  $mapper->fastmap($sr_name, $seq_region_start, $seq_region_end,$seq_region_strand, $sr_cs);
537  }
538 
539  #skip features that map to gaps or coord system boundaries
540  if(!defined($seq_region_id)) {
541  $throw_away = $misc_feature_id;
542  next FEATURE;
543  }
544 
545  #get a slice in the coord system we just mapped to
546  $slice = $slice_hash{"ID:".$seq_region_id} ||= $sa->fetch_by_seq_region_id($seq_region_id);
547  }
548 
549  #
550  # If a destination slice was provided convert the coords
551  #
552  if ($dest_slice) {
553  my $seq_region_len = $dest_slice->seq_region_length();
554 
555  if ($dest_slice_strand == 1) { # Positive strand
556  $seq_region_start = $seq_region_start - $dest_slice_start + 1;
557  $seq_region_end = $seq_region_end - $dest_slice_start + 1;
558 
559  if ($dest_slice->is_circular()) {
560  # Handle cicular chromosomes.
561 
562  if ($seq_region_start > $seq_region_end) {
563  # Looking at a feature overlapping the chromsome origin.
564 
565  if ($seq_region_end > $dest_slice_start) {
566  # Looking at the region in the beginning of the chromosome.
567  $seq_region_start -= $seq_region_len;
568  }
569  if ($seq_region_end < 0) {
570  $seq_region_end += $seq_region_len;
571  }
572  } else {
573  if ($dest_slice_start > $dest_slice_end && $seq_region_end < 0) {
574  # Looking at the region overlapping the chromosome
575  # origin and a feature which is at the beginning of the
576  # chromosome.
577  $seq_region_start += $seq_region_len;
578  $seq_region_end += $seq_region_len;
579  }
580  }
581  } ## end if ($dest_slice->is_circular...)
582  } else { # Negative strand
583 
584  my $start = $dest_slice_end - $seq_region_end + 1;
585  my $end = $dest_slice_end - $seq_region_start + 1;
586 
587  if ($dest_slice->is_circular()) {
588 
589  if ($dest_slice_start > $dest_slice_end) {
590  # slice spans origin or replication
591 
592  if ($seq_region_start >= $dest_slice_start) {
593  $end += $seq_region_len;
594  $start += $seq_region_len if $seq_region_end > $dest_slice_start;
595 
596  } elsif ($seq_region_start <= $dest_slice_end) {
597  # do nothing
598  } elsif ($seq_region_end >= $dest_slice_start) {
599  $start += $seq_region_len;
600  $end += $seq_region_len;
601 
602  } elsif ($seq_region_end <= $dest_slice_end) {
603  $end += $seq_region_len if $end < 0;
604 
605  } elsif ($seq_region_start > $seq_region_end) {
606  $end += $seq_region_len;
607  }
608  } else {
609 
610  if ($seq_region_start <= $dest_slice_end and $seq_region_end >= $dest_slice_start) {
611  # do nothing
612  } elsif ($seq_region_start > $seq_region_end) {
613  if ($seq_region_start <= $dest_slice_end) {
614  $start -= $seq_region_len;
615  } elsif ($seq_region_end >= $dest_slice_start) {
616  $end += $seq_region_len;
617  }
618  }
619  }
620  }
621 
622  $seq_region_start = $start;
623  $seq_region_end = $end;
624  $seq_region_strand *= -1;
625 
626  } ## end else [ if ($dest_slice_strand...)]
627 
628  #throw away features off the end of the requested slice
629  if ($seq_region_end < 1 || $seq_region_start > $dest_slice_length ||
630  $dest_slice_sr_id != $seq_region_id) {
631  #flag this feature as one to throw away
632  $throw_away = $misc_feature_id;
633  next FEATURE;
634  }
635 
636  $slice = $dest_slice;
637  }
638 
639 
640  if ($attrib_value && $attrib_type_code) {
641  my $attrib = Bio::EnsEMBL::Attribute->new
642  ( -CODE => $attrib_type_code,
643  -NAME => $attrib_type_name,
644  -DESC => $attrib_type_description,
645  -VALUE => $attrib_value
646  );
647  $feat_attribs = [$attrib];
648  $seen_attribs->{"$attrib_type_code:$attrib_value"} = 1;
649  }
650 
651  $feat =
652  $self->_create_feature_fast( 'Bio::EnsEMBL::MiscFeature', {
653  'start' => $seq_region_start,
654  'end' => $seq_region_end,
655  'strand' => $seq_region_strand,
656  'slice' => $slice,
657  'adaptor' => $self,
658  'dbID' => $misc_feature_id,
659  'attributes' => $feat_attribs ||= []
660  } );
661 
662  push @features, $feat;
663 
664  if ($misc_set_id) {
665  #get the misc_set object
666  my $misc_set = $ms_hash{$misc_set_id} ||=
667  $msa->fetch_by_dbID($misc_set_id);
668  if ( ! exists $feat_misc_sets->{$misc_set->{'code'}} ) {
669  $feat->add_MiscSet( $misc_set );
670  $feat_misc_sets->{$misc_set->{'code'}} = $misc_set;
671  }
672  }
673  }
674  }
675 
676  return \@features;
677 }
678 
679 
680 
681 =head2 list_dbIDs
682 
683  Arg [1] : none
684  Example : @feature_ids = @{$misc_feature_adaptor->list_dbIDs()};
685  Description: Gets an array of internal ids for all misc_features in the
686  current db
687  Arg[1] : <optional> int. not 0 for the ids to be sorted by the seq_region.
688  Returntype : list of ints
689  Exceptions : none
690  Caller : ?
691  Status : Stable
692 
693 =cut
694 
695 sub list_dbIDs {
696  my ($self,$ordered) = @_;
697 
698  return $self->_list_dbIDs("misc_feature",undef,$ordered);
699 }
700 
701 
702 =head2 store
703 
704  Arg [1] : list of Bio::EnsEMBL::MiscFeatures @misc_features
705  Example : $misc_feature_adaptor->store(@misc_features);
706  Description: Stores a list of MiscFeatures in this database. The stored
707  features will have their
708  Returntype : none
709  Exceptions : throw on invalid arguments
710  warning if misc feature is already stored in this database
711  throw if start/end/strand attribs are not valid
712  Caller : general
713  Status : Stable
714 
715 =cut
716 
717 sub store {
718  my $self = shift;
719  my @misc_features = @_;
720 
721  my $db = $self->db();
722 
723  my $feature_sth = $self->prepare(
724  q{INSERT INTO misc_feature (
725  seq_region_id,
726  seq_region_start,
727  seq_region_end,
728  seq_region_strand
729  ) VALUES (?, ?, ?, ?)
730  });
731 
732  my $insert_ignore = $self->insert_ignore_clause();
733  my $feature_set_sth = $self->prepare(
734  qq{${insert_ignore} INTO misc_feature_misc_set (
735  misc_feature_id,
736  misc_set_id
737  ) VALUES (?, ?)
738  });
739 
740  my $msa = $db->get_MiscSetAdaptor();
741  my $aa = $db->get_AttributeAdaptor();
742 
743  FEATURE:
744  foreach my $mf (@misc_features) {
745  if(!ref($mf) || !$mf->isa('Bio::EnsEMBL::MiscFeature')) {
746  throw("List of MiscFeature arguments expeceted");
747  }
748 
749  if($mf->is_stored($db)) {
750  warning("MiscFeature [" .$mf->dbID."] is already stored in database.");
751  next FEATURE;
752  }
753 
754  # do some checking of the start/end and convert to seq_region coords
755  my $original = $mf;
756  my $seq_region_id;
757  ($mf, $seq_region_id) = $self->_pre_store($mf);
758 
759  # store the actual MiscFeature
760  $feature_sth->bind_param(1,$seq_region_id,SQL_INTEGER);
761  $feature_sth->bind_param(2,$mf->start,SQL_INTEGER);
762  $feature_sth->bind_param(3,$mf->end,SQL_INTEGER);
763  $feature_sth->bind_param(4,$mf->strand,SQL_TINYINT);
764  $feature_sth->execute();
765 
766  my $dbID = $self->last_insert_id('misc_feature_id', undef, 'misc_feature');
767 
768  $mf->dbID($dbID);
769  $mf->adaptor($self);
770 
771  # store all the attributes
772  my $attribs = $mf->get_all_Attributes();
773  $aa->store_on_MiscFeature($mf, $attribs);
774 
775  # store all the sets that have not been stored yet
776  my $sets = $mf->get_all_MiscSets();
777  foreach my $set (@$sets) {
778  $msa->store($set) if(!$set->is_stored($db));
779 
780  # update the misc_feat_misc_set table to store the set relationship
781  $feature_set_sth->bind_param(1,$dbID,SQL_INTEGER);
782  $feature_set_sth->bind_param(2,$set->dbID,SQL_INTEGER);
783 
784  $feature_set_sth->execute();
785  }
786  }
787 
788  return;
789 }
790 
791 1;
792 
793 
794 
795 
796 
Bio::EnsEMBL::DBSQL::MiscFeatureAdaptor
Definition: MiscFeatureAdaptor.pm:40
Bio::EnsEMBL::MiscSet
Definition: MiscSet.pm:31
map
public map()
Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
Definition: BaseFeatureAdaptor.pm:24
Bio::EnsEMBL::MiscFeature
Definition: MiscFeature.pm:86
Bio::EnsEMBL::DBSQL::BaseAdaptor::fetch_by_dbID
public Bio::EnsEMBL::Feature fetch_by_dbID()
accession
public accession()
Bio::EnsEMBL::Attribute::new
public Bio::EnsEMBL::Attribute new()
Bio::EnsEMBL::Slice
Definition: Slice.pm:50
Bio::EnsEMBL::Attribute
Definition: Attribute.pm:34
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68