{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":99552,"databundleVersionId":13190393,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Setup the enviroment and import relevant libraries","metadata":{}},{"cell_type":"code","source":"# General utilities\nimport os\nimport numpy as np\nimport pandas as pd\n\n# Visualization\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# DICOM handling\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\n# Warnings\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:50:33.538199Z","iopub.execute_input":"2025-07-31T14:50:33.538379Z","iopub.status.idle":"2025-07-31T14:50:37.4022Z","shell.execute_reply.started":"2025-07-31T14:50:33.538362Z","shell.execute_reply":"2025-07-31T14:50:37.401506Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 3D visualization (optional for later steps)\nimport nibabel as nib  # for working with NifTI if needed\nimport cv2  # for interpolation / resizing in preprocessing\nfrom IPython.display import display, HTML  # for cleaner output\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:50:37.402962Z","iopub.execute_input":"2025-07-31T14:50:37.403328Z","iopub.status.idle":"2025-07-31T14:50:37.794827Z","shell.execute_reply.started":"2025-07-31T14:50:37.403303Z","shell.execute_reply":"2025-07-31T14:50:37.794312Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load and Explore the metadata","metadata":{}},{"cell_type":"code","source":"# Step 2: Load Metadata\nBASE_DIR = \"/kaggle/input/rsna-intracranial-aneurysm-detection\"\n\ntrain_df = pd.read_csv(f\"{BASE_DIR}/train.csv\")\nlocalizer_df = pd.read_csv(f\"{BASE_DIR}/train_localizers.csv\")\n\nprint(\"train.csv shape:\", train_df.shape)\nprint(\"train_localizers.csv shape:\", localizer_df.shape)\n\n# Aneurysm presence distribution\nprint(train_df[\"Aneurysm Present\"].value_counts())\n\n# Show some rows\ntrain_df.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:50:37.796037Z","iopub.execute_input":"2025-07-31T14:50:37.796431Z","iopub.status.idle":"2025-07-31T14:50:37.878496Z","shell.execute_reply.started":"2025-07-31T14:50:37.796413Z","shell.execute_reply":"2025-07-31T14:50:37.877848Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load & Visualize DICOM Series","metadata":{}},{"cell_type":"code","source":"# Step 3: Visualize a Series\ndef load_dicom_volume(series_path):\n    files = [pydicom.dcmread(os.path.join(series_path, f)) \n             for f in os.listdir(series_path) if f.endswith(\".dcm\")]\n    files.sort(key=lambda x: int(x.InstanceNumber))\n    \n    # Convert to 3D volume\n    volume = np.stack([f.pixel_array for f in files])\n    \n    return volume, files\n\n\ndef show_dicom_slices_grid(volume, num_rows=4, num_cols=6):\n    total_slices = num_rows * num_cols\n    interval = len(volume) // total_slices\n    selected_slices = [volume[i * interval] for i in range(total_slices)]\n\n    fig, axes = plt.subplots(num_rows, num_cols, figsize=(12, 8))\n    for i, ax in enumerate(axes.flat):\n        ax.imshow(selected_slices[i], cmap='gray')\n        ax.axis('off')\n    plt.suptitle(\"Sample DICOM Slices\", fontsize=16)\n    plt.tight_layout()\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:51:03.168375Z","iopub.execute_input":"2025-07-31T14:51:03.168771Z","iopub.status.idle":"2025-07-31T14:51:03.176113Z","shell.execute_reply.started":"2025-07-31T14:51:03.168737Z","shell.execute_reply":"2025-07-31T14:51:03.175291Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"series_dir = f\"/kaggle/input/rsna-intracranial-aneurysm-detection/series\"\nsample_uids = train_df[\"SeriesInstanceUID\"].unique()[:3]  # visualize first 3 patients\n\nfor uid in sample_uids:\n    print(f\"Series UID: {uid}\")\n    path = os.path.join(series_dir, uid)\n    \n    try:\n        volume, files = load_dicom_volume(path)\n        print(f\"Volume shape: {volume.shape}\")\n        show_dicom_slices_grid(volume)\n    except Exception as e:\n        print(f\"Error in series {uid}: {e}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:51:17.563294Z","iopub.execute_input":"2025-07-31T14:51:17.56403Z","iopub.status.idle":"2025-07-31T14:51:30.952282Z","shell.execute_reply.started":"2025-07-31T14:51:17.564001Z","shell.execute_reply":"2025-07-31T14:51:30.95152Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def scroll_dicom_series(volume):\n    from IPython.display import display, clear_output\n    import time\n    \n    for i in range(volume.shape[0]):\n        plt.imshow(volume[i], cmap='gray')\n        plt.title(f\"Slice {i + 1}/{volume.shape[0]}\")\n        plt.axis('off')\n        display(plt.gcf())\n        clear_output(wait=True)\n        time.sleep(0.1)  # Adjust speed\n\n# Example for one series:\nvolume, _ = load_dicom_volume(os.path.join(series_dir, sample_uids[0]))\nscroll_dicom_series(volume)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:52:04.334839Z","iopub.execute_input":"2025-07-31T14:52:04.335589Z","iopub.status.idle":"2025-07-31T14:53:45.944528Z","shell.execute_reply.started":"2025-07-31T14:52:04.335565Z","shell.execute_reply":"2025-07-31T14:53:45.943337Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## DICOM Preprocessing","metadata":{}},{"cell_type":"code","source":"from skimage.transform import resize\n\ndef preprocess_dicom_series(series_path, target_shape=(64, 128, 128), normalize=\"z-score\"):\n    \"\"\"\n    Preprocess a DICOM series: loads, sorts, normalizes, and resizes to target shape.\n    \n    Args:\n        series_path (str): Path to DICOM series folder.\n        target_shape (tuple): Output shape (Depth, Height, Width)\n        normalize (str): 'z-score' or 'min-max'\n    \n    Returns:\n        np.ndarray: Preprocessed 3D volume of shape target_shape\n    \"\"\"\n    # Step 1: Load and sort slices\n    slices = []\n    for fname in os.listdir(series_path):\n        if fname.endswith(\".dcm\"):\n            dcm = pydicom.dcmread(os.path.join(series_path, fname))\n            slices.append(dcm)\n    \n    # Sort by position in Z or instance number\n    try:\n        slices.sort(key=lambda x: float(x.ImagePositionPatient[2]))\n    except:\n        slices.sort(key=lambda x: int(x.InstanceNumber))\n    \n    # Stack to form a volume\n    volume = np.stack([s.pixel_array for s in slices])\n    volume = volume.astype(np.float32)\n\n    # Step 2: Intensity normalization\n    if normalize == \"min-max\":\n        volume = (volume - np.min(volume)) / (np.max(volume) - np.min(volume) + 1e-5)\n    elif normalize == \"z-score\":\n        mean = np.mean(volume)\n        std = np.std(volume)\n        volume = (volume - mean) / (std + 1e-5)\n    \n    # Step 3: Resize to target shape\n    volume_resized = resize(volume, output_shape=target_shape, preserve_range=True, mode='constant')\n    \n    return volume_resized\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:54:21.98933Z","iopub.execute_input":"2025-07-31T14:54:21.990009Z","iopub.status.idle":"2025-07-31T14:54:22.072265Z","shell.execute_reply.started":"2025-07-31T14:54:21.989983Z","shell.execute_reply":"2025-07-31T14:54:22.071773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sample_uid = train_df.iloc[0][\"SeriesInstanceUID\"]\nsample_path = os.path.join(series_dir, sample_uid)\n\nvolume_cleaned = preprocess_dicom_series(sample_path, target_shape=(64, 128, 128))\nprint(\"Processed volume shape:\", volume_cleaned.shape)\n\n# Visualize a few slices\nplt.figure(figsize=(10, 6))\nfor i in range(6):\n    plt.subplot(2, 3, i+1)\n    plt.imshow(volume_cleaned[i * 10], cmap=\"gray\")\n    plt.axis(\"off\")\n    plt.title(f\"Slice {i * 10}\")\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-31T14:54:39.70262Z","iopub.execute_input":"2025-07-31T14:54:39.703285Z","iopub.status.idle":"2025-07-31T14:54:44.783122Z","shell.execute_reply.started":"2025-07-31T14:54:39.703264Z","shell.execute_reply":"2025-07-31T14:54:44.782521Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}