001 /** 002 * Copyright (C) 2010 The Roslin Institute <contact andy.law@roslin.ed.ac.uk> 003 * 004 * This file is part of the Ensembl Java API demonstration project developed by the 005 * Bioinformatics Group at The Roslin Institute, The Royal (Dick) School of 006 * Veterinary Studies, University of Edinburgh. 007 * 008 * This is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (version 3) as published by 010 * the Free Software Foundation. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * in this software distribution. If not, see <http://www.gnu.org/licenses/gpl-3.0.html/>. 019 */ 020 package uk.ac.roslin.ensembl.dao.database.compara; 021 022 import java.util.ArrayList; 023 import java.util.HashMap; 024 import java.util.List; 025 import java.util.TreeMap; 026 import org.apache.ibatis.session.SqlSession; 027 import org.apache.log4j.Logger; 028 import uk.ac.roslin.ensembl.config.EnsemblComparaDivision; 029 import uk.ac.roslin.ensembl.dao.compara.HomologyDAO; 030 import uk.ac.roslin.ensembl.dao.database.DBBaseDAO; 031 import uk.ac.roslin.ensembl.dao.database.DBSpecies; 032 import uk.ac.roslin.ensembl.dao.factory.DAOComparaFactory; 033 import uk.ac.roslin.ensembl.model.MappingSet; 034 import uk.ac.roslin.ensembl.datasourceaware.compara.DAHomologyPairRelationship; 035 import uk.ac.roslin.ensembl.datasourceaware.compara.InverseHomologyPairRelationshipView; 036 import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome; 037 import uk.ac.roslin.ensembl.datasourceaware.core.DADNASequence; 038 import uk.ac.roslin.ensembl.datasourceaware.core.DAGene; 039 import uk.ac.roslin.ensembl.exception.DAOException; 040 import uk.ac.roslin.ensembl.mapper.compara.HomologyPairMapper; 041 import uk.ac.roslin.ensembl.model.Coordinate; 042 import uk.ac.roslin.ensembl.model.Mapping; 043 import uk.ac.roslin.ensembl.model.compara.HomologyAlignmentProperties; 044 import uk.ac.roslin.ensembl.model.core.Chromosome; 045 import uk.ac.roslin.ensembl.model.core.Gene; 046 import uk.ac.roslin.ensembl.model.core.Species; 047 048 049 public class DBHomologyDAO extends DBBaseDAO implements HomologyDAO { 050 051 final static Logger LOGGER = Logger.getLogger(DBHomologyDAO.class); 052 053 //If we really want to cache here we will need to use a singleton DBHomologyDAO 054 TreeMap<String, DAGene> localGeneCache = new TreeMap<String, DAGene>(); 055 056 EnsemblComparaDivision comparaDivision; 057 058 public DBHomologyDAO(DAOComparaFactory factory) throws DAOException { 059 super(factory); 060 comparaDivision = factory.getComparaDivision(); 061 } 062 063 @Override 064 public List<DAHomologyPairRelationship> getHomologiesForGene(Gene g) throws DAOException { 065 066 DAGene gene = (DAGene) g; 067 068 //this tests for the field used by mybatis 069 if (gene.getStableID()==null || gene.getStableID().isEmpty()) { 070 throw new DAOException("Failed to get homologies for a gene without a stable EnsemblID"); 071 } 072 073 List<DAHomologyPairRelationship> results = new ArrayList<DAHomologyPairRelationship>(); 074 SqlSession session = null; 075 076 try { 077 session = this.getFactory().getNewSqlSession(); 078 HomologyPairMapper mapper = session.getMapper(HomologyPairMapper.class); 079 results = mapper.getHomologiesForGene(g); 080 } catch (Exception e) { 081 throw new DAOException("Failed to call getHomologiesForGene(g) on HomologyDAO", e); 082 } finally { 083 if (session != null) { 084 session.close(); 085 } 086 } 087 088 //do i want to do this - or to throw an exception to indicate something 089 //has gone wrong with the DB call 090 if (results==null) { 091 return new ArrayList<DAHomologyPairRelationship>(); 092 } 093 094 for (DAHomologyPairRelationship h : results) { 095 096 Species sp = null; 097 //the DAO must have a factory or it wouldn't get here 098 //and we 'should' always have a registry on a factory 099 //we use this to get the species for the homologous gene (i.e from the registry) 100 //but we can return null here 101 sp = this.getFactory().getRegistry().getSpeciesByAlias(h.getTargetProperties().getSpeciesName()); 102 103 if (sp == null) { 104 //make a 'dummy species' - this wont have a factory! 105 sp = new DBSpecies(); 106 ((DBSpecies) sp).setComparaName(h.getTargetProperties().getSpeciesName()); 107 } 108 109 h.setSource(gene); 110 111 DAGene target = new DAGene(); 112 target.setDBVersion( this.getFactory().getDBVersion()); 113 target.setStableID(h.getTargetProperties().getGeneID()); 114 target.setSpecies(sp); 115 116 //hopefully there will only be one relationship to a given target gene 117 //but just in case 118 if (localGeneCache.containsKey(target.getStableID())) { 119 target = localGeneCache.get(target.getStableID()); 120 } else { 121 localGeneCache.put(target.getStableID(),target ); 122 } 123 124 125 h.setTarget(target); 126 127 //fill in the sourceProperties that are not filled in by sql 128 //but are needed once we reverse the relationship 129 HomologyAlignmentProperties sourceProperties = h.getSourceProperties(); 130 131 132 try { 133 sourceProperties.setSequenceName( 134 ((DADNASequence)gene.getAnnotationLevelMappings().first().getTarget()).getName()); 135 sourceProperties.setCoords( 136 gene.getAnnotationLevelMappings().first().getTargetCoordinates()); 137 } catch (Exception e) { 138 LOGGER.warn("Gene "+gene.getHashID()+ " has no annotation level coordinates."); 139 } 140 sourceProperties.setSpeciesName( 141 (gene.getSpecies()!= null) ? gene.getSpecies().getComparaName() : "" 142 ); 143 144 // //reverse the relationship 145 // DAHomologyPairRelationship reverse = new DAHomologyPairRelationship(); 146 // reverse.setSource(target); 147 // reverse.setTarget(gene); 148 // //these arent treversable - use the same type?? 149 // //i.e the type one2many is not necessarily specified the correct way 150 // reverse.setRelationshipType(h.getRelationshipType()); 151 // reverse.setTargetProperties(h.getSourceProperties()); 152 // reverse.setSourceProperties(h.getTargetProperties()); 153 // reverse.setLastCommonAncestor(h.getLastCommonAncestor()); 154 // reverse.setId(h.getId()); 155 // 156 // //add the reversed relationship 157 // target.addHomology(comparaDivision, reverse); 158 159 //this doesnt reverse the direction of the relationship 160 //maybe i do want to do this - and remember that i have to look at 161 //relationships either way 162 target.addHomology(comparaDivision, new InverseHomologyPairRelationshipView(h)); 163 164 } 165 return results; 166 } 167 168 @Override 169 public HashMap<DADNASequence, MappingSet> getRegionsOfConservedSynteny(Chromosome source, Coordinate range, 170 Species target) throws DAOException { 171 172 DAChromosome sChr; 173 DBSpecies tSp; 174 175 if (source==null || target==null) { 176 throw new DAOException("Require a source chromosome and a target species to call getRegionsOfConservedSynteny"); 177 } 178 179 try { 180 sChr = (DAChromosome) source; 181 tSp = (DBSpecies) target; 182 } catch (Exception e) { 183 throw new DAOException("failed to pass valid parameters to get Regions of Conserved Synteny", e); 184 } 185 186 HashMap<DADNASequence, MappingSet> syntenies = new HashMap<DADNASequence, MappingSet>(); 187 188 if (range == null || range.getStart() == null || range.getEnd() == null) { 189 range = new Coordinate(sChr.getBioBegin(), sChr.getBioEnd(), 1); 190 } 191 192 List<DAGene> sGenes = sChr.getGenesOnRegion(range); 193 194 if (sGenes == null || sGenes.isEmpty()) { 195 return syntenies; 196 } 197 198 for (DAGene g : sGenes) { 199 List<DAHomologyPairRelationship> l = g.getHomologies(this.comparaDivision, tSp); 200 201 for (DAHomologyPairRelationship hpr : l) { 202 //force conversion to real mappings, re-using cached chromosomes if appropriate 203 MappingSet m = null; 204 try { 205 //get annotation level mappingsof the target (homologous) gene 206 //i.e. gene-> chromosome in general? 207 m = hpr.getTarget().getAnnotationLevelMappings(); 208 } catch (DAOException dAOException) { 209 } 210 if (m != null && !m.isEmpty()) { 211 //probably only one of these? 212 for (Mapping mp : m) { 213 DADNASequence dna = (DADNASequence) mp.getTarget(); 214 if (!syntenies.containsKey(dna)) { 215 //if we are using the gene->chr mappings we need to be sorting on the target coords 216 //syntenies.put(dna, new MappingSet(Mapping.mappingOnTargetComparator)); 217 //but if we are using the chr->gene mappings we can sort on the source coords (i.e. default comparator) 218 syntenies.put(dna, new MappingSet()); 219 } 220 // this adds the mapping hom_gene->chr 221 //syntenies.get(dna).add(mp); 222 //but we want the mapping chr->hom_gene 223 224 //this method is called within the getReverseMapping method if required! 225 //Mapping.addReverseMapping(mp); 226 syntenies.get(dna).add(mp.getReverseMapping()); 227 } 228 } 229 // incase there are no mappings for the homologous genes on a chromosome! 230 else 231 { 232 //what do we do 233 } 234 } 235 } 236 return syntenies; 237 } 238 }