def calc_spheroid_objects(self, tm, Da, theta, phi):
        """Function for calculating the spheroidal diffusion tensor objects."""

        # The parameter values.
        Diso = 1/(6*tm)
        Dpar = Diso + 2.0/3.0 * Da
        Dper = Diso - 1.0/3.0 * Da
        Dratio = Dpar / Dper

        # Vectors.
        Dpar_unit = array([sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)])

        # Matrices.
        if Dpar > Dper:
            axis = array([0, 0, 1], float64)
            tensor_diag = array([[ Dper,  0.0,  0.0],
                                 [  0.0, Dper,  0.0],
                                 [  0.0,  0.0, Dpar]])
        else:
            axis = array([1, 0, 0], float64)
            tensor_diag = array([[ Dpar,  0.0,  0.0],
                                 [  0.0, Dper,  0.0],
                                 [  0.0,  0.0, Dper]])

        # The rotation.
        rotation = zeros((3, 3), float64)
        two_vect_to_R(Dpar_unit, axis, rotation)

        # The diffusion tensor.
        tensor = dot(rotation, dot(tensor_diag, transpose(rotation)))

        # Return the objects.
        return Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor
Beispiel #2
0
    def calc_spheroid_objects(self, tm, Da, theta, phi):
        """Function for calculating the spheroidal diffusion tensor objects."""

        # The parameter values.
        Diso = 1 / (6 * tm)
        Dpar = Diso + 2.0 / 3.0 * Da
        Dper = Diso - 1.0 / 3.0 * Da
        Dratio = Dpar / Dper

        # Vectors.
        Dpar_unit = array(
            [sin(theta) * cos(phi),
             sin(theta) * sin(phi),
             cos(theta)])

        # Matrices.
        if Dpar > Dper:
            axis = array([0, 0, 1], float64)
            tensor_diag = array([[Dper, 0.0, 0.0], [0.0, Dper, 0.0],
                                 [0.0, 0.0, Dpar]])
        else:
            axis = array([1, 0, 0], float64)
            tensor_diag = array([[Dpar, 0.0, 0.0], [0.0, Dper, 0.0],
                                 [0.0, 0.0, Dper]])

        # The rotation.
        rotation = zeros((3, 3), float64)
        two_vect_to_R(Dpar_unit, axis, rotation)

        # The diffusion tensor.
        tensor = dot(rotation, dot(tensor_diag, transpose(rotation)))

        # Return the objects.
        return Diso, Dpar, Dper, Dratio, Dpar_unit, tensor_diag, rotation, tensor
Beispiel #3
0
    def calc_Rx2_eigen_axis(self, axis_theta, axis_phi):
        """Calculate the Kronecker product of the eigenframe rotation for the z-axis based frame."""

        # Generate the cone axis from the spherical angles.
        spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)

        # Pre-calculate the eigenframe rotation matrix.
        two_vect_to_R(self.z_axis, self.cone_axis, self.R_temp)

        # The Kronecker product of the eigenframe rotation.
        return kron_prod(self.R_temp, self.R_temp)
Beispiel #4
0
    def calc_Rx2_eigen_axis(self, axis_theta, axis_phi):
        """Calculate the Kronecker product of the eigenframe rotation for the z-axis based frame."""

        # Generate the cone axis from the spherical angles.
        spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)

        # Pre-calculate the eigenframe rotation matrix.
        two_vect_to_R(self.z_axis, self.cone_axis, self.R_temp)

        # The Kronecker product of the eigenframe rotation.
        return kron_prod(self.R_temp, self.R_temp)
Beispiel #5
0
    def get_spheroid(self, Dpar=None, Dper=None, theta=None, phi=None):
        """Return all the diffusion tensor info about the given spheroid tensor."""

        # The tensor info.
        Diso = (Dpar + 2*Dper) / 3.0
        tm = 1.0/(6.0 * Diso)
        Da = Dpar - Dper
        Dratio = Dpar / Dper

        # The eigenvalues and unique axis in the eigenframe.
        if Dpar > Dper:
            Dx, Dy, Dz = Dper, Dper, Dpar
            axis = array([0, 0, 1], float64)
        else:
            Dx, Dy, Dz = Dpar, Dper, Dper
            axis = array([1, 0, 0], float64)

        # The actual tensor in the PDB frame.
        R = zeros((3, 3), float64)
        spher_vect = array([1, theta, phi], float64)
        diff_axis = zeros(3, float64)
        spherical_to_cartesian(spher_vect, diff_axis)
        two_vect_to_R(diff_axis, axis, R)

        # The tensor in the eigenframe.
        D_prime = zeros((3, 3), float64)
        D_prime[0, 0] = Dx
        D_prime[1, 1] = Dy
        D_prime[2, 2] = Dz

        # Rotate a little about the unique axis!
        twist = zeros((3, 3), float64)
        axis_angle_to_R(axis, 0.3, twist)
        D = dot(twist, dot(D_prime, transpose(twist)))

        # The tensor in the PDB frame.
        D = dot(R, dot(D, transpose(R)))

        # Return the data.
        return tm, Dx, Dy, Dz, Diso, Da, Dratio, D, D_prime, R
