{"cells":[{"metadata":{},"cell_type":"markdown","source":"Chemical bonds could be useful in this competition. MatthewMasters hinted in [this thread](https://www.kaggle.com/c/champs-scalar-coupling/discussion/93928#latest-553167) that we could use OpenBabel to extract the bond information automatically. If, like me, you are unfamiliar with OpenBabel, this kernel will show you how to use that library to get the bonds.\n\nWe need to install OpenBabel first. You can install the package directly under \"Settings\" on the right side of the editor, or use the following command:"},{"metadata":{"trusted":true,"_kg_hide-input":false,"_kg_hide-output":true},"cell_type":"code","source":"!conda install -c openbabel openbabel -y","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We want to read all the files in ../input/structures and let OpenBabel figure out the chemical bonds for each molecule. We will save the results into a new dataframe similar to the ones we already have."},{"metadata":{"trusted":true},"cell_type":"code","source":"import openbabel\nimport os\nimport pandas as pd","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path = '../input/structures/'\n\n# Initialize the OpenBabel object that we will use later.\nobConversion = openbabel.OBConversion()\nobConversion.SetInFormat(\"xyz\")\n\n# Define containers\nmol_index = [] # This will be our dataframe index\nbond_atom_0 = []\nbond_atom_1 = []\nbond_order = []\nbond_length = []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for f in os.scandir(path):\n    # Initialize an OBMol object\n    mol = openbabel.OBMol()\n    read_ok = obConversion.ReadFile(mol, f.path)\n    if not read_ok:\n        # There was an error reading the file\n        raise Exception(f'Could not read file {f.path}')\n    \n    mol_name = f.name[:-4] \n    mol_index.extend([mol_name] * mol.NumBonds()) # We need one entry per bond\n    \n    # Extract bond information\n    mol_bonds = openbabel.OBMolBondIter(mol) # iterate over all the bonds in the molecule\n    for bond in mol_bonds:\n        bond_atom_0.append(bond.GetBeginAtomIdx() - 1) # Must be 0-indexed\n        bond_atom_1.append(bond.GetEndAtomIdx() - 1)\n        bond_length.append(bond.GetLength())\n        bond_order.append(bond.GetBondOrder())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Put everything into a dataframe\ndf = pd.DataFrame({'molecule_name': mol_index,\n                   'atom_0': bond_atom_0,\n                   'atom_1': bond_atom_1,\n                   'order': bond_order,\n                   'length': bond_length})\n    \ndf = df.sort_values(['molecule_name', 'atom_0', 'atom_1']).reset_index(drop=True)    \n\nprint(df.head(10))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# My favorite way of storing variables\nimport shelve\nwith shelve.open('vars.shelf') as shelf:\n    shelf['bonds'] = df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# To load the variable later, use:\nwith shelve.open('vars.shelf') as shelf:\n    bonds = shelf['bonds']","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We should use this information with care. OpenBabel might fail to get the bonds right for some of the more exotic molecules. See [here](https://www.kaggle.com/c/champs-scalar-coupling/discussion/94755#546968) and [here](https://www.kaggle.com/c/champs-scalar-coupling/discussion/94117#latest-542356).\n\nAlso note that other users have proposed different ways of extracting bond information:\n* https://www.kaggle.com/aekoch95/bonds-from-structure-data\n* https://www.kaggle.com/asauve/dataset-with-number-of-bonds-between-atoms"}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}