Пример #1
0
 def showMolecules(self):
     tstep = self.animationSlider.value()
     self.animationTime.setText("Time: %7.2f fs" % (tstep * self.dt))
     self.mol.clear()
     for geoms in self.geometries:
         geom_time = geoms[min(tstep, len(geoms)-1)]
         # atoms
         atoms = []
         for (Z,pos) in geom_time:
             a = self.mol.addAtom()
             a.pos = np.array(pos, dtype=float)
             a.atomicNumber = Z
             atoms.append(a)
         # bond
         C = XYZ.connectivity_matrix(geom_time)
         Nat = len(geom_time)
         for i in range(0, Nat):
             for j in range(i+1,Nat):
                 if C[i,j] == 1:
                     bond = self.mol.addBond()
                     bond.setBegin(atoms[i])
                     bond.setEnd(atoms[j])
                     bond.order = 1
                     
     self.glWidget.mol = self.mol
     self.glWidget.updateGeometry()
     Avogadro.toPyQt(self.glWidget).update()
Пример #2
0
 def __init__(self, atomlist, embedding="electrostatic", verbose=0, name="uff", unique_tmp=False):
     self.embedding = embedding
     self.verbose = verbose
     self.atomlist = atomlist
     # find the scratch directory where Gaussian writes to
     try:
         scratch_dir = os.environ["GAUSS_SCRDIR"]
     except KeyError as e:
         print("WARNING: Environment variable GAUSS_SCRDIR not set!")
         print("         Check that g09 is installed correctly!")
         #raise e
         scratch_dir="./"
     if unique_tmp == True:
         name += "-" + str(uuid.uuid4())    
     # write input to temporary file
     self.com_file = join(scratch_dir, "%s.gcom" % name)
     self.chk_file = join(scratch_dir, "%s.chk" % name)
     self.fchk_file = join(scratch_dir, "%s.fchk" % name)
     self.log_file = join(scratch_dir, "%s.log" % name)
     # determine the connectivity of the atoms. The connectivity should not change
     # during a dynamics simulation, since this would lead to kinks in the potential
     # energy
     ConMat = XYZ.connectivity_matrix(atomlist)
     self.connectivity = []  # connectivity[i] is a list with atoms bonded to i
     for i in range(0, len(atomlist)):
         self.connectivity.append( list(np.where(ConMat[i,:] != 0)[0]) )
     # first calculation is done only in order to get the
     # correct partial charges from Qeq
     """
     if self.embedding == "electrostatic":
         self.calc(atomlist, do_Qeq=True)
     """
     self.have_charges = False
Пример #3
0
def check_connectivity(atomlist):
    """
    In a capped carbon nanotube, every atoms should be connected
    to 6 or 5 neighbours. If this is not the case, there must a
    hole somewhere.
    """
    Con = XYZ.connectivity_matrix(atomlist)
    nr_neighbours = np.sum(Con, axis=1)
    con_min = nr_neighbours.min()
    con_max = nr_neighbours.max()
    print "nr_neighbours = %s" % nr_neighbours
    print "%s <= connectivity <= %s" % (con_min, con_max)
    if (3 <= con_min) and (con_max <= 3):
        return True
    else:
        print "Not all C-atoms are connected to 3. There must be a hole somewhere!"
        return False
Пример #4
0
def atomlist2graph(atomlist, hydrogen_bonds=False, conmat=None):
    """
    Based on the adjacency matrix a molecular graph is constructed. 
    """
    Nat = len(atomlist)
    if conmat is None:
        # adjacency matrix, conmat[i,j] = 1 if there is a bond between atoms i and j
        conmat = XYZ.connectivity_matrix(atomlist,
                                         thresh=1.3,
                                         hydrogen_bonds=hydrogen_bonds)
    else:
        # check shape of adjacency matrix
        assert conmat.shape == (Nat, Nat)
    # visited flags the atoms that have been added to the graph to avoid
    # repetitions and to identify disconnected parts
    visited = [0 for i in range(0, Nat)]
    # atomic numbers
    Zs = [Zi for (Zi, posi) in atomlist]

    # This recursive function starts at one atoms and adds all the connected
    # atoms as child nodes
    def make_graph(i):
        graph = AtomNode(i, Zs[i])
        visited[i] = 1
        connected = np.where(conmat[i, :] == 1)[0]
        for j in connected:
            if visited[j] == 1:
                continue
            graph[j] = make_graph(j)
            visited[j] = 1
        return graph

    #
    fragment_graphs = []
    while True:
        # find the first atom that has not been visited yet
        try:
            start = visited.index(0)
        except ValueError:
            # all atoms have been visited
            break
        graph = make_graph(start)
        fragment_graphs.append(graph)
    #print "number of disconnected fragments: %d" % len(fragment_graphs)
    return fragment_graphs
