Exemple #1
0
def rotation_matrix(a, b, weights=None):
    """Returns the 3x3 rotation matrix for RMSD fitting coordinate sets *a* and *b*.

    The rotation matrix *R* transforms *a* to overlap with *b* (i.e. *b* is the
    reference structure):

       *b* = *R* . *a*

    :Arguments:
       *a*
          coordinates that are to be rotated ("mobile set"); array of N atoms
          of shape N*3 as generated by, e.g.,
          :meth:`MDAnalysis.core.AtomGroup.AtomGroup.coordinates`.
       *b*
          reference coordinates; array of N atoms of shape N*3 as generated by,
          e.g., :meth:`MDAnalysis.core.AtomGroup.AtomGroup.coordinates`.
       *weights*
          array of floats of size N for doing weighted RMSD fitting (e.g. the
          masses of the atoms)

    :Returns: ``(R, rmsd)`` rmsd and rotation matrix *R*


    *R* can be used as an argument for
    :meth:`MDAnalysis.core.AtomGroup.AtomGroup.rotate` to generate a rotated
    selection, e.g. ::

      >>> R = rotation_matrix(A.selectAtoms('backbone').coordinates(), B.selectAtoms('backbone').coordinates())
      >>> A.atoms.rotate(R)
      >>> A.atoms.write("rotated.pdb")

    Note that the function does *not* shift the centers of mass or geometry;
    this needs to be done by the user.

    .. SeeAlso:: :func:`rmsd` calculates the RMSD between *a* and *b*; for
                 fitting a whole trajectory it is more efficient to use
                 :func:`rms_fit_trj`. A complete fit of two structures can be
                 done with :func:`alignto`.
    """
    if not weights is None:
        # weights are constructed as relative to the mean
        weights = numpy.asarray(weights) / numpy.mean(weights)
    rot = numpy.zeros(9, dtype=numpy.float64)
    rmsd = qcp.CalcRMSDRotationalMatrix(a.T.astype(numpy.float64),
                                        b.T.astype(numpy.float64), b.shape[0],
                                        rot, weights)
    return numpy.matrix(rot.reshape(3, 3)), rmsd
Exemple #2
0
def rmsd(a, b, weights=None, center=False):
    """Returns RMSD between two coordinate sets *a* and *b*.

    *a* and *b* are arrays of the coordinates of N atoms of shape N*3
    as generated by, e.g.,
    :meth:`MDAnalysis.core.AtomGroup.AtomGroup.coordinates`.

    An implicit optimal superposition is performed, which minimizes
    the RMSD between *a* and *b* although both *a* and *b* must be
    centered on the origin before performing the RMSD calculation so
    that translations are removed.

    One can use the *center* = ``True`` keyword, which subtracts the
    center of geometry (for *weights* = ``None``) before the
    superposition. With *weights*, a weighted average is computed as
    the center.

    The *weights* can be an array of length N, containing e.g. masses
    for a weighted RMSD calculation.

    The function uses Douglas Theobald's fast QCP algorithm
    [Theobald2005]_ to calculate the RMSD.

    Example::
     >>> u = Universe(PSF,DCD)
     >>> bb = u.selectAtoms('backbone')
     >>> A = bb.coordinates()  # coordinates of first frame
     >>> u.trajectory[-1]      # forward to last frame
     >>> B = bb.coordinates()  # coordinates of last frame
     >>> rmsd(A,B)
     6.8342494129169804

     .. versionchanged: 0.8.1
        *center* keyword added
    """
    if weights is not None:
        # weights are constructed as relative to the mean
        relative_weights = numpy.asarray(weights) / numpy.mean(weights)
    else:
        relative_weights = None
    if center:
        # make copies (do not change the user data!)
        # weights=None is equivalent to all weights 1
        a = a - numpy.average(a, axis=0, weights=weights)
        b = b - numpy.average(b, axis=0, weights=weights)
    return qcp.CalcRMSDRotationalMatrix(a.T.astype(numpy.float64), b.T.astype(numpy.float64),
                                        a.shape[0], None, relative_weights)
