Пример #1
0
def get_peptide_bond_parameters():
    '''Print peptide parameters.'''
    d = {
        'c_n_length': 1.32869,
        'n_ca_length': 1.458,
        'ca_c_length': 1.52326,
        'c_n_ca_angle': np.radians(121.7),
        'n_ca_c_angle': np.radians(111.2),
        'ca_c_n_angle': np.radians(116.2),
        'omega': np.radians(180)
    }

    p1 = np.array([0, 0, 0])
    p2 = np.array([0, 0, d['ca_c_length']])
    p3 = p2 + d['c_n_length'] * np.array(
        [np.sin(d['ca_c_n_angle']), 0, -np.cos(d['ca_c_n_angle'])])
    p4 = geometry.cartesian_coord_from_internal_coord(p1, p2, p3,
                                                      d['n_ca_length'],
                                                      d['n_ca_c_angle'],
                                                      d['omega'])

    d['theta_c'] = geometry.angle(p4 - p1, p2 - p1)
    d['theta_n'] = geometry.angle(p1 - p4, p3 - p4)

    return d
Пример #2
0
def get_ideal_parameters_from_internal_coordinates(theta1, tau1, theta2, tau2):
    '''Get ideal parameters R, delta, alpha and eta from internal coordinates.'''

    # Always requires theta2 >= theta1

    if theta2 < theta1:
        theta1, tau1, theta2, tau2 = theta2, tau2, theta1, tau1

    # Get all the points

    p0 = D_MEAN * np.array([np.sin(theta1), np.cos(theta1), 0])
    p1 = np.array([0, 0, 0])
    p2 = np.array([0, D_MEAN, 0])
    p3 = geometry.cartesian_coord_from_internal_coord(p0, p1, p2, D_MEAN,
                                                      theta2, tau1)
    p4 = geometry.cartesian_coord_from_internal_coord(p1, p2, p3, D_MEAN,
                                                      theta1, tau2)

    # Get the rotation and translation of the middle point between p0 and p2

    M = np.transpose(geometry.create_frame_from_three_points(p2, p3, p4))
    t = (p4 - p0) / 2

    # Get parameters

    v, delta = geometry.rotation_matrix_to_axis_and_angle(M)
    if delta < 0:
        delta = -delta
        v = -v

    R = np.linalg.norm(t - np.dot(t, v) * v) / (2 * np.sin(delta / 2))
    alpha = np.pi / 2 - geometry.angle(v, p2 - p0)
    if alpha < 0:
        alpha += np.pi

    p1_0 = np.cross(p2 - p0, v)
    if np.dot(p1_0, p1 - (p2 + p0) / 2) < 0:
        p1_0 = -p1_0

    eta = geometry.angle(p1 - (p2 + p0) / 2, p1_0)
    if np.dot(np.cross(p1_0, p1 - (p2 + p0) / 2), p2 - p0) < 0:
        eta = -eta

    return R, delta, alpha, eta
Пример #3
0
def extend_a_strand(strand, forward=True):
    '''Extend a strand by one atom. Angle and torsion of the 
    strand will be used to extend the new atom.
    '''
    if forward:
        last_p = geometry.cartesian_coord_from_internal_coord(
            strand[-3], strand[-2], strand[-1], D_MEAN,
            geometry.angle(strand[-4] - strand[-3], strand[-2] - strand[-3]),
            geometry.dihedral(strand[-5], strand[-4], strand[-3], strand[-2]))

        return strand + [last_p]

    else:
        first_p = geometry.cartesian_coord_from_internal_coord(
            strand[2], strand[1], strand[0], D_MEAN,
            geometry.angle(strand[3] - strand[2], strand[1] - strand[2]),
            geometry.dihedral(strand[4], strand[3], strand[2], strand[1]))

        return [first_p] + strand