Пример #5
0
def plot_planar_geometry(ax, atomlist, zaxis=2):
    Con = XYZ.connectivity_matrix(atomlist)
    ax.set_aspect('equal', 'datalim')
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    # atomic positions
    for A, (ZA, posA) in enumerate(atomlist):
        x, y = posA[0:2]
        atname = AtomicData.atom_names[ZA - 1]
        if atname in ["h", "c"]:
            # do not draw the carbon skeleton
            ax.plot([x], [y],
                    "o",
                    color="black",
                    markersize=AtomicData.covalent_radii[atname] * 3.0)
        else:
            ax.text(x, y, "%s" % atname.capitalize(), ha='center', va='center')
    # bonds
    Nat = len(atomlist)
    for A in range(0, Nat):
        ZA, posA = atomlist[A]
        xA, yA = posA[0:2]
        connected_atoms = np.where(Con[A, :] > 0)[0]
        for Bcon in connected_atoms:
            ZB, posB = atomlist[Bcon]
            xB, yB, zB = posB[0:3]
            #
            if zB > 0.3:
                ax.annotate("",
                            xy=(xA, yA),
                            xytext=(xB, yB),
                            arrowprops=dict(arrowstyle="wedge",
                                            connectionstyle="arc3",
                                            color="gray",
                                            lw=4))
            elif zB < -0.3:
                ax.plot([xA, xB], [yA, yB], ls="-.", lw=4, color="gray")
            else:
                ax.plot([xA, xB], [yA, yB], ls="-", lw=4, color="gray")
Пример #6
0
    def _update_visualization(self, atomlist):
        """
        only change the underlying data but do not recreate visualization.
        This is faster and avoids jerky animations.
        """
        vec = XYZ.atomlist2vector(atomlist)
        x, y, z = vec[::3], vec[1::3], vec[2::3]
        s = self.atom_radii
        if self.show_flags["atoms"] == False:
            # make atoms so small that one does not see them
            scale_factor = 0.01
            self.shown_atoms = False
        else:
            scale_factor = 0.3
            self.shown_atoms = True
        # update atom positions
        self.atoms.mlab_source.set(x=x,y=y,z=z,u=s,v=s,w=s, scalars=self.Zs, scale_factor=scale_factor)
        # atoms are coloured by their atomic number
        self.atoms.glyph.color_mode = "color_by_scalar"
        self.atoms.glyph.glyph_source.glyph_source.center = [0,0,0]
        self.atoms.module_manager.scalar_lut_manager.lut.table = self.lut
        self.atoms.module_manager.scalar_lut_manager.data_range = (0.0, 255.0)

        # update bonds
        self.bonds.mlab_source.reset(x=x,y=y,z=z, scale_factor=1.0)

        C = XYZ.connectivity_matrix(atomlist)
        Nat = len(atomlist)
        connections = []
        for i in range(0, Nat):
            Zi, posi = atomlist[i]
            for j in range(i+1,Nat):
                if C[i,j] == 1:
                    Zj, posj = atomlist[j]
                    connections.append( (i,j) )
        self.bonds.mlab_source.dataset.lines = np.array(connections)
        self.bonds.mlab_source.dataset.modified()
