ensembl-hive  2.8.1
MarkerFeatureAdaptor.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 =head1 DESCRIPTION
38 
39 This object is responisble for all database interaction involving marker
40 features including the fetching and storing of marker features.
41 
42 The bulk of this objects' methods are inherited from
43 Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
44 
45 =head1 METHODS
46 
47 =cut
48 
49 package Bio::EnsEMBL::Map::DBSQL::MarkerFeatureAdaptor;
50 
51 use strict;
52 
53 use Bio::EnsEMBL::Map::MarkerFeature;
54 use Bio::EnsEMBL::Map::Marker;
55 use Bio::EnsEMBL::Map::MarkerSynonym;
56 use Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor;
57 
58 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
59 
60 use vars qw(@ISA);
61 
62 @ISA = qw(Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor);
63 
64 
65 
66 =head2 fetch_all_by_Marker
67 
68  Arg [1] : Bio::EnsEMBL::Map::Marker
69  Example : @ms = @{$marker_feature_adaptor->fetch_by_Marker($mrkr)};
70  Description: Retrieves a list of MarkerFeatures for a given marker
71  Returntype : listref of Bio::EnsEMBL::MarkerFeatures
72  Exceptions : none
73  Caller : general
74  Status : stable
75 
76 =cut
77 
78 sub fetch_all_by_Marker {
79  my $self = shift;
80  my $marker = shift;
81 
82  my $constraint = 'm.marker_id = ' . $marker->dbID;
83 
84  return $self->generic_fetch($constraint, @_);
85 }
86 
87 =head2 fetch_all_by_Slice_and_MarkerName
88 
89  Arg [1] : Bio::EnsEMBL::Slice $slice
90  Arg [2] : string marker name
91  Example : @ms = @{$marker_feature_adaptor->fetch_all_by_Slice_and_MarkerName($slice, $name)};
92  Description: Retrieves a list of MarkerFeatures for a given marker name
93  Returntype : listref of Bio::EnsEMBL::Map::MarkerFeatures
94  Exceptions : none
95  Caller : general
96  Status : stable
97 
98 =cut
99 
100 sub fetch_all_by_Slice_and_MarkerName {
101  my ($self, $slice, $name) = @_;
102  return unless $slice && $name;
103 
104  my $constraint = 'ms.name = "' . $name . '"';
105  my $results = $self->fetch_all_by_Slice_constraint($slice, $constraint);
106  return $results;
107 }
108 
109 
110 =head2 fetch_all_by_Slice_and_priority
111 
112  Arg [1] : Bio::EnsEMBL::Slice $slice
113  Arg [2] : (optional) int $priority
114  Arg [3] : (optional) int $map_weight
115  Arg [3] : (optional) string $logic_name
116  Example : @feats = @{$mfa->fetch_all_by_Slice_and_priority($slice,80,2)};
117  Description: Retrieves all marker features above a specified threshold
118  priority which overlap the provided slice, below a
119  a specified map_weight.
120  Returntype : listref of Bio::EnsEMBL::Map::MarkerFeatures in slice coords
121  Exceptions : none
122  Caller : general
123  Status : stable
124 
125 =cut
126 
127 sub fetch_all_by_Slice_and_priority {
128  my ($self, $slice, $priority, $map_weight, @args) = @_;
129 
130  my $constraint = '';
131  if(defined $priority) {
132  $constraint = "m.priority > $priority";
133  }
134 
135  if(defined $map_weight) {
136  if($constraint) {
137  $constraint .= " AND mf.map_weight < $map_weight";
138  } else {
139  $constraint = "mf.map_weight < $map_weight";
140  }
141  }
142 
143  return $self->fetch_all_by_Slice_constraint($slice, $constraint, @args);
144 }
145 
146 
147 
148 sub _columns {
149  my $self = shift;
150 
151  return ('mf.marker_feature_id', 'mf.marker_id',
152  'mf.seq_region_id', 'mf.seq_region_start', 'mf.seq_region_end',
153  'mf.analysis_id', 'mf.map_weight',
154  'm.left_primer', 'm.right_primer', 'm.min_primer_dist',
155  'm.max_primer_dist', 'm.priority', 'm.type', 'ms.marker_synonym_id',
156  'ms.name', 'ms.source');
157 }
158 
159 sub _tables {
160  my $self = shift;
161 
162  return (['marker_feature', 'mf'], #primary table
163  ['marker', 'm'],
164  ['marker_synonym', 'ms']);
165 }
166 
167 sub _left_join {
168  my $self = shift;
169 
170  return ( [ 'marker_synonym',
171  'm.display_marker_synonym_id = ms.marker_synonym_id' ] );
172 }
173 
174 sub _default_where_clause {
175  my $self = shift;
176 
177  return ('mf.marker_id = m.marker_id');
178 }
179 
180 sub _objs_from_sth {
181  my ($self, $sth, $mapper, $dest_slice) = @_;
182 
183  my ($marker_feature_id, $marker_id,
184  $seq_region_id, $seq_region_start, $seq_region_end,
185  $analysis_id, $map_weight,
186  $left_primer, $right_primer, $min_primer_dist, $max_primer_dist,
187  $priority, $type, $ms_id, $ms_name, $ms_source);
188 
189  #warning: ordering depends on _columns function implementation
190  $sth->bind_columns(\$marker_feature_id, \$marker_id,
191  \$seq_region_id, \$seq_region_start, \$seq_region_end,
192  \$analysis_id, \$map_weight,
193  \$left_primer, \$right_primer, \$min_primer_dist, \$max_primer_dist,
194  \$priority, \$type, \$ms_id, \$ms_name, \$ms_source);
195 
196  my @out = ();
197 
198  my %marker_cache;
199  my %slice_hash;
200 # my %sr_name_hash;
201  my %sr_cs_hash;
202  my %analysis_cache;
203  my $marker_adp = $self->db->get_MarkerAdaptor;
204  my $sa = $self->db->get_SliceAdaptor;
205  my $analysis_adp = $self->db->get_AnalysisAdaptor;
206 
207  my $asm_cs;
208  my $cmp_cs;
209  my $asm_cs_vers;
210  my $asm_cs_name;
211  my $cmp_cs_vers;
212  my $cmp_cs_name;
213  if($mapper) {
214  $asm_cs = $mapper->assembled_CoordSystem();
215  $cmp_cs = $mapper->component_CoordSystem();
216  $asm_cs_name = $asm_cs->name();
217  $asm_cs_vers = $asm_cs->version();
218  $cmp_cs_name = $cmp_cs->name();
219  $cmp_cs_vers = $cmp_cs->version();
220  }
221 
222  my $dest_slice_start;
223  my $dest_slice_end;
224  my $dest_slice_strand;
225  my $dest_slice_length;
226  if($dest_slice) {
227  $dest_slice_start = $dest_slice->start();
228  $dest_slice_end = $dest_slice->end();
229  $dest_slice_strand = $dest_slice->strand();
230  $dest_slice_length = $dest_slice->length();
231  }
232 
233  FEATURE: while($sth->fetch) {
234  #create a new marker unless this one has been seen already
235  my $marker;
236  if(!($marker = $marker_cache{$marker_id})) {
237  #create a new marker synonym for the display synonym (if defined)
238  my $ms;
239  if($ms_id) {
240  $ms = Bio::EnsEMBL::Map::MarkerSynonym->new
241  ($ms_id, $ms_source, $ms_name);
242  }
243 
244  #create a new marker
245  $marker = Bio::EnsEMBL::Map::Marker->new
246  ($marker_id, $marker_adp,
247  $left_primer, $right_primer, $min_primer_dist, $max_primer_dist,
248  $priority, $type, $ms);
249  $marker_cache{$marker_id} = $marker;
250  }
251 
252  #get the slice object
253  my $slice = $slice_hash{$seq_region_id};
254 
255  if(!$slice) {
256  $slice = $sa->fetch_by_seq_region_id($seq_region_id);
257  $slice_hash{$seq_region_id} = $slice;
258 # $sr_name_hash{$seq_region_id} = $slice->seq_region_name();
259  $sr_cs_hash{$seq_region_id} = $slice->coord_system();
260  }
261 
262  #retrieve analysis
263  my $analysis;
264  unless($analysis = $analysis_cache{$analysis_id}) {
265  $analysis = $analysis_adp->fetch_by_dbID($analysis_id);
266  $analysis_cache{$analysis_id} = $analysis;
267  }
268 
269  #
270  # remap the feature coordinates to another coord system
271  # if a mapper was provided
272  #
273  if($mapper) {
274 # my $sr_name = $sr_name_hash{$seq_region_id};
275  my $sr_cs = $sr_cs_hash{$seq_region_id};
276 
277  ($seq_region_id,$seq_region_start,$seq_region_end) =
278  $mapper->fastmap($slice->seq_region_name(), $seq_region_start, $seq_region_end, 0, $sr_cs);
279 
280  #skip features that map to gaps or coord system boundaries
281  next FEATURE if(!defined($seq_region_id));
282 
283  #get a slice in the coord system we just mapped to
284  $slice = $slice_hash{"$seq_region_id"} ||=
285  $sa->fetch_by_seq_region_id($seq_region_id);
286  }
287 
288  #
289  # If a destination slice was provided convert the coords
290  # If the dest_slice starts at 1 and is foward strand, nothing needs doing
291  #
292  if($dest_slice) {
293  my $seq_region_len = $dest_slice->seq_region_length();
294 
295  if ($dest_slice_strand == 1) { # Positive strand
296 
297  $seq_region_start = $seq_region_start - $dest_slice_start + 1;
298  $seq_region_end = $seq_region_end - $dest_slice_start + 1;
299 
300  if ($dest_slice->is_circular()) {
301  # Handle cicular chromosomes.
302 
303  if ($seq_region_start > $seq_region_end) {
304  # Looking at a feature overlapping the chromsome origin.
305 
306  if ($seq_region_end > $dest_slice_start) {
307 
308  # Looking at the region in the beginning of the
309  # chromosome.
310  $seq_region_start -= $seq_region_len;
311  }
312 
313  if ($seq_region_end < 0) {
314  $seq_region_end += $seq_region_len;
315  }
316 
317  } else {
318 
319  if ( $dest_slice_start > $dest_slice_end
320  && $seq_region_end < 0) {
321  # Looking at the region overlapping the chromosome
322  # origin and a feature which is at the beginning of the
323  # chromosome.
324  $seq_region_start += $seq_region_len;
325  $seq_region_end += $seq_region_len;
326  }
327  }
328 
329  } ## end if ($dest_slice->is_circular...)
330 
331  } else { # Negative strand
332 
333  my $start = $dest_slice_end - $seq_region_end + 1;
334  my $end = $dest_slice_end - $seq_region_start + 1;
335 
336  if ($dest_slice->is_circular()) {
337 
338  if ($dest_slice_start > $dest_slice_end) {
339  # slice spans origin or replication
340 
341  if ($seq_region_start >= $dest_slice_start) {
342  $end += $seq_region_len;
343  $start += $seq_region_len
344  if $seq_region_end > $dest_slice_start;
345 
346  } elsif ($seq_region_start <= $dest_slice_end) {
347  # do nothing
348  } elsif ($seq_region_end >= $dest_slice_start) {
349  $start += $seq_region_len;
350  $end += $seq_region_len;
351 
352  } elsif ($seq_region_end <= $dest_slice_end) {
353 
354  $end += $seq_region_len
355  if $end < 0;
356 
357  } elsif ($seq_region_start > $seq_region_end) {
358 
359  $end += $seq_region_len;
360 
361  } else {
362 
363  }
364 
365  } else {
366 
367  if ($seq_region_start <= $dest_slice_end and $seq_region_end >= $dest_slice_start) {
368  # do nothing
369  } elsif ($seq_region_start > $seq_region_end) {
370  if ($seq_region_start <= $dest_slice_end) {
371 
372  $start -= $seq_region_len;
373 
374  } elsif ($seq_region_end >= $dest_slice_start) {
375  $end += $seq_region_len;
376 
377  } else {
378 
379  }
380  }
381  }
382 
383  }
384 
385  $seq_region_start = $start;
386  $seq_region_end = $end;
387 
388  } ## end else [ if ($dest_slice_strand...)]
389 
390  # throw away features off the end of the requested slice
391  if($seq_region_end < 1 || $seq_region_start > $dest_slice_length) {
392  next FEATURE;
393  }
394 
395  $slice = $dest_slice;
396  }
397 
398  #now create a new marker_feature using the marker
399  push @out, Bio::EnsEMBL::Map::MarkerFeature->new
400  ($marker_feature_id, $self,
401  $seq_region_start, $seq_region_end, $slice,
402  $analysis, $marker_id, $map_weight, $marker);
403  }
404 
405  return \@out;
406 }
407 
408 
409 
410 
411 =head2 store
412 
413  Arg [1] : Bio::EnsEMBL::Map::MarkerFeature
414  Example : $marker_feature_adaptor->store(@marker_features);
415  Description: Stores a list of marker features in this database.
416  The dbID and adaptor of each marker will be set on successful
417  storing.
418  Returntype : none
419  Exceptions : thrown if not all data needed for storing is populated in the
420  marker features
421  Caller : general
422  Status : stable
423 
424 =cut
425 
426 sub store {
427  my ($self, @mfs) = @_;
428 
429  foreach my $mf (@mfs) {
430 
431  #
432  # Sanity checking!
433  #
434  if(!ref($mf) || !$mf->isa('Bio::EnsEMBL::Map::MarkerFeature')) {
435  $self->throw("Incorrect argument [$mf] to store. Expected " .
437  }
438 
439  #don't store this feature if it has already been stored
440  if($mf->is_stored($self->db())) {
441  warning('MarkerFeature ['.$mf->dbID.'] is already stored in this DB.');
442  next;
443  }
444 
445  # Get/test the marker
446  my $marker = $mf->marker;
447  if(!$marker || !ref($marker) ||
448  !$marker->isa('Bio::EnsEMBL::Map::Marker')) {
449  throw('Cannot store MarkerFeature without an associated Marker');
450  }
451 
452  #store the marker if it has not been stored yet
453  if(!$marker->is_stored($self->db())) {
454  my $marker_adaptor = $self->db->get_adaptor('Marker');
455  $marker_adaptor->store($marker);
456  }
457  my $marker_id = $marker->dbID ||
458  throw('Associated Marker must have dbID to store MarkerFeature');
459 
460  # Get/test the analysis
461  my $analysis = $mf->analysis;
462  if(!$analysis || !ref($analysis) ||
463  !$analysis->isa('Bio::EnsEMBL::Analysis')) {
464  throw('Cannot store MarkerFeature without an associated Analysis');
465  }
466 
467  #store the analysis if it has not been stored yet
468  if(!$analysis->is_stored($self->db())) {
469  my $analysis_adaptor = $self->db->get_adaptor('Analysis');
470  $analysis_adaptor->store($mf->analysis());
471  }
472  my $analysis_id = $analysis->dbID ||
473  throw('Associated Analysis must have dbID to store MarkerFeature');
474 
475  # Store the marker feature itself
476  my $original = $mf;
477  my $seq_region_id;
478  ($mf, $seq_region_id) = $self->_pre_store($mf);
479 
480  my $sth =
481  $self->prepare("INSERT INTO marker_feature (marker_id,
482  seq_region_id, seq_region_start, seq_region_end,
483  analysis_id, map_weight)
484  VALUES (?, ?, ?, ?, ?, ?)");
485  $sth->execute($marker_id,
486  $seq_region_id, $mf->start, $mf->end,
487  $analysis_id, $mf->map_weight || 0);
488 
489  my $dbID = $self->last_insert_id('marker_feature_id', undef, 'marker_feature');
490 
491  $original->dbID($dbID);
492  $original->adaptor($self);
493  }
494 }
495 
496 
497 1;
Bio::EnsEMBL::Map::DBSQL::MarkerFeatureAdaptor
Definition: MarkerFeatureAdaptor.pm:23
Bio::EnsEMBL::Map::MarkerFeature
Definition: MarkerFeature.pm:16