Beispiel #6
0
    def get_spheroid(self, Dpar=None, Dper=None, theta=None, phi=None):
        """Return all the diffusion tensor info about the given spheroid tensor."""

        # The tensor info.
        Diso = (Dpar + 2*Dper) / 3.0
        tm = 1.0/(6.0 * Diso)
        Da = Dpar - Dper
        Dratio = Dpar / Dper

        # The eigenvalues and unique axis in the eigenframe.
        if Dpar > Dper:
            Dx, Dy, Dz = Dper, Dper, Dpar
            axis = array([0, 0, 1], float64)
        else:
            Dx, Dy, Dz = Dpar, Dper, Dper
            axis = array([1, 0, 0], float64)

        # The actual tensor in the PDB frame.
        R = zeros((3, 3), float64)
        spher_vect = array([1, theta, phi], float64)
        diff_axis = zeros(3, float64)
        spherical_to_cartesian(spher_vect, diff_axis)
        two_vect_to_R(diff_axis, axis, R)

        # The tensor in the eigenframe.
        D_prime = zeros((3, 3), float64)
        D_prime[0, 0] = Dx
        D_prime[1, 1] = Dy
        D_prime[2, 2] = Dz

        # Rotate a little about the unique axis!
        twist = zeros((3, 3), float64)
        axis_angle_to_R(axis, 0.3, twist)
        D = dot(twist, dot(D_prime, transpose(twist)))

        # The tensor in the PDB frame.
        D = dot(R, dot(D, transpose(R)))

        # Return the data.
        return tm, Dx, Dy, Dz, Diso, Da, Dratio, D, D_prime, R
Beispiel #7
0
def cone_edge(mol=None, cone_obj=None, res_name='CON', res_num=None, chain_id='', apex=None, axis=None, R=None, scale=None, inc=None, distribution='uniform'):
    """Add a residue to the atomic data representing a cone of the given angle.

    A series of vectors totalling the number of increments and starting at the origin are equally spaced around the cone axis.  The atoms representing neighbouring vectors will be directly bonded together.  This will generate an object representing the outer edge of a cone.


    @keyword mol:           The molecule container.
    @type mol:              MolContainer instance
    @keyword cone_obj:      The cone object.  This should provide the limit_check() method with determines the limits of the distribution accepting two arguments, the polar angle phi and the azimuthal angle theta, and return True if the point is in the limits or False if outside.  It should also provide the phi_max() method for returning the phi value for the given theta.
    @type cone_obj:         class instance
    @keyword res_name:      The residue name.
    @type res_name:         str
    @keyword res_num:       The residue number.
    @type res_num:          int
    @keyword chain_id:      The chain identifier.
    @type chain_id:         str
    @keyword apex:          The apex of the cone.
    @type apex:             numpy array, len 3
    @keyword axis:          The central axis of the cone.  If supplied, then this arg will be used to construct the rotation matrix.
    @type axis:             numpy array, len 3
    @keyword R:             A 3x3 rotation matrix.  If the axis arg supplied, then this matrix will be ignored.
    @type R:                3x3 numpy array
    @keyword scale:         The scaling factor to stretch all points by.
    @type scale:            float
    @keyword inc:           The number of increments or number of vectors used to generate the outer edge of the cone.
    @type inc:              int
    @keyword distribution:  The type of point distribution to use.  This can be 'uniform' or 'regular'.
    @type distribution:     str
    """

    # The atom numbers (and indices).
    atom_num = 1
    if len(mol.atom_num):
        atom_num = mol.atom_num[-1]+1

    # Add an atom for the cone apex.
    mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name='APX', res_name=res_name, res_num=res_num, pos=apex, segment_id=None, element='H')
    origin_atom = atom_num

    # Get the polar and azimuthal angles for the distribution.
    if distribution == 'uniform':
        phi, theta = angles_uniform(inc)
    else:
        phi, theta = angles_regular(inc)

    # Initialise the rotation matrix.
    if R is None:
        R = eye(3)

    # Get the rotation matrix.
    if axis != None:
        two_vect_to_R(array([0, 0, 1], float64), axis, R)

    # Determine the maximum phi values of the point just above the edge.
    phi_max = zeros(len(theta), float64)
    for i in range(len(theta)):
        phi_max[i] = cone_obj.phi_max(theta[i])

    # Move around the azimuth.
    atom_num = atom_num + 1
    for i in range(len(theta)):
        # The vector in the unrotated frame.
        x = cos(theta[i]) * sin(phi_max[i])
        y = sin(theta[i])* sin(phi_max[i])
        z = cos(phi_max[i])
        vector = array([x, y, z], float64)

        # Rotate the vector.
        vector = dot(R, vector)

        # The atom id.
        atom_id = 'T' + repr(i)

        # The atom position.
        pos = apex+vector*scale

        # Add the vector as a H atom of the cone residue.
        mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name=get_proton_name(atom_num), res_name=res_name, res_num=res_num, pos=pos, segment_id=None, element='H')

        # Join the longitude atom to the cone apex.
        mol.atom_connect(index1=origin_atom-1, index2=atom_num-1)

        # Increment the atom number.
        atom_num = atom_num + 1

    # Build the cone edge.
    for i in range(origin_atom, atom_num-2):
        mol.atom_connect(index1=i, index2=i+1)

    # Connect the last radial array to the first (to zip up the circle).
    mol.atom_connect(index1=atom_num-2, index2=origin_atom)
