Mercurial > repos > guerler > springsuite
view spring_package/Molecule.py @ 37:0be0af9e695d draft
"planemo upload commit c716195a2cc1ed30ff8c4936621091296a93b2fc"
author | guerler |
---|---|
date | Wed, 25 Nov 2020 14:35:35 +0000 |
parents | |
children | 172398348efd |
line wrap: on
line source
class Molecule: def __init__(self, fileName=None): self.calpha = dict() self.biomol = dict() self.atoms = list() if fileName is not None: self.fromFile(fileName) def fromFile(self, fileName): biomolNumber = 0 biomolChains = list() self.biomol[0] = None with open(fileName) as file: for line in file: key = line[0:6].strip() if key == "ATOM": atom = line[12:16] atomNumber = line[6:11] chainName = line[21:22] if chainName not in self.calpha: self.calpha[chainName] = dict() x = self.toFloat(line[30:38]) y = self.toFloat(line[38:46]) z = self.toFloat(line[46:54]) occupancy = self.toFloat(line[54:60], optional=True) temperature = self.toFloat(line[54:60], optional=True) residue = line[17:20] residueNumber = self.toInt(line[22:26]) atomNumber = self.toInt(line[6:11]) atomName = line[12:16] atomDict = dict(x=x, y=y, z=z, residue=residue, occupancy=occupancy, temperature=temperature, atomNumber=atomNumber, atomName=atomName, residueNumber=residueNumber, chainName=chainName) if atom.strip() == "CA": self.calpha[chainName][residueNumber] = atomDict self.atoms.append(atomDict) biokey = "REMARK 350 BIOMOLECULE:" if line[0:len(biokey)] == biokey: biomolNumber = self.toInt(line[len(biokey):]) if biomolNumber == 0: raise Exception("Invalid biomolecule identifier [0].") biokey = "REMARK 350 APPLY THE FOLLOWING TO CHAINS:" nextLine = next(file) while nextLine[:len(biokey)] != biokey: nextLine = next(file) biomolChains = nextLine[len(biokey):].split(",") biomolChains = list(map(lambda x: x.strip(), biomolChains)) biokey = "REMARK 350 AND CHAINS:" nextLine = next(file) while nextLine[:len(biokey)] == biokey: moreChains = nextLine[len(biokey):].split(",") moreChains = list(map(lambda x: x.strip(), moreChains)) biomolChains = biomolChains + moreChains nextLine = next(file) biokey = "REMARK 350 BIOMT" if nextLine[:len(biokey)] == biokey: biomolMatId1, biomolMat1 = self.getFloats(nextLine) nextLine = next(file) biomolMatId2, biomolMat2 = self.getFloats(nextLine) nextLine = next(file) biomolMatId3, biomolMat3 = self.getFloats(nextLine) if biomolMatId1 != biomolMatId2 or biomolMatId1 != biomolMatId3: raise Exception("Invalid rotation matrix format [%s]." % biomolMatId1) matrix = [biomolMat1, biomolMat2, biomolMat3] biomolChains = [c for c in biomolChains if c] if biomolNumber not in self.biomol: self.biomol[biomolNumber] = list() self.biomol[biomolNumber].append(dict(chains=biomolChains, matrix=matrix)) removeChains = [] for chainName in self.calpha: if len(self.calpha[chainName]) == 0: removeChains.append(chainName) for chainName in removeChains: del self.calpha[chainName] if not self.calpha: raise Exception("Molecule has no atoms.") def getFloats(self, nextLine): matId = self.toInt(nextLine[20:23]) matLine = nextLine[23:].split() matLine = list(map(lambda x: self.toFloat(x), matLine)) return matId, matLine def createUnit(self, biomolNumber=1): molecule = Molecule() chainCount = 0 for matrixDict in self.biomol[biomolNumber]: for chain in matrixDict["chains"]: if chain in self.calpha: chainCopy = dict() for residue in self.calpha[chain]: chainCopy[residue] = self.calpha[chain][residue].copy() for atomNumber in chainCopy: atom = chainCopy[atomNumber] rotmat = matrixDict["matrix"] self.applyMatrix(atom, rotmat) if chain in molecule.calpha: chainName = "%s%d" % (chain, chainCount) else: chainName = chain molecule.calpha[chainName] = chainCopy chainCount = chainCount + 1 return molecule def getSequence(self, chainName): seq = "" if chainName not in self.calpha: raise Exception("Chain identifier not found [%s]" % chainName) chainDict = self.calpha[chainName] for residueNumber in sorted(chainDict): seq = seq + self.toSingleAmino(chainDict[residueNumber]["residue"]) return seq def applyMatrix(self, atom, rotmat): newx = atom["x"] * rotmat[0][0] + atom["y"] * rotmat[0][1] + atom["z"] * rotmat[0][2] + rotmat[0][3] newy = atom["x"] * rotmat[1][0] + atom["y"] * rotmat[1][1] + atom["z"] * rotmat[1][2] + rotmat[1][3] newz = atom["x"] * rotmat[2][0] + atom["y"] * rotmat[2][1] + atom["z"] * rotmat[2][2] + rotmat[2][3] atom["x"] = newx atom["y"] = newy atom["z"] = newz return atom def toFloat(self, x, optional=False): try: return float(x) except Exception: if not optional: raise Exception("Invalid float conversion [%s]." % x) return 0.0 def toInt(self, x): try: return int(x) except Exception: raise Exception("Invalid integer conversion [%s]." % x) def toSingleAmino(self, seq): code = dict(GLY="G", ALA="A", VAL="V", LEU="L", ILE="I", MET="M", PHE="F", PRO="P", TYR="Y", TRP="W", LYS="K", SER="S", CYS="C", ASN="N", GLN="Q", HIS="H", THR="T", GLU="E", ASP="D", ARG="R") return code[seq] if seq in code else "X" def saveChain(self, chainName, outputName): print("Writing PDB file to %s." % outputName) f = open(outputName, "w") for residueNumber in sorted(self.calpha[chainName].keys()): ca = self.calpha[chainName][residueNumber] if ca["residue"] is not None: f.write(self.atomString(ca)) f.close() def save(self, outputName, append=False, chainName=None): print("Writing atoms to PDB file to %s." % outputName) fileFlag = "+a" if append else "w" f = open(outputName, fileFlag) for atom in self.atoms: atom["chainName"] = chainName if chainName else atom["chainName"] f.write(self.atomString(atom)) f.write("TER\n") f.close() def atomString(self, atom): return "ATOM %5d %s %s %1s%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"])