Esempio n. 1
0
 def secondPhos(self, mapNum, curPhos, direction = 3):
     """find the second phosphate in a chain using phosphate distance data
     
     ARGUMENTS:
         mapNum    - the molecule number of the Coot map to use
         curPhos   - the coordinates of the first phosphate
     OPTIONAL ARGUMENTS:
         direction - which direction to trace the chain: 3 implies 5'->3'
                                                         5 implies 3'->5'
                     defaults to 3 (5'->3')
     RETURNS:
         peakList  - a list of potential phosphate peaks
         sugarList - a list of potential C1' locations for each phosphate peak
     """
     
     peaks = self.getPeaks(mapNum, curPhos)
     
     #calculate the score for each peak
     peakScores = []
     for curPeak in peaks:
         #exclude any peaks that are within an Angstom of the current phosphate position
         #this will exclude the peak corresponding to the current phosphate position
         if dist(curPhos, curPeak) >= 1:
             
             #do a sugar search for the current phosphate
             if direction == 3:
                 sugarLocs = self.findSugar(mapNum, curPhos, curPeak)
             else: #direction == 5:
                 sugarLocs = self.findSugar(mapNum, curPeak, curPhos)
             densityScore = sugarLocs[0][3] + curPeak[3]
             
             score = ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))) + (SECOND_PHOS_DENSITY_WEIGHT * ln(densityScore))
             peakScores.append((curPeak, score, sugarLocs))
     
     #sort the peaks according to score
     peakScores.sort(key = lambda x: x[1], reverse = 1)
     
     #return only the coordinates, not the scores
     peakList  = [x[0] for x in peakScores]
     sugarList = [x[2] for x in peakScores]
     
     return (peakList, sugarList)
Esempio n. 2
0
 def secondPhos(self, mapNum, curPhos, direction = 3):
     """find the second phosphate in a chain using phosphate distance data
     
     ARGUMENTS:
         mapNum    - the molecule number of the Coot map to use
         curPhos   - the coordinates of the first phosphate
     OPTIONAL ARGUMENTS:
         direction - which direction to trace the chain: 3 implies 5'->3'
                                                         5 implies 3'->5'
                     defaults to 3 (5'->3')
     RETURNS:
         peakList  - a list of potential phosphate peaks
         sugarList - a list of potential C1' locations for each phosphate peak
     """
     
     peaks = self.getPeaks(mapNum, curPhos)
     
     #calculate the score for each peak
     peakScores = []
     for curPeak in peaks:
         #exclude any peaks that are within an Angstom of the current phosphate position
         #this will exclude the peak corresponding to the current phosphate position
         if dist(curPhos, curPeak) >= 1:
             
             #do a sugar search for the current phosphate
             if direction == 3:
                 sugarLocs = self.findSugar(mapNum, curPhos, curPeak)
             else: #direction == 5:
                 sugarLocs = self.findSugar(mapNum, curPeak, curPhos)
             densityScore = sugarLocs[0][3] + curPeak[3]
             
             score = ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))) + (SECOND_PHOS_DENSITY_WEIGHT * ln(densityScore))
             peakScores.append((curPeak, score, sugarLocs))
     
     #sort the peaks according to score
     peakScores.sort(key = lambda x: x[1], reverse = 1)
     
     #return only the coordinates, not the scores
     peakList  = [x[0] for x in peakScores]
     sugarList = [x[2] for x in peakScores]
     
     return (peakList, sugarList)
Esempio n. 3
0
 def firstPhos(self, mapNum, curPos):
     """find the first phosphate in a chain
     
     ARGUMENTS:
         mapNum    - the molecule number of the Coot map to use
         curPos    - where to start the search (i.e. the current screen center coordinates)
     RETURNS:
         peaks     - a list of potential phosphate peaks
     """
     
     peaks = self.getPeaks(mapNum, curPos)
     
     #sort the peaks based on how close they are to curPos
     peaks.sort(key=lambda x: dist(curPos, x))
     
     return peaks
