def alignmol(mol): masses = [] coordinates = [a.coords for a in mol.atoms] totalMass = 0 for atom in mol: m = 1 if options.useweights: m = atom.atomicmass masses.append(m) totalMass += m coordinates = numpy.array(coordinates) masses = numpy.array(masses) trans = -numpy.sum(coordinates * masses[:, numpy.newaxis], axis=0) / totalMass mol.OBMol.Translate(openbabel.vector3(*trans)) coordinates += trans #this is shamelessly stolen from the mdanalysis package inertia = calcI(masses, coordinates) eigenval, eigenvec = eig(inertia) # Sort indices = numpy.argsort(eigenval) # Return transposed in more logical form. See Issue 33. principalAxes = eigenvec[:, indices].T if det(principalAxes) < 0: principalAxes = -principalAxes #remove reflection !!Is this correct?? Kabasch wiki says negate just one row, but this is Kabasch... xrot = openbabel.double_array([1, 0, 0, 0, -1, 0, 0, 0, -1]) yrot = openbabel.double_array([-1, 0, 0, 0, 1, 0, 0, 0, -1]) zrot = openbabel.double_array([-1, 0, 0, 0, -1, 0, 0, 0, 1]) ident = openbabel.double_array([1, 0, 0, 0, 1, 0, 0, 0, 1]) rotmat = openbabel.double_array(principalAxes.flatten()) mol.OBMol.Rotate(rotmat) coordinates = [a.coords for a in mol.atoms] #should be modified (a, b) = calcSplitMoments(coordinates, 1) if (a < b): mol.OBMol.Rotate(xrot) # print a,b (a, b) = calcSplitMoments(coordinates, 0) if (a < b): mol.OBMol.Rotate(yrot) # print a,b return
def shiftAndCalculateReactionCoordinate(mol,nOfAtoms,reactionCoordinate,vector,h,coords=None): # this function is called many times if coords==None: tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = [ tmp[i] for i in xrange(3*nOfAtoms) ] coords = addVec(coords,multVec(h,vector)) mol.SetCoordinates(openbabel.double_array(coords)) return reactionCoordinate(mol)
def separateFragments(pymol, dist=3.0): mol = pymol.OBMol nAtom = len(pymol.atoms) unvisited = set(range(1, nAtom + 1)) q = deque([1]) fragments = [set()] while q or unvisited: if q: curr = q.popleft() unvisited.remove(curr) fragments[-1].add(curr) else: curr = unvisited.pop() fragments.append({curr}) atom = mol.GetAtom(curr) for nbr in ob.OBAtomAtomIter(atom): nbrNum = nbr.GetIdx() if nbrNum in unvisited: q.append(nbrNum) coords = [] for atom in pymol: coords.append(list(atom.coords)) nFragments = len(fragments) delta = -(nFragments - 1) * dist / 2.0 for fragment in fragments: for atomIdx in fragment: x, y, z = coords[atomIdx - 1] coords[atomIdx - 1] = [x + delta, y + delta, z + delta] delta += dist coords = [item for sublist in coords for item in sublist] c_coords = ob.double_array(coords) mol.SetCoordinates(c_coords)
def alignmol(mol): masses = [] coordinates = [ a.coords for a in mol.atoms] totalMass = 0 for atom in mol: m = 1 if options.useweights: m = atom.atomicmass masses.append(m) totalMass += m coordinates = numpy.array(coordinates) masses = numpy.array(masses) trans = -numpy.sum(coordinates * masses[:, numpy.newaxis], axis=0) / totalMass mol.OBMol.Translate(openbabel.vector3(*trans)) coordinates += trans #this is shamelessly stolen from the mdanalysis package inertia = calcI(masses, coordinates) eigenval, eigenvec = eig(inertia) # Sort indices = numpy.argsort(eigenval) # Return transposed in more logical form. See Issue 33. principalAxes = eigenvec[:,indices].T if det(principalAxes) < 0: principalAxes = -principalAxes #remove reflection !!Is this correct?? Kabasch wiki says negate just one row, but this is Kabasch... xrot = openbabel.double_array([1,0,0,0,-1,0,0,0,-1]) yrot = openbabel.double_array([-1,0,0,0,1,0,0,0,-1]) zrot = openbabel.double_array([-1,0,0,0,-1,0,0,0,1]) ident = openbabel.double_array([1,0,0,0,1,0,0,0,1]) rotmat = openbabel.double_array(principalAxes.flatten()) mol.OBMol.Rotate(rotmat) coordinates = [ a.coords for a in mol.atoms] #should be modified (a,b) = calcSplitMoments(coordinates, 1) if(a < b): mol.OBMol.Rotate(xrot) # print a,b (a,b) = calcSplitMoments(coordinates, 0) if(a < b): mol.OBMol.Rotate(yrot) # print a,b return
def set_xyz(x,coords): """ Parameters: mol : Open babel mol object, or anything that can be converted to mol object with get_mol. coords : One-d array of natom floats """ mol = get_mol(x) mol.OBMol.SetCoordinates(openbabel.double_array(coords)) return mol
def rotate(mol, theta, phi): m_theta = np.array([[1.0, 0.0, 0.0], [0.0, math.cos(theta), -math.sin(theta)], [0.0, math.sin(theta), math.cos(theta)]]) m_phi = np.array([[math.cos(phi), 0.0, math.sin(phi)], [0.0, 1.0, 0.0], [-math.sin(phi), 0.0, math.cos(phi)]]) m = np.dot(m_phi, m_theta) m_list = list(itertools.chain(*m)) mol.Rotate(ob.double_array(m_list)) return mol
def shiftAndCalculateReactionCoordinate( mol, nOfAtoms, reactionCoordinate, vector, h, coords=None): # this function is called many times if coords == None: tmp = openbabel.doubleArray_frompointer(mol.GetCoordinates()) coords = [tmp[i] for i in xrange(3 * nOfAtoms)] coords = addVec(coords, multVec(h, vector)) mol.SetCoordinates(openbabel.double_array(coords)) return reactionCoordinate(mol)
def AndersenIntegrator(self,mol,relevantCoordinates,ff,h,reactionCoordinate,timeStep,timeStep2,nuTimesTimeStep): currCoords = self.coords[-1] currVelocity = self.velocity[-1] currAcc = self.acceleration[-1] # calculating next position: nextCoords = self.nOfAtomsX3*[0] for i in xrange(self.nOfAtomsX3): nextCoords[i] = currCoords[i] + timeStep*currVelocity[i] + currAcc[i]*timeStep2/2 # nie jestem pewien tego currAcc for i in xrange(self.nOfAtomsX3): currVelocity[i] = currVelocity[i] + 0.5*timeStep*currAcc[i] # that's the ACTUAL currentVelocity mol.SetCoordinates( openbabel.double_array(nextCoords) ) energy = self.calculateGradU(ff,mol) gradKsi = calcGrad(mol,relevantCoordinates,reactionCoordinate,h) self.calculateZksi( gradKsi ) Zksi = self.Zksi[-1] gradU = self.gradU[-1] if Zksi==0: constraintLambda = 0 else: constraintLambda = (scalarTrippleProduct(self.invMasses,gradKsi,gradU)-calcVectorHessianVectorProduct(mol,reactionCoordinate,h,currVelocity)) / Zksi ########################### #constraintLambda = 0 # if set to 0 it will be a simple Andersen dynamics simulation ########################### currAcc = self.nOfAtomsX3*[0] for i in xrange(self.nOfAtomsX3): currAcc[i] = (-gradU[i] + constraintLambda*gradKsi[i])/self.masses[i] # TODO: upewnij sie, ze tu jest dzielenie przez mase # second velocity half-step for i in xrange(self.nOfAtomsX3): currVelocity[i] = currVelocity[i] + 0.5*timeStep*currAcc[i] # that's the ACTUAL currentVelocity # Andersen thermostat for i in xrange(self.nOfAtoms): if random.random()<nuTimesTimeStep: for j in xrange(3): currVelocity[3*i+j] = random.gauss(0,self.AndersenSigmas[3*i+j]) self.setNonVelocityAtribute(self.coords,nextCoords) self.setNonVelocityAtribute(self.acceleration,currAcc) self.setNonVelocityAtribute(self.gradU,gradU) self.velocity[3] = currVelocity return energy
def make_structure(request): def makeResidue(mol, idx, aaatoms): res = mol.NewResidue() res.SetNum(idx) for atom in ob.OBMolAtomIter(mol): if atom.GetIdx() not in aaatoms: res.AddAtom(atom) aminoacids = request.GET.getlist("as") color = request.GET.get("rescol", "#3EC1CD") mol = ob.OBMol() conv = ob.OBConversion() pattern = ob.OBSmartsPattern() pattern.Init("[NX3][$([CX4H1]([*])),$([CX4H2])][CX3](=[OX1])[OX2]") builder = ob.OBBuilder() conv.SetInAndOutFormats("sdf", "svg") conv.AddOption("d", ob.OBConversion.OUTOPTIONS) conv.AddOption("b", ob.OBConversion.OUTOPTIONS, "none") conv.ReadString(mol, str(Substrate.objects.get(pk=int(aminoacids[0])).structure)) pattern.Match(mol) mollist = pattern.GetUMapList()[0] oatom = mol.GetAtom(mollist[4]) catom = mol.GetAtom(mollist[2]) firstnatom = mol.GetAtom(mollist[0]) makeResidue(mol, 0, mollist) i = 1 for aa in aminoacids[1:]: mol2 = ob.OBMol() conv.ReadString(mol2, str(Substrate.objects.get(pk=int(aa)).structure)) pattern.Match(mol2) mollist = pattern.GetUMapList()[0] makeResidue(mol2, i, mollist) molnatoms = mol.NumAtoms() mol += mol2 natom = mol.GetAtom(molnatoms + mol2.GetAtom(mollist[0]).GetIdx()) builder.Connect(mol, catom.GetIdx(), natom.GetIdx()) foatom = mol.GetAtom(molnatoms + mol2.GetAtom(mollist[4]).GetIdx()) catom = mol.GetAtom(molnatoms + mol2.GetAtom(mollist[2]).GetIdx()) mol.DeleteHydrogens(oatom) mol.DeleteAtom(oatom) natom.SetImplicitValence(3) mol.DeleteHydrogens(natom) mol.AddHydrogens(natom) oatom = foatom i += 1 nidx = firstnatom.GetIdx() oidx = oatom.GetIdx() builder.Build(mol) natom = mol.GetAtom(nidx) oatom = mol.GetAtom(oidx) for res in ob.OBResidueIter(mol): for atom in ob.OBResidueAtomIter(res): for bond in ob.OBAtomBondIter(atom): data = ob.OBPairData() data.SetAttribute("color") data.SetValue(color) bond.CloneData(data) mol.DeleteHydrogens() gen2d = ob.OBOp.FindType("gen2d") gen2d.Do(mol) opp = oatom.GetY() - natom.GetY() adj = oatom.GetX() - natom.GetX() angle = abs(math.atan(opp / adj)) if opp > 0 and adj > 0: pass elif opp > 0 and adj < 0: angle = math.pi - angle elif opp < 0 and adj < 0: angle = math.pi + angle elif opp < 0 and adj > 0: angle = 2 * math.pi - angle angle = -angle mol.Rotate(ob.double_array([math.cos(angle), -math.sin(angle), 0, math.sin(angle), math.cos(angle), 0, 0, 0, 1])) svg = conv.WriteString(mol) # need to get rid of square aspect ratio delstart = svg.find("width") delend = svg.find("svg", delstart) delend = svg.find("viewBox", delend) svgend = svg.rfind("</g>") svg = svg[0:delstart] + svg[delend:svgend] return HttpResponse(svg, mimetype="image/svg+xml")
# generate .top and write fcontent = gen_top(args.force_field, os.path.splitext(args.dfrfile)[0] + ".itp") with open("topology.top", "w") as f: f.write(fcontent) # get the molecule diameter mol.OBMol.Center() maxd = 0.0 for atom in mol: x, y, z = atom.coords r = sqrt(x * x + y * y + z * z) if r > maxd: maxd = r # modify the unit cell and translate the molecule to the center of box boxsize = maxd + 100.0 cell = openbabel.OBUnitCell() cell.SetData(boxsize, boxsize, boxsize, 90.0, 90.0, 90.0) mol.OBMol.CloneData(cell) disp = boxsize / 2.0 arr = openbabel.vector3(openbabel.double_array([disp, disp, disp])) mol.OBMol.Translate(arr) # write .gro mol.write("gro", os.path.splitext(args.txtfile)[0] + ".gro", overwrite=True)
def AndersenIntegrator(self, mol, relevantCoordinates, ff, h, reactionCoordinate, timeStep, timeStep2, nuTimesTimeStep): currCoords = self.coords[-1] currVelocity = self.velocity[-1] currAcc = self.acceleration[-1] # calculating next position: nextCoords = self.nOfAtomsX3 * [0] for i in xrange(self.nOfAtomsX3): nextCoords[ i] = currCoords[i] + timeStep * currVelocity[i] + currAcc[ i] * timeStep2 / 2 # nie jestem pewien tego currAcc for i in xrange(self.nOfAtomsX3): currVelocity[i] = currVelocity[i] + 0.5 * timeStep * currAcc[ i] # that's the ACTUAL currentVelocity mol.SetCoordinates(openbabel.double_array(nextCoords)) energy = self.calculateGradU(ff, mol) gradKsi = calcGrad(mol, relevantCoordinates, reactionCoordinate, h) self.calculateZksi(gradKsi) Zksi = self.Zksi[-1] gradU = self.gradU[-1] if Zksi == 0: constraintLambda = 0 else: constraintLambda = ( scalarTrippleProduct(self.invMasses, gradKsi, gradU) - calcVectorHessianVectorProduct(mol, reactionCoordinate, h, currVelocity)) / Zksi ########################### #constraintLambda = 0 # if set to 0 it will be a simple Andersen dynamics simulation ########################### currAcc = self.nOfAtomsX3 * [0] for i in xrange(self.nOfAtomsX3): currAcc[i] = ( -gradU[i] + constraintLambda * gradKsi[i]) / self.masses[ i] # TODO: upewnij sie, ze tu jest dzielenie przez mase # second velocity half-step for i in xrange(self.nOfAtomsX3): currVelocity[i] = currVelocity[i] + 0.5 * timeStep * currAcc[ i] # that's the ACTUAL currentVelocity # Andersen thermostat for i in xrange(self.nOfAtoms): if random.random() < nuTimesTimeStep: for j in xrange(3): currVelocity[3 * i + j] = random.gauss( 0, self.AndersenSigmas[3 * i + j]) self.setNonVelocityAtribute(self.coords, nextCoords) self.setNonVelocityAtribute(self.acceleration, currAcc) self.setNonVelocityAtribute(self.gradU, gradU) self.velocity[3] = currVelocity return energy
def align_ligand(dummies, ligand): # fit dummy atoms of ligand to defined positions log.info('Aligning ligand dummy atoms to desired dummy atoms...') # 0.9 create local copy, as this function would otherwise modify the given ligand aligned_ligand = openbabel.OBMol(ligand) # 1.0 get dummy atoms from ligand log.debug('... get dummy atoms of ligand') ligand_dummies = get_dummies(ligand) # 1.1 get translation vector from read-in position to origin log.info('... determing translation vector from read-in to origin') translation = ligand_dummies.Center(1) ## DEBUG #obconversion = openbabel.OBConversion() #obconversion.SetOutFormat("pdb") #obconversion.WriteFile(ligand_dummies,"ligand_dummies_centered.pdb") # 1.2 initialize OBAlign for alignment to final destination log.info('... doing the alignment for dummy atoms') aligner = openbabel.OBAlign(dummies, ligand_dummies) success=aligner.Align() if success == False: return None, None #log.info('... done.') rmsd=aligner.GetRMSD() log.debug('RMSD of alignment: ' + str(rmsd)) ## 1.2.1 get Rotation Matrix for alignment log.info('... determining the rotation matrix') rotation_matrix = aligner.GetRotMatrix() rot = openbabel.double_array([1,2,3,4,5,6,7,8,9]) rotation_matrix.GetArray(rot) # .. only for debugging: arewedebugging = log.getLogger() if arewedebugging.isEnabledFor(logging.DEBUG): log.debug('--- rotation matrix ---') for i in range(0,9): log.debug(str(i)+ " : " + str(rot[i])) # 1.3 generate positioning vector ## NB: centering would not work because of rotation!! ## update cooordinates to new value aligner.UpdateCoords(ligand_dummies) log.info('... generating positioning vector') positioning = openbabel.vector3() ## calculate the vector for positioning to destination n = 0 for atom in openbabel.OBMolAtomIter(ligand_dummies): n += 1 positioning += atom.GetVector() positioning /= n # 1.4 move all ligand atoms to fit the pose the dummy atoms have been aligned to ## 1.4.1 generate inverted translation vector to translate ligand to origin translation_to_origin = translation translation_to_origin *= -1 ## 1.4.2 generate inverted rotation matrix to reconstruct alignment results rotation_inversion = rotation_matrix.transpose() rot_inv = openbabel.double_array([1,2,3,4,5,6,7,8,9]) rotation_inversion.GetArray(rot_inv) ## 1.4.3 apply translation to origin, rotation, and translation to final destination aligned_ligand.Translate(translation_to_origin) aligned_ligand.Rotate(rot_inv) aligned_ligand.Translate(positioning) ## 1.5 clean output ligand of dummy atoms, if desired if remove_dummies: log.info('Cleaning the ligand of unwanted dummies...') _temp_atom = [] for atom in openbabel.OBMolAtomIter(aligned_ligand): #aligned_ligand.AddResidue(atom.GetResidue()) #aligned_ligand.AddAtom(atom) if atom.GetAtomicNum() == 0: _temp_atom.append(atom) for a in _temp_atom: aligned_ligand.DeleteAtom(a) #else: #aligned_ligand = ligand log.info('... returning the aligned ligand.') return aligned_ligand, rmsd
print "x=%f; y=%f; z=%f" % (natom.GetX(), natom.GetY(), natom.GetZ()) print "x=%f; y=%f; z=%f" % (oatom.GetX(), oatom.GetY(), oatom.GetZ()) opp = oatom.GetY() - natom.GetY() adj = oatom.GetX() - natom.GetX() angle = abs(math.atan(opp / adj)) if opp > 0 and adj > 0: pass elif opp > 0 and adj < 0: angle = math.pi - angle elif opp < 0 and adj < 0: angle = math.pi + angle elif opp < 0 and adj > 0: angle = 2 * math.pi - angle print math.degrees(angle) angle = -angle mol.Rotate(ob.double_array([math.cos(angle), -math.sin(angle), 0, math.sin(angle), math.cos(angle), 0, 0, 0, 1])) svg = conv.WriteString(mol) # need to get rid of square aspect ratio delstart = svg.find("width") delend = svg.find("svg", delstart) delend = svg.find("viewBox", delend) svgend = svg.rfind("</g>") svg = svg[0:delstart] + svg[delend:svgend] outf = file("test.svg", "w") outf.write(svg) outf.close()