def findPositions(self): # First atom at origin self.coordinates[self.data[0][0]] = Vector(0,0,0) # Second atom along x-axis self.coordinates[self.data[1][0]] = Vector(self.data[1][2],0,0) # Third atom in xy-plane try: pos1 = self.coordinates[self.data[2][1]] except KeyError: raise ValueError("atom %d has no defined position" % self.data[2][1].number) try: pos2 = self.coordinates[self.data[2][3]] except KeyError: raise ValueError("atom %d has no defined position" % self.data[2][3].number) sphere = Sphere(pos1, self.data[2][2]) cone = Cone(pos1, pos2-pos1, self.data[2][4]) plane = Plane(Vector(0,0,0), Vector(0,0,1)) points = sphere.intersectWith(cone).intersectWith(plane) self.coordinates[self.data[2][0]] = points[0] # All following atoms defined by distance + angle + dihedral for entry in self.data[3:]: try: pos1 = self.coordinates[entry[1]] except KeyError: raise ValueError("atom %d has no defined position" % entry[1].number) try: pos2 = self.coordinates[entry[3]] except KeyError: raise ValueError("atom %d has no defined position" % entry[3].number) try: pos3 = self.coordinates[entry[5]] except KeyError: raise ValueError("atom %d has no defined position" % entry[5].number) distance = entry[2] angle = entry[4] dihedral = entry[6] sphere = Sphere(pos1, distance) cone = Cone(pos1, pos2-pos1, angle) plane123 = Plane(pos3, pos2, pos1) points = sphere.intersectWith(cone).intersectWith(plane123) for p in points: if Plane(pos2, pos1, p).normal * plane123.normal > 0: break p = rotatePoint(p, Line(pos1, pos2-pos1), dihedral) self.coordinates[entry[0]] = p
def findPositions(self): # First atom at origin self.coordinates[self.data[0][0]] = Vector(0, 0, 0) # Second atom along x-axis self.coordinates[self.data[1][0]] = Vector(self.data[1][2], 0, 0) # Third atom in xy-plane try: pos1 = self.coordinates[self.data[2][1]] except KeyError: raise ValueError("atom %d has no defined position" % self.data[2][1].number) try: pos2 = self.coordinates[self.data[2][3]] except KeyError: raise ValueError("atom %d has no defined position" % self.data[2][3].number) sphere = Sphere(pos1, self.data[2][2]) cone = Cone(pos1, pos2 - pos1, self.data[2][4]) plane = Plane(Vector(0, 0, 0), Vector(0, 0, 1)) points = sphere.intersectWith(cone).intersectWith(plane) self.coordinates[self.data[2][0]] = points[0] # All following atoms defined by distance + angle + dihedral for entry in self.data[3:]: try: pos1 = self.coordinates[entry[1]] except KeyError: raise ValueError("atom %d has no defined position" % entry[1].number) try: pos2 = self.coordinates[entry[3]] except KeyError: raise ValueError("atom %d has no defined position" % entry[3].number) try: pos3 = self.coordinates[entry[5]] except KeyError: raise ValueError("atom %d has no defined position" % entry[5].number) distance = entry[2] angle = entry[4] dihedral = entry[6] sphere = Sphere(pos1, distance) cone = Cone(pos1, pos2 - pos1, angle) plane123 = Plane(pos3, pos2, pos1) points = sphere.intersectWith(cone).intersectWith(plane123) for p in points: if Plane(pos2, pos1, p).normal * plane123.normal > 0: break p = rotatePoint(p, Line(pos1, pos2 - pos1), dihedral) self.coordinates[entry[0]] = p
def Cartesian(self, BAT): """ Conversion from (internal or extended) Bond-Angle-Torsion to Cartesian coordinates """ # Arrange BAT coordinates in convenient arrays offset = 6 if len(BAT)==(3*self.molecule.numberOfAtoms()) else 0 bonds = BAT[offset+3:self.ntorsions+offset+3] angles = BAT[self.ntorsions+offset+3:2*self.ntorsions+offset+3] phase_torsions = BAT[2*self.ntorsions+offset+3:] torsions = [(phase_torsions[n] + phase_torsions[self._firstTorsionInd[n]]) \ if self._firstTorsionInd[n]!=n else phase_torsions[n] \ for n in range(self.ntorsions)] # Determine the positions of the first three atoms p1 = Vector(0,0,0) # First atom at origin p2 = Vector(0,0,BAT[offset]) # Second atom along z-axis # Third atom in xz-plane sphere = Sphere(p2, BAT[offset+1]) cone = Cone(p2, -p2, BAT[offset+2]) plane = Plane(p1, Vector(0,1,0)) p3 = sphere.intersectWith(cone).intersectWith(plane)[0] # If appropriate, rotate and translate the first three atoms if offset==6: p1 = np.array(p1) p2 = np.array(p2) p3 = np.array(p3) # Rotate the third atom by the appropriate value (phi,theta,omega) = BAT[3:6] co = np.cos(omega) so = np.sin(omega) Romega = np.array([[co, -so, 0],[so, co, 0], [0, 0, 1]]) p3 = Romega.dot(p3) # Rotate the second two atoms to point in the right direction cp = np.cos(phi) sp = np.sin(phi) ct = np.cos(theta) st = np.sin(theta) Re = np.array([[cp*ct,-sp,cp*st],[ct*sp,cp,sp*st],[-st,0,ct]]) p2 = Re.dot(p2) p3 = Re.dot(p3) # Translate the first three atoms by the origin origin = np.array(BAT[:3]) p1 += origin p2 += origin p3 += origin self.root[0].setPosition(Vector(p1)) self.root[1].setPosition(Vector(p2)) self.root[2].setPosition(Vector(p3)) # Add fourth and remaining atoms for ((a1,a2,a3,a4), bond, angle, torsion) in zip(self._torsionL,bonds,angles,torsions): sphere = Sphere(a2.position(), bond) cone = Cone(a2.position(), a3.position()-a2.position(), angle) plane123 = Plane(a4.position(), a3.position(), a2.position()) points = sphere.intersectWith(cone).intersectWith(plane123) for p in points: if Plane(a3.position(), a2.position(), p).normal * plane123.normal > 0: break # The line points in the opposite direction to the ZMatrix constructor from # MMTK, but it seems to be correct p = rotatePoint(p, Line(a2.position(), a2.position()-a3.position()), torsion) a1.setPosition(p) return self.universe.configuration().array
def Cartesian(self, BAT): """ Conversion from (internal or extended) Bond-Angle-Torsion to Cartesian coordinates """ # Arrange BAT coordinates in convenient arrays offset = 6 if len(BAT)==(3*self.natoms) else 0 bonds = BAT[offset+3::3] angles = BAT[offset+4::3] phase_torsions = BAT[offset+5::3] torsions = [(phase_torsions[n] + phase_torsions[self._firstTorsionTInd[n]]) \ if self._firstTorsionTInd[n]!=n else phase_torsions[n] \ for n in range(self.ntorsions)] p1 = np.array([0.,0.,0.]) p2 = np.array([0.,0.,BAT[offset]]) p3 = np.array([BAT[offset+1]*np.sin(BAT[offset+2]), 0., \ BAT[offset]-BAT[offset+1]*np.cos(BAT[offset+2])]) # If appropriate, rotate and translate the first three atoms if offset==6: # Rotate the third atom by the appropriate value (phi,theta,omega) = BAT[3:6] co = np.cos(omega) so = np.sin(omega) Romega = np.array([[co, -so, 0],[so, co, 0], [0, 0, 1]]) p3 = Romega.dot(p3) # Rotate the second two atoms to point in the right direction cp = np.cos(phi) sp = np.sin(phi) ct = np.cos(theta) st = np.sin(theta) Re = np.array([[cp*ct,-sp,cp*st],[ct*sp,cp,sp*st],[-st,0,ct]]) p2 = Re.dot(p2) p3 = Re.dot(p3) # Translate the first three atoms by the origin origin = np.array(BAT[:3]) p1 += origin p2 += origin p3 += origin XYZ = np.zeros((self.natoms,3)) XYZ[self.rootInd[0]] = p1 XYZ[self.rootInd[1]] = p2 XYZ[self.rootInd[2]] = p3 for ((a1,a2,a3,a4), bond, angle, torsion) in \ zip(self._torsionIndL,bonds,angles,torsions): sphere = Sphere(Vector(XYZ[a2]), bond) cone = Cone(Vector(XYZ[a2]), Vector(XYZ[a3]-XYZ[a2]), angle) plane123 = Plane(Vector(XYZ[a4]), Vector(XYZ[a3]), Vector(XYZ[a2])) points = sphere.intersectWith(cone).intersectWith(plane123) p = points[0] if (Plane(Vector(XYZ[a3]), Vector(XYZ[a2]), points[0]).normal*plane123.normal)>0 else points[1] p = rotatePoint(Vector(p), Line(Vector(XYZ[a2]), Vector(XYZ[a2]-XYZ[a3])), torsion) XYZ[a1] = p.array return XYZ for ((a1,a2,a3,a4), bond, angle, torsion) in \ zip(self._torsionIndL,bonds,angles,torsions): p2 = XYZ[a2] p3 = XYZ[a3] p4 = XYZ[a4] # circle = sphere.intersectWith(cone) n23 = normalize(p3-p2) # points = circle.intersectWith(plane123) # plane.intersectWith(Plane(circle.center, circle.normal)) is a line # line_direction = cross(normalize(cross(p4-p3,n23)),n23) # Rotate the point about the p2-p3 axis by the torsion angle v21 = (bond*np.cos(angle))*n23 - (bond*np.sin(angle))*cross(normalize(cross(p4-p3,n23)),n23) s = np.sin(torsion) c = np.cos(torsion) XYZ[a1] = p2 - cross(n23,v21)*s + np.sum(n23*v21)*n23*(1.0-c) + v21*c
def Cartesian(self, BAT): """ Conversion from (internal or extended) Bond-Angle-Torsion to Cartesian coordinates """ # Arrange BAT coordinates in convenient arrays offset = 6 if len(BAT) == (3 * self.natoms) else 0 bonds = BAT[offset + 3::3] angles = BAT[offset + 4::3] phase_torsions = BAT[offset + 5::3] torsions = [(phase_torsions[n] + phase_torsions[self._firstTorsionTInd[n]]) \ if self._firstTorsionTInd[n]!=n else phase_torsions[n] \ for n in range(self.ntorsions)] p1 = np.array([0., 0., 0.]) p2 = np.array([0., 0., BAT[offset]]) p3 = np.array([BAT[offset+1]*np.sin(BAT[offset+2]), 0., \ BAT[offset]-BAT[offset+1]*np.cos(BAT[offset+2])]) # If appropriate, rotate and translate the first three atoms if offset == 6: # Rotate the third atom by the appropriate value (phi, theta, omega) = BAT[3:6] co = np.cos(omega) so = np.sin(omega) Romega = np.array([[co, -so, 0], [so, co, 0], [0, 0, 1]]) p3 = Romega.dot(p3) # Rotate the second two atoms to point in the right direction cp = np.cos(phi) sp = np.sin(phi) ct = np.cos(theta) st = np.sin(theta) Re = np.array([[cp * ct, -sp, cp * st], [ct * sp, cp, sp * st], [-st, 0, ct]]) p2 = Re.dot(p2) p3 = Re.dot(p3) # Translate the first three atoms by the origin origin = np.array(BAT[:3]) p1 += origin p2 += origin p3 += origin XYZ = np.zeros((self.natoms, 3)) XYZ[self.rootInd[0]] = p1 XYZ[self.rootInd[1]] = p2 XYZ[self.rootInd[2]] = p3 for ((a1,a2,a3,a4), bond, angle, torsion) in \ zip(self._torsionIndL,bonds,angles,torsions): sphere = Sphere(Vector(XYZ[a2]), bond) cone = Cone(Vector(XYZ[a2]), Vector(XYZ[a3] - XYZ[a2]), angle) plane123 = Plane(Vector(XYZ[a4]), Vector(XYZ[a3]), Vector(XYZ[a2])) points = sphere.intersectWith(cone).intersectWith(plane123) p = points[0] if (Plane(Vector(XYZ[a3]), Vector( XYZ[a2]), points[0]).normal * plane123.normal) > 0 else points[1] p = rotatePoint(Vector(p), Line(Vector(XYZ[a2]), Vector(XYZ[a2] - XYZ[a3])), torsion) XYZ[a1] = p.array return XYZ for ((a1,a2,a3,a4), bond, angle, torsion) in \ zip(self._torsionIndL,bonds,angles,torsions): p2 = XYZ[a2] p3 = XYZ[a3] p4 = XYZ[a4] # circle = sphere.intersectWith(cone) n23 = normalize(p3 - p2) # points = circle.intersectWith(plane123) # plane.intersectWith(Plane(circle.center, circle.normal)) is a line # line_direction = cross(normalize(cross(p4-p3,n23)),n23) # Rotate the point about the p2-p3 axis by the torsion angle v21 = (bond * np.cos(angle)) * n23 - (bond * np.sin(angle)) * cross( normalize(cross(p4 - p3, n23)), n23) s = np.sin(torsion) c = np.cos(torsion) XYZ[a1] = p2 - cross(n23, v21) * s + np.sum( n23 * v21) * n23 * (1.0 - c) + v21 * c
def Cartesian(self, BAT): """ Conversion from (internal or extended) Bond-Angle-Torsion to Cartesian coordinates """ # Arrange BAT coordinates in convenient arrays offset = 6 if len(BAT) == (3 * self.molecule.numberOfAtoms()) else 0 bonds = BAT[offset + 3:self.ntorsions + offset + 3] angles = BAT[self.ntorsions + offset + 3:2 * self.ntorsions + offset + 3] phase_torsions = BAT[2 * self.ntorsions + offset + 3:] torsions = [(phase_torsions[n] + phase_torsions[self._firstTorsionInd[n]]) \ if self._firstTorsionInd[n]!=n else phase_torsions[n] \ for n in range(self.ntorsions)] # Determine the positions of the first three atoms p1 = Vector(0, 0, 0) # First atom at origin p2 = Vector(0, 0, BAT[offset]) # Second atom along z-axis # Third atom in xz-plane sphere = Sphere(p2, BAT[offset + 1]) cone = Cone(p2, -p2, BAT[offset + 2]) plane = Plane(p1, Vector(0, 1, 0)) p3 = sphere.intersectWith(cone).intersectWith(plane)[0] # If appropriate, rotate and translate the first three atoms if offset == 6: p1 = np.array(p1) p2 = np.array(p2) p3 = np.array(p3) # Rotate the third atom by the appropriate value (phi, theta, omega) = BAT[3:6] co = np.cos(omega) so = np.sin(omega) Romega = np.array([[co, -so, 0], [so, co, 0], [0, 0, 1]]) p3 = Romega.dot(p3) # Rotate the second two atoms to point in the right direction cp = np.cos(phi) sp = np.sin(phi) ct = np.cos(theta) st = np.sin(theta) Re = np.array([[cp * ct, -sp, cp * st], [ct * sp, cp, sp * st], [-st, 0, ct]]) p2 = Re.dot(p2) p3 = Re.dot(p3) # Translate the first three atoms by the origin origin = np.array(BAT[:3]) p1 += origin p2 += origin p3 += origin self.root[0].setPosition(Vector(p1)) self.root[1].setPosition(Vector(p2)) self.root[2].setPosition(Vector(p3)) # Add fourth and remaining atoms for ((a1, a2, a3, a4), bond, angle, torsion) in zip(self._torsionL, bonds, angles, torsions): sphere = Sphere(a2.position(), bond) cone = Cone(a2.position(), a3.position() - a2.position(), angle) plane123 = Plane(a4.position(), a3.position(), a2.position()) points = sphere.intersectWith(cone).intersectWith(plane123) for p in points: if Plane(a3.position(), a2.position(), p).normal * plane123.normal > 0: break # The line points in the opposite direction to the ZMatrix constructor from # MMTK, but it seems to be correct p = rotatePoint(p, Line(a2.position(), a2.position() - a3.position()), torsion) a1.setPosition(p)