{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"markdown","source":"## **Adding Coloring Hack to 3D Visualization**\n![Before and After Color Hack Example](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F256034%2F8437314cf8ea8b244d91be549a4ad4b3%2F3D_view_color_hack_illustration2.jpg?generation=1563162851977006&alt=media)\n**Warning: **\n\n**Please don't attempt to convince your chemistry professor that you can randomly replace atoms in molecules \"because you saw pictures\" :) **\n\nThis kernel is based on Boris D's [How To: Easy Visualization of Molecules](https://www.kaggle.com/borisdee/how-to-easy-visualization-of-molecules)\nfor  [Predicting Molecular Properties](https://www.kaggle.com/c/champs-scalar-coupling/overview) challenge.\n\nIt is helpful to see the actual coupled atoms we are predicting. The following quick hack works quite well: replace the J-coupled atoms based on this dictionary: `{\"H\":\"He\",\"C\":\"Be\",\"N\":\"B\"}`. This tricks the visualizer into substituting differently colored spheres for the atoms in question. There must be a better way for this but this is the best I've got.\n\n**Don't attempt this with actual molecules in the lab because, at best, it won't work. In the worst case, you may hurt yourself. And wear protective goggles at all times if you do still want to try this despite my warning.**"},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport random\n\nstruct_file = pd.read_csv('../input/structures.csv')\ntrain = pd.read_csv('../input/train.csv')","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"!pip install ase  # added !pip install, Internet must be on. \n                  # Alternatively, use Boris's instructions: click on the *Settings* tab on the right panel, then click on *Install...*, \n                  # right next to *Packages*. In the *pip package name* entry, just write **ase** then hit *Install Package*. \n                  # Kaggle is going to do its things then restart the Kernel.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import ase\nfrom ase import Atoms\nimport ase.visualize","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Select molecule based on name. Will use this molecule to demonstrate the coloring scheme.\nmolecule = struct_file[struct_file['molecule_name'] == 'dsgdb9nsd_000010']\ndisplay(molecule)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Next we need to retrieve the atomic coordinates in a numpy array form:"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get atomic coordinates\natoms = molecule.iloc[:, 3:].values\nprint(atoms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The last thing we need is the atomic symbols:"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get atomic symbols\nsymbols = molecule.iloc[:, 2].values\nprint(symbols)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Finally, let's put everything into something that **ase** can process. You can rotate the molecule with a left click, translate it with a middle click, and zoom in or out using right click. "},{"metadata":{"trusted":true},"cell_type":"code","source":"system = Atoms(positions=atoms, symbols=symbols)\nase.visualize.view(system, viewer=\"x3d\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Here comes my quick and dirty hack to color two atoms that are J-coupled. J-coupled atoms are replaced based on the dictionary: `{\"H\":\"He\",\"C\":\"Be\",\"N\":\"B\"}`. This is chemically absurd but it happens to work for this visualization. Compare this visualization with the above molecule to see the new color scheme for J-coupled atoms in question: 'H' ='light blue', 'C' = 'light green', 'N' = 'pinkish tan'. The replaced atoms are of slightly different sizes: 'H' is slightly undersized, 'C' and 'N' are slightly oversized. This does not pose any obvious problems and, in any case, I did not find better size replacements."},{"metadata":{"trusted":true},"cell_type":"code","source":"my_dict = {\"H\":\"He\",\"C\":\"Be\",\"N\":\"B\"}\nprint(my_dict)\natom_index=(1,2,3)\n\njj_symbols=symbols.copy()\nfor k in atom_index:\n    if jj_symbols[k] in my_dict:\n        print (k, jj_symbols[k],my_dict[jj_symbols[k]])\n        jj_symbols[k]=my_dict[jj_symbols[k]]\n    else:\n        print(\"Atom is not in the dictionary\")\n        \nsystem = Atoms(positions=atoms, symbols=jj_symbols)\nase.visualize.view(system, viewer=\"x3d\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Below is the function that visualizes a molecule and colors the two atoms (optional). It uses row index from train dataframe to get molecule name and the J-coupled atom locations."},{"metadata":{"trusted":true},"cell_type":"code","source":"def view_jj(train_ix, df=train, color =True):\n    # Get molecule name and J-J indices\n    mol_jj = df.iloc[[train_ix],1:4]\n    atom_index=(mol_jj['atom_index_0'].values[0],mol_jj['atom_index_1'].values[0])\n    molecule = mol_jj['molecule_name'].values[0]\n    \n    # Select a molecule\n    mol = struct_file[struct_file['molecule_name'] == molecule]\n    \n    # Get atomic coordinates\n    xcart = mol.iloc[:, 3:].values\n    \n    # Get atomic symbols\n    symbols = mol.iloc[:, 2].values\n    \n    # Actual hack where J-J atoms we are predicted are substituted by approximately sized atoms of different colors:\n    jj_symbols=symbols.copy()\n    if color == True:\n        for k in atom_index:\n            if jj_symbols[k] in my_dict:\n                print (k, jj_symbols[k],my_dict[jj_symbols[k]])\n                jj_symbols[k]=my_dict[jj_symbols[k]]\n            else:\n                print(\"Atom is not in the dictionary\")\n    \n    # Display molecule\n    system = Atoms(positions=xcart, symbols=jj_symbols)\n       \n    #system = Atoms(positions=xcart, symbols=symbols)\n    print('Molecule Name: %s.' %molecule)\n    return ase.visualize.view(system, viewer=\"x3d\")\n\nview_jj(665999)\n#view_jj(665999, color=False)  # Uncomment to see the original version without atom replacement","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let me know if there is a better way to add J-coupled atoms to an interactive 3D viewer. I am new to Python so any code suggestions are highly appreciated. \n\nAnd last but not least: **Vote early and vote often! ;) **"}],"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}