Exemple #3
0
def rms_fit_trj(traj,
                reference,
                select='all',
                filename=None,
                rmsdfile=None,
                prefix='rmsfit_',
                mass_weighted=False,
                tol_mass=0.1,
                force=True,
                quiet=False,
                **kwargs):
    """RMS-fit trajectory to a reference structure using a selection.

    Both reference *ref* and trajectory *traj* must be
    :class:`MDAnalysis.Universe` instances. If they contain a
    trajectory then it is used. The output file format is determined
    by the file extension of *filename*. One can also use the same
    universe if one wants to fit to the current frame.

    :Arguments:
      *traj*
         trajectory, :class:`MDAnalysis.Universe` object
      *reference*
         reference coordinates; :class:`MDAnalysis.Universe` object
         (uses the current time step of the object)
      *select*
         1. any valid selection string for
            :meth:`~MDAnalysis.core.AtomGroup.AtomGroup.selectAtoms` that produces identical
            selections in *mobile* and *reference*; or
         2. a dictionary ``{'mobile':sel1, 'reference':sel2}`` (the
            :func:`fasta2select` function returns such a
            dictionary based on a ClustalW_ or STAMP_ sequence alignment); or
         3. a tuple ``(sel1, sel2)``

         When using 2. or 3. with *sel1* and *sel2* then these selections can also each be
         a list of selection strings (to generate a AtomGroup with defined atom order as
         described under :ref:`ordered-selections-label`).
      *filename*
         file name for the RMS-fitted trajectory or pdb; defaults to the
         original trajectory filename (from *traj*) with *prefix* prepended
      *rmsdfile*
         file name for writing the RMSD timeseries [``None``]
      *prefix*
         prefix for autogenerating the new output filename
      *mass_weighted*
         do a mass-weighted RMSD fit
      *tol_mass*
         Reject match if the atomic masses for matched atoms differ by more than
         *tol_mass* [0.1]
      *force*
         - ``True``: Overwrite an existing output trajectory (default)
         - ``False``: simply return if the file already exists
      *quiet*
         - ``True``: suppress progress and logging for levels INFO and below.
         - ``False``: show all status messages and do not change the the logging
           level (default)

         .. Note:: If


      *kwargs*
         All other keyword arguments are passed on the trajectory
         :class:`~MDAnalysis.coordinates.base.Writer`; this allows manipulating/fixing
         trajectories on the fly (e.g. change the output format by changing the extension of *filename*
         and setting different parameters as described for the corresponding writer).

    :Returns: *filename* (either provided or auto-generated)

    .. _ClustalW: http://www.clustal.org/
    .. _STAMP: http://www.compbio.dundee.ac.uk/manuals/stamp.4.2/

    .. versionchanged:: 0.8
       Added *kwargs* to be passed to the trajectory :class:`~MDAnalysis.coordinates.base.Writer` and
       *filename* is returned.
    """
    frames = traj.trajectory
    if quiet:
        # should be part of a try ... finally to guarantee restoring the log level
        logging.disable(logging.WARN)

    kwargs.setdefault('remarks', 'RMS fitted trajectory to reference')
    if filename is None:
        path, fn = os.path.split(frames.filename)
        filename = os.path.join(path, prefix + fn)
        _Writer = frames.Writer
    else:
        _Writer = frames.OtherWriter
    if os.path.exists(filename) and not force:
        logger.warn(
            "{0} already exists and will NOT be overwritten; use force=True if you want this"
            .format(filename))
        return filename
    writer = _Writer(filename, **kwargs)
    del _Writer

    select = _process_selection(select)
    ref_atoms = reference.selectAtoms(*select['reference'])
    traj_atoms = traj.selectAtoms(*select['mobile'])
    natoms = traj_atoms.numberOfAtoms()

    check_same_atoms(ref_atoms, traj_atoms, tol_mass=tol_mass)

    logger.info("RMS-fitting on %d atoms." % len(ref_atoms))
    if mass_weighted:
        # if performing a mass-weighted alignment/rmsd calculation
        weight = ref_atoms.masses() / ref_atoms.masses().mean()
    else:
        weight = None

    # reference centre of mass system
    # (compatibility with pre 1.0 numpy: explicitly cast coords to float32)
    ref_com = ref_atoms.centerOfMass().astype(numpy.float32)
    ref_coordinates = ref_atoms.coordinates() - ref_com

    # allocate the array for selection atom coords
    traj_coordinates = traj_atoms.coordinates().copy()

    # RMSD timeseries
    nframes = len(frames)
    rmsd = numpy.zeros((nframes, ))

    # R: rotation matrix that aligns r-r_com, x~-x~com
    #    (x~: selected coordinates, x: all coordinates)
    # Final transformed traj coordinates: x' = (x-x~_com)*R + ref_com
    rot = numpy.zeros(9, dtype=numpy.float64)  # allocate space for calculation
    R = numpy.matrix(rot.reshape(3, 3))

    percentage = ProgressMeter(
        nframes,
        interval=10,
        quiet=quiet,
        format="Fitted frame %(step)5d/%(numsteps)d  [%(percentage)5.1f%%]\r")

    for k, ts in enumerate(frames):
        # shift coordinates for rotation fitting
        # selection is updated with the time frame
        x_com = traj_atoms.centerOfMass().astype(numpy.float32)
        traj_coordinates[:] = traj_atoms.coordinates() - x_com

        # Need to transpose coordinates such that the coordinate array is
        # 3xN instead of Nx3. Also qcp requires that the dtype be float64
        # (I think we swapped the position of ref and traj in CalcRMSDRotationalMatrix
        # so that R acts **to the left** and can be broadcasted; we're saving
        # one transpose. [orbeckst])
        rmsd[k] = qcp.CalcRMSDRotationalMatrix(
            ref_coordinates.T.astype(numpy.float64),
            traj_coordinates.T.astype(numpy.float64), natoms, rot, weight)
        R[:, :] = rot.reshape(3, 3)

        # Transform each atom in the trajectory (use inplace ops to avoid copying arrays)
        # (Marginally (~3%) faster than "ts._pos[:] = (ts._pos - x_com) * R + ref_com".)
        ts._pos -= x_com
        ts._pos[:] = ts._pos * R  # R acts to the left & is broadcasted N times.
        ts._pos += ref_com

        writer.write(traj.atoms)  # write whole input trajectory system
        percentage.echo(ts.frame)
    logger.info("Wrote %d RMS-fitted coordinate frames to file %r",
                frames.numframes, filename)
    if not rmsdfile is None:
        numpy.savetxt(rmsdfile, rmsd)
        logger.info("Wrote RMSD timeseries  to file %r", rmsdfile)

    if quiet:
        # should be part of a try ... finally to guarantee restoring the log level
        logging.disable(logging.NOTSET)

    return filename
