def inside(lst, reference, positions, positions2, cell_vector): global upper global finished if len(lst) > 0: for a in lst: temp_pos = positions2[a:a + 1] # permutate over the periodic boundary conditions for vector in range(len(cell_vector)): rmsd1 = rmsd(reference[:len(positions) + 1], np.append(positions, temp_pos + cell_vector[vector], axis=0), superposition=True) if rmsd1 <= upper: positions1 = np.append(positions, temp_pos + cell_vector[vector], axis=0) lst_i = lst[:] lst_i.remove(a) inside(lst_i, reference, positions1, positions2, cell_vector) else: temp = rmsd(reference[:len(positions)], positions, superposition=True) if upper >= temp: upper = temp
def test_rmsd(self, universe, reference): universe.trajectory[0] # ensure first frame bb = universe.select_atoms('backbone') first_frame = bb.positions universe.trajectory[-1] last_frame = bb.positions assert_almost_equal(rms.rmsd(first_frame, first_frame), 0.0, 5, err_msg="error: rmsd(X,X) should be 0") # rmsd(A,B) = rmsd(B,A) should be exact but spurious failures in the # 9th decimal have been observed (see Issue 57 comment #1) so we relax # the test to 6 decimals. rmsd = rms.rmsd(first_frame, last_frame, superposition=True) assert_almost_equal( rms.rmsd(last_frame, first_frame, superposition=True), rmsd, 6, err_msg="error: rmsd() is not symmetric") assert_almost_equal(rmsd, 6.820321761927005, 5, err_msg="RMSD calculation between 1st and last AdK frame gave wrong answer") # test masses as weights last_atoms_weight = universe.atoms.masses A = universe.trajectory[0] B = reference.trajectory[-1] rmsd = align.alignto(universe, reference, weights='mass') rmsd_sup_weight = rms.rmsd(A, B, weights=last_atoms_weight, center=True, superposition=True) assert_almost_equal(rmsd[1], rmsd_sup_weight, 6)
def test_weights(self, a, b): weights = np.zeros(len(a)) weights[0] = 1 weights[1] = 1 weighted = rms.rmsd(a, b, weights=weights) firstCoords = rms.rmsd(a[:2], b[:2]) assert_almost_equal(weighted, firstCoords)
def test_with_superposition_smaller(self, p_first, p_last): A = p_first.positions B = p_last.positions rmsd = rms.rmsd(A, B) rmsd_superposition = rms.rmsd(A, B, center=True, superposition=True) # by design the super positioned rmsd is smaller assert rmsd > rmsd_superposition
def test_with_superposition_equal(self, p_first, p_last): align.alignto(p_first, p_last) A = p_first.positions B = p_last.positions rmsd = rms.rmsd(A, B) rmsd_superposition = rms.rmsd(A, B, center=True, superposition=True) assert_almost_equal(rmsd, rmsd_superposition, decimal=6)
def test_weights_and_superposition_1(self, u): weights = np.ones(len(u.trajectory[0])) weighted = rms.rmsd(u.trajectory[0], u.trajectory[1], weights=weights, superposition=True) firstCoords = rms.rmsd(u.trajectory[0], u.trajectory[1], superposition=True) assert_almost_equal(weighted, firstCoords, decimal=5)
def test_rmsd(self): self.universe.trajectory[0] # ensure first frame bb = self.universe.select_atoms('backbone') first_frame = bb.positions self.universe.trajectory[-1] last_frame = bb.positions assert_almost_equal(rms.rmsd(first_frame, first_frame), 0.0, 5, err_msg="error: rmsd(X,X) should be 0") # rmsd(A,B) = rmsd(B,A) should be exact but spurious failures in the # 9th decimal have been observed (see Issue 57 comment #1) so we relax # the test to 6 decimals. rmsd = rms.rmsd(first_frame, last_frame, superposition=True) assert_almost_equal(rms.rmsd(last_frame, first_frame, superposition=True), rmsd, 6, err_msg="error: rmsd() is not symmetric") assert_almost_equal(rmsd, 6.820321761927005, 5, err_msg="RMSD calculation between 1st and last " "AdK frame gave wrong answer") # test masses as weights last_atoms_weight = self.universe.atoms.masses A = self.universe.trajectory[0] B = self.reference.trajectory[-1] rmsd = align.alignto(self.universe, self.reference, weights='mass') rmsd_sup_weight = rms.rmsd(A, B, weights=last_atoms_weight, center=True, superposition=True) assert_almost_equal(rmsd[1], rmsd_sup_weight, 6)
def test_weights(self): weights = np.zeros(len(self.a)) weights[0] = 1 weights[1] = 1 weighted = rms.rmsd(self.a, self.b, weights=weights) firstCoords = rms.rmsd(self.a[:2], self.b[:2]) assert_almost_equal(weighted, firstCoords)
def test_weights_and_superposition_1(self): weights = np.ones(len(self.u.trajectory[0])) weighted = rms.rmsd(self.u.trajectory[0], self.u.trajectory[1], weights=weights, superposition=True) firstCoords = rms.rmsd(self.u.trajectory[0], self.u.trajectory[1], superposition=True) assert_almost_equal(weighted, firstCoords, decimal=5)
def test_with_superposition_equal(self): align.alignto(self.p_first, self.p_last) A = self.p_first.positions B = self.p_last.positions rmsd = rms.rmsd(A, B) rmsd_superposition = rms.rmsd(A, B, center=True, superposition=True) assert_almost_equal(rmsd, rmsd_superposition)
def test_rmsd(self): self.universe.trajectory[0] # ensure first frame bb = self.universe.select_atoms('backbone') first_frame = bb.positions self.universe.trajectory[-1] last_frame = bb.positions assert_almost_equal(rms.rmsd(first_frame, first_frame), 0.0, 5, err_msg="error: rmsd(X,X) should be 0") # rmsd(A,B) = rmsd(B,A) should be exact but spurious failures in the # 9th decimal have been observed (see Issue 57 comment #1) so we relax # the test to 6 decimals. rmsd = rms.rmsd(first_frame, last_frame, superposition=True) assert_almost_equal(rms.rmsd(last_frame, first_frame, superposition=True), rmsd, 6, err_msg="error: rmsd() is not symmetric") assert_almost_equal(rmsd, 6.820321761927005, 5, err_msg="RMSD calculation between 1st and last " "AdK frame gave wrong answer")
def test_with_superposition_smaller(self): A = self.p_first.positions B = self.p_last.positions rmsd = rms.rmsd(A, B) rmsd_superposition = rms.rmsd(A, B, center=True, superposition=True) print(rmsd, rmsd_superposition) # by design the super positioned rmsd is smaller assert_(rmsd > rmsd_superposition)
def test_weights_and_superposition_2(self): weights = np.zeros(len(self.u.trajectory[0])) weights[:100] = 1 weighted = rms.rmsd(self.u.trajectory[0], self.u.trajectory[-1], weights=weights, superposition=True) firstCoords = rms.rmsd(self.u.trajectory[0][:100], self.u.trajectory[-1][:100], superposition=True) #very close to zero, change significant decimal places to 5 assert_almost_equal(weighted, firstCoords, decimal = 5)
def test_weights_and_superposition_2(self, u): weights = np.zeros(len(u.trajectory[0])) weights[:100] = 1 weighted = rms.rmsd(u.trajectory[0], u.trajectory[-1], weights=weights, superposition=True) firstCoords = rms.rmsd(u.trajectory[0][:100], u.trajectory[-1][:100], superposition=True) # very close to zero, change significant decimal places to 5 assert_almost_equal(weighted, firstCoords, decimal=5)
def time_rmsd(self, num_atoms, weights, center, superposition): """Benchmark rmsd function using a setup similar to its docstring example code along with several possible permutations of parameters. """ rms.rmsd(a=self.A, b=self.B, weights=weights, center=center, superposition=superposition)
def measure_rmsd(ref, mobile): backbone_ref = ref.select_atoms("backbone") LIG_ref = ref.select_atoms("resname LIG") backbone_mobile = mobile.select_atoms("backbone") LIG_mobile = mobile.select_atoms("resname LIG") rmsd_backbone = rms.rmsd(backbone_mobile.positions, backbone_ref.positions) rmsd_LIG = rms.rmsd(LIG_mobile.positions, LIG_ref.positions) return rmsd_backbone, rmsd_LIG
def rmsd_perm(lista, cell_vector=[[0.0, 0.0, 0.0]]): reference = lista[0] positions2 = lista[1] N = len(reference) global upper lst0 = range(N) # computation time of RMSD grows expotentially with the RMSD # thefore you might consider using cut-off, i.g.: # upper=4.0 # instead of: upper = rmsd(reference, positions2, superposition=True) # becasue most of the time you are only intrested in close things not the things which are far apart # If it is the same frame return 0.0 if (np.all(reference - positions2 < 10e-6)): return 0.0 for a in lst0: lst1 = lst0[:] lst1.remove(a) positions = positions2[a:a + 1] inside(lst1, reference, positions, positions2, cell_vector) return upper
def block_rmsd(dset, xref0, start=None, stop=None, step=None): start00 = time.time() print("block_rmsd", start, stop, step) bsize = int(stop - start) results = np.zeros([bsize, 2], dtype=float) t_comp = np.zeros(bsize, dtype=float) t_IO = np.zeros(bsize, dtype=float) start0 = time.time() for iframe, ts in enumerate(range(start, stop, step)): start1 = time.time() pos = np.reshape(dset[ts, :], (-1, 3)) start2 = time.time() results[iframe, :] = ts, rms.rmsd(pos, xref0, center=True, superposition=True) t_comp[iframe] = time.time() - start2 t_IO[iframe] = start2 - start1 start1 = time.time() start3 = time.time() t_end_loop = start3 - start1 t_all_frame = start3 - start0 t_IO_final = np.sum(t_IO) t_comp_final = np.sum(t_comp) t_init = start0 - start00 return results, t_comp_final, t_IO_final, t_all_frame, t_end_loop, t_init
def _fitter_worker(self, tasks, coords, subset_coords, masses, subset_masses, rmsdmat, pbar_counter): ''' Fitter RMSD Matrix calculator. See encore.confdistmatrix.RMSDMatrixGenerator._fitter_worker for details. ''' if subset_coords == None: for i, j in trm_indeces(tasks[0], tasks[1]): coords[i] -= average(coords[i], axis=0, weights=masses) coords[j] -= average(coords[j], axis=0, weights=masses) weights = asarray(masses) / mean(masses) rmsdmat[(i + 1) * i / 2 + j] = -rmsd(coords[i], coords[j], weights=weights) pbar_counter.value += 1 else: for i, j in trm_indeces(tasks[0], tasks[1]): #masses = asarray(masses)/mean(masses) summasses = sum(masses) com_i = average(subset_coords[i], axis=0, weights=subset_masses) translated_i = coords[i] - com_i subset1_coords = subset_coords[i] - com_i com_j = average(subset_coords[j], axis=0, weights=subset_masses) translated_j = coords[j] - com_j subset2_coords = subset_coords[j] - com_j rotamat = rotation_matrix(subset1_coords, subset2_coords, subset_masses)[0] rotated_i = transpose(dot(rotamat, transpose(translated_i))) rmsdmat[(i + 1) * i / 2 + j] = MinusRMSD( rotated_i.astype(float64), translated_j.astype(float64), coords[j].shape[0], masses, summasses) pbar_counter.value += 1
def _assert_rmsd(self, fitted, frame, desired): fitted.trajectory[frame] rmsd = rms.rmsd(self.reference.atoms.coordinates(), fitted.atoms.coordinates()) assert_almost_equal(rmsd, desired, decimal=5, err_msg="frame {0:d} of fit does not have " "expected RMSD".format(frame))
def ligRMSD(u,ref): """ This function produces RMSD data and plots for ligand. :input 1) Universe of Trajectory 2) reference universe :return 1) matplot object 2) array for RMSD data. """ RMSD_lig = [] ligand = u.select_atoms("(resid 142:146) and not name H*") ## include selection based on user description #current = u.select_atoms("segname BGLC and not name H*") reference = ref.select_atoms("(resid 142:146) and not name H*") for ts in u.trajectory: A = ligand.coordinates() B = reference.coordinates() C = rmsd(A,B) RMSD_lig.append((u.trajectory.frame, C)) RMSD_lig = np.array(RMSD_lig) #print RMSD_lig import matplotlib.pyplot as plt ax = plt.subplot(111) ax.plot(RMSD_lig[:,0], RMSD_lig[:,1], 'r--', lw=2, label=r"$R_G$") ax.set_xlabel("Frame") ax.set_ylabel(r"RMSD of ligand ($\AA$)") #ax.figure.savefig("RMSD_ligand.pdf") #plt.draw() handles, labels = ax.get_legend_handles_labels() ax.legend(handles, labels, loc = 'lower left') return ax, RMSD_lig
def rmsd_to_target(atomgroup, target_atomgroup = target.atoms, selection = rmsd_measurement_selection, center = True, superposition = True): """Calculate RMSD to the target structure :Arguments: atomgroup the MDA atomgroup associated with a trajectory initial_atomgroup atomgroup of the target structure selection atom selection used for fitting center, superposition conditions for fitting by MDA (should be Boolean) :Returns: rmsd a scalar RMSD-to-target value""" ag = atomgroup.select_atoms(selection) target_ag = target_atomgroup.select_atoms(selection) return rmsd(ag.positions, target_ag.positions, center=center, superposition=superposition)
def block_rmsd(index, topology, trajectory, xref0): start00 = time.time() clone = mda.Universe(topology, trajectory) g = clone.atoms[index] bsize = g.universe.trajectory.n_frames results = np.zeros([bsize, 2], dtype=float) t_comp = np.zeros(bsize, dtype=float) t_IO = np.zeros(bsize, dtype=float) start1 = time.time() start0 = start1 for iframe, ts in enumerate(clone.trajectory): start2 = time.time() results[iframe, :] = ts.time, rms.rmsd(g.positions, xref0, center=True, superposition=True) t_comp[iframe] = time.time() - start2 t_IO[iframe] = start2 - start1 start1 = time.time() t_end_loop = time.time() - start1 t_all_frame = time.time() - start0 t_IO_final = np.sum(t_IO) t_comp_final = np.sum(t_comp) t_init = start0 - start00 return results, t_comp_final, t_IO_final, t_all_frame, t_end_loop, t_init
def _assert_rmsd(self, reference, fitted, frame, desired, weights=None): fitted.trajectory[frame] rmsd = rms.rmsd(reference.atoms.positions, fitted.atoms.positions, superposition=True) assert_almost_equal(rmsd, desired, decimal=5, err_msg="frame {0:d} of fit does not have " "expected RMSD".format(frame))
def __init__(self, u): ref = u.select_atoms('name CA').positions mobile = [u.select_atoms('name CA').positions for t in u.trajectory] self.rmsd = [ rmsd(ref, mobile[i], superposition=True) for i in range(len(mobile)) ]
def Calculate_ddRMSD(ABMD, Ini_ref, End_ref): ''' Parameters: ABMD: Full traj Ini_ref: Initial frame End_ref: Target frame rmsd_ab: rmsd between start and end frame Returns: time: time coordinate for one traj ddRMSD: ddRMSD along time ''' Ini_temp = Ini_ref.select_atoms('name CA') End_temp = End_ref.select_atoms('name CA') align.alignto(Ini_temp, End_temp) Ini_position = Ini_temp.positions End_position = End_temp.positions rmsd_ab = rmsd(Ini_position, End_position) RMSD_ini = RMSD(ABMD, Ini_ref, select='name CA') RMSD_ini.run() RMSD_end = RMSD(ABMD, End_ref, select='name CA') RMSD_end.run() rmsd_ini = RMSD_ini.rmsd.T rmsd_end = RMSD_end.rmsd.T time = rmsd_ini[1] ddRMSD = (rmsd_ini[2] - rmsd_end[2]) / rmsd_ab return time, ddRMSD, rmsd_ini, rmsd_end
def _assert_rmsd(self, fitted, frame, desired, weights=None): fitted.trajectory[frame] rmsd = rms.rmsd(self.reference.atoms.positions, fitted.atoms.positions, superposition=True) assert_almost_equal(rmsd, desired, decimal=5, err_msg="frame {0:d} of fit does not have " "expected RMSD".format(frame))
def iterative_align_average_com(coord, selGroup, frameStart=0, frameStop=-1, deltaFrame=1, maxSteps=25, thresh=0.001): if frameStop < 0: frameStop = coord.trajectory.n_frames + frameStop + 1 nFrames = int((frameStop - frameStart) // deltaFrame) # create numpy array of aligned positions alignedPos = np.empty((nFrames, selGroup.n_residues, 3), dtype=np.float64) #generate an initial average by aligning to first frame avg = np.zeros((selGroup.n_residues, 3), dtype=np.float64) comPos = np.empty((selGroup.n_residues, 3), dtype=np.float64) frameCount = 0 selGroupUniqueResids = np.unique(selGroup.resids) psel = coord.select_atoms( "name P") # added for including phosphates in analysis for ts in coord.trajectory[frameStart:frameStop:deltaFrame]: if ts.frame % 100 == 0: print("CGing frame ", ts.frame, " of ", nFrames) selGroup.translate(-selGroup.center_of_mass()) # for i, resid in enumerate(selGroupUniqueResids): for i in range(451): # added for including phosphates in analysis comPos[i, :] = coord.residues[i].atoms.center_of_mass() comPos[ 451:, :] = psel.positions # added for including phosphates in analysis if frameCount == 0: ref = np.copy(comPos) else: R = align.rotation_matrix(comPos, ref)[0] comPos = np.dot(comPos, R.T) avg += comPos alignedPos[frameCount, :, :] = comPos frameCount += 1 # finish average avg /= nFrames # perform iterative alignment and average to converge average newAvg = np.zeros((selGroup.n_residues, 3), dtype=np.float64) avgRmsd = 2 * thresh step = 0 while step < maxSteps and avgRmsd > thresh: newAvg = 0.0 frameCount = 0 for ts in coord.trajectory[frameStart:frameStop:deltaFrame]: alignedPos[frameCount, :, :] -= np.mean( alignedPos[frameCount, :, :], axis=0) R = align.rotation_matrix(alignedPos[frameCount, :, :], avg)[0] alignedPos[frameCount, :, :] = np.dot(alignedPos[frameCount, :, :], R.T) newAvg += alignedPos[frameCount, :, :] frameCount += 1 # finish average newAvg /= nFrames avgRmsd = rmsd(avg, newAvg, center=False, superposition=False) avg = np.copy(newAvg) step += 1 print(step, avgRmsd) return avg, alignedPos
def _fitter_worker(self, tasks, coords, subset_coords, masses, subset_masses, rmsdmat, pbar_counter): ''' Fitter RMSD Matrix calculator. See encore.confdistmatrix.RMSDMatrixGenerator._fitter_worker for details. ''' if subset_coords == None: for i,j in trm_indeces(tasks[0],tasks[1]): coords[i] -= average(coords[i], axis=0, weights=masses) coords[j] -= average(coords[j], axis=0, weights=masses) weights = asarray(masses)/mean(masses) rmsdmat[(i+1)*i/2+j] = - rmsd(coords[i],coords[j],weights=weights) pbar_counter.value += 1 else: for i,j in trm_indeces(tasks[0],tasks[1]): #masses = asarray(masses)/mean(masses) summasses = sum(masses) com_i = average(subset_coords[i], axis=0, weights=subset_masses) translated_i = coords[i] - com_i subset1_coords = subset_coords[i] - com_i com_j = average(subset_coords[j], axis=0, weights=subset_masses) translated_j = coords[j] - com_j subset2_coords = subset_coords[j] - com_j rotamat = rotation_matrix(subset1_coords, subset2_coords, subset_masses)[0] rotated_i = transpose(dot(rotamat, transpose(translated_i))) rmsdmat[(i+1)*i/2+j] = MinusRMSD(rotated_i.astype(float64), translated_j.astype(float64), coords[j].shape[0], masses, summasses) pbar_counter.value += 1
def test_superposition(self, a, b, u): bb = u.atoms.select_atoms('backbone') a = bb.positions.copy() u.trajectory[-1] b = bb.positions.copy() rmsd = rms.rmsd(a, b, superposition=True) assert_almost_equal(rmsd, 6.820321761927005)
def test_superposition(self): bb = self.u.atoms.select_atoms('backbone') a = bb.positions.copy() self.u.trajectory[-1] b = bb.positions.copy() rmsd = rms.rmsd(a, b, superposition=True) assert_almost_equal(rmsd, 6.820321761927005)
def benchmark_mda_rmsd(u): """Benchmarks rmsd calculation for a given universe""" CA = u.select_atoms("protein and name CA") x_ref = CA.positions.copy() total_io = 0 total_rmsd = 0 total_loop = -time.time() for i in range(len(u.trajectory)): start_io = time.time() ts = u.trajectory[i] total_io += time.time() - start_io start_rmsd = time.time() result = rmsd(CA.positions, x_ref, superposition=True) total_rmsd += time.time() - start_rmsd total_loop += time.time() return {"Loop": total_loop, "Loop_per_frame": (total_loop/u.trajectory.n_frames), "I/O": total_io, "I/O_per_frame": (total_io/u.trajectory.n_frames), "RMSD": total_rmsd, "RMSD_per_frame": (total_rmsd/u.trajectory.n_frames), "Overhead": (total_loop - (total_io + total_rmsd)), "Overhead_per_frame": ((total_loop - (total_io + total_rmsd))/u.trajectory.n_frames)}
def _fitter_worker(self, tasks, coords, subset_coords, masses, subset_masses, rmsdmat, pbar_counter): ''' Fitter RMSD Matrix calculator: performs least-square fitting between each pair of structures before calculating the RMSD. **Arguments:** `tasks` : iterator of int of length 2 Given a triangular matrix written in a row-major order, this worker will calculate RMSD values from element tasks[0] to tasks[1]. Since the matrix is triangular. the trm_indeces function automatically calculates the corrisponding i,j matrix indeces. (see the see encore.utils.TriangularMatrix for details). `coords` : numpy.array Array of the ensemble coordinates `subset_coords` : numpy.array or None Array of the coordinates used for fitting `masses` : numpy.array or None Array of atomic masses, having the same order as the coordinates array. If None, coords will be used instead. `subset_masses` : numpy.array Array of atomic masses, having the same order as the subset_coords array `rmsdmat` : encore.utils.TriangularMatrix Memory-shared triangular matrix object `pbar_counter` : multiprocessing.RawValue Thread-safe shared value. This counter is updated at every cycle and used to evaluate the progress of each worker. ''' if subset_coords == None: for i, j in trm_indeces(tasks[0], tasks[1]): coords[i] -= average(coords[i], axis=0, weights=masses) coords[j] -= average(coords[j], axis=0, weights=masses) weights = asarray(masses) / mean(masses) rmsdmat[(i + 1) * i / 2 + j] = rmsd(coords[i], coords[j], weights=weights) pbar_counter.value += 1 else: for i, j in trm_indeces(tasks[0], tasks[1]): summasses = sum(masses) subset_weights = asarray(subset_masses) / mean(subset_masses) com_i = average(subset_coords[i], axis=0, weights=subset_masses) translated_i = coords[i] - com_i subset1_coords = subset_coords[i] - com_i com_j = average(subset_coords[j], axis=0, weights=subset_masses) translated_j = coords[j] - com_j subset2_coords = subset_coords[j] - com_j rotamat = rotation_matrix(subset1_coords, subset2_coords, subset_weights)[0] rotated_i = transpose(dot(rotamat, transpose(translated_i))) rmsdmat[(i + 1) * i / 2 + j] = PureRMSD( rotated_i.astype(float64), translated_j.astype(float64), coords[j].shape[0], masses, summasses) pbar_counter.value += 1
def _collect_rmsd(self, positions): if self.wrap is not None: positions = self.wrap(positions) rmsd = rms.rmsd(positions, self._reference_positions, superposition=True) self._rmsd.append(rmsd)
def test_rmsd(): c = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]]) d = np.array([[13,14,15], [16,17,18], [19,20,21], [22,23,24]]) k = np.array([[.9977195, .02926979, .06082009], [-.0310942, .9990878, .02926979], [-.05990789, -.0310942, .9977195]]) l = np.dot(d, k) m = rms.rmsd(l, c) h = 20.73219522556076 assert_almost_equal(m, h, 6)
def _single_frame(self): # what to do at each frame this_frame_tgt = self.target.positions self.rmsd_list.append( rmsd(this_frame_tgt, self.reference, center=self.do_center, superposition=self.do_superpose))
def test_rmsd_custom_mass_weights(self): last_atoms_weight = self.universe.atoms.masses A = self.universe.trajectory[0] B = self.reference.trajectory[-1] rmsd = align.alignto(self.universe, self.reference, weights=self.reference.atoms.masses) rmsd_sup_weight = rms.rmsd(A, B, weights=last_atoms_weight, center=True, superposition=True) assert_almost_equal(rmsd[1], rmsd_sup_weight, 6)
def test_rmsd(self): self.universe.trajectory[0] # ensure first frame bb = self.universe.select_atoms('backbone') first_frame = bb.coordinates(copy=True) self.universe.trajectory[-1] last_frame = bb.coordinates() assert_almost_equal(rms.rmsd(first_frame, first_frame), 0.0, 5, err_msg="error: rmsd(X,X) should be 0") # rmsd(A,B) = rmsd(B,A) should be exact but spurious failures in the # 9th decimal have been observed (see Issue 57 comment #1) so we relax # the test to 6 decimals. rmsd = rms.rmsd(first_frame, last_frame) assert_almost_equal(rms.rmsd(last_frame, first_frame), rmsd, 6, err_msg="error: rmsd() is not symmetric") assert_almost_equal(rmsd, 6.8342494129169804, 5, err_msg="RMSD calculation between 1st and last " "AdK frame gave wrong answer")
def test_rmsd_custom_mass_weights(self, universe, reference): last_atoms_weight = universe.atoms.masses A = universe.trajectory[0] B = reference.trajectory[-1] rmsd = align.alignto(universe, reference, weights=reference.atoms.masses) rmsd_sup_weight = rms.rmsd(A, B, weights=last_atoms_weight, center=True, superposition=True) assert_almost_equal(rmsd[1], rmsd_sup_weight, 6)
def proRMSD(u,ref): """ This function produces RMSD data and plots for Protein. :input 1) Universe of Trajectory 2) reference universe :return 1) matplot object 2) array for RMSD data. """ RMSD = [] RMSDAllAtom = [] backbone = u.select_atoms("protein and (name C or name N or name CA)") reference = ref.select_atoms("protein and (name C or name N or name CA)") Allcurrent = u.select_atoms("protein and not name H*") Allreference = ref.select_atoms("protein and not name H*") for ts in u.trajectory: A = backbone.coordinates() B = reference.coordinates() E = Allcurrent.coordinates() F = Allreference.coordinates() C = rmsd(A,B) G = rmsd(E,F) RMSD.append((u.trajectory.frame, C)) RMSDAllAtom.append((u.trajectory.frame, G)) RMSD = np.array(RMSD) RMSDAllAtom = np.array(RMSDAllAtom) #print RMSDAllAtom #print RMSD ax = plt.subplot(111) ax.plot(RMSD[:,0], RMSD[:,1], 'r', lw=2, label="Calpha RMSD") ax.plot(RMSDAllAtom[:,0], RMSDAllAtom[:,1], 'g', lw=2, label="All Atom RMSD (noH)") ax.set_xlabel("Frame") ax.set_ylabel(r"RMSD of Backbone ($\AA$)") #ax.figure.savefig("RMSD.pdf") handles, labels = ax.get_legend_handles_labels() ax.legend(handles, labels, loc = 'lower left') #plt.draw() return ax, RMSD, RMSDAllAtom
def test_rmsd_deprecated(self): last_atoms_weight = self.universe.atoms.masses A = self.universe.trajectory[0] B = self.reference.trajectory[-1] with warnings.catch_warnings(record=True) as warn: warnings.simplefilter('always') rmsd = align.alignto(self.universe, self.reference, mass_weighted=True) assert_equal(len(warn), 1) rmsd_sup_weight = rms.rmsd(A, B, weights=last_atoms_weight, center=True, superposition=True) assert_almost_equal(rmsd[1], rmsd_sup_weight, 6)
def _fitter_worker(self, tasks, coords, subset_coords, masses, subset_masses, rmsdmat, pbar_counter): ''' Fitter RMSD Matrix calculator: performs least-square fitting between each pair of structures before calculating the RMSD. **Arguments:** `tasks` : iterator of int of length 2 Given a triangular matrix written in a row-major order, this worker will calculate RMSD values from element tasks[0] to tasks[1]. Since the matrix is triangular. the trm_indeces function automatically calculates the corrisponding i,j matrix indeces. (see the see encore.utils.TriangularMatrix for details). `coords` : numpy.array Array of the ensemble coordinates `subset_coords` : numpy.array or None Array of the coordinates used for fitting `masses` : numpy.array or None Array of atomic masses, having the same order as the coordinates array. If None, coords will be used instead. `subset_masses` : numpy.array Array of atomic masses, having the same order as the subset_coords array `rmsdmat` : encore.utils.TriangularMatrix Memory-shared triangular matrix object `pbar_counter` : multiprocessing.RawValue Thread-safe shared value. This counter is updated at every cycle and used to evaluate the progress of each worker. ''' if subset_coords == None: for i,j in trm_indeces(tasks[0],tasks[1]): coords[i] -= average(coords[i], axis=0, weights=masses) coords[j] -= average(coords[j], axis=0, weights=masses) weights = asarray(masses)/mean(masses) rmsdmat[(i+1)*i/2+j] = rmsd(coords[i],coords[j],weights=weights) pbar_counter.value += 1 else: for i,j in trm_indeces(tasks[0],tasks[1]): summasses = sum(masses) subset_weights = asarray(subset_masses)/mean(subset_masses) com_i = average(subset_coords[i], axis=0, weights=subset_masses) translated_i = coords[i] - com_i subset1_coords = subset_coords[i] - com_i com_j = average(subset_coords[j], axis=0, weights=subset_masses) translated_j = coords[j] - com_j subset2_coords = subset_coords[j] - com_j rotamat = rotation_matrix(subset1_coords, subset2_coords, subset_weights)[0] rotated_i = transpose(dot(rotamat, transpose(translated_i))) rmsdmat[(i+1)*i/2+j] = PureRMSD(rotated_i.astype(float64), translated_j.astype(float64), coords[j].shape[0], masses, summasses) pbar_counter.value += 1
def metric(self, psf, dcd): u = MDAnalysis.Universe(psf, dcd) ref = MDAnalysis.Universe(self.get_pdb(psf)) s = self.get_selection(psf) data = [] for i, ts in enumerate(u.trajectory): self.log(i) alignto(u, ref, select="protein and name CA and not resid 271") rmsd_val = rmsd(u.select_atoms(s).positions, ref.select_atoms(s).positions, superposition=True) name = os.path.basename(dcd)[:-4].split('_') row = [i, rmsd_val, name[0], name[1], name[2]] # row format is [index, distance, run label] data.append(row) return data
def test_rmsd_matrix_without_superimposition(self, ens1): selection_string = "name CA" selection = ens1.select_atoms(selection_string) reference_rmsd = [] coordinates = ens1.trajectory.timeseries(selection, order='fac') for coord in coordinates: reference_rmsd.append(rms.rmsd(coordinates[0], coord, superposition=False)) confdist_matrix = encore.confdistmatrix.conformational_distance_matrix( ens1, encore.confdistmatrix.set_rmsd_matrix_elements, selection=selection_string, pairwise_align=False, weights='mass', n_jobs=1) print (repr(confdist_matrix.as_array()[0,:])) assert_almost_equal(confdist_matrix.as_array()[0,:], reference_rmsd, decimal=3, err_msg="calculated RMSD values differ from reference")
def alignto(mobile, reference, select="all", mass_weighted=False, subselection=None, tol_mass=0.1, strict=False): """Spatially align *mobile* to *reference* by doing a RMSD fit on *select* atoms. The superposition is done in the following way: 1. A rotation matrix is computed that minimizes the RMSD between the coordinates of `mobile.select_atoms(sel1)` and `reference.select_atoms(sel2)`; before the rotation, *mobile* is translated so that its center of geometry (or center of mass) coincides with the one of *reference*. (See below for explanation of how *sel1* and *sel2* are derived from *select*.) 2. All atoms in :class:`~MDAnalysis.core.AtomGroup.Universe` that contains *mobile* are shifted and rotated. (See below for how to change this behavior through the *subselection* keyword.) The *mobile* and *reference* atom groups can be constructed so that they already match atom by atom. In this case, *select* should be set to "all" (or ``None``) so that no further selections are applied to *mobile* and *reference*, therefore preserving the exact atom ordering (see :ref:`ordered-selections-label`). .. Warning:: The atom order for *mobile* and *reference* is *only* preserved when *select* is either "all" or ``None``. In any other case, a new selection will be made that will sort the resulting AtomGroup by index and therefore destroy the correspondence between the two groups. **It is safest not to mix ordered AtomGroups with selection strings.** :Arguments: *mobile* structure to be aligned, a :class:`~MDAnalysis.core.AtomGroup.AtomGroup` or a whole :class:`~MDAnalysis.core.AtomGroup.Universe` *reference* reference structure, a :class:`~MDAnalysis.core.AtomGroup.AtomGroup` or a whole :class:`~MDAnalysis.core.AtomGroup.Universe` *select* 1. any valid selection string for :meth:`~MDAnalysis.core.AtomGroup.AtomGroup.select_atoms` that produces identical selections in *mobile* and *reference*; or 2. dictionary ``{'mobile':sel1, 'reference':sel2}``. (the :func:`fasta2select` function returns such a dictionary based on a ClustalW_ or STAMP_ sequence alignment); or 3. 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`). *mass_weighted* : boolean ``True`` uses the masses :meth:`reference.masses` as weights for the RMSD fit. *tol_mass* Reject match if the atomic masses for matched atoms differ by more than *tol_mass* [0.1] *strict* ``True`` Will raise :exc:`SelectioError` if a single atom does not match between the two selections. ``False`` [default] Will try to prepare a matching selection by dropping residues with non-matching atoms. See :func:`get_matching_atoms` for details. *subselection* Apply the transformation only to this selection. ``None`` [default] Apply to `mobile.universe.atoms` (i.e. all atoms in the context of the selection from *mobile* such as the rest of a protein, ligands and the surrounding water) *selection-string* Apply to `mobile.select_atoms(selection-string)` :class:`~MDAnalysis.core.AtomGroup.AtomGroup` Apply to the arbitrary group of atoms :Returns: RMSD before and after spatial alignment. .. SeeAlso:: For RMSD-fitting trajectories it is more efficient to use :func:`rms_fit_trj`. .. versionchanged:: 0.8 Added check that the two groups describe the same atoms including the new *tol_mass* keyword. .. versionchanged:: 0.10.0 Uses :func:`get_matching_atoms` to work with incomplete selections and new *strict* keyword. The new default is to be lenient whereas the old behavior was the equivalent of *strict* = ``True``. """ if select in ('all', None): # keep the EXACT order in the input AtomGroups; select_atoms('all') # orders them by index, which can lead to wrong results if the user # has crafted mobile and reference to match atom by atom mobile_atoms = mobile.atoms ref_atoms = reference.atoms else: select = rms._process_selection(select) mobile_atoms = mobile.select_atoms(*select['mobile']) ref_atoms = reference.select_atoms(*select['reference']) ref_atoms, mobile_atoms = get_matching_atoms(ref_atoms, mobile_atoms, tol_mass=tol_mass, strict=strict) if mass_weighted: weights = ref_atoms.masses / np.mean(ref_atoms.masses) ref_com = ref_atoms.center_of_mass() mobile_com = mobile_atoms.center_of_mass() else: weights = None ref_com = ref_atoms.center_of_geometry() mobile_com = mobile_atoms.center_of_geometry() ref_coordinates = ref_atoms.positions - ref_com mobile_coordinates = mobile_atoms.positions - mobile_com old_rmsd = rms.rmsd(mobile_coordinates, ref_coordinates) R, new_rmsd = rotation_matrix(mobile_coordinates, ref_coordinates, weights=weights) if subselection is None: atoms = mobile.universe.atoms elif type(subselection) is str: atoms = mobile.select_atoms(subselection) else: try: atoms = subselection.atoms except AttributeError: raise TypeError("subselection must be a selection string, a AtomGroup or Universe or None") atoms.translate(-mobile_com) atoms.rotate(R) atoms.translate(ref_com) return old_rmsd, new_rmsd
def test_unequal_shape(): a = np.ones((4, 3)) b = np.ones((5, 3)) rms.rmsd(a, b)
def test_wrong_weights(self): w = np.ones(2) rms.rmsd(self.a, self.b, w)
def test_center(self): rmsd = rms.rmsd(self.a, self.b, center=True) assert_almost_equal(rmsd, 0.0)
def test_no_center(self): rmsd = rms.rmsd(self.a, self.b, center=False) assert_almost_equal(rmsd, 1.0)
def alignto(mobile, reference, select="all", weights=None, subselection=None, tol_mass=0.1, strict=False): """Perform a spatial superposition by minimizing the RMSD. Spatially align the group of atoms `mobile` to `reference` by doing a RMSD fit on `select` atoms. The superposition is done in the following way: 1. A rotation matrix is computed that minimizes the RMSD between the coordinates of `mobile.select_atoms(sel1)` and `reference.select_atoms(sel2)`; before the rotation, `mobile` is translated so that its center of geometry (or center of mass) coincides with the one of `reference`. (See below for explanation of how *sel1* and *sel2* are derived from `select`.) 2. All atoms in :class:`~MDAnalysis.core.universe.Universe` that contain `mobile` are shifted and rotated. (See below for how to change this behavior through the `subselection` keyword.) The `mobile` and `reference` atom groups can be constructed so that they already match atom by atom. In this case, `select` should be set to "all" (or ``None``) so that no further selections are applied to `mobile` and `reference`, therefore preserving the exact atom ordering (see :ref:`ordered-selections-label`). .. Warning:: The atom order for `mobile` and `reference` is *only* preserved when `select` is either "all" or ``None``. In any other case, a new selection will be made that will sort the resulting AtomGroup by index and therefore destroy the correspondence between the two groups. **It is safest not to mix ordered AtomGroups with selection strings.** Parameters ---------- mobile : Universe or AtomGroup structure to be aligned, a :class:`~MDAnalysis.core.groups.AtomGroup` or a whole :class:`~MDAnalysis.core.universe.Universe` reference : Universe or AtomGroup reference structure, a :class:`~MDAnalysis.core.groups.AtomGroup` or a whole :class:`~MDAnalysis.core.universe.Universe` select : str or dict or tuple (optional) The selection to operate on; can be one of: 1. any valid selection string for :meth:`~MDAnalysis.core.groups.AtomGroup.select_atoms` that produces identical selections in `mobile` and `reference`; or 2. a dictionary ``{'mobile': sel1, 'reference': sel2}`` where *sel1* and *sel2* are valid selection strings that are applied to `mobile` and `reference` respectively (the :func:`MDAnalysis.analysis.align.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 selection strings are applied to `atomgroup` and `reference` respectively and should generate *groups of equivalent atoms*. *sel1* and *sel2* can each also be a *list of selection strings* to generate a :class:`~MDAnalysis.core.groups.AtomGroup` with defined atom order as described under :ref:`ordered-selections-label`). weights : {"mass", ``None``} or array_like (optional) choose weights. With ``"mass"`` uses masses as weights; with ``None`` weigh each atom equally. If a float array of the same length as `mobile` is provided, use each element of the `array_like` as a weight for the corresponding atom in `mobile`. tol_mass: float (optional) Reject match if the atomic masses for matched atoms differ by more than `tol_mass`, default [0.1] strict: bool (optional) ``True`` Will raise :exc:`SelectionError` if a single atom does not match between the two selections. ``False`` [default] Will try to prepare a matching selection by dropping residues with non-matching atoms. See :func:`get_matching_atoms` for details. subselection : str or AtomGroup or None (optional) Apply the transformation only to this selection. ``None`` [default] Apply to ``mobile.universe.atoms`` (i.e., all atoms in the context of the selection from `mobile` such as the rest of a protein, ligands and the surrounding water) *selection-string* Apply to ``mobile.select_atoms(selection-string)`` :class:`~MDAnalysis.core.groups.AtomGroup` Apply to the arbitrary group of atoms Returns ------- old_rmsd : float RMSD before spatial alignment new_rmsd : float RMSD after spatial alignment See Also -------- AlignTraj: More efficient method for RMSD-fitting trajectories. .. _ClustalW: http://www.clustal.org/ .. _STAMP: http://www.compbio.dundee.ac.uk/manuals/stamp.4.2/ .. versionchanged:: 0.8 Added check that the two groups describe the same atoms including the new *tol_mass* keyword. .. versionchanged:: 0.10.0 Uses :func:`get_matching_atoms` to work with incomplete selections and new `strict` keyword. The new default is to be lenient whereas the old behavior was the equivalent of ``strict = True``. .. versionchanged:: 0.16.0 new general 'weights' kwarg replace `mass_weighted`, deprecated `mass_weighted` .. deprecated:: 0.16.0 Instead of ``mass_weighted=True`` use new ``weights='mass'`` .. versionchanged:: 0.17.0 Deprecated keyword `mass_weighted` was removed. """ if select in ('all', None): # keep the EXACT order in the input AtomGroups; select_atoms('all') # orders them by index, which can lead to wrong results if the user # has crafted mobile and reference to match atom by atom mobile_atoms = mobile.atoms ref_atoms = reference.atoms else: select = rms.process_selection(select) mobile_atoms = mobile.select_atoms(*select['mobile']) ref_atoms = reference.select_atoms(*select['reference']) ref_atoms, mobile_atoms = get_matching_atoms(ref_atoms, mobile_atoms, tol_mass=tol_mass, strict=strict) weights = get_weights(ref_atoms, weights) mobile_com = mobile_atoms.center(weights) ref_com = ref_atoms.center(weights) ref_coordinates = ref_atoms.positions - ref_com mobile_coordinates = mobile_atoms.positions - mobile_com old_rmsd = rms.rmsd(mobile_coordinates, ref_coordinates, weights) if subselection is None: # mobile_atoms is Universe mobile_atoms = mobile.universe.atoms elif isinstance(subselection, string_types): # select mobile_atoms from string mobile_atoms = mobile.select_atoms(subselection) else: try: # treat subselection as AtomGroup mobile_atoms = subselection.atoms except AttributeError: raise TypeError("subselection must be a selection string, an" " AtomGroup or Universe or None") # _fit_to DOES subtract center of mass, will provide proper min_rmsd mobile_atoms, new_rmsd = _fit_to(mobile_coordinates, ref_coordinates, mobile_atoms, mobile_com, ref_com, weights=weights) return old_rmsd, new_rmsd
def test_list(self): rmsd = rms.rmsd(self.a.tolist(), self.b.tolist(), center=False) assert_almost_equal(rmsd, 1.0)