PageRenderTime 116ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/Tailor/Feature.py

https://github.com/gilleain/tailor
Python | 253 lines | 225 code | 22 blank | 6 comment | 27 complexity | f7526c1ec92f598b3e338b9cdaf4061f MD5 | raw file
  1. from copy import copy, deepcopy
  2. from Geometry import Vector
  3. #from Description import ChainDescription, ResidueDescription, AtomDescription
  4. from Exception import DescriptionException
  5. def chunk(l, i):
  6. if i > len(l):
  7. return
  8. else:
  9. k = 0
  10. for j in range(i, len(l)):
  11. yield l[k:j]
  12. k += 1
  13. class Feature(object):
  14. def __init__(self):
  15. self.subFeatures = []
  16. def add(self, feature):
  17. self.subFeatures.append(feature)
  18. def listFeaturesThatMatch(self, description):
  19. return iter(self.searchForFeaturesThatMatch(description))
  20. def searchForFeaturesThatMatch(self, description):
  21. matchingFeatures = []
  22. subFeatures = self.getSubFeaturesBelowLevel(description.levelCode)
  23. descriptionLength = len(description)
  24. featureType = descriptionToFeatureMap[type(description)]
  25. for subFeatureList in chunk(subFeatures, descriptionLength):
  26. # note that this is not a normal method call as such - featureType is a class
  27. feature = featureType(description.getName())
  28. for i, subFeature in enumerate(subFeatureList):
  29. subFeatureCopy = copy(subFeature)
  30. subFeatureCopy.position = i + 1
  31. feature.add(subFeatureCopy)
  32. if description.describes(feature):
  33. matchingFeatures.append(feature)
  34. return matchingFeatures
  35. def getSubFeaturesBelowLevel(self, levelCode):
  36. if self.levelCode == levelCode or self.levelCode == "A":
  37. return self.subFeatures
  38. else:
  39. for subFeature in self.subFeatures:
  40. return subFeature.getSubFeaturesBelowLevel(levelCode)
  41. def findFeature(self, description):
  42. if self.levelCode == description.levelCode:
  43. if description.describes(self):
  44. copySelf = copy(self)
  45. copySelf.subFeatures = []
  46. for subDescription in description:
  47. matchingSubFeature = self.searchSubFeatures(subDescription)
  48. if matchingSubFeature is not None:
  49. copySelf.add(matchingSubFeature)
  50. else:
  51. raise DescriptionException, "no match for description %s" % subDescription
  52. """
  53. copySelf.subFeatures = [copy(sf) for sf in self]
  54. """
  55. return copySelf
  56. else:
  57. return self.searchSubFeatures(description)
  58. def searchSubFeatures(self, description):
  59. for subFeature in self:
  60. result = subFeature.findFeature(description)
  61. if result is not None:
  62. return result
  63. return None
  64. def __len__(self):
  65. return len(self.subFeatures)
  66. def __iter__(self):
  67. return iter(self.subFeatures)
  68. def __getitem__(self, index):
  69. return self.subFeatures[index]
  70. def getCenter(self):
  71. if len(self) > 0:
  72. total = Vector(0,0,0)
  73. for subFeature in self.subFeatures:
  74. total += subFeature.center
  75. return total / len(self)
  76. else:
  77. if self.levelCode == "A":
  78. return self.getAtomCenter()
  79. else:
  80. # this shouldn't really happen!
  81. return Vector(0,0,0)
  82. center = property(getCenter)
  83. class Structure(Feature):
  84. def __init__(self, id):
  85. super(type(self), self).__init__()
  86. self.id = id
  87. self.levelCode = "S"
  88. def chainsWithID(self, chainID):
  89. for model in self:
  90. for chain in model:
  91. if chainID == "" or chain.chainID == chainID:
  92. yield chain
  93. def chainsOfType(self, chainType):
  94. chainsToReturn = []
  95. for model in self:
  96. for chain in model:
  97. #print "comparing", chain.chainType, "with", chainType, "in", self.id
  98. if chainType == "" or chain.chainType == chainType:
  99. chainsToReturn.append(chain)
  100. else:
  101. continue
  102. return chainsToReturn
  103. def __repr__(self):
  104. return "%s" % self.id
  105. class Model(Feature):
  106. def __init__(self, number):
  107. super(type(self), self).__init__()
  108. self.number = number
  109. self.levelCode = "M"
  110. def __repr__(self):
  111. return "%s" % self.number
  112. class Chain(Feature):
  113. def __init__(self, chainID, chainType=None):
  114. super(type(self), self).__init__()
  115. self.chainID = chainID
  116. self.chainType = chainType
  117. self.levelCode = "C"
  118. def getFirst(self):
  119. return self.subFeatures[0]
  120. first = property(getFirst)
  121. def getLast(self):
  122. return self.subFeatures[-1]
  123. last = property(getLast)
  124. def getResidueRange(self):
  125. if len(self) > 1:
  126. return "%s-%s" % (self.first.number, self.last.number)
  127. else:
  128. return "%s" % self.first.number
  129. residueRange = property(getResidueRange)
  130. def getResidueNumber(self, residueNumber):
  131. for r in self:
  132. if r.number == residueNumber:
  133. return r
  134. return None
  135. def __repr__(self):
  136. return "%s %s %s" % (self.chainType, self.chainID, self.residueRange)
  137. class Residue(Feature):
  138. def __init__(self, residueID, resname, segID=None):
  139. super(type(self), self).__init__()
  140. if isinstance(residueID, tuple):
  141. self.residueID = residueID
  142. else:
  143. self.residueID = (residueID, '')
  144. self.resname = resname
  145. self.segID = segID
  146. self.levelCode = "R"
  147. def getNumber(self):
  148. return self.residueID[0]
  149. number = property(getNumber)
  150. def getAtom(self, atomName):
  151. for atom in self:
  152. if atom.name == atomName:
  153. return atom
  154. raise KeyError, "No atom with name %s" % atomName
  155. def getAtomPosition(self, atomName):
  156. return self.getAtom(atomName).getAtomCenter()
  157. def toFullString(self):
  158. return "%s%s" % (str(self), str(self.subFeatures))
  159. def __repr__(self):
  160. return "%s%s%s" % (self.resname, self.residueID[0], self.residueID[1])
  161. class Atom(Feature):
  162. def __init__(self, name, coord, b_factor=None, occupancy=1.0, altloc=None):
  163. super(type(self), self).__init__()
  164. self.name = name.strip()
  165. self.coord = coord
  166. self.b_factor = b_factor
  167. self.occupancy = occupancy
  168. self.altloc = altloc
  169. self.levelCode = "A"
  170. def getAtomCenter(self):
  171. if isinstance(self.coord, Vector):
  172. return self.coord
  173. else:
  174. return Vector(self.coord[0], self.coord[1], self.coord[2])
  175. def __repr__(self):
  176. return "%s" % self.name
  177. descriptionToFeatureMap = {}
  178. """
  179. ChainDescription : Chain,
  180. ResidueDescription : Residue,
  181. AtomDescription : Atom
  182. }
  183. """
  184. featureToSubFeatureMap = {
  185. Structure : Model,
  186. Model : Chain,
  187. Chain : Residue,
  188. Residue : Atom,
  189. Atom : None
  190. }
  191. if __name__ == "__main__":
  192. import sys
  193. from Parse import PDBFileList
  194. from Feature import *
  195. path = sys.argv[1]
  196. structure = PDBFileList(path)[0]
  197. nestFeature = predefined_features["RLnest"]
  198. extraResidue = ResidueDescription({"position" : 4})
  199. extraResidue.addMatchCondition("resname", "GLY")
  200. #nestFeature.addResidue(extraResidue)
  201. print(nestFeature)
  202. for i, nest in enumerate(structure.list_features(predefined_descriptions["RLnest"])):
  203. print("nest", i, nest)