{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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":59156,"databundleVersionId":13719397,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 🐭 MABe Mouse Behavior Detection Dataset - EDA","metadata":{}},{"cell_type":"code","source":"# MABe Mouse Behavior Detection - Data Reading and EDA\n# This notebook provides comprehensive exploratory data analysis of the MABe mouse behavior dataset\n\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport plotly.express as px\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Set style for better plots\nplt.style.use('seaborn-v0_8')\nsns.set_palette(\"husl\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:11:57.808394Z","iopub.execute_input":"2025-09-19T08:11:57.808781Z","iopub.status.idle":"2025-09-19T08:11:57.816813Z","shell.execute_reply.started":"2025-09-19T08:11:57.808755Z","shell.execute_reply":"2025-09-19T08:11:57.815144Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define data paths\nDATA_DIR = \"/kaggle/input/MABe-mouse-behavior-detection/\"\nTRAIN_CSV = DATA_DIR + \"train.csv\"\nTEST_CSV = DATA_DIR + \"test.csv\"\nSAMPLE_SUB = DATA_DIR + \"sample_submission.csv\"\nTRAIN_TRACKING = DATA_DIR + \"train_tracking/\"\nTRAIN_ANNOTATION = DATA_DIR + \"train_annotation/\"\nTEST_TRACKING = DATA_DIR + \"test_tracking/\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:11:57.818747Z","iopub.execute_input":"2025-09-19T08:11:57.819113Z","iopub.status.idle":"2025-09-19T08:11:57.845694Z","shell.execute_reply.started":"2025-09-19T08:11:57.819086Z","shell.execute_reply":"2025-09-19T08:11:57.844424Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1. Loading Basic Dataset Information\n\nLet's start by loading the main CSV files to understand the dataset structure and metadata.","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv(TRAIN_CSV)\ntest_df = pd.read_csv(TEST_CSV)\nsample_sub = pd.read_csv(SAMPLE_SUB)\n\nprint(f\"📈 Training videos: {len(train_df)}\")\nprint(f\"📈 Test videos: {len(test_df)}\")\nprint(f\"📈 Sample submission rows: {len(sample_sub)}\")\nprint(f\"📈 Total unique labs: {train_df['lab_id'].nunique()}\")\nprint(f\"📈 Total training video duration: {train_df['video_duration_sec'].sum()/3600:.1f} hours\")\nprint(f\"📈 Total test video duration: {test_df['video_duration_sec'].sum()/3600:.1f} hours\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:11:57.846908Z","iopub.execute_input":"2025-09-19T08:11:57.847897Z","iopub.status.idle":"2025-09-19T08:11:58.04832Z","shell.execute_reply.started":"2025-09-19T08:11:57.847868Z","shell.execute_reply":"2025-09-19T08:11:58.04708Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Display basic info about training data\nprint(\"🔍 Training Data Structure:\")\nprint(train_df.info())\nprint(\"\\n\" + \"=\"*50)\nprint(\"📋 Column Names:\")\nfor i, col in enumerate(train_df.columns):\n    print(f\"{i+1:2d}. {col}\")\n    \nprint(\"\\n\" + \"=\"*50)\nprint(\"📊 First Few Rows:\")\ntrain_df.head(3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:11:58.050742Z","iopub.execute_input":"2025-09-19T08:11:58.051067Z","iopub.status.idle":"2025-09-19T08:11:58.129399Z","shell.execute_reply.started":"2025-09-19T08:11:58.051042Z","shell.execute_reply":"2025-09-19T08:11:58.128002Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2. Laboratory and Video Analysis\n\nLet's analyze the distribution of laboratories, video characteristics, and experimental setups.","metadata":{}},{"cell_type":"code","source":"# Laboratory distribution\nfig, axes = plt.subplots(2, 2, figsize=(16, 12))\n\n# Lab distribution\nlab_counts = train_df['lab_id'].value_counts()\nax1 = axes[0, 0]\nlab_counts.plot(kind='bar', ax=ax1, color='skyblue')\nax1.set_title('🏢 Distribution of Videos by Laboratory', fontsize=14, fontweight='bold')\nax1.set_xlabel('Laboratory ID')\nax1.set_ylabel('Number of Videos')\nax1.tick_params(axis='x', rotation=45)\n\n# Video duration distribution\nax2 = axes[0, 1]\ntrain_df['video_duration_sec'].hist(bins=50, ax=ax2, color='lightcoral', alpha=0.7)\nax2.set_title('⏱️ Video Duration Distribution', fontsize=14, fontweight='bold')\nax2.set_xlabel('Duration (seconds)')\nax2.set_ylabel('Frequency')\n\n# Arena shape distribution\nax3 = axes[1, 0]\narena_counts = train_df['arena_shape'].value_counts()\narena_counts.plot(kind='pie', ax=ax3, autopct='%1.1f%%', colors=['lightgreen', 'orange'])\nax3.set_title('🏟️ Arena Shape Distribution', fontsize=14, fontweight='bold')\n\n# Frames per second distribution\nax4 = axes[1, 1]\nfps_counts = train_df['frames_per_second'].value_counts()\nfps_counts.plot(kind='bar', ax=ax4, color='gold')\nax4.set_title('📹 Frames Per Second Distribution', fontsize=14, fontweight='bold')\nax4.set_xlabel('FPS')\nax4.set_ylabel('Number of Videos')\n\nplt.tight_layout()\nplt.show()\n\nprint(f\"📊 Laboratory Statistics:\")\nprint(f\"   • Total laboratories: {train_df['lab_id'].nunique()}\")\nprint(f\"   • Videos per lab (avg): {len(train_df) / train_df['lab_id'].nunique():.1f}\")\nprint(f\"   • Most active lab: {lab_counts.index[0]} ({lab_counts.iloc[0]} videos)\")\nprint(f\"   • Least active lab: {lab_counts.index[-1]} ({lab_counts.iloc[-1]} videos)\")\n\nprint(f\"\\n📹 Video Statistics:\")\nprint(f\"   • Average duration: {train_df['video_duration_sec'].mean():.1f} seconds\")\nprint(f\"   • Duration range: {train_df['video_duration_sec'].min():.1f} - {train_df['video_duration_sec'].max():.1f} seconds\")\nprint(f\"   • Most common FPS: {train_df['frames_per_second'].mode().iloc[0]}\")\nprint(f\"   • Arena shapes: {', '.join(train_df['arena_shape'].unique())}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:11:58.130756Z","iopub.execute_input":"2025-09-19T08:11:58.131126Z","iopub.status.idle":"2025-09-19T08:11:59.482769Z","shell.execute_reply.started":"2025-09-19T08:11:58.131089Z","shell.execute_reply":"2025-09-19T08:11:59.481534Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 3. Mouse Characteristics Analysis\n\nLet's examine the mouse strains, colors, sex distribution, and other biological characteristics.","metadata":{}},{"cell_type":"code","source":"# Analyze mouse characteristics\ndef get_mouse_data(df, mouse_num):\n    \"\"\"Extract mouse data for analysis\"\"\"\n    return df[[f'mouse{mouse_num}_strain', f'mouse{mouse_num}_color', \n               f'mouse{mouse_num}_sex', f'mouse{mouse_num}_age', \n               f'mouse{mouse_num}_condition']].dropna()\n\n# Combine all mouse data\nall_mice_data = []\nfor i in range(1, 5):  # mice 1-4\n    mouse_data = get_mouse_data(train_df, i)\n    mouse_data.columns = ['strain', 'color', 'sex', 'age', 'condition']\n    mouse_data['mouse_number'] = i\n    all_mice_data.append(mouse_data)\n\nmice_df = pd.concat(all_mice_data, ignore_index=True)\n\n# Create comprehensive mouse analysis plot\nfig, axes = plt.subplots(2, 3, figsize=(18, 12))\n\n# Mouse strain distribution\nax1 = axes[0, 0]\nstrain_counts = mice_df['strain'].value_counts()\nstrain_counts.plot(kind='bar', ax=ax1, color='lightblue')\nax1.set_title('🧬 Mouse Strain Distribution', fontsize=14, fontweight='bold')\nax1.set_xlabel('Strain')\nax1.set_ylabel('Count')\nax1.tick_params(axis='x', rotation=45)\n\n# Mouse color distribution\nax2 = axes[0, 1]\ncolor_counts = mice_df['color'].value_counts()\ncolors_map = {'white': 'white', 'black': 'black', 'brown': 'brown', 'gray': 'gray'}\nplot_colors = [colors_map.get(color, 'blue') for color in color_counts.index]\ncolor_counts.plot(kind='bar', ax=ax2, color=plot_colors, edgecolor='black')\nax2.set_title('🎨 Mouse Color Distribution', fontsize=14, fontweight='bold')\nax2.set_xlabel('Color')\nax2.set_ylabel('Count')\nax2.tick_params(axis='x', rotation=45)\n\n# Mouse sex distribution\nax3 = axes[0, 2]\nsex_counts = mice_df['sex'].value_counts()\nsex_counts.plot(kind='pie', ax=ax3, autopct='%1.1f%%', colors=['lightpink', 'lightblue'])\nax3.set_title('⚥ Mouse Sex Distribution', fontsize=14, fontweight='bold')\n\n# Age distribution\nax4 = axes[1, 0]\nage_counts = mice_df['age'].value_counts()\nage_counts.plot(kind='bar', ax=ax4, color='orange')\nax4.set_title('📅 Mouse Age Distribution', fontsize=14, fontweight='bold')\nax4.set_xlabel('Age')\nax4.set_ylabel('Count')\nax4.tick_params(axis='x', rotation=45)\n\n# Condition distribution\nax5 = axes[1, 1]\ncondition_counts = mice_df['condition'].value_counts()\ncondition_counts.plot(kind='bar', ax=ax5, color='lightgreen')\nax5.set_title('🔬 Mouse Condition Distribution', fontsize=14, fontweight='bold')\nax5.set_xlabel('Condition')\nax5.set_ylabel('Count')\nax5.tick_params(axis='x', rotation=45)\n\n# Mouse number distribution\nax6 = axes[1, 2]\nmouse_num_counts = mice_df['mouse_number'].value_counts().sort_index()\nmouse_num_counts.plot(kind='bar', ax=ax6, color='purple')\nax6.set_title('🐭 Mouse Position Distribution', fontsize=14, fontweight='bold')\nax6.set_xlabel('Mouse Number')\nax6.set_ylabel('Count')\n\nplt.tight_layout()\nplt.show()\n\nprint(\"🐭 Mouse Characteristics Summary:\")\nprint(f\"   • Total mouse records: {len(mice_df):,}\")\nprint(f\"   • Unique strains: {mice_df['strain'].nunique()}\")\nprint(f\"   • Most common strain: {strain_counts.index[0]} ({strain_counts.iloc[0]:,} mice)\")\nprint(f\"   • Color distribution: {dict(color_counts)}\")\nprint(f\"   • Sex distribution: {dict(sex_counts)}\")\nprint(f\"   • Age groups: {mice_df['age'].nunique()}\")\nprint(f\"   • Experimental conditions: {mice_df['condition'].nunique()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:11:59.483988Z","iopub.execute_input":"2025-09-19T08:11:59.484278Z","iopub.status.idle":"2025-09-19T08:12:32.479171Z","shell.execute_reply.started":"2025-09-19T08:11:59.484254Z","shell.execute_reply":"2025-09-19T08:12:32.478197Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 4. Behavior Analysis\n\nLet's analyze the behaviors being tracked and labeled in this dataset.","metadata":{}},{"cell_type":"code","source":"# Parse behavior labels\nimport ast\n\ndef parse_behaviors(behavior_str):\n    \"\"\"Parse behavior string into list of behaviors\"\"\"\n    try:\n        return ast.literal_eval(behavior_str)\n    except:\n        return []\n\n# Get all behaviors from training data\nall_behaviors = []\nbehavior_types = {}\n\nfor idx, row in train_df.iterrows():\n    behaviors = parse_behaviors(row['behaviors_labeled'])\n    all_behaviors.extend(behaviors)\n    \n    # Extract behavior types\n    for behavior in behaviors:\n        if ',' in behavior:\n            parts = behavior.split(',')\n            if len(parts) == 3:\n                agent, target, action = parts\n                if action not in behavior_types:\n                    behavior_types[action] = 0\n                behavior_types[action] += 1\n\n# Count behavior frequencies\nbehavior_counts = pd.Series(all_behaviors).value_counts()\n\nprint(\"🎭 Behavior Analysis:\")\nprint(f\"   • Total behavior instances: {len(all_behaviors):,}\")\nprint(f\"   • Unique behaviors: {len(behavior_counts)}\")\nprint(f\"   • Unique behavior types: {len(behavior_types)}\")\n\n# Plot behavior types\nfig, axes = plt.subplots(2, 2, figsize=(16, 12))\n\n# Behavior types distribution\nax1 = axes[0, 0]\nbehavior_type_series = pd.Series(behavior_types)\nbehavior_type_series.sort_values(ascending=False).plot(kind='bar', ax=ax1, color='coral')\nax1.set_title('🎭 Behavior Types Distribution', fontsize=14, fontweight='bold')\nax1.set_xlabel('Behavior Type')\nax1.set_ylabel('Frequency')\nax1.tick_params(axis='x', rotation=45)\n\n# Top 20 most common specific behaviors\nax2 = axes[0, 1]\ntop_behaviors = behavior_counts.head(20)\ntop_behaviors.plot(kind='barh', ax=ax2, color='lightgreen')\nax2.set_title('🔝 Top 20 Most Common Behaviors', fontsize=14, fontweight='bold')\nax2.set_xlabel('Frequency')\n\n# Behavior complexity (number of behaviors per video)\nax3 = axes[1, 0]\nbehaviors_per_video = []\nfor idx, row in train_df.iterrows():\n    behaviors = parse_behaviors(row['behaviors_labeled'])\n    behaviors_per_video.append(len(behaviors))\n\npd.Series(behaviors_per_video).hist(bins=30, ax=ax3, color='skyblue', alpha=0.7)\nax3.set_title('📊 Behaviors Per Video Distribution', fontsize=14, fontweight='bold')\nax3.set_xlabel('Number of Behaviors')\nax3.set_ylabel('Frequency')\n\n# Arena type vs behavior complexity\nax4 = axes[1, 1]\ntrain_df['num_behaviors'] = behaviors_per_video\narena_behavior = train_df.groupby('arena_type')['num_behaviors'].mean()\narena_behavior.plot(kind='bar', ax=ax4, color='gold')\nax4.set_title('🏟️ Avg Behaviors by Arena Type', fontsize=14, fontweight='bold')\nax4.set_xlabel('Arena Type')\nax4.set_ylabel('Average # Behaviors')\nax4.tick_params(axis='x', rotation=45)\n\nplt.tight_layout()\nplt.show()\n\nprint(f\"\\n🎭 Top 10 Behavior Types:\")\nfor i, (behavior, count) in enumerate(behavior_type_series.sort_values(ascending=False).head(10).items()):\n    print(f\"   {i+1:2d}. {behavior}: {count:,}\")\n\nprint(f\"\\n📊 Behavior Complexity:\")\nprint(f\"   • Average behaviors per video: {np.mean(behaviors_per_video):.1f}\")\nprint(f\"   • Max behaviors in a video: {max(behaviors_per_video)}\")\nprint(f\"   • Min behaviors in a video: {min(behaviors_per_video)}\")\nprint(f\"   • Videos with no behaviors: {behaviors_per_video.count(0)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:12:32.480348Z","iopub.execute_input":"2025-09-19T08:12:32.480691Z","iopub.status.idle":"2025-09-19T08:12:34.637752Z","shell.execute_reply.started":"2025-09-19T08:12:32.480663Z","shell.execute_reply":"2025-09-19T08:12:34.636445Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5. Body Parts and Tracking Analysis\n\nLet's examine the body parts being tracked and the tracking methods used.","metadata":{}},{"cell_type":"code","source":"# Analyze body parts tracking\ndef parse_body_parts(body_parts_str):\n    \"\"\"Parse body parts string into list\"\"\"\n    try:\n        return ast.literal_eval(body_parts_str)\n    except:\n        return []\n\n# Get all body parts\nall_body_parts = []\nfor idx, row in train_df.iterrows():\n    body_parts = parse_body_parts(row['body_parts_tracked'])\n    all_body_parts.extend(body_parts)\n\nbody_parts_counts = pd.Series(all_body_parts).value_counts()\n\n# Analyze tracking methods\ntracking_methods = train_df['tracking_method'].value_counts()\n\n# Create visualizations\nfig, axes = plt.subplots(2, 2, figsize=(16, 12))\n\n# Body parts frequency\nax1 = axes[0, 0]\nbody_parts_counts.plot(kind='barh', ax=ax1, color='lightblue')\nax1.set_title('🎯 Body Parts Tracking Frequency', fontsize=14, fontweight='bold')\nax1.set_xlabel('Frequency')\n\n# Tracking methods\nax2 = axes[0, 1]\ntracking_methods.plot(kind='pie', ax=ax2, autopct='%1.1f%%', colors=['lightcoral', 'gold'])\nax2.set_title('📱 Tracking Methods Distribution', fontsize=14, fontweight='bold')\n\n# Number of body parts per video\nax3 = axes[1, 0]\nbody_parts_per_video = []\nfor idx, row in train_df.iterrows():\n    body_parts = parse_body_parts(row['body_parts_tracked'])\n    body_parts_per_video.append(len(body_parts))\n\npd.Series(body_parts_per_video).hist(bins=20, ax=ax3, color='lightgreen', alpha=0.7)\nax3.set_title('📊 Body Parts Per Video Distribution', fontsize=14, fontweight='bold')\nax3.set_xlabel('Number of Body Parts')\nax3.set_ylabel('Frequency')\n\n# Video resolution distribution\nax4 = axes[1, 1]\ntrain_df['resolution'] = train_df['video_width_pix'].astype(str) + 'x' + train_df['video_height_pix'].astype(str)\nresolution_counts = train_df['resolution'].value_counts().head(10)\nresolution_counts.plot(kind='bar', ax=ax4, color='purple')\nax4.set_title('📺 Top Video Resolutions', fontsize=14, fontweight='bold')\nax4.set_xlabel('Resolution')\nax4.set_ylabel('Count')\nax4.tick_params(axis='x', rotation=45)\n\nplt.tight_layout()\nplt.show()\n\nprint(\"🎯 Body Parts Analysis:\")\nprint(f\"   • Total body part instances: {len(all_body_parts):,}\")\nprint(f\"   • Unique body parts: {len(body_parts_counts)}\")\nprint(f\"   • Average body parts per video: {np.mean(body_parts_per_video):.1f}\")\nprint(f\"   • Most tracked body part: {body_parts_counts.index[0]} ({body_parts_counts.iloc[0]:,} times)\")\n\nprint(f\"\\n📱 Tracking Methods:\")\nfor method, count in tracking_methods.items():\n    print(f\"   • {method}: {count:,} videos ({count/len(train_df)*100:.1f}%)\")\n\nprint(f\"\\n🎯 Top 10 Body Parts:\")\nfor i, (part, count) in enumerate(body_parts_counts.head(10).items()):\n    print(f\"   {i+1:2d}. {part}: {count:,}\")\n\nprint(f\"\\n📺 Video Specifications:\")\nprint(f\"   • Width range: {train_df['video_width_pix'].min()} - {train_df['video_width_pix'].max()} pixels\")\nprint(f\"   • Height range: {train_df['video_height_pix'].min()} - {train_df['video_height_pix'].max()} pixels\")\nprint(f\"   • Pixel density range: {train_df['pix_per_cm_approx'].min()} - {train_df['pix_per_cm_approx'].max()} pix/cm\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:12:34.639013Z","iopub.execute_input":"2025-09-19T08:12:34.639389Z","iopub.status.idle":"2025-09-19T08:12:37.258001Z","shell.execute_reply.started":"2025-09-19T08:12:34.639368Z","shell.execute_reply":"2025-09-19T08:12:37.257058Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6. Tracking Data Analysis\n\nNow let's examine some actual tracking data (parquet files) to understand the keypoint coordinates and structure.","metadata":{}},{"cell_type":"code","source":"# Load and examine a sample tracking file\nimport os\n\n# Get a sample tracking file\nsample_lab = 'AdaptableSnail'\ntracking_path = f\"{TRAIN_TRACKING}{sample_lab}/\"\ntracking_files = os.listdir(tracking_path)\nsample_file = [f for f in tracking_files if f.endswith('.parquet')][0]\nsample_tracking_path = f\"{tracking_path}{sample_file}\"\n\nprint(f\"📁 Loading sample tracking data: {sample_file}\")\ntracking_data = pd.read_parquet(sample_tracking_path)\n\nprint(f\"📊 Tracking Data Shape: {tracking_data.shape}\")\nprint(f\"📋 Columns: {list(tracking_data.columns)}\")\nprint(f\"🎯 Body parts detected: {len([col for col in tracking_data.columns if '_x' in col])}\")\n\n# Display basic info\nprint(\"\\n\" + \"=\"*50)\nprint(\"TRACKING DATA STRUCTURE\")\nprint(\"=\"*50)\nprint(tracking_data.info())\n\n# Show first few rows\nprint(\"\\n📊 First 5 rows:\")\ntracking_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:12:37.259307Z","iopub.execute_input":"2025-09-19T08:12:37.259612Z","iopub.status.idle":"2025-09-19T08:12:37.939922Z","shell.execute_reply.started":"2025-09-19T08:12:37.259589Z","shell.execute_reply":"2025-09-19T08:12:37.938835Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Analyze tracking data structure\nprint(\"🔍 Tracking Data Analysis:\")\n\n# Basic statistics\nnum_frames = tracking_data['video_frame'].nunique()\nnum_mice = tracking_data['mouse_id'].nunique()\nnum_bodyparts = tracking_data['bodypart'].nunique()\n\nprint(f\"   • Total frames: {num_frames:,}\")\nprint(f\"   • Number of mice: {num_mice}\")\nprint(f\"   • Body parts tracked: {num_bodyparts}\")\nprint(f\"   • Total data points: {len(tracking_data):,}\")\nprint(f\"   • Data points per frame: {len(tracking_data) / num_frames:.1f}\")\n\n# Body parts in this video\nbodyparts = tracking_data['bodypart'].unique()\nprint(f\"\\n🎯 Body parts in this video:\")\nfor i, part in enumerate(sorted(bodyparts)):\n    print(f\"   {i+1:2d}. {part}\")\n\n# Mouse tracking\nmouse_counts = tracking_data['mouse_id'].value_counts().sort_index()\nprint(f\"\\n🐭 Mouse tracking distribution:\")\nfor mouse_id, count in mouse_counts.items():\n    print(f\"   Mouse {mouse_id}: {count:,} data points\")\n\n# Coordinate ranges\nprint(f\"\\n📍 Coordinate ranges:\")\nprint(f\"   • X coordinates: {tracking_data['x'].min():.1f} - {tracking_data['x'].max():.1f}\")\nprint(f\"   • Y coordinates: {tracking_data['y'].min():.1f} - {tracking_data['y'].max():.1f}\")\n\n# Create tracking visualization\nfig, axes = plt.subplots(2, 2, figsize=(16, 12))\n\n# Frame distribution\nax1 = axes[0, 0]\nframe_counts = tracking_data.groupby('video_frame').size()\nframe_counts.plot(ax=ax1, color='blue', alpha=0.7)\nax1.set_title('📹 Data Points per Frame', fontsize=14, fontweight='bold')\nax1.set_xlabel('Frame Number')\nax1.set_ylabel('Number of Data Points')\n\n# Body part frequency\nax2 = axes[0, 1]\nbodypart_counts = tracking_data['bodypart'].value_counts()\nbodypart_counts.plot(kind='bar', ax=ax2, color='orange')\nax2.set_title('🎯 Body Part Frequency', fontsize=14, fontweight='bold')\nax2.set_xlabel('Body Part')\nax2.set_ylabel('Count')\nax2.tick_params(axis='x', rotation=45)\n\n# Mouse movement (sample trajectory for mouse 1)\nax3 = axes[1, 0]\nmouse1_data = tracking_data[tracking_data['mouse_id'] == 1]\nnose_data = mouse1_data[mouse1_data['bodypart'] == 'nose'].head(100)  # First 100 frames\nax3.plot(nose_data['x'], nose_data['y'], 'b-', alpha=0.7, linewidth=2)\nax3.scatter(nose_data['x'].iloc[0], nose_data['y'].iloc[0], color='green', s=100, label='Start')\nax3.scatter(nose_data['x'].iloc[-1], nose_data['y'].iloc[-1], color='red', s=100, label='End')\nax3.set_title('🐭 Mouse 1 Nose Trajectory (First 100 frames)', fontsize=14, fontweight='bold')\nax3.set_xlabel('X Coordinate')\nax3.set_ylabel('Y Coordinate')\nax3.legend()\nax3.grid(True, alpha=0.3)\n\n# Coordinate distribution\nax4 = axes[1, 1]\nax4.scatter(tracking_data['x'], tracking_data['y'], alpha=0.1, s=1)\nax4.set_title('📍 All Coordinate Points', fontsize=14, fontweight='bold')\nax4.set_xlabel('X Coordinate')\nax4.set_ylabel('Y Coordinate')\nax4.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:12:37.942708Z","iopub.execute_input":"2025-09-19T08:12:37.943076Z","iopub.status.idle":"2025-09-19T08:12:41.021414Z","shell.execute_reply.started":"2025-09-19T08:12:37.943052Z","shell.execute_reply":"2025-09-19T08:12:41.020247Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 7. Annotation Data Analysis\n\nLet's examine the annotation data to understand how behaviors are labeled in the dataset.","metadata":{}},{"cell_type":"code","source":"# Load and examine annotation data\nannotation_path = f\"{TRAIN_ANNOTATION}{sample_lab}/\"\nannotation_files = os.listdir(annotation_path)\nsample_annotation_file = [f for f in annotation_files if f.endswith('.parquet')][0]\nsample_annotation_path = f\"{annotation_path}{sample_annotation_file}\"\n\nprint(f\"📁 Loading sample annotation data: {sample_annotation_file}\")\nannotation_data = pd.read_parquet(sample_annotation_path)\n\nprint(f\"📊 Annotation Data Shape: {annotation_data.shape}\")\nprint(f\"📋 Columns: {list(annotation_data.columns)}\")\n\n# Display basic info\nprint(\"\\n\" + \"=\"*50)\nprint(\"ANNOTATION DATA STRUCTURE\")\nprint(\"=\"*50)\nprint(annotation_data.info())\n\n# Show first few rows\nprint(\"\\n📊 First 10 rows:\")\ndisplay(annotation_data.head(10))\n\n# Analyze annotation patterns\nprint(\"\\n🎭 Behavior Annotation Analysis:\")\n\n# Get unique actions in this file (correct column name is 'action')\nactions = annotation_data['action'].unique()\nprint(f\"   • Actions in this file: {len(actions)}\")\n\naction_counts = annotation_data['action'].value_counts()\nprint(f\"\\n🔝 Action frequency in this video:\")\nfor action, count in action_counts.head(10).items():\n    print(f\"   • {action}: {count}\")\n\n# Analyze frame ranges\nprint(f\"\\n📹 Frame Analysis:\")\nprint(f\"   • Start frames range: {annotation_data['start_frame'].min()} - {annotation_data['start_frame'].max()}\")\nprint(f\"   • Stop frames range: {annotation_data['stop_frame'].min()} - {annotation_data['stop_frame'].max()}\")\nprint(f\"   • Average action duration: {(annotation_data['stop_frame'] - annotation_data['start_frame']).mean():.1f} frames\")\n\n# Agents and targets\nprint(f\"\\n🎯 Agent/Target Analysis:\")\nagents = annotation_data['agent_id'].unique()\ntargets = annotation_data['target_id'].unique()\nprint(f\"   • Unique agents: {sorted(agents)}\")\nprint(f\"   • Unique targets: {sorted(targets)}\")\n\n# Visualize annotation data\nfig, axes = plt.subplots(2, 2, figsize=(16, 12))\n\n# Action frequency\nax1 = axes[0, 0]\naction_counts.plot(kind='bar', ax=ax1, color='lightcoral')\nax1.set_title('🎭 Action Frequency in Sample Video', fontsize=14, fontweight='bold')\nax1.set_xlabel('Action')\nax1.set_ylabel('Count')\nax1.tick_params(axis='x', rotation=45)\n\n# Action duration distribution\nax2 = axes[0, 1]\ndurations = annotation_data['stop_frame'] - annotation_data['start_frame']\ndurations.hist(bins=30, ax=ax2, color='lightblue', alpha=0.7)\nax2.set_title('⏱️ Action Duration Distribution', fontsize=14, fontweight='bold')\nax2.set_xlabel('Duration (frames)')\nax2.set_ylabel('Frequency')\n\n# Timeline of actions\nax3 = axes[1, 0]\nfor i, (idx, row) in enumerate(annotation_data.head(20).iterrows()):\n    ax3.barh(i, row['stop_frame'] - row['start_frame'], \n             left=row['start_frame'], alpha=0.7,\n             label=row['action'] if i < 5 else \"\")\nax3.set_title('📅 Action Timeline (First 20 actions)', fontsize=14, fontweight='bold')\nax3.set_xlabel('Frame Number')\nax3.set_ylabel('Action Instance')\n\n# Agent-Target interaction matrix\nax4 = axes[1, 1]\ninteraction_matrix = annotation_data.groupby(['agent_id', 'target_id']).size().unstack(fill_value=0)\nsns.heatmap(interaction_matrix, annot=True, fmt='d', ax=ax4, cmap='YlOrRd')\nax4.set_title('🤝 Agent-Target Interaction Matrix', fontsize=14, fontweight='bold')\nax4.set_xlabel('Target ID')\nax4.set_ylabel('Agent ID')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T08:12:41.022623Z","iopub.execute_input":"2025-09-19T08:12:41.02294Z","iopub.status.idle":"2025-09-19T08:12:42.112066Z","shell.execute_reply.started":"2025-09-19T08:12:41.022912Z","shell.execute_reply":"2025-09-19T08:12:42.110483Z"}},"outputs":[],"execution_count":null}]}