Raw content of Bio::EnsEMBL::Map::DBSQL::MarkerAdaptor =head1 LICENSE Copyright (c) 1999-2009 The European Bioinformatics Institute and Genome Research Limited. All rights reserved. This software is distributed under a modified Apache license. For license details, please see /info/about/code_licence.html =head1 CONTACT Please email comments or questions to the public Ensembl developers list at <ensembl-dev@ebi.ac.uk>. Questions may also be sent to the Ensembl help desk at <helpdesk@ensembl.org>. =cut =head1 NAME Bio::EnsEMBL::Map::DBSQL::MarkerAdaptor =head1 SYNOPSIS =head1 DESCRIPTION Provides database interaction for the Bio::EnsEMBL::Map::Marker object =head1 METHODS =cut package Bio::EnsEMBL::Map::DBSQL::MarkerAdaptor; use strict; use vars ('@ISA'); use Bio::EnsEMBL::Map::Marker; use Bio::EnsEMBL::Map::MapLocation; use Bio::EnsEMBL::Map::MarkerSynonym; use Bio::EnsEMBL::DBSQL::BaseAdaptor; use Bio::EnsEMBL::Utils::Exception qw(warning); @ISA = qw(Bio::EnsEMBL::DBSQL::BaseAdaptor); =head2 fetch_all Arg [1] : none Example : @all_markers = @{$marker_adaptor->fetch_all}; Description: Retrieves all markers from the database Returntype : listref of Bio::EnsEMBL::Map::Markers Exceptions : none Caller : general Status : stable =cut sub fetch_all { my $self = shift; my $dbID = shift; my $sth = $self->prepare("SELECT m.marker_id, m.priority, m.left_primer, m.right_primer, m.type, m.min_primer_dist, m.max_primer_dist, ms.marker_synonym_id, ms.name, ms.source FROM marker m LEFT JOIN marker_synonym ms ON ms.marker_synonym_id = m.display_marker_synonym_id"); $sth->execute; my( $marker_id, $priority, $left_primer, $right_primer, $type, $min_pdist, $max_pdist, $ms_id, $ms_name, $ms_src); $sth->bind_columns(\$marker_id, \$priority, \$left_primer, \$right_primer, \$type, \$min_pdist, \$max_pdist, \$ms_id, \$ms_name, \$ms_src); my @out; while($sth->fetch) { #create a display marker synonym for each marker created, if one is defined my $synonym; if($ms_id) { $synonym = Bio::EnsEMBL::Map::MarkerSynonym->new ($ms_id, $ms_src, $ms_name); } push @out, Bio::EnsEMBL::Map::Marker->new ($marker_id, $self, $left_primer, $right_primer, $min_pdist, $max_pdist, $priority, $type, $synonym); } return \@out; } =head2 fetch_by_dbID Arg [1] : int $dbID The internal identifier of the Marker to retrieve Example : $marker = $marker_adaptor->fetch_by_dbID(123); Description: Retrieves a marker object from the database via its internal identifier. Returntype : Bio::EnsEMBL::Map::Marker Exceptions : thrown if no marker with $dbID is present in the database Caller : general Status : stable =cut sub fetch_by_dbID { my $self = shift; my $dbID = shift; $self->throw('dbID argument is required') unless($dbID); my $sth = $self->prepare("SELECT m.marker_id, m.display_marker_synonym_id, m.priority, m.left_primer, m.right_primer, m.type, m.min_primer_dist, m.max_primer_dist, ms.marker_synonym_id, ms.source, ms.name FROM marker m, marker_synonym ms WHERE m.marker_id = ? AND ms.marker_id = m.marker_id"); $sth->execute($dbID); my( $marker_id, $display_ms_id, $priority, $left_primer, $right_primer, $type, $min_pdist, $max_pdist, $ms_id, $ms_src, $ms_name); $sth->bind_columns(\$marker_id, \$display_ms_id, \$priority, \$left_primer, \$right_primer, \$type, \$min_pdist, \$max_pdist, \$ms_id, \$ms_src, \$ms_name); my $display_synonym; my @synonyms; while($sth->fetch) { #create a new synonym for each row my $s = new Bio::EnsEMBL::Map::MarkerSynonym->new($ms_id, $ms_src, $ms_name); $display_synonym = $s if($display_ms_id == $ms_id); push @synonyms, $s; } $sth->finish; unless($marker_id) { $self-> warning("marker with dbID=[$dbID] not present in database"); return undef; } #now create the marker return new Bio::EnsEMBL::Map::Marker->new( $marker_id, $self, $left_primer, $right_primer,$min_pdist, $max_pdist, $priority, $type,$display_synonym, \@synonyms); } =head2 fetch_all_by_synonym Arg [1] : string $synonym An name of this marker Arg [2] : (opional) string $source The source of this name Example : @markers = @{$marker_adaptor->fetch_all_by_synonym($id)}; Description: Retrieves a list of markers with the synonym (alias) $synonym and from source $source. In most cases the list will have a single element, however it is possible that multiple markers with the same synonym exist. Returntype : listref of Bio::EnsEMBL::Map::Markers Exceptions : none Caller : general Status : stable =cut sub fetch_all_by_synonym { my ($self, $synonym, $source) = @_; $self->throw("synonym argument is required") unless($synonym); my $q = "SELECT marker_id FROM marker_synonym ms WHERE ms.name = ?"; my @bind_vals = ($synonym); if($source) { $q .= " AND ms.source = ?"; push(@bind_vals, $source); } my $sth = $self->prepare($q); $sth->execute(@bind_vals); my @out = (); my $marker_id; my %seen; #fetch the markers and filter out duplictes while(($marker_id) = $sth->fetchrow_array) { next if $seen{$marker_id}; # some synonyms point to markers that don't exist, so only add genuine ones my $marker = $self->fetch_by_dbID($marker_id); push @out, $marker if ($marker); $seen{$marker_id} = 1; } $sth->finish; return \@out; } =head2 fetch_attributes Arg [1] : Bio::EnsEMBL::Map::Marker $marker Example : $marker_adaptor->fetch_attributes($marker); Description: Fetches the marker_synonym and map_location attributes of a marker. This is done so that these attributes can be lazy-loaded on request. Returntype : none Exceptions : none Caller : Bio::EnsEMBL::Map::Marker::marker Status : stable =cut sub fetch_attributes { my $self = shift; my $marker = shift; my $m_id = $marker->dbID; $self->throw('Marker argument does not have a dbID') unless($m_id); # # First Retrieve synonyms for this marker # $marker->flush_MarkerSynonyms; my $sth = $self->prepare("SELECT ms.marker_synonym_id, ms.source, ms.name FROM marker_synonym ms WHERE ms.marker_id = ?"); my @syns = (); my ($ms_id, $ms_src, $ms_name); $sth->execute($m_id); $sth->bind_columns(\$ms_id, \$ms_src, \$ms_name); while($sth->fetch) { push @syns, Bio::EnsEMBL::Map::MarkerSynonym->new($ms_id,$ms_src,$ms_name); } $sth->finish; $marker->add_MarkerSynonyms(@syns) if(@syns); # # Now retrieve map locations for this marker # $marker->flush_MapLocations; $sth = $self->prepare("SELECT mloc.chromosome_name, mloc.position, mloc.lod_score, map.map_name, ms.name FROM marker_map_location mloc, map map, marker_synonym ms WHERE mloc.marker_id = ? AND map.map_id = mloc.map_id AND ms.marker_synonym_id = mloc.marker_synonym_id"); my($chr_name, $pos, $lod, $mname, $name); my @mlocs; $sth->execute($m_id); $sth->bind_columns(\$chr_name, \$pos, \$lod, \$mname, \$name); while($sth->fetch) { push(@mlocs, Bio::EnsEMBL::Map::MapLocation->new($name, $mname, $chr_name,$pos,$lod)); } $sth->finish; $marker->add_MapLocations(@mlocs); } =head2 store Arg [1] : Bio::EnsEMBL::Map::Marker Example : $marker_adaptor->store(@markers); Description: Stores a list of markers in this database. The dbID and adaptor of each marker will be set on successful storing. Returntype : 1 on success Exceptions : thrown if not all data needed for storing is populated in the marker Caller : general Status : stable =cut sub store { my ($self, @markers) = @_; MARKER:foreach my $marker( @markers ){ if($marker->dbID){ if($self->fetch_by_dbID($marker->dbID)){ next MARKER; } } # # Sanity check # if(!$marker || !ref($marker) || !$marker->isa('Bio::EnsEMBL::Map::Marker')) { $self->throw('Incorrect argument [$marker] to store. Expected ' . 'Bio::EnsEMBL::Map::Marker'); } # Don't store if already stored if($marker->is_stored($self->db())) { warning('Marker ['.$marker->dbID.'] is already stored in this DB.'); next; } # Get/test the display marker synonym my $display_synonym = $marker->display_MarkerSynonym; if(!$display_synonym || !ref($display_synonym) || !$display_synonym->isa('Bio::EnsEMBL::Map::MarkerSynonym')) { $self->throw('Cannot store Marker without an associated '. 'display_MarkerSynonym'); } # Store the Marker itself my $q = qq( INSERT INTO marker ( left_primer, right_primer, min_primer_dist, max_primer_dist, priority, type) VALUES ( ?,?,?,?,?,?) ); my $sth = $self->prepare($q); $sth->execute( $marker->left_primer || '', $marker->right_primer || '', $marker->min_primer_dist || 0, $marker->max_primer_dist || 0, $marker->priority, $marker->type ); my $dbID = $sth->{'mysql_insertid'}; $marker->dbID($dbID); $marker->adaptor($self); if(!$display_synonym->dbID) { # Store synonym $self->_store_MarkerSynonym($marker,$display_synonym); } my $display_synonym_id = $display_synonym->dbID || $self->throw('display_MarkerSynonym must have dbID to store Marker'); # Update the marker with the display synonym my $qup = qq( UPDATE marker SET display_marker_synonym_id = $display_synonym_id WHERE marker_id = ? ); my $sthup = $self->prepare($qup); $sthup->execute($dbID); # Loop through all MarkerSynonyms and store if needed foreach my $synonym( @{$marker->get_all_MarkerSynonyms} ){ if(!$synonym->dbID) { $self->_store_MarkerSynonym($marker,$synonym); } } # Loop through all MapLocations and store if needed foreach my $loc( @{$marker->get_all_MapLocations} ){ # Dunno how to implement this :( Just bomb out $self->throw( 'Storing of MapLocation objects is not yet implemented' ) } } return 1; } =head2 _store_MarkerSynonym Arg [1] : Bio::EnsEMBL::Map::Marker Arg [2] : Bio::EnsEMBL::Map::MarkerSynonym Example : $marker_adaptor->_store_MarkerSynonym($marker,$ms); Description: Stores a marker synonym attached to the marker in the database The dbID of each MarkerSynonym will be set on successful storing. Returntype : dbID of the MarkerSynonym Exceptions : thrown if not all data needed for storing is populated Caller : $self->store Status : stable =cut sub _store_MarkerSynonym{ my $self = shift; my $marker = shift; my $ms = shift; # Sanity check if(!$marker || !ref($marker) || !$marker->isa('Bio::EnsEMBL::Map::Marker')) { $self->throw("Incorrect argument [$marker] to _store_MarkerSynonym." . "Expected Bio::EnsEMBL::Map::Marker"); } if(!$ms || !ref($ms) || !$ms->isa('Bio::EnsEMBL::Map::MarkerSynonym')) { $self->throw("Incorrect argument [$ms] to _store_MarkerSynonym." . "Expected Bio::EnsEMBL::Map::MarkerSynonym"); } # Don't store if already stored if($ms->dbID) { warning('MarkerSynonym ['.$ms->dbID.'] is already stored in this DB.'); return; } my $marker_id = $marker->dbID || throw( "Marker has no dbID. Cannot store MarkerSynonym" ); # Store the synonym my $q = qq( INSERT INTO marker_synonym ( marker_id, source, name ) VALUES ( ?,?,?) ); my $sth = $self->prepare($q); $sth->execute( $marker_id, $ms->source, $ms->name ); my $dbID = $sth->{'mysql_insertid'}; $ms->dbID($dbID); return $dbID; } 1;