Exemple #4
0
def test_CalcRMSDRotationalMatrix():
    # Setup coordinates
    frag_a = numpy.zeros((3, 7), dtype=numpy.float64)
    frag_b = numpy.zeros((3, 7), dtype=numpy.float64)
    N = 7

    frag_a[0][0] = -2.803
    frag_a[1][0] = -15.373
    frag_a[2][0] = 24.556
    frag_a[0][1] = 0.893
    frag_a[1][1] = -16.062
    frag_a[2][1] = 25.147
    frag_a[0][2] = 1.368
    frag_a[1][2] = -12.371
    frag_a[2][2] = 25.885
    frag_a[0][3] = -1.651
    frag_a[1][3] = -12.153
    frag_a[2][3] = 28.177
    frag_a[0][4] = -0.440
    frag_a[1][4] = -15.218
    frag_a[2][4] = 30.068
    frag_a[0][5] = 2.551
    frag_a[1][5] = -13.273
    frag_a[2][5] = 31.372
    frag_a[0][6] = 0.105
    frag_a[1][6] = -11.330
    frag_a[2][6] = 33.567

    frag_b[0][0] = -14.739
    frag_b[1][0] = -18.673
    frag_b[2][0] = 15.040
    frag_b[0][1] = -12.473
    frag_b[1][1] = -15.810
    frag_b[2][1] = 16.074
    frag_b[0][2] = -14.802
    frag_b[1][2] = -13.307
    frag_b[2][2] = 14.408
    frag_b[0][3] = -17.782
    frag_b[1][3] = -14.852
    frag_b[2][3] = 16.171
    frag_b[0][4] = -16.124
    frag_b[1][4] = -14.617
    frag_b[2][4] = 19.584
    frag_b[0][5] = -15.029
    frag_b[1][5] = -11.037
    frag_b[2][5] = 18.902
    frag_b[0][6] = -18.577
    frag_b[1][6] = -10.001
    frag_b[2][6] = 17.996

    # Allocate rotation array
    rot = numpy.zeros((9, ), dtype=numpy.float64)

    # Calculate center of geometry
    comA = numpy.sum(frag_a, axis=1) / N
    comB = numpy.sum(frag_b, axis=1) / N

    # Center each fragment
    frag_a = frag_a - comA.reshape(3, 1)
    frag_b = frag_b - comB.reshape(3, 1)

    # Calculate rmsd and rotation matrix
    qcp_rmsd = qcp.CalcRMSDRotationalMatrix(frag_a, frag_b, N, rot, None)

    #print 'qcp rmsd = ',rmsd
    #print 'rotation matrix:'
    #print rot.reshape((3,3))

    # rotate frag_b to obtain optimal alignment
    frag_br = frag_b.T * numpy.matrix(rot.reshape((3, 3)))
    aligned_rmsd = rmsd(frag_br.T, frag_a)
    #print 'rmsd after applying rotation: ',rmsd

    assert_almost_equal(
        aligned_rmsd, 0.719106, 6,
        "RMSD between fragments A and B does not match excpected value.")

    expected_rot = numpy.array([[0.72216358, -0.52038257, -0.45572112],
                                [0.69118937, 0.51700833, 0.50493528],
                                [-0.0271479, -0.67963547, 0.73304748]])
    assert_almost_equal(
        rot.reshape((3, 3)), expected_rot, 6,
        "Rotation matrix for aliging B to A does not have expected values.")
