Source code for besmarts.core.topology

"""
besmarts.core.topology

Topology in BESMARTS describe the structure of a graph, and are a necessary
component of structure graphs.
"""

from typing import Sequence, Tuple
from itertools import permutations


[docs] class structure_topology: """ The structure topology describes several properties of a graph that allow it to be a structure. The data in a structure is agnostic to the graph and uses relative indexing of the nodes. All graphs that have the same structure, such as angles, use the same topology. """ __slots__ = ("primary", "connect", "permutations") def __init__( self, primary: Sequence[int], connect: Sequence[Tuple[int, int]], permutations: Sequence[Sequence[int]], ): self.primary = primary self.connect = connect self.permutations = permutations def __eq__(self, o): return ( self.primary == o.primary and self.connect == o.connect and self.permutations == o.permutations ) def __neq__(self, o): return not self.__eq__(o) def __hash__(self): return hash((self.primary, self.connect, self.permutations))
[docs] class transcode_topology: """ A pair of topologies that defines a transformation from A to B """ __slots__ = ("A", "B", "transcode") def __init__( self, A: structure_topology, B: structure_topology, transcode, ): self.A: structure_topology= A self.B: structure_topology= B self.transcode: Dict[Sequence[Sequence[int]], Sequence[Sequence[int]]] = transcode def __eq__(self, o): return ( self.A == o.A and self.B == o.B and self.transcode == o.transcode ) def __neq__(self, o): return not self.__eq__(o) def __hash__(self): return hash((self.A, self.B, self.transcode))
[docs] def null_topology() -> structure_topology: """ Return a topology that describes a null/undefined topology. This is used when the data/structures describe don't have a well defined graph topology, such as entire molecules where the permutations aren't known. Parameters ---------- Returns ------- structure_topology """ return structure_topology((), (), ((),))
[docs] def atom_topology() -> structure_topology: """ Return a topology that describes an atom Parameters ---------- Returns ------- structure_topology """ return structure_topology((0,), (), ((0,),))
[docs] def bond_topology() -> structure_topology: """ Return a topology that describes a bond Parameters ---------- Returns ------- structure_topology """ return structure_topology((0, 1), ((0, 1),), ((0, 1), (1, 0)))
[docs] def angle_topology() -> structure_topology: """ Return a topology that describes an angle Parameters ---------- Returns ------- structure_topology """ return structure_topology( (0, 1, 2), ((0, 1), (1, 2)), ((0, 1, 2), (2, 1, 0)) )
[docs] def torsion_topology() -> structure_topology: """ Return a topology that describes a torsion dihedral Parameters ---------- Returns ------- structure_topology """ return structure_topology( (0, 1, 2, 3), ((0, 1), (1, 2), (2, 3)), ((0, 1, 2, 3), (3, 2, 1, 0)) )
[docs] def outofplane_topology() -> structure_topology: """ Return a topology that describes an out-of-plane dihedral Parameters ---------- Returns ------- structure_topology """ return structure_topology( (0, 1, 2, 3), ((0, 1), (1, 2), (1, 3)), ( (0, 1, 2, 3), (0, 1, 3, 2), (2, 1, 0, 3), (2, 1, 3, 0), (3, 1, 0, 2), (3, 1, 2, 0), ), )
[docs] def chain_topology(n: int) -> structure_topology: """ Return a topology that describes an arbitrary linear sequence of atoms. Parameters ---------- n : int The length of the chain Returns ------- structure_topology """ return structure_topology( tuple(range(n)), tuple(((i, i + 1) for i in range(n))), (tuple(range(n)), tuple(reversed(range(n)))), )
[docs] def ring_topology(n: int) -> structure_topology: """ Return a topology that describes a ring of atoms of arbitrary length. Parameters ---------- n : int The length of the ring Returns ------- structure_topology """ cycles = tuple(tuple(i % n for i in range(j, n + j)) for j in range(n - 1)) return structure_topology( tuple(range(n)), tuple(((i, (i + 1) % n) for i in range(n))), (*cycles, *(tuple(reversed(x)) for x in cycles)), )
[docs] def n_body_topology(n: int) -> structure_topology: """ Return a topology that describes n nonbonded atoms Parameters ---------- n : int The number of bodies Returns ------- structure_topology """ return structure_topology( tuple(range(n)), (), tuple((tuple(x) for x in permutations(range(n), n))), )
[docs] def pair_topology() -> structure_topology: """ Return a topology that describes a pair, or a set of atoms that may not be bonded Parameters ---------- Returns ------- structure_topology """ return n_body_topology(2)
# Singletons null = null_topology() atom = atom_topology() bond = bond_topology() angle = angle_topology() torsion = torsion_topology() outofplane = outofplane_topology() pair = n_body_topology(2) triplet = n_body_topology(3) atom_to_atom = transcode_topology( atom, atom, {((0,),) : ((0,),)} ) # 2x1 bond_to_atom = transcode_topology( bond, atom, [[1],[1]] ) # 3x1 mapping # each have an equal weight angle_to_atom = transcode_topology( angle, atom, [[1],[1],[1]] ) torsion_to_atom = transcode_topology( torsion, atom, {((0,), (1,), (2,), (3,)) : ((0,1,2,3),)} ) torsion_to_bond = transcode_topology( torsion, bond, {0:0, 1:0, 2:1, 3:1} ) topology_index = [ null, atom, bond, angle, torsion, outofplane, pair, triplet, ]
[docs] def index_of(topo: structure_topology): return topology_index.index(topo)