| 6 | 1 # | 
|  | 2 # Copyright INRA-URGI 2009-2010 | 
|  | 3 # | 
|  | 4 # This software is governed by the CeCILL license under French law and | 
|  | 5 # abiding by the rules of distribution of free software. You can use, | 
|  | 6 # modify and/ or redistribute the software under the terms of the CeCILL | 
|  | 7 # license as circulated by CEA, CNRS and INRIA at the following URL | 
|  | 8 # "http://www.cecill.info". | 
|  | 9 # | 
|  | 10 # As a counterpart to the access to the source code and rights to copy, | 
|  | 11 # modify and redistribute granted by the license, users are provided only | 
|  | 12 # with a limited warranty and the software's author, the holder of the | 
|  | 13 # economic rights, and the successive licensors have only limited | 
|  | 14 # liability. | 
|  | 15 # | 
|  | 16 # In this respect, the user's attention is drawn to the risks associated | 
|  | 17 # with loading, using, modifying and/or developing or reproducing the | 
|  | 18 # software by the user in light of its specific status of free software, | 
|  | 19 # that may mean that it is complicated to manipulate, and that also | 
|  | 20 # therefore means that it is reserved for developers and experienced | 
|  | 21 # professionals having in-depth computer knowledge. Users are therefore | 
|  | 22 # encouraged to load and test the software's suitability as regards their | 
|  | 23 # requirements in conditions enabling the security of their systems and/or | 
|  | 24 # data to be ensured and, more generally, to use and operate it in the | 
|  | 25 # same conditions as regards security. | 
|  | 26 # | 
|  | 27 # The fact that you are presently reading this means that you have had | 
|  | 28 # knowledge of the CeCILL license and that you accept its terms. | 
|  | 29 # | 
|  | 30 from SMART.Java.Python.structure.SubMapping import SubMapping | 
|  | 31 from SMART.Java.Python.structure.Transcript import Transcript | 
|  | 32 from SMART.Java.Python.structure.Interval import Interval | 
|  | 33 | 
|  | 34 class Mapping(object): | 
|  | 35     """A class that represents a mapping""" | 
|  | 36 | 
|  | 37     def __init__(self): | 
|  | 38         self.targetInterval = None | 
|  | 39         self.queryInterval  = None | 
|  | 40         self.subMappings    = [] | 
|  | 41         self.size           = None | 
|  | 42         self.transcript     = None | 
|  | 43         self.tags           = {} | 
|  | 44 | 
|  | 45 | 
|  | 46     def copy(self, mapping): | 
|  | 47         for subMapping in mapping.subMappings: | 
|  | 48             newSubMapping = SubMapping(subMapping) | 
|  | 49             self.addSubMapping(newSubMapping) | 
|  | 50         self.targetInterval = Interval(mapping.targetInterval) | 
|  | 51         self.queryInterval  = Interval(mapping.queryInterval) | 
|  | 52         self.size           = mapping.size | 
|  | 53         self.tags           = {} | 
|  | 54         for tag in mapping.tags: | 
|  | 55             self.tags[tag] = mapping[tag] | 
|  | 56         self.transcript.copy(mapping.transcript) | 
|  | 57 | 
|  | 58 | 
|  | 59     def setTargetInterval(self, interval): | 
|  | 60         self.targetInterval = Interval(interval) | 
|  | 61         if self.queryInterval != None: | 
|  | 62             self.setDirection(self.targetInterval.getDirection() * self.queryInterval.getDirection()) | 
|  | 63 | 
|  | 64 | 
|  | 65     def setQueryInterval(self, interval): | 
|  | 66         self.queryInterval = Interval(interval) | 
|  | 67         if self.targetInterval != None: | 
|  | 68             self.setDirection(self.targetInterval.getDirection() * self.queryInterval.getDirection()) | 
|  | 69 | 
|  | 70 | 
|  | 71     def getQueryInterval(self): | 
|  | 72         return self.queryInterval | 
|  | 73 | 
|  | 74 | 
|  | 75     def addSubMapping(self, subMapping): | 
|  | 76         subMappingCopy = SubMapping(subMapping) | 
|  | 77         self.subMappings.append(subMappingCopy) | 
|  | 78 | 
|  | 79         if self.targetInterval: | 
|  | 80             self.targetInterval.setStart(min(self.targetInterval.getStart(), subMapping.targetInterval.getStart())) | 
|  | 81             self.targetInterval.setEnd(max(self.targetInterval.getEnd(),     subMapping.targetInterval.getEnd())) | 
|  | 82         else: | 
|  | 83             self.setTargetInterval(subMapping.targetInterval) | 
|  | 84         if self.queryInterval: | 
|  | 85             self.queryInterval.setStart(min(self.queryInterval.getStart(), subMapping.queryInterval.getStart())) | 
|  | 86             self.queryInterval.setEnd(max(self.queryInterval.getEnd(),     subMapping.queryInterval.getEnd())) | 
|  | 87         else: | 
|  | 88             self.setQueryInterval(subMapping.queryInterval) | 
|  | 89 | 
|  | 90         if self.getDirection() != 0: | 
|  | 91             subMapping.setDirection(self.getDirection()) | 
|  | 92         if self.size == None: | 
|  | 93             self.size = 0 | 
|  | 94         if "identity" in subMapping.getTagNames() and "identity" not in self.getTagNames(): | 
|  | 95             self.setTagValue("identity", subMapping.getTagValue("identity")) | 
|  | 96         elif "identity" in subMapping.getTagNames() and subMapping.size != None: | 
|  | 97             self.setTagValue("identity", (self.getTagValue("identity") * self.size + subMapping.getTagValue("identity") * subMapping.size) / (self.size + subMapping.size)) | 
|  | 98         if subMapping.size != None: | 
|  | 99             self.size += subMapping.size | 
|  | 100         if "nbMismatches" in subMapping.getTagNames() and "nbMismatches" not in self.getTagNames(): | 
|  | 101             self.setTagValue("nbMismatches", subMapping.getTagValue("nbMismatches")) | 
|  | 102         elif "nbMismatches" in subMapping.getTagNames(): | 
|  | 103             self.setTagValue("nbMismatches", self.getTagValue("nbMismatches") + subMapping.getTagValue("nbMismatches")) | 
|  | 104         if "nbGaps" in subMapping.getTagNames() and "nbGaps" not in self.getTagNames(): | 
|  | 105             self.setTagValue("nbGaps", subMapping.getTagValue("nbGaps")) | 
|  | 106         elif "nbGaps" in subMapping.getTagNames(): | 
|  | 107             self.setTagValue("nbGaps", self.getTagValue("nbGaps") + subMapping.getTagValue("nbGaps")) | 
|  | 108 | 
|  | 109 | 
|  | 110     def setDirection(self, direction): | 
|  | 111         for subMapping in self.subMappings: | 
|  | 112             subMapping.setDirection(direction) | 
|  | 113 | 
|  | 114 | 
|  | 115     def getDirection(self): | 
|  | 116         if not self.subMappings: | 
|  | 117             raise Exception("Error! Mapping '%s' has no submapping" % (self)) | 
|  | 118         return self.subMappings[0].getDirection() | 
|  | 119 | 
|  | 120 | 
|  | 121     def setSize(self, size): | 
|  | 122         self.size = size | 
|  | 123         if "identity" in self.getTagNames(): | 
|  | 124             self.setTagValue("nbMismatches", self.size - round(self.size * self.getTagValue("identity") / 100.0)) | 
|  | 125 | 
|  | 126 | 
|  | 127     def setTagValue(self, name, value): | 
|  | 128         self.tags[name] = value | 
|  | 129         self.transcript = None | 
|  | 130 | 
|  | 131 | 
|  | 132     def getTagValue(self, name): | 
|  | 133         return self.tags[name] | 
|  | 134 | 
|  | 135 | 
|  | 136     def getTagNames(self): | 
|  | 137         return self.tags.keys() | 
|  | 138 | 
|  | 139 | 
|  | 140     def setIdentity(self, identity): | 
|  | 141         self.setTagValue("identity", identity) | 
|  | 142         if self.size != None and "nbMismatches" not in self.getTagNames(): | 
|  | 143             nbMismatches = 0 if self.size == 0 else self.size - round(self.size * self.getTagValue("identity") / 100.0) | 
|  | 144             self.setTagValue("nbMismatches", nbMismatches) | 
|  | 145 | 
|  | 146 | 
|  | 147     def setNbOccurrences(self, nbOccurrences): | 
|  | 148         self.setTagValue("nbOccurrences", nbOccurrences) | 
|  | 149 | 
|  | 150 | 
|  | 151     def setNbMismatches(self, nbMismatches): | 
|  | 152         self.setTagValue("nbMismatches", nbMismatches) | 
|  | 153         if self.size != None and "identity" not in self.getTagNames(): | 
|  | 154             identity = 100 if self.size == 0 else (self.size - self.getTagValue("nbMismatches")) / float(self.size) * 100 | 
|  | 155             self.setTagValue("identity", identity) | 
|  | 156 | 
|  | 157 | 
|  | 158     def setNbGaps(self, nbGaps): | 
|  | 159         self.setTagValue("nbGaps", nbGaps) | 
|  | 160 | 
|  | 161 | 
|  | 162     def setRank(self, rank): | 
|  | 163         self.setTagValue("rank", rank) | 
|  | 164 | 
|  | 165 | 
|  | 166     def setEvalue(self, evalue): | 
|  | 167         self.setTagValue("evalue", evalue) | 
|  | 168 | 
|  | 169 | 
|  | 170     def setOccurrence(self, occurrence): | 
|  | 171         self.setTagValue("occurrence", occurrence) | 
|  | 172 | 
|  | 173 | 
|  | 174     def setBestRegion(self, bestRegion): | 
|  | 175         self.setTagValue("bestRegion", bestRegion) | 
|  | 176 | 
|  | 177 | 
|  | 178     def mergeExons(self, distance): | 
|  | 179         previousSubMapping = None | 
|  | 180         subMappings        = [] | 
|  | 181         for subMapping in self.subMappings: | 
|  | 182             if previousSubMapping == None: | 
|  | 183                 subMappings.append(subMapping) | 
|  | 184                 previousSubMapping = subMapping | 
|  | 185             else: | 
|  | 186                 targetDistance = subMapping.targetInterval.getDistance(previousSubMapping.targetInterval) | 
|  | 187                 queryDistance  = subMapping.queryInterval.getDistance(previousSubMapping.queryInterval) | 
|  | 188                 if targetDistance <= distance: | 
|  | 189                     self.setTagValue("nbGaps", self.getTagValue("nbGaps") + queryDistance) | 
|  | 190                     previousSubMapping.merge(subMapping) | 
|  | 191                 else: | 
|  | 192                     subMappings.append(subMapping) | 
|  | 193                     previousSubMapping = subMapping | 
|  | 194         self.subMappings = subMappings | 
|  | 195 | 
|  | 196 | 
|  | 197     def getTranscript(self): | 
|  | 198         """ | 
|  | 199         Extract a transcript from this mapping | 
|  | 200         @return: a transcript | 
|  | 201         """ | 
|  | 202         if self.transcript != None: | 
|  | 203             return self.transcript | 
|  | 204         self.transcript = Transcript() | 
|  | 205         self.transcript.copy(self.targetInterval) | 
|  | 206         self.transcript.setDirection(self.getDirection()) | 
|  | 207         self.transcript.setName(self.queryInterval.getName()) | 
|  | 208         self.transcript.removeExons() | 
|  | 209         if len(self.subMappings) > 1: | 
|  | 210             for subMapping in self.subMappings: | 
|  | 211                 self.transcript.addExon(subMapping.targetInterval) | 
|  | 212         cpt = 1 | 
|  | 213         for exon in self.transcript.exons: | 
|  | 214             exon.setDirection(self.transcript.getDirection()) | 
|  | 215             exon.setName("%s-exon%d" % (self.transcript.getName(), cpt)) | 
|  | 216             exon.setChromosome(self.transcript.getChromosome()) | 
|  | 217             cpt += 1 | 
|  | 218         self.transcript.setDirection(self.getDirection()) | 
|  | 219         self.transcript.sortExons() | 
|  | 220         for tag in self.tags: | 
|  | 221             if "bestRegion" not in self.getTagNames(): | 
|  | 222                 self.transcript.setTagValue("bestRegion", "(self)") | 
|  | 223             self.transcript.setTagValue(tag, self.getTagValue(tag)) | 
|  | 224         return self.transcript | 
|  | 225 | 
|  | 226 | 
|  | 227     def getChromosome(self): | 
|  | 228         if not self.subMappings: | 
|  | 229             raise Exception("Error! Mapping '%s' has no submapping" % (self)) | 
|  | 230         return self.subMappings[0].targetInterval.getChromosome() | 
|  | 231 | 
|  | 232 | 
|  | 233 | 
|  | 234     def getErrorScore(self): | 
|  | 235         return self.getTagValue("nbGaps") * 3 + self.getTagValue("nbMismatches") + (len(self.subMappings) - 1) * 0.1 | 
|  | 236 | 
|  | 237 | 
|  | 238     def printGBrowseReference(self): | 
|  | 239         return self.getTranscript().printGBrowseReference() | 
|  | 240 | 
|  | 241 | 
|  | 242     def printGBrowseLine(self): | 
|  | 243         return self.getTranscript().printGBrowseLine() | 
|  | 244 | 
|  | 245 | 
|  | 246     def printGBrowse(self): | 
|  | 247         return self.getTranscript().printGBrowse() | 
|  | 248 | 
|  | 249 | 
|  | 250     def printBed(self): | 
|  | 251         return self.getTranscript().printBed() | 
|  | 252 | 
|  | 253 | 
|  | 254     def __str__(self): | 
|  | 255         return "%s     ----     %s" % (str(self.getTranscript()), ", ". join([str(submapping) for submapping in self.subMappings])) |