Esempio n. 4
0
 def firstPhos(self, mapNum, curPos):
     """find the first phosphate in a chain
     
     ARGUMENTS:
         mapNum    - the molecule number of the Coot map to use
         curPos    - where to start the search (i.e. the current screen center coordinates)
     RETURNS:
         peaks     - a list of potential phosphate peaks
     """
     
     peaks = self.getPeaks(mapNum, curPos)
     
     #sort the peaks based on how close they are to curPos
     peaks.sort(key=lambda x: dist(curPos, x))
     
     return peaks
Esempio n. 5
0
 def startingSugarDist(self):
     """Calculate the sugar-sugar distance for the starting suite of this nucleotide
     
     ARGUMENTS:
         None
     RETURNS:
         the distance from the sugar atom (i.e. C1') of the previous nucleotide to the sugar atom (C1') of this nucleotide
         None if there is no previous nucleotide
     NOTE:
         Behavior of this function is undefined if this nucleotide is not part of a chain.
         (Currently, it returns None.)
     """
     
     if self.connectedToPrev() and self.hasAtom(SUGARATOM) and self.prevNuc().hasAtom(SUGARATOM):
         return dist(self.atoms[SUGARATOM], self.prevNuc().atoms[SUGARATOM])
     else:
         return None
Esempio n. 6
0
 def phosDist(self):
     """Calculate the phosphate-phosphate distance
     
     ARGUMENTS:
         None
     RETURNS:
         The distance from the phosphate of this nucleotide to the phosphate of the next nucleotide
         None if no next phosphate if present
     NOTE:
         Behavior of this function is undefined if this nucleotide is not part of a chain.
         (Currently, it raises an error.)
     """
     
     if self.connectedToNext() and self.hasAtom("P") and self.nextNuc().hasAtom("P"):
         return dist(self.atoms["P"], self.nextNuc().atoms["P"])
     else:
         return None
Esempio n. 7
0
 def startingSugarDist(self):
     """Calculate the sugar-sugar distance for the starting suite of this nucleotide
     
     ARGUMENTS:
         None
     RETURNS:
         the distance from the sugar atom (i.e. C1') of the previous nucleotide to the sugar atom (C1') of this nucleotide
         None if there is no previous nucleotide
     NOTE:
         Behavior of this function is undefined if this nucleotide is not part of a chain.
         (Currently, it returns None.)
     """
     
     if self.connectedToPrev() and self.hasAtom(SUGARATOM) and self.prevNuc().hasAtom(SUGARATOM):
         return dist(self.atoms[SUGARATOM], self.prevNuc().atoms[SUGARATOM])
     else:
         return None
Esempio n. 8
0
 def phosDist(self):
     """Calculate the phosphate-phosphate distance
     
     ARGUMENTS:
         None
     RETURNS:
         The distance from the phosphate of this nucleotide to the phosphate of the next nucleotide
         None if no next phosphate if present
     NOTE:
         Behavior of this function is undefined if this nucleotide is not part of a chain.
         (Currently, it raises an error.)
     """
     
     if self.connectedToNext() and self.hasAtom("P") and self.nextNuc().hasAtom("P"):
         return dist(self.atoms["P"], self.nextNuc().atoms["P"])
     else:
         return None