Пример #7
0
        print "  This script simply adds a 5th column with the atom type"
        print "  and writes the result to the .ff-file ."
        print " "
        print "  WARNING: The type assignment and the force field implementation itself probably have lots of bugs!"
        exit(-1)
    # laod xyz-file
    xyz_file = sys.argv[1]
    atomlist = XYZ.read_xyz(xyz_file)[0]
    # find total charge
    kwds = XYZ.extract_keywords_xyz(xyz_file)
    charge = kwds.get("charge", 0.0)

    nat = len(atomlist)
    # determine bond orders
    print "connectivity matrix"
    ConMat = XYZ.connectivity_matrix(atomlist, search_neighbours=200)
    print "bond order assignment"
    bondsTuples, bond_orders, lone_pairs, formal_charges = BondOrders.assign_bond_orders(
        atomlist, ConMat, charge=charge)
    # list of bond orders
    bond_orders_atomwise = [[] for i in range(0, nat)]
    # names of atoms connected to each
    bonded_atomnames = [[] for i in range(0, nat)]
    for i, (atI, atJ) in enumerate(bondsTuples):
        BO = bond_orders[i]
        bond_orders_atomwise[atI].append(BO)
        bond_orders_atomwise[atJ].append(BO)
        # name of atoms involved in this bond
        Zi = atomlist[atI][0]
        Zj = atomlist[atJ][0]
        atnameI = AtomicData.atom_names[Zi - 1].capitalize()
Пример #8
0
    def __init__(self, atomlist, freeze=[], explicit_bonds=[], verbose=0):
        """
        setup system of internal coordinates using
        valence bonds, angles and dihedrals

        Parameters
        ----------
        atomlist   :  list of tuples (Z,[x,y,z]) with molecular
                      geometry, connectivity defines the valence
                      coordinates

        Optional
        --------
        freeze          :  list of tuples of atom indices (starting at 0) corresponding
                           to internal coordinates that should be frozen
        explicit_bonds :   list of pairs of atom indices (starting at 0) between which artificial
                           bonds should be inserted, i.e. [(0,1), (10,20)].
                           This allows to connect separate fragments.
        verbose        :   write out additional information if > 0
        """
        self.verbose = verbose
        self.atomlist = atomlist

        self.masses = AtomicData.atomlist2masses(self.atomlist)
        # Bonds, angles and torsions are constructed by the force field.
        # Atom types, partial charges and lattice vectors
        # all don't matter, so we assign atom type 6 (C_R, carbon in resonance)
        # to all atoms.
        atomtypes = [6 for atom in atomlist]
        partial_charges = [0.0 for atom in atomlist]
        lattice_vectors = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
        # But since the covalent radii are wrong, we have to provide
        # the connectivity matrix
        conmat = XYZ.connectivity_matrix(atomlist, hydrogen_bonds=True)

        # insert artificial bonds
        for (I, J) in explicit_bonds:
            print("explicit bond between atoms %d-%d" % (I + 1, J + 1))
            conmat[I, J] = 1

        # Internal coordinates only work if the molecule does not
        # contain disconnected fragments, since there is no way how the
        # interfragment distance could be expressed in terms of internal coordinates.
        # We need to check that there is only a single fragment.
        fragment_graphs = MolecularGraph.atomlist2graph(self.atomlist,
                                                        conmat=conmat)
        nr_fragments = len(fragment_graphs)
        error_msg = "The molecule consists of %d disconnected fragments.\n" % nr_fragments
        error_msg += "Internal coordinates only work if all atoms in the molecular graph are connected.\n"
        error_msg += "Disconnected fragments may be joined via an artificial bond using the\n"
        error_msg += "`explicit_bonds` option.\n"
        assert nr_fragments == 1, error_msg

        # Frozen degrees of freedom do not necessarily correspond to physical bonds
        # or angles. For instance we can freeze the H-H distance in water although there
        # is no bond between the hydrogens. To allow the definition of such 'unphysical'
        # internal coordinates, we have to modify the connectivity matrix and introduce
        # artificial bonds.
        for IJKL in freeze:
            if len(IJKL) == 2:
                I, J = IJKL
                # create artificial bond between atoms I and J
                conmat[I, J] = 1
            elif len(IJKL) == 3:
                I, J, K = IJKL
                # create artifical bonds I-J and J-K so that the valence angle I-J-K exists
                conmat[I, J] = 1
                conmat[J, K] = 1
            elif len(IJKL) == 4:
                I, J, K, L = IJKL
                # create artifical bonds I-J, J-K and K-L so that the dihedral angle I-J-K-L
                # exists
                conmat[I, J] = 1
                conmat[J, K] = 1
                conmat[K, L] = 1

        # cutoff for small singular values when solving the
        # linear system of equations B.dx = dq in a least square
        # sense.
        self.cond_threshold = 1.0e-10

        self.force_field = PeriodicForceField(atomlist,
                                              atomtypes,
                                              partial_charges,
                                              lattice_vectors, [],
                                              connectivity_matrix=conmat,
                                              verbose=1)
        x0 = XYZ.atomlist2vector(atomlist)
        # shift molecule to center of mass
        self.x0 = MolCo.shift_to_com(x0, self.masses)

        self._selectActiveInternals(freeze=freeze)
