def test_centering_broken_mol(): ref_struct_filepath = os.path.join(root_dir, 'test_data/ala_centered.gro') ref_top_filepath = os.path.join(root_dir, 'test_data/top.tpr') other_filepath = os.path.join(root_dir, 'test_data/ala_shifted_broken.gro') ref_univ = MDAnalysis.Universe(ref_top_filepath, ref_struct_filepath) other_univ = MDAnalysis.Universe(ref_top_filepath, other_filepath) center_mol(other_univ) np.testing.assert_array_almost_equal(ref_univ.atoms.positions, other_univ.atoms.positions, decimal=2)
def check_centering(ref_filepath, ref_toppath, other_glob): u_ref = MDAnalysis.Universe(ref_toppath, ref_filepath) ref_com = u_ref.select_atoms(sel_spec_nowall).center_of_mass() try: ref_close_atoms = u_ref.select_atoms('around {:.2f} ({})'.format( DIST_CUTOFF, sel_spec_nowall)) ref_pos = ref_close_atoms.positions except NoDataError: ref_close_atoms = None other_paths = glob.glob(other_glob) for other_filepath in other_paths: u_other = MDAnalysis.Universe(ref_toppath, other_filepath) # apply centering or rotating function center_mol(u_other) other_com = u_other.select_atoms(sel_spec_nowall).center_of_mass() err_msg = 'Center of masses of mol not equal within precision' np.testing.assert_array_almost_equal(ref_com, other_com, err_msg=err_msg, decimal=2) np.testing.assert_array_almost_equal( u_ref.select_atoms(sel_spec_nowall).positions, u_other.select_atoms(sel_spec_nowall).positions, decimal=2) if ref_close_atoms is not None: other_pos = u_other.atoms[ref_close_atoms.indices].positions rms = np.sqrt((np.sum((ref_pos - other_pos)**2, axis=1)).mean()) assert rms < RMSD_TOL, "RMSD ({}) is greater than tolerance ({}) for atoms within {:.2f} A".format( rms, RMSD_TOL, DIST_CUTOFF)
def test_align_prot_struct(): top_file_path = os.path.join(root_dir, 'test_data/ubiq/ubiq.tpr') ref_struct_path = os.path.join(root_dir, 'test_data/ubiq/ubiq_reference.gro') other_struct_path = os.path.join(root_dir, 'test_data/ubiq/ubiq_other.gro') ref_univ = MDAnalysis.Universe(top_file_path, ref_struct_path) other_univ = MDAnalysis.Universe(top_file_path, other_struct_path) center_mol(ref_univ) center_mol(other_univ) # Rotationally align according to all protein heavies rotate_mol(other_univ, ref_univ, mol_spec=sel_spec_heavies_nowall) ref_mol = ref_univ.select_atoms(sel_spec_heavies_nowall) other_mol = ref_univ.select_atoms(sel_spec_heavies_nowall) rms = np.sqrt( (np.sum((ref_mol.atoms.positions - other_mol.atoms.positions)**2, axis=1)).mean()) assert rms < 5.0, "RMSD ({}) is greater than {} A".format(rms)
def test_align_prot_after_shift(): top_file_path = os.path.join(root_dir, 'test_data/ubiq/ubiq.tpr') ref_struct_path = os.path.join(root_dir, 'test_data/ubiq/ubiq_reference.gro') ref_univ = MDAnalysis.Universe(top_file_path, ref_struct_path) center_mol(ref_univ) box = ref_univ.dimensions[:3] assert np.array_equal(ref_univ.dimensions[3:], np.ones(3) * 90), "Not a cubic box!" other_univ = MDAnalysis.Universe(top_file_path, ref_struct_path) center_mol(other_univ) com = other_univ.select_atoms(sel_spec_nowall).center_of_mass() # Rotate the system randomly rot_vector = np.random.random((3)) is_neg = np.random.random(3) > 0.5 rot_vector[is_neg] = -rot_vector[is_neg] degree_to_rot = np.random.random() * 360.0 curr_rot_mat = rotation_matrix(rot_vector, degree_to_rot) # Rotate about protein's COM init_positions = other_univ.atoms.positions - com new_positions = np.dot(init_positions, curr_rot_mat) + com other_univ.atoms.positions = new_positions # Shift all positions shift_vec = np.random.random((3)) shift_vec /= np.sqrt(np.sum(shift_vec**2)) is_neg = np.random.random(3) > 0.5 shift_vec[is_neg] = -shift_vec[is_neg] # Max shift of 10 A in any direction dist_to_shift = np.random.random() * 5.0 shift_vec *= dist_to_shift other_univ.atoms.positions += shift_vec # ...and apply pbc pbc(other_univ) ## No check we can retrieve original structure by centering # and fitting the protein's heavy atoms center_mol(other_univ) new_com = other_univ.select_atoms(sel_spec_nowall).center_of_mass() np.testing.assert_array_almost_equal(com, new_com, decimal=ARR_PREC_TIGHT) rotate_mol(ref_univ, other_univ, sel_spec_heavies_nowall) ref_mol = ref_univ.select_atoms(sel_spec_nowall) other_mol = other_univ.select_atoms(sel_spec_nowall) rmsd_mol = rmsd(ref_mol.positions, other_mol.positions) assert rmsd_mol < 1e-4 ## Make sure all waters within a reasonable distance of protein are still good ref_close_waters = ref_univ.select_atoms( 'name OW and around {:.1f} {}'.format(PROT_DIST_CUTOFF, sel_spec_nowall)) other_close_waters = other_univ.atoms[ref_close_waters.indices] assert ref_close_waters.n_atoms > 1000 rmsd_waters = rmsd(ref_close_waters.positions, other_close_waters.positions) assert rmsd_waters < 1e-4
def go(self): header_str = "fitspec: {}; rmsdspec: {}; fitspec_other: {}; rmsd_spec_other: {}".format( self.sel_spec, self.rmsd_spec, self.sel_spec_other, self.rmsd_spec_other) n_frames = self.last_frame - self.start_frame ndim = 2 if self.rmsd_spec is None else 3 self.rmsd_arr = np.zeros((self.n_frames, ndim)) self.ref_univ.atoms.write('fit_ref.gro') if self.rmsd_spec is not None: ref_struct = self.ref_univ.select_atoms(self.rmsd_spec) other_struct = self.other_univ.select_atoms(self.rmsd_spec_other) assert ref_struct.n_atoms == other_struct.n_atoms self.rms_per_atom = np.zeros((self.n_frames, ref_struct.n_atoms)) if self.do_traj: with MDAnalysis.Writer(self.outfile + ".xtc", self.other_univ.atoms.n_atoms) as W: for i_frame in range(self.start_frame, self.last_frame): if i_frame % 100 == 0: print("doing frame {} of {}".format( i_frame, self.last_frame)) sys.stdout.flush() curr_ts = self.other_univ.trajectory[i_frame] center_mol(self.other_univ, do_pbc=False) if not self.center_only: rms = rotate_mol(self.ref_univ, self.other_univ, ref_spec=self.sel_spec, other_spec=self.sel_spec_other) self.rmsd_arr[i_frame - self.start_frame, 0] = curr_ts.time self.rmsd_arr[i_frame - self.start_frame, 1] = rms if i_frame == self.start_frame: self.other_univ.atoms.write('first_frame_fit.gro') W.write(self.other_univ.atoms) if self.rmsd_spec is not None and not self.center_only: rms_other = rmsd(ref_struct.atoms.positions, other_struct.atoms.positions) self.rmsd_arr[i_frame - self.start_frame, 2] = rms_other self.rms_per_atom[i_frame - self.start_frame, :] = np.sqrt( np.sum( (ref_struct.atoms.positions - other_struct.atoms.positions )**2, axis=1)) else: center_mol(self.other_univ, do_pbc=False, check_broken=False) rms = rotate_mol(self.ref_univ, self.other_univ, ref_spec=self.sel_spec, other_spec=self.sel_spec_other) self.other_univ.atoms.write(self.outfile + ".gro") self.rmsd_arr[0, 0] = 0.0 self.rmsd_arr[0, 1] = rms if self.rmsd_spec is not None: rms_other = rmsd(ref_struct.atoms.positions, other_struct.atoms.positions) self.rmsd_arr[0, 2] = rms_other self.rms_per_atom[0, :] = np.sqrt( np.sum((ref_struct.atoms.positions - other_struct.atoms.positions)**2, axis=1)) if self.rmsd_spec is not None: avg_rms_per_atom = self.rms_per_atom.mean(axis=0) self.other_univ.add_TopologyAttr('tempfactors') other_struct.tempfactors = avg_rms_per_atom other_struct.write('fit_per_atom_rmsd.pdb', bonds=None) self.ref_univ.add_TopologyAttr('tempfactors') ref_struct.tempfactors = avg_rms_per_atom ref_struct.write('fit_ref_per_atom_rmsd.pdb', bonds=None) # Save output np.savetxt(self.rmsd_out, self.rmsd_arr, header=header_str) np.savez_compressed('rms_per_atom.dat', header=self.rmsd_spec, rms_per_atom=self.rms_per_atom)