Esempio n. 9
0
 def findSugar(self, mapNum, phos5, phos3):
     """find potential C1' locations between the given 5' and 3' phosphate coordinates
     
     ARGUMENTS:
         mapNum      - the molecule number of the Coot map to use
         phos5       - the coordinates of the 5' phosphate
         phos3       - the coordinates of the 3' phosphate
     RETURNS:
         sugarMaxima - a list of potential C1' locations, each listed as [x, y, z, score]
     """
     
     #calculate the distance between the two phosphatse
     phosPhosDist = dist(phos5, phos3)
     
     #calculate a potential spot for the sugar based on the phosphate-phosphate distance
     #projDist is how far along the 3'P-5'P vector the sugar center should be (measured from the 3'P)
     #perpDist is how far off from the 3'P-5'P vector the sugar center should be
     
     #these functions are for the sugar center, which is what we try to find here
     #since it will be more in the center of the density blob
     perpDist = -0.185842*phosPhosDist**2 + 1.62296*phosPhosDist - 0.124146
     projDist = 0.440092*phosPhosDist + 0.909732
     
     #if we wanted to find the C1' instead of the sugar center, we'd use these functions
     #however, finding the C1' directly causes our density scores to be less accurate
     #so we instead use the functions above to find the sugar center and later adjust our
     #coordinates to get the C1' location
     #perpDist = -0.124615*phosPhosDist**2 + 0.955624*phosPhosDist + 2.772573
     #projDist = 0.466938*phosPhosDist + 0.649833
     
     
     #calculate the normal to the plane defined by 3'P, 5'P, and a dummy point
     normal = crossProd([10,0,0], minus(phos3, phos5))
     
     #make sure the magnitude of the normal is not zero (or almost zero)
     #if it is zero, that means that our dummy point was co-linear with the 3'P-5'P vector
     #and we haven't calculated a normal
     #if the magnitude is almost zero, then the dummy point was almost co-linear and we have to worry about rounding error
     #in either of those cases, just use a different dummy point
     #they should both be incredibly rare cases, but it doesn't hurt to be safe
     if magnitude(normal) < 0.001:
         #print "Recalculating normal"
         normal = crossProd([0,10,0], minus(phos5, phos3))
     
     
     #scale the normal to the length of perpDist
     perpVector = scalarProd(normal, perpDist/magnitude(normal))
     
     #calculate the 3'P-5'P vector and scale it to the length of projDist
     projVector = minus(phos3, phos5)
     projVector = scalarProd(projVector, projDist/magnitude(projVector))
     
     #calculate a possible sugar location
     sugarLoc = plus(phos5, projVector)
     sugarLoc = plus(sugarLoc, perpVector)
     
     #rotate the potential sugar location around the 3'P-5'P vector to generate a list of potential sugar locations
     sugarRotationPoints = self.__rotateSugarCenter(phos5, phos3, sugarLoc)
     
     #test each potential sugar locations to find the one with the best electron density
     for curSugarLocFull in sugarRotationPoints:
         curSugarLoc = curSugarLocFull[0:3] #the rotation angle is stored as curSugarLocFull[4], so we trim that off for curSugarLoc
         curDensityTotal = 0
         #densityList = []   #if desired, this could be used to generate additional statistics on the density (such as the median or quartiles)
         
         #check density along the 5'P-sugar vector
         phosSugarVector = minus(curSugarLoc, phos5)
         phosSugarVector = scalarProd(phosSugarVector, 1.0/(DENSITY_CHECK_POINTS+1))
         for i in range(1, DENSITY_CHECK_POINTS+1):
             (x, y, z) = plus(phos5, scalarProd(i, phosSugarVector))
             curPointDensity = density_at_point(mapNum, x, y, z)
             curDensityTotal += curPointDensity
             #densityList.append(curPointDensity)
             
         
         #check at the sugar center
         (x, y, z) = curSugarLoc
         curPointDensity = density_at_point(mapNum, x, y, z)
         curDensityTotal += curPointDensity
         #densityList.append(curPointDensity)
         
         #check along the sugar-3'P vector
         sugarPhosVector = minus(phos3, curSugarLoc)
         sugarPhosVector = scalarProd(sugarPhosVector, 1.0/(DENSITY_CHECK_POINTS+1))
         for i in range(1, DENSITY_CHECK_POINTS+1):
             (x, y, z) = plus(curSugarLoc, scalarProd(i, sugarPhosVector))
             curPointDensity = density_at_point(mapNum, x, y, z)
             curDensityTotal += curPointDensity
             #densityList.append(curPointDensity)
         
         curSugarLocFull.append(curDensityTotal)
         #curSugarLocFull.extend([curDensityTotal, median(densityList), lowerQuartile(densityList), min(densityList)])#, pointList])
     
     #find all the local maxima
     sugarMaxima = []
     curPeakHeight = sugarRotationPoints[-1][4]
     nextPeakHeight = sugarRotationPoints[0][4]
     sugarRotationPoints.append(sugarRotationPoints[0]) #copy the first point to the end so that we can properly check the last point
     for i in range(0, len(sugarRotationPoints)-1):
         prevPeakHeight = curPeakHeight
         curPeakHeight  = nextPeakHeight
         nextPeakHeight = sugarRotationPoints[i+1][4]
         if prevPeakHeight < curPeakHeight and curPeakHeight >=  nextPeakHeight:
             sugarMaxima.append(sugarRotationPoints[i])
     
     #sort the local maxima by their density score
     sugarMaxima.sort(key = lambda x: x[4], reverse = True)
     
     #adjust all the sugar center coordinates so that they represent the corresponding C1' coordinates
     for i in range(0, len(sugarMaxima)):
         curSugar = sugarMaxima[i][0:3]
         #rotate a vector 148 degrees from the phosphate bisector
         phosAngle = angle(phos5, curSugar, phos3)
         phos5vector = minus(phos5, curSugar)
         axis = crossProd(minus(phos3, curSugar), phos5vector)
         axis = scalarProd(axis, 1/magnitude(axis))
         c1vec = rotate(phos5vector, axis, 148.539123-phosAngle/2)
         
         #scale the vector to the appropriate length
         c1vec = scalarProd(c1vec, 1.235367/magnitude(c1vec))
         
         #rotate the vector about the phosphate bisector
         phosBisectorAxis = rotate(phos5vector, axis, -phosAngle/2)
         phosBisectorAxis = scalarProd(phosBisectorAxis, 1/magnitude(phosBisectorAxis)) 
         c1vec = rotate(c1vec, phosBisectorAxis, -71.409162)
         
         sugarMaxima[i][0:3] = plus(c1vec, curSugar)
     
     return sugarMaxima