Пример #9
0
def dual_lattice(atomlist):
    Con = XYZ.connectivity_matrix(atomlist)
    # place and atom between all closest
    pass
Пример #10
0
def find_beta_meso_carbons(atomlist):
    """
    Assuming that `atomlist` contains the geometry of a beta-beta, meso-meso, beta-beta
    fused porphyrin polyomino, this functions finds the indices of the exterior
    beta and meso carbons, which can be identified by the two conditions

      1) The carbon is bonded to a hydrogen atom
      2) There are exactly one (for beta) or exactly two (for meso) nitrogen atoms
         in the list of second nearest neighbours.

    Parameters
    ----------
    atomlist       :   geometry of porphyrin polyomino

    Returns
    -------
    beta_carbons   :   list of indeces into atomlist (starting at 0)
                       of beta carbons
    beta_hydrogens :   list of indeces into atomlist (starting at 0)
                       of hydrogens bound to beta carbons
    meso_carbons   :   list of indeces into atomlist (starting at 0)
                       of meso carbons
    beso_hydrogens :   list of indeces into atomlist (starting at 0)
                       of hydrogens bound to meso carbons
    """
    C = XYZ.connectivity_matrix(atomlist)
    # indices (into atomlist) of exterior beta and meso carbon atoms
    beta_carbons = []
    meso_carbons = []
    # indices (into atomlist) of beta and meso hydrogens
    beta_hydrogens = []
    meso_hydrogens = []

    for i, (Zi, pos) in enumerate(atomlist):
        # Is this a carbon atom ?
        if Zi != 6:
            continue

        # nearest neighbours
        neighbours1 = np.where(C[i, :] == 1)[0]
        for j in neighbours1:
            Zj = atomlist[j][0]
            # Is the carbon bonded to a hydrogen atom?
            if Zj == 1:
                break
        else:
            # No hydrogen was found in the list of nearest neighbours,
            # so this cannot be a meso carbon.
            continue

        # list of second nearest neighbours
        neighbours2 = []
        for k in neighbours1:
            neighbours2 += list(np.where(C[k, :] == 1)[0])
        # delete duplicates in list
        neighbours2 = list(set(neighbours2))

        # Are there exactly two nitrogens in the list of second-nearest neighbour atoms?
        num_nitrogens = 0
        for k in neighbours2:
            Zk = atomlist[k][0]
            if Zk == 7:
                num_nitrogens += 1
        if num_nitrogens == 1:
            beta_carbons.append(i)
            beta_hydrogens.append(j)
        elif num_nitrogens == 2:
            meso_carbons.append(i)
            meso_hydrogens.append(j)

    return beta_carbons, beta_hydrogens, meso_carbons, meso_hydrogens