Beispiel #8
0
def cone_pdb(cone_type=None, scale=1.0, file=None, dir=None, force=False):
    """Create a PDB file containing a geometric object representing the various cone models.

    Currently the only cone types supported are 'diff in cone' and 'diff on cone'.


    @param cone_type:   The type of cone model to represent.
    @type cone_type:    str
    @param scale:       The size of the geometric object is eqaul to the average pivot-CoM
                        vector length multiplied by this scaling factor.
    @type scale:        float
    @param file:        The name of the PDB file to create.
    @type file:         str
    @param dir:         The name of the directory to place the PDB file into.
    @type dir:          str
    @param force:       Flag which if set to True will cause any pre-existing file to be
                        overwritten.
    @type force:        int
    """

    # Test if the cone models have been determined.
    if cone_type == 'diff in cone':
        if not hasattr(cdp, 'S_diff_in_cone'):
            raise RelaxError(
                "The diffusion in a cone model has not yet been determined.")
    elif cone_type == 'diff on cone':
        if not hasattr(cdp, 'S_diff_on_cone'):
            raise RelaxError(
                "The diffusion on a cone model has not yet been determined.")
    else:
        raise RelaxError("The cone type " + repr(cone_type) + " is unknown.")

    # The number of increments for the filling of the cone objects.
    inc = 20

    # The rotation matrix.
    R = zeros((3, 3), float64)
    two_vect_to_R(array([0, 0, 1], float64),
                  cdp.ave_pivot_CoM / norm(cdp.ave_pivot_CoM), R)

    # The isotropic cone object.
    if cone_type == 'diff in cone':
        angle = cdp.theta_diff_in_cone
    elif cone_type == 'diff on cone':
        angle = cdp.theta_diff_on_cone
    cone_obj = Iso_cone(angle)

    # Create the structural object.
    structure = Internal()

    # Add a structure.
    structure.add_molecule(name='cone')

    # Alias the single molecule from the single model.
    mol = structure.structural_data[0].mol[0]

    # Add the pivot point.
    mol.atom_add(pdb_record='HETATM',
                 atom_num=1,
                 atom_name='R',
                 res_name='PIV',
                 res_num=1,
                 pos=cdp.pivot_point,
                 element='C')

    # Generate the average pivot-CoM vectors.
    print("\nGenerating the average pivot-CoM vectors.")
    sim_vectors = None
    if hasattr(cdp, 'ave_pivot_CoM_sim'):
        sim_vectors = cdp.ave_pivot_CoM_sim
    res_num = generate_vector_residues(mol=mol,
                                       vector=cdp.ave_pivot_CoM,
                                       atom_name='Ave',
                                       res_name_vect='AVE',
                                       sim_vectors=sim_vectors,
                                       res_num=2,
                                       origin=cdp.pivot_point,
                                       scale=scale)

    # Generate the cone outer edge.
    print("\nGenerating the cone outer edge.")
    cap_start_atom = mol.atom_num[-1] + 1
    cone_edge(mol=mol,
              cone_obj=cone_obj,
              res_name='CON',
              res_num=3,
              apex=cdp.pivot_point,
              R=R,
              scale=norm(cdp.pivot_CoM),
              inc=inc)

    # Generate the cone cap, and stitch it to the cone edge.
    if cone_type == 'diff in cone':
        print("\nGenerating the cone cap.")
        cone_start_atom = mol.atom_num[-1] + 1
        generate_vector_dist(mol=mol,
                             res_name='CON',
                             res_num=3,
                             centre=cdp.pivot_point,
                             R=R,
                             phi_max_fn=cone_obj.phi_max,
                             scale=norm(cdp.pivot_CoM),
                             inc=inc)

    # Create the PDB file.
    print("\nGenerating the PDB file.")
    pdb_file = open_write_file(file, dir, force=force)
    structure.write_pdb(pdb_file)
    pdb_file.close()
