def _align_pythonic(self, coords1, coords2): """the slow pythonic version of align""" # note: this minimizes the angle-distance, but it might be better to # minimize the atomistic distance. These are not always the same c1 = self.topology.coords_adapter(coords1) c2 = self.topology.coords_adapter(coords2) # now account for inner-molecular symmetry for p1, p2, site in izip(c1.rotRigid,c2.rotRigid, self.topology.sites): theta_min = 10. mx2 = rotations.aa2mx(p2) mx1 = rotations.aa2mx(p1).transpose() mx = np.dot(mx1, mx2) # find the symmetry operation which puts p2 into best alignment with p1 for rot in site.symmetries: mx_diff = np.dot(mx, rot) # theta is the rotation angle between p1 and p2 after # applying the symmetry operation rot to site2 theta = np.linalg.norm(rotations.mx2aa(mx_diff)) # remove any extra factors of 2*pi theta -= int(theta / (2.*pi)) * 2.*pi if theta < theta_min: theta_min = theta rot_best = rot p2[:] = rotations.rotate_aa(rotations.mx2aa(rot_best), p2)
def zeroEV(self, x): zev = [] ca = self.coords_adapter(x) cv = self.coords_adapter(np.zeros(x.shape)) translate_rigid = zeroev.zeroEV_translation(ca.posRigid) for v in translate_rigid: cv.posRigid[:] = v zev.append(cv.coords.copy()) #rotate_r = zeroev.zeroEV_rotation(ca.posRigid) #rotate_aa = transform = TransformAngleAxisCluster(self) d = 1e-5 dx = x.copy() transform.rotate(dx, rotations.aa2mx(np.array([d, 0, 0]))) self.align_path([x, dx]) dx -= x dx /= np.linalg.norm(dx) dy = x.copy() transform.rotate(dy, rotations.aa2mx(np.array([0, d, 0]))) self.align_path([x, dy]) dy -= x dy /= np.linalg.norm(dy) dz = x.copy() transform.rotate(dz, rotations.aa2mx(np.array([0, 0, d]))) self.align_path([x, dz]) dz -= x dz /= np.linalg.norm(dz) #print "Zero eigenvectors", zev return zev + [dx, dy, dz]
def distance_squared(self, com1, p1, com2, p2): ''' distance measure between 2 angle axis bodies of same type Parameters ---------- com1: center of mass of 1st site p1: angle axis vector of 1st site com2: center of mass of 2nd site p2: angle axis vector of 2nd site sitetype: AASiteType, optional angle axis site type with mass and moment of inertia tensor returns: distance squared ''' return sitedist(self.get_smallest_rij(com1, com2), p1, p2, self.S, self.W, self.cog) R1 = rotations.aa2mx(p1) R2 = rotations.aa2mx(p2) dR = R2 - R1 dR = dR d_M = self.W*np.sum((com2-com1)**2) # dR_kl S_lm dR_km d_P = np.trace(np.dot(dR, np.dot(self.S, dR.transpose()))) d_mix = 2.*self.W * np.dot((com2-com1), np.dot(dR, self.cog)) return d_M + d_P + d_mix
def _align_pythonic(self, coords1, coords2): """the slow pythonic version of align""" # note: this minimizes the angle-distance, but it might be better to # minimize the atomistic distance. These are not always the same c1 = self.topology.coords_adapter(coords1) c2 = self.topology.coords_adapter(coords2) # now account for inner-molecular symmetry for p1, p2, site in zip(c1.rotRigid, c2.rotRigid, self.topology.sites): theta_min = 10. mx2 = rotations.aa2mx(p2) mx1 = rotations.aa2mx(p1).transpose() mx = np.dot(mx1, mx2) # find the symmetry operation which puts p2 into best alignment with p1 for rot in site.symmetries: mx_diff = np.dot(mx, rot) # theta is the rotation angle between p1 and p2 after # applying the symmetry operation rot to site2 theta = np.linalg.norm(rotations.mx2aa(mx_diff)) # remove any extra factors of 2*pi theta -= int(old_div(theta, (2. * pi))) * 2. * pi if theta < theta_min: theta_min = theta rot_best = rot p2[:] = rotations.rotate_aa(rotations.mx2aa(rot_best), p2)
def mouseMoveEvent(self, event): delta = (event.posF() - self.last_mouse_pos)*0.01 self.last_mouse_pos = event.posF() if event.buttons() == Qt.LeftButton: drot = rot.aa2mx(-np.array([delta.y(), delta.x(), 0.])) self.rotation = np.dot(self.rotation, drot) elif event.buttons() == Qt.RightButton: drot = rot.aa2mx(np.array([0., 0., delta.x()])) self.rotation = np.dot(self.rotation, drot) self.zoom *= 1.0 - 0.2*delta.y() self.repaint()
def mouseMoveEvent(self, event): delta = (event.posF() - self.last_mouse_pos) * 0.01 self.last_mouse_pos = event.posF() if event.buttons() == Qt.LeftButton: drot = rot.aa2mx(-np.array([delta.y(), delta.x(), 0.])) self.rotation = np.dot(self.rotation, drot) elif event.buttons() == Qt.RightButton: drot = rot.aa2mx(np.array([0., 0., delta.x()])) self.rotation = np.dot(self.rotation, drot) self.zoom *= 1.0 - 0.2 * delta.y() self.repaint()
def export_xyz(fl, coords): ca = CoordsAdapter(nrigid=coords.size/6, coords = coords) fl.write("%d\n\n"%(2*ca.nrigid)) for i in xrange(ca.nrigid): a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) x_back = ca.posRigid[i] - 0.4*a # backbone bead x_stack = ca.posRigid[i] + 0.4*a a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([0., 0., 1.])) x_tmp = x_back + 0.2*a fl.write("C %f %f %f\n"%(x_back[0], x_back[1], x_back[2])) fl.write("H %f %f %f\n"%(x_stack[0], x_stack[1], x_stack[2]))
def export_xyz(fl, coords): ca = CoordsAdapter(nrigid=old_div(coords.size, 6), coords=coords) fl.write("%d\n\n" % (2 * ca.nrigid)) for i in range(ca.nrigid): a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) x_back = ca.posRigid[i] - 0.4 * a # backbone bead x_stack = ca.posRigid[i] + 0.4 * a a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([0., 0., 1.])) x_tmp = x_back + 0.2 * a fl.write("C %f %f %f\n" % (x_back[0], x_back[1], x_back[2])) fl.write("H %f %f %f\n" % (x_stack[0], x_stack[1], x_stack[2]))
def testBLJ_isomer(self): """ test with BLJ potential. We have two classes of permutable atoms test case where X2 is an isomer of X1. """ import pele.utils.rotations as rot X1i = np.copy(self.X1) X1 = np.copy(self.X1) X2 = np.copy(X1) #rotate X2 randomly aa = rot.random_aa() rot_mx = rot.aa2mx( aa ) for j in range(self.natoms): i = 3*j X2[i:i+3] = np.dot( rot_mx, X1[i:i+3] ) #permute X2 import random, copy from pele.mindist.permutational_alignment import permuteArray for atomlist in self.permlist: perm = copy.copy(atomlist) random.shuffle( perm ) X2 = permuteArray( X2, perm) X2i = np.copy(X2) #distreturned, X1, X2 = self.runtest(X1, X2) distreturned, X1, X2 = self.runtest(X1, X2, MinPermDistCluster(measure=MeasureAtomicCluster(permlist=self.permlist))) #it's an isomer, so the distance should be zero self.assertTrue( abs(distreturned) < 1e-14, "didn't find isomer: dist = %g" % distreturned)
def test_distpot(): #define two structures natoms = 12 X1 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) X2 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) #make X2 a rotation of X1 print "testing with", natoms, "atoms, with X2 a rotated and permuted isomer of X1" aa = rot.random_aa() rot_mx = rot.aa2mx( aa ) for j in range(natoms): i = 3*j X2[i:i+3] = np.dot( rot_mx, X1[i:i+3] ) #import random, mindistutils #perm = range(natoms) #random.shuffle( perm ) #print perm #X2 = mindistutils.permuteArray( X2, perm) pot = MinPermDistPotential(X1, X2, L = .2) aa = rot.random_aa() e = pot.getEnergy(aa) print "energy", e de, dg = pot.getEnergyGradient(aa) print "energy from gradient", de, "diff", e-de den, dgn = pot.getEnergyGradientNumerical(aa) maxgrad= np.max( np.abs( dg ) ) maxdiff = np.max( np.abs( dg - dgn ) ) print "maximum gradient", maxgrad print "max difference in analytical vs numerical gradient", maxdiff
def test_cpp_rotate(self): x0 = np.array([random_aa() for _ in range(2*self.nrigid)]).ravel() aa = random_aa() mx = aa2mx(aa) x0_rotated = x0.copy() self.transform.rotate(x0_rotated, mx) x0_rotated_python = x0.copy() self.transform._rotate_python(x0_rotated_python, mx) assert_arrays_almost_equal(self, x0_rotated, x0_rotated_python) mx_reverse = aa2mx(-aa) self.transform.rotate(x0_rotated, mx_reverse) assert_arrays_almost_equal(self, x0, x0_rotated)
def test_cpp_rotate(self): x0 = np.array([random_aa() for _ in range(2 * self.nrigid)]).ravel() aa = random_aa() mx = aa2mx(aa) x0_rotated = x0.copy() self.transform.rotate(x0_rotated, mx) x0_rotated_python = x0.copy() self.transform._rotate_python(x0_rotated_python, mx) assert_arrays_almost_equal(self, x0_rotated, x0_rotated_python) mx_reverse = aa2mx(-aa) self.transform.rotate(x0_rotated, mx_reverse) assert_arrays_almost_equal(self, x0, x0_rotated)
def __call__(self, coords1, coords2): ''' Parameters ---------- coords1, coords2 : np.array the structures to align. X2 will be aligned with X1, both the center of masses will be shifted to the origin Returns ------- a tripple of (dist, coords1, coords2). coords1 are the unchanged coords1 and coords2 are brought in best alignment with coords2 ''' # we don't want to change the given coordinates check_inversion = False coords1 = coords1.copy() coords2 = coords2.copy() x1 = np.copy(coords1) x2 = np.copy(coords2) com1 = self.measure.get_com(x1) self.transform.translate(x1, -com1) com2 = self.measure.get_com(x2) self.transform.translate(x2, -com2) self.com_shift = com1 self.mxbest = np.identity(3) self.distbest = self.measure.get_dist(x1, x2) self.x2_best = x2.copy() if self.distbest < self.tol: dist, x2 = self.finalize_best_match(coords1) return self.distbest, coords1, x2 for rot, invert in self._standard_alignments(x1, x2): self.check_match(x1, x2, rot, invert) if self.distbest < self.tol: dist, x2 = self.finalize_best_match(coords1) return dist, coords1, x2 # if we didn't find a perfect match here, try random rotations to optimize the match for i in range(self.niter): rot = rotations.aa2mx(rotations.random_aa()) self.check_match(x1, x2, rot, False) if(self.transform.can_invert()): self.check_match(x1, x2, rot, True) # self.transform.rotate(X2, mxbest) # dist, perm = self.measure.find_permutation(X1, X2) # X2 = self.transform.permute(X2, perm) # tmp, mx = self.measure.find_rotation(X1.copy(), X2.copy()) # self.transform.rotate(X2, mx) # TODO: should we do an additional sanity check for permutation / rotation? dist, x2 = self.finalize_best_match(coords1) return dist, coords1, x2
def interpolate_spin(v1, v2, t): vx = np.cross(v2, v1) theta = np.arccos(np.dot(v1, v2)) theta *= (1.0 - t) aa = old_div(theta * vx, np.linalg.norm(vx)) mx = rotations.aa2mx(aa) v3 = np.dot(mx, v2) return old_div(v3, np.linalg.norm(v3))
def interpolate_spin(v1, v2, t): vx = np.cross(v2, v1) theta = np.arccos(np.dot(v1, v2)) theta *= (1.0 - t) aa = theta * vx / np.linalg.norm(vx) mx = rotations.aa2mx(aa) v3 = np.dot(mx, v2) return v3 / np.linalg.norm(v3)
def takeStep(self, coords, **kwargs): # easy access to coordinates ca = CoordsAdapter(nrigid=coords.size / 6, coords=coords) # random displacement for positions ca.posRigid[:] += 2. * self.displace * (np.random.random(ca.posRigid.shape) - 0.5) # determine backbone beads for com, p in zip(ca.posRigid, ca.rotRigid): p_rnd = rotations.small_random_aa(self.rotate) # adjust center of mass if self.rotate_around_backbone: a1 = np.dot(rotations.aa2mx(p), np.array([1., 0., 0.])) x1 = com - 0.4 * a1 mx = rotations.aa2mx(p_rnd) com[:] = np.dot(mx, com - x1) + x1 # random rotation for angle-axis vectors p[:] = rotations.rotate_aa(p, p_rnd)
def __init__(self, parent): QGLWidget.__init__(self, parent) self.setMinimumSize(200, 200) # glutInit()#sys.argv) self.coords = {1: None, 2: None} self.minima = {1: None, 2: None} self.last_mouse_pos = QtCore.QPointF(0., 0.) self.rotation = rot.aa2mx(np.array([0., 0., 0.])) # np.array([0., 0.]) self.zoom = 1.0 self._fatal_error = False # don't try to plot if it won't work
def align(self, coords1, coords2): c1 = self.topology.coords_adapter(coords1) c2 = self.topology.coords_adapter(coords2) # now account for symmetry in water for p1, p2, site in zip(c1.rotRigid,c2.rotRigid, self.topology.sites): theta_min = 10. mx2 = rotations.aa2mx(p2) mx1 = rotations.aa2mx(p1).transpose() mx = np.dot(mx1, mx2) for rot in site.symmetries: mx_diff = np.dot(mx, rot) theta = np.linalg.norm(rotations.mx2aa(mx_diff)) theta -= int(theta/2./pi)*2.*pi if(theta < theta_min): theta_min = theta rot_best = rot p2[:] = rotations.rotate_aa(rotations.mx2aa(rot_best), p2)
def __init__(self, parent): QGLWidget.__init__(self, parent) self.setMinimumSize(200, 200) # glutInit()#sys.argv) self.coords = {1:None, 2:None} self.minima = {1:None, 2:None} self.last_mouse_pos = QtCore.QPointF(0., 0.) self.rotation = rot.aa2mx(np.array([0.,0.,0.])) # np.array([0., 0.]) self.zoom = 1.0 self._fatal_error = False # don't try to plot if it won't work
def align_structures(self, coords1, coords2): """ Parameters ---------- coords1, coords2 : np.array the structures to align. X2 will be aligned with X1, both the center of masses will be shifted to the origin Returns ------- a triple of (dist, coords1, coords2). coords1 are the unchanged coords1 and coords2 are brought in best alignment with coords2 """ # we don't want to change the given coordinates coords1 = coords1.copy() coords2 = coords2.copy() x1 = np.copy(coords1) x2 = np.copy(coords2) com1 = self.measure.get_com(x1) self.transform.translate(x1, -com1) com2 = self.measure.get_com(x2) self.transform.translate(x2, -com2) self.com_shift = com1 self.mxbest = np.identity(3) self.distbest = self.measure.get_dist(x1, x2) self.x2_best = x2.copy() # sn402: The unlikely event that the structures are already nearly perfectly aligned. if self.distbest < self.tol: dist, x2 = self.finalize_best_match(coords1) return self.distbest, coords1, x2 for rot, invert in self._standard_alignments(x1, x2): self.check_match(x1, x2, rot, invert) if self.distbest < self.tol: dist, x2 = self.finalize_best_match(coords1) return dist, coords1, x2 # if we didn't find a perfect match here, try random rotations to optimize the match for i in range(self.niter): rot = rotations.aa2mx(rotations.random_aa()) self.check_match(x1, x2, rot, False) if self.transform.can_invert(): self.check_match(x1, x2, rot, True) # TODO: should we do an additional sanity check for permutation / rotation? dist, x2 = self.finalize_best_match(coords1) return dist, coords1, x2
def aa2xyz(XB, AA): """ Rotate XB according to angle axis AA """ nsites = len(XB)/3 XBnew = np.copy(XB) rot_mx = rot.aa2mx( AA ) for j in range(nsites): i = 3*j XBnew[i:i+3] = np.dot( rot_mx, XBnew[i:i+3] ) return XBnew
def _zeroEV_python(self, x): """return a list of zero eigenvectors This does both translational and rotational eigenvectors """ zev = [] ca = self.coords_adapter(x) cv = self.coords_adapter(np.zeros(x.shape)) # get the zero eigenvectors corresponding to translation translate_rigid = zeroev.zeroEV_translation(ca.posRigid) for v in translate_rigid: cv.posRigid[:] = v zev.append(cv.coords.copy()) # get the zero eigenvectors corresponding to rotation #rotate_r = zeroev.zeroEV_rotation(ca.posRigid) #rotate_aa = transform = TransformAngleAxisCluster(self) d = 1e-5 dx = x.copy() transform.rotate(dx, rotations.aa2mx(np.array([d, 0, 0]))) self.align_path([x, dx]) dx -= x dx /= np.linalg.norm(dx) dy = x.copy() transform.rotate(dy, rotations.aa2mx(np.array([0, d, 0]))) self.align_path([x, dy]) dy -= x dy /= np.linalg.norm(dy) dz = x.copy() transform.rotate(dz, rotations.aa2mx(np.array([0, 0, d]))) self.align_path([x, dz]) dz -= x dz /= np.linalg.norm(dz) #print "Zero eigenvectors", zev return zev + [dx, dy, dz]
def test_LJ(natoms = 12, **kwargs): from pele.potentials.lj import LJ from pele.optimize import mylbfgs import pele.utils.rotations as rot from pele.mindist.permutational_alignment import permuteArray import random quench = mylbfgs lj = LJ() X1 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) #quench X1 ret = quench( X1, lj) X1 = ret.coords X2 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) #make X2 a rotation of X1 print "testing with", natoms, "atoms, with X2 a rotated and permuted isomer of X1" aa = rot.random_aa() rot_mx = rot.aa2mx( aa ) for j in range(natoms): i = 3*j X2[i:i+3] = np.dot( rot_mx, X1[i:i+3] ) perm = range(natoms) random.shuffle( perm ) print perm X2 = permuteArray( X2, perm) #X1 = np.array( [ 0., 0., 0., 1., 0., 0., 0., 0., 1.,] ) #X2 = np.array( [ 0., 0., 0., 1., 0., 0., 0., 1., 0.,] ) import copy X1i = copy.copy(X1) X2i = copy.copy(X2) print "******************************" print "testing normal LJ ISOMER" print "******************************" test(X1, X2, lj, **kwargs) print "******************************" print "testing normal LJ non isomer" print "******************************" X2 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) ret = quench( X2, lj) X2 = ret.coords Y = X1.reshape([-1,3]) Y+=np.random.random(3) X1[:] = Y.flatten() test(X1, X2, lj, **kwargs) distinit = np.linalg.norm(X1-X2) print "distinit", distinit
def getEnergy_no_rigid_body(self, AA ): # Rotate XB0 according to angle axis AA rot_mx = rot.aa2mx( AA ) for j in range(self.nsites): i = 3*j self.XB[i:i+3] = np.dot( rot_mx, self.XB0[i:i+3] ) #return distance between XB and XA0 E = 0. for atomlist in self.permlist: E -= self.overlap( self.XA0, self.XB, self.L2, atomlist, [self.nsites, len(atomlist)]) #if E < -10.5: # print E, atomlist, [self.nsites, len(atomlist)], len(self.XA0), len(self.XB) return E
def coordsApplyRotation(coordsin, aa): coords = coordsin.copy() nmol = len(coords) / 3 / 2 rmat = rot.aa2mx(aa) # rotate center of mass coords for imol in range(nmol): k = imol * 3 coords[k : k + 3] = np.dot(rmat, coords[k : k + 3]) # update aa coords for imol in range(nmol): k = nmol * 3 + imol * 3 coords[k : k + 3] = rot.rotate_aa(coords[k : k + 3], aa) return coords
def test(v1in, v2in, aadistfunc = aadistance): v1 = np.copy(v1in) v2 = np.copy(v2in) print v1, v2 v1n = np.linalg.norm(v1) v2n = np.linalg.norm(v2) print "initial norms", v1n, v2n aadistfunc(v1, v2) v3n = np.linalg.norm(v1) v4n = np.linalg.norm(v2) print "final norms ", v3n, v4n import pele.utils.rotations as rot print "v1 unchanged:", all( (rot.aa2mx( v1) == rot.aa2mx( v1in))[:].tolist() ) print "v2 unchanged:", all( (rot.aa2mx( v2) == rot.aa2mx( v2in))[:].tolist() ) print "cartesian distance between vectors before", np.linalg.norm(v1in-v2in) print "cartesian distance between vectors after ", np.linalg.norm(v1-v2)
def test_transform_rotate(self): print("\ntest rotate") x = self.x0.copy() p = np.array(list(range(1,4)), dtype=float) p /= np.linalg.norm(p) self.transform.rotate(x, rotations.aa2mx(p)) xnewtrue = np.array([ 0.48757698, 0.61588594, 2.09355038, 2.02484605, 4.76822812, 4.81289924, 3.56211511, 8.92057031, 7.53224809, 0.71469473, 1.23875927, 1.36136748, 0.72426504, 1.24674367, 1.34426835, 0.73015833, 1.25159032, 1.33345003]) for v1, v2 in zip(x, xnewtrue): self.assertAlmostEqual(v1, v2, 5)
def test_LJ(natoms=12, **kwargs): # pragma: no cover from pele.potentials.lj import LJ from pele.optimize import mylbfgs import pele.utils.rotations as rot from pele.mindist.permutational_alignment import permuteArray import random quench = mylbfgs lj = LJ() X1 = np.random.uniform(-1, 1, [natoms * 3]) * (float(natoms))**(1. / 3) # quench X1 ret = quench(X1, lj) X1 = ret.coords X2 = np.random.uniform(-1, 1, [natoms * 3]) * (float(natoms))**(1. / 3) # make X2 a rotation of X1 print("testing with", natoms, "atoms, with X2 a rotated and permuted isomer of X1") aa = rot.random_aa() rot_mx = rot.aa2mx(aa) for j in range(natoms): i = 3 * j X2[i:i + 3] = np.dot(rot_mx, X1[i:i + 3]) perm = list(range(natoms)) random.shuffle(perm) print(perm) X2 = permuteArray(X2, perm) import copy X1i = copy.copy(X1) X2i = copy.copy(X2) print("******************************") print("testing normal LJ ISOMER") print("******************************") test(X1, X2, lj, **kwargs) print("******************************") print("testing normal LJ non isomer") print("******************************") X2 = np.random.uniform(-1, 1, [natoms * 3]) * (float(natoms))**(1. / 3) ret = quench(X2, lj) X2 = ret.coords Y = X1.reshape([-1, 3]) Y += np.random.random(3) X1[:] = Y.flatten() test(X1, X2, lj, **kwargs) distinit = np.linalg.norm(X1 - X2) print("distinit", distinit)
def _optimizePermRot(X1, X2, niter, permlist, verbose=False, use_quench=True): if use_quench: pot = MinPermDistPotential(X1, X2.copy(), permlist=permlist) distbest = getDistxyz(X1, X2) mxbest = np.identity(3) X20 = X2.copy() for i in range(niter): #get and apply a random rotation aa = random_aa() if not use_quench: mx = aa2mx(aa) mxtot = mx #print "X2.shape", X2.shape else: #optimize the rotation using a permutationally invariand distance metric ret = defaults.quenchRoutine(aa, pot.getEnergyGradient, tol=0.01) aa1 = ret[0] mx1 = aa2mx(aa1) mxtot = mx1 X2 = applyRotation(mxtot, X20) #optimize the permutations dist, X1, X2 = findBestPermutation(X1, X2, permlist) if verbose: print "dist", dist, "distbest", distbest #print "X2.shape", X2.shape #optimize the rotation dist, Q2 = getAlignRotation(X1, X2) # print "dist", dist, "Q2", Q2 mx2 = q2mx(Q2) mxtot = np.dot(mx2, mxtot) if dist < distbest: distbest = dist mxbest = mxtot return distbest, mxbest
def test_dist(self): aadistance(self.v1, self.v2) v1n = np.linalg.norm(self.v1) v2n = np.linalg.norm(self.v2) v1inn = np.linalg.norm(self.v1in) v1inn = np.linalg.norm(self.v1in) distbefore = np.linalg.norm(self.v1in - self.v2in) distafter = np.linalg.norm(self.v1 - self.v2) self.assertTrue(distbefore >= distafter, "distance between aa vectors increased") import pele.utils.rotations as rot rot1 = rot.aa2mx( self.v1 ) rot1i = rot.aa2mx( self.v1in ) self.assertTrue( all( (rot1 == rot1i)[:].tolist() ), "aa vector returned different rotation matrix" ) rot2 = rot.aa2mx( self.v2 ) rot2i = rot.aa2mx( self.v2in ) self.assertTrue( all( (rot2 == rot2i)[:].tolist() ), "aa vector returned different rotation matrix" )
def test_transform_rotate(self): print("\ntest rotate") x = self.x0.copy() p = np.array(list(range(1, 4)), dtype=float) p /= np.linalg.norm(p) self.transform.rotate(x, rotations.aa2mx(p)) xnewtrue = np.array([ 0.48757698, 0.61588594, 2.09355038, 2.02484605, 4.76822812, 4.81289924, 3.56211511, 8.92057031, 7.53224809, 0.71469473, 1.23875927, 1.36136748, 0.72426504, 1.24674367, 1.34426835, 0.73015833, 1.25159032, 1.33345003 ]) for v1, v2 in zip(x, xnewtrue): self.assertAlmostEqual(v1, v2, 5)
def getSymmetries(self, com, aa ): """ a generator which iteratively returns the absolute xyz coordinates of the molecule subject to it's symmetries com: the center of mass coords of the molecule aa: the orientation of the molecule in angle-axis """ com = np.array(com) rmat = rot.aa2mx(aa) #rotation matrix #first yield the unaltered molecule xyz = self.getxyz_rmat(rmat, com=com) yield xyz, aa #now loop through the symmetries for p in self.symmetrylist_rot: #combine the two rotations into one rmat_comb = np.dot( rmat, rot.aa2mx(p) ) xyz = self.getxyz_rmat(rmat_comb, com=com) newaa = rot.rotate_aa(p, aa) #print rmat_comb #print rot.aa2mx( newaa) yield xyz, newaa
def align(self, coords1, coords2): """align the rotations so that the atomistic coordinates will be in best alignment""" try: return self.cpp_measure.align(coords1, coords2) except AttributeError: pass c1 = self.topology.coords_adapter(coords1) c2 = self.topology.coords_adapter(coords2) # now account for inner-molecular symmetry for p1, p2, site in zip(c1.rotRigid, c2.rotRigid, self.topology.sites): theta_min = 10. mx2 = rotations.aa2mx(p2) mx1 = rotations.aa2mx(p1).transpose() mx = np.dot(mx1, mx2) for rot in site.symmetries: mx_diff = np.dot(mx, rot) theta = np.linalg.norm(rotations.mx2aa(mx_diff)) theta -= int(theta / 2. / pi) * 2. * pi if theta < theta_min: theta_min = theta rot_best = rot p2[:] = rotations.rotate_aa(rotations.mx2aa(rot_best), p2)
def align(self, coords1, coords2): """align the rotations so that the atomistic coordinates will be in best alignment""" try: return self.cpp_measure.align(coords1, coords2) except AttributeError: pass c1 = self.topology.coords_adapter(coords1) c2 = self.topology.coords_adapter(coords2) # now account for symmetry in water for p1, p2, site in zip(c1.rotRigid,c2.rotRigid, self.topology.sites): theta_min = 10. mx2 = rotations.aa2mx(p2) mx1 = rotations.aa2mx(p1).transpose() mx = np.dot(mx1, mx2) for rot in site.symmetries: mx_diff = np.dot(mx, rot) theta = np.linalg.norm(rotations.mx2aa(mx_diff)) theta -= int(theta/2./pi)*2.*pi if(theta < theta_min): theta_min = theta rot_best = rot p2[:] = rotations.rotate_aa(rotations.mx2aa(rot_best), p2)
def test_LJ(natoms = 12, **kwargs): from pele.potentials.lj import LJ import pele.defaults import pele.utils.rotations as rot from pele.mindist.permutational_alignment import permuteArray import random quench = pele.defaults.quenchRoutine lj = LJ() X1 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) #quench X1 ret = quench( X1, lj.getEnergyGradient) X1 = ret[0] X2 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) #make X2 a rotation of X1 print "testing with", natoms, "atoms, with X2 a rotated and permuted isomer of X1" aa = rot.random_aa() rot_mx = rot.aa2mx( aa ) for j in range(natoms): i = 3*j X2[i:i+3] = np.dot( rot_mx, X1[i:i+3] ) perm = range(natoms) random.shuffle( perm ) print perm X2 = permuteArray( X2, perm) #X1 = np.array( [ 0., 0., 0., 1., 0., 0., 0., 0., 1.,] ) #X2 = np.array( [ 0., 0., 0., 1., 0., 0., 0., 1., 0.,] ) import copy X1i = copy.copy(X1) X2i = copy.copy(X2) print "******************************" print "testing normal LJ ISOMER" print "******************************" test(X1, X2, lj, **kwargs) print "******************************" print "testing normal LJ non isomer" print "******************************" X2 = np.random.uniform(-1,1,[natoms*3])*(float(natoms))**(1./3) ret = quench( X2, lj.getEnergyGradient) X2 = ret[0] test(X1, X2, lj, **kwargs) distinit = np.linalg.norm(X1-X2) print "distinit", distinit
def takeStep(self, coords, **kwargs): # easy access to coordinates ca = CoordsAdapter(nrigid=coords.size / 6, coords=coords) backbone = np.zeros(3) # random rotation for angle-axis vectors for pos, rot in zip(ca.posRigid, ca.rotRigid): backbone += rotations.vec_random() * 0.7525 # choose a random rotation rot[:] = rotations.random_aa() # calcualte center of base from backgone a1 = np.dot(rotations.aa2mx(rot), np.array([1., 0., 0.])) pos[:] = backbone + 0.4 * a1
def takeStep(self, coords, **kwargs): # easy access to coordinates ca = CoordsAdapter(nrigid=old_div(coords.size, 6), coords=coords) backbone = np.zeros(3) # random rotation for angle-axis vectors for pos, rot in zip(ca.posRigid, ca.rotRigid): backbone += rotations.vec_random() * 0.7525 # choose a random rotation rot[:] = rotations.random_aa() # calcualte center of base from backgone a1 = np.dot(rotations.aa2mx(rot), np.array([1., 0., 0.])) pos[:] = backbone + 0.4 * a1
def test_rotation(self): """assert that the HSA energy is *not* invariant under rotation""" pot = self.system.get_potential() aa = rotations.random_aa() rmat = rotations.aa2mx(aa) from pele.mindist import TransformAtomicCluster tform = TransformAtomicCluster(can_invert=True) for m in self.database.minima(): x = m.coords.copy() # randomly move the atoms by a small amount x += np.random.uniform(-1e-3, 1e-3, x.shape) ehsa1 = self.sampler.compute_energy(x, m, x0=m.coords) ecalc = pot.getEnergy(x) # now rotate by a random matrix xnew = x.copy() tform.rotate(xnew, rmat) ehsa2 = self.sampler.compute_energy(xnew, m, x0=m.coords) ecalc2 = pot.getEnergy(xnew) self.assertAlmostEqual(ecalc, ecalc2, 5) self.assertNotAlmostEqual(ehsa1, ehsa2, 1)
def distance_squared_grad(self, com1, p1, com2, p2): ''' calculate spring force between 2 sites Parameters ---------- com1: center of mass of 1st site p1: angle axis vector of 1st site com2: center of mass of 2nd site p2: angle axis vector of 2nd site sitetype: AASiteType, optional amgle axis site type with mass and moment of inertia tensor returns: tuple spring cart, spring rot ''' return sitedist_grad(self.get_smallest_rij(com1, com2), p1, p2, self.S, self.W, self.cog) R1, R11, R12, R13 = rotMatDeriv(p1, True) R2 = rotations.aa2mx(p2) dR = R2 - R1 dR = dR g_M = -2.*self.W*(com2-com1) # dR_kl S_lm dR_km g_P = np.zeros(3) g_P[0] = -2.*np.trace(np.dot(R11, np.dot(self.S, dR.transpose()))) g_P[1] = -2.*np.trace(np.dot(R12, np.dot(self.S, dR.transpose()))) g_P[2] = -2.*np.trace(np.dot(R13, np.dot(self.S, dR.transpose()))) g_M -= 2.*self.W * np.dot(dR, self.cog) g_P[0] -= 2.*self.W * np.dot((com2-com1), np.dot(R11, self.cog)) g_P[1] -= 2.*self.W * np.dot((com2-com1), np.dot(R12, self.cog)) g_P[2] -= 2.*self.W * np.dot((com2-com1), np.dot(R13, self.cog)) return g_M, g_P
def takeStep(self, coords, **kwargs): # easy access to coordinates ca = CoordsAdapter(nrigid=old_div(coords.size, 6), coords=coords) for i in range(ca.nrigid): a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) a *= 2. * (np.random.random() - 0.5) * self.rotate_base ca.rotRigid[i] = rotations.rotate_aa(ca.rotRigid[i], a) # random rotation for angle-axis vectors if self.rotate_backbone != 0.: for j in range(self.ntorsionmoves): # choose bond to rotate around, index is first bead that changes index = choose_bond(ca.nrigid - 1, self.P_mid) + 1 # determine backbone beads a1 = np.dot(rotations.aa2mx(ca.rotRigid[index - 1]), np.array([1., 0., 0.])) a2 = np.dot(rotations.aa2mx(ca.rotRigid[index]), np.array([1., 0., 0.])) x1 = ca.posRigid[index - 1] - 0.4 * a1 # backbone bead x2 = ca.posRigid[index] - 0.4 * a2 # backbone bead # get bond vector as axis of rotation + random magnitude p = x2 - x1 p /= np.linalg.norm(p) p *= 2. * (np.random.random() - 0.5) * self.rotate_backbone # convert random rotation to a matrix mx = rotations.aa2mx(p) # center of rotation is in middle of backbone bond center = 0.5 * (x1 + x2) # apply rotation to positions and orientations for i in range(index, ca.nrigid): a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) ca.rotRigid[i] = rotations.rotate_aa(ca.rotRigid[i], p) x = ca.posRigid[i] - 0.4 * a ca.posRigid[i] = np.dot(mx, x - center) + center a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) ca.posRigid[i] += 0.4 * a
def takeStep(self, coords, **kwargs): # easy access to coordinates ca = CoordsAdapter(nrigid=coords.size / 6, coords=coords) for i in xrange(ca.nrigid): a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) a *= 2. * (np.random.random() - 0.5) * self.rotate_base ca.rotRigid[i] = rotations.rotate_aa(ca.rotRigid[i], a) # random rotation for angle-axis vectors if self.rotate_backbone != 0.: for j in xrange(self.ntorsionmoves): # choose bond to rotate around, index is first bead that changes index = choose_bond(ca.nrigid - 1, self.P_mid) + 1 # determine backbone beads a1 = np.dot(rotations.aa2mx(ca.rotRigid[index - 1]), np.array([1., 0., 0.])) a2 = np.dot(rotations.aa2mx(ca.rotRigid[index]), np.array([1., 0., 0.])) x1 = ca.posRigid[index - 1] - 0.4 * a1 # backbone bead x2 = ca.posRigid[index] - 0.4 * a2 # backbone bead # get bond vector as axis of rotation + random magnitude p = x2 - x1 p /= np.linalg.norm(p) p *= 2. * (np.random.random() - 0.5) * self.rotate_backbone # convert random rotation to a matrix mx = rotations.aa2mx(p) # center of rotation is in middle of backbone bond center = 0.5 * (x1 + x2) # apply rotation to positions and orientations for i in xrange(index, ca.nrigid): a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) ca.rotRigid[i] = rotations.rotate_aa(ca.rotRigid[i], p) x = ca.posRigid[i] - 0.4 * a ca.posRigid[i] = np.dot(mx, x - center) + center a = np.dot(rotations.aa2mx(ca.rotRigid[i]), np.array([1., 0., 0.])) ca.posRigid[i] += 0.4 * a
def relative_angle(aa1, aa2): m1 = rotations.aa2mx(aa1) m2 = rotations.aa2mx(aa2) m2 = m1.transpose().dot(m2) theta = np.linalg.norm(rotations.mx2aa(m2)) return theta
def to_atomistic(self, com, p): """convert the center of mass position + angle axis vector to atomistic coords """ R = rotations.aa2mx(p) return com + np.dot(R, np.transpose(self.atom_positions)).transpose()
def test(): # pragma: no cover natoms = 3 x = np.random.random([natoms, 3]) * 5 masses = [1., 1., 16.] # np.random.random(natoms) print masses x -= np.average(x, axis=0, weights=masses) cog = np.average(x, axis=0) S = np.zeros([3, 3]) for i in xrange(3): for j in xrange(3): S[i][j] = np.sum(x[:, i] * x[:, j]) site = AASiteType(M=natoms, S=S, W=natoms, cog=cog) X1 = 10.1 * np.random.random(3) X2 = 10.1 * np.random.random(3) p1 = rotations.random_aa() p2 = rotations.random_aa() R1 = rotations.aa2mx(p1) R2 = rotations.aa2mx(p2) x1 = np.dot(R1, x.transpose()).transpose() + X1 x2 = np.dot(R2, x.transpose()).transpose() + X2 import _aadist print "site representation:", np.sum((x1 - x2) ** 2) print "distance function: ", site.distance_squared(X1, p1, X2, p2) print "fortran function: ", _aadist.sitedist(X2 - X1, p1, p2, site.S, site.W, cog) import time t0 = time.time() for i in xrange(1000): site.distance_squared(X1, p1, X2, p2) t1 = time.time() print "time python", t1 - t0 for i in xrange(1000): sitedist(X2 - X1, p1, p2, site.S, site.W, cog) # _aadist.aadist(coords1, coords2, site.S, site.W, cog) t2 = time.time() print "time fortran", t2 - t1 # for i in xrange(1000/20): # #_aadist.sitedist(X1, p1, X2, p2, site.S, site.W, cog) # _aadist.aadist(coords1, coords2, site.S, site.W, cog) t2 = time.time() print "time fortran acc", t2 - t1 print site.distance_squared_grad(X1, p1, X2, p2) g_M = np.zeros(3) g_P = np.zeros(3) for i in xrange(3): eps = 1e-6 delta = np.zeros(3) delta[i] = eps g_M[i] = (site.distance_squared(X1 + delta, p1, X2, p2) - site.distance_squared(X1, p1, X2, p2)) / eps g_P[i] = (site.distance_squared(X1, p1 + delta, X2, p2) - site.distance_squared(X1, p1, X2, p2)) / eps print g_M, g_P xx = site.distance_squared_grad(X1, p1, X2, p2) print g_M / xx[0], g_P / xx[1] print _aadist.sitedist_grad(X2 - X1, p1, p2, site.S, site.W, cog)
def test(): # pragma: no cover natoms = 3 x = np.random.random([natoms, 3]) * 5 masses = [1., 1., 16.] # np.random.random(natoms) print(masses) x -= np.average(x, axis=0, weights=masses) cog = np.average(x, axis=0) S = np.zeros([3, 3]) for i in range(3): for j in range(3): S[i][j] = np.sum(x[:, i] * x[:, j]) site = AASiteType(M=natoms, S=S, W=natoms, cog=cog) X1 = 10.1 * np.random.random(3) X2 = 10.1 * np.random.random(3) p1 = rotations.random_aa() p2 = rotations.random_aa() R1 = rotations.aa2mx(p1) R2 = rotations.aa2mx(p2) x1 = np.dot(R1, x.transpose()).transpose() + X1 x2 = np.dot(R2, x.transpose()).transpose() + X2 from . import _aadist print("site representation:", np.sum((x1 - x2) ** 2)) print("distance function: ", site.distance_squared(X1, p1, X2, p2)) print("fortran function: ", _aadist.sitedist(X2 - X1, p1, p2, site.S, site.W, cog)) import time t0 = time.time() for i in range(1000): site.distance_squared(X1, p1, X2, p2) t1 = time.time() print("time python", t1 - t0) for i in range(1000): sitedist(X2 - X1, p1, p2, site.S, site.W, cog) # _aadist.aadist(coords1, coords2, site.S, site.W, cog) t2 = time.time() print("time fortran", t2 - t1) # for i in xrange(1000/20): # #_aadist.sitedist(X1, p1, X2, p2, site.S, site.W, cog) # _aadist.aadist(coords1, coords2, site.S, site.W, cog) t2 = time.time() print("time fortran acc", t2 - t1) print(site.distance_squared_grad(X1, p1, X2, p2)) g_M = np.zeros(3) g_P = np.zeros(3) for i in range(3): eps = 1e-6 delta = np.zeros(3) delta[i] = eps g_M[i] = old_div((site.distance_squared(X1 + delta, p1, X2, p2) - site.distance_squared(X1, p1, X2, p2)), eps) g_P[i] = old_div((site.distance_squared(X1, p1 + delta, X2, p2) - site.distance_squared(X1, p1, X2, p2)), eps) print(g_M, g_P) xx = site.distance_squared_grad(X1, p1, X2, p2) print(old_div(g_M, xx[0]), old_div(g_P, xx[1])) print(_aadist.sitedist_grad(X2 - X1, p1, p2, site.S, site.W, cog))
def test_aa2mx(self): aa = random_aa() mx1 = aa2mx(aa) mx2 = rotations.aa2mx(aa) self.arrays_equal(mx1, mx2)
def rrot(self, x): aa = rotations.random_aa() mx = rotations.aa2mx(aa) self.match.transform.rotate(x, mx)