Пример #11
0
def morgan_ordering(atomlist, hydrogen_bonds=False):
    """
    order atoms canonically using a variant of Morgan's algorithm according
    to 
     Morgan, H.L., The Generation of a Unique Machine Description for Chemical Structures
    and 
     "Morgan Revisited" by Figueras,J.  J.Chem.Inf.Comput.Sci. 1993, 33, 717-718

    Optional:
    =========
    hydrogen_bonds: hydrogen bonds are included in the connectivity matrix

    Returns:
    ========
    atomlist_can: canonically reordered atoms
    A_can: adjacency matrix for canonical order of atoms
    """
    Nat = len(atomlist)
    # adjacency matrix, A[i,j] = 1 if there is a bond between atoms i and j
    A = XYZ.connectivity_matrix(atomlist,
                                thresh=1.3,
                                hydrogen_bonds=hydrogen_bonds)
    # initial invariants are the atom types
    v = [Zi for (Zi, posi) in atomlist]
    k = len(np.unique(v))
    #
    for i in range(0, 100):
        #while True:
        vnext = np.dot(A, v)
        # count the number of unique invariants
        knext = len(np.unique(vnext))
        v = vnext
        if knext <= k:
            #
            break
        k = knext
    else:
        raise Exception("Morgan algorithm did not converge in %d iterations!" %
                        i)
    # Symmetry equivalent atoms have same labels in v, while symmetry-inequivalent
    # ones should have different labels
    #print "Labels"
    #print v

    # Now the molecular graph is traversed starting with the atom with the lowest
    # label. Nearest neighbours are added in the order of their invariants.

    # visited flags the atoms that have been added to the graph to avoid
    # repetitions and to identify disconnected parts
    visited = [0 for i in range(0, Nat)]

    def traverse_ordered(i, ordering=[]):
        # atoms are added as they are encountered while traversing the graph
        ordering += [i]
        # mark atom i as visited
        visited[i] = 1
        # sort connected atoms by values of invariants
        connected = np.where(A[i, :] == 1)[0]
        sort_indx = np.argsort(v[connected])
        # The child nodes are added in depth-first order. Nodes on the same level
        # are sorted by v.
        for j in connected[sort_indx]:
            if visited[j] == 1:
                continue
            ordering = traverse_ordered(j, ordering)
        return ordering

    # start with the atom with the lowest label
    istart = np.argmin(v)
    ordering = traverse_ordered(istart)

    assert len(
        ordering
    ) == Nat, "It seems that the molecule contains disconnected fragments. Try to compute the canonical ordering for each fragment separately."

    #print "Canonical Ordering"
    #print ordering

    # Atoms are reorderd according to the canonical ordering
    atomlist_can = []
    for i in ordering:
        atomlist_can.append(atomlist[i])
    # The rows of the adjacency matrix are also reordered
    A_can = A[ordering, :][:, ordering]
    # check
    """
    print "A reordered"
    print A_can
    print "A calculated"
    print XYZ.connectivity_matrix(atomlist_can)
    """
    return atomlist_can, A_can
Пример #12
0
    def _create_visualization(self, atomlist):
        mlab = self.scene.mlab
        # draw atoms as balls
        vec = XYZ.atomlist2vector(atomlist)
        x, y, z = vec[::3], vec[1::3], vec[2::3]
        Zs = np.array([Z for (Z,pos) in atomlist])
        atom_names = [AtomicData.atom_names[Z-1] for (Z,pos) in atomlist]
        rads = np.array([AtomicData.covalent_radii.get(atname) for atname in atom_names])
        atom_radii = np.sqrt(rads)*1.8

        s = atom_radii
        if self.show_flags["atoms"] == False:
            # make atoms so small that one does not see them
            scale_factor = 0.01
            self.shown_atoms = False
        else:
            scale_factor = 0.45
            self.shown_atoms = True
        atoms = mlab.quiver3d(x,y,z, s,s,s, scalars=Zs.astype(float),
                              mode="sphere", scale_factor=scale_factor, resolution=20,
                              figure=self.scene.mayavi_scene)

        # atoms are coloured by their atomic number
        atoms.glyph.color_mode = "color_by_scalar"
        atoms.glyph.glyph_source.glyph_source.center = [0,0,0]
        self.lut = atoms.module_manager.scalar_lut_manager.lut.table.to_array()
        for atname in set(atom_names):
            Z = AtomicData.atomic_number(atname)
            self.lut[Z,0:3] = ( np.array( atom_colours_rgb.get(atname, (0.0, 0.75, 0.75)) )*255.0 ).astype('uint8')
        atoms.module_manager.scalar_lut_manager.lut.table = self.lut
        atoms.module_manager.scalar_lut_manager.data_range = (0.0, 255.0)
        
        # draw bonds
        C = XYZ.connectivity_matrix(atomlist)
        Nat = len(atomlist)
        connections = []
        bonds = mlab.points3d(x,y,z, scale_factor=0.15, resolution=20,
                              figure=self.scene.mayavi_scene)
        for i in range(0, Nat):
            Zi, posi = atomlist[i]
            for j in range(i+1,Nat):
                if C[i,j] == 1:
                    Zj, posj = atomlist[j]
                    connections.append( (i,j) )
        bonds.mlab_source.dataset.lines = np.array(connections)
        bonds.mlab_source.dataset.modified()
        
        tube = mlab.pipeline.tube(bonds, tube_radius=0.15, #tube_radius=0.05,
                                  figure=self.scene.mayavi_scene)
        tube.filter.radius_factor = 1.0
        surface = mlab.pipeline.surface(tube, color=(0.8,0.8,0.0),
                                        opacity=0.7,
                                        figure=self.scene.mayavi_scene)

        self.atoms = atoms
        self.bonds = bonds