Beispiel #9
0
def calc_rotation(diff_type, *args):
    """Function for calculating the rotation matrix.

    Spherical diffusion
    ===================

    As the orientation of the diffusion tensor within the structural frame is undefined when the molecule diffuses as a sphere, the rotation matrix is simply the identity matrix::

              | 1  0  0 |
        R  =  | 0  1  0 |.
              | 0  0  1 |


    Spheroidal diffusion
    ====================

    The rotation matrix required to shift from the diffusion tensor frame to the structural frame is generated from the unique axis of the diffusion tensor.


    Ellipsoidal diffusion
    =====================

    The rotation matrix required to shift from the diffusion tensor frame to the structural frame is equal to::

        R  =  | Dx_unit  Dy_unit  Dz_unit |,

              | Dx_unit[0]  Dy_unit[0]  Dz_unit[0] |
           =  | Dx_unit[1]  Dy_unit[1]  Dz_unit[1] |.
              | Dx_unit[2]  Dy_unit[2]  Dz_unit[2] |

    @param args:        All the function arguments.  For the spheroid, this includes the spheroid_type (str), the azimuthal angle theta in radians (float), and the polar angle phi in radians (float).  For the ellipsoid, this includes the Dx unit vector (numpy 3D, rank-1 array), the Dy unit vector (numpy 3D, rank-1 array), and the Dz unit vector (numpy 3D, rank-1 array).
    @type args:         tuple
    @return:            The rotation matrix.
    @rtype:             numpy 3x3 array
    """

    # The rotation matrix for the sphere.
    if diff_type == 'sphere':
        return identity(3, float64)

    # The rotation matrix for the spheroid.
    elif diff_type == 'spheroid':
        # Unpack the arguments.
        spheroid_type, theta, phi = args

        # Initialise the rotation matrix.
        R = zeros((3, 3), float64)

        # The unique axis in the diffusion frame.
        if spheroid_type == 'prolate':
            axis = array([0, 0, 1], float64)
        else:
            axis = array([1, 0, 0], float64)

        # The spherical coordinate vector.
        spher_vect = array([1, theta, phi], float64)

        # The diffusion tensor axis in the PDB frame.
        diff_axis = zeros(3, float64)
        spherical_to_cartesian(spher_vect, diff_axis)

        # The rotation matrix.
        two_vect_to_R(diff_axis, axis, R)

        # Return the rotation.
        return R

    # The rotation matrix for the ellipsoid.
    elif diff_type == 'ellipsoid':
        # Unpack the arguments.
        Dx_unit, Dy_unit, Dz_unit = args

        # Initialise the rotation matrix.
        rotation = identity(3, float64)

        # First column of the rotation matrix.
        rotation[:, 0] = Dx_unit

        # Second column of the rotation matrix.
        rotation[:, 1] = Dy_unit

        # Third column of the rotation matrix.
        rotation[:, 2] = Dz_unit

        # Return the tensor.
        return rotation

    # Raise an error.
    else:
        raise RelaxError('The diffusion tensor has not been specified')
