{"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":99552,"databundleVersionId":13851420,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport shutil\nimport random\n\n# Input dataset folder (RSNA series folders)\nsrc_folder = \"/kaggle/input/rsna-intracranial-aneurysm-detection/series\"\n\n# Output folder for 10GB subset\ndst_folder = \"/kaggle/working/train_subset\"\nos.makedirs(dst_folder, exist_ok=True)\n\n# List all series folders (patients)\nseries_folders = [os.path.join(src_folder, d) for d in os.listdir(src_folder) \n                  if os.path.isdir(os.path.join(src_folder, d))]\n\nprint(\"Total series/patient folders:\", len(series_folders))\n\n# Shuffle folders for randomness\nrandom.shuffle(series_folders)\n\n# Copy DICOMs folder-wise until 10GB\nmax_size = 10 * (1024**3)  # 10GB\ncopied_size = 0\ncopied_series = 0\n\nfor folder in series_folders:\n    # Get all dicom files in this series\n    dicoms = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(\".dcm\")]\n\n    # Check if adding this series exceeds 10GB\n    series_size = sum(os.path.getsize(f) for f in dicoms)\n    if copied_size + series_size > max_size:\n        # If adding full series exceeds, copy files one by one until limit\n        for f in dicoms:\n            fsize = os.path.getsize(f)\n            if copied_size + fsize > max_size:\n                break\n            shutil.copy(f, dst_folder)\n            copied_size += fsize\n        break\n\n    # Copy entire series folder\n    for f in dicoms:\n        shutil.copy(f, dst_folder)\n    copied_size += series_size\n    copied_series += 1\n\nprint(f\"✅ Copied {copied_series} series/patients, total size: {copied_size/(1024**3):.2f} GB\")\nprint(f\"Subset saved in: {dst_folder}\")\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pydicom\nimport cv2\nimport numpy as np\nfrom tqdm import tqdm\n\n# Input folder: multiple patients DICOM subset\nsrc_folder = \"/kaggle/working/train_subset\"\n\n# Output folder: preprocessed images\ndst_folder = \"/kaggle/working/preprocessed_images\"\nos.makedirs(dst_folder, exist_ok=True)\n\ndef window_image(img, window_center, window_width):\n    \"\"\"Apply DICOM windowing\"\"\"\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n    img = (img - img_min) / (img_max - img_min) * 255.0\n    return img.astype(np.uint8)\n\ndef preprocess_dicom_safe(dicom_path, output_path, size=(256, 256)):\n    try:\n        dcm = pydicom.dcmread(dicom_path)\n        img = dcm.pixel_array.astype(np.float32)\n\n        # Skip empty / zero-size images\n        if img is None or img.size == 0:\n            print(f\"⚠ Skipping empty DICOM: {dicom_path}\")\n            return\n\n        # Apply windowing if available\n        try:\n            wc = dcm.WindowCenter\n            ww = dcm.WindowWidth\n            if isinstance(wc, pydicom.multival.MultiValue):\n                wc = wc[0]\n            if isinstance(ww, pydicom.multival.MultiValue):\n                ww = ww[0]\n            img = window_image(img, wc, ww)\n        except:\n            # fallback normalization\n            img = (img - np.min(img)) / (np.max(img) - np.min(img)) * 255.0\n            img = img.astype(np.uint8)\n\n        # Resize\n        if img.size == 0:\n            print(f\"⚠ Skipping DICOM with empty image after processing: {dicom_path}\")\n            return\n\n        img = cv2.resize(img, size)\n\n        # Ensure 2D for cv2.imwrite\n        if img.ndim == 2:\n            cv2.imwrite(output_path, img)\n        elif img.ndim == 3:\n            # take first channel if multi-channel\n            cv2.imwrite(output_path, img[:, :, 0])\n        else:\n            print(f\"⚠ Skipping invalid shape: {dicom_path}, shape={img.shape}\")\n\n    except Exception as e:\n        print(f\"❌ Error in {dicom_path}: {e}\")\n\n# Process all DICOM files in subset\nfor f in tqdm(os.listdir(src_folder)):\n    if f.endswith(\".dcm\"):\n        dicom_path = os.path.join(src_folder, f)\n        output_path = os.path.join(dst_folder, f.replace(\".dcm\", \".png\"))\n        preprocess_dicom_safe(dicom_path, output_path)\n\nprint(\"✅ Preprocessing complete! Images saved in:\", dst_folder)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-02T11:45:19.178296Z","iopub.execute_input":"2025-10-02T11:45:19.178696Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"SeriesInstanceUID","metadata":{}},{"cell_type":"code","source":"import os\nimport pydicom\nimport cv2\nimport numpy as np\nfrom tqdm import tqdm\n\n# Input folder: multiple patients DICOM subset\nsrc_folder = \"/kaggle/working/train_subset\"\n\n# Output folder: preprocessed images\ndst_folder = \"/kaggle/working/preprocessed_images\"\nos.makedirs(dst_folder, exist_ok=True)\n\ndef window_image(img, window_center, window_width):\n    \"\"\"Apply DICOM windowing\"\"\"\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n    img = (img - img_min) / (img_max - img_min) * 255.0\n    return img.astype(np.uint8)\n\ndef preprocess_dicom_safe(dicom_path, output_path, size=(256, 256)):\n    try:\n        dcm = pydicom.dcmread(dicom_path)\n        img = dcm.pixel_array.astype(np.float32)\n\n        # Skip empty / zero-size images\n        if img is None or img.size == 0:\n            print(f\"⚠ Skipping empty DICOM: {dicom_path}\")\n            return\n\n        # Apply windowing if available\n        try:\n            wc = dcm.WindowCenter\n            ww = dcm.WindowWidth\n            if isinstance(wc, pydicom.multival.MultiValue):\n                wc = wc[0]\n            if isinstance(ww, pydicom.multival.MultiValue):\n                ww = ww[0]\n            img = window_image(img, wc, ww)\n        except:\n            # fallback normalization\n            img = (img - np.min(img)) / (np.max(img) - np.min(img)) * 255.0\n            img = img.astype(np.uint8)\n\n        # Resize\n        if img.size == 0:\n            print(f\"⚠ Skipping DICOM with empty image after processing: {dicom_path}\")\n            return\n\n        img = cv2.resize(img, size)\n\n        # Ensure 2D for cv2.imwrite\n        if img.ndim == 2:\n            cv2.imwrite(output_path, img)\n        elif img.ndim == 3:\n            # take first channel if multi-channel\n            cv2.imwrite(output_path, img[:, :, 0])\n        else:\n            print(f\"⚠ Skipping invalid shape: {dicom_path}, shape={img.shape}\")\n\n    except Exception as e:\n        print(f\"❌ Error in {dicom_path}: {e}\")\n\n# Process all DICOM files in subset\nfor f in tqdm(os.listdir(src_folder)):\n    if f.endswith(\".dcm\"):\n        dicom_path = os.path.join(src_folder, f)\n        output_path = os.path.join(dst_folder, f.replace(\".dcm\", \".png\"))\n        preprocess_dicom_safe(dicom_path, output_path)\n\nprint(\"✅ Preprocessing complete! Images saved in:\", dst_folder)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}