{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":99552,"databundleVersionId":13851420},{"sourceType":"datasetVersion","sourceId":13382569,"datasetId":8491061,"databundleVersionId":14092251},{"sourceType":"datasetVersion","sourceId":14048010,"datasetId":8943298,"databundleVersionId":14827121},{"sourceType":"datasetVersion","sourceId":15727526,"datasetId":10074332,"databundleVersionId":16668720},{"sourceType":"datasetVersion","sourceId":15727550,"datasetId":10076883,"databundleVersionId":16668745}],"dockerImageVersionId":31328,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport glob\nimport numpy as np\nimport polars as pl\nimport nibabel as nib\nimport pydicom\nimport matplotlib.pyplot as plt","metadata":{"trusted":true,"execution":{"execution_failed":"2026-04-14T19:20:26.379Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nDATA_ROOT = \"/kaggle/input/competitions/rsna-intracranial-aneurysm-detection\"\nSERIES_ROOT = f\"{DATA_ROOT}/series\"\nSEG_ROOT = f\"{DATA_ROOT}/segmentations\"\nWORK_ROOT = \"/kaggle/working/\"\n\nprint(\"DATA_ROOT exists:\", os.path.exists(DATA_ROOT))\nprint(\"SERIES_ROOT exists:\", os.path.exists(SERIES_ROOT))\nprint(\"SEG_ROOT exists:\", os.path.exists(SEG_ROOT))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:21:18.40568Z","iopub.execute_input":"2026-04-14T19:21:18.406112Z","iopub.status.idle":"2026-04-14T19:21:18.414889Z","shell.execute_reply.started":"2026-04-14T19:21:18.406082Z","shell.execute_reply":"2026-04-14T19:21:18.414079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Files in DATA_ROOT:\")\nfor f in os.listdir(DATA_ROOT):\n    print(\" -\", f)\n\nprint(\"\\nFirst 5 series folders:\")\nfor s in sorted(os.listdir(SERIES_ROOT))[:5]:\n    print(\" -\", s)\n\nprint(\"\\nFirst 5 segmentation files:\")\nfor s in sorted(os.listdir(SEG_ROOT))[:5]:\n    print(\" -\", s)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:21:30.81984Z","iopub.execute_input":"2026-04-14T19:21:30.820297Z","iopub.status.idle":"2026-04-14T19:21:31.200559Z","shell.execute_reply.started":"2026-04-14T19:21:30.820267Z","shell.execute_reply":"2026-04-14T19:21:31.199512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import polars as pl\n\ntrain = pl.read_csv(f\"{DATA_ROOT}/train.csv\")\nlocalizers = pl.read_csv(f\"{DATA_ROOT}/train_localizers.csv\")\n\nprint(\"train.csv shape:\", train.shape)\nprint(\"train_localizers.csv shape:\", localizers.shape)\n\nprint(\"\\ntrain columns:\")\nprint(train.columns)\n\nprint(\"\\nlocalizers columns:\")\nprint(localizers.columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:22:07.344427Z","iopub.execute_input":"2026-04-14T19:22:07.345235Z","iopub.status.idle":"2026-04-14T19:22:08.383696Z","shell.execute_reply.started":"2026-04-14T19:22:07.3452Z","shell.execute_reply":"2026-04-14T19:22:08.382556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Train rows: {len(train)}\")\n\nif \"Aneurysm Present\" in train.columns:\n    print(f\"Positive cases: {int(train['Aneurysm Present'].sum())}\")\n    print(f\"Negative cases: {int((train['Aneurysm Present'] == 0).sum())}\")\n\nprint(\"\\nFirst 5 train rows:\")\nprint(train.head(5))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:22:12.74754Z","iopub.execute_input":"2026-04-14T19:22:12.747915Z","iopub.status.idle":"2026-04-14T19:22:12.799358Z","shell.execute_reply.started":"2026-04-14T19:22:12.747884Z","shell.execute_reply":"2026-04-14T19:22:12.79796Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"exclude = {\"SeriesInstanceUID\", \"PatientAge\", \"PatientSex\", \"Modality\", \"Aneurysm Present\"}\nlocation_cols = [c for c in train.columns if c not in exclude]\n\nprint(\"Aneurysm location counts:\")\nfor col in location_cols:\n    if train[col].dtype in [pl.Int64, pl.Int32, pl.Float64, pl.Float32]:\n        print(f\"{col:<35} {int(train[col].sum())}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:22:21.881425Z","iopub.execute_input":"2026-04-14T19:22:21.881921Z","iopub.status.idle":"2026-04-14T19:22:21.889987Z","shell.execute_reply.started":"2026-04-14T19:22:21.881884Z","shell.execute_reply":"2026-04-14T19:22:21.888761Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"First 10 localizer rows:\")\nprint(localizers.head(10))\n\nif \"SeriesInstanceUID\" in localizers.columns:\n    loc_counts = (\n        localizers\n        .group_by(\"SeriesInstanceUID\")\n        .len()\n        .sort(\"len\", descending=True)\n    )\n    print(\"\\nTop series by localizer row count:\")\n    print(loc_counts.head(10))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:22:31.404585Z","iopub.execute_input":"2026-04-14T19:22:31.405504Z","iopub.status.idle":"2026-04-14T19:22:31.492854Z","shell.execute_reply.started":"2026-04-14T19:22:31.40547Z","shell.execute_reply":"2026-04-14T19:22:31.491763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def dicom_series_to_volume(series_path):\n    dcm_files = sorted(glob.glob(os.path.join(series_path, \"*.dcm\")))\n    if len(dcm_files) == 0:\n        return None, 0\n\n    slices = []\n    for f in dcm_files:\n        ds = pydicom.dcmread(f)\n        img = ds.pixel_array.astype(np.float32)\n        img = img * float(getattr(ds, \"RescaleSlope\", 1)) + float(getattr(ds, \"RescaleIntercept\", 0))\n        slices.append(img)\n\n    vol = np.stack(slices, axis=2)\n    return vol, len(dcm_files)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:22:45.276971Z","iopub.execute_input":"2026-04-14T19:22:45.277434Z","iopub.status.idle":"2026-04-14T19:22:45.283879Z","shell.execute_reply.started":"2026-04-14T19:22:45.277402Z","shell.execute_reply":"2026-04-14T19:22:45.282699Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"positives = train.filter(pl.col(\"Aneurysm Present\") == 1)\nprint(f\"Total positive cases: {len(positives)}\")\n\nshow_cols = [c for c in [\"SeriesInstanceUID\", \"Aneurysm Present\", \"Modality\", \"PatientAge\", \"PatientSex\"] if c in train.columns]\nprint(\"\\nSample positive cases:\")\nprint(positives.select(show_cols).head(5))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:22:55.443648Z","iopub.execute_input":"2026-04-14T19:22:55.444075Z","iopub.status.idle":"2026-04-14T19:22:55.472708Z","shell.execute_reply.started":"2026-04-14T19:22:55.444043Z","shell.execute_reply":"2026-04-14T19:22:55.471986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport glob\nimport numpy as np\nimport polars as pl\nimport nibabel as nib\nimport pydicom\nimport matplotlib.pyplot as plt\n\nrow = positives.to_dicts()[0]\nuid = row[\"SeriesInstanceUID\"]\n\nseries_path = os.path.join(SERIES_ROOT, uid)\nprint(\"Using UID:\", uid)\nprint(\"Series path exists:\", os.path.exists(series_path))\n\nvol, n_slices = dicom_series_to_volume(series_path)\nprint(\"DICOM slices:\", n_slices)\n\nout_path = f\"{WORK_ROOT}/positive_1.nii\"\nnib.save(nib.Nifti1Image(vol, np.eye(4)), out_path)\n\nprint(\"Saved:\", out_path)\nprint(\"Volume shape:\", vol.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:24:31.813845Z","iopub.execute_input":"2026-04-14T19:24:31.814291Z","iopub.status.idle":"2026-04-14T19:24:40.180385Z","shell.execute_reply.started":"2026-04-14T19:24:31.814263Z","shell.execute_reply":"2026-04-14T19:24:40.179333Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nii_files = sorted(glob.glob(f\"{WORK_ROOT}/*.nii\"))\n\nprint(\"NIfTI files in working folder:\")\nfor f in nii_files:\n    print(\" -\", os.path.basename(f))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:24:50.970298Z","iopub.execute_input":"2026-04-14T19:24:50.971184Z","iopub.status.idle":"2026-04-14T19:24:50.977135Z","shell.execute_reply.started":"2026-04-14T19:24:50.971149Z","shell.execute_reply":"2026-04-14T19:24:50.975882Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"vol = nib.load(f\"{WORK_ROOT}/positive_1.nii\").get_fdata()\n\nprint(\"Loaded positive_1.nii\")\nprint(\"Shape:\", vol.shape)\nprint(\"Min HU:\", float(vol.min()))\nprint(\"Max HU:\", float(vol.max()))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:24:56.70518Z","iopub.execute_input":"2026-04-14T19:24:56.705512Z","iopub.status.idle":"2026-04-14T19:24:57.058902Z","shell.execute_reply.started":"2026-04-14T19:24:56.705451Z","shell.execute_reply":"2026-04-14T19:24:57.057864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"total = vol.shape[2]\n\nprint(f\"Total slices: {total}\")\nprint(f\"Current middle slice: {total // 2}\")\nprint(f\"Better brain slice: {int(total * 0.6)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:25:03.343881Z","iopub.execute_input":"2026-04-14T19:25:03.344675Z","iopub.status.idle":"2026-04-14T19:25:03.35021Z","shell.execute_reply.started":"2026-04-14T19:25:03.34464Z","shell.execute_reply":"2026-04-14T19:25:03.348971Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"idxs = [int(total * 0.45), int(total * 0.60), int(total * 0.75)]\ntitles = [\"Lower brain\", \"Better brain slice\", \"Upper brain\"]\n\nfig, axes = plt.subplots(1, 3, figsize=(15, 5))\nfor ax, idx, title in zip(axes, idxs, titles):\n    sl = vol[:, :, idx]\n    sl = np.clip(sl, -100, 700)\n    sl = (sl - sl.min()) / (sl.max() - sl.min() + 1e-6)\n    ax.imshow(sl, cmap=\"gray\")\n    ax.set_title(f\"{title}\\nSlice {idx}/{total}\")\n    ax.axis(\"off\")\n\nplt.tight_layout()\nplt.savefig(f\"{WORK_ROOT}/slice_check.png\", dpi=150)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:25:09.623476Z","iopub.execute_input":"2026-04-14T19:25:09.623811Z","iopub.status.idle":"2026-04-14T19:25:11.141327Z","shell.execute_reply.started":"2026-04-14T19:25:09.623754Z","shell.execute_reply":"2026-04-14T19:25:11.139859Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"idx = int(total * 0.6)\nsl = vol[:, :, idx]\n\nprint(f\"Volume shape: {vol.shape}\")\nprint(f\"HU min: {vol.min():.1f}\")\nprint(f\"HU max: {vol.max():.1f}\")\nprint(f\"Brain-slice mean: {sl.mean():.1f}\")\nprint(f\"Brain-slice std: {sl.std():.1f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:25:15.702751Z","iopub.execute_input":"2026-04-14T19:25:15.703147Z","iopub.status.idle":"2026-04-14T19:25:15.813261Z","shell.execute_reply.started":"2026-04-14T19:25:15.703118Z","shell.execute_reply":"2026-04-14T19:25:15.812201Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"seg_files = sorted(glob.glob(os.path.join(SEG_ROOT, \"*.nii\")))\n\nprint(\"Segmentation files found:\", len(seg_files))\nfor f in seg_files[:10]:\n    print(\" -\", os.path.basename(f))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:25:20.512548Z","iopub.execute_input":"2026-04-14T19:25:20.512869Z","iopub.status.idle":"2026-04-14T19:25:20.522454Z","shell.execute_reply.started":"2026-04-14T19:25:20.512843Z","shell.execute_reply":"2026-04-14T19:25:20.521662Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"vol_path = f\"{WORK_ROOT}/positive_1.nii\"\n\nif os.path.exists(vol_path) and len(seg_files) > 0:\n    vol = nib.load(vol_path).get_fdata()\n    seg = nib.load(seg_files[0]).get_fdata()\n\n    print(\"Volume shape:\", vol.shape)\n    print(\"Segmentation shape:\", seg.shape)\n\n    total = min(vol.shape[2], seg.shape[2])\n    idx = int(total * 0.6)\n\n    img = vol[:, :, idx]\n    msk = seg[:, :, idx] if seg.ndim == 3 else seg\n\n    img = np.clip(img, -100, 700)\n    img = (img - img.min()) / (img.max() - img.min() + 1e-6)\n\n    fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n\n    axes[0].imshow(img, cmap=\"gray\")\n    axes[0].set_title(\"Image\")\n    axes[0].axis(\"off\")\n\n    axes[1].imshow(msk, cmap=\"hot\")\n    axes[1].set_title(\"Mask\")\n    axes[1].axis(\"off\")\n\n    axes[2].imshow(img, cmap=\"gray\")\n    axes[2].imshow(msk, cmap=\"jet\", alpha=0.35)\n    axes[2].set_title(\"Overlay\")\n    axes[2].axis(\"off\")\n\n    plt.tight_layout()\n    plt.savefig(f\"{WORK_ROOT}/mask_overlay.png\", dpi=150)\n    plt.show()\nelse:\n    print(\"Missing positive_1.nii or no segmentation files found.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:25:25.87389Z","iopub.execute_input":"2026-04-14T19:25:25.874601Z","iopub.status.idle":"2026-04-14T19:25:32.472977Z","shell.execute_reply.started":"2026-04-14T19:25:25.874567Z","shell.execute_reply":"2026-04-14T19:25:32.471913Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"converted = 0\nmax_cases = 5\n\nfor row in positives.head(max_cases).to_dicts():\n    uid = row[\"SeriesInstanceUID\"]\n    series_path = os.path.join(SERIES_ROOT, uid)\n\n    if not os.path.exists(series_path):\n        print(\"Missing series:\", uid)\n        continue\n\n    vol, n_slices = dicom_series_to_volume(series_path)\n    if vol is None or n_slices < 10:\n        print(\"Skipped:\", uid)\n        continue\n\n    out_path = f\"{WORK_ROOT}/positive_{converted+1}.nii\"\n    nib.save(nib.Nifti1Image(vol, np.eye(4)), out_path)\n\n    print(f\"✅ Saved {os.path.basename(out_path)} | shape={vol.shape} | slices={n_slices}\")\n    converted += 1\n\nprint(f\"\\nTotal NIfTI files created for deployment testing: {converted}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:25:45.448901Z","iopub.execute_input":"2026-04-14T19:25:45.44921Z","iopub.status.idle":"2026-04-14T19:26:51.051263Z","shell.execute_reply.started":"2026-04-14T19:25:45.449184Z","shell.execute_reply":"2026-04-14T19:26:51.050091Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nii_files = sorted(glob.glob(f\"{WORK_ROOT}/positive_*.nii\"))\n\nprint(\"Created NIfTI files:\")\nfor f in nii_files:\n    print(\" -\", os.path.basename(f))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-14T19:26:51.052624Z","iopub.execute_input":"2026-04-14T19:26:51.053061Z","iopub.status.idle":"2026-04-14T19:26:51.060239Z","shell.execute_reply.started":"2026-04-14T19:26:51.053013Z","shell.execute_reply":"2026-04-14T19:26:51.059065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}