Beispiel #10
0
def cone_edge(mol=None, cone=None, res_name='CON', res_num=None, chain_id='', apex=None, axis=None, R=None, scale=None, inc=None, distribution='uniform', debug=False):
    """Add a residue to the atomic data representing a cone of the given angle.

    A series of vectors totalling the number of increments and starting at the origin are equally spaced around the cone axis.  The atoms representing neighbouring vectors will be directly bonded together.  This will generate an object representing the outer edge of a cone.


    @keyword mol:           The molecule container.
    @type mol:              MolContainer instance
    @keyword cone:          The cone object.  This should provide the limit_check() method with determines the limits of the distribution accepting two arguments, the polar angle phi and the azimuthal angle theta, and return True if the point is in the limits or False if outside.  It should also provide the phi_max() method for returning the phi value for the given theta.
    @type cone:             class instance
    @keyword res_name:      The residue name.
    @type res_name:         str
    @keyword res_num:       The residue number.
    @type res_num:          int
    @keyword chain_id:      The chain identifier.
    @type chain_id:         str
    @keyword apex:          The apex of the cone.
    @type apex:             numpy array, len 3
    @keyword axis:          The central axis of the cone.  If supplied, then this arg will be used to construct the rotation matrix.
    @type axis:             numpy array, len 3
    @keyword R:             A 3x3 rotation matrix.  If the axis arg supplied, then this matrix will be ignored.
    @type R:                3x3 numpy array
    @keyword scale:         The scaling factor to stretch all points by.
    @type scale:            float
    @keyword inc:           The number of increments or number of vectors used to generate the outer edge of the cone.
    @type inc:              int
    @keyword distribution:  The type of point distribution to use.  This can be 'uniform' or 'regular'.
    @type distribution:     str
    """

    # The atom numbers (and indices).
    atom_num = mol.atom_num[-1]+1

    # Add an atom for the cone apex.
    mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name='APX', res_name=res_name, res_num=res_num, pos=apex, segment_id=None, element='H')
    origin_atom = atom_num

    # Get the polar and azimuthal angles for the distribution.
    if distribution == 'uniform':
        phi, theta = angles_uniform(inc)
    else:
        phi, theta = angles_regular(inc)

    # Initialise the rotation matrix.
    if R == None:
        R = eye(3)

    # Get the rotation matrix.
    if axis != None:
        two_vect_to_R(array([0, 0, 1], float64), axis, R)

    # Determine the maximum phi values and the indices of the point just above the edge.
    phi_max = zeros(len(theta), float64)
    edge_index = zeros(len(theta), int)
    for i in range(len(theta)):
        # Get the polar angle for the longitude edge atom.
        phi_max[i] = cone.phi_max(theta[i])

        # The index.
        for j in range(len(phi)):
            if phi[j] <= phi_max[i]:
                edge_index[i] = j
                break

    # Reverse edge index.
    edge_index_rev = len(phi) - 1 - edge_index

    # Move around the azimuth.
    atom_num = atom_num + 1
    for i in range(len(theta)):
        # The vector in the unrotated frame.
        x = cos(theta[i]) * sin(phi_max[i])
        y = sin(theta[i])* sin(phi_max[i])
        z = cos(phi_max[i])
        vector = array([x, y, z], float64)

        # Rotate the vector.
        vector = dot(R, vector)

        # The atom id.
        atom_id = 'T' + repr(i)

        # The atom position.
        pos = apex+vector*scale

        # Debugging.
        if debug:
            print("i: %s; theta: %s" % (i, theta[i]))
            print("%sAdding atom %s." % (" "*4, get_proton_name(atom_num)))

        # Add the vector as a H atom of the cone residue.
        mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name=get_proton_name(atom_num), res_name=res_name, res_num=res_num, pos=pos, segment_id=None, element='H')

        # Join the longitude atom to the cone apex.
        mol.atom_connect(index1=origin_atom-1, index2=atom_num-1)

        # Increment the atom number.
        atom_num = atom_num + 1

        # Add latitude atoms for a smoother cone edge and better stitching to the cap.
        for j in range(len(phi)):
            # The index for the direction top to bottom!
            k = len(phi) - 1 - j

            # Debugging.
            if debug:
                print("%sj: %s; phi: %-20s; k: %s; phi: %-20s; phi_max: %-20s" % (" "*4, j, phi[j], k, phi[k], phi_max[i]))

            # No edge.
            skip = True

            # Forward edge (skip when the latitude is phi max).
            fwd_index = i+1
            if i == len(theta)-1:
                fwd_index = 0
            if j >= edge_index[i] and j < edge_index[fwd_index] and not abs(phi_max[fwd_index] - phi[j]) < 1e-6:
                # Debugging.
                if debug:
                    print("%sForward edge." % (" "*8))

                # Edge found.
                skip = False

                # Find the theta value for this polar angle phi.
                phi_val = phi[j]
                if fwd_index == 0:
                    theta_max = theta[fwd_index] + 2*pi
                else:
                    theta_max = theta[fwd_index]
                theta_max = cone.theta_max(phi_val, theta_min=theta[i], theta_max=theta_max-1e-7)

            # Back edge (skip when the latitude is phi max).
            rev_index = i-1
            if i == 0:
                rev_index = len(theta)-1
            if i < len(theta)-1 and j > edge_index_rev[i] and j <= edge_index_rev[i+1] and not abs(phi_max[fwd_index] - phi[k]) < 1e-6:
                # Debugging.
                if debug:
                    print("%sBack edge." % (" "*8))

                # Edge found.
                skip = False

                # Find the theta value for this polar angle phi.
                phi_val = phi[k]
                theta_max = cone.theta_max(phi_val, theta_min=theta[i-1], theta_max=theta[i])

            # Skipping.
            if skip:
                continue

            # Debugging.
            if debug:
                print("%sAdding atom %s." % (" "*8, get_proton_name(atom_num)))

            # The coordinates.
            x = cos(theta_max) * sin(phi_val)
            y = sin(theta_max) * sin(phi_val)
            z = cos(phi_val)
            pos = array([x, y, z], float64) * scale

            # Rotate and shift.
            pos = apex + dot(R, pos)

            # Add the atom.
            mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name=get_proton_name(atom_num), res_name=res_name, chain_id=chain_id, res_num=res_num, pos=pos, segment_id=None, element='H')

            # Increment the atom number.
            atom_num = atom_num + 1

    # Debugging.
    if debug:
        print("\nBuilding the edge.")

    # Build the cone edge.
    for i in range(origin_atom, atom_num-2):
        # Debugging.
        if debug:
            print("%sCone edge, connecting %s to %s" % (" "*4, get_proton_name(i), get_proton_name(i+1)))

        # Connect.
        mol.atom_connect(index1=i, index2=i+1)

    # Connect the last radial array to the first (to zip up the circle).
    mol.atom_connect(index1=atom_num-2, index2=origin_atom)
