| 
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]))
 |