Graph

Class

class scine_molassembler.Graph

Molecular graph in which atoms are vertices and bonds are edges.

>>> import scine_utilities as utils
>>> ethane = io.experimental.from_smiles("CC")
>>> g = ethane.graph
>>> g.atoms_of_element(utils.ElementType.C)
[0, 1]
>>> g.degree(0)
4
>>> g.can_remove(0)
False
>>> g.can_remove(BondIndex(0, 1))
False
>>> hydrogen_indices = g.atoms_of_element(utils.ElementType.H)
>>> can_remove = lambda a : g.can_remove(a)
>>> all(map(can_remove, hydrogen_indices))
True
>>> g.V
8
>>> g.E
7
property B

The number of bonds in the graph

property E

The number of bonds in the graph

property N

The number of atoms in the graph

property V

The number of atoms in the graph

__init__(*args, **kwargs)
add_atom(self: scine_molassembler.Graph, bonded_to: Scine::Utils::ElementType, element: int, bond_type: scine_molassembler.BondType) int

Adds a bonded vertex to the graph

Warning

Do not edit Graph instances that are components of Molecule instances. Molecule must update its stereopermutators when a vertex in the graph is added. Use Molecule.add_atom instead. Modifying a component graph and then using the Molecule containing it can yield UB.

Parameters
  • bonded_to – The atom the new atom is bonded to

  • element – The element type of the new atom

  • bond_type – The bond type between bonded_to and element.

Returns

The atom index of the new vertex

add_bond(self: scine_molassembler.Graph, i: int, j: int, bond_type: scine_molassembler.BondType) scine_molassembler.BondIndex
Warning

Do not edit Graph instances that are components of Molecule instances. Molecule must update its stereopermutators when a bond in the graph is added. Use Molecule.add_bond instead. Modifying a component graph and then using the Molecule containing it can yield UB.

Raises

RuntimeError – If either vertex is out of range or the bond already exists.

adjacent(self: scine_molassembler.Graph, first_atom: int, second_atom: int) bool

Returns whether two atoms are bonded

>>> ethane = io.experimental.from_smiles("CC")
>>> ethane.graph.degree(0)
4
>>> [ethane.graph.adjacent(0, a) for a in range(1, ethane.graph.V)]
[True, True, True, True, False, False, False]
adjacents(self: scine_molassembler.Graph, a: int) Iterator

Iterate through all adjacent atom indices of an atom

>>> import scine_utilities as utils
>>> m = io.experimental.from_smiles("NC")
>>> [a for a in m.graph.adjacents(0)]
[1, 2, 3]
>>> element = lambda a: m.graph.element_type(a)
>>> [element(a) for a in m.graph.adjacents(0)]
[ElementType.C, ElementType.H, ElementType.H]
atoms(self: scine_molassembler.Graph) Iterator

Iterate through all valid atom indices of the graph

Fully equivalent to: range(graph.V)

atoms_of_element(self: scine_molassembler.Graph, element_type: Scine::Utils::ElementType) List[int]

Returns atoms matching an element type

>>> import scine_utilities as utils
>>> ethanol = io.experimental.from_smiles("CCO")
>>> ethanol.graph.atoms_of_element(utils.ElementType.O)
[2]
>>> ethanol.graph.atoms_of_element(utils.ElementType.C)
[0, 1]
bond_orders(self: scine_molassembler.Graph) Scine::Utils::BondOrderCollection

Generates a BondOrderCollection representation of the molecule connectivity

>>> # Convert acetaldehyde's graph into a floating point bond order matrix
>>> import scine_utilities as utils
>>> acetaldehyde = io.experimental.from_smiles("CC=O")
>>> bo = acetaldehyde.graph.bond_orders()
>>> bo.empty()
False
>>> bo.get_order(0, 1) # The order between the carbon atoms
1.0
>>> bo.get_order(1, 2) # The order between a carbon and oxygen
2.0
bond_type(self: scine_molassembler.Graph, bond_index: scine_molassembler.BondIndex) scine_molassembler.BondType

Fetches the BondType at a particular BondIndex

>>> # Look at some bond orders of an interesting model compound
>>> compound = io.experimental.from_smiles("[Co]1(C#N)(C#O)C=C1")
>>> g = compound.graph
>>> g.bond_type(BondIndex(0, 1)) == BondType.Single  # Co-CN bond
True
>>> g.bond_type(BondIndex(0, 5)) == BondType.Eta  # Co-C=C bond
True
>>> g.bond_type(BondIndex(5, 6)) == BondType.Double  # C=C bond
True
>>> g[BondIndex(1, 2)] == BondType.Triple  # C#N bond by bond subsetting
True
bonds(*args, **kwargs)

Overloaded function.

  1. bonds(self: scine_molassembler.Graph) -> Iterator

    Iterate through all valid bond indices of the graph

    >>> import scine_utilities as utils
    >>> model = io.experimental.from_smiles("F/C=C/I")
    >>> [b for b in model.graph.bonds()]
    [(0, 1), (1, 2), (2, 3), (1, 4), (2, 5)]
    
  2. bonds(self: scine_molassembler.Graph, a: int) -> Iterator

    Iterate through all incident bonds of an atom

    >>> import scine_utilities as utils
    >>> m = io.experimental.from_smiles("NC")
    >>> [b for b in m.graph.bonds(0)]
    [(0, 1), (0, 2), (0, 3)]
    