Beispiel #11
0
def cone_edge(mol=None, cone_obj=None, res_name='CON', res_num=None, chain_id='', apex=None, axis=None, R=None, scale=None, inc=None, distribution='uniform'):
    """Add a residue to the atomic data representing a cone of the given angle.

    A series of vectors totalling the number of increments and starting at the origin are equally spaced around the cone axis.  The atoms representing neighbouring vectors will be directly bonded together.  This will generate an object representing the outer edge of a cone.


    @keyword mol:           The molecule container.
    @type mol:              MolContainer instance
    @keyword cone_obj:      The cone object.  This should provide the limit_check() method with determines the limits of the distribution accepting two arguments, the polar angle phi and the azimuthal angle theta, and return True if the point is in the limits or False if outside.  It should also provide the phi_max() method for returning the phi value for the given theta.
    @type cone_obj:         class instance
    @keyword res_name:      The residue name.
    @type res_name:         str
    @keyword res_num:       The residue number.
    @type res_num:          int
    @keyword chain_id:      The chain identifier.
    @type chain_id:         str
    @keyword apex:          The apex of the cone.
    @type apex:             numpy array, len 3
    @keyword axis:          The central axis of the cone.  If supplied, then this arg will be used to construct the rotation matrix.
    @type axis:             numpy array, len 3
    @keyword R:             A 3x3 rotation matrix.  If the axis arg supplied, then this matrix will be ignored.
    @type R:                3x3 numpy array
    @keyword scale:         The scaling factor to stretch all points by.
    @type scale:            float
    @keyword inc:           The number of increments or number of vectors used to generate the outer edge of the cone.
    @type inc:              int
    @keyword distribution:  The type of point distribution to use.  This can be 'uniform' or 'regular'.
    @type distribution:     str
    """

    # The atom numbers (and indices).
    atom_num = 1
    if len(mol.atom_num):
        atom_num = mol.atom_num[-1]+1

    # Add an atom for the cone apex.
    mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name='APX', res_name=res_name, res_num=res_num, pos=apex, segment_id=None, element='H')
    origin_atom = atom_num

    # Get the polar and azimuthal angles for the distribution.
    if distribution == 'uniform':
        phi, theta = angles_uniform(inc)
    else:
        phi, theta = angles_regular(inc)

    # Initialise the rotation matrix.
    if R is None:
        R = eye(3)

    # Get the rotation matrix.
    if axis != None:
        two_vect_to_R(array([0, 0, 1], float64), axis, R)

    # Determine the maximum phi values of the point just above the edge.
    phi_max = zeros(len(theta), float64)
    for i in range(len(theta)):
        phi_max[i] = cone_obj.phi_max(theta[i])

    # Move around the azimuth.
    atom_num = atom_num + 1
    for i in range(len(theta)):
        # The vector in the unrotated frame.
        x = cos(theta[i]) * sin(phi_max[i])
        y = sin(theta[i])* sin(phi_max[i])
        z = cos(phi_max[i])
        vector = array([x, y, z], float64)

        # Rotate the vector.
        vector = dot(R, vector)

        # The atom id.
        atom_id = 'T' + repr(i)

        # The atom position.
        pos = apex+vector*scale

        # Add the vector as a H atom of the cone residue.
        mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name=get_proton_name(atom_num), res_name=res_name, res_num=res_num, pos=pos, segment_id=None, element='H')

        # Join the longitude atom to the cone apex.
        mol.atom_connect(index1=origin_atom-1, index2=atom_num-1)

        # Increment the atom number.
        atom_num = atom_num + 1

    # Build the cone edge.
    for i in range(origin_atom, atom_num-2):
        mol.atom_connect(index1=i, index2=i+1)

    # Connect the last radial array to the first (to zip up the circle).
    mol.atom_connect(index1=atom_num-2, index2=origin_atom)
