def test_dihedral_reverves_vectors(self, vectors): a, b, c, d = vectors angle_1 = geometry.dihedral(a, b, c, d) angle_2 = geometry.dihedral(d, c, b, a) at = numpy.isclose(angle_1, angle_2) or numpy.isclose( angle_1, -angle_2) self.assertTrue(at)
def build(self): """Builds the `HelicalHelix`.""" helical_helix = Polypeptide() primitive_coords = self.curve_primitive.coordinates helices = [ Helix.from_start_and_end(start=primitive_coords[i], end=primitive_coords[i + 1], helix_type=self.minor_helix_type, aa=1) for i in range(len(primitive_coords) - 1) ] residues_per_turn = self.minor_residues_per_turn( minor_repeat=self.minor_repeat) if residues_per_turn == 0: residues_per_turn = _helix_parameters[self.minor_helix_type][0] if self.minor_handedness == 'l': residues_per_turn *= -1 # initial phi_c_alpha value calculated using the first Helix in helices. if self.orientation != -1: initial_angle = dihedral(numpy.array([0, 0, 0]), primitive_coords[0], primitive_coords[1], helices[0][0]['CA']) else: initial_angle = dihedral( numpy.array([0, 0, primitive_coords[0][2]]), primitive_coords[0], numpy.array([ primitive_coords[0][0], primitive_coords[0][1], primitive_coords[1][2] ]), helices[0][0]['CA']) # angle required to achieve desired phi_c_alpha value of self.phi_c_alpha. addition_angle = self.phi_c_alpha - initial_angle for i, h in enumerate(helices): angle = (i * (360.0 / residues_per_turn)) + addition_angle h.rotate(angle=angle, axis=h.axis.unit_tangent, point=h.helix_start) helical_helix.extend(h) helical_helix.relabel_all() self._monomers = helical_helix._monomers[:] for monomer in self._monomers: monomer.parent = self return
def generate_complementary_strand(strand1): """Takes a SingleStrandHelix and creates the antisense strand.""" rise_adjust = ( strand1.rise_per_nucleotide * strand1.axis.unit_tangent) * 2 strand2 = NucleicAcidStrand.from_start_and_end( strand1.helix_end - rise_adjust, strand1.helix_start - rise_adjust, generate_antisense_sequence(strand1.base_sequence), phos_3_prime=strand1.phos_3_prime) ad_ang = dihedral(strand1[0]["C1'"]._vector, strand1.axis.start, strand2.axis.start + rise_adjust, strand2[-1]["C1'"]._vector) strand2.rotate( 225.0 + ad_ang, strand2.axis.unit_tangent, point=strand2.helix_start) # 225 is the base adjust return strand2
def align_nab(tar, ref): """Aligns the N-CA and CA-CB vector of the target monomer. Parameters ---------- tar: ampal.Residue The residue that will be aligned to the reference. ref: ampal.Residue The reference residue for the alignment. """ rot_trans_1 = find_transformations(tar['N'].array, tar['CA'].array, ref['N'].array, ref['CA'].array) apply_trans_rot(tar, *rot_trans_1) rot_ang_ca_cb = dihedral(tar['CB'], ref['CA'], ref['N'], ref['CB']) tar.rotate(rot_ang_ca_cb, ref['N'].array - ref['CA'].array, ref['N'].array) return
def test_dihedral_range(self): """Test dihedral angle for randomly generated sets of four points.""" results = [] for _ in range(1000): # Generate four random points in an array. points = numpy.random.rand(4, 3) # Multiply them randomly by some integer in the range [-100, 100]. choices = numpy.random.choice(range(-100, 101), size=12).reshape(4, 3) points = numpy.multiply(points, choices) # Calculate dihedral angle using the random points and # check it lies in correct range angle = geometry.dihedral(*points) if (angle <= 180.0) and (angle >= -180.0): results.append(1) else: results.append(0) at = numpy.all(results) self.assertTrue(at) return
def get_orient_angle(self, reference_point=numpy.array([0, 0, 0]), monomer_index=0, res_label='CA', radians=False): """ Angle between reference_point and self[monomer_index][res_label]. Notes ----- Angle is calculated using the dihedral angle, with the second and third points coming from the curve_primitive. Parameters ---------- reference_point : list, tuple or numpy.array of length 3. monomer_index : int Index of the Residue to centre. res_label : str Atom name for centred atom, e.g. "CA" or "OE1". radians : bool If True, then desired_angle is in radians instead of degrees. """ if (monomer_index < len(self)) and monomer_index != -1: adjacent_index = monomer_index + 1 elif (monomer_index == len(self)) or monomer_index == -1: adjacent_index = monomer_index - 1 else: raise ValueError("centred_index ({0}) cannot be greater than the " "length of the polymer ({1})".format( monomer_index, len(self))) angle = dihedral(reference_point, self.curve_primitive[monomer_index]['CA'], self.curve_primitive[adjacent_index]['CA'], self[monomer_index][res_label]) if radians: angle = numpy.deg2rad(angle) return angle
def test_dihedral_same_point(self): test_points = [(12.1, 23.5, 3.3)] * 4 self.assertEqual(geometry.dihedral(*test_points), 0.0)
def test_dihedral_floats(self): test_points = [(12.1, 23.5, 3.3), (11.1, 24.5, 2.3), (8.1, 3.5, 0.2), (19.2, -5.5, -6.3)] self.assertAlmostEqual(geometry.dihedral(*test_points), -68.74, places=2)
def test_dihedral_180(self): test_points_180 = [(0, 0, 1), (0, 0, 0), (0, 1, 0), (0, 1, -1)] self.assertEqual(abs(geometry.dihedral(*test_points_180)), 180.0)
def test_dihedral_0(self): test_points_0 = [(0, 0, 1), (0, 0, 0), (0, 1, 0), (0, 1, 1)] self.assertEqual(geometry.dihedral(*test_points_0), 0.0)
def test_dihedral_90(self): test_points_90 = [(0, 0, 1), (0, 0, 0), (0, 1, 0), (1, 1, 0)] self.assertEqual(geometry.dihedral(*test_points_90), 90.0) test_points_90 = [(0, 0, -1), (0, 0, 0), (0, -1, 0), (-1, -1, 0)] self.assertEqual(geometry.dihedral(*test_points_90), -90.0)
def build(self): """Build single DNA strand along z-axis, starting with P on x-axis""" ang_per_res = (2 * numpy.pi) / self.nucleotides_per_turn atom_offset_coords = _backbone_properties[self.helix_type]['atoms'] if self.handedness == 'l': handedness = -1 else: handedness = 1 base_atom_labels = _backbone_properties[self.helix_type]['labels'] monomers = [] mol_code_format = _backbone_properties[ self.helix_type]['mol_code_format'] for i, b in enumerate(self.base_sequence): nucleotide = Nucleotide(mol_code=mol_code_format.format(b), parent=self) atoms_dict = OrderedDict() if (i == (len(self.base_sequence) - 1)) and not self.phos_3_prime: # Do not include phosphate on last nucleotide atom_labels = base_atom_labels[3:] + [_bases[b]['labels'][2]] atom_offsets = { k: v for k, v in zip(atom_labels, atom_offset_coords[3:]) } else: atom_labels = base_atom_labels + [_bases[b]['labels'][2]] atom_offsets = { k: v for k, v in zip(atom_labels, atom_offset_coords) } for atom_label in atom_labels: r, zeta, z_shift = atom_offsets[atom_label] rot_ang = ((i * ang_per_res) + zeta) * handedness z = (self.rise_per_nucleotide * i) + z_shift coords = cylindrical_to_cartesian(radius=r, azimuth=rot_ang, z=z, radians=True) atom = Atom(coordinates=coords, element=atom_label[0], parent=nucleotide, res_label=atom_label) atoms_dict[atom_label] = atom base_ref = _bases[b]['ref_atom'] rot_adj = _bases[b]['rot_adj'] base_dict = OrderedDict( zip(_bases[b]['labels'], _bases[b]['atoms'])) translation, angle, axis, point = find_transformations( base_dict[base_ref], base_dict["C1'"], atoms_dict[base_ref]._vector, atoms_dict["C1'"]._vector) q1 = Quaternion.angle_and_axis(angle, axis) # Align N9 C1' for k, v in base_dict.items(): base_dict[k] = q1.rotate_vector(v, point) + translation # Rotate to align O4' axis = numpy.array(base_dict["C1'"]) - base_dict[base_ref] angle = dihedral(base_dict["O4'"], base_dict[base_ref], base_dict["C1'"], atoms_dict["O4'"]) - rot_adj q2 = Quaternion.angle_and_axis(angle, axis) for k, v in list(base_dict.items()): if k not in atoms_dict: atom = Atom(q2.rotate_vector(v, base_dict[base_ref]), element=k[0], parent=nucleotide, res_label=k) atoms_dict[k] = atom nucleotide.atoms = atoms_dict monomers.append(nucleotide) self._monomers = monomers self.relabel_monomers() self.relabel_atoms() return