Bond Class¶
This tutorial is meant to illustrate some of the properties and functionality available within the Bond class.
[111]:
# Imports necessary packages and checks the version of molli.
import molli as ml
ml.aux.assert_molli_version_min("1.0a")
#Loads in the dendrobine molecule
mol = ml.load(ml.files.benzene_mol2)
Each Molecule has a list of bonds in a defined order. Individual bonds can be retrieved in a fashion similar in how to retrieve an Atom:
[112]:
ex_bond1 = mol.get_bond(0)
ex_bond1
[112]:
Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=1, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
Bonds have quite a few important properties
[113]:
ex_bond1.as_dict()
[113]:
{'a1': {'element': C,
'isotope': None,
'label': 'C',
'atype': <AtomType.Aromatic: 2>,
'stereo': <AtomStereo.Unknown: 0>,
'geom': <AtomGeom.Unknown: 0>,
'formal_charge': 0,
'formal_spin': 0,
'attrib': {},
'_parent': <weakref at 0x7fd77b19a0c0; to 'Molecule' at 0x7fd77afedb50>},
'a2': {'element': C,
'isotope': None,
'label': 'C',
'atype': <AtomType.Aromatic: 2>,
'stereo': <AtomStereo.Unknown: 0>,
'geom': <AtomGeom.Unknown: 0>,
'formal_charge': 0,
'formal_spin': 0,
'attrib': {},
'_parent': <weakref at 0x7fd77b19a0c0; to 'Molecule' at 0x7fd77afedb50>},
'label': None,
'btype': <BondType.Aromatic: 20>,
'stereo': <BondStereo.Unknown: 0>,
'f_order': 1.0,
'attrib': {},
'_parent': <weakref at 0x7fd77b19a0c0; to 'Molecule' at 0x7fd77afedb50>}
Here’s an example of individual atoms of the bond can be quickly called upon
[114]:
#This calls Atom 1 of the bond
atom1 = ex_bond1.a1
#This calls Atom2 of a bond
atom2 = ex_bond1.a2
atom2
[114]:
Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0)
An important note about bonds is that a1 (atom 1) and a2 (atom2) are somewhat arbitrary depending on how the molecule was constructed/read in. Another option that can be come useful when looking is using the modulus (%) operator.
[115]:
#This finds the other atom a part of the bond
other_atom = ex_bond1 % atom2
#This checks if atom1 is equal to the other_atom
atom1 == other_atom
[115]:
True
molli implements that functionality to find atoms connected other atoms quickly
[116]:
#This finds the atoms also connected to atom2
connected_atoms = [a for a in mol.connected_atoms(atom2)]
connected_atoms
[116]:
[Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0),
Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0),
Atom(element=H, isotope=None, label='H', formal_charge=0, formal_spin=0)]
molli also implements functionality to find the bonds associated with other atoms
[117]:
n_bonds_atom2 = mol.n_bonds_with_atom(atom2)
print(f'The number of bonds with Atom 2 = {n_bonds_atom2}')
bonds_from_atom = [b for b in mol.bonds_with_atom(atom2)]
bonds_from_atom
The number of bonds with Atom 2 = 3
[117]:
[Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=1, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0),
Bond(a1=1, a2=2, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0),
Bond(a1=1, a2=7, label=None, btype=Single, stereo=Unknown, f_order=1.0)]
Bond Deletion¶
Bonds can also be quickly deleted either through the direct deletion of atoms or bonds
[118]:
# Prints the index of the bond and the bond itself
for i, b in enumerate(mol.bonds):
print(format(i, "<5"), b)
0 Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=1, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
1 Bond(a1=1, a2=2, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
2 Bond(a1=2, a2=3, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
3 Bond(a1=3, a2=4, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
4 Bond(a1=4, a2=5, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
5 Bond(a1=5, a2=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
6 Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=6, label=None, btype=Single, stereo=Unknown, f_order=1.0)
7 Bond(a1=1, a2=7, label=None, btype=Single, stereo=Unknown, f_order=1.0)
8 Bond(a1=2, a2=8, label=None, btype=Single, stereo=Unknown, f_order=1.0)
9 Bond(a1=3, a2=9, label=None, btype=Single, stereo=Unknown, f_order=1.0)
10 Bond(a1=4, a2=10, label=None, btype=Single, stereo=Unknown, f_order=1.0)
11 Bond(a1=5, a2=11, label=None, btype=Single, stereo=Unknown, f_order=1.0)
Deleting an Atom will delete both the Atom and the bonds associated with that `Atom
[119]:
# Deletes the first atom in the molecule
mol.del_atom(0)
# Prints the updated bond list
for i, b in enumerate(mol.bonds):
print(format(i, "<5"), b)
0 Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=1, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
1 Bond(a1=1, a2=2, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
2 Bond(a1=2, a2=3, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
3 Bond(a1=3, a2=4, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
4 Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=6, label=None, btype=Single, stereo=Unknown, f_order=1.0)
5 Bond(a1=1, a2=7, label=None, btype=Single, stereo=Unknown, f_order=1.0)
6 Bond(a1=2, a2=8, label=None, btype=Single, stereo=Unknown, f_order=1.0)
7 Bond(a1=3, a2=9, label=None, btype=Single, stereo=Unknown, f_order=1.0)
8 Bond(a1=4, a2=10, label=None, btype=Single, stereo=Unknown, f_order=1.0)
Deleting a Bond will ONLY delete the `Bond`` and still maintain the same number of atoms
[120]:
print(f'The number of atoms before deleting a bond = {mol.n_atoms}')
#This gets the first bond in the list
ex_bond = mol.get_bond(0)
# Deletes the first bond in the molecule
mol.del_bond(ex_bond)
print(f'The number of atoms after deleting a bond = {mol.n_atoms}')
# Prints the updated bond list
for i, b in enumerate(mol.bonds):
print(format(i, "<5"), b)
The number of atoms before deleting a bond = 11
The number of atoms after deleting a bond = 11
0 Bond(a1=1, a2=2, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
1 Bond(a1=2, a2=3, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
2 Bond(a1=3, a2=4, label=None, btype=Aromatic, stereo=Unknown, f_order=1.0)
3 Bond(a1=Atom(element=C, isotope=None, label='C', formal_charge=0, formal_spin=0), a2=6, label=None, btype=Single, stereo=Unknown, f_order=1.0)
4 Bond(a1=1, a2=7, label=None, btype=Single, stereo=Unknown, f_order=1.0)
5 Bond(a1=2, a2=8, label=None, btype=Single, stereo=Unknown, f_order=1.0)
6 Bond(a1=3, a2=9, label=None, btype=Single, stereo=Unknown, f_order=1.0)
7 Bond(a1=4, a2=10, label=None, btype=Single, stereo=Unknown, f_order=1.0)
Other Miscellaneous Properties of Bonds¶
Bond coordinates can be retrieved as follows
[121]:
#This gets the first bond in the list
ex_bond = mol.get_bond(0)
# These are the coordinates of the atoms attached to the bond
mol.bond_coords(ex_bond)
[121]:
array([[-3.8438, -0.82 , -0. ],
[-2.7152, -1.6396, -0. ]])
The Bond length can be retrieved as follows
[122]:
#This gets the length of a bond
mol.bond_length(ex_bond)
[122]:
1.3948054057824697
Bonds can also be found using atoms and indexed
[123]:
#This finds the bond whose atoms 5 and 11 are associated with the bond
ex_bond = mol.lookup_bond(3, 9)
#This finds the index of the bond found
mol.index_bond(ex_bond)
[123]:
6
The vector created by the bond can also be called
[124]:
mol.bond_vector(ex_bond)
[124]:
array([ 0.8793, -0.6386, 0. ])
Much like the Atom class, the Bond class allows for storage of arbitrary objects. Here is an example
[125]:
#Gets the first bond
ex_bond = mol.get_bond(0)
print(f'Current attribute list for an Example Bond')
ex_bond.attrib["List"] = [0,1,2]
ex_bond.attrib["Tuple"] = ('a','b','c')
ex_bond.attrib["Dictionary"] = {"Data": (0.1, 0.2, 0.3)}
ex_bond.attrib
Current attribute list for an Example Bond
[125]:
{'List': [0, 1, 2],
'Tuple': ('a', 'b', 'c'),
'Dictionary': {'Data': (0.1, 0.2, 0.3)}}