#        self.tube = tube
#        self.surface = surface
        self.atom_radii = s
        self.Zs = Zs.astype(float)
        self.primitives.append(atoms)
        self.primitives.append(bonds)
        self.primitives.append(tube)
        self.primitives.append(surface)
        # Lewis structure
        if self.show_flags["Lewis structure"] == True:
            bondsTuples, bond_orders, lone_pairs, formal_charges = BondOrders.assign_bond_orders(atomlist, C, charge=0)
            # plot DOUBLE bonds
            double_bonds = mlab.points3d(x,y,z, scale_factor=0.15, resolution=20, figure=self.scene.mayavi_scene)
            connections_double = []
            for i,bond in enumerate(bondsTuples):
                if bond_orders[i] == 2:
                    # double bond between atoms I and J
                    connections_double.append( bond )
            double_bonds.mlab_source.dataset.lines = np.array(connections_double)
            double_bonds.mlab_source.dataset.modified()
            
            tube = mlab.pipeline.tube(double_bonds, tube_radius=0.35, figure=self.scene.mayavi_scene)
            tube.filter.radius_factor = 1.0
            surface = mlab.pipeline.surface(tube, color=(0.8,0.8,0.0), figure=self.scene.mayavi_scene)
            #
            self.double_bonds = double_bonds
            self.primitives.append(double_bonds)
            self.primitives.append(tube)
            self.primitives.append(surface)
            #
            # plot TRIPLE bonds
            triple_bonds = mlab.points3d(x,y,z, scale_factor=0.15, resolution=20, figure=self.scene.mayavi_scene)
            connections_triple = []
            for i,bond in enumerate(bondsTuples):
                if bond_orders[i] == 3:
                    # triple bond between atoms I and J
                    connections_triple.append( bond )
            triple_bonds.mlab_source.dataset.lines = np.array(connections_triple)
            triple_bonds.mlab_source.dataset.modified()
            
            tube = mlab.pipeline.tube(triple_bonds, tube_radius=0.35, figure=self.scene.mayavi_scene)
            tube.filter.radius_factor = 1.0
            surface = mlab.pipeline.surface(tube, color=(0.8,0.8,0.0), figure=self.scene.mayavi_scene)
            #
            self.triple_bonds = triple_bonds
            self.primitives.append(triple_bonds)
            self.primitives.append(tube)
            self.primitives.append(surface)

            self.shown_lewis_structure = True
Пример #13
0
    lines = fh.readlines()
    print "LINES = %s" % lines
    fh.close()
    for l in lines:
        print "LINE=%s" % line.strip()
        if ("The polytope has" in l) and ("vertices." in l):
            nr_vertices = int(l.split()[3])
        elif "The number of lattice points is:" in l:
            print "##################################################"
            exit(-1)
            if len(l.split()) == 9:
                nr_inside = int(l.split()[7])
            else:
                nr_inside = 0
            break
    else:
        raise Exception("Latte calculation failed! See output")
    print "DONE"
    return nr_inside + nr_vertices


if __name__ == "__main__":
    import sys

    xyz_file = sys.argv[1]
    atomlist = XYZ.read_xyz(xyz_file)[0]
    ConMat = XYZ.connectivity_matrix(atomlist)
    assign_bond_orders(atomlist,
                       ConMat,
                       latte_file=xyz_file.replace(".xyz", ".hrep.latte"))