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
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)
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
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.")
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
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)
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)