Exemple #5
0
    def run(self, **kwargs):
        """Perform RMSD analysis on the trajectory.

        A number of parameters can be changed from the defaults. The
        result is stored as the array :attr:`RMSD.rmsd`.

        :Keywords:
          *start*, *stop*, *step*
             start and stop frame index with step size: analyse
             ``trajectory[start:stop:step]`` [``None``]
          *mass_weighted*
             do a mass-weighted RMSD fit
          *tol_mass*
             Reject match if the atomic masses for matched atoms differ by more than
             *tol_mass*
          *ref_frame*
             frame index to select frame from *reference*

        """
        from itertools import izip

        start = kwargs.pop('start', None)
        stop = kwargs.pop('stop', None)
        step = kwargs.pop('step', None)
        mass_weighted = kwargs.pop('mass_weighted', self.mass_weighted)
        ref_frame = kwargs.pop('ref_frame', self.ref_frame)

        natoms = self.traj_atoms.numberOfAtoms()
        trajectory = self.universe.trajectory
        traj_atoms = self.traj_atoms

        if mass_weighted:
            # if performing a mass-weighted alignment/rmsd calculation
            weight = self.ref_atoms.masses() / self.ref_atoms.masses().mean()
        else:
            weight = None

        # reference centre of mass system
        current_frame = self.reference.trajectory.ts.frame - 1
        try:
            # Move to the ref_frame
            # (coordinates MUST be stored in case the ref traj is advanced elsewhere or if ref == mobile universe)
            self.reference.trajectory[ref_frame]
            ref_com = self.ref_atoms.centerOfMass()
            ref_coordinates = self.ref_atoms.positions - ref_com  # makes a copy
            if self.groupselections_atoms:
                groupselections_ref_coords_T_64 = [
                    self.reference.selectAtoms(*s['reference']).positions.T.astype(numpy.float64) for s in
                    self.groupselections]
        finally:
            # Move back to the original frame
            self.reference.trajectory[current_frame]
        ref_coordinates_T_64 = ref_coordinates.T.astype(numpy.float64)

        # allocate the array for selection atom coords
        traj_coordinates = traj_atoms.coordinates().copy()

        if self.groupselections_atoms:
            # Only carry out a rotation if we want to calculate secondary RMSDs.
            # R: rotation matrix that aligns r-r_com, x~-x~com
            #    (x~: selected coordinates, x: all coordinates)
            # Final transformed traj coordinates: x' = (x-x~_com)*R + ref_com
            rot = numpy.zeros(9, dtype=numpy.float64)  # allocate space for calculation
            R = numpy.matrix(rot.reshape(3, 3))
        else:
            rot = None

        # RMSD timeseries
        nframes = len(numpy.arange(0, len(trajectory))[start:stop:step])
        rmsd = numpy.zeros((nframes, 3 + len(self.groupselections_atoms)))

        percentage = ProgressMeter(nframes, interval=10,
                                   format="RMSD %(rmsd)5.2f A at frame %(step)5d/%(numsteps)d  [%(percentage)5.1f%%]\r")

        for k, ts in enumerate(trajectory[start:stop:step]):
            # shift coordinates for rotation fitting
            # selection is updated with the time frame
            x_com = traj_atoms.centerOfMass().astype(numpy.float32)
            traj_coordinates[:] = traj_atoms.coordinates() - x_com

            rmsd[k, :2] = ts.frame, trajectory.time

            if self.groupselections_atoms:
                # 1) superposition structures
                # Need to transpose coordinates such that the coordinate array is
                # 3xN instead of Nx3. Also qcp requires that the dtype be float64
                # (I think we swapped the position of ref and traj in CalcRMSDRotationalMatrix
                # so that R acts **to the left** and can be broadcasted; we're saving
                # one transpose. [orbeckst])
                rmsd[k, 2] = qcp.CalcRMSDRotationalMatrix(ref_coordinates_T_64,
                                                          traj_coordinates.T.astype(numpy.float64),
                                                          natoms, rot, weight)
                R[:, :] = rot.reshape(3, 3)

                # Transform each atom in the trajectory (use inplace ops to avoid copying arrays)
                # (Marginally (~3%) faster than "ts._pos[:] = (ts._pos - x_com) * R + ref_com".)
                ts._pos -= x_com
                ts._pos[:] = ts._pos * R  # R acts to the left & is broadcasted N times.
                ts._pos += ref_com

                # 2) calculate secondary RMSDs
                for igroup, (refpos, atoms) in enumerate(
                        izip(groupselections_ref_coords_T_64, self.groupselections_atoms), 3):
                    rmsd[k, igroup] = qcp.CalcRMSDRotationalMatrix(refpos,
                                                                   atoms['mobile'].positions.T.astype(numpy.float64),
                                                                   atoms['mobile'].numberOfAtoms(), None, weight)
            else:
                # only calculate RMSD by setting the Rmatrix to None
                # (no need to carry out the rotation as we already get the optimum RMSD)
                rmsd[k, 2] = qcp.CalcRMSDRotationalMatrix(ref_coordinates_T_64,
                                                          traj_coordinates.T.astype(numpy.float64),
                                                          natoms, None, weight)

            percentage.echo(ts.frame, rmsd=rmsd[k, 2])
        self.rmsd = rmsd
