def set_dihedral(a1, a2, a3, a4, theta, adjustmol=True): """ Set the twist angle of atoms a1 and a4 around the central bond a2-a3. The atoms will be adjusted along the gradient of the angle. If ``adjustmol`` is True and the topology is unambiguous, then the entire molecule's positions will be modified as well Args: a1,a2,a3,a4 (mdt.Atom): atoms to adjust theta (u.Scalar[angle]): new angle to set adjustmol (bool): Adjust all atoms on either side of this bond? """ # TODO: deal with co-linear a1/a4, a2, a3 - the angle is ill-defined \ # (should just an arbitrary axis normal to the central bond) current = dihedral(a1, a2, a3, a4) rotation = sub_angles(theta, current) if abs(rotation) < 1.0e-6: return axis = a2.position - a3.position if not adjustmol: rotmat_l = external.transformations.rotation_matrix( -rotation / 2.0, axis, a3.position) rotmat_r = external.transformations.rotation_matrix( rotation / 2.0, axis, a3.position) a1.position = apply_4x4_transform(rotmat_l, a1.position) a4.position = apply_4x4_transform(rotmat_r, a4.position) else: mol = a2.molecule indices, sign = _get_fragment_indices(mol, a3, a2) rotmat = external.transformations.rotation_matrix( rotation, axis * sign, a3.position) mol.positions[indices] = apply_4x4_transform(rotmat, mol.positions[indices])
def set_angle(a1, a2, a3, theta, adjustmol=True): """ Set the angle between bonds a1-a2 and a3-a2. The atoms will be adjusted along the gradient of the angle. If ``adjustmol`` is True and the topology is unambiguous, then the entire molecule's positions will be modified as well Args: a1,a2,a3 (mdt.Atom): atoms to adjust theta (u.Scalar[angle]): new angle to set adjustmol (bool): Adjust all atoms on either side of this bond? """ # TODO: deal with co-linear a1, a2, a3 - the rotation axis is ill-defined in this case \ # (require an axis to be specified) # TODO: weakly cache the rotation axis so that users can set angle to 0 or 180 without losing the axis current = angle(a1, a2, a3) rotation = sub_angles(current, theta) if abs(rotation) < 1.0e-6: return axis = np.cross(a1.position - a2.position, a3.position - a2.position) # do vecs need to be normalized? if not adjustmol: rotmat_l = external.transformations.rotation_matrix(rotation / 2.0, axis, a2.position) rotmat_r = external.transformations.rotation_matrix(-rotation / 2.0, axis, a2.position) a1.position = apply_4x4_transform(rotmat_l, a1.position) a3.position = apply_4x4_transform(rotmat_r, a3.position) else: mol = a2.molecule indices, sign = _get_fragment_indices(mol, a1, a2) rotmat = external.transformations.rotation_matrix(rotation, axis*sign, a2.position) mol.positions[indices] = apply_4x4_transform(rotmat, mol.positions[indices])
def set_dihedral(a1, a2=None, a3=None, a4=None, theta=None, adjustmol=True): """ Set the twist angle of atoms a1 and a4 around the central bond a2-a3. The atoms will be adjusted along the gradient of the angle. Can be called as ``set_dihedral(a1, a2, a3, a4, theta, adjustmol=True)`` OR ``set_dihedral(a2, a2, theta, adjustmol=True)`` OR ``set_dihedral(bond, theta, adjustmol=True)`` If ``adjustmol`` is True and the topology is unambiguous, then the entire molecule's positions will be modified as well Args: a1 (mdt.Bond): central bond in dihedral a1,a2 (mdt.Atom): atoms around central bond in dihedral a3, a4 (mdt.Atom): theta (u.Scalar[angle]): new angle to set adjustmol (bool): Adjust all atoms on either side of this bond? """ # TODO: deal with co-linear a1/a4, a2, a3 - the angle is ill-defined \ # (should just an arbitrary axis normal to the central bond) if a4 is None: if isinstance(a1, mdt.Bond): if theta is None: theta = a2 a1, a2 = a1.a1, a1.a2 if a3 is not None and theta is None: theta, a3 = a3, theta elif a3 is not None or a4 is not None or theta is None: raise ValueError('Invalid number of arguments for set_dihedral') a1, a2, a3, a4 = _infer_dihedral(a1, a2) current = dihedral(a1, a2, a3, a4) rotation = sub_angles(theta, current) if abs(rotation) < 1.0e-6: return axis = a2.position - a3.position if not adjustmol: rotmat_l = external.transformations.rotation_matrix( -rotation / 2.0, axis, a3.position) rotmat_r = external.transformations.rotation_matrix( rotation / 2.0, axis, a3.position) a1.position = apply_4x4_transform(rotmat_l, a1.position) a4.position = apply_4x4_transform(rotmat_r, a4.position) else: mol = a2.molecule indices, sign = _get_fragment_indices(mol, a3, a2) rotmat = external.transformations.rotation_matrix( rotation, axis * sign, a3.position) mol.positions[indices] = apply_4x4_transform(rotmat, mol.positions[indices])
def set_dihedral(a1, a2=None, a3=None, a4=None, theta=None, adjustmol=True): """ Set the twist angle of atoms a1 and a4 around the central bond a2-a3. The atoms will be adjusted along the gradient of the angle. Can be called as ``set_dihedral(a1, a2, a3, a4, theta, adjustmol=True)`` OR ``set_dihedral(a2, a2, theta, adjustmol=True)`` OR ``set_dihedral(bond, theta, adjustmol=True)`` If ``adjustmol`` is True and the topology is unambiguous, then the entire molecule's positions will be modified as well Args: a1 (mdt.Bond): central bond in dihedral a1,a2 (mdt.Atom): atoms around central bond in dihedral a3, a4 (mdt.Atom): theta (u.Scalar[angle]): new angle to set adjustmol (bool): Adjust all atoms on either side of this bond? """ # TODO: deal with co-linear a1/a4, a2, a3 - the angle is ill-defined \ # (should just an arbitrary axis normal to the central bond) if a4 is None: if isinstance(a1, mdt.Bond): if theta is None: theta = a2 a1, a2 = a1.a1, a1.a2 if a3 is not None and theta is None: theta, a3 = a3, theta elif a3 is not None or a4 is not None or theta is None: raise ValueError('Invalid number of arguments for set_dihedral') a1, a2, a3, a4 = _infer_dihedral(a1, a2) current = dihedral(a1, a2, a3, a4) rotation = sub_angles(theta, current) if abs(rotation) < 1.0e-6: return axis = a2.position - a3.position if not adjustmol: rotmat_l = external.transformations.rotation_matrix((-rotation / 2.0), axis, a3.position) rotmat_r = external.transformations.rotation_matrix((rotation / 2.0), axis, a3.position) a1.position = apply_4x4_transform(rotmat_l, a1.position) a4.position = apply_4x4_transform(rotmat_r, a4.position) else: mol = a2.molecule indices, sign = _get_fragment_indices(mol, a3, a2) rotmat = external.transformations.rotation_matrix(rotation, axis*sign, a3.position) mol.positions[indices] = apply_4x4_transform(rotmat, mol.positions[indices])
def transform(self, matrix): """ Transform this object's coordinates using the provided 4x4 matrix Args: matrix (numpy.ndarray): transformation matrix, shape=(4,4) """ # TODO: deal with units ... hard because the matrix has diff units for diff columns assert matrix.shape == (4, 4) self.positions = mathutils.apply_4x4_transform(matrix, self.positions)
def set_angle(a1, a2, a3, theta, adjustmol=True): """ Set the angle between bonds a1-a2 and a3-a2. The atoms will be adjusted along the gradient of the angle. If ``adjustmol`` is True and the topology is unambiguous, then the entire molecule's positions will be modified as well Args: a1,a2,a3 (mdt.Atom): atoms to adjust theta (u.Scalar[angle]): new angle to set adjustmol (bool): Adjust all atoms on either side of this bond? """ # TODO: deal with co-linear a1, a2, a3 - the rotation axis is ill-defined in this case \ # (require an axis to be specified) # TODO: weakly cache the rotation axis so that users can set angle to 0 or 180 without losing the axis current = angle(a1, a2, a3) rotation = sub_angles(current, theta) if abs(rotation) < 1.0e-6: return axis = np.cross(a1.position - a2.position, a3.position - a2.position) # do vecs need to be normalized? if not adjustmol: rotmat_l = external.transformations.rotation_matrix( rotation / 2.0, axis, a2.position) rotmat_r = external.transformations.rotation_matrix( -rotation / 2.0, axis, a2.position) a1.position = apply_4x4_transform(rotmat_l, a1.position) a3.position = apply_4x4_transform(rotmat_r, a3.position) else: mol = a2.molecule indices, sign = _get_fragment_indices(mol, a1, a2) rotmat = external.transformations.rotation_matrix( rotation, axis * sign, a2.position) mol.positions[indices] = apply_4x4_transform(rotmat, mol.positions[indices])