示例#1
0
文件: vmat.py 项目: snelliott/automol
def vmatrix(gra, keys=None, rng_keys=None):
    """ v-matrix for a connected graph

    :param gra: the graph
    :param keys: restrict the v-matrix to a subset of keys, which must span a
        connected graph
    :param rng_keys: keys for a ring to start from
    """
    if keys is not None:
        gra = subgraph(gra, keys)

    assert is_connected(gra), "Graph must be connected!"

    # Start with the ring systems and their connections. If there aren't any,
    # start with the first terminal atom
    if ring_systems(gra):
        vma, zma_keys = connected_ring_systems(gra, rng_keys=rng_keys)
    else:
        term_keys = sorted(terminal_heavy_atom_keys(gra))
        if term_keys:
            start_key = term_keys[0]
        else:
            start_key = sorted(atom_keys(gra))[0]

        vma, zma_keys = start_at(gra, start_key)

    rem_keys = atom_keys(gra) - set(zma_keys)
    vma, zma_keys = continue_vmatrix(gra, rem_keys, vma, zma_keys)
    return vma, zma_keys
示例#2
0
文件: vmat.py 项目: snelliott/automol
def connected_ring_systems(gra, rng_keys=None, check=True):
    """ generate a v-matrix covering a graph's ring systems and the connections
    between them
    """
    if check:
        assert is_connected(gra), "Graph must be connected!"

    rsys = sorted(ring_systems(gra), key=atom_count)

    # Construct the v-matrix for the first ring system, choosing which ring
    # to start from
    if rng_keys is None:
        rsy = rsys.pop(0)
        rngs = sorted(rings(rsy), key=atom_count)
        rng_keys = sorted_ring_atom_keys(rngs.pop(0))
    else:
        idx = next((i for i, ks in enumerate(map(atom_keys, rsys))
                    if set(rng_keys) <= ks), None)
        assert idx is not None, (
            "The ring {} is not in this graph:\n{}"
            .format(str(rng_keys), string(gra, one_indexed=False)))
        rsy = rsys.pop(idx)

    keys_lst = list(ring_system_decomposed_atom_keys(rsy, rng_keys=rng_keys))

    vma, zma_keys = ring_system(gra, keys_lst)

    keys = atom_keys(gra) - set(zma_keys)

    vma, zma_keys = continue_connected_ring_systems(
        gra, keys, vma, zma_keys, rsys=rsys, check=False)

    return vma, zma_keys
示例#3
0
文件: vmat.py 项目: snelliott/automol
def continue_connected_ring_systems(gra, keys, vma, zma_keys, rsys=None,
                                    check=True):
    """ generate the connected ring systems for a subset of keys, continuing on
    from a partial v-matrix

    The subset must have at least one neighbor that already exists in the
    v-matrix

    :param gra: the graph for which the v-matrix will be constructed
    :param keys: the subset of keys to be added to the v-matrix
    :param vma: a partial v-matrix from which to continue
    :param zma_keys: row keys for the partial v-matrix, identifying the atom
        specified by each row of `vma` in order
    :param rsys: optionally, pass the ring systems in to avoid recalculating
    """
    gra = subgraph(gra, set(keys) | set(zma_keys))
    sub = subgraph(gra, keys)
    if check:
        assert is_connected(gra), "Graph must be connected!"

    if rsys is None:
        rsys = sorted(ring_systems(sub), key=atom_count)

    rsys = list(rsys)

    while rsys:
        # Find the next ring system with a connection to the current
        # v-vmatrix and connect them
        conn = False
        for idx, rsy_keys in enumerate(map(atom_keys, rsys)):
            if set(zma_keys) & rsy_keys:
                # ring systems are connected by one bond -- no chain needed
                keys = set(zma_keys) & rsy_keys
                assert len(keys) == 1, (
                    "Attempting to add redundant keys to v-matrix: {}"
                    .format(str(keys)))
                key, = keys

                conn = True
            else:
                # see if the ring systems are connected by a chain
                keys = shortest_path_between_groups(
                    gra, zma_keys, rsy_keys)

                # if so, build a bridge from the current v-matrix to this next
                # ring system
                vma, zma_keys = continue_chain(gra, keys[:-1], vma, zma_keys,
                                               term_hydrogens=False)
                key = keys[-1]

                conn = bool(keys is not None)

            if conn:
                rsy = rsys.pop(idx)
                break

        assert keys is not None, "This is a disconnected graph!"

        # 2. Decompose the ring system with the connecting ring first
        rng_keys = next(rks for rks in rings_atom_keys(rsy) if key in rks)
        keys_lst = ring_system_decomposed_atom_keys(rsy, rng_keys=rng_keys)

        # 3. Build the next ring system
        vma, zma_keys = continue_ring_system(gra, keys_lst, vma, zma_keys)

    return vma, zma_keys