Exemple #6
0
def QH_entro(top_file,
             traj_file,
             index_file,
             temperature=300,
             skip=1,
             begin=0,
             end=-1,
             WRITE_EIGENVECTOR=False):
    '''
    Add some words here.
    '''
    #step 1: reading the trajectory.
    BEGIN_TIME = Time.time()
    print "step 1: Reading trajectory"
    U = MDAnalysis.Universe(top_file, traj_file)
    index = Index.Read_index_to_Inclass(index_file)
    Index.Print_Index(index)
    while True:
        try:
            solute_index = int(
                raw_input("Choose the group for entropy calculation:"))
            break
        except:
            print "You should input a number."
            continue
    chose_group = index[solute_index].group_list

    if end == -1:
        nframes = U.trajectory.numframes - begin
    elif end > begin:
        nframes = end - begin
    else:
        print "The begin and the end of the frame seem not correct."
        sys.exit()

    natoms = len(chose_group)
    print "\t Reading %d frames from trajectory file: %s" % (nframes,
                                                             traj_file)

    #step 2: put data to traj_data matrix. get eigenvalues and eigenvectors.

    traj_data = np.zeros((nframes, natoms, 3), dtype=np.float32)
    traj_data2 = np.zeros((nframes, 3 * natoms), dtype=np.float32)
    traj_ave = np.zeros((3 * natoms), dtype=np.float32)
    covar_mat = np.zeros((3 * natoms, 3 * natoms), dtype=np.float32)

    sqrt_mass = [
        math.sqrt(U.atoms[i].mass) for i in range(U.trajectory.numatoms)
    ]

    POINT = 0
    ##  POINT used to replace the U.trajectory.frame in this part.
    for ts in U.trajectory:
        #        temp_vect = np.zeros(3*natoms,dtype=np.float32)
        POINT += 1
        if POINT > begin and (POINT - begin) < nframes + 1:
            pass
        elif POINT < begin:
            continue
        elif POINT > end and end > 0:
            break
        else:
            print "Note: reach here. begin=%6d,end=%6d,POINT=%6d" % (
                begin, end, POINT)
            sys.exit()

        sys.stderr.write("\t Reading frame %8d\r" % POINT)
        sys.stderr.flush()

        for i, ai in list(enumerate(chose_group)):
            traj_data[POINT - begin - 1, i,
                      0] = ts._x[ai - 1] * sqrt_mass[ai - 1]
            traj_data[POINT - begin - 1, i,
                      1] = ts._y[ai - 1] * sqrt_mass[ai - 1]
            traj_data[POINT - begin - 1, i,
                      2] = ts._z[ai - 1] * sqrt_mass[ai - 1]