Beispiel #12
0
def cone_pdb(cone_type=None, scale=1.0, file=None, dir=None, force=False):
    """Create a PDB file containing a geometric object representing the various cone models.

    Currently the only cone types supported are 'diff in cone' and 'diff on cone'.


    @param cone_type:   The type of cone model to represent.
    @type cone_type:    str
    @param scale:       The size of the geometric object is eqaul to the average pivot-CoM
                        vector length multiplied by this scaling factor.
    @type scale:        float
    @param file:        The name of the PDB file to create.
    @type file:         str
    @param dir:         The name of the directory to place the PDB file into.
    @type dir:          str
    @param force:       Flag which if set to True will cause any pre-existing file to be
                        overwritten.
    @type force:        int
    """

    # Test if the cone models have been determined.
    if cone_type == 'diff in cone':
        if not hasattr(cdp, 'S_diff_in_cone'):
            raise RelaxError("The diffusion in a cone model has not yet been determined.")
    elif cone_type == 'diff on cone':
        if not hasattr(cdp, 'S_diff_on_cone'):
            raise RelaxError("The diffusion on a cone model has not yet been determined.")
    else:
        raise RelaxError("The cone type " + repr(cone_type) + " is unknown.")

    # The number of increments for the filling of the cone objects.
    inc = 20

    # The rotation matrix.
    R = zeros((3, 3), float64)
    two_vect_to_R(array([0, 0, 1], float64), cdp.ave_pivot_CoM/norm(cdp.ave_pivot_CoM), R)

    # The isotropic cone object.
    if cone_type == 'diff in cone':
        angle = cdp.theta_diff_in_cone
    elif cone_type == 'diff on cone':
        angle = cdp.theta_diff_on_cone
    cone_obj = Iso_cone(angle)

    # Create the structural object.
    structure = Internal()

    # Add a structure.
    structure.add_molecule(name='cone')

    # Alias the single molecule from the single model.
    mol = structure.structural_data[0].mol[0]

    # Add the pivot point.
    mol.atom_add(pdb_record='HETATM', atom_num=1, atom_name='R', res_name='PIV', res_num=1, pos=cdp.pivot_point, element='C')

    # Generate the average pivot-CoM vectors.
    print("\nGenerating the average pivot-CoM vectors.")
    sim_vectors = None
    if hasattr(cdp, 'ave_pivot_CoM_sim'):
        sim_vectors = cdp.ave_pivot_CoM_sim
    res_num = generate_vector_residues(mol=mol, vector=cdp.ave_pivot_CoM, atom_name='Ave', res_name_vect='AVE', sim_vectors=sim_vectors, res_num=2, origin=cdp.pivot_point, scale=scale)

    # Generate the cone outer edge.
    print("\nGenerating the cone outer edge.")
    cap_start_atom = mol.atom_num[-1]+1
    cone_edge(mol=mol, cone_obj=cone_obj, res_name='CON', res_num=3, apex=cdp.pivot_point, R=R, scale=norm(cdp.pivot_CoM), inc=inc)

    # Generate the cone cap, and stitch it to the cone edge.
    if cone_type == 'diff in cone':
        print("\nGenerating the cone cap.")
        cone_start_atom = mol.atom_num[-1]+1
        generate_vector_dist(mol=mol, res_name='CON', res_num=3, centre=cdp.pivot_point, R=R, phi_max_fn=cone_obj.phi_max, scale=norm(cdp.pivot_CoM), inc=inc)

    # Create the PDB file.
    print("\nGenerating the PDB file.")
    pdb_file = open_write_file(file, dir, force=force)
    structure.write_pdb(pdb_file)
    pdb_file.close()
