def octa_and_face(ao, co, save="not_save"): """ Display 3D structure of octahedral complex with 8 faces. Parameters ---------- ao : list Atomic labels of octahedral structure. co : list Atomic coordinates of octahedral structure. save : str Name of image file to save. If this argument is not set by user, do not save a figure as image. Returns ------- None : None """ fig = plt.figure() ax = Axes3D(fig) # Plot atoms for i in range(len(co)): # Determine atomic number n = elements.check_atom(ao[i]) ax.scatter(co[i][0], co[i][1], co[i][2], marker='o', linewidths=0.5, edgecolors='black', color=elements.check_color(n), label=f"{ao[i]}", s=elements.check_radii(n) * 300) # Draw 8 faces # Get atomic coordinates of octahedron _, c_ref, _, _ = tools.find_faces_octa(co) # Create array of vertices for 8 faces vertices_list = [] for i in range(8): get_vertices = c_ref[i].tolist() x, y, z = zip(*get_vertices) vertices = [list(zip(x, y, z))] vertices_list.append(vertices) # Added faces color_list = [ "red", "blue", "green", "yellow", "violet", "cyan", "brown", "grey" ] for i in range(len(vertices_list)): ax.add_collection3d( Poly3DCollection(vertices_list[i], alpha=0.5, color=color_list[i])) # Draw line for i in range(1, len(co)): merge = list(zip(co[0], co[i])) x, y, z = merge ax.plot(x, y, z, 'k-', color="black", linewidth=2) # Set legend # Remove duplicate labels in legend. # Ref.https://stackoverflow.com/a/26550501/6596684 handles, labels = ax.get_legend_handles_labels() handle_list, label_list = [], [] for handle, label in zip(handles, labels): if label not in label_list: handle_list.append(handle) label_list.append(label) leg = plt.legend(handle_list, label_list, loc="lower left", scatterpoints=1, fontsize=12) # Fixed size of point in legend # Ref. https://stackoverflow.com/a/24707567/6596684 for i in range(len(leg.legendHandles)): leg.legendHandles[i]._sizes = [90] # Set axis ax.set_xlabel(r'X', fontsize=15) ax.set_ylabel(r'Y', fontsize=15) ax.set_zlabel(r'Z', fontsize=15) ax.set_title('Octahedral structure with faces', fontsize="12") ax.grid(True) # plt.axis('equal') if save != "not_save": plt.savefig('{0}.png'.format(save)) plt.show()
def all_atom(fal, fcl, save="not_save"): """ Display 3D structure of octahedral complex with label for each atoms. Parameters ---------- fal : list Atomic labels of full complex. fcl : list Atomic coordinates of full complex. save : str Name of image file to save. If this argument is not set by user, do not save a figure as image. Returns ------- None : None """ fig = plt.figure() ax = Axes3D(fig) # ax = fig.add_subplot(111, projection='3d') # Plot all atoms for i in range(len(fcl)): # Determine atomic number n = elements.check_atom(fal[i]) ax.scatter(fcl[i][0], fcl[i][1], fcl[i][2], marker='o', linewidths=0.5, edgecolors='black', color=elements.check_color(n), label=f"{fal[i]}", s=elements.check_radii(n) * 300) # Calculate distance bond_list = tools.find_bonds(fal, fcl) atoms_pair = [] for i in range(len(bond_list)): get_atoms = bond_list[i] x, y, z = zip(*get_atoms) atoms = list(zip(x, y, z)) atoms_pair.append(atoms) # Draw line for i in range(len(atoms_pair)): merge = list(zip(atoms_pair[i][0], atoms_pair[i][1])) x, y, z = merge ax.plot(x, y, z, 'k-', color="black", linewidth=2) # Set legend # Remove duplicate labels in legend. # Ref.https://stackoverflow.com/a/26550501/6596684 handles, labels = ax.get_legend_handles_labels() handle_list, label_list = [], [] for handle, label in zip(handles, labels): if label not in label_list: handle_list.append(handle) label_list.append(label) leg = plt.legend(handle_list, label_list, loc="lower left", scatterpoints=1, fontsize=12) # Fixed size of point in legend # Ref. https://stackoverflow.com/a/24707567/6596684 for i in range(len(leg.legendHandles)): leg.legendHandles[i]._sizes = [90] # Set axis ax.set_xlabel(r'X', fontsize=15) ax.set_ylabel(r'Y', fontsize=15) ax.set_zlabel(r'Z', fontsize=15) ax.set_title('Full complex', fontsize="12") ax.grid(True) # plt.axis('equal') if save != "not_save": plt.savefig('{0}.png'.format(save)) plt.show()
def octa(ao, co, save="not_save"): """ Display 3D structure of octahedral complex. Parameters ---------- ao : list Atomic labels of octahedral structure. co : list Atomic coordinates of octahedral structure. save : str Name of image file to save. If this argument is not set by user, do not save a figure as image. Returns ------- None : None """ fig = plt.figure() ax = Axes3D(fig) # Plot atoms for i in range(len(co)): # Determine atomic number n = elements.check_atom(ao[i]) ax.scatter(co[i][0], co[i][1], co[i][2], marker='o', linewidths=0.5, edgecolors='black', color=elements.check_color(n), label=f"{ao[i]}", s=elements.check_radii(n) * 300) # Draw line for i in range(1, len(co)): merge = list(zip(co[0], co[i])) x, y, z = merge ax.plot(x, y, z, 'k-', color="black", linewidth=2) # Set legend # Remove duplicate labels in legend. # Ref.https://stackoverflow.com/a/26550501/6596684 handles, labels = ax.get_legend_handles_labels() handle_list, label_list = [], [] for handle, label in zip(handles, labels): if label not in label_list: handle_list.append(handle) label_list.append(label) leg = plt.legend(handle_list, label_list, loc="lower left", scatterpoints=1, fontsize=12) # Fixed size of point in legend # Ref. https://stackoverflow.com/a/24707567/6596684 for i in range(len(leg.legendHandles)): leg.legendHandles[i]._sizes = [90] # Set axis ax.set_xlabel(r'X', fontsize=15) ax.set_ylabel(r'Y', fontsize=15) ax.set_zlabel(r'Z', fontsize=15) ax.set_title('Octahedral structure', fontsize="12") ax.grid(True) # plt.axis('equal') if save != "not_save": plt.savefig('{0}.png'.format(save)) plt.show()
def plot_fit_plane(self): """ Display complex and two fit planes of two sets of ligand in molecule. """ ############### # Clear boxes # ############### self.box_angle1.delete(0, tk.END) self.box_angle2.delete(0, tk.END) self.box_eq1.delete(0, tk.END) self.box_eq2.delete(0, tk.END) ######################## # Find eq of the plane # ######################## xx, yy, z, abcd = plane.find_fit_plane(self.coord_A) plane_a = (xx, yy, z) a1, b1, c1, d1 = abcd self.box_eq1.insert( tk.INSERT, f"{a1:8.5f}x {b1:+8.5f}y {c1:+8.5f}z {d1:+8.5f} = 0") xx, yy, z, abcd = plane.find_fit_plane(self.coord_B) plane_b = (xx, yy, z) a2, b2, c2, d2 = abcd self.box_eq2.insert( tk.INSERT, f"{a2:8.5f}x {b2:+8.5f}y {c2:+8.5f}z {d2:+8.5f} = 0") #################################### # Calculate angle between 2 planes # #################################### angle = linear.angle_btw_planes(a1, b1, c1, a2, b2, c2) self.box_angle1.insert(tk.INSERT, f"{angle:10.6f}") # insert to box sup_angle = abs(180 - angle) # supplementary angle self.box_angle2.insert(tk.INSERT, f"{sup_angle:10.6f}") # insert to box ############### # Plot planes # ############### fig = plt.figure() # fig = plt.figure(figsize=(5, 4), dpi=100) ax = Axes3D(fig) # ax = fig.add_subplot(111, projection='3d') # Plot all atoms for i in range(len(self.coord)): # Determine atomic number n = elements.check_atom(self.atom[i]) ax.scatter( self.coord[i][0], self.coord[i][1], self.coord[i][2], marker="o", linewidths=0.5, edgecolors="black", picker=5, color=elements.check_color(n), label=f"{self.atom[i]}", s=elements.check_radii(n) * 300, ) atoms_pair = [] for i in range(len(self.bond_list)): get_atoms = self.bond_list[i] x, y, z = zip(*get_atoms) atoms = list(zip(x, y, z)) atoms_pair.append(atoms) # Draw line for i in range(len(atoms_pair)): merge = list(zip(atoms_pair[i][0], atoms_pair[i][1])) x, y, z = merge ax.plot(x, y, z, "k-", color="black", linewidth=2) # Set legend # Remove duplicate labels in legend. # Ref.https://stackoverflow.com/a/26550501/6596684 handles, labels = ax.get_legend_handles_labels() handle_list, label_list = [], [] for handle, label in zip(handles, labels): if label not in label_list: handle_list.append(handle) label_list.append(label) leg = fig.legend(handle_list, label_list, loc="lower left", scatterpoints=1, fontsize=12) # Fixed size of point in legend # Ref. https://stackoverflow.com/a/24707567/6596684 for i in range(len(leg.legendHandles)): leg.legendHandles[i]._sizes = [90] # Set axis ax.set_xlabel(r"X", fontsize=15) ax.set_ylabel(r"Y", fontsize=15) ax.set_zlabel(r"Z", fontsize=15) ax.set_title("Full complex", fontsize="12") ax.grid(True) # Plot plane A xx, yy, z = plane_a ax.plot_surface(xx, yy, z, alpha=0.2, color="green") # Plot plane B xx, yy, z = plane_b ax.plot_surface(xx, yy, z, alpha=0.2, color="red") # ax.set_xlim(-10, 10) # ax.set_ylim(-10, 10) # ax.set_zlim(0, 10) # plt.axis('equal') # plt.axis('off') plt.show()
def pick_atom(self, group): """ On-mouse pick atom and get XYZ coordinate. Parameters ---------- group : str Group A or B. """ fig = plt.figure() # fig = plt.figure(figsize=(5, 4), dpi=100) ax = Axes3D(fig) # ax = fig.add_subplot(111, projection='3d') # Plot all atoms for i in range(len(self.coord)): # Determine atomic number n = elements.check_atom(self.atom[i]) ax.scatter( self.coord[i][0], self.coord[i][1], self.coord[i][2], marker="o", linewidths=0.5, edgecolors="black", picker=5, color=elements.check_color(n), label=f"{self.atom[i]}", s=elements.check_radii(n) * 300, ) atoms_pair = [] for i in range(len(self.bond_list)): get_atoms = self.bond_list[i] x, y, z = zip(*get_atoms) atoms = list(zip(x, y, z)) atoms_pair.append(atoms) # Draw line for i in range(len(atoms_pair)): merge = list(zip(atoms_pair[i][0], atoms_pair[i][1])) x, y, z = merge ax.plot(x, y, z, "k-", color="black", linewidth=2) # Set legend # Remove duplicate labels in legend. # Ref.https://stackoverflow.com/a/26550501/6596684 handles, labels = ax.get_legend_handles_labels() handle_list, label_list = [], [] for handle, label in zip(handles, labels): if label not in label_list: handle_list.append(handle) label_list.append(label) leg = fig.legend(handle_list, label_list, loc="lower left", scatterpoints=1, fontsize=12) # Fixed size of point in legend # Ref. https://stackoverflow.com/a/24707567/6596684 for i in range(len(leg.legendHandles)): leg.legendHandles[i]._sizes = [90] # Set axis ax.set_xlabel(r"X", fontsize=15) ax.set_ylabel(r"Y", fontsize=15) ax.set_zlabel(r"Z", fontsize=15) ax.set_title("Full complex", fontsize="12") ax.grid(True) def insert_text(text, coord, group): """ Insert text in boxes. Parameters ---------- text : str Text. coord : list or array Coordinates. group : str Group A or B. """ if group == "A": self.box_1.insert(tk.INSERT, text + "\n") self.box_1.see(tk.END) self.coord_A.append(coord) elif group == "B": self.box_2.insert(tk.INSERT, text + "\n") self.box_2.see(tk.END) self.coord_B.append(coord) def on_pick(event): """ Pick point and get XYZ data Parameters ---------- event : object Event object for on-pick function. Examples -------- >>> def on_pick(event): >>> ... ind = event.ind >>> ... print("on_pick scatter:", ind, np.take(x, ind), np.take(y, ind)) """ ind = event.ind[0] x, y, z = event.artist._offsets3d for i in range(len(self.atom)): if x[ind] == self.coord[i][0]: if y[ind] == self.coord[i][1]: if z[ind] == self.coord[i][2]: atom = self.atom[i] break results = f"{i + 1} {atom} : {x[ind]} {y[ind]} {z[ind]}" coord = [x[ind], y[ind], z[ind]] insert_text(results, coord, group) # Highlight selected atom index = elements.check_atom(atom) ax.scatter( x[ind], y[ind], z[ind], marker="o", linewidths=0.5, edgecolors="orange", picker=5, alpha=0.5, color="yellow", s=elements.check_radii(index) * 400, ) # print(i+1, atom, x[ind], y[ind], z[ind]) fig.canvas.mpl_connect("pick_event", on_pick) # plt.axis('equal') # plt.axis('off') plt.show()
def plot_fit_plane(acf, coord_A, coord_B): """ Display complex and two fit planes of two sets of ligand in molecule. Parameters ---------- acf : list Atomic labels and coordinates of full complex. coord_A : list List of chunk of atoms, set A. coord_B : list List of chunk of atoms, set B. Returns ------- None : None """ ######################## # Find eq of the plane # ######################## xx, yy, z, abcd = calc_fit_plane(coord_A) plane_A = (xx, yy, z) a1, b1, c1, d1 = abcd xx, yy, z, abcd = calc_fit_plane(coord_B) plane_B = (xx, yy, z) a2, b2, c2, d2 = abcd #################################### # Calculate angle between 2 planes # #################################### angle = linear.angle_btw_planes(a1, b1, c1, a2, b2, c2) sup_angle = abs(180 - angle) # supplementary angle ############### # Plot planes # ############### fal, fcl = acf[0] fig = plt.figure() # fig = plt.figure(figsize=(5, 4), dpi=100) ax = Axes3D(fig) # ax = fig.add_subplot(111, projection='3d') # Plot all atoms for i in range(len(fcl)): # Determine atomic number n = elements.check_atom(fal[i]) ax.scatter(fcl[i][0], fcl[i][1], fcl[i][2], marker='o', linewidths=0.5, edgecolors='black', picker=5, color=elements.check_color(n), label=f"{fal[i]}", s=elements.check_radii(n) * 300) # Calculate distance bond_list = tools.find_bonds(fal, fcl) atoms_pair = [] for i in range(len(bond_list)): get_atoms = bond_list[i] x, y, z = zip(*get_atoms) atoms = list(zip(x, y, z)) atoms_pair.append(atoms) # Draw line for i in range(len(atoms_pair)): merge = list(zip(atoms_pair[i][0], atoms_pair[i][1])) x, y, z = merge ax.plot(x, y, z, 'k-', color="black", linewidth=2) # Set legend # Remove duplicate labels in legend. # Ref.https://stackoverflow.com/a/26550501/6596684 handles, labels = ax.get_legend_handles_labels() handle_list, label_list = [], [] for handle, label in zip(handles, labels): if label not in label_list: handle_list.append(handle) label_list.append(label) leg = fig.legend(handle_list, label_list, loc="lower left", scatterpoints=1, fontsize=12) # Fixed size of point in legend # Ref. https://stackoverflow.com/a/24707567/6596684 for i in range(len(leg.legendHandles)): leg.legendHandles[i]._sizes = [90] # Set axis ax.set_xlabel(r'X', fontsize=15) ax.set_ylabel(r'Y', fontsize=15) ax.set_zlabel(r'Z', fontsize=15) ax.set_title('Full complex', fontsize="12") ax.grid(True) # Plot plane A xx, yy, z = plane_A ax.plot_surface(xx, yy, z, alpha=0.2, color='green') # Plot plane B xx, yy, z = plane_B ax.plot_surface(xx, yy, z, alpha=0.2, color='red') # ax.set_xlim(-10, 10) # ax.set_ylim(-10, 10) # ax.set_zlim(0, 10) # plt.axis('equal') # plt.axis('off') plt.show()