########################
#Add fitting code here. from matrix traj_data to a new matrix.
    print "\nstep 2: Fitting the trajectory."

    ref_coor = traj_data[0, :, :]

    for k in range(natoms):
        for l in range(3):
            traj_data2[0, 3 * k + l] = ref_coor[k, l]

    ref_com = np.array([
        sum(ref_coor[:, 0]) / nframes,
        sum(ref_coor[:, 1]) / nframes,
        sum(ref_coor[:, 2]) / nframes
    ])
    #ref_com means center of coordinate the reference.
    ref_coordinates = ref_coor - ref_com

    # traj_coordinates = traj_atoms.coordinates().copy()

    # nframes = len(frames)
    rmsd = np.zeros((nframes, ))

    rot = np.zeros(9, dtype=np.float64)  # allocate space for calculation
    R = np.matrix(rot.reshape(3, 3))

    for k in range(1, nframes):
        # shift coordinates for rotation fitting
        # selection is updated with the time frame

        sys.stderr.write("\t Fitting frame %8d\r" % (k + 1))
        sys.stderr.flush()

        traj_coor = traj_data[k, :, :]
        x_com = np.array([
            sum(traj_coor[:, 0]) / nframes,
            sum(traj_coor[:, 1]) / nframes,
            sum(traj_coor[:, 2]) / nframes
        ])
        traj_coordinates = traj_coor - x_com

        rmsd[k] = qcp.CalcRMSDRotationalMatrix(
            ref_coordinates.T.astype(np.float64),
            traj_coordinates.T.astype(np.float64), natoms, rot, None)
        R[:, :] = rot.reshape(3, 3)

        # Transform each atom in the trajectory (use inplace ops to avoid copying arrays)
        # (Marginally (~3%) faster than "ts._pos[:] = (ts._pos - x_com) * R + ref_com".)
        # ts._pos   -= x_com
        # ts._pos[:] = ts._pos * R # R acts to the left & is broadcasted N times.
        # ts._pos   += ref_com
        new_coor = np.array(
            np.matrix(traj_coordinates) * np.matrix(R)) + ref_com

        for i in range(natoms):
            for j in range(3):
                traj_data2[k, 3 * i + j] = ref_coor[i, j]

    del traj_data
    ########################
    print "\nstep 3: Creating covariance matrix"
    print "\t Generazing the (%d X %d) covariance matrix" % (3 * natoms,
                                                             3 * natoms)

    #        traj_data[ts.frame-1]=temp_vect
    for i in range(nframes):
        traj_ave += traj_data2[i]

    traj_ave = traj_ave / nframes

    for i in range(nframes):
        delta_vect = [
            traj_data2[i][j] - traj_ave[j] for j in range(3 * natoms)
        ]
        covar_mat += np.array(np.matrix(delta_vect).T * np.matrix(delta_vect))