can_remove(*args, **kwargs)

Overloaded function.

  1. can_remove(self: scine_molassembler.Graph, atom: int) -> bool

    Returns whether an atom can be removed without disconnecting the graph

    >>> # In graph terms, articulation vertices cannot be removed
    >>> methane = io.experimental.from_smiles("C")
    >>> methane.graph.can_remove(0) # We cannot remove the central carbon
    False
    >>> all([methane.graph.can_remove(i) for i in range(1, 5)]) # But hydrogens!
    True
    
  2. can_remove(self: scine_molassembler.Graph, bond_index: scine_molassembler.BondIndex) -> bool

    Returns whether a bond can be removed without disconnecting the graph

    >>> # In graph terms, bridge edges cannot be removed
    >>> import scine_utilities as utils
    >>> from itertools import combinations
    >>> cyclopropane = io.experimental.from_smiles("C1CC1")
    >>> carbon_atoms = cyclopropane.graph.atoms_of_element(utils.ElementType.C)
    >>> cc_bonds = [BondIndex(a, b) for (a, b) in combinations(carbon_atoms, 2)]
    >>> can_remove = lambda b: cyclopropane.graph.can_remove(b)
    >>> all(map(can_remove, cc_bonds)) # We can remove any one of the bonds
    True
    >>> cyclopropane.remove_bond(cc_bonds[0]) # Remove one C-C bond
    >>> any(map(can_remove, cc_bonds[1:])) # Can we still remove any of the others?
    False
    
property cycles

Fetch a reference to cycles information

degree(self: scine_molassembler.Graph, atom: int) int

Returns the number of bonds incident upon an atom.

>>> # A silly example
>>> model = io.experimental.from_smiles("CNO[H]")
>>> [model.graph.degree(i) for i in range(0, 4)]
[4, 3, 2, 1]
element_type(self: scine_molassembler.Graph, atom: int) Scine::Utils::ElementType

Fetch the element type of an atom

>>> # Some isotopes
>>> import scine_utilities as utils
>>> m = io.experimental.from_smiles("[1H]C([2H])([3H])[H]")
>>> m.graph.element_type(0)
ElementType.H1
>>> m.graph.element_type(2)
ElementType.D
>>> m.graph[4] # Subsettable with atom indices to get element types
ElementType.H
elements(self: scine_molassembler.Graph) List[Scine::Utils::ElementType]

Generates an ElementCollection representation of the molecule’s atoms’ element types

>>> # Some isotopes
>>> import scine_utilities as utils
>>> m = io.experimental.from_smiles("[1H]C([2H])([3H])[H]")
>>> m.graph.elements()
[ElementType.H1, ElementType.C, ElementType.D, ElementType.T, ElementType.H]
remove_atom(self: scine_molassembler.Graph, atom_index: int) None

Removes a vertex from the graph.

Warning

Do not edit Graph instances that are components of Molecule instances. Molecule must update its stereopermutators when a vertex in the graph is removed. Use Molecule.remove_atom instead. Modifying a component graph and then using the Molecule containing it can yield UB.

Raises

RuntimeError – If the bond does not exist in the graph or if removing it would disconnect the graph (see Graph.can_remove).

remove_bond(self: scine_molassembler.Graph, bond: scine_molassembler.BondIndex) None

Removes a bond from the graph.

Warning

Do not edit Graph instances that are components of Molecule instances. Molecule must update its stereopermutators when an edge in the graph is removed. Use Molecule.remove_bond instead. Modifying a component graph and then using the Molecule containing it can yield UB.

Raises

RuntimeError – If the bond does not exist in the graph or if removing it would disconnect the graph (see Graph.can_remove).

>>> # Let's linearize acenaphythlene, a tricyclic aromatic molecule
>>> acenaphtyhlene_smiles = "C1=CC2=C3C(=C1)C=CC3=CC=C2"
>>> acenaphthylene = io.experimental.from_smiles(acenaphtyhlene_smiles)
>>> from copy import deepcopy
>>> graph = deepcopy(acenaphthylene.graph)  # Never modify a molecule's graph in-place
>>> graph.E
22
>>> can_remove = [b for b in graph.bonds() if graph.can_remove(b)]
>>> while len(can_remove) != 0:
...     graph.remove_bond(can_remove[0])
...     # Have to re-evaluate this!
...     can_remove = [b for b in graph.bonds() if graph.can_remove(b)]
...
>>> graph.E
19
split_along_bridge(self: scine_molassembler.Graph, bridge_bond: scine_molassembler.BondIndex) Tuple[List[int], List[int]]

Determine which atoms belong to either side of a bond

>>> # Hypothetically splitting a model compound
>>> m = io.experimental.from_smiles("CN")
>>> m.graph.split_along_bridge(BondIndex(0, 1))
([0, 2, 3, 4], [1, 5, 6])

Free functions

scine_molassembler.distance(source: int, graph: scine_molassembler.Graph) List[int]

Calculates graph distances from a single atom index to all others

>>> m = io.experimental.from_smiles("CC(CC)C")
>>> distances = distance(1, m.graph)