Пример #4
0
def twist_minimum_unit(thetas, taus, M_init, axis, pitch_angle, omega):
    '''Twist a minimum twist unit.
    Return new values for thetas and taus. Return None if the twist failed.
    '''

    if len(thetas) != 3 or len(taus) != 3:
        raise Exception(
            "A minimum twist unit must have 3 angles and 3 torsions!")

    screw_axes = []

    # Get the new value of the first axis

    axis1_local = geometry.rotation_matrix_to_axis_and_angle(
        theta_tau_to_rotation_matrix(thetas[0], taus[0]))[0]

    axis1_global = np.dot(M_init, axis1_local)

    angle_to_rotate = pitch_angle - geometry.angle(axis, axis1_global)
    rotate_axis = geometry.normalize(np.cross(axis, axis1_global))

    for i in range(1, 5):
        M_rot = geometry.rotation_matrix_from_axis_and_angle(
            rotate_axis, angle_to_rotate)

        new_axis_global = np.dot(M_rot, axis1_global)
        new_axis_local = np.dot(np.transpose(M_init), new_axis_global)

        theta, tau = axis_to_theta_tau(new_axis_local)

        if check_theta_tau(theta, tau):
            screw_axes.append(new_axis_global)
            break

        angle_to_rotate /= 2

    if len(screw_axes) == 0: return None, None

    # Get the new screw axes

    M_rot = geometry.rotation_matrix_from_axis_and_angle(axis, omega)

    for i in range(1, 3):
        screw_axes.append(np.dot(M_rot, screw_axes[i - 1]))

    # Get the internal coordinates

    try:
        thetas, taus, M = get_theta_tau_and_rotation_matrix_from_screw_axes(
            screw_axes, M_init=M_init)
    except:
        return None, None

    return thetas[1:], taus
Пример #5
0
def get_internal_coordinates_for_ideal_strand(R, delta, alpha, eta):
    '''Get 4 internal coordinates for an ideal beta strand.
    The inputs are the screw redius R, the angle alpha which is
    between a tangent of the screw spiral and the horizontal plane
    and the screw angle omega between Ca_i and Ca_i+2, delta which
    is the screw angle from Ca_i to Ca_i+2 and eta which is the value
    of tilting.

    Note that alpha is in the range (0, pi/2) for right handed strands
    and (pi/2, pi) for left handed strands.

    The outputs are theta1, tau1, theta2, tau2.
    '''

    # Adjust the sign of delta for left handed strand

    if alpha > np.pi / 2:
        delta = -delta

    theta1 = 2 * np.arcsin(R * np.absolute(np.tan(delta / 2)) /
                           (D_MEAN * np.absolute(np.cos(alpha))))
    h = 2 * D_MEAN * np.sin(theta1 / 2) * np.sin(alpha)

    p2 = np.array([0, D_MEAN * np.sin(theta1 / 2) * np.cos(alpha), h / 2])

    # Get p1

    p1_0 = np.array([D_MEAN * np.cos(theta1 / 2), 0, 0])
    M1 = geometry.rotation_matrix_from_axis_and_angle(p2, eta)
    p1 = np.dot(M1, p1_0)

    # Get p3 and p4

    M_screw, t_screw = geometry.get_screw_transformation(
        np.array([0, 0, 1]), delta, 2 * np.pi / np.absolute(delta) * h,
        np.array([-R, 0, 0]))

    p3 = np.dot(M_screw, p1) + t_screw
    p4 = np.dot(M_screw, p2) + t_screw

    theta2 = geometry.angle(p1 - p2, p3 - p2)
    tau1 = geometry.dihedral(-p2, p1, p2, p3)
    tau2 = geometry.dihedral(p1, p2, p3, p4)

    return theta1, tau1, theta2, tau2