#    covar_mat = covar_mat / ( nframes -1 )   # be careful!
    covar_mat = covar_mat / nframes

    TIME1 = Time.time()
    print "\t Time used %6.2f s" % (TIME1 - BEGIN_TIME)

    print "step 4: Diagnoalizing the covariance matrix"
    eigenvalues, eigenvectors = np.linalg.eig(covar_mat)
    print eigenvalues

    TIME2 = Time.time()

    print "\t Time used %6.2f s" % (TIME2 - TIME1)

    #    sys.exit()

    #step 3: get the number of classical mode eigenvalues.
    #    eigenvalues=sorted(eigenvalues,reverse=True)
    #    np.savetxt("eigen.xvg",eigenvalues)

    eigen_thr = 1e-6
    truncate_num = 0
    for i in range(3 * natoms):
        if eigenvalues[i] < eigen_thr:
            truncate_num = i
            break
        elif eigenvalues[-1] > eigen_thr:
            truncate_num = 3 * natoms
    print "\t Using %d eigenvalues to calculate entropy." % truncate_num

    print "step 5: Calculating the quasiharmonic entropy"
    global HBA
    global K
    global MP
    # global R
    alpha_const = HBA * (1e10) / math.sqrt(K * temperature * MP)
    eigval_class = eigenvalues[:truncate_num]
    eigvec_class = eigenvectors[:truncate_num]

    alpha = [
        alpha_const / math.sqrt(eigval_class[i]) for i in range(truncate_num)
    ]
    s_quantum = [
        alpha[i] / (math.exp(alpha[i]) - 1) - math.log(1 - math.exp(-alpha[i]))
        for i in range(truncate_num)
    ]
    print s_quantum

    total_entropy = sum(s_quantum) * R
    print "\t Entopy: %8.2f J/mol/K, %8.2f Kcal/mol." % (
        total_entropy, total_entropy / 4186.8 * temperature)