Esempio n. 10
0
 def nextPhos(self, mapNum, curPhos, prevPhos, prevSugar, direction = 3):
     """Find the next phosphate in a chain using phosphate distance and angle data
     
     ARGUMENTS:
         mapNum    - the molecule number of the Coot map to use
         curPhos   - the coordinates of the current phosphate
         prevPhos  - the coordinates of the previous phosphate
         prevSugar - the coordinates of the previous C1' atom
     OPTIONAL ARGUMENTS:
         direction - which direction to trace the chain: 3 implies 5'->3'
                                                         5 implies 3'->5'
                     defaults to 3 (5'->3')
     RETURNS:
         peakList  - a list of potential phosphate peaks
         sugarList - a list of potential C1' locations for each phosphate peak
     """
     
     peaks = self.getPeaks(mapNum, curPhos)
     
     #calculate the score for each peak
     peakScores = []
     for curPeak in peaks:
         #exclude any peaks that are within an Angstom of the current phosphate position
         #this will exclude the peak corresponding to the current phosphate position
         if dist(curPhos, curPeak) >= 1:
             
             #do a sugar search for the current phosphate
             if direction == 3:
                 sugarLocs = self.findSugar(mapNum, curPhos, curPeak)
             else:
                 sugarLocs = self.findSugar(mapNum, curPeak, curPhos)
             
             densityScore = sugarLocs[0][3] + curPeak[3]
             
             score = ((PHOS_DIST_WEIGHT * ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))))
                      + ln(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak)))
                      + ln(self.__sugarPhosSugarAngleInterp.interp(angle(prevSugar, curPhos, sugarLocs[0][0:3])))
                      + (DENSITY_WEIGHT * ln(densityScore))
                     )
             peakScores.append((curPeak, score, sugarLocs))
             
             #FOR DEBUGGING OUTPUT
             #peakScores.append((curPeak, score, sugarLocs, ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))), ln(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak))), ln(self.__sugarPhosSugarAngleInterp.interp(angle(prevSugar, prevPhos, sugarLocs[0][0:3]))), sugarLocs[0][3], sugarLocs[0][4], sugarLocs[0][5], sugarLocs[0][6], curPeak[3], sugarLocs[0][7]))
             #peakScores.append((curPeak, score, sugarLocs, ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))), ln(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak))), ln(self.__sugarPhosSugarAngleInterp.interp(angle(prevSugar, curPhos, sugarLocs[0][0:3]))), ln(densityScore), DENSITY_WEIGHT * ln(densityScore), sugarLocs[0][3], curPeak[3]))
             #print "Score for peak %(curPeak)s is %(score)f" % vars()
             #print "\tDist: " + str(dist(curPhos, curPeak)) + "\t" + str(self.__phosDistInterp.interp(dist(curPhos, curPeak)))
             #print "\tAngle: " + str(angle(prevPhos, curPhos, curPeak)) + "\t" + str(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak)))
             
     
     #sort the peaks according to score
     peakScores.sort(key = lambda x: x[1], reverse = 1)
     
     #return only the coordinates, not the scores
     peakList  = [x[0] for x in peakScores]
     sugarList = [x[2] for x in peakScores]
     
     #FOR DEBUGGING OUTPUT
     #print "Current scores:"
     #print "overall\t\tphosDist\tphosAngle\tsPsAngle\tdensity score\tw. den score\tsugar score\tphos score"
     #for x in peakScores:
     #    #print "SCORE: %f\tSUGAR SCORE: %f" % (x[1], x[2][0][3])
     #    print "\t".join(map(str, (x[1],) + x[3:]))
     
     return (peakList, sugarList)
