{"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":59156,"databundleVersionId":13719397,"sourceType":"competition"},{"sourceId":13172654,"sourceType":"datasetVersion","datasetId":8347346}],"dockerImageVersionId":31089,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport joblib\nimport json\n\n# --- PART 1: Load Model and Training Columns ---\n# IMPORTANT: Update 'mabe-final-assets' if you named your dataset something else\nmodel_path = '/kaggle/input/mabe-final-assets/final_model.pkl' \ncolumns_path = '/kaggle/input/mabe-final-assets/training_columns.json'\n\nmodel = joblib.load(model_path)\nwith open(columns_path, 'r') as f:\n    training_columns = json.load(f)\n\n# --- PART 2: Feature Engineering Function ---\ndef create_features_for_video(video_id, lab_id, data_path):\n    try:\n        tracking_file_path = f\"{data_path}/{lab_id}/{video_id}.parquet\"\n        tracking_df = pd.read_parquet(tracking_file_path)\n        mice_in_video = tracking_df['mouse_id'].unique()\n        if 1 not in mice_in_video or 2 not in mice_in_video: return None\n        wide_df = tracking_df.pivot(index=['video_frame', 'mouse_id'], columns='bodypart', values=['x', 'y'])\n        wide_df.columns = ['_'.join(col) for col in wide_df.columns.values]\n        wide_df = wide_df.reset_index().interpolate(method='linear', limit_direction='both')\n        wide_df['body_length'] = np.sqrt((wide_df['x_nose'] - wide_df['x_tail_base'])**2 + (wide_df['y_nose'] - wide_df['y_tail_base'])**2)\n        bodyparts = ['nose', 'tail_base']\n        for part in bodyparts:\n            for coord in ['x', 'y']:\n                col_name = f'{coord}_{part}'\n                wide_df[f'vel_{col_name}'] = wide_df.groupby('mouse_id')[col_name].diff().fillna(0)\n                wide_df[f'accel_{col_name}'] = wide_df.groupby('mouse_id')[f'vel_{col_name}'].diff().fillna(0)\n        mouse1_df = wide_df[wide_df['mouse_id'] == 1].set_index('video_frame')\n        mouse2_df = wide_df[wide_df['mouse_id'] == 2].set_index('video_frame')\n        features_df = pd.merge(mouse1_df, mouse2_df, on='video_frame', suffixes=('_m1', '_m2'))\n        features_df['nose_to_nose_dist'] = np.sqrt((features_df['x_nose_m1'] - features_df['x_nose_m2'])**2 + (features_df['y_nose_m1'] - features_df['y_nose_m2'])**2)\n        features_df['nose_to_tail_dist'] = np.sqrt((features_df['x_nose_m1'] - features_df['x_tail_base_m2'])**2 + (features_df['y_nose_m1'] - features_df['y_tail_base_m2'])**2)\n        features_df = features_df.drop(columns=['mouse_id_m1', 'mouse_id_m2'])\n        \n        # Force the columns to match the training set\n        return features_df.reindex(columns=training_columns, fill_value=0)\n    except Exception as e:\n        return None\n\n# --- PART 3: Process the Test Set and Create Submission File ---\ncompetition_data_path = '/kaggle/input/MABe-mouse-behavior-detection'\ntest_tracking_path = f'{competition_data_path}/test_tracking'\ntest_df = pd.read_csv(f'{competition_data_path}/test.csv')\nvideo_to_lab_map = test_df.set_index('video_id')['lab_id'].to_dict()\nall_predictions = []\n\nprint(\"Starting prediction on the hidden test set...\")\nfor video_id, lab_id in video_to_lab_map.items():\n    features = create_features_for_video(video_id, lab_id, test_tracking_path)\n    if features is not None and not features.empty:\n        frame_predictions = model.predict(features)\n        current_action = 'background'\n        start_frame = -1\n        for i, action in enumerate(frame_predictions):\n            frame_num = features.index[i]\n            if action != current_action:\n                if current_action != 'background':\n                    all_predictions.append([video_id, 1, 2, current_action, start_frame, frame_num - 1])\n                current_action = action\n                start_frame = frame_num\n        if current_action != 'background':\n            all_predictions.append([video_id, 1, 2, current_action, start_frame, features.index[-1]])\n\nprint(\"Prediction complete. Creating submission file...\")\nsubmission_df = pd.DataFrame(all_predictions, columns=['video_id', 'agent_id', 'target_id', 'action', 'start_frame', 'stop_frame'])\nsubmission_df['agent_id'] = 'mouse' + submission_df['agent_id'].astype(str)\nsubmission_df['target_id'] = 'mouse' + submission_df['target_id'].astype(str)\nsubmission_df.insert(0, 'row_id', range(len(submission_df)))\nsubmission_df.to_csv('submission.csv', index=False)\nprint(\"submission.csv created successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T06:18:28.201922Z","iopub.execute_input":"2025-09-26T06:18:28.202773Z","iopub.status.idle":"2025-09-26T06:18:41.947177Z","shell.execute_reply.started":"2025-09-26T06:18:28.202732Z","shell.execute_reply":"2025-09-26T06:18:41.945820Z"}},"outputs":[],"execution_count":null}]}