Exemple #7
0
def Main(top_file,
         traj_file,
         index_file,
         log_file,
         eigen_file,
         temperature=300,
         begin=0,
         end=-1,
         CYCLES=1):
    '''
    Add some words here.
    '''
    #step 1: reading the trajectory.
    # BEGIN_TIME=Time.time()
    print "step 1: Reading trajectory"
    U = MDAnalysis.Universe(top_file, traj_file)
    index = Read_index_to_Inclass(index_file)
    Print_Index(index)

    fp = open(log_file, "w")
    fp.write("Loading top_file   %s\n" % top_file)
    fp.write("Loading traj file  %s\n" % traj_file)
    fp.write("Loading index file %s\n" % index_file)

    while True:
        try:
            solute_index = int(
                raw_input("Choosing the group for entropy calculation:"))
            break
        except:
            print "You should input a number."
            continue
    chose_group = index[solute_index].group_list

    fp.write("Choose group %d, %s\n" %
             (solute_index, index[solute_index].group_name))
    #    print chose_group
    print "\t Loading the trajectory file %s, please wait..." % (traj_file)
    if end == -1:
        nframes = (U.trajectory.numframes - begin)
    elif end > begin:
        nframes = (end - begin)
    elif begin > U.trajectory.numframes:
        print "The begin is out of the range of trajectory frames."
        sys.exit()
    else:
        pass
        # print "The begin and the end of the frame seem not correct."
        # sys.exit()

    natoms = len(chose_group)
    print "\t Reading %d frames from trajectory file: %s" % (nframes,
                                                             traj_file)
    fp.write("Reading %d frames from trajectory file: %s\n" %
             (nframes, traj_file))
    fp.close()

    traj_data = np.zeros((nframes, natoms, 3), dtype=np.float32)
    traj_data2 = np.zeros((nframes, 3 * natoms), dtype=np.float32)

    POINT = 0
    ##  POINT used to replace the U.trajectory.frame in this part.
    for ts in U.trajectory:

        if ts.frame > nframes + begin:
            break
        elif ts.frame < begin:
            continue
        # elif (ts.frame-begin) % skip != 0:
        #     continue

        sys.stderr.write("\t Reading frame %8d\r" % ts.frame)
        sys.stderr.flush()

        for i, ai in list(enumerate(chose_group)):
            traj_data[POINT, i, 0] = ts._x[ai - 1]
            traj_data[POINT, i, 1] = ts._y[ai - 1]
            traj_data[POINT, i, 2] = ts._z[ai - 1]
        POINT += 1

########################
#Add fitting code here. from matrix traj_data to a new matrix.
    print "\nstep 2: Fitting the trajectory."

    ref_coor = traj_data[0, :, :]
    ref_com = np.array([
        sum(ref_coor[:, 0]) / natoms,
        sum(ref_coor[:, 1]) / natoms,
        sum(ref_coor[:, 2]) / natoms
    ])
    ref_coordinates = ref_coor - ref_com
    # print ref_coordinates

    for k in range(natoms):
        for l in range(3):
            traj_data2[0, 3 * k + l] = ref_coordinates[k, l]

    rmsd = np.zeros((nframes, ))
    rot = np.zeros(9, dtype=np.float64)  # allocate space for calculation
    R = np.matrix(rot.reshape(3, 3))

    for k in range(1, nframes):
        # shift coordinates for rotation fitting
        # selection is updated with the time frame

        sys.stderr.write("\t Fitting frame %8d\r" % (k + 1))
        sys.stderr.flush()

        traj_coor = traj_data[k, :, :]
        x_com = np.array([
            sum(traj_coor[:, 0]) / natoms,
            sum(traj_coor[:, 1]) / natoms,
            sum(traj_coor[:, 2]) / natoms
        ])
        traj_coordinates = traj_coor - x_com

        rmsd[k] = qcp.CalcRMSDRotationalMatrix(
            ref_coordinates.T.astype(np.float64),
            traj_coordinates.T.astype(np.float64), natoms, rot, None)
        R[:, :] = rot.reshape(3, 3)
        new_coor = np.array(np.matrix(traj_coordinates) * np.matrix(R))
        for i in range(natoms):
            for j in range(3):
                traj_data2[k, 3 * i + j] = new_coor[i, j]

    del traj_data
    # np.savetxt("rmsd.dat",rmsd)

    ########################
    print "\nstep 3: Creating covariance matrix"
    print "\t Generazing the (%d X %d) covariance matrix" % (3 * natoms,
                                                             3 * natoms)

    group_mass = np.repeat(
        [math.sqrt(U.atoms[i - 1].mass) for i in chose_group], 3)
    for cycle in range(CYCLES):
        QHE(traj_data2,
            group_mass,
            temperature,
            nframes / CYCLES * (cycle + 1),
            log_file=log_file)