{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:10:03.989624Z","iopub.execute_input":"2025-08-18T06:10:03.99037Z","iopub.status.idle":"2025-08-18T06:10:04.010487Z","shell.execute_reply.started":"2025-08-18T06:10:03.990336Z","shell.execute_reply":"2025-08-18T06:10:04.009614Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T07:06:31.999629Z","iopub.execute_input":"2025-08-18T07:06:32.000014Z","iopub.status.idle":"2025-08-18T07:07:02.286003Z","shell.execute_reply.started":"2025-08-18T07:06:31.999982Z","shell.execute_reply":"2025-08-18T07:07:02.284958Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#print(list(df.columns))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:10:41.465246Z","iopub.execute_input":"2025-08-18T06:10:41.465537Z","iopub.status.idle":"2025-08-18T06:10:41.471033Z","shell.execute_reply.started":"2025-08-18T06:10:41.465512Z","shell.execute_reply":"2025-08-18T06:10:41.470205Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T07:07:02.2876Z","iopub.execute_input":"2025-08-18T07:07:02.287933Z","iopub.status.idle":"2025-08-18T07:07:02.311294Z","shell.execute_reply.started":"2025-08-18T07:07:02.287901Z","shell.execute_reply":"2025-08-18T07:07:02.310183Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# summarized DataFrame for display\ndata = [\n    {\"Category\": \"Identifiers\", \"Columns\": \"row_id, sequence_type, sequence_id, sequence_counter\", \"Count\": 4, \"Description\": \"Unique identifiers for rows and sequences\"},\n    {\"Category\": \"Metadata\", \"Columns\": \"subject, orientation, behavior, phase, gesture\", \"Count\": 5, \"Description\": \"Contextual information about the data\"},\n    {\"Category\": \"Accelerometer\", \"Columns\": \"acc_x, acc_y, acc_z\", \"Count\": 3, \"Description\": \"Acceleration data in three axes\"},\n    {\"Category\": \"Rotation\", \"Columns\": \"rot_w, rot_x, rot_y, rot_z\", \"Count\": 4, \"Description\": \"Quaternion rotation data\"},\n    {\"Category\": \"Thermometer\", \"Columns\": \"thm_1, thm_2, thm_3, thm_4, thm_5\", \"Count\": 5, \"Description\": \"Temperature sensor readings\"},\n    {\"Category\": \"TOF Sensor 1\", \"Columns\": \"tof_1_v0 to tof_1_v63\", \"Count\": 64, \"Description\": \"Time-of-Flight sensor 1 values (0–63)\"},\n    {\"Category\": \"TOF Sensor 2\", \"Columns\": \"tof_2_v0 to tof_2_v63\", \"Count\": 64, \"Description\": \"Time-of-Flight sensor 2 values (0–63)\"},\n    {\"Category\": \"TOF Sensor 3\", \"Columns\": \"tof_3_v0 to tof_3_v63\", \"Count\": 64, \"Description\": \"Time-of-Flight sensor 3 values (0–63)\"},\n    {\"Category\": \"TOF Sensor 4\", \"Columns\": \"tof_4_v0 to tof_4_v63\", \"Count\": 64, \"Description\": \"Time-of-Flight sensor 4 values (0–63)\"},\n    {\"Category\": \"TOF Sensor 5\", \"Columns\": \"tof_5_v0 to tof_5_v63\", \"Count\": 64, \"Description\": \"Time-of-Flight sensor 5 values (0–63)\"}\n]\n\n\n# Style the DataFrame\nstyled_df = pd.DataFrame(data).style.set_properties(**{\n    'text-align': 'left',\n    'font-size': '12px',\n    'border-color': '#4a4a4a',\n    'border-style': 'solid',\n    'border-width': '1px',\n    'padding': '5px',\n    'white-space': 'pre-wrap'\n}).set_table_styles([\n    {'selector': 'th', 'props': [('background-color', '#2b3e50'), ('color', 'white'), ('font-weight', 'bold'), ('text-align', 'center'), ('padding', '8px')]},\n    {'selector': 'td', 'props': [('background-color', '#f7f7f7'), ('color', '#333333')]},\n    {'selector': 'tr:nth-child(even) td', 'props': [('background-color', '#e8ecef')]},\n    {'selector': 'table', 'props': [('border-collapse', 'collapse'), ('width', '100%'), ('max-width', '1000px'), ('margin', '0 auto')]}\n]).set_caption(\"Column Categories Overview\")\n\n# Display the styled DataFrame\nstyled_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:10:41.472287Z","iopub.execute_input":"2025-08-18T06:10:41.472596Z","iopub.status.idle":"2025-08-18T06:10:41.595204Z","shell.execute_reply.started":"2025-08-18T06:10:41.472574Z","shell.execute_reply":"2025-08-18T06:10:41.594383Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.behavior.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:10:41.637675Z","iopub.execute_input":"2025-08-18T06:10:41.638009Z","iopub.status.idle":"2025-08-18T06:10:41.687374Z","shell.execute_reply.started":"2025-08-18T06:10:41.637973Z","shell.execute_reply":"2025-08-18T06:10:41.686441Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.phase.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:10:41.688322Z","iopub.execute_input":"2025-08-18T06:10:41.688594Z","iopub.status.idle":"2025-08-18T06:10:41.723132Z","shell.execute_reply.started":"2025-08-18T06:10:41.688561Z","shell.execute_reply":"2025-08-18T06:10:41.722224Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# orientation\n\ndf.orientation.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:10:41.724594Z","iopub.execute_input":"2025-08-18T06:10:41.724882Z","iopub.status.idle":"2025-08-18T06:10:41.766037Z","shell.execute_reply.started":"2025-08-18T06:10:41.724861Z","shell.execute_reply":"2025-08-18T06:10:41.7653Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":" df.sequence_type.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:52:28.662357Z","iopub.execute_input":"2025-08-18T06:52:28.662644Z","iopub.status.idle":"2025-08-18T06:52:28.697241Z","shell.execute_reply.started":"2025-08-18T06:52:28.662625Z","shell.execute_reply":"2025-08-18T06:52:28.696003Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.gesture.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:53:59.724308Z","iopub.execute_input":"2025-08-18T06:53:59.724706Z","iopub.status.idle":"2025-08-18T06:53:59.766043Z","shell.execute_reply.started":"2025-08-18T06:53:59.724672Z","shell.execute_reply":"2025-08-18T06:53:59.765155Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Set the style of the plots\nsns.set_style(\"whitegrid\")\n\n# Create a figure and a set of subplots\nfig, axes = plt.subplots(nrows=3, ncols=2, figsize=(15, 18))\nfig.suptitle('Distribution of Categorical Variables', fontsize=16)\n\n# Plot `behavior`\nsns.countplot(y='behavior', data=df, ax=axes[0, 0], order=df['behavior'].value_counts().index)\naxes[0, 0].set_title('Distribution of Behavior')\naxes[0, 0].set_xlabel('Count')\naxes[0, 0].set_ylabel('Behavior')\n\n# Plot `phase`\nsns.countplot(x='phase', data=df, ax=axes[0, 1], order=df['phase'].value_counts().index)\naxes[0, 1].set_title('Distribution of Phase')\naxes[0, 1].set_xlabel('Phase')\naxes[0, 1].set_ylabel('Count')\n\n# Plot `orientation`\nsns.countplot(y='orientation', data=df, ax=axes[1, 0], order=df['orientation'].value_counts().index)\naxes[1, 0].set_title('Distribution of Orientation')\naxes[1, 0].set_xlabel('Count')\naxes[1, 0].set_ylabel('Orientation')\n\n# Plot `sequence_type`\nsns.countplot(x='sequence_type', data=df, ax=axes[1, 1], order=df['sequence_type'].value_counts().index)\naxes[1, 1].set_title('Distribution of Sequence Type')\naxes[1, 1].set_xlabel('Sequence Type')\naxes[1, 1].set_ylabel('Count')\n\n# Plot `gesture`\nsns.countplot(y='gesture', data=df, ax=axes[2, 0], order=df['gesture'].value_counts().index)\naxes[2, 0].set_title('Distribution of Gesture')\naxes[2, 0].set_xlabel('Count')\naxes[2, 0].set_ylabel('Gesture')\n\n# Remove the empty subplot\nfig.delaxes(axes[2, 1])\n\nplt.tight_layout(rect=[0, 0, 1, 0.96])\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T07:07:15.303832Z","iopub.execute_input":"2025-08-18T07:07:15.304141Z","iopub.status.idle":"2025-08-18T07:07:17.988726Z","shell.execute_reply.started":"2025-08-18T07:07:15.304117Z","shell.execute_reply":"2025-08-18T07:07:17.987663Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#each sequence type has one orientation\nvec = df.groupby(['sequence_id','orientation'])[['sequence_id']].count(\n    ).squeeze().values - df.groupby(['sequence_id','orientation'])[['orientation']].count().squeeze().values\n\nmax(vec)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:53:41.596466Z","iopub.execute_input":"2025-08-18T06:53:41.597298Z","iopub.status.idle":"2025-08-18T06:53:41.826155Z","shell.execute_reply.started":"2025-08-18T06:53:41.597269Z","shell.execute_reply":"2025-08-18T06:53:41.825317Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for gesture in df.gesture.unique():\n    df_filter = df[df.gesture == gesture]\n    for seq_id in df_filter.sequence_id.unique()[0:2]:\n        print(seq_id  + '--' + str(df_filter.subject.unique()[0]))\n        df_seq = df[df.sequence_id == seq_id].copy()\n    \n        # Define the mapping for behavior and transition/gesture\n        df_seq['Behaviour'] = df_seq.behavior.map(dict(zip(df_seq.behavior.unique(), range(df_seq.behavior.nunique()))))\n        df_seq['Transition/Gesture'] =  df_seq.phase.map(dict(zip(df_seq.phase.unique(), range(df_seq.phase.nunique()))))\n        \n        # Define the different plotting scenarios, grouped by primary columns\n        plots_to_create = [\n            (['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5'], 'Transition/Gesture', 'Temperature with Transition/Gesture (0,1,2,...)'),\n            (['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5'], 'Behaviour', 'Temperature with Behavioural  (0,1,2,...)'),\n            (['acc_x', 'acc_y', 'acc_z'], 'Transition/Gesture', 'Acceleration with Transition/Gesture  (0,1,2,...)'),\n            (['acc_x', 'acc_y', 'acc_z'], 'Behaviour', 'Acceleration with Behavioural  (0,1,2,...)'),\n            (['rot_w', 'rot_x', 'rot_y', 'rot_z'], 'Transition/Gesture', 'Rotation with Transition/Gesture  (0,1,2,...)'),\n            (['rot_w', 'rot_x', 'rot_y', 'rot_z'], 'Behaviour', 'Rotation with Behavioural (0,1,2,...)')\n        ]\n    \n        # Create a single figure with a 3x2 grid of subplots for each sequence\n        fig, axes = plt.subplots(nrows=3, ncols=2, figsize=(15, 15))\n        fig.suptitle( str( [df_seq.gesture.unique()[0]] + [df_seq.orientation.unique()[0]] + [df_seq.sequence_type.unique()[0]] )\n                     , fontsize=16, color = 'blue')\n        \n        axes = axes.flatten()\n    \n        for i, (primary_cols, secondary_col, title) in enumerate(plots_to_create):\n            ax = axes[i]\n            \n            # Plot the primary columns on the primary y-axis\n            df_seq[primary_cols].plot(ax=ax)\n            \n            # Plot the secondary column on a secondary y-axis\n            df_seq[secondary_col].plot(secondary_y=True, ax=ax, style='--', linewidth = 2)\n            \n            # Set labels and title\n            ax.set_ylabel(f'({\", \".join(primary_cols)})')\n            ax.right_ax.set_ylabel(f' ({secondary_col})')\n            ax.set_title(f\"{title}\") #- SEQ {seq_id}\n            \n            # Set the secondary y-axis ticks to show only the numeric values from the categories\n            if secondary_col == 'beh':\n                ax.right_ax.set_yticks(range(df_seq.behavior.nunique()))\n            elif secondary_col == 'tg':\n                ax.right_ax.set_yticks(range(df_seq.phase.nunique()))\n            \n            # Add legend to the plot\n            ax.legend(loc='upper left')\n            ax.right_ax.legend(loc='upper right')\n    \n        plt.tight_layout(pad=1.0)\n        plt.show()\n        print(\"\\n\")\n        \n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T06:56:25.451145Z","iopub.execute_input":"2025-08-18T06:56:25.451854Z","iopub.status.idle":"2025-08-18T06:57:57.473325Z","shell.execute_reply.started":"2025-08-18T06:56:25.451822Z","shell.execute_reply":"2025-08-18T06:57:57.472289Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":" print(df_seq.sequence_id.unique()[0]  + '--' + str(df_seq.subject.unique()[0]))\n\n\n# Create column names for tof_1 to tof_7\ncol1 = [f'tof_1_v{i}' for i in range(64)]\ncol2 = [f'tof_2_v{i}' for i in range(64)]\ncol3 = [f'tof_3_v{i}' for i in range(64)]\ncol4 = [f'tof_4_v{i}' for i in range(64)]\ncol5 = [f'tof_5_v{i}' for i in range(64)]\ncol6 = [f'Transition/Gesture' for i in range(64)]\ncol7 = [f'Behaviour' for i in range(64)]\n\n# Create DataFrames\ndf_seq_tof1 = df_seq[col1].reset_index(drop=True)\ndf_seq_tof2 = df_seq[col2].reset_index(drop=True)\ndf_seq_tof3 = df_seq[col3].reset_index(drop=True)\ndf_seq_tof4 = df_seq[col4].reset_index(drop=True)\ndf_seq_tof5 = df_seq[col5].reset_index(drop=True)\ndf_seq_tof6 = df_seq[col6].reset_index(drop=True)\ndf_seq_tof7 = df_seq[col7].reset_index(drop=True) \n\n\n# List of DataFrames\ndfs = [df_seq_tof1, df_seq_tof2, df_seq_tof3, df_seq_tof4, df_seq_tof5, df_seq_tof6, df_seq_tof7]\n\n# Set up the figure and axes for a df_seq.shape[0] x 7 grid\nrows, cols = df_seq.shape[0], 7\nfig, axes = plt.subplots(rows, cols, figsize=(17, 2.5 * rows))  # ~2.4 inches per column, ~2.5 inches per heatmap\naxes = axes.reshape(rows, cols)  # Ensure 2D array for indexing\nfig.suptitle( str( [df_seq.sequence_id.unique()[0]] +[df_seq.gesture.unique()[0]] + [df_seq.orientation.unique()[0]] + [df_seq.sequence_type.unique()[0]] )\n                     , fontsize=16, color = 'blue')\n\n\ncol_list = [col1[0], col2[0], col3[0], col4[0], col5[0], col6[0], col7[0]]\n# Plot each 8x8 image as a heatmap\ncolor_map = [ 'coolwarm', 'RdBu', 'spring', 'cool', 'viridis']\nfor col_idx, df_seq_tof in enumerate(dfs):\n    for var_i in range(rows):\n        # Extract and process the image\n        image = df_seq_tof.iloc[var_i].replace(-1, np.nan).values.reshape(8, 8)\n        # Plot heatmap\n\n        if(col_idx < 5):\n            im = axes[var_i, col_idx].imshow(image, cmap='RdYlGn', interpolation='nearest')\n            # if col_idx == 0:\n            #     axes[var_i, col_idx].set_title(f'{var_i}', fontsize=10, pad=3)  # Label var_i on first column\n            # else:\n            axes[var_i, col_idx].set_title(col_list[col_idx], fontsize=10, pad=3)  # Label tof_k\n            axes[var_i, col_idx].set_xticks([])  # Remove x-axis ticks\n            axes[var_i, col_idx].set_yticks([])  # Remove y-axis ticks\n        else:\n            if((image == 0).sum() == 64):\n                cmap = color_map[0]\n            if((image == 1).sum() == 64):\n                cmap = color_map[1]\n            if((image == 2).sum() == 64):\n                cmap = color_map[2]\n            if((image == 3).sum() == 64):\n                cmap = color_map[3]\n            if((image == 4).sum() == 64):\n                cmap = color_map[4]\n            \n            im = axes[var_i, col_idx].imshow(image, cmap=cmap, interpolation='nearest')\n            # if col_idx == 0:\n            #     axes[var_i, col_idx].set_title(f'{var_i}', fontsize=10, pad=3)  # Label var_i on first column\n            # else:\n            axes[var_i, col_idx].set_title(col_list[col_idx], fontsize=10, pad=3)  # Label tof_k\n            axes[var_i, col_idx].set_xticks([])  # Remove x-axis ticks\n            axes[var_i, col_idx].set_yticks([])  # Remove y-axis ticks\n            \n    # Add a colorbar for each column\n    fig.colorbar(im, ax=axes[:, col_idx], location='bottom', label=f'tof_{col_idx+1} Value', shrink=0.6, pad=0.05)\n\n# Adjust layout with extra spacing to prevent overlap\nplt.tight_layout(h_pad=1.0, w_pad=1.0)\n\n# Display the plot\nplt.show()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-18T07:02:40.572225Z","iopub.execute_input":"2025-08-18T07:02:40.573392Z","iopub.status.idle":"2025-08-18T07:02:57.843374Z","shell.execute_reply.started":"2025-08-18T07:02:40.573349Z","shell.execute_reply":"2025-08-18T07:02:57.84238Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}