Beispiel #13
0
def calc_rotation(diff_type, *args):
    """Function for calculating the rotation matrix.

    Spherical diffusion
    ===================

    As the orientation of the diffusion tensor within the structural frame is undefined when the molecule diffuses as a sphere, the rotation matrix is simply the identity matrix::

              | 1  0  0 |
        R  =  | 0  1  0 |.
              | 0  0  1 |


    Spheroidal diffusion
    ====================

    The rotation matrix required to shift from the diffusion tensor frame to the structural frame is generated from the unique axis of the diffusion tensor.


    Ellipsoidal diffusion
    =====================

    The rotation matrix required to shift from the diffusion tensor frame to the structural frame is equal to::

        R  =  | Dx_unit  Dy_unit  Dz_unit |,

              | Dx_unit[0]  Dy_unit[0]  Dz_unit[0] |
           =  | Dx_unit[1]  Dy_unit[1]  Dz_unit[1] |.
              | Dx_unit[2]  Dy_unit[2]  Dz_unit[2] |

    @param args:        All the function arguments.  For the spheroid, this includes the spheroid_type (str), the azimuthal angle theta in radians (float), and the polar angle phi in radians (float).  For the ellipsoid, this includes the Dx unit vector (numpy 3D, rank-1 array), the Dy unit vector (numpy 3D, rank-1 array), and the Dz unit vector (numpy 3D, rank-1 array).
    @type args:         tuple
    @return:            The rotation matrix.
    @rtype:             numpy 3x3 array
    """

    # The rotation matrix for the sphere.
    if diff_type == 'sphere':
        return identity(3, float64)

    # The rotation matrix for the spheroid.
    elif diff_type == 'spheroid':
        # Unpack the arguments.
        spheroid_type, theta, phi = args

        # Initialise the rotation matrix.
        R = zeros((3, 3), float64)

        # The unique axis in the diffusion frame.
        if spheroid_type == 'prolate':
            axis = array([0, 0, 1], float64)
        else:
            axis = array([1, 0, 0], float64)

        # The spherical coordinate vector.
        spher_vect = array([1, theta, phi], float64)

        # The diffusion tensor axis in the PDB frame.
        diff_axis = zeros(3, float64)
        spherical_to_cartesian(spher_vect, diff_axis)

        # The rotation matrix.
        two_vect_to_R(diff_axis, axis, R)

        # Return the rotation.
        return R

    # The rotation matrix for the ellipsoid.
    elif diff_type == 'ellipsoid':
        # Unpack the arguments.
        Dx_unit, Dy_unit, Dz_unit = args

        # Initialise the rotation matrix.
        rotation = identity(3, float64)

        # First column of the rotation matrix.
        rotation[:, 0] = Dx_unit

        # Second column of the rotation matrix.
        rotation[:, 1] = Dy_unit

        # Third column of the rotation matrix.
        rotation[:, 2] = Dz_unit

        # Return the tensor.
        return rotation

    # Raise an error.
    else:
        raise RelaxError('The diffusion tensor has not been specified')