Esempio n. 11
0
 def findSugar(self, mapNum, phos5, phos3):
     """find potential C1' locations between the given 5' and 3' phosphate coordinates
     
     ARGUMENTS:
         mapNum      - the molecule number of the Coot map to use
         phos5       - the coordinates of the 5' phosphate
         phos3       - the coordinates of the 3' phosphate
     RETURNS:
         sugarMaxima - a list of potential C1' locations, each listed as [x, y, z, score]
     """
     
     #calculate the distance between the two phosphatse
     phosPhosDist = dist(phos5, phos3)
     
     #calculate a potential spot for the sugar based on the phosphate-phosphate distance
     #projDist is how far along the 3'P-5'P vector the sugar center should be (measured from the 3'P)
     #perpDist is how far off from the 3'P-5'P vector the sugar center should be
     
     #these functions are for the sugar center, which is what we try to find here
     #since it will be more in the center of the density blob
     perpDist = -0.185842*phosPhosDist**2 + 1.62296*phosPhosDist - 0.124146
     projDist = 0.440092*phosPhosDist + 0.909732
     
     #if we wanted to find the C1' instead of the sugar center, we'd use these functions
     #however, finding the C1' directly causes our density scores to be less accurate
     #so we instead use the functions above to find the sugar center and later adjust our
     #coordinates to get the C1' location
     #perpDist = -0.124615*phosPhosDist**2 + 0.955624*phosPhosDist + 2.772573
     #projDist = 0.466938*phosPhosDist + 0.649833
     
     
     #calculate the normal to the plane defined by 3'P, 5'P, and a dummy point
     normal = crossProd([10,0,0], minus(phos3, phos5))
     
     #make sure the magnitude of the normal is not zero (or almost zero)
     #if it is zero, that means that our dummy point was co-linear with the 3'P-5'P vector
     #and we haven't calculated a normal
     #if the magnitude is almost zero, then the dummy point was almost co-linear and we have to worry about rounding error
     #in either of those cases, just use a different dummy point
     #they should both be incredibly rare cases, but it doesn't hurt to be safe
     if magnitude(normal) < 0.001:
         #print "Recalculating normal"
         normal = crossProd([0,10,0], minus(phos5, phos3))
     
     
     #scale the normal to the length of perpDist
     perpVector = scalarProd(normal, perpDist/magnitude(normal))
     
     #calculate the 3'P-5'P vector and scale it to the length of projDist
     projVector = minus(phos3, phos5)
     projVector = scalarProd(projVector, projDist/magnitude(projVector))
     
     #calculate a possible sugar location
     sugarLoc = plus(phos5, projVector)
     sugarLoc = plus(sugarLoc, perpVector)
     
     #rotate the potential sugar location around the 3'P-5'P vector to generate a list of potential sugar locations
     sugarRotationPoints = self.__rotateSugarCenter(phos5, phos3, sugarLoc)
     
     #test each potential sugar locations to find the one with the best electron density
     for curSugarLocFull in sugarRotationPoints:
         curSugarLoc = curSugarLocFull[0:3] #the rotation angle is stored as curSugarLocFull[4], so we trim that off for curSugarLoc
         curDensityTotal = 0
         #densityList = []   #if desired, this could be used to generate additional statistics on the density (such as the median or quartiles)
         
         #check density along the 5'P-sugar vector
         phosSugarVector = minus(curSugarLoc, phos5)
         phosSugarVector = scalarProd(phosSugarVector, 1.0/(DENSITY_CHECK_POINTS+1))
         for i in range(1, DENSITY_CHECK_POINTS+1):
             (x, y, z) = plus(phos5, scalarProd(i, phosSugarVector))
             curPointDensity = density_at_point(mapNum, x, y, z)
             curDensityTotal += curPointDensity
             #densityList.append(curPointDensity)
             
         
         #check at the sugar center
         (x, y, z) = curSugarLoc
         curPointDensity = density_at_point(mapNum, x, y, z)
         curDensityTotal += curPointDensity
         #densityList.append(curPointDensity)
         
         #check along the sugar-3'P vector
         sugarPhosVector = minus(phos3, curSugarLoc)
         sugarPhosVector = scalarProd(sugarPhosVector, 1.0/(DENSITY_CHECK_POINTS+1))
         for i in range(1, DENSITY_CHECK_POINTS+1):
             (x, y, z) = plus(curSugarLoc, scalarProd(i, sugarPhosVector))
             curPointDensity = density_at_point(mapNum, x, y, z)
             curDensityTotal += curPointDensity
             #densityList.append(curPointDensity)
         
         curSugarLocFull.append(curDensityTotal)
         #curSugarLocFull.extend([curDensityTotal, median(densityList), lowerQuartile(densityList), min(densityList)])#, pointList])
     
     #find all the local maxima
     sugarMaxima = []
     curPeakHeight = sugarRotationPoints[-1][4]
     nextPeakHeight = sugarRotationPoints[0][4]
     sugarRotationPoints.append(sugarRotationPoints[0]) #copy the first point to the end so that we can properly check the last point
     for i in range(0, len(sugarRotationPoints)-1):
         prevPeakHeight = curPeakHeight
         curPeakHeight  = nextPeakHeight
         nextPeakHeight = sugarRotationPoints[i+1][4]
         if prevPeakHeight < curPeakHeight and curPeakHeight >=  nextPeakHeight:
             sugarMaxima.append(sugarRotationPoints[i])
     
     #sort the local maxima by their density score
     sugarMaxima.sort(key = lambda x: x[4], reverse = True)
     
     #adjust all the sugar center coordinates so that they represent the corresponding C1' coordinates
     for i in range(0, len(sugarMaxima)):
         curSugar = sugarMaxima[i][0:3]
         #rotate a vector 148 degrees from the phosphate bisector
         phosAngle = angle(phos5, curSugar, phos3)
         phos5vector = minus(phos5, curSugar)
         axis = crossProd(minus(phos3, curSugar), phos5vector)
         axis = scalarProd(axis, 1/magnitude(axis))
         c1vec = rotate(phos5vector, axis, 148.539123-phosAngle/2)
         
         #scale the vector to the appropriate length
         c1vec = scalarProd(c1vec, 1.235367/magnitude(c1vec))
         
         #rotate the vector about the phosphate bisector
         phosBisectorAxis = rotate(phos5vector, axis, -phosAngle/2)
         phosBisectorAxis = scalarProd(phosBisectorAxis, 1/magnitude(phosBisectorAxis)) 
         c1vec = rotate(c1vec, phosBisectorAxis, -71.409162)
         
         sugarMaxima[i][0:3] = plus(c1vec, curSugar)
     
     return sugarMaxima
