3 See the NOTICE file distributed with
this work
for additional information
4 regarding copyright ownership.
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
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.
23 Please email comments or questions to the
public Ensembl
24 developers list at <http:
26 Questions may also be sent to the Ensembl help desk at
39 This
object is responisble
for all database interaction involving marker
40 features including the fetching and storing of marker features.
42 The bulk of
this objects
' methods are inherited from
43 Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
49 package Bio::EnsEMBL::Map::DBSQL::MarkerFeatureAdaptor;
53 use Bio::EnsEMBL::Map::MarkerFeature;
54 use Bio::EnsEMBL::Map::Marker;
55 use Bio::EnsEMBL::Map::MarkerSynonym;
56 use Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor;
58 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
62 @ISA = qw(Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor);
66 =head2 fetch_all_by_Marker
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
78 sub fetch_all_by_Marker {
82 my $constraint = 'm.marker_id =
' . $marker->dbID;
84 return $self->generic_fetch($constraint, @_);
87 =head2 fetch_all_by_Slice_and_MarkerName
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
100 sub fetch_all_by_Slice_and_MarkerName {
101 my ($self, $slice, $name) = @_;
102 return unless $slice && $name;
104 my $constraint = 'ms.name =
"' . $name . '"';
105 my $results = $self->fetch_all_by_Slice_constraint($slice, $constraint);
110 =head2 fetch_all_by_Slice_and_priority
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
127 sub fetch_all_by_Slice_and_priority {
128 my ($self, $slice, $priority, $map_weight, @args) = @_;
131 if(defined $priority) {
132 $constraint = "m.priority > $priority";
135 if(defined $map_weight) {
137 $constraint .= " AND mf.map_weight < $map_weight";
139 $constraint = "mf.map_weight < $map_weight";
143 return $self->fetch_all_by_Slice_constraint($slice, $constraint, @args);
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
');
162 return (['marker_feature
', 'mf
'], #primary table
164 ['marker_synonym
', 'ms
']);
170 return ( [ 'marker_synonym
',
171 'm.display_marker_synonym_id = ms.marker_synonym_id
' ] );
174 sub _default_where_clause {
177 return ('mf.marker_id = m.marker_id
');
181 my ($self, $sth, $mapper, $dest_slice) = @_;
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);
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);
203 my $marker_adp = $self->db->get_MarkerAdaptor;
204 my $sa = $self->db->get_SliceAdaptor;
205 my $analysis_adp = $self->db->get_AnalysisAdaptor;
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();
222 my $dest_slice_start;
224 my $dest_slice_strand;
225 my $dest_slice_length;
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();
233 FEATURE: while($sth->fetch) {
234 #create a new marker unless this one has been seen already
236 if(!($marker = $marker_cache{$marker_id})) {
237 #create a new marker synonym for the display synonym (if defined)
240 $ms = Bio::EnsEMBL::Map::MarkerSynonym->new
241 ($ms_id, $ms_source, $ms_name);
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;
252 #get the slice object
253 my $slice = $slice_hash{$seq_region_id};
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();
264 unless($analysis = $analysis_cache{$analysis_id}) {
265 $analysis = $analysis_adp->fetch_by_dbID($analysis_id);
266 $analysis_cache{$analysis_id} = $analysis;
270 # remap the feature coordinates to another coord system
271 # if a mapper was provided
274 # my $sr_name = $sr_name_hash{$seq_region_id};
275 my $sr_cs = $sr_cs_hash{$seq_region_id};
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);
280 #skip features that map to gaps or coord system boundaries
281 next FEATURE if(!defined($seq_region_id));
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);
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
293 my $seq_region_len = $dest_slice->seq_region_length();
295 if ($dest_slice_strand == 1) { # Positive strand
297 $seq_region_start = $seq_region_start - $dest_slice_start + 1;
298 $seq_region_end = $seq_region_end - $dest_slice_start + 1;
300 if ($dest_slice->is_circular()) {
301 # Handle cicular chromosomes.
303 if ($seq_region_start > $seq_region_end) {
304 # Looking at a feature overlapping the chromsome origin.
306 if ($seq_region_end > $dest_slice_start) {
308 # Looking at the region in the beginning of the
310 $seq_region_start -= $seq_region_len;
313 if ($seq_region_end < 0) {
314 $seq_region_end += $seq_region_len;
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
324 $seq_region_start += $seq_region_len;
325 $seq_region_end += $seq_region_len;
329 } ## end if ($dest_slice->is_circular...)
331 } else { # Negative strand
333 my $start = $dest_slice_end - $seq_region_end + 1;
334 my $end = $dest_slice_end - $seq_region_start + 1;
336 if ($dest_slice->is_circular()) {
338 if ($dest_slice_start > $dest_slice_end) {
339 # slice spans origin or replication
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;
346 } elsif ($seq_region_start <= $dest_slice_end) {
348 } elsif ($seq_region_end >= $dest_slice_start) {
349 $start += $seq_region_len;
350 $end += $seq_region_len;
352 } elsif ($seq_region_end <= $dest_slice_end) {
354 $end += $seq_region_len
357 } elsif ($seq_region_start > $seq_region_end) {
359 $end += $seq_region_len;
367 if ($seq_region_start <= $dest_slice_end and $seq_region_end >= $dest_slice_start) {
369 } elsif ($seq_region_start > $seq_region_end) {
370 if ($seq_region_start <= $dest_slice_end) {
372 $start -= $seq_region_len;
374 } elsif ($seq_region_end >= $dest_slice_start) {
375 $end += $seq_region_len;
385 $seq_region_start = $start;
386 $seq_region_end = $end;
388 } ## end else [ if ($dest_slice_strand...)]
390 # throw away features off the end of the requested slice
391 if($seq_region_end < 1 || $seq_region_start > $dest_slice_length) {
395 $slice = $dest_slice;
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);
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
419 Exceptions : thrown if not all data needed for storing is populated in the
427 my ($self, @mfs) = @_;
429 foreach my $mf (@mfs) {
435 $self->throw("Incorrect argument [$mf] to store. Expected " .
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.');
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');
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);
457 my $marker_id = $marker->dbID ||
458 throw(
'Associated Marker must have dbID to store MarkerFeature');
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');
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());
472 my $analysis_id = $analysis->dbID ||
473 throw(
'Associated Analysis must have dbID to store MarkerFeature');
475 # Store the marker feature itself
478 ($mf, $seq_region_id) = $self->_pre_store($mf);
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);
489 my $dbID = $self->last_insert_id(
'marker_feature_id', undef,
'marker_feature');
491 $original->dbID($dbID);
492 $original->adaptor($self);