{"cells":[{"metadata":{},"cell_type":"markdown","source":"This is how you could compute basic edge features as angles between all atom pairs, dihedral angles between all triplets and shortest path (i.e. number of bonds) between all atoms. RDKit is used for everything."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":false,"_kg_hide-output":true},"cell_type":"code","source":"import sys\n!conda install --yes --prefix {sys.prefix} -c rdkit rdkit","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-input":false,"_kg_hide-output":true},"cell_type":"code","source":"%%bash -e\nif ! [[ -f ./xyz2mol.py ]]; then\n  wget https://raw.githubusercontent.com/jensengroup/xyz2mol/master/xyz2mol.py\nfi","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"# Imports\n\n# Standard library\nimport pickle\n\n# Basic imports\nimport numpy as np\nimport pandas as pd\n\n# rdkit & xyz2mol\nimport rdkit\nfrom rdkit import Chem\nfrom rdkit.Chem.rdmolops import SanitizeFlags\nfrom rdkit.Chem import rdMolTransforms\n\n# https://github.com/jensengroup/xyz2mol\nfrom xyz2mol import xyz2mol, xyz2AC, AC2mol, read_xyz_file\nfrom pathlib import Path\nimport pickle\n\nfrom tqdm.auto import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"CACHEDIR = Path('./')\n\ndef chiral_stereo_check(mol):\n    Chem.SanitizeMol(mol, SanitizeFlags.SANITIZE_ALL - SanitizeFlags.SANITIZE_PROPERTIES)\n    Chem.DetectBondStereochemistry(mol,-1)\n    return mol\n\ndef xyz2mol(atomicNumList,charge,xyz_coordinates,charged_fragments,quick):\n    AC,mol = xyz2AC(atomicNumList,xyz_coordinates)\n    new_mol = AC2mol(mol,AC,atomicNumList,charge,charged_fragments,quick)\n    new_mol = chiral_stereo_check(new_mol)\n    return new_mol\n\ndef MolFromXYZ(filename):\n    charged_fragments = True\n    quick = True\n    try:\n        atomicNumList, charge, xyz_coordinates = read_xyz_file(filename)\n        mol = xyz2mol(atomicNumList, charge, xyz_coordinates, charged_fragments, quick)\n    except:\n        print(filename)\n    return atomicNumList, mol\n\ndef MolFromXYZ_(filename):\n    return filename.stem, MolFromXYZ(filename)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"def symmetrize(matrix):\n    return matrix + matrix.T - np.diag(matrix.diagonal())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"train_df = pd.read_csv(\"../input/train.csv\")\ntest_df = pd.read_csv(\"../input/test.csv\")\nstructures = pd.read_csv(\"../input/structures.csv\")\ndftr = structures[[\"molecule_name\"]]\ndftr = dftr.drop_duplicates()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"list_of_shortest_paths = list()\nlist_of_angles = list()\nlist_of_dihedrals = list()\nfor i, row in tqdm(dftr.iterrows()):\n    name = row[\"molecule_name\"]\n    path = Path(f'../input/structures/{name}.xyz')\n    ats, molecule = MolFromXYZ(path)\n    conformer = molecule.GetConformer(0)\n    N_atoms = molecule.GetNumAtoms()\n    matrix_of_shortest_paths = np.zeros((N_atoms, N_atoms), dtype=\"int32\")\n    matrix_of_angles = np.zeros((N_atoms, N_atoms))\n    matrix_of_dihedral_angles = np.zeros((N_atoms, N_atoms))\n    for i in range(N_atoms):\n        for j in range(i+1, N_atoms):\n            shortest_path_indices = Chem.GetShortestPath(molecule, i, j)\n            length_of_shortest_path = len(shortest_path_indices) - 1 \n            matrix_of_shortest_paths[i, j] = length_of_shortest_path\n            if length_of_shortest_path == 2:\n                angle = np.abs(rdMolTransforms.GetAngleDeg(conformer, *shortest_path_indices))\n                matrix_of_angles[i, j] = rdMolTransforms.GetAngleDeg(conformer, *shortest_path_indices)\n            elif length_of_shortest_path == 3:\n                matrix_of_dihedral_angles[i, j] = rdMolTransforms.GetDihedralDeg(conformer, *shortest_path_indices)\n                if np.isnan(matrix_of_dihedral_angles[i, j]):\n                    matrix_of_dihedral_angles[i, j] = 0.0\n    list_of_shortest_paths.append(symmetrize(matrix_of_shortest_paths))\n    list_of_angles.append(symmetrize(matrix_of_angles))\n    list_of_dihedrals.append(symmetrize(matrix_of_dihedral_angles))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"with open(\"BasicShortestPathMatrices.pkl\", \"wb\") as f:\n    pickle.dump(list_of_shortest_paths, f)\nwith open(\"BasicAnglesMatrices.pkl\", \"wb\") as f:\n    pickle.dump(list_of_angles, f)\nwith open(\"BasicDihedralsMatrices.pkl\", \"wb\") as f:\n    pickle.dump(list_of_dihedrals, f)","execution_count":null,"outputs":[]}],"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}