{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":52950,"databundleVersionId":5973250,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport re\nimport warnings\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom scipy.signal import spectrogram\n\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-25T19:29:06.855934Z","iopub.execute_input":"2025-05-25T19:29:06.85659Z","iopub.status.idle":"2025-05-25T19:29:07.995732Z","shell.execute_reply.started":"2025-05-25T19:29:06.856551Z","shell.execute_reply":"2025-05-25T19:29:07.994607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_xyz_magnitude(data, columns):\n    coord_groups = {}\n    for col in columns:\n        match = re.match(r\"(x|y|z)_(.*)_(\\d+)\", col)\n        if match:\n            axis, _, idx = match.groups()\n            idx = int(idx)\n            coord_groups.setdefault(idx, {})[axis] = col\n\n    magnitudes = []\n    for idx in sorted(coord_groups):\n        group = coord_groups[idx]\n        if all(k in group for k in ['x', 'y', 'z']):\n            x = data[group['x']].fillna(0).values\n            y = data[group['y']].fillna(0).values\n            z = data[group['z']].fillna(0).values\n            mag = np.sqrt(x**2 + y**2 + z**2)\n            magnitudes.append(mag)\n\n    return np.array(magnitudes) if magnitudes else None\n\ndef normalize_matrix(mat):\n    norm_mat = mat.copy()\n    for i in range(norm_mat.shape[0]):\n        row = norm_mat[i]\n        if np.max(row) > 0:\n            norm_mat[i] = (row - np.min(row)) / (np.max(row) - np.min(row))\n    return norm_mat\n\ndef plot_component(name, matrix):\n    print(name)\n    plt.figure(figsize=(8, 3))\n    plt.imshow(matrix, aspect='auto', cmap='inferno', vmin=0, vmax=np.percentile(matrix, 99))\n    plt.tight_layout(pad=0)\n    plt.subplots_adjust(left=0, right=1, top=1, bottom=0)\n    plt.axis('off')\n    plt.savefig(f'{name}_figure.png')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T19:30:16.747915Z","iopub.execute_input":"2025-05-25T19:30:16.748269Z","iopub.status.idle":"2025-05-25T19:30:16.759453Z","shell.execute_reply.started":"2025-05-25T19:30:16.748246Z","shell.execute_reply":"2025-05-25T19:30:16.75834Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base = '/kaggle/input/asl-fingerspelling/train_landmarks'\npq_paths = os.listdir(base)\nidx = np.random.randint(0, len(pq_paths))\n\npath = os.path.join(base, pq_paths[idx])\ndata = pd.read_parquet(path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T19:30:16.970125Z","iopub.execute_input":"2025-05-25T19:30:16.970419Z","iopub.status.idle":"2025-05-25T19:30:33.96251Z","shell.execute_reply.started":"2025-05-25T19:30:16.970398Z","shell.execute_reply":"2025-05-25T19:30:33.961359Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"face_columns = [col for col in data.columns if 'face' in col]\npose_columns = [col for col in data.columns if 'pose' in col]\nleft_hand_columns = [col for col in data.columns if 'left_hand' in col]\nright_hand_columns = [col for col in data.columns if 'right_hand' in col]\n\ncomponents = {\n    \"face\": face_columns,\n    \"pose\": pose_columns,\n    \"left_hand\": left_hand_columns,\n    \"right_hand\": right_hand_columns,\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T19:30:33.964069Z","iopub.execute_input":"2025-05-25T19:30:33.964611Z","iopub.status.idle":"2025-05-25T19:30:33.972609Z","shell.execute_reply.started":"2025-05-25T19:30:33.964574Z","shell.execute_reply":"2025-05-25T19:30:33.971674Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"component_matrices = {}\nfor name, cols in components.items():\n    mag = extract_xyz_magnitude(data, cols)\n    if mag is not None and mag.size > 0:\n        norm_mag = normalize_matrix(mag)\n        component_matrices[name] = norm_mag\n        plot_component(name, norm_mag)\n    else:\n        print(f\"⚠️ Skipping '{name}': no valid landmarks found.\")\n\ngap_size = 5\nblock_offsets = {}\ncurrent_offset = 0\ntotal_rows = sum(mat.shape[0] + gap_size for mat in component_matrices.values())\n\nnum_frames = next(iter(component_matrices.values())).shape[1]\ncombined_matrix = np.zeros((total_rows, num_frames))\n\nfor name, mat in component_matrices.items():\n    block_offsets[name] = current_offset\n    combined_matrix[current_offset:current_offset + mat.shape[0], :] = mat\n    current_offset += mat.shape[0] + gap_size\n\nplt.figure(figsize=(8, 8))\nplt.imshow(combined_matrix, aspect='auto', cmap='inferno', vmin=0, vmax=np.percentile(combined_matrix, 99))\nplt.xlabel(\"Time\")\nplt.ylabel(\"Landmark idx\")\n\nfor name, offset in block_offsets.items():\n    plt.text(5, offset + 5, name, color='white', fontsize=10, va='top')\n\nplt.tight_layout(pad=0)\nplt.subplots_adjust(left=0, right=1, top=1, bottom=0)\nplt.savefig('combined_components_figure.png')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T19:30:33.973453Z","iopub.execute_input":"2025-05-25T19:30:33.973741Z","iopub.status.idle":"2025-05-25T19:31:37.462184Z","shell.execute_reply.started":"2025-05-25T19:30:33.973708Z","shell.execute_reply":"2025-05-25T19:31:37.461177Z"}},"outputs":[],"execution_count":null}]}