comparison spring_package/Molecule.py @ 17:c790d25086dc draft

"planemo upload commit b0ede77caf410ab69043d33a44e190054024d340-dirty"
author guerler
date Wed, 28 Oct 2020 05:11:56 +0000
parents
children
comparison
equal deleted inserted replaced
16:16eb2acaaa20 17:c790d25086dc
1 class Molecule:
2 def __init__(self, fileName = None):
3 self.calpha = dict()
4 self.biomol = dict()
5 self.rotmat = dict()
6 self.atoms = list()
7 if fileName is not None:
8 self.fromFile(fileName)
9
10 def fromFile(self, fileName):
11 biomolNumber = 0
12 biomolChains = list()
13 with open(fileName) as file:
14 for index, line in enumerate(file):
15 key = line[0:6].strip()
16 if key == "ATOM":
17 atom = line[12:16]
18 atomNumber = line[6:11]
19 chainName = line[21:22]
20 if chainName not in self.calpha:
21 self.calpha[chainName] = dict()
22 x = self.toFloat(line[30:38])
23 y = self.toFloat(line[38:46])
24 z = self.toFloat(line[46:54])
25 occupancy = self.toFloat(line[54:60], optional=True)
26 temperature = self.toFloat(line[54:60], optional=True)
27 residue = line[17:20]
28 residueNumber = self.toInt(line[22:26])
29 atomNumber = self.toInt(line[6:11])
30 atomName = line[12:16]
31 atomDict = dict(x=x, y=y, z=z,
32 residue=residue,
33 occupancy=occupancy,
34 temperature=temperature,
35 atomNumber=atomNumber,
36 atomName=atomName,
37 residueNumber=residueNumber,
38 chainName=chainName)
39 if atom.strip() == "CA":
40 self.calpha[chainName][residueNumber] = atomDict
41 self.atoms.append(atomDict)
42 biokey = "REMARK 350 BIOMOLECULE:"
43 if line[0:len(biokey)] == biokey:
44 biomolNumber = self.toInt(line[len(biokey):])
45 biokey = "REMARK 350 APPLY THE FOLLOWING TO CHAINS:"
46 nextLine = next(file)
47 while nextLine[:len(biokey)] != biokey:
48 nextLine = next(file)
49 biomolChains = nextLine[len(biokey):].split(",")
50 biomolChains = list(map(lambda x: x.strip(), biomolChains))
51 biokey = "REMARK 350 AND CHAINS:"
52 nextLine = next(file)
53 while nextLine[:len(biokey)] == biokey:
54 moreChains = nextLine[len(biokey):].split(",")
55 moreChains = list(map(lambda x: x.strip(), moreChains))
56 biomolChains = biomolChains + moreChains
57 nextLine = next(file)
58 biokey = "REMARK 350 BIOMT"
59 if nextLine[:len(biokey)] == biokey:
60 biomolMatId1, biomolMat1 = self.getFloats(nextLine)
61 nextLine = next(file)
62 biomolMatId2, biomolMat2 = self.getFloats(nextLine)
63 nextLine = next(file)
64 biomolMatId3, biomolMat3 = self.getFloats(nextLine)
65 if biomolMatId1 != biomolMatId2 or biomolMatId1 != biomolMatId3:
66 raise Exception("Invalid rotation matrix format [%s]." % biomolMatId1)
67 matrix = [biomolMat1, biomolMat2, biomolMat3]
68 biomolChains = [c for c in biomolChains if c]
69 if biomolNumber not in self.rotmat:
70 self.rotmat[biomolNumber] = list()
71 self.rotmat[biomolNumber].append(dict(chains=biomolChains, matrix=matrix))
72 removeChains = []
73 for chainName in self.calpha:
74 if len(self.calpha[chainName]) == 0:
75 removeChains.append(chainName)
76 for chainName in removeChains:
77 del self.calpha[chainName]
78 if not self.calpha:
79 raise Exception("Molecule has no atoms.")
80
81 def getFloats(self, nextLine):
82 matId = self.toInt(nextLine[20:23])
83 matLine = nextLine[23:].split()
84 matLine = list(map(lambda x: self.toFloat(x), matLine))
85 return matId, matLine
86
87 def createUnit(self, biomolNumber = 1):
88 molecule = Molecule()
89 chainCount = 0
90 for matrixDict in self.rotmat[biomolNumber]:
91 for chain in matrixDict["chains"]:
92 if chain in self.calpha:
93 chainCopy = dict()
94 for residue in self.calpha[chain]:
95 chainCopy[residue] = self.calpha[chain][residue].copy()
96 for atomNumber in chainCopy:
97 atom = chainCopy[atomNumber]
98 rotmat = matrixDict["matrix"]
99 self.applyMatrix(atom, rotmat)
100 if chain in molecule.calpha:
101 chainName = chainCount
102 else:
103 chainName = chain
104 molecule.calpha[chainName] = chainCopy
105 chainCount = chainCount + 1
106 return molecule
107
108 def applyMatrix(self, atom, rotmat):
109 newx = atom["x"] * rotmat[0][0] + atom["y"] * rotmat[0][1] + atom["z"] * rotmat[0][2] + rotmat[0][3]
110 newy = atom["x"] * rotmat[1][0] + atom["y"] * rotmat[1][1] + atom["z"] * rotmat[1][2] + rotmat[1][3]
111 newz = atom["x"] * rotmat[2][0] + atom["y"] * rotmat[2][1] + atom["z"] * rotmat[2][2] + rotmat[2][3]
112 atom["x"] = newx
113 atom["y"] = newy
114 atom["z"] = newz
115 return atom
116
117 def toFloat(self, x, optional=False):
118 try:
119 return float(x)
120 except:
121 if not optional:
122 raise Exception("Invalid float conversion [%s]." % x)
123 return 0.0
124
125 def toInt(self, x):
126 try:
127 return int(x)
128 except:
129 raise Exception("Invalid integer conversion [%s]." % x)
130
131 def saveChain(self, chainName, outputName):
132 print ("Writing PDB file to %s." % outputName)
133 f = open(outputName, "w")
134 for residueNumber in sorted(self.calpha[chainName].keys()):
135 ca = self.calpha[chainName][residueNumber]
136 if ca["residue"] is not None:
137 f.write(self.atomString(ca))
138 f.close()
139
140 def save(self, outputName, append=False, chainName=None):
141 print ("Writing atoms to PDB file to %s." % outputName)
142 fileFlag = "+a" if append else "w"
143 f = open(outputName, fileFlag)
144 for atom in self.atoms:
145 atom["chainName"] = chainName if chainName else atom["chainName"]
146 f.write(self.atomString(atom))
147 f.write("TER\n")
148 f.close()
149
150 def atomString(self, atom):
151 return "ATOM %5d %s %s %s%4d %8.3f%8.3f%8.3f%6.2f%6.2f\n" % (atom["atomNumber"], atom["atomName"], atom["residue"], atom["chainName"], atom["residueNumber"], atom["x"], atom["y"], atom["z"], atom["occupancy"], atom["temperature"])
152