Esempio n. 12
0
 def nextPhos(self, mapNum, curPhos, prevPhos, prevSugar, direction = 3):
     """Find the next phosphate in a chain using phosphate distance and angle data
     
     ARGUMENTS:
         mapNum    - the molecule number of the Coot map to use
         curPhos   - the coordinates of the current phosphate
         prevPhos  - the coordinates of the previous phosphate
         prevSugar - the coordinates of the previous C1' atom
     OPTIONAL ARGUMENTS:
         direction - which direction to trace the chain: 3 implies 5'->3'
                                                         5 implies 3'->5'
                     defaults to 3 (5'->3')
     RETURNS:
         peakList  - a list of potential phosphate peaks
         sugarList - a list of potential C1' locations for each phosphate peak
     """
     
     peaks = self.getPeaks(mapNum, curPhos)
     
     #calculate the score for each peak
     peakScores = []
     for curPeak in peaks:
         #exclude any peaks that are within an Angstom of the current phosphate position
         #this will exclude the peak corresponding to the current phosphate position
         if dist(curPhos, curPeak) >= 1:
             
             #do a sugar search for the current phosphate
             if direction == 3:
                 sugarLocs = self.findSugar(mapNum, curPhos, curPeak)
             else:
                 sugarLocs = self.findSugar(mapNum, curPeak, curPhos)
             
             densityScore = sugarLocs[0][3] + curPeak[3]
             
             score = ((PHOS_DIST_WEIGHT * ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))))
                      + ln(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak)))
                      + ln(self.__sugarPhosSugarAngleInterp.interp(angle(prevSugar, curPhos, sugarLocs[0][0:3])))
                      + (DENSITY_WEIGHT * ln(densityScore))
                     )
             peakScores.append((curPeak, score, sugarLocs))
             
             #FOR DEBUGGING OUTPUT
             #peakScores.append((curPeak, score, sugarLocs, ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))), ln(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak))), ln(self.__sugarPhosSugarAngleInterp.interp(angle(prevSugar, prevPhos, sugarLocs[0][0:3]))), sugarLocs[0][3], sugarLocs[0][4], sugarLocs[0][5], sugarLocs[0][6], curPeak[3], sugarLocs[0][7]))
             #peakScores.append((curPeak, score, sugarLocs, ln(self.__phosDistInterp.interp(dist(curPhos, curPeak))), ln(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak))), ln(self.__sugarPhosSugarAngleInterp.interp(angle(prevSugar, curPhos, sugarLocs[0][0:3]))), ln(densityScore), DENSITY_WEIGHT * ln(densityScore), sugarLocs[0][3], curPeak[3]))
             #print "Score for peak %(curPeak)s is %(score)f" % vars()
             #print "\tDist: " + str(dist(curPhos, curPeak)) + "\t" + str(self.__phosDistInterp.interp(dist(curPhos, curPeak)))
             #print "\tAngle: " + str(angle(prevPhos, curPhos, curPeak)) + "\t" + str(self.__phosAngleInterp.interp(angle(prevPhos, curPhos, curPeak)))
             
     
     #sort the peaks according to score
     peakScores.sort(key = lambda x: x[1], reverse = 1)
     
     #return only the coordinates, not the scores
     peakList  = [x[0] for x in peakScores]
     sugarList = [x[2] for x in peakScores]
     
     #FOR DEBUGGING OUTPUT
     #print "Current scores:"
     #print "overall\t\tphosDist\tphosAngle\tsPsAngle\tdensity score\tw. den score\tsugar score\tphos score"
     #for x in peakScores:
     #    #print "SCORE: %f\tSUGAR SCORE: %f" % (x[1], x[2][0][3])
     #    print "\t".join(map(str, (x[1],) + x[3:]))
     
     return (peakList, sugarList)