def normalize_pts(pts1, pts2): #print pts1 A = pts1[:, 0:2] B = pts2[:, 0:2] assert len(A) == len(B) N = A.shape[0] # total points # find centroids centroid_A = rmsd.centroid(A) centroid_B = rmsd.centroid(B) # centre the points AA = A - centroid_A BB = B - centroid_B #get optimal rotation matrix R = rmsd.kabsch(AA, BB) # Apply transformation AA1 = np.dot(AA, R) angle1 = math.atan2(R[1][0], R[1][1]) #try flippin' it AA[:, 1] *= -1 #get optimal rotation matrix R = rmsd.kabsch(AA, BB) # Apply transformation AA2 = np.dot(AA, R)#get optimal rotation matrix angle2 = math.atan2(R[1][0], R[1][1]) #go with whichever one is better a2diff = np.abs(pts2[:,2]-(pts1[:,2]-angle2)) a1diff = np.abs(pts2[:,2]-(pts1[:,2]+angle1)) #angle differences are fun! for i in range(0, len(a1diff)): while (a2diff[i] > np.pi): a2diff[i] -= 2*np.pi while (a1diff[i] > np.pi): a1diff[i] -= 2*np.pi print np.degrees(a2diff), np.degrees(a1diff) if (np.sum(np.abs(a1diff)) > np.sum(np.abs(a2diff))): pts1[:, 0:2] = AA2 + centroid_B # rotate the rotations (backwards, since we mirrored the thing) pts1[:, 2] -= angle2 return rmsd.rmsd(AA2, BB) else: pts1[:, 0:2] = AA1 + centroid_B # rotate the rotations pts1[:, 2] += angle1 return rmsd.rmsd(AA1, BB)
def get_mappings(ref, structure): n = len(structure) cs = itertools.permutations(range(n), 3) keeps = {} for c in cs: Q = rmsd.kabsch(ref[:3], structure[list(c)]).T assert np.linalg.det(Q) > 0.5 rotated = np.dot(structure, Q.T) ds = scipy.spatial.distance.cdist(rotated, ref) _, res = scipy.optimize.linear_sum_assignment(ds) res = invert_array(res) obj = rmsd.rmsd(rotated[res], structure) if obj > 1E-3: continue key = tuple(res) if key not in keeps: keeps[key] = Q return keeps
def normalize_pts(self, pts1, pts2): #print pts1 A = pts1[:, 0:2] B = pts2[:, 0:2] assert len(A) == len(B) N = A.shape[0] # total points # find centroids centroid_A = rmsd.centroid(A) centroid_B = rmsd.centroid(B) # centre the points AA = A - centroid_A BB = B - centroid_B #get optimal rotation matrix R = rmsd.kabsch(AA, BB) # Apply transformation AA1 = np.dot(AA, R) angle1 = math.atan2(R[1][0], R[1][1]) pts1[:, 0:2] = AA1 + centroid_B # rotate the rotations pts1[:, 2] -= angle1 return rmsd.rmsd(AA1, BB)
def alin(A,B): A -= rmsd.centroid(A) B -= rmsd.centroid(B) #print (B) U = rmsd.kabsch(A, B) A = np.dot(A, U) return A, B, rmsd.rmsd(A,B)
def KabschTransform(MAT_B, MAT_R): C_road = rmsd.centroid(MAT_R) # centreroid of the road points C_back = rmsd.centroid(MAT_B) # centreroid of the back points XYZroad_centered = MAT_R - C_road #XYZ of road after centering XYZback_centered = MAT_B - C_back #XYZ of back after centering R = rmsd.kabsch( XYZroad_centered, XYZback_centered ) # the optimal rotation matrix to rotate road points to back coordinates return C_road, C_back, R
def get_transformation_matrix_kabsch(q, p): # compute centroids Pc = rmsd.centroid(p) Qc = rmsd.centroid(q) # Kabsch algorithm for estimating R and t T = np.identity(4) T[:3, :3] = rmsd.kabsch(p - Pc, q - Qc) T[:3, 3] = Pc - np.dot(T[:3, :3], Qc) return T
def crmsd_kabsch(A, B): # Translate A -= rmsd.centroid(A) B -= rmsd.centroid(B) # Rotate U = rmsd.kabsch(A, B) A = np.dot(A, U) return rmsd.rmsd(A, B)
def kabsch(pointsCurrent, pointsRef): C_curr = rmsd.centroid(pointsCurrent) C_ref = rmsd.centroid(pointsRef) points_curr_norm = pointsCurrent - C_curr # XYZ current after centering points_ref_norm = pointsRef - C_ref # the optimal rotation matrix to rotate XYZcurrent to XYZref R = rmsd.kabsch(points_curr_norm, points_ref_norm) return (R, C_curr, C_ref)
def test_kabash_algorith_pdb(): filename_1 = pathlib.PurePath(RESOURCE_PATH, "ci2_1.pdb") filename_2 = pathlib.PurePath(RESOURCE_PATH, "ci2_2.pdb") p_atoms, p_coord = rmsd.get_coordinates_pdb(filename_1) q_atoms, q_coord = rmsd.get_coordinates_pdb(filename_2) rotation_matrix = rmsd.kabsch(p_coord, q_coord) np.testing.assert_array_almost_equal([-0.5124, 0.8565, 0.0608], rotation_matrix[0], decimal=3)
def align(q_coord, p_coord): """ align q and p. return q coord rotated """ U = rmsd.kabsch(q_coord, p_coord) q_coord = np.dot(q_coord, U) return q_coord
def center_and_kabsch(P, Q): """ returns centroid of P, Q and a rotational matrix (in subsequent analyses, you may want to subtract centroidP/Q from your point sets) that minimizes RMSD between corresponding points in P and Q, *when applied to P* """ P = np.array(P) Q = np.array(Q) centroidP = rmsd.centroid(P) centroidQ = rmsd.centroid(Q) P = P - centroidP Q = Q - centroidQ return centroidP, centroidQ, rmsd.kabsch(P, Q)
def calculate_rmsd(mol_id, geometry_id1=None, geometry_id2=None, heavy_atoms_only=False): # These cause circular import errors if we put them at the top of the file from ._girder import GirderClient from ._calculation import GirderMolecule # Allow the user to pass in a GirderMolecule instead of an id if isinstance(mol_id, GirderMolecule): mol_id = mol_id._id if geometry_id1 is None: cjson1 = GirderClient().get('/molecules/%s/cjson' % mol_id) else: cjson1 = GirderClient().get('/molecules/%s/geometries/%s/cjson' % (mol_id, geometry_id1)) if geometry_id2 is None: cjson2 = GirderClient().get('/molecules/%s/cjson' % mol_id) else: cjson2 = GirderClient().get('/molecules/%s/geometries/%s/cjson' % (mol_id, geometry_id2)) coords1 = cjson1['atoms']['coords']['3d'] coords1_triplets = zip(coords1[0::3], coords1[1::3], coords1[2::3]) A = np.array([x for x in coords1_triplets]) coords2 = cjson2['atoms']['coords']['3d'] coords2_triplets = zip(coords2[0::3], coords2[1::3], coords2[2::3]) B = np.array([x for x in coords2_triplets]) if heavy_atoms_only: atomic_numbers = cjson1['atoms']['elements']['number'] heavy_indices = [i for i, n in enumerate(atomic_numbers) if n != 1] A = A.take(heavy_indices, 0) B = B.take(heavy_indices, 0) # Translate A -= rmsd.centroid(A) B -= rmsd.centroid(B) # Rotate U = rmsd.kabsch(A, B) A = np.dot(A, U) return rmsd.rmsd(A, B)
def xyz4a_position(i, lines): template1 = np.array([[-0.93454, 0.91954, 1.11786], [-0.01675, 0.03488, 0.58954], [1.10621, 0.72253, -0.004], [1.6148, 1.14817, -0.57075]]) template2 = np.array([[-0.93454, 0.91954, 1.11786], [-0.01675, 0.03488, 0.58954], [1.10621, 0.72253, -0.004], [1.6148, 1.14817, -0.57075], [-0.64719, -0.82998, -0.40926], [-1.12252, -1.99515, -0.72338]]) amino_acid_position = [] for k in range(i, i + 4, 1): try: x = lines[k][30:38] y = lines[k][38:46] z = lines[k][46:54] amino_acid_position.append(np.asarray([x, y, z], dtype=float)) except: sys.exit( "Error parsing input for the following line: \n{0:s}".format( lines[k])) amino_acid_position = np.asarray(amino_acid_position) #print amino_acid_position a_acid_p = amino_acid_position - rmsd.centroid(amino_acid_position) template1 -= rmsd.centroid(template1) #centroid P2 into f template2 = template2 - rmsd.centroid(template2) #for debug print '*************8888888888888888' #print template1.shape#(4,3) #print a_acid_p.shape#(5,3) #print template2.shape#(6.3) rot = rmsd.kabsch(template1, a_acid_p) #pp is the rotated martix,Rotate matrix P2 unto Q new_position = np.dot(template2, rot) #translation the P2 into initial position after rotation new_position += rmsd.centroid(amino_acid_position) C = new_position.tolist() #print new_position #print lenthg #for n in range(0,6,1): position5 = ('%8s' % str(float('%.3f' % C[4][0]))) + ('%8s' % str( float('%.3f' % C[4][1]))) + ('%8s' % str(float('%.3f' % C[4][2]))) position6 = ('%8s' % str(float('%.3f' % C[5][0]))) + ('%8s' % str( float('%.3f' % C[5][1]))) + ('%8s' % str(float('%.3f' % C[5][2]))) print 'print the position of position 5 and position 6' return position5, position6
def getkabschangle(Ac, Bc): # Ac = Ac[:,0:3:2] # Bc = Bc[:,0:3:2] # Manipulate A = Ac - rmsd.centroid(Ac) B = Bc - rmsd.centroid(Bc) U = rmsd.kabsch(A, B) # print(U) degvals = (rotationMatrixToEulerAngles(U)) return degvals[1] """
def save_results(mol, results, filename): # make rdkit conformers energies = [x[4] for x in results] energies = np.array(energies) sortidx = np.argsort(energies) N_atoms = mol.GetNumAtoms() atoms = mol.GetAtoms() atoms = [atom.GetSymbol() for atom in atoms] coordinates_list = [] no_hydrogen = np.array([2, 5, 6]) no_hydrogen -= 1 for idx in sortidx: result = results[idx] coord = result[-1] coord = np.array(coord) coord = coord.reshape((N_atoms, 3)) coord -= rmsd.centroid(coord[no_hydrogen]) coordinates_list.append(coord) out = [] # atoms = np.array(atoms) # no_hydrogen = np.where(atoms != 'H') for i, coord in enumerate(coordinates_list[1:]): U = rmsd.kabsch(coord[no_hydrogen], coordinates_list[0][no_hydrogen]) coord = np.dot(coord, U) strxyz = rmsd.set_coordinates(atoms, coord) out += [strxyz] f = open(filename, 'w') f.write("\n".join(out)) f.close() return
def calc_rmsd(coords1, coords2): """Calculate root-mean square deviation. Parameters ---------- coords1 : list(list(str,int,int,int)) The coordinates for the first molecule (conformer). coords2 : list(list(str,int,int,int)) The coordinates for the second molecule (conformer). Notes ----- The coordinates are given as follows: atom name, x coord, y coord, z coord Example for carbon monoxide: [[C, 0.0, 0.0, 0.0],[O, 1.0, 0.0, 0.0]] The distances are in Angstroms. Returns ------- rmsd : float The rmsd between two molecular geometries. This rmsd is calculated after applying centering and a rotation matrix (calculated via the Kabsch algorithm). """ # trivial check assert len(coords1) == len(coords2) # first turn lists into numpy arrays (otherwise # cannot perform some rmsd operations) # and excise atom names (not needed for rmsd) mol1 = np.array([[coords1[i][1], coords1[i][2], coords1[i][3]] for i in range(len(coords1))]) mol2 = np.array([[coords2[i][1], coords2[i][2], coords2[i][3]] for i in range(len(coords2))]) # first center each molecule mol1 -= rmsd.centroid(mol1) mol2 -= rmsd.centroid(mol2) # calculate the rotation matrix rot_matrix = rmsd.kabsch(mol1, mol2) # apply the rotation matrix mol1 = np.dot(mol1, rot_matrix) # finally get the rmsd return rmsd.rmsd(mol1, mol2)
def align_coordinates(coordinates): # Align everything to first coordinate coordinates = copy.deepcopy(coordinates) coordinate_ref = coordinates[0] coordinate_ref -= rmsd.centroid(coordinate_ref) coordinates[0] = coordinate_ref for i, coordinate in enumerate(coordinates[1:]): coordinate -= rmsd.centroid(coordinate) U = rmsd.kabsch(coordinate, coordinate_ref) coordinate = np.dot(coordinate, U) coordinates[i] = coordinate return coordinates
def calculate_transformation_kabsch( src_points: np.ndarray, dst_points: np.ndarray) -> Tuple[np.array, float]: """ Calculates the optimal rigid transformation from src_points to dst_points (regarding the least squares error) Parameters: ----------- src_points: array (3,N) matrix dst_points: array (3,N) matrix Returns: ----------- rotation_matrix: array (3,3) matrix translation_vector: array (3,1) matrix rmsd_value: float """ assert src_points.shape == dst_points.shape if src_points.shape[0] != 3: raise Exception( "The input data matrix had to be transposed in order to compute transformation." ) src_points = src_points.transpose() dst_points = dst_points.transpose() src_points_centered = src_points - rmsd.centroid(src_points) dst_points_centered = dst_points - rmsd.centroid(dst_points) rotation_matrix = rmsd.kabsch(src_points_centered, dst_points_centered) rmsd_value = rmsd.kabsch_rmsd(src_points_centered, dst_points_centered) translation_vector = rmsd.centroid(dst_points) - np.matmul( rmsd.centroid(src_points), rotation_matrix) return create_homogenous(rotation_matrix.transpose(), translation_vector.transpose()), rmsd_value
def find_rotation_matrix(ax, ay, az, imu_ax, imu_ay, imu_az): print("Finding rotation matrix...") rx = 0 ry = 0 rz = 0 diff_a = [] imu_a = [] # Kabsch algorithm setup for i in range(np.minimum(len(ax), len(imu_ax))): diff_a.append([ax[i] / 9.81, ay[i] / 9.81, az[i] / 9.81]) for i in range(np.minimum(len(ax), len(imu_ax))): imu_a.append([imu_ax[i], imu_ay[i], imu_az[i]]) diff_a = np.array(diff_a) imu_a = np.array(imu_a) print("Rotation matrix: ", rmsd.kabsch(diff_a, imu_a)) print("RMSD: ", rmsd.kabsch_rmsd(diff_a, imu_a)) # diff_a -= rmsd.centroid(diff_a) # imu_a -= rmsd.centroid(imu_a) # print("Rotation matrix after translation: ", rmsd.kabsch(diff_a, imu_a)) # print("RMSD after translation: ", rmsd.kabsch_rmsd(diff_a, imu_a)) rotated_a = rmsd.kabsch_rotate(diff_a, imu_a) r_ax = [] r_ay = [] r_az = [] for i in range(len(rotated_a)): r_ax.append(rotated_a[i][0]) r_ay.append(rotated_a[i][1]) r_az.append(rotated_a[i][2]) x_axis = np.array(range(len(r_ax))) plt.figure(5) plt.title("Rotated Differentiated Acceleration") plt.plot(x_axis, r_ax, label='x', color='red') plt.plot(x_axis, r_ay, label='y', color='green') plt.plot(x_axis, r_az, label='z', color='blue') plt.legend()
def normalize_pts_old(pts1, pts2, win): #print pts1 A = pts1[:, 0:2] B = pts2[:, 0:2] assert len(A) == len(B) N = A.shape[0] # total points # find centroids centroid_A = rmsd.centroid(A) centroid_B = rmsd.centroid(B) # centre the points AA = A - centroid_A BB = B - centroid_B #get optimal rotation matrix R = rmsd.kabsch(AA, BB) # Apply transformation AA1 = np.dot(AA, R) angle1 = math.atan2(R[1][0], R[1][1]) i=0 for pt in pts1: pt_graphics = Point(int(pt[0]-centroid_A[0]+centroid_B[0]), int(pt[1]-centroid_A[1]+centroid_B[1])) cir = Circle(pt_graphics, 8) cir.setOutline('green') cir.draw(win) line = Line(pt_graphics, Point(pt_graphics.x+8*np.cos(-pt[2]), pt_graphics.y+8*np.sin(-pt[2]))) line.draw(win) text = Text(pt_graphics, str(i)) i += 1 text.draw(win) pts1[:, 0:2] = AA1 + centroid_B # rotate the rotations pts1[:, 2] -= angle1 return rmsd.rmsd(AA1, BB)
def calc_rmsd(self): """ Calculate normal, translated, and rotated RMSD. """ tmp_1, tmp_2 = self.coord_1.copy(), self.coord_2.copy() self.rmsd_normal = rmsd.rmsd(self.coord_1, self.coord_2) # Manipulate recenter self.coord_1 -= rmsd.centroid(self.coord_1) self.coord_2 -= rmsd.centroid(self.coord_2) self.rmsd_translate = rmsd.rmsd(self.coord_1, self.coord_2) # Rotate rotation_matrix = rmsd.kabsch(self.coord_1, self.coord_2) self.coord_1 = np.dot(self.coord_1, rotation_matrix) self.rmsd_rotate = rmsd.rmsd(self.coord_1, self.coord_2) self.coord_1, self.coord_2 = tmp_1, tmp_2
def kabschangleVisual(A, B): # Manipulate #A = A[:, 0:3:2] #B = B[:, 0:3:2] print(A) print(B) print("RMSD", geterror(A, B)) save_plot(A, B, "plot_beginning") A -= rmsd.centroid(A) B -= rmsd.centroid(B) print("Translated RMSD", geterror(A, B)) save_plot(A, B, "plot_translated") U = rmsd.kabsch(A, B) print("Rotation Matrix") print(U) print("Angle") #val = math.acos(U[0][0]) #print(U[0][0]) #if(abs(val) <=1): # deg = math.acos(U[0][0]) / 3.14 * 180 #else: # print("OIII GOT ERROR SIAL") # deg = 0 degvals = (rotationMatrixToEulerAngles(U)) print("The degree") print(degvals[1]) #print(deg) #A = np.dot(A, U) print("Rotated RMSD", geterror(A, B)) save_plot(A, B, "plot_rotated")
def align_structures(structures: np.array, indexes=None): ''' Aligns molecules of a structure array (shape is (n_structures, n_atoms, 3)) to the first one, based on the indexes. If not provided, all atoms are used to get the best alignment. Return is the aligned array. ''' reference = structures[0] targets = structures[1:] if isinstance(indexes, (list, tuple)): indexes = np.array(indexes) indexes = slice(0, len(reference)) if indexes is None or len( indexes) == 0 else indexes.ravel() reference -= np.mean(reference[indexes], axis=0) for t, _ in enumerate(targets): targets[t] -= np.mean(targets[t, indexes], axis=0) output = np.zeros(structures.shape) output[0] = reference for t, target in enumerate(targets): try: matrix = kabsch(reference[indexes], target[indexes]) except LinAlgError: # it is actually possible for the kabsch alg not to converge matrix = np.eye(3) # output[t+1] = np.array([matrix @ vector for vector in target]) output[t + 1] = (matrix @ target.T).T return output
commonData[i] -= centroidPos centroidData.append(centroidPos) # calculate pairwise deviation and rotate deviations = np.empty((numOfLoci, 0), float) for i in range(numOfStructures): for j in range(numOfStructures): if j == i: continue # mirror image if needed mirrorFactor = 1.0 if rmsd.kabsch_rmsd(commonData[i], commonData[j]) > rmsd.kabsch_rmsd( commonData[i], -1.0 * commonData[j]): mirrorFactor = -1.0 # calculate deviation rotationMatrix = rmsd.kabsch(mirrorFactor * commonData[j], commonData[i]) if j > i: deviation = np.linalg.norm( np.dot(mirrorFactor * commonData[j], rotationMatrix) - commonData[i], axis=1).T deviations = np.c_[deviations, deviation] sys.stderr.write('median deviation between ' + str(i) + ' and ' + str(j) + ': ' + str(np.median(deviation)) + '\n') # rotate j to align with i sys.stderr.write('aligning ' + str(j) + ' to ' + str(i) + '\n') alignedFilename = "aligned_" + str(j) + "_to_" + str(i) + ".3dg" alignedFile = open(alignedFilename, "wb") for inputLocus in inputData[j]: #sys.stderr.write("locus: "+str(inputLocus)+"\n") #sys.stderr.write("old: "+str(np.array(inputData[j][inputLocus]))+"\n")
#B = np.append(B, extra, axis = 0) B += random.uniform(-10, 10) #np.random.shuffle(B) #A, B = generate_set(A, B) plot3d(A, B) print("Normal RMSD", rmsd.rmsd(A, B)) # Manipulate A -= rmsd.centroid(A) B -= rmsd.centroid(B) plot3d(A, B) print("Translated RMSD", rmsd.rmsd(A, B)) markA = A[0:3, :] markB = B[0:3, :] U = rmsd.kabsch(markA, markB) A = np.dot(A, U) plot3d(A, B) print("Rotated RMSD", rmsd.rmsd(A, B)) #data projection d = 12 unit = 0.01 maxindex = int(d / unit) Aindex = np.floor(A / unit) Bindex = np.floor(B / unit) Aindex -= np.min(Aindex) Bindex -= np.min(Bindex) Axy = Aindex[:, 0:2] Bxy = Bindex[:, 0:2]
def get_angle(vecs1, vecs2): """Returns rotation angle between two vector sets, representing inverse lattices""" # https://en.wikipedia.org/wiki/Rotation_matrix#Determining_the_angle return np.rad2deg(np.arccos((np.trace(rmsd.kabsch(vecs1, vecs2)) - 1) / 2))
[2.0, 1.5]]) # Same "molecule" B = np.array([[1.0, 1.0], [1.0, 2.0], [2.0, 1.5]]) B *= 1.4 # Translate B -= 3 # Rotate B = np.dot(B, rotation_matrix(90)) print("Normal RMSD", rmsd.rmsd(A, B)) save_plot(A, B, "plot_beginning.png") # Manipulate A -= rmsd.centroid(A) B -= rmsd.centroid(B) print("Centered RMSD", rmsd.rmsd(A, B)) save_plot(A, B, "plot_centered.png") U = rmsd.kabsch(A, B) A = np.dot(A, U) print("Translated RMSD", rmsd.rmsd(A, B)) save_plot(A, B, "plot_translated.png")
def calculate_head_COM(file, output_folder): f_cam = 1000 n_tags = 23 no_subj = 1 pose_all = np.empty((no_subj), dtype=object) mesh_all = np.empty((no_subj), dtype=object) suct = 0 print('Calculating center of mass on file', file) for i in np.array([1]): # files in os.listdir(path_loc): file_path = file f = open(file_path) csv_f = csv.reader(f, delimiter='\t') new_frame = np.empty((23, 7, 1)) new_frame[:] = np.NAN full_array = new_frame.copy() count = -1 for row in csv_f: row = row[1:] if (count == -1): count = count+1 elif (row[1] == str(NULL_MARKER)): full_array = np.append(full_array, new_frame, axis=2) count = count+1 else: if (int(row[0]) < 23): read_array = np.asarray(row[2:]).astype(np.float) quart = Quaternion(matrix=rf.eul2mat(read_array[4:])) full_array[int(row[0]), :, count] = np.concatenate( (np.array([-read_array[2], read_array[3], -read_array[1]]), quart.elements), axis=0) full_array = full_array[:, :, :-1] f.close() pose_all[suct] = full_array suct += 1 final_ori = np.zeros((full_array.shape[2], full_array.shape[1])) cur_fullmesh = np.empty((n_tags*4, 3, full_array.shape[2])) cur_fullmesh[:] = np.NaN mesh_visible = np.empty((n_tags*4, 3, full_array.shape[2])) mesh_visible[:] = np.NaN vismesh_px = np.empty((n_tags*4, 2, full_array.shape[2])) vismesh_px[:] = np.NaN fullmesh_px = np.empty((n_tags*4, 2, full_array.shape[2])) fullmesh_px[:] = np.NaN err_dist = np.zeros((full_array.shape[2], 1)) avg_mesh = np.load("./visualize_2/mesh_calib.npy") for f_ct in range(0, full_array.shape[2]): cur_mesh = np.empty((n_tags*4, 3)) cur_mesh[:] = np.NaN for tag_ct in range(0, n_tags): cur_mesh[tag_ct*4:(tag_ct+1)*4, :] = rf.orient_square( full_array[tag_ct, 0:3, f_ct], Quaternion(full_array[tag_ct, 3:, f_ct])) while True: mesh1 = avg_mesh[(~np.isnan(cur_mesh[:, 1])), :] mesh2 = cur_mesh[(~np.isnan(cur_mesh[:, 1])), :] m1c = rmsd.centroid(mesh1) m2c = rmsd.centroid(mesh2) mesh1 -= m1c mesh2 -= m2c rot2_1 = rmsd.kabsch(mesh1, mesh2) cur_fullmesh[:, :, f_ct] = np.dot(avg_mesh - m1c, rot2_1) + m2c # if f_ct >= 2: # cur_fullmesh[:,:,f_ct] = np.nansum((0.5*cur_fullmesh[:,:,f_ct],0.3*cur_fullmesh[:,:,f_ct-1],0.2*cur_fullmesh[:,:,f_ct-2]),axis = 0) err = np.linalg.norm( cur_fullmesh[:, :, f_ct] - cur_mesh, axis=1) if mesh1.shape[0] == 0: break if np.partition(err, 3)[3] > 0.005: break elif (np.nanmean(err) < 0.005): break cur_mesh[np.nanargmax(err), :] = np.array( [np.nan, np.nan, np.nan]) final_ori[f_ct, 0:3] = rmsd.centroid(cur_fullmesh[:, :, f_ct]) final_ori[f_ct, 3:] = Quaternion(matrix=rot2_1).elements # mesh_visible[(~np.isnan(cur_mesh[:,1])),:] = cur_fullmesh[(~np.isnan(cur_mesh[:,1])),:] vismesh_px[:, 0, f_ct] = 960 - \ (cur_mesh[:, 0]/cur_mesh[:, 2]*f_cam) vismesh_px[:, 1, f_ct] = 540 + \ (cur_mesh[:, 1]/cur_mesh[:, 2]*f_cam) fullmesh_px[:, 0, f_ct] = 960 - \ (cur_fullmesh[:, 0, f_ct]/cur_fullmesh[:, 2, f_ct]*f_cam) fullmesh_px[:, 1, f_ct] = 540 + \ (cur_fullmesh[:, 1, f_ct]/cur_fullmesh[:, 2, f_ct]*f_cam) err_dist[f_ct] = np.nanmean(np.linalg.norm( cur_fullmesh[:, :, f_ct] - cur_mesh, axis=1)) if np.size(mesh2, axis=0) <= 12: err_dist[f_ct] = 1 loc = rmsd.centroid(cur_fullmesh) #pose_all[suct] = final_ori #mesh_all[suct] = fullmesh_px suct = suct+1 print(suct) axis_px = np.empty((4, 2, full_array.shape[2])) axis_px[:] = np.NaN for ct in range(0, full_array.shape[2]): rot_mat = Quaternion(np.array( [final_ori[ct, 3], final_ori[ct, 4], final_ori[ct, 5], final_ori[ct, 6]])).rotation_matrix/25 ax = np.c_[rot_mat, final_ori[ct, 0:3]] ax_ad = ax.copy() for row in range(3): ax_ad[:, row] = ax[:, row] + final_ori[ct, 0:3] axis_px[:, 0, ct] = 960 - (ax_ad[0, :]/ax_ad[2, :]*f_cam) axis_px[:, 1, ct] = 540 + (ax_ad[1, :]/ax_ad[2, :]*f_cam) axis_px1 = np.empty((4, 2, full_array.shape[2])) axis_px1[:] = np.NaN for ct in range(0, full_array.shape[2]): rot_mat = Quaternion(np.array( [final_ori[ct, 6], final_ori[ct, 5], final_ori[ct, 4], final_ori[ct, 3]])).rotation_matrix/25 ax = np.c_[rot_mat, final_ori[ct, 0:3]] ax_ad = ax.copy() for row in range(3): ax_ad[:, row] = ax[:, row] + final_ori[ct, 0:3] axis_px1[:, 0, ct] = 960 - (ax_ad[0, :]/ax_ad[2, :]*f_cam) axis_px1[:, 1, ct] = 540 + (ax_ad[1, :]/ax_ad[2, :]*f_cam) # sio.savemat('meshsave_back_2.mat',{'vismesh_px':vismesh_px,'mesh_all':fullmesh_px,'pose_all':pose_all[1],'axis_px':axis_px,'axis_px1':axis_px1}) sio.savemat('meshsave_back_2.mat', {'vismesh_px': vismesh_px, 'mesh_all': fullmesh_px, 'pose_all': final_ori, 'axis_px': axis_px, 'axis_px1': axis_px1})
def align(argv): # default parameters output_prefix = None # read arguments try: opts, args = getopt.getopt(argv[1:], "o:") except getopt.GetoptError as err: sys.stderr.write("[E::" + __name__ + "] unknown command\n") return 1 if len(args) == 0: sys.stderr.write( "Usage: dip-c align [options] <in1.3dg> <in2.3dg> ...\n") sys.stderr.write("Options:\n") sys.stderr.write(" -o STR output prefix [no output]\n") sys.stderr.write("Output:\n") sys.stderr.write(" tab-delimited: homolog, locus, RMSD\n") sys.stderr.write( " additionally with \"-o\": 3DG files aligned to each other\n") return 1 for o, a in opts: if o == "-o": output_prefix = a # load 3dg files input_data = [] num_structures = len(args) if num_structures < 2: sys.stderr.write("[E::" + __name__ + "] at least 2 structures are required\n") return 1 counter = 0 for input_filename in args: sys.stderr.write("[M::" + __name__ + "] reading 3dg file " + str(counter) + ": " + input_filename + "\n") input_data.append({}) for input_file_line in open(input_filename, "rb"): input_file_line_data = input_file_line.strip().split() input_data[-1][(input_file_line_data[0], int(input_file_line_data[1]))] = [ float(input_file_line_data[2]), float(input_file_line_data[3]), float(input_file_line_data[4]) ] counter += 1 # find common particles common_loci = set(input_data[0]) for input_structure in input_data[1:]: common_loci = common_loci.intersection(set(input_structure)) num_loci = len(common_loci) common_loci = list(common_loci) common_data = [] for input_structure in input_data: common_data.append([]) for common_locus in common_loci: common_data[-1].append(input_structure[common_locus]) sys.stderr.write("[M::" + __name__ + "] found " + str(num_loci) + " common particles\n") # subtract centroid common_data = np.array(common_data) centroid_data = [] for i in range(num_structures): common_data[i] = np.array(common_data[i]) centroid_pos = rmsd.centroid(common_data[i]) common_data[i] -= centroid_pos centroid_data.append(centroid_pos) sys.stderr.write("[M::" + __name__ + "] found centroids for " + str(num_structures) + " structures\n") # calculate pairwise deviation and rotate deviations = np.empty((num_loci, 0), float) for i in range(num_structures): for j in range(num_structures): if j == i: continue # mirror image if needed mirror_factor = 1.0 if rmsd.kabsch_rmsd(common_data[i], common_data[j]) > rmsd.kabsch_rmsd( common_data[i], -1.0 * common_data[j]): mirror_factor = -1.0 # calculate deviation rotation_matrix = rmsd.kabsch(mirror_factor * common_data[j], common_data[i]) if j > i: deviation = np.linalg.norm( np.dot(mirror_factor * common_data[j], rotation_matrix) - common_data[i], axis=1).T deviations = np.c_[deviations, deviation] sys.stderr.write("[M::" + __name__ + "] median deviation between file " + str(i) + " and file " + str(j) + ": " + str(np.median(deviation)) + "\n") # rotate if output_prefix is not None: # rotate j to align with i sys.stderr.write("[M::" + __name__ + "] aligning file " + str(j) + " to file " + str(i) + "\n") aligned_filename = output_prefix + str(j) + "_to_" + str( i) + ".3dg" aligned_file = open(aligned_filename, "wb") for input_locus in input_data[j]: aligned_pos = np.dot( (np.array(input_data[j][input_locus]) - centroid_data[j]) * mirror_factor, rotation_matrix) + centroid_data[i] aligned_file.write("\t".join([ input_locus[0], str(input_locus[1]), str(aligned_pos[0]), str(aligned_pos[1]), str(aligned_pos[2]) ]) + "\n") aligned_file.close() # summarize rmsd and print rmsds = np.sqrt((deviations**2).mean(axis=1)) totalrmsd = np.sqrt((rmsds**2).mean(axis=0)) sys.stderr.write("[M::" + __name__ + "] RMS RMSD: " + str(totalrmsd) + "\n") sys.stderr.write("[M::" + __name__ + "] median RMSD: " + str(np.median(rmsds, axis=0)) + "\n") sys.stderr.write("[M::" + __name__ + "] writing output\n") for i in range(num_loci): sys.stdout.write("\t".join( map(str, [common_loci[i][0], common_loci[i][1], rmsds[i]])) + "\n") return 0
def run(self, r1: SetOfResidues, r2: SetOfResidues, get_centered_c_alpha_coords: GetCenteredCAlphaCoords): P, Q = map(get_centered_c_alpha_coords, (r1, r2)) return rmsd.kabsch(P, Q)
def run(self, s1d1: SetOfResidues, s1d2: SetOfResidues, s2d1: SetOfResidues, s2d2: SetOfResidues, get_c_alpha_coords: GetCAlphaCoords, get_centroid: GetCentroid, get_rotation_matrix: GetRotationMatrix) -> (float, float): """ :param s1d1: a domain in the first structure :param s1d2: another domain in the first structure :param s2d1: a domain in the second structure corresponding to s1d1 domain (same length required) :param s2d2: a domain in the second structure corresponding to s1d2 domain (same length required) :return: tuple of angle (non-negative -- absolute value) and translation (again non-negative). Angle (movement of a domain between the structures) and translation -> in the direction of the rotation axis """ # superimpose s2d1 on s1d1 (correspoding domains, 1st domain chosen arbitrarily), taking s2d2 along with it # -> translate and rotate # superimpose the moved s2d2 on s1d2, remember translation+rotation. Decompose translation+rotation into rotation along a single # axis somewhere in space + translation along that axis. (screw motion). # axis direction: 1 eigenvector of rot. matrix. Translation along that axis: subtract from translation it's projection # to screw axis _|_ space (P_s_|_). # [ In case we would need the location of the screw axis: the projection P_s_|_ is the length of # the chord line (how the centroid rotated along the positioned screw axis). I know the rot. angle, so the location of screw axis is # at two possible positions, above and below the chord line, however the angle sign should solve this # r = chord/(2 * sin(angle/2)), compute triangle height <r,chord,r> and multiply by that a unit vector perpendiculat to the chord, # and in the rotation plane. This will be the candidate (one of two, see the angle sign) for the screw axis location. # (A point lying on the axis). ] # superimpose the two structures by their first domain U = get_rotation_matrix(s2d1, s1d1) s1d2_coords = get_c_alpha_coords(s1d2) fixed_s2d2_coords = np.matmul( get_c_alpha_coords(s2d2) - get_centroid(s2d1), U) + get_centroid(s1d1) # compare d2 coords fixed_s2d2_coords_centroid = fixed_s2d2_coords.mean(axis=0) d2_rotation_m = rmsd.kabsch( fixed_s2d2_coords - fixed_s2d2_coords_centroid, s1d2_coords - get_centroid(s1d2)) d2_translation = get_centroid(s1d2) - fixed_s2d2_coords_centroid # calculate return values angle = np.arccos((np.trace(d2_rotation_m) - 1) / 2) # formula tr(Rot_matrix) = 1 + 2cos(angle) rotation_axis_plane = d2_rotation_m - np.eye( 3 ) # rotation axis is the normal of that plane, row/col vectors generate the plane axis = np.cross( rotation_axis_plane[:, 0], rotation_axis_plane[:, 1]) # a vector in the direction of the axis # (result of cross product is perpendicular to both vectors, these are in rotation_axis_plane) https://math.stackexchange.com/q/2074316/331963 axis = axis / np.linalg.norm(axis) # make it a unit vector # translation projected into the rotation axis (get the translation component of a screw motion) translation_in_axis = np.dot(d2_translation, axis) # it could also be possible to calculate here the location of rotation axis --> so we would have the complete screw description # of the domain movement, see [ ] above return ScrewMotionResult(abs(angle), abs(translation_in_axis), float(np.linalg.norm(d2_translation)))