{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91249,"databundleVersionId":11294684,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"%matplotlib inline\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport os\nimport numpy as np\nfrom mpl_toolkits.mplot3d import Axes3D\n\ndef visualize_flagellar_motors(base_path, tomo_id=None, alpha=0.3, downscale=2):\n    tomograms = [d for d in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, d))]\n\n    target_dir = os.path.join(base_path, tomo_id if tomo_id else tomograms[0])\n\n    slices = sorted([f for f in os.listdir(target_dir) if f.endswith('.jpg')],\n                    key=lambda x: int(x.split('_')[1].split('.')[0]))  # 解析slice_0000格式\n\n    first_slice = Image.open(os.path.join(target_dir, slices[0]))\n    original_size = first_slice.size  # (width, height)\n    first_slice.close()\n    \n    new_size = (original_size[0]//downscale, original_size[1]//downscale)\n    \n    z_center_idx = len(slices) // 2\n    z_center_slice = np.array(Image.open(os.path.join(target_dir, slices[z_center_idx]))\n                             .convert('L').resize(new_size))\n    \n    max_projection = np.zeros(new_size[::-1], dtype=np.uint8)  # (height, width)\n    sum_projection = np.zeros(new_size[::-1], dtype=np.float32)\n    \n    for i, f in enumerate(slices):\n        img = Image.open(os.path.join(target_dir, f)).convert('L').resize(new_size)\n        slice_data = np.array(img)\n        img.close()\n        \n        np.maximum(max_projection, slice_data, out=max_projection)\n        sum_projection += slice_data.astype(np.float32)\n        \n        del slice_data\n    \n    avg_projection = (sum_projection / len(slices)).astype(np.uint8)\n    \n    fig, axs = plt.subplots(1, 3, figsize=(18, 6))\n    \n    axs[0].imshow(z_center_slice, cmap='gray')\n    axs[0].set_title(\"Center Slice\")\n    \n    axs[1].imshow(max_projection, cmap='gray')\n    axs[1].set_title(\"Max Projection\")\n    \n    axs[2].imshow(avg_projection, cmap='gray')\n    axs[2].set_title(\"Average Projection\")\n    \n    plt.tight_layout()\n    #plt.close()\n    return #fig\n\nvisualize_flagellar_motors('/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train/', tomo_id='tomo_00e047', downscale=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T15:03:16.977835Z","iopub.execute_input":"2025-03-26T15:03:16.978161Z","iopub.status.idle":"2025-03-26T15:03:22.481523Z","shell.execute_reply.started":"2025-03-26T15:03:16.978138Z","shell.execute_reply":"2025-03-26T15:03:22.480514Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nfrom PIL import Image\nimport pandas as pd\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\n\ndef interactive_3d_visualization(base_path, tomo_id, label_path='/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train_labels.csv', downscale=8):\n    labels = pd.read_csv(label_path)\n    tomo_labels = labels[labels['tomo_id'] == tomo_id]\n    \n    target_dir = os.path.join(base_path, tomo_id)\n    slices = sorted([f for f in os.listdir(target_dir) if f.endswith('.jpg')],\n                    key=lambda x: int(x.split('_')[1].split('.')[0]))\n    \n    first_slice = Image.open(os.path.join(target_dir, slices[0]))\n    original_size = first_slice.size\n    new_size = (original_size[0]//downscale, original_size[1]//downscale)\n    first_slice.close()\n    \n    volume = np.zeros((len(slices), new_size[1], new_size[0]), dtype=np.uint8)\n    \n    for i, f in enumerate(slices):\n        img = Image.open(os.path.join(target_dir, f)).convert('L').resize(new_size)\n        volume[i] = np.array(img)\n        img.close()\n    \n    fig = go.Figure()\n    \n    fig.add_trace(go.Volume(\n        x=volume.shape[2]*np.ones(volume.size),\n        y=np.repeat(np.arange(volume.shape[1]), volume.shape[0]*volume.shape[2]),\n        z=np.tile(np.repeat(np.arange(volume.shape[0]), volume.shape[2]), volume.shape[1]),\n        value=volume.flatten(),\n        isomin=np.percentile(volume, 50),\n        isomax=np.percentile(volume, 99),\n        opacity=0.05,\n        surface_count=15,\n        colorscale='gray'\n    ))\n    \n    if not tomo_labels.empty:\n        for _, row in tomo_labels.iterrows():\n            z = row['Motor axis 0'] / downscale\n            y = row['Motor axis 1'] / downscale\n            x = row['Motor axis 2'] / downscale\n            \n            fig.add_trace(go.Scatter3d(\n                x=[x],\n                y=[y],\n                z=[z],\n                mode='markers',\n                marker=dict(\n                    size=10,\n                    color='red',\n                    opacity=0.8\n                ),\n                name=f'Motor ({x:.1f}, {y:.1f}, {z:.1f})'\n            ))\n    \n    fig.update_layout(\n        scene=dict(\n            xaxis=dict(title='X'),\n            yaxis=dict(title='Y'),\n            zaxis=dict(title='Z'),\n            camera=dict(eye=dict(x=1.5, y=1.5, z=1.5))\n        ),\n        width=800,\n        height=640\n    )\n    \n    return fig\n\ntomo_id = 'tomo_00e047'\nfig = interactive_3d_visualization('/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train/', tomo_id)\nfig.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T15:03:56.208832Z","iopub.execute_input":"2025-03-26T15:03:56.209144Z","iopub.status.idle":"2025-03-26T15:04:01.960039Z","shell.execute_reply.started":"2025-03-26T15:03:56.209122Z","shell.execute_reply":"2025-03-26T15:04:01.958930Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nfrom PIL import Image\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\n\ndef visualize_motor_slices(base_path, tomo_id, label_path='/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train_labels.csv', z_range=5, box_size=20):\n    labels = pd.read_csv(label_path)\n    tomo_labels = labels[labels['tomo_id'] == tomo_id]\n\n    target_dir = os.path.join(base_path, tomo_id)\n    slices = sorted([f for f in os.listdir(target_dir) if f.endswith('.jpg')],\n                    key=lambda x: int(x.split('_')[1].split('.')[0]))\n    \n    sample_slice = np.array(Image.open(os.path.join(target_dir, slices[0])))\n    slice_shape = sample_slice.shape\n    num_slices = len(slices)\n    \n    combined_image = np.zeros(slice_shape, dtype=np.float32)\n    motor_boxes = []\n\n    for _, motor in tomo_labels.iterrows():\n        z_center = int(motor['Motor axis 0'])\n        y_center = int(motor['Motor axis 1'])\n        x_center = int(motor['Motor axis 2'])\n        \n        z_start = max(0, z_center - z_range)\n        z_end = min(num_slices, z_center + z_range + 1)\n        \n        slice_count = 0\n        for z in range(z_start, z_end):\n            img = np.array(Image.open(os.path.join(target_dir, slices[z])).convert('L'))\n            combined_image += img.astype(np.float32)\n            slice_count += 1\n        \n        motor_boxes.append((\n            x_center - box_size//2,  # x_min\n            y_center - box_size//2,  # y_min\n            box_size,                # width\n            box_size,                # height\n            f\"Motor@{z_center}\"      # label\n        ))\n\n        if slice_count > 0:\n            combined_image /= slice_count\n        combined_image = np.clip(combined_image, 0, 255).astype(np.uint8)\n\n    fig, ax = plt.subplots(figsize=(10, 10))\n    ax.imshow(combined_image, cmap='gray')\n    \n    for box in motor_boxes:\n        rect = patches.Rectangle(\n            (box[0], box[1]), box[2], box[3],\n            linewidth=2, edgecolor='r', facecolor='none'\n        )\n        ax.add_patch(rect)\n        plt.text(\n            box[0], box[1]-5, box[4],\n            color='red', fontsize=10, weight='bold'\n        )\n    \n    plt.title(f\"Tomogram {tomo_id}\\nMotor Positions (Red Boxes)\")\n    plt.axis('off')\n    plt.show()\n\nvisualize_motor_slices('/kaggle/input/byu-locating-bacterial-flagellar-motors-2025/train/', 'tomo_00e047', z_range=3, box_size=30)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T15:04:49.291448Z","iopub.execute_input":"2025-03-26T15:04:49.291923Z","iopub.status.idle":"2025-03-26T15:04:49.906845Z","shell.execute_reply.started":"2025-03-26T15:04:49.291883Z","shell.execute_reply":"2025-03-26T15:04:49.905567Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}