{"cells":[{"metadata":{},"cell_type":"markdown","source":"Most people are using distance features, but not using **ANGLE** features. My teacher 'Google' taught me that the angles among atoms are important to estimate molecular properties. Let me show some examples in this kernel."},{"metadata":{},"cell_type":"markdown","source":"## Import & Load"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nwarnings.filterwarnings(action=\"ignore\",category=DeprecationWarning)\nwarnings.filterwarnings(action=\"ignore\",category=FutureWarning)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"df_train=pd.read_csv('../input/train.csv')\n#df_test=pd.read_csv('../input/test.csv')\ndf_struct=pd.read_csv('../input/structures.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I use this great kernel to get x,y,z position. https://www.kaggle.com/seriousran/just-speed-up-calculate-distance-from-benchmark"},{"metadata":{"trusted":true},"cell_type":"code","source":"def map_atom_info(df_1,df_2, atom_idx):\n    df = pd.merge(df_1, df_2, how = 'left',\n                  left_on  = ['molecule_name', f'atom_index_{atom_idx}'],\n                  right_on = ['molecule_name',  'atom_index'])\n    df = df.drop('atom_index', axis=1)\n\n    return df\nfor atom_idx in [0,1]:\n    df_train = map_atom_info(df_train,df_struct, atom_idx)\n    df_train = df_train.rename(columns={'atom': f'atom_{atom_idx}',\n                                        'x': f'x_{atom_idx}',\n                                        'y': f'y_{atom_idx}',\n                                        'z': f'z_{atom_idx}'})","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create Features\nLet's get the distance between atoms first."},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_features(df):\n    df['dx']=df['x_1']-df['x_0']\n    df['dy']=df['y_1']-df['y_0']\n    df['dz']=df['z_1']-df['z_0']\n    df['distance']=(df['dx']**2+df['dy']**2+df['dz']**2)**(1/2)\n    return df\ndf_train=make_features(df_train)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Next, find the coupled atom of atom_1 and atom_2. I'd like to use the distance to get the coupled atom(closest atom). You can use 'type' feature instead."},{"metadata":{"trusted":true},"cell_type":"code","source":"#I apologize for my poor coding skill. Please make the better one.\nprint(df_train.shape)\ndf_temp=df_train.loc[:,[\"molecule_name\",\"atom_index_0\",\"atom_index_1\",\"distance\",\"x_0\",\"y_0\",\"z_0\",\"x_1\",\"y_1\",\"z_1\"]].copy()\n\ndf_temp_=df_temp.copy()\ndf_temp_= df_temp_.rename(columns={'atom_index_0': 'atom_index_1',\n                                   'atom_index_1': 'atom_index_0',\n                                   'x_0': 'x_1',\n                                   'y_0': 'y_1',\n                                   'z_0': 'z_1',\n                                   'x_1': 'x_0',\n                                   'y_1': 'y_0',\n                                   'z_1': 'z_0'})\ndf_temp=pd.concat((df_temp,df_temp_),axis=0)\n\ndf_temp[\"min_distance\"]=df_temp.groupby(['molecule_name', 'atom_index_0'])['distance'].transform('min')\ndf_temp= df_temp[df_temp[\"min_distance\"]==df_temp[\"distance\"]]\n\ndf_temp=df_temp.drop(['x_0','y_0','z_0','min_distance'], axis=1)\ndf_temp= df_temp.rename(columns={'atom_index_0': 'atom_index',\n                                 'atom_index_1': 'atom_index_closest',\n                                 'distance': 'distance_closest',\n                                 'x_1': 'x_closest',\n                                 'y_1': 'y_closest',\n                                 'z_1': 'z_closest'})\n\nprint(df_temp.duplicated(subset=['molecule_name', 'atom_index']).value_counts())\n#delete duplicated rows (some atom pairs have perfectly same distance)\n#This code is added based on Adriano Avelar's comment.\ndf_temp=df_temp.drop_duplicates(subset=['molecule_name', 'atom_index'])\n\nfor atom_idx in [0,1]:\n    df_train = map_atom_info(df_train,df_temp, atom_idx)\n    df_train = df_train.rename(columns={'atom_index_closest': f'atom_index_closest_{atom_idx}',\n                                        'distance_closest': f'distance_closest_{atom_idx}',\n                                        'x_closest': f'x_closest_{atom_idx}',\n                                        'y_closest': f'y_closest_{atom_idx}',\n                                        'z_closest': f'z_closest_{atom_idx}'})\n\nprint(df_train.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now, I get xyz positions of 4 atoms.\n1. atom_0\n2. atom_1\n3. closest one to atom_0\n4. closest one to atom_1\nIf atom_1 is C or N, it has some connections. It's not considered here. "},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's get **cosine angles** by calculating dot product of vectors."},{"metadata":{"trusted":true},"cell_type":"code","source":"def add_cos_features(df):\n    df[\"distance_0\"]=((df['x_0']-df['x_closest_0'])**2+(df['y_0']-df['y_closest_0'])**2+(df['z_0']-df['z_closest_0'])**2)**(1/2)\n    df[\"distance_1\"]=((df['x_1']-df['x_closest_1'])**2+(df['y_1']-df['y_closest_1'])**2+(df['z_1']-df['z_closest_1'])**2)**(1/2)\n    df[\"vec_0_x\"]=(df['x_0']-df['x_closest_0'])/df[\"distance_0\"]\n    df[\"vec_0_y\"]=(df['y_0']-df['y_closest_0'])/df[\"distance_0\"]\n    df[\"vec_0_z\"]=(df['z_0']-df['z_closest_0'])/df[\"distance_0\"]\n    df[\"vec_1_x\"]=(df['x_1']-df['x_closest_1'])/df[\"distance_1\"]\n    df[\"vec_1_y\"]=(df['y_1']-df['y_closest_1'])/df[\"distance_1\"]\n    df[\"vec_1_z\"]=(df['z_1']-df['z_closest_1'])/df[\"distance_1\"]\n    df[\"vec_x\"]=(df['x_1']-df['x_0'])/df[\"distance\"]\n    df[\"vec_y\"]=(df['y_1']-df['y_0'])/df[\"distance\"]\n    df[\"vec_z\"]=(df['z_1']-df['z_0'])/df[\"distance\"]\n    df[\"cos_0_1\"]=df[\"vec_0_x\"]*df[\"vec_1_x\"]+df[\"vec_0_y\"]*df[\"vec_1_y\"]+df[\"vec_0_z\"]*df[\"vec_1_z\"]\n    df[\"cos_0\"]=df[\"vec_0_x\"]*df[\"vec_x\"]+df[\"vec_0_y\"]*df[\"vec_y\"]+df[\"vec_0_z\"]*df[\"vec_z\"]\n    df[\"cos_1\"]=df[\"vec_1_x\"]*df[\"vec_x\"]+df[\"vec_1_y\"]*df[\"vec_y\"]+df[\"vec_1_z\"]*df[\"vec_z\"]\n    df=df.drop(['vec_0_x','vec_0_y','vec_0_z','vec_1_x','vec_1_y','vec_1_z','vec_x','vec_y','vec_z'], axis=1)\n    return df\n    \ndf_train=add_cos_features(df_train)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I'd like to show some graph. You can see the obvious relationship between 'angle' and 'scalar_coupling_constant'."},{"metadata":{"trusted":true},"cell_type":"code","source":"mol_types=df_train[\"type\"].unique()\ndf_train_=df_train.iloc[:100000,:].copy()\n\nfig, ax = plt.subplots(8, 1, figsize=(8, 32))\nfor i, mol_type in enumerate(mol_types):\n    ax[i].scatter(df_train_.loc[df_train_['type'] ==mol_type][\"cos_0_1\"], df_train_.loc[df_train_['type'] == mol_type] ['scalar_coupling_constant'],s=10,alpha=0.3);\n    ax[i].set_title(str(mol_type))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mol_types=df_train[\"type\"].unique()\ndf_train_=df_train.iloc[:100000,:].copy()\n\nfig, ax = plt.subplots(8, 1, figsize=(8, 32))\nfor i, mol_type in enumerate(mol_types):\n    ax[i].scatter(df_train_.loc[df_train_['type'] ==mol_type][\"cos_0\"], df_train_.loc[df_train_['type'] == mol_type] ['scalar_coupling_constant'],s=10,alpha=0.3);\n    ax[i].set_title(str(mol_type))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mol_types=df_train[\"type\"].unique()\ndf_train_=df_train.iloc[:100000,:].copy()\n\nfig, ax = plt.subplots(8, 1, figsize=(8, 32))\nfor i, mol_type in enumerate(mol_types):\n    ax[i].scatter(df_train_.loc[df_train_['type'] ==mol_type][\"cos_1\"], df_train_.loc[df_train_['type'] == mol_type] ['scalar_coupling_constant'],s=10,alpha=0.3);\n    ax[i].set_title(str(mol_type))","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}