Пример #6
0
def get_internal_coordinates_from_ca_list(ca_list):
    '''Get the list of ds, thetas and taus from a ca list.'''
    ds = []
    thetas = []
    taus = []

    for i in range(len(ca_list) - 1):
        ds.append(np.linalg.norm(ca_list[i + 1] - ca_list[i]))

    for i in range(1, len(ca_list) - 1):
        thetas.append(
            geometry.angle(ca_list[i - 1] - ca_list[i],
                           ca_list[i + 1] - ca_list[i]))

    for i in range(1, len(ca_list) - 2):
        taus.append(
            geometry.dihedral(ca_list[i - 1], ca_list[i], ca_list[i + 1],
                              ca_list[i + 2]))

    return ds, thetas, taus
Пример #7
0
def get_c_for_pp_bond_forward(ca1, ca2, v_n, z_sign=1):
    '''Get the coordinate of the C atom in a peptide bond.
    Inputs are the two ends of the peptide bond, the direction
    from ca1 to the position of the previous N and the sign
    of Z direction that is used to pick one solution from two.
    '''
    params = get_peptide_bond_parameters()

    frame = geometry.create_frame_from_three_points(ca1 + v_n, ca1, ca2)
    beta = geometry.angle(v_n, ca2 - ca1)

    gamma = z_sign * np.arccos((np.cos(params['n_ca_c_angle']) - np.cos(params['theta_c']) * np.cos(beta)) \
            / (np.sin(params['theta_c']) * np.sin(beta)))

    c_local = params['ca_c_length'] * np.array([
        np.sin(params['theta_c']) * np.cos(gamma),
        np.cos(params['theta_c']),
        np.sin(params['theta_c']) * np.sin(gamma)
    ])

    return ca1 + np.dot(np.transpose(frame), c_local)
Пример #8
0
def get_screw_transformation_for_strand(strand, distance, direction):
    '''Get the screw transformation for a strand. The first five atoms
    of the strand are used to calculate relative parameters.
    '''
    # Get internal coordinates

    theta1 = geometry.angle(strand[0] - strand[1], strand[2] - strand[1])
    theta2 = geometry.angle(strand[1] - strand[2], strand[3] - strand[2])
    tau1 = geometry.dihedral(strand[0], strand[1], strand[2], strand[3])
    tau2 = geometry.dihedral(strand[1], strand[2], strand[3], strand[4])

    # Get the direction vector

    d_v = geometry.normalize(
        np.cross(strand[1] - strand[2], strand[3] - strand[2]))
    if direction == '-':
        d_v = -d_v

    # Get the ideal parameters

    R, delta, alpha, eta = get_ideal_parameters_from_internal_coordinates(
        theta1, tau1, theta2, tau2)

    # If theta1 == theta2 or the alpha is zero, do a pure translation

    if np.absolute(theta1 - theta2) < 0.001 \
      or np.absolute(alpha) < 0.001 or np.absolute(alpha - np.pi) < 0.001:
        M = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        t = distance * d_v
        return M, t

    # Get the anchor

    anchor = strand[:3] if theta1 <= theta2 else strand[1:4]

    # Get the outer cylinder radius

    R_out = R + D_MEAN * np.cos(min(theta1, theta2) / 2)

    # Get the screw axis

    rot_p2_p0 = geometry.rotation_matrix_from_axis_and_angle(
        anchor[2] - anchor[0], -eta)
    x = geometry.normalize(
        np.dot(rot_p2_p0, anchor[1] - (anchor[2] + anchor[0]) / 2))
    rot_x = geometry.rotation_matrix_from_axis_and_angle(x, np.pi / 2 - alpha)

    z = geometry.normalize(np.dot(rot_x, anchor[2] - anchor[0]))
    if np.dot(d_v, z) < 0:
        z = -z

    u = (anchor[0] + anchor[2]) / 2 - R * x

    # Get the pitch

    pitch = np.absolute(geometry.pitch_angle_to_pitch(alpha, R_out))

    # Get the screw angle

    screw_angle = -distance * np.sin(alpha) / R_out if alpha < np.pi / 2 \
            else distance * np.sin(alpha) / R_out

    # Get the screw rotation and translation

    return geometry.get_screw_transformation(z, screw_angle, pitch, u)