Ejemplo n.º 1
0
def get_coord_nwchem(f):
    """
    Extract XYZ coordinate from NWChem output file.

    Parameters
    ----------
    f : str
        User input filename.

    Returns
    -------
    atom : list
        Full atomic labels of complex.
    coord : ndarray
        Full atomic coordinates of complex.

    """
    nwchem_file = open(f, "r")
    nline = nwchem_file.readlines()

    start = 0
    end = 0
    atom, coord = [], []
    for i in range(len(nline)):
        if "Optimization converged" in nline[i]:
            start = i

    for i in range(len(nline)):
        if "No. of atoms" in nline[i]:
            end = int(nline[i].split()[4])

    start = start + 18
    end = start + end
    # The 1st line of coordinate is at 18 lines next to 'Optimization converged'
    for line in nline[start:end]:
        dat = line.split()
        dat1 = int(float(dat[2]))
        coord_x = float(dat[3])
        coord_y = float(dat[4])
        coord_z = float(dat[5])
        dat1 = elements.check_atom(dat1)
        atom.append(dat1)
        coord.append([coord_x, coord_y, coord_z])

    nwchem_file.close()

    coord = np.asarray(coord, dtype=np.float64)

    return atom, coord
Ejemplo n.º 2
0
def get_coord_gaussian(f):
    """
    Extract XYZ coordinate from Gaussian output file.

    Parameters
    ----------
    f : str
        User input filename.

    Returns
    -------
    atom : list
        Full atomic labels of complex.
    coord : ndarray
        Full atomic coordinates of complex.

    """
    gaussian_file = open(f, "r")
    nline = gaussian_file.readlines()

    start = 0
    end = 0
    atom, coord = [], []
    for i in range(len(nline)):
        if "Standard orientation:" in nline[i]:
            start = i

    for i in range(start + 5, len(nline)):
        if "---" in nline[i]:
            end = i
            break

    for line in nline[start + 5:end]:
        data = line.split()
        data1 = int(data[1])
        coord_x = float(data[3])
        coord_y = float(data[4])
        coord_z = float(data[5])
        data1 = elements.check_atom(data1)
        atom.append(data1)
        coord.append([coord_x, coord_y, coord_z])

    gaussian_file.close()

    coord = np.asarray(coord, dtype=np.float64)

    return atom, coord
Ejemplo n.º 3
0
        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,
            )
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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()
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
def find_metal(atom=None, coord=None):
    """
    Count the number of metal center atom in complex.

    Parameters
    ----------
    atom : list, None
        Full atomic labels of complex.
    coord : array_like, None
        Full atomic coordinates of complex.

    Returns
    -------
    total_metal : int
        The total number of metal center atom.
    atom_metal : list
        Atomic labels of metal center atom.
    coord_metal : ndarray
        Atomic coordinates of metal center atom.

    See Also
    --------
    octadist.src.elements.check_atom :
        Convert atomic number to atomic symbol and vice versa.

    Examples
    --------
    >>> atom = ['Fe', 'N', 'N', 'N', 'N', 'N', 'N']
    >>> coord = [[-1.95348286e+00,  4.51770478e+00,  1.47855811e+01],
                 [-1.87618286e+00,  4.48070478e+00,  1.26484811e+01],
                 [-3.90128286e+00,  5.27750478e+00,  1.40814811e+01],
                 [-4.88286000e-03,  3.69060478e+00,  1.42392811e+01],
                 [-2.18698286e+00,  4.34540478e+00,  1.69060811e+01],
                 [-1.17538286e+00,  6.38340478e+00,  1.56457811e+01],
                 [-2.75078286e+00,  2.50260478e+00,  1.51806811e+01]]
    >>> total_metal, atom_metal, coord_metal = find_metal(atom, coord)
    >>> total_metal
    1
    >>> atom_metal
    ['Fe']
    >>> coord_metal
    [[-1.95348286  4.51770478 14.78558113]]

    """
    if atom is None or coord is None:
        raise TypeError("find_metal needs two arguments: atom, coord")

    total_metal = 0
    atom_metal = []
    coord_metal = []

    for i in range(len(atom)):
        number = elements.check_atom(atom[i])

        if (21 <= number <= 30 or 39 <= number <= 48 or 57 <= number <= 80
                or 89 <= number <= 109):

            total_metal += 1
            atom_metal.append(atom[i])
            coord_metal.append(coord[i])

    coord_metal = np.asarray(coord_metal, dtype=np.float64)

    return total_metal, atom_metal, coord_metal
Ejemplo n.º 8
0
    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()
Ejemplo n.º 9
0
    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()
Ejemplo n.º 10
0
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()