{"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":"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\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,"execution":{"iopub.status.busy":"2025-08-12T10:48:31.507487Z","iopub.execute_input":"2025-08-12T10:48:31.50798Z","iopub.status.idle":"2025-08-12T10:48:32.190572Z","shell.execute_reply.started":"2025-08-12T10:48:31.507903Z","shell.execute_reply":"2025-08-12T10:48:32.189401Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === Paths (senden gelenler) ===\nCOW_MASK = \"/kaggle/input/rsna-intracranial-aneurysm-detection/segmentations/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381_cowseg.nii\"\nVOL_NII  = \"/kaggle/input/rsna-intracranial-aneurysm-detection/segmentations/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381.nii\"\nONE_DICOM = \"/kaggle/input/rsna-intracranial-aneurysm-detection/series/1.2.826.0.1.3680043.8.498.10004044428023505108375152878107656647/1.2.826.0.1.3680043.8.498.10124807242473374136099471315028464450.dcm\"\n\nTRAIN_CSV = \"/kaggle/input/rsna-intracranial-aneurysm-detection/train.csv\"\nLOC_CSV   = \"/kaggle/input/rsna-intracranial-aneurysm-detection/train_localizers.csv\"\n\n# === Imports ===\nimport os, json, numpy as np, nibabel as nib, SimpleITK as sitk, pydicom\nimport pandas as pd\n\nWORKDIR = \"/kaggle/working/check_case\"\nos.makedirs(WORKDIR, exist_ok=True)\n\ndef load_canonical_nii(path, dtype=None):\n    \"\"\"NIfTI'yi RAS kanonik yönüne çevir, isteğe bağlı dtype uygula.\"\"\"\n    img = nib.load(path)\n    can = nib.as_closest_canonical(img)\n    data = can.get_fdata()\n    if dtype is not None:\n        data = data.astype(dtype)\n    return nib.Nifti1Image(data, can.affine)\n\ndef save_nii(img, out_path):\n    nib.save(img, out_path)\n    return out_path\n\ndef nii_info(img):\n    \"\"\"Şekil, voxel spacing (zooms), aralık (min/max).\"\"\"\n    data = img.get_fdata()\n    return {\n        \"shape\": tuple(data.shape),\n        \"zooms\": tuple(np.round(img.header.get_zooms(), 5)),\n        \"dtype\": str(data.dtype),\n        \"minmax\": (float(np.nanmin(data)), float(np.nanmax(data))),\n    }\n\ndef resample_to_ref(moving_path, ref_path, out_path, is_label=False):\n    \"\"\"moving NIfTI'yi ref NIfTI'ye SimpleITK ile hizala (grid/spacinge).\"\"\"\n    moving = sitk.ReadImage(moving_path)\n    ref = sitk.ReadImage(ref_path)\n    resampler = sitk.ResampleImageFilter()\n    resampler.SetReferenceImage(ref)\n    resampler.SetInterpolator(sitk.sitkNearestNeighbor if is_label else sitk.sitkLinear)\n    out = resampler.Execute(moving)\n    sitk.WriteImage(out, out_path)\n    return out_path\n\n# 1) Hacmi ve CoW maskesini kanonikleştir\nvol_can = load_canonical_nii(VOL_NII, np.float32)\nmsk_can = load_canonical_nii(COW_MASK, np.uint8)\n\nvol_can_path = save_nii(vol_can, os.path.join(WORKDIR, \"vol_canonical.nii.gz\"))\nmsk_can_path = save_nii(msk_can, os.path.join(WORKDIR, \"cow_canonical.nii.gz\"))\n\nprint(\"Vol:\", nii_info(vol_can))\nprint(\"Mask:\", nii_info(msk_can))\n\n# 2) Shape/affine kontrolü; farklıysa maske hacme yeniden örneklenir\nsame_shape = vol_can.shape == msk_can.shape\nsame_affine = np.allclose(vol_can.affine, msk_can.affine, atol=1e-3)\n\nif not (same_shape and same_affine):\n    print(\">> UYARI: vol & mask grid/affine farklı. Maskeyi volume referansına yeniden örnekliyorum...\")\n    msk_res_path = os.path.join(WORKDIR, \"cow_resampled_to_vol.nii.gz\")\n    resample_to_ref(msk_can_path, vol_can_path, msk_res_path, is_label=True)\n    msk_can = nib.load(msk_res_path)\n    print(\"Yeni Mask:\", nii_info(msk_can))\nelse:\n    print(\"Vol & Mask grid/affine uyumlu görünüyor.\")\n\n# 3) Maske etiketlerini listele (0..13 beklenir)\nuniq = np.unique(msk_can.get_fdata()).astype(int)\nprint(\"Mask unique labels:\", uniq[:20], \"(toplam benzersiz:\", len(uniq), \")\")\n\n# 4) Tek bir DICOM dosyasından temel meta (seri/örnek eşlemesi için)\nds = pydicom.dcmread(ONE_DICOM, stop_before_pixels=True)\nprint(\"SeriesInstanceUID:\", str(ds.SeriesInstanceUID))\nprint(\"SOPInstanceUID   :\", str(ds.SOPInstanceUID))\n# Opsiyonel yararlı alanlar:\npixsp = getattr(ds, \"PixelSpacing\", None)\nslth  = getattr(ds, \"SliceThickness\", None)\nipp   = getattr(ds, \"ImagePositionPatient\", None)\nior   = getattr(ds, \"ImageOrientationPatient\", None)\nprint(\"PixelSpacing:\", pixsp, \"| SliceThickness:\", slth)\nprint(\"ImagePositionPatient:\", ipp)\nprint(\"ImageOrientationPatient:\", ior)\n\n# 5) CSV'ler erişilebilir mi?\nprint(\"train.csv satır sayısı  :\", sum(1 for _ in open(TRAIN_CSV)))\nprint(\"localizers.csv satır sayısı:\", sum(1 for _ in open(LOC_CSV)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T10:48:32.191958Z","iopub.execute_input":"2025-08-12T10:48:32.192932Z","iopub.status.idle":"2025-08-12T10:48:49.895595Z","shell.execute_reply.started":"2025-08-12T10:48:32.192892Z","shell.execute_reply":"2025-08-12T10:48:49.894456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, json, glob, numpy as np, nibabel as nib\nfrom tqdm import tqdm\n\n# === Giriş kökleri ===\nSEGS_ROOT = \"/kaggle/input/rsna-intracranial-aneurysm-detection/segmentations\"\n\n# === nnU-Net kökleri (Adım-1'de oluşturmadıysak) ===\nos.environ['nnUNet_raw'] = os.getenv('nnUNet_raw', '/kaggle/working/nnUNet_raw')\nos.environ['nnUNet_preprocessed'] = os.getenv('nnUNet_preprocessed', '/kaggle/working/nnUNet_preprocessed')\nos.environ['nnUNet_results'] = os.getenv('nnUNet_results', '/kaggle/working/nnUNet_results')\n\nDATASET_ID = 100\nNAME = f\"Dataset{DATASET_ID}_RSNAIA_CoW\"\nRAW_BASE = f\"{os.environ['nnUNet_raw']}/{NAME}\"\npaths = {k: os.path.join(RAW_BASE,k) for k in ['imagesTr','labelsTr']}\nfor p in paths.values(): os.makedirs(p, exist_ok=True)\n\n# CoW sınıf isimleri (0 arka plan)\nLABELS = {\n    \"0\":\"background\",\n    \"1\":\"Other Posterior Circulation\",\n    \"2\":\"Basilar Tip\",\n    \"3\":\"Right Posterior Communicating Artery\",\n    \"4\":\"Left Posterior Communicating Artery\",\n    \"5\":\"Right Infraclinoid Internal Carotid Artery\",\n    \"6\":\"Left Infraclinoid Internal Carotid Artery\",\n    \"7\":\"Right Supraclinoid Internal Carotid Artery\",\n    \"8\":\"Left Supraclinoid Internal Carotid Artery\",\n    \"9\":\"Right Middle Cerebral Artery\",\n    \"10\":\"Left Middle Cerebral Artery\",\n    \"11\":\"Right Anterior Cerebral Artery\",\n    \"12\":\"Left Anterior Cerebral Artery\",\n    \"13\":\"Anterior Communicating Artery\"\n}\n\ndef as_canonical_nii(path, dtype=None):\n    img = nib.load(path)\n    can = nib.as_closest_canonical(img)\n    arr = can.get_fdata()\n    if dtype is not None:\n        arr = arr.astype(dtype)\n    return nib.Nifti1Image(arr, can.affine)\n\npairs = []\nfor fol in sorted(glob.glob(os.path.join(SEGS_ROOT, \"*\"))):\n    vols = [v for v in glob.glob(os.path.join(fol, \"*.nii\")) if \"_cowseg\" not in v]\n    if not vols:\n        continue\n    vol = vols[0]\n    base = os.path.splitext(os.path.basename(vol))[0]\n    msk = os.path.join(fol, base + \"_cowseg.nii\")\n    if os.path.exists(msk):\n        pairs.append((base, vol, msk))\n\nprint(\"Bulunan hacim+maske çifti:\", len(pairs))\n\n# Kopyala & kanonikleştir & doğru dtype\nproblem_cases = []\nall_label_values = set()\nfor cid, v, m in tqdm(pairs):\n    try:\n        v_can = as_canonical_nii(v, np.float32)\n        m_can = as_canonical_nii(m)  # etiket değerlerini koruyacağız\n        # grid kontrolü: shape aynı değilse AFFINE/gridi korumak için etiketi yeniden kaydetmiyoruz;\n        # burada genelde aynı zaten. Fark varsa yine de shape'leri kontrol edelim:\n        if v_can.shape != m_can.shape:\n            problem_cases.append((cid, \"shape_mismatch\", v_can.shape, m_can.shape))\n            continue\n\n        # maske uint8'e çevir (0..13 korunur)\n        m_arr = m_can.get_fdata()\n        all_label_values.update(np.unique(m_arr).astype(int).tolist())\n\n        nib.save(nib.Nifti1Image(v_can.get_fdata().astype(np.float32), v_can.affine),\n                 os.path.join(paths['imagesTr'], f\"{cid}_0000.nii.gz\"))\n        nib.save(nib.Nifti1Image(m_arr.astype(np.uint8), m_can.affine),\n                 os.path.join(paths['labelsTr'], f\"{cid}.nii.gz\"))\n    except Exception as e:\n        problem_cases.append((cid, repr(e)))\n\nprint(\"Sorunlu vaka sayısı:\", len(problem_cases))\nif problem_cases[:5]: \n    print(\"Örnek sorunlar:\", problem_cases[:5])\n\nprint(\"Tüm veride görülen etiket değerleri (toplu):\", sorted(all_label_values))\n\n# dataset.json\ndataset_json = {\n  \"name\": NAME,\n  \"description\": \"Circle of Willis multi-class segmentation to drive aneurysm classification\",\n  \"reference\": \"RSNA Intracranial Aneurysm Detection\",\n  \"licence\": \"academic\",\n  \"release\": \"1.0\",\n  \"modality\": {\"0\": \"CT\"},  # veri MR içeriyorsa da sorun olmaz; bu alan bilgilendirici\n  \"labels\": LABELS,\n  \"numTraining\": len(os.listdir(paths['imagesTr'])),\n  \"numTest\": 0,\n  \"training\": [\n      {\n        \"image\": f\"./imagesTr/{fn}\",\n        \"label\": f\"./labelsTr/{fn.replace('_0000.nii.gz','.nii.gz')}\"\n      }\n      for fn in sorted(os.listdir(paths['imagesTr'])) if fn.endswith(\"_0000.nii.gz\")\n  ],\n  \"test\": []\n}\nwith open(os.path.join(RAW_BASE, \"dataset.json\"), \"w\") as f:\n    json.dump(dataset_json, f, indent=2)\n\nprint(\"nnU-Net ham veri hazır:\", RAW_BASE)\nprint(\"imagesTr:\", len(os.listdir(paths['imagesTr'])), \"labelsTr:\", len(os.listdir(paths['labelsTr'])))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T10:50:40.998436Z","iopub.execute_input":"2025-08-12T10:50:40.999629Z","iopub.status.idle":"2025-08-12T11:31:10.819566Z","shell.execute_reply.started":"2025-08-12T10:50:40.999593Z","shell.execute_reply":"2025-08-12T11:31:10.816087Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json, os\n\nRAW_BASE = \"/kaggle/working/nnUNet_raw/Dataset100_RSNAIA_CoW\"\njpath = os.path.join(RAW_BASE, \"dataset.json\")\n\nwith open(jpath) as f:\n    d = json.load(f)\n\nold = d[\"labels\"]                      # şu an {\"0\":\"background\",\"1\":\"...\"} biçiminde\n# yeni biçim: {\"background\":0, \"Other Posterior Circulation\":1, ...}\nnew_labels = {}\nfor k, v in old.items():\n    try:\n        i = int(k)                     # \"0\",\"1\",...\n        new_labels[v] = i              # \"background\":0, \"Basilar Tip\":2, ...\n    except:\n        pass\n\n# zorunlu anahtarlar\nd[\"labels\"] = new_labels\nd.setdefault(\"channel_names\", {\"0\": \"CT\"})\nd.setdefault(\"file_ending\", \".nii.gz\")\n\nwith open(jpath, \"w\") as f:\n    json.dump(d, f, indent=2)\n\nprint(\"labels patched ->\", d[\"labels\"])\nprint(\"channel_names:\", d[\"channel_names\"], \"| file_ending:\", d[\"file_ending\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T12:13:15.445296Z","iopub.execute_input":"2025-08-12T12:13:15.445694Z","iopub.status.idle":"2025-08-12T12:13:15.48555Z","shell.execute_reply.started":"2025-08-12T12:13:15.445662Z","shell.execute_reply":"2025-08-12T12:13:15.484145Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, json\nRAW_BASE = \"/kaggle/working/nnUNet_raw/Dataset100_RSNAIA_CoW\"\njpath = os.path.join(RAW_BASE, \"dataset.json\")\n\nwith open(jpath) as f:\n    d = json.load(f)\n\n# Zorunlu alanları ekle\nd[\"channel_names\"] = {\"0\": \"CT/MRA\"}       \nd[\"file_ending\"] = \".nii.gz\"              # dosya uzantımız\n\n\nwith open(jpath, \"w\") as f:\n    json.dump(d, f, indent=2)\n\nprint(\"Patched keys:\", [k for k in [\"labels\",\"channel_names\",\"numTraining\",\"file_ending\"] if k in d])\nprint(\"channel_names =\", d[\"channel_names\"], \"| file_ending =\", d[\"file_ending\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T12:11:26.440275Z","iopub.execute_input":"2025-08-12T12:11:26.441503Z","iopub.status.idle":"2025-08-12T12:11:26.455748Z","shell.execute_reply.started":"2025-08-12T12:11:26.441456Z","shell.execute_reply":"2025-08-12T12:11:26.454354Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!nnUNetv2_plan_and_preprocess -d 100 --verify_dataset_integrity -c 3d_fullres","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T12:13:19.737804Z","iopub.execute_input":"2025-08-12T12:13:19.738284Z","iopub.status.idle":"2025-08-12T12:39:06.259859Z","shell.execute_reply.started":"2025-08-12T12:13:19.738235Z","shell.execute_reply":"2025-08-12T12:39:06.258452Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%env ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=1\n%env OMP_NUM_THREADS=1\n%env OPENBLAS_NUM_THREADS=1\n%env MKL_NUM_THREADS=1\n%env NUMEXPR_NUM_THREADS=1\n\n!nnUNetv2_plan_and_preprocess -d 100 --verify_dataset_integrity -c 3d_fullres -np 2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T12:52:33.177509Z","iopub.execute_input":"2025-08-12T12:52:33.177961Z","iopub.status.idle":"2025-08-12T13:56:51.890796Z","shell.execute_reply.started":"2025-08-12T12:52:33.177919Z","shell.execute_reply":"2025-08-12T13:56:51.888997Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Preprocessed klasöründe kaç tane .npz var?\n!ls /kaggle/working/nnUNet_preprocessed/Dataset100_RSNAIA_CoW | grep \".npz\" | wc -l\n\n# Raw dataset klasöründe kaç tane case var? (imagesTr)\n!ls /kaggle/working/nnUNet_raw/Dataset100_RSNAIA_CoW/imagesTr | wc -l","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T14:07:22.927659Z","iopub.execute_input":"2025-08-12T14:07:22.927995Z","iopub.status.idle":"2025-08-12T14:07:23.242246Z","shell.execute_reply.started":"2025-08-12T14:07:22.927974Z","shell.execute_reply":"2025-08-12T14:07:23.240718Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!find /kaggle/working/nnUNet_preprocessed/Dataset100_RSNAIA_CoW/nnUNetPlans_3d_fullres -type f -name \"*.npz\" | wc -l","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:15:25.950452Z","iopub.status.idle":"2025-08-12T17:15:25.950898Z","shell.execute_reply.started":"2025-08-12T17:15:25.950678Z","shell.execute_reply":"2025-08-12T17:15:25.950699Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%bash\nset -e\n\n# 1) Doğru symlink: /kaggle/working/nnUNet_raw -> /tmp/nnUNet_raw/nnUNet_raw\nrm -f /kaggle/working/nnUNet_raw\nln -s /tmp/nnUNet_raw/nnUNet_raw /kaggle/working/nnUNet_raw\n\n# 2) dataset.json gerçekten var mı? (yoksa dur)\ntest -f /kaggle/working/nnUNet_raw/Dataset100_RSNAIA_CoW/dataset.json \\\n  || { echo \"ERROR: dataset.json bulunamadı. Symlink hedefini kontrol et.\"; ls -l /kaggle/working/nnUNet_raw; exit 1; }\n\n# 3) Yer aç: 2D ve 3D lowres preprocessed klasörleri (lazım değilse)\nrm -rf /kaggle/working/nnUNet_preprocessed/Dataset100_RSNAIA_CoW/nnUNetPlans_2d || true\nrm -rf /kaggle/working/nnUNet_preprocessed/Dataset100_RSNAIA_CoW/nnUNetPlans_3d_lowres || true\nrm -rf /kaggle/working/check_case || true\n\n# 4) RAM dostu thread sınırları (bu hücre için geçerli)\nexport ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=2\nexport OMP_NUM_THREADS=2\nexport OPENBLAS_NUM_THREADS=2\nexport MKL_NUM_THREADS=2\nexport NUMEXPR_NUM_THREADS=2\n\n# 5) Kaldığı yerden 3D fullres preprocess (2 worker)\nnnUNetv2_plan_and_preprocess -d 100 --verify_dataset_integrity -c 3d_fullres -np 2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T14:37:20.899173Z","iopub.execute_input":"2025-08-12T14:37:20.899694Z","iopub.status.idle":"2025-08-12T17:15:25.912908Z","shell.execute_reply.started":"2025-08-12T14:37:20.89966Z","shell.execute_reply":"2025-08-12T17:15:25.908199Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%bash\nset -e\n\n# 0) Durum bilgisi (isteğe bağlı)\necho \"Before:\"; df -h /kaggle/working | tail -n1\n\n# 1) nnUNet_preprocessed'i /tmp'ye taşı ve geri symlink koy\nif [ -d /kaggle/working/nnUNet_preprocessed ]; then\n  mv /kaggle/working/nnUNet_preprocessed /tmp/nnUNet_preprocessed\n  ln -s /tmp/nnUNet_preprocessed /kaggle/working/nnUNet_preprocessed\nfi\n\n# 2) (Hatırlatma) raw zaten /tmp'de; symlink doğru mu?\nls -ld /kaggle/working/nnUNet_raw || true\n\n# 3) nnU-Net ortam değişkenleri: sonuçlar da /tmp'ye gitsin\nexport nnUNet_raw=/kaggle/working/nnUNet_raw\nexport nnUNet_preprocessed=/tmp/nnUNet_preprocessed\nexport nnUNet_results=/tmp/nnUNet_results\nmkdir -p \"$nnUNet_results\"\n\n# 4) RAM dostu thread sınırları\nexport ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS=2\nexport OMP_NUM_THREADS=2\nexport OPENBLAS_NUM_THREADS=2\nexport MKL_NUM_THREADS=2\nexport NUMEXPR_NUM_THREADS=2\n\necho \"After move:\"; df -h /kaggle/working | tail -n1\necho \"Ready to train. Results will go to: $nnUNet_results\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:36:03.430506Z","iopub.execute_input":"2025-08-12T17:36:03.431078Z","iopub.status.idle":"2025-08-12T17:38:23.489688Z","shell.execute_reply.started":"2025-08-12T17:36:03.431046Z","shell.execute_reply":"2025-08-12T17:38:23.488369Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Ortam değişkenleri (sen zaten ayarladın ama tam olsun)\n%env nnUNet_raw=/kaggle/working/nnUNet_raw\n%env nnUNet_preprocessed=/tmp/nnUNet_preprocessed\n%env nnUNet_results=/kaggle/working/nnUNet_results\n\n# SIRALAMA: [DATASET_ID] [CONFIG] [FOLD]\n!nnUNetv2_train 100 3d_fullres 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:44:12.285858Z","iopub.execute_input":"2025-08-12T17:44:12.286568Z","iopub.status.idle":"2025-08-12T17:44:22.657628Z","shell.execute_reply.started":"2025-08-12T17:44:12.286511Z","shell.execute_reply":"2025-08-12T17:44:22.656368Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%bash\nset -e\n\necho \"Before:\"; df -h /kaggle/working | tail -n1\n\n# 1) Çalışmada eski symlink/dizin varsa temizle\nif [ -L /kaggle/working/nnUNet_preprocessed ]; then\n  rm -f /kaggle/working/nnUNet_preprocessed\nelif [ -d /kaggle/working/nnUNet_preprocessed ]; then\n  echo \"Uyarı: /kaggle/working/nnUNet_preprocessed zaten var, yedekliyorum.\"\n  mv /kaggle/working/nnUNet_preprocessed /kaggle/working/nnUNet_preprocessed_backup_$(date +%H%M%S)\nfi\n\n# 2) /tmp'den working'e taşı\nif [ -d /tmp/nnUNet_preprocessed ]; then\n  mv /tmp/nnUNet_preprocessed /kaggle/working/nnUNet_preprocessed\nelse\n  echo \"HATA: /tmp/nnUNet_preprocessed bulunamadı!\"; exit 1\nfi\n\n# 3) Hızlı doğrulamalar\necho \"Preprocessed boyutu:\"\ndu -sh /kaggle/working/nnUNet_preprocessed\n\necho \"3d_fullres dosya sayısı (.b2nd):\"\nfind /kaggle/working/nnUNet_preprocessed/Dataset100_RSNAIA_CoW/nnUNetPlans_3d_fullres -type f -name \"*.b2nd\" | wc -l\n\n# 4) Sonuç klasörünü hazırla (çıkışlar burada kalsın)\nmkdir -p /kaggle/working/nnUNet_results\n\necho \"After:\"; df -h /kaggle/working | tail -n1\necho \"TAŞIMA TAMAM. Artık kernel reset/GPU açsan da preprocessed silinmez.\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:49:37.073646Z","iopub.execute_input":"2025-08-12T17:49:37.074241Z","iopub.status.idle":"2025-08-12T17:51:42.278157Z","shell.execute_reply.started":"2025-08-12T17:49:37.074197Z","shell.execute_reply":"2025-08-12T17:51:42.276793Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, torch\nos.environ[\"nnUNet_preprocessed\"] = \"/kaggle/working/nnUNet_preprocessed\"   # preprocessed bizde kalıcı\nos.environ[\"nnUNet_results\"] = \"/kaggle/working/nnUNet_results\"             # Output panelinde görünsün\nos.makedirs(os.environ[\"nnUNet_results\"], exist_ok=True)\n\nprint(\"CUDA available:\", torch.cuda.is_available())  # True olmalı","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T18:15:48.514999Z","iopub.execute_input":"2025-08-12T18:15:48.515296Z","iopub.status.idle":"2025-08-12T18:15:54.838162Z","shell.execute_reply.started":"2025-08-12T18:15:48.515275Z","shell.execute_reply":"2025-08-12T18:15:54.837489Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pathlib, re\n\np = pathlib.Path(\"/usr/local/lib/python3.11/dist-packages/nnunetv2/run/run_training.py\")\ntxt = p.read_text()\n# Satırı string'e çevir: = 1  --> = \"1\"\nfixed = re.sub(r\"os\\.environ\\[\\s*['\\\"]TORCHINDUCTOR_COMPILE_THREADS['\\\"]\\s*\\]\\s*=\\s*1\",\n               \"os.environ['TORCHINDUCTOR_COMPILE_THREADS'] = \\\"1\\\"\", txt)\nif fixed != txt:\n    p.write_text(fixed)\n    print(\"Patched run_training.py (TORCHINDUCTOR_COMPILE_THREADS now string).\")\nelse:\n    print(\"Patch not needed (already string or different version).\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T18:54:24.267603Z","iopub.execute_input":"2025-08-12T18:54:24.268248Z","iopub.status.idle":"2025-08-12T18:54:24.274562Z","shell.execute_reply.started":"2025-08-12T18:54:24.268216Z","shell.execute_reply":"2025-08-12T18:54:24.273922Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!mkdir -p /kaggle/working/nnUNet_results /kaggle/working/nnUNet_raw\n!ls -lah /kaggle/working","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T20:36:46.236318Z","iopub.execute_input":"2025-08-12T20:36:46.236616Z","iopub.status.idle":"2025-08-12T20:36:46.471764Z","shell.execute_reply.started":"2025-08-12T20:36:46.23659Z","shell.execute_reply":"2025-08-12T20:36:46.470952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, sys, subprocess, shutil, inspect, re, time\nfrom pathlib import Path\n\n# ---------- 0) Hızlı teşhis ----------\nprint(\"== Teşhis ==\")\ntry:\n    import torch\n    print(\"torch:\", torch.__version__, \"| cuda_available:\", torch.cuda.is_available())\n    if torch.cuda.is_available():\n        print(\"gpu:\", torch.cuda.get_device_name(0))\nexcept Exception as e:\n    print(\"torch import error:\", e)\n\ntry:\n    import nnunetv2\n    print(\"nnunetv2:\", nnunetv2.__version__ if hasattr(nnunetv2, \"__version__\") else \"ok\")\n    rt_path = Path(inspect.getfile(nnunetv2)).parent / \"run\" / \"run_training.py\"\n    print(\"run_training.py:\", rt_path)\nexcept Exception as e:\n    print(\"nnunetv2 import error:\", e)\n\n# ---------- 1) Patch (idempotent) ----------\ntry:\n    txt = rt_path.read_text()\n    fixed = re.sub(\n        r\"os\\.environ\\[\\s*['\\\"]TORCHINDUCTOR_COMPILE_THREADS['\\\"]\\s*\\]\\s*=\\s*1\",\n        \"os.environ['TORCHINDUCTOR_COMPILE_THREADS'] = \\\"1\\\"\",\n        txt\n    )\n    if fixed != txt:\n        rt_path.write_text(fixed)\n        print(\"[PATCH] TORCHINDUCTOR_COMPILE_THREADS -> '1' (string) uygulandı\")\n    else:\n        print(\"[PATCH] zaten doğru\")\nexcept Exception as e:\n    print(\"[PATCH] hata:\", e)\n\n# ---------- 2) Yol ve dosyalar ----------\nRAW = \"/kaggle/working/nnUNet_raw\"  # symlink olabilir\nPRE = \"/kaggle/working/nnUNet_preprocessed\"\nRES = \"/kaggle/working/nnUNet_results\"\n\nprint(\"\\n== Yol kontrol ==\")\nprint(\"PRE exists:\", Path(PRE).exists())\nprint(\"RES exists:\", Path(RES).exists())\n\nsplit_file = Path(PRE) / \"Dataset100_RSNAIA_CoW\" / \"splits_final.json\"\nprint(\"splits_final.json:\", split_file, \"->\", split_file.exists())\n\nfold_dir = Path(RES) / \"Dataset100_RSNAIA_CoW\" / \"nnUNetTrainer__nnUNetPlans__3d_fullres\" / \"fold_0\"\nfold_dir.mkdir(parents=True, exist_ok=True)\nbest = fold_dir/\"checkpoint_best.pth\"\nlatest = fold_dir/\"checkpoint_latest.pth\"\n\nif (not latest.exists()) and best.exists():\n    shutil.copy2(best, latest)\n    print(\"[RESUME] checkpoint_latest.pth oluşturuldu (best'ten).\")\n\nprint(\"latest.exists:\", latest.exists(), \"| best.exists:\", best.exists())\n\n# ---------- 3) Env ----------\nos.environ.update({\n    \"nnUNet_raw\": RAW,\n    \"nnUNet_preprocessed\": PRE,\n    \"nnUNet_results\": RES,\n    \"CUDA_VISIBLE_DEVICES\": \"0\",   # tek GPU\n    \"PYTHONUNBUFFERED\": \"1\",\n    \"TORCH_COMPILE_DISABLE\": \"1\",  # compile kapalı (daha stabil)\n    \"nnUNet_compile\": \"0\",\n    \"ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS\": \"2\",\n    \"OMP_NUM_THREADS\": \"2\",\n    \"OPENBLAS_NUM_THREADS\": \"2\",\n    \"MKL_NUM_THREADS\": \"2\",\n    \"NUMEXPR_NUM_THREADS\": \"2\",\n})\n\n# ---------- 4) Hızlı ön-test: help/versiyon, hata yakalamak için ----------\nprint(\"\\n== Hızlı ön-test ==\")\ntest_cmd = [\"python\",\"-c\",\"import torch,nnunetv2;print('cuda',torch.cuda.is_available())\"]\nret = subprocess.run(test_cmd, capture_output=True, text=True)\nprint(\"Pretest rc:\", ret.returncode, \"| out:\", ret.stdout.strip(), \"| err:\", ret.stderr.strip())\n\n# Eğer burada hata varsa, nnunetv2/torch ortamı sorunsuz çalışmıyor demektir.\n# ---------- 5) Eğitim (filtreli, yalnızca önemli satırlar) ----------\ncmd = [\"python\",\"-u\",\"-m\",\"nnunetv2.run.run_training\",\"100\",\"3d_fullres\",\"0\",\"--c\"]\nprint(\"\\n[RUN]\", \" \".join(cmd), \"\\n\", flush=True)\n\nwant_prefixes = (\n    \"Using device:\",\n    \"Epoch \",\n    \"Current learning rate:\",\n    \"train_loss\", \"val_loss\",\n    \"Pseudo dice [\",\n    \"Yayy! New best EMA\",\n)\n\nlast_epoch = None\np = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)\ntry:\n    for ln in p.stdout:\n        s = ln.strip()\n        if s.startswith(\"Using device:\"):\n            print(s); continue\n        if s.startswith(want_prefixes):\n            if s.startswith(\"Epoch \"):\n                try:\n                    ep = int(s.split()[1])\n                except: ep = None\n                if ep is None or ep != last_epoch:\n                    last_epoch = ep\n                    print(s)\n            else:\n                print(s)\n    rc = p.wait()\n    print(f\"\\n[EXIT] return code: {rc}\")\nexcept KeyboardInterrupt:\n    print(\"\\n[STOP] kullanıcı durdurdu.\")\n    try: p.terminate()\n    except: pass","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-13T08:48:32.207338Z","iopub.execute_input":"2025-08-13T08:48:32.207867Z","execution_failed":"2025-08-13T20:43:04.283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!mkdir -p /kaggle/working/tmp_nifti\n\n# DICOM -> NIfTI çevir\n!dcm2niix -z y -o /kaggle/working/tmp_nifti /kaggle/input/rsna-intracranial-aneurysm-detection/series/1.2.826.0.1.3680043.8.498.10004044428023505108375152878107656647","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-13T22:56:07.032601Z","iopub.execute_input":"2025-08-13T22:56:07.033366Z","iopub.status.idle":"2025-08-13T22:56:12.707991Z","shell.execute_reply.started":"2025-08-13T22:56:07.033333Z","shell.execute_reply":"2025-08-13T22:56:12.70702Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, shutil, time, subprocess, glob, pathlib\n\n# --- Yollar ---\nSERIES_DIR = \"/kaggle/input/rsna-intracranial-aneurysm-detection/series/1.2.826.0.1.3680043.8.498.10004044428023505108375152878107656647\"\nNIFTI_DIR  = \"/kaggle/working/tmp_nifti\"\nOUT_DIR    = \"/kaggle/working/nnunet_predictions\"\n\n# nnU-Net ortam değişkenleri (emin olmak için tekrar ayarlıyoruz)\nos.environ[\"nnUNet_raw\"]          = \"/kaggle/working/nnUNet_raw\"\nos.environ[\"nnUNet_preprocessed\"] = \"/kaggle/working/nnUNet_preprocessed\"\nos.environ[\"nnUNet_results\"]      = \"/kaggle/working/nnUNet_results\"\n\n# Klasörleri hazırla\nos.makedirs(NIFTI_DIR, exist_ok=True)\nos.makedirs(OUT_DIR, exist_ok=True)\n\nprint(\"== DICOM -> NIfTI ==\")\n# DICOM -> NIfTI (sıkıştırılmış .nii.gz)\nsubprocess.run(\n    [\"dcm2niix\", \"-z\", \"y\", \"-o\", NIFTI_DIR, SERIES_DIR],\n    check=True\n)\n\n# Klasördeki NIfTI'leri bul\nniis = sorted(glob.glob(os.path.join(NIFTI_DIR, \"*.nii*\")), key=os.path.getmtime)\nif not niis:\n    raise RuntimeError(\"NIfTI bulunamadı. dcm2niix çıktısını kontrol et.\")\n# En son oluşturulanı seç, diğerlerini temizle (karışıklık olmasın)\nlatest = niis[-1]\nfor f in niis[:-1]:\n    try:\n        os.remove(f)\n    except:\n        pass\n\n# Tek NIfTI kaldığından emin ol\nniis = glob.glob(os.path.join(NIFTI_DIR, \"*.nii*\"))\nassert len(niis) == 1, f\"Birden fazla NIfTI var: {niis}\"\nnii_path = niis[0]\n\n# İsim sonunu _0000.nii.gz yap (tek kanal beklentisi)\nbase = os.path.basename(nii_path)\nif not (base.endswith(\"_0000.nii\") or base.endswith(\"_0000.nii.gz\")):\n    # .nii.gz mi .nii mi?\n    if base.endswith(\".nii.gz\"):\n        new_base = base[:-7] + \"_0000.nii.gz\"\n    elif base.endswith(\".nii\"):\n        new_base = base[:-4] + \"_0000.nii\"\n    else:\n        # olağan dışı uzantı\n        stem = pathlib.Path(base).stem\n        new_base = stem + \"_0000.nii.gz\"\n    new_path = os.path.join(NIFTI_DIR, new_base)\n    os.rename(nii_path, new_path)\n    nii_path = new_path\n\nprint(f\"Kullanılacak NIfTI: {nii_path}\")\n\n# Yan ürün JSON’ları (sidecar) varsa kalsın; nnUNet bunlara dokunmaz.\n# Inference\nprint(\"\\n== nnUNetv2_predict ==\")\ncmd = [\n    \"nnUNetv2_predict\",\n    \"-i\", NIFTI_DIR,\n    \"-o\", OUT_DIR,\n    \"-d\", \"100\",             # Dataset100_RSNAIA_CoW\n    \"-c\", \"3d_fullres\",\n    \"-f\", \"0\",\n    \"-tr\", \"nnUNetTrainer\",\n    \"-chk\", \"checkpoint_best.pth\",   # .pth yazma, sadece adı ver\n    \"--verbose\"\n]\n\nt0 = time.time()\n# Canlı çıktı için:\nwith subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1) as p:\n    for line in p.stdout:\n        print(line, end=\"\")\n    rc = p.wait()\nt1 = time.time()\n\nprint(f\"\\n✅ İnferans tamamlandı. Geçen süre: {t1 - t0:.2f} s, çıkış kodu: {rc}\")\n\n# Çıktıları listele\nprint(\"\\n== Çıktı dosyaları ==\")\nfor p in sorted(glob.glob(os.path.join(OUT_DIR, \"*\"))):\n    print(\" -\", os.path.basename(p))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-13T23:01:23.998653Z","iopub.execute_input":"2025-08-13T23:01:23.99896Z","iopub.status.idle":"2025-08-13T23:03:52.364053Z","shell.execute_reply.started":"2025-08-13T23:01:23.998941Z","shell.execute_reply":"2025-08-13T23:03:52.363105Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import nibabel as nib, numpy as np, os\np = \"/kaggle/working/nnunet_predictions/1.2.826.0.1.3680043.8.498.10004044428023505108375152878107656647_AX_COW_20230531221060_1.nii.gz\"\nlab = nib.load(p).get_fdata().astype(np.int16)\nvals, cnt = np.unique(lab, return_counts=True)\nprint(dict(zip(vals.tolist(), cnt.tolist())))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-13T23:04:57.601821Z","iopub.execute_input":"2025-08-13T23:04:57.602378Z","iopub.status.idle":"2025-08-13T23:04:59.483316Z","shell.execute_reply.started":"2025-08-13T23:04:57.602353Z","shell.execute_reply":"2025-08-13T23:04:59.48249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === 0) Kurulum & import\nimport os, glob, json, math\nfrom pathlib import Path\nimport numpy as np\nimport nibabel as nib\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nplt.rcParams[\"figure.dpi\"] = 120\n\n# === 1) Yollar\nNIFTI_DIR = \"/kaggle/working/tmp_nifti\"\nPRED_DIR  = \"/kaggle/working/nnunet_predictions\"\nOUT_VIS   = \"/kaggle/working/vis\"\nOUT_CROP  = \"/kaggle/working/crops\"\nOUT_CSV   = \"/kaggle/working/features.csv\"\n\nPath(OUT_VIS).mkdir(parents=True, exist_ok=True)\nPath(OUT_CROP).mkdir(parents=True, exist_ok=True)\n\n# === 2) Dosyaları bul\nnifti_files = sorted(glob.glob(f\"{NIFTI_DIR}/*.nii.gz\"))\npred_files  = sorted([p for p in glob.glob(f\"{PRED_DIR}/*.nii.gz\")\n                      if not Path(p).name.startswith((\"dataset\",\"plans\",\"predict_from_raw\"))])\n\nassert len(nifti_files)>=1, f\"NIfTI bulunamadı: {NIFTI_DIR}\"\nassert len(pred_files)>=1,  f\"Tahmin NIfTI bulunamadı: {PRED_DIR}\"\n\nnii_path  = nifti_files[0]\npred_path = pred_files[0]\nprint(\"Görüntü:\", Path(nii_path).name)\nprint(\"Tahmin :\", Path(pred_path).name)\n\n# === 3) Oku\nimg_nii  = nib.load(nii_path)\nimg      = img_nii.get_fdata().astype(np.float32)\naff      = img_nii.affine\nvox_mm   = np.abs(np.linalg.det(aff[:3,:3]))  # voxel hacmi (mm^3)\n\npred_nii = nib.load(pred_path)\npred     = pred_nii.get_fdata().astype(np.int16)\n\n# Şekiller uyuşmuyorsa (nadiren olur) yeniden örnekleme yapmayalım; uyarı verelim\nif img.shape != pred.shape:\n    print(\"UYARI: img ve pred şekilleri farklı:\", img.shape, pred.shape)\n\n# === 4) Sınıf sözlüğü (1..13)\nid2name = {\n    1: \"Other Posterior Circulation\",\n    2: \"Basilar Tip\",\n    3: \"Right PCom\",\n    4: \"Left PCom\",\n    5: \"Right Infraclinoid ICA\",\n    6: \"Left Infraclinoid ICA\",\n    7: \"Right Supraclinoid ICA\",\n    8: \"Left Supraclinoid ICA\",\n    9: \"Right MCA\",\n    10: \"Left MCA\",\n    11: \"Right ACA\",\n    12: \"Left ACA\",\n    13: \"ACom\",\n}\nlabels = sorted(id2name.keys())\n\n# === 5) Basit normalizasyon (görselleştirme için)\np = np.percentile(img, (1, 99))\nimg_viz = np.clip((img - p[0]) / (p[1]-p[0] + 1e-6), 0, 1)\n\n# === 6) MIP + overlay (3 eksen)\ndef save_mip_overlay(img01, lab, axis, out_png):\n    # img01: [0,1] normalize\n    mip_img = np.max(img01, axis=axis)\n    mip_lab = np.max(lab,    axis=axis)  # sınıf idlerinin MIP'i (en büyük id)\n    # Renk haritası: 0 şeffaf, >0 sabit renk (hızlıca)\n    overlay = np.zeros((*mip_img.shape, 3), dtype=np.float32)\n    overlay[...,0] = (mip_lab>0).astype(np.float32)  # kırmızı ton\n    alpha = 0.35*(mip_lab>0)\n    rgb = np.stack([mip_img]*3, axis=-1)\n    out = (1-alpha[...,None])*rgb + alpha[...,None]*overlay\n\n    plt.figure(figsize=(6,6))\n    plt.imshow(out, cmap=None)\n    plt.axis('off')\n    plt.title(f\"MIP axis={axis}\")\n    plt.tight_layout()\n    plt.savefig(out_png, bbox_inches='tight', pad_inches=0)\n    plt.close()\n\nsave_mip_overlay(img_viz, pred, axis=0, out_png=f\"{OUT_VIS}/mip_ax0.png\")\nsave_mip_overlay(img_viz, pred, axis=1, out_png=f\"{OUT_VIS}/mip_ax1.png\")\nsave_mip_overlay(img_viz, pred, axis=2, out_png=f\"{OUT_VIS}/mip_ax2.png\")\nprint(\"MIP görseller kaydedildi:\", OUT_VIS)\n\n# === 7) Sınıf bazlı istatistik + crop çıkarma\nrows = []\nfor cls in labels:\n    mask = (pred==cls)\n    vox = int(mask.sum())\n    if vox==0:\n        rows.append({\n            \"label_id\": cls,\n            \"label_name\": id2name[cls],\n            \"voxels\": 0, \"mm3\": 0.0,\n            \"bbox_zyx\": None,\n            \"centroid_zyx\": None,\n            \"crop_path\": None\n        })\n        continue\n\n    # bbox\n    zyx = np.array(np.where(mask)).T\n    zmin, ymin, xmin = zyx.min(axis=0)\n    zmax, ymax, xmax = zyx.max(axis=0)\n\n    # küçük bir margin ile crop\n    m = 4\n    z0, z1 = max(0, zmin-m), min(mask.shape[0], zmax+m+1)\n    y0, y1 = max(0, ymin-m), min(mask.shape[1], ymax+m+1)\n    x0, x1 = max(0, xmin-m), min(mask.shape[2], xmax+m+1)\n\n    crop_img  = img[z0:z1, y0:y1, x0:x1]\n    crop_mask = mask[z0:z1, y0:y1, x0:x1].astype(np.uint8)\n\n    # crop NIfTI kaydet (img ve maskeyi ayrı)\n    base = f\"class{cls:02d}_{id2name[cls].replace(' ','_')}\"\n    img_nii_out  = os.path.join(OUT_CROP, base+\"_img.nii.gz\")\n    mask_nii_out = os.path.join(OUT_CROP, base+\"_mask.nii.gz\")\n    nib.save(nib.Nifti1Image(crop_img, aff),  img_nii_out)\n    nib.save(nib.Nifti1Image(crop_mask, aff), mask_nii_out)\n\n    # merkez (yoğunluk ağırlıksız)\n    cz, cy, cx = zyx.mean(axis=0)\n\n    rows.append({\n        \"label_id\": cls,\n        \"label_name\": id2name[cls],\n        \"voxels\": int(vox),\n        \"mm3\": float(vox * vox_mm),\n        \"bbox_zyx\": [int(z0), int(z1), int(y0), int(y1), int(x0), int(x1)],\n        \"centroid_zyx\": [float(cz), float(cy), float(cx)],\n        \"crop_path\": [img_nii_out, mask_nii_out],\n    })\n\ndf = pd.DataFrame(rows)\ndf = df.sort_values(\"label_id\")\ndf.to_csv(OUT_CSV, index=False)\nprint(\"Özellik tablosu:\", OUT_CSV)\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T11:20:55.757186Z","iopub.execute_input":"2025-08-14T11:20:55.757598Z","iopub.status.idle":"2025-08-14T11:21:16.853248Z","shell.execute_reply.started":"2025-08-14T11:20:55.757562Z","shell.execute_reply":"2025-08-14T11:21:16.852378Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- Yollar ---\nIMG_PATH = \"/kaggle/working/tmp_nifti/1.2.826.0.1.3680043.8.498.10004044428023505108375152878107656647_AX_COW_20230531221060_1_0000.nii.gz\"\n\nimport os, os.path as op, numpy as np, nibabel as nib, matplotlib.pyplot as plt\nfrom matplotlib.colors import ListedColormap\n\n# SEG yolunu IMG dosya adına göre türet ( _0000.nii.gz -> .nii.gz )\ncase_id = op.basename(IMG_PATH).replace(\"_0000.nii.gz\", \"\")\nSEG_PATH = f\"/kaggle/working/nnunet_predictions/{case_id}.nii.gz\"\n\nprint(\"IMG_PATH:\", IMG_PATH)\nprint(\"SEG_PATH:\", SEG_PATH)\nassert op.exists(IMG_PATH), \"IMG dosyası bulunamadı!\"\nassert op.exists(SEG_PATH), \"SEG dosyası bulunamadı!\"\n\n# --- Yükle ---\nimg = nib.load(IMG_PATH);  img_data = img.get_fdata().astype(np.float32)\nseg = nib.load(SEG_PATH);  seg_data = seg.get_fdata().astype(np.int16)\n\n# Görüntüyü (sadece görselleştirme için) 1–99 persentil aralığında normalize et\np1, p99 = np.percentile(img_data, [1, 99])\nimg_disp = np.clip((img_data - p1) / max(p99 - p1, 1e-5), 0, 1)\n\n# --- Renkler: 0 arka plan, 1..13 damar sınıfları ---\n# (tab20’den seçilmiş 13 renk)\ntab = plt.get_cmap(\"tab20\").colors\nlut = np.zeros((14, 4))   # RGBA\nlut[1:14, :3] = np.array(tab[:13])\nlut[:, 3] = [0.0] + [1.0]*13       # alfa = 1, overlay'de ayrıca şeffaflık vereceğiz\ncmap = ListedColormap(lut)\n\n# Orta dilimler\nz, y, x = img_disp.shape\nslices = (z//2, y//2, x//2)\n\ndef show_overlay(img3d, seg3d, slices, alpha=0.35, figsize=(15,5)):\n    fig, ax = plt.subplots(1, 3, figsize=figsize)\n    # axial (z)\n    ax[0].imshow(img3d[slices[0], :, :], cmap=\"gray\")\n    ax[0].imshow(seg3d[slices[0], :, :], cmap=cmap, alpha=alpha, interpolation=\"nearest\")\n    ax[0].set_title(f\"Axial z={slices[0]}\")\n    ax[0].axis(\"off\")\n    # coronal (y)\n    ax[1].imshow(img3d[:, slices[1], :].T, cmap=\"gray\", origin=\"lower\")\n    ax[1].imshow(seg3d[:, slices[1], :].T, cmap=cmap, alpha=alpha, origin=\"lower\", interpolation=\"nearest\")\n    ax[1].set_title(f\"Coronal y={slices[1]}\")\n    ax[1].axis(\"off\")\n    # sagittal (x)\n    ax[2].imshow(img3d[:, :, slices[2]].T, cmap=\"gray\", origin=\"lower\")\n    ax[2].imshow(seg3d[:, :, slices[2]].T, cmap=cmap, alpha=alpha, origin=\"lower\", interpolation=\"nearest\")\n    ax[2].set_title(f\"Sagittal x={slices[2]}\")\n    ax[2].axis(\"off\")\n    fig.tight_layout()\n    return fig\n\nfig = show_overlay(img_disp, seg_data, slices, alpha=0.35)\nos.makedirs(\"/kaggle/working/vis\", exist_ok=True)\nout_png = \"/kaggle/working/vis/overlay_preview.png\"\nfig.savefig(out_png, dpi=150)\nplt.show()\nprint(\"Kaydedildi:\", out_png)\n\n# --- Sınıf başına voxel sayısı ---\nlabels = {\n    1: \"Other Posterior Circulation\",\n    2: \"Basilar Tip\",\n    3: \"Right PCom\",\n    4: \"Left PCom\",\n    5: \"Right Infraclinoid ICA\",\n    6: \"Left Infraclinoid ICA\",\n    7: \"Right Supraclinoid ICA\",\n    8: \"Left Supraclinoid ICA\",\n    9: \"Right MCA\",\n    10: \"Left MCA\",\n    11: \"Right ACA\",\n    12: \"Left ACA\",\n    13: \"ACom\",\n}\ncounts = {k: int((seg_data == k).sum()) for k in range(0, 14)}\nprint(\"\\nVoxeller:\")\nprint(f\"  0: background -> {counts[0]:,}\")\nfor k in range(1, 14):\n    print(f\"{k:>3}: {labels[k]:35s} -> {counts[k]:,}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T11:57:00.491656Z","iopub.execute_input":"2025-08-14T11:57:00.492042Z","iopub.status.idle":"2025-08-14T11:57:07.553535Z","shell.execute_reply.started":"2025-08-14T11:57:00.49201Z","shell.execute_reply":"2025-08-14T11:57:07.55241Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# dcm2niix yüklü değilse kur (DICOM -> NIfTI çevirisi için)\n!apt-get update -qq\n!apt-get install -y -qq dcm2niix\n\n# ======= Parametreler (sadece STUDY_UID'yi değiştirmen yeterli) =======\nSTUDY_UID = \"1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381\"  # GT olan hasta\nDATA_ROOT = \"/kaggle/input/rsna-intracranial-aneurysm-detection\"\n\n# nnU-Net eğitim çıktıların\nimport os, shutil\nos.environ[\"nnUNet_results\"] = \"/kaggle/working/nnUNet_results\"\n\n# Çalışma klasörleri\nTMP_NIFTI = \"/kaggle/working/tmp_eval_nifti\"     # DICOM->NIfTI geçici\nPRED_DIR  = \"/kaggle/working/nnunet_eval_pred\"   # nnU-Net tahminleri\nfor p in [TMP_NIFTI, PRED_DIR]:\n    os.makedirs(p, exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T12:17:10.473095Z","iopub.execute_input":"2025-08-14T12:17:10.473572Z","iopub.status.idle":"2025-08-14T12:17:28.65043Z","shell.execute_reply.started":"2025-08-14T12:17:10.473536Z","shell.execute_reply":"2025-08-14T12:17:28.648934Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\nimport shutil, os\n\nDATA_ROOT = \"/kaggle/input/rsna-intracranial-aneurysm-detection\"\nSTUDY_UID = \"1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381\"\nTMP_NIFTI = \"/kaggle/working/tmp_eval_nifti\"\nos.makedirs(TMP_NIFTI, exist_ok=True)\n\nSERIES_DIR = f\"{DATA_ROOT}/series/{STUDY_UID}\"\nSEG_DIR    = f\"{DATA_ROOT}/segmentations/{STUDY_UID}\"\n\nassert Path(SERIES_DIR).exists(), f\"Series yok: {SERIES_DIR}\"\nassert Path(SEG_DIR).exists(),    f\"Seg yok: {SEG_DIR}\"\n\ngt_files = sorted(Path(SEG_DIR).glob(\"*.nii*\"))\nassert gt_files, f\"GT .nii bulunamadı: {SEG_DIR}\"\nGT_PATH = str(gt_files[0])\nprint(\"Seri klasörü:\", SERIES_DIR)\nprint(\"GT maske   :\", GT_PATH)\n\n# geçici klasörü temizle\nfor p in Path(TMP_NIFTI).glob(\"*\"):\n    try: p.unlink()\n    except: shutil.rmtree(p, ignore_errors=True)\n\n# DICOM -> NIfTI\n!dcm2niix -z y -o \"{TMP_NIFTI}\" \"{SERIES_DIR}\"\n\n# nnU-Net tek kanal isimlendirmesi: *_0000.nii.gz\nnii_list = sorted(Path(TMP_NIFTI).glob(\"*.nii.gz\"))\nassert nii_list, \"dcm2niix çıktı üretmedi.\"\nimg0 = nii_list[0]\nif not img0.name.endswith(\"_0000.nii.gz\"):\n    fixed = img0.with_name(img0.stem + \"_0000.nii.gz\")\n    shutil.copy2(img0, fixed)\n    IMG_PATH = str(fixed)\nelse:\n    IMG_PATH = str(img0)\nprint(\"Girdi NIfTI :\", IMG_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T12:18:55.327905Z","iopub.execute_input":"2025-08-14T12:18:55.328357Z","iopub.status.idle":"2025-08-14T12:19:04.042608Z","shell.execute_reply.started":"2025-08-14T12:18:55.328302Z","shell.execute_reply":"2025-08-14T12:19:04.040283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, time, subprocess, torch\nfrom pathlib import Path\n\n# --- 1) Yol tanımları (senin düzenin) ---\nRAW = \"/kaggle/working/nnUNet_raw\"                 # symlink olabilir (varsa sorun değil)\nPRE = \"/kaggle/working/nnUNet_preprocessed\"        # mevcut (18 GB)\nRES = \"/kaggle/working/nnUNet_results\"             # eğitim çıktıları burada\n\nMODEL_DIR = Path(RES) / \"Dataset100_RSNAIA_CoW\" / \"nnUNetTrainer__nnUNetPlans__3d_fullres\" / \"fold_0\"\nCKPT = MODEL_DIR / \"checkpoint_best.pth\"\n\nIN_DIR  = Path(\"/kaggle/working/eval_in\")          # 0000.nii.gz burada\nOUT_DIR = Path(\"/kaggle/working/eval_pred\")        # tahminler buraya\n\n# --- 2) Kontroller ---\nassert Path(PRE).exists(), f\"Bulunamadı: {PRE}\"\nassert Path(RES).exists(), f\"Bulunamadı: {RES}\"\nassert MODEL_DIR.exists(), f\"Model klasörü yok: {MODEL_DIR}\"\nassert CKPT.exists(), f\"Checkpoint yok: {CKPT}\"\nassert IN_DIR.exists() and any(IN_DIR.glob(\"*.nii.gz\")), f\"Girdi NIfTI bulunamadı: {IN_DIR}\"\n\nOUT_DIR.mkdir(parents=True, exist_ok=True)\n\n# --- 3) Ortam değişkenlerini KUR ---\nos.environ[\"nnUNet_raw\"] = RAW\nos.environ[\"nnUNet_preprocessed\"] = PRE\nos.environ[\"nnUNet_results\"] = RES\nos.environ[\"PYTHONUNBUFFERED\"] = \"1\"\nos.environ[\"nnUNet_compile\"] = \"0\"\nos.environ[\"TORCH_COMPILE_DISABLE\"] = \"1\"\n\n# --- 4) Cihaz seçimi (cuda varsa cuda, yoksa cpu) ---\ndevice_flag = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nprint(f\"Device: {device_flag}\")\n\n# --- 5) Tahmin komutu ---\ncmd = [\n    \"nnUNetv2_predict\",\n    \"-i\", str(IN_DIR),\n    \"-o\", str(OUT_DIR),\n    # Dataset kimliği: adıyla vermek daha güvenli\n    \"-d\", \"Dataset100_RSNAIA_CoW\",\n    \"-c\", \"3d_fullres\",\n    \"-f\", \"0\",\n    \"-tr\", \"nnUNetTrainer\",\n    \"-chk\", \"checkpoint_best.pth\",   # cwd=MODEL_DIR olduğu için sadece adı yeterli\n    \"-device\", device_flag,\n    \"--verbose\"\n]\n\nprint(\"[RUN]\", \" \".join(cmd))\nt0 = time.time()\nrc = subprocess.run(cmd, cwd=str(MODEL_DIR)).returncode\ndt = time.time() - t0\nprint(f\"\\n✅ İnferans bitti. rc={rc}, süre={dt:.1f}s\")\nprint(\"Çıktılar:\", [p.name for p in OUT_DIR.glob(\"*\")])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T12:54:14.302209Z","iopub.execute_input":"2025-08-14T12:54:14.302837Z","iopub.status.idle":"2025-08-14T12:59:20.118843Z","shell.execute_reply.started":"2025-08-14T12:54:14.302808Z","shell.execute_reply":"2025-08-14T12:59:20.11791Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# -- Hücre 1: Yükle & hizala (SimpleITK) --\nimport os\nfrom pathlib import Path\nimport SimpleITK as sitk\n\n# YOLLAR — bunları değiştirebilirsin\nGT_PATH   = \"/kaggle/input/rsna-intracranial-aneurysm-detection/segmentations/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381_cowseg.nii\"\nPRED_PATH = \"/kaggle/working/eval_pred/case.nii.gz\"\n\n# ÇIKTI: pred'i GT uzayına getirilmiş hizalanmış label\nALIGNED_PRED_PATH = \"/kaggle/working/eval_pred/case_aligned_to_gt.nii.gz\"\n\n# Oku\ngt_img   = sitk.ReadImage(GT_PATH)\npred_img = sitk.ReadImage(PRED_PATH)\n\nprint(\"GT size / spacing :\", gt_img.GetSize(), \"/\", gt_img.GetSpacing())\nprint(\"PR size / spacing :\", pred_img.GetSize(), \"/\", pred_img.GetSpacing())\n\n# Eğer boyut/spacing/affine farklıysa pred'i GT uzayına resample et\nneeds_resample = (gt_img.GetSize()!=pred_img.GetSize()) or (gt_img.GetSpacing()!=pred_img.GetSpacing()) or (gt_img.GetOrigin()!=pred_img.GetOrigin()) or (gt_img.GetDirection()!=pred_img.GetDirection())\n\nif needs_resample:\n    print(\"→ Boyut/uzay farklı: prediction GT uzayına yeniden örneklenecek (nearest).\")\n    # Nearest neighbor (etiket verisi!)\n    resampler = sitk.ResampleImageFilter()\n    resampler.SetReferenceImage(gt_img)\n    resampler.SetInterpolator(sitk.sitkNearestNeighbor)\n    resampler.SetOutputPixelType(sitk.sitkUInt16)\n    pred_aligned = resampler.Execute(pred_img)\n    sitk.WriteImage(pred_aligned, ALIGNED_PRED_PATH)\n    print(\"Kaydedildi:\", ALIGNED_PRED_PATH)\n    pred_img = pred_aligned\nelse:\n    print(\"→ Uzaylar uyumlu. Hizalama gerekmiyor.\")\n    # Uyumluysa yine de tekilleştirelim\n    ALIGNED_PRED_PATH = PRED_PATH","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T13:04:30.55691Z","iopub.execute_input":"2025-08-14T13:04:30.557812Z","iopub.status.idle":"2025-08-14T13:04:31.904526Z","shell.execute_reply.started":"2025-08-14T13:04:30.55778Z","shell.execute_reply":"2025-08-14T13:04:31.903878Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# -- Hücre 2: Dice metrikleri --\nimport numpy as np\nimport SimpleITK as sitk\nimport pandas as pd\n\ngt = sitk.GetArrayFromImage(sitk.ReadImage(GT_PATH)).astype(np.int16)\npr = sitk.GetArrayFromImage(sitk.ReadImage(ALIGNED_PRED_PATH)).astype(np.int16)\n\n# Dice hesaplayıcı\ndef dice_coef(y_true, y_pred, cls):\n    y1 = (y_true==cls)\n    y2 = (y_pred==cls)\n    inter = (y1 & y2).sum()\n    denom = y1.sum() + y2.sum()\n    return (2.0*inter/denom) if denom>0 else np.nan\n\n# Hangi etiketleri değerlendirelim?\n# Senin kurulumuna göre 0: background, 1..13: damarsal segmentler\nclasses = list(range(1,14))\n\nrows = []\nfor c in classes:\n    d = dice_coef(gt, pr, c)\n    vox_gt = int((gt==c).sum())\n    vox_pr = int((pr==c).sum())\n    rows.append({\"class\": c, \"dice\": d, \"gt_vox\": vox_gt, \"pred_vox\": vox_pr})\n\ndf = pd.DataFrame(rows).sort_values(\"class\")\nprint(df.to_string(index=False))\n\n# Ortalama (geçerli sınıflar üzerinden)\nmean_dice = np.nanmean(df[\"dice\"].values)\nprint(f\"\\nMean Dice (1..13): {mean_dice:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T13:04:38.912348Z","iopub.execute_input":"2025-08-14T13:04:38.912988Z","iopub.status.idle":"2025-08-14T13:04:44.603419Z","shell.execute_reply.started":"2025-08-14T13:04:38.912967Z","shell.execute_reply":"2025-08-14T13:04:44.602682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# -- Hücre 3: Görselleştirme --\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport SimpleITK as sitk\n\ngt_img   = sitk.GetArrayFromImage(sitk.ReadImage(GT_PATH))\npr_img   = sitk.GetArrayFromImage(sitk.ReadImage(ALIGNED_PRED_PATH))\n\n# Aynı klasörde dcm2niix ile üretilen intensity görüntüsünü de göstermek istersen:\n# (Eğer varsa; yoksa sadece maskeleri gösterir)\nmaybe_intensity = list(Path(\"/kaggle/working/tmp_eval_nifti\").glob(\"*_0000.nii.gz\"))\nimg_arr = None\nif maybe_intensity:\n    try:\n        img_arr = sitk.GetArrayFromImage(sitk.ReadImage(str(maybe_intensity[0]))).astype(np.float32)\n        # normalize\n        p1, p99 = np.percentile(img_arr, [1,99])\n        img_arr = np.clip((img_arr - p1)/(p99-p1 + 1e-6), 0, 1)\n    except:\n        img_arr = None\n\nZ = gt_img.shape[0]\nslices = np.linspace(Z*0.2, Z*0.8, 6).astype(int)\n\nplt.figure(figsize=(12,8))\nfor i, z in enumerate(slices, 1):\n    plt.subplot(2,3,i)\n    if img_arr is not None and z < img_arr.shape[0]:\n        base = img_arr[z]\n        plt.imshow(base, cmap='gray')\n        # tahmini kontur\n        plt.contour(pr_img[z] > 0, levels=[0.5], linewidths=0.6)\n        # GT kontur\n        plt.contour(gt_img[z] > 0, levels=[0.5], linewidths=0.6, linestyles='--')\n        plt.title(f\"z={z} | pred(—), gt(--)\")\n    else:\n        # sadece maskeler\n        overlay = np.zeros((*gt_img.shape[1:], 3), dtype=np.float32)\n        overlay[..., 0] = (gt_img[z] > 0) * 1.0      # GT kırmızı\n        overlay[..., 1] = (pr_img[z] > 0) * 1.0      # Pred yeşil\n        plt.imshow(overlay)\n        plt.title(f\"z={z} | R=GT, G=Pred\")\n    plt.axis('off')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T13:05:35.645276Z","iopub.execute_input":"2025-08-14T13:05:35.645791Z","iopub.status.idle":"2025-08-14T13:05:38.528129Z","shell.execute_reply.started":"2025-08-14T13:05:35.645765Z","shell.execute_reply":"2025-08-14T13:05:38.527318Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ========= RSNA CoW: Tek-seri uçtan-uca pipeline =========\n# Girdi: SeriesInstanceUID  (anevrizmalı olduğunu söylediğin örnek)\nSERIES_ID = \"1.2.826.0.1.3680043.8.498.10005158603912009425635473100344077317\"\n\n# --------- Sabitler / Yollar (eğittiğin nnU-Net'e göre) ---------\nDATASET_NAME = \"Dataset100_RSNAIA_CoW\"\nCFG          = \"3d_fullres\"\nFOLD         = \"0\"\nTRAINER      = \"nnUNetTrainer\"\nCHKPT_NAME   = \"checkpoint_best.pth\"\n\nSERIES_ROOT = \"/kaggle/input/rsna-intracranial-aneurysm-detection/series\"\nNNUNET_RES  = \"/kaggle/working/nnUNet_results\"          # eğitim çıktıların burada\nNNUNET_PRE  = \"/kaggle/working/nnUNet_preprocessed\"     # preprocessed burada\nNNUNET_RAW  = \"/kaggle/working/nnUNet_raw\"              # boş olabilir ama env ister\n\n# CNN ağı (opsiyonel): burada bir .pt bulursan aday crop'larda var/yok olasılığı üretirim.\nCNN_WEIGHTS = \"/kaggle/working/aneurysm_cnn.pt\"          # yoksa heuristik ile devam\n\n# Çalışma klasörü\nfrom pathlib import Path\nBASE = Path(f\"/kaggle/working/pipeline_out/{SERIES_ID}\")\nNIFTI_DIR = BASE/\"nifti\";  PRED_DIR = BASE/\"pred\";  VIZ_DIR = BASE/\"viz\";  CROP_DIR = BASE/\"crops\"\nfor d in [BASE, NIFTI_DIR, PRED_DIR, VIZ_DIR, CROP_DIR]:\n    d.mkdir(parents=True, exist_ok=True)\n\n# --------- Ortam ve bağımlılıklar ---------\nimport os, sys, json, time, shutil, math, subprocess, warnings\nimport numpy as np, pandas as pd\nimport nibabel as nib\nimport matplotlib.pyplot as plt\nimport scipy.ndimage as ndi\n\nos.environ[\"nnUNet_results\"]      = NNUNET_RES\nos.environ[\"nnUNet_preprocessed\"] = NNUNET_PRE\nos.environ[\"nnUNet_raw\"]          = NNUNET_RAW\n\n# dcm2niix yoksa kur\nif shutil.which(\"dcm2niix\") is None:\n    !apt-get -y update >/dev/null\n    !apt-get -y install dcm2niix >/dev/null\n\n# nnUNetv2_predict yoksa pip (genelde kurulu)\nif shutil.which(\"nnUNetv2_predict\") is None:\n    try:\n        import nnunetv2  # noqa\n    except Exception:\n        !pip -q install nnunetv2 >/dev/null\n\n# --------- Yardımcılar ---------\nLABELS = {\n 1:\"Other Posterior Circulation\",\n 2:\"Basilar Tip\",\n 3:\"Right Posterior Communicating Artery\",\n 4:\"Left Posterior Communicating Artery\",\n 5:\"Right Infraclinoid Internal Carotid Artery\",\n 6:\"Left Infraclinoid Internal Carotid Artery\",\n 7:\"Right Supraclinoid Internal Carotid Artery\",\n 8:\"Left Supraclinoid Internal Carotid Artery\",\n 9:\"Right Middle Cerebral Artery\",\n10:\"Left Middle Cerebral Artery\",\n11:\"Right Anterior Cerebral Artery\",\n12:\"Left Anterior Cerebral Artery\",\n13:\"Anterior Communicating Artery\",\n}\n\nANEURYSMY_LOCATIONS = {2,3,4,5,6,7,8,9,10,11,12,13}  # klinikte daha sık görülenler\n\ndef norm_clip(x):\n    lo, hi = np.percentile(x, 1), np.percentile(x, 99)\n    x = np.clip(x, lo, hi)\n    m, s = x.mean(), x.std() + 1e-6\n    return (x - m) / s\n\ndef ensure_nii(series_id:str) -> Path:\n    \"\"\"DICOM → NIfTI; çıktı *_0000.nii.gz garantilenir.\"\"\"\n    out_dir = NIFTI_DIR\n    out_dir.mkdir(exist_ok=True, parents=True)\n    # zaten varsa alma\n    cand = sorted(out_dir.glob(\"*_0000.nii.gz\"))\n    if cand:\n        return cand[-1]\n    src = Path(SERIES_ROOT)/series_id\n    assert src.exists(), f\"DICOM klasörü yok: {src}\"\n    cmd = [\"dcm2niix\", \"-z\", \"y\", \"-o\", str(out_dir), str(src)]\n    print(\"[DICOM→NIfTI]\", \" \".join(cmd))\n    rc = subprocess.run(cmd, capture_output=True, text=True).returncode\n    if rc != 0:\n        raise RuntimeError(\"dcm2niix hata\")\n    nii = sorted(out_dir.glob(\"*.nii.gz\"), key=lambda p:p.stat().st_mtime)[-1]\n    if not nii.name.endswith(\"_0000.nii.gz\"):\n        newp = nii.with_name(nii.name.replace(\".nii.gz\",\"_0000.nii.gz\"))\n        nii.rename(newp); nii = newp\n    return nii\n\ndef run_nnunet(nii_path:Path) -> Path:\n    \"\"\"nnU-Net tahmini; çıktı PRED_DIR/case.nii.gz\"\"\"\n    out_dir = PRED_DIR; out_dir.mkdir(exist_ok=True)\n    seg_path = out_dir/\"case.nii.gz\"\n    if seg_path.exists():\n        return seg_path\n    # nnU-Net klasör inputu\n    tmp_in = out_dir/\"in\"; \n    if tmp_in.exists(): shutil.rmtree(tmp_in)\n    tmp_in.mkdir(parents=True, exist_ok=True)\n    shutil.copy2(nii_path, tmp_in/\"case_0000.nii.gz\")\n\n    device = \"cuda\" if (shutil.which(\"nvidia-smi\") or os.environ.get(\"CUDA_VISIBLE_DEVICES\")) else \"cpu\"\n    print(\"Device:\", device)\n    cmd = [\n        \"nnUNetv2_predict\",\n        \"-i\", str(tmp_in),\n        \"-o\", str(out_dir),\n        \"-d\", DATASET_NAME,\n        \"-c\", CFG,\n        \"-f\", FOLD,\n        \"-tr\", TRAINER,\n        \"-chk\", CHKPT_NAME,\n        \"-device\", device,\n        \"--verbose\"\n    ]\n    print(\"[nnUNet]\", \" \".join(cmd))\n    t0=time.time()\n    rc = subprocess.run(cmd).returncode\n    print(f\"[nnUNet] rc={rc}, süre={time.time()-t0:.1f}s\")\n    if rc!=0: raise RuntimeError(\"nnUNet tahmin hatası\")\n    assert seg_path.exists(), \"Tahmin çıktısı yok\"\n    return seg_path\n\ndef connected_components_by_class(seg):\n    \"\"\"Her sınıf için bağlı bileşen listesi: (label, vox_count, bbox, centroid)\"\"\"\n    out=[]\n    for lab in range(1,14):\n        mask = (seg==lab)\n        if mask.sum()==0: \n            continue\n        lab_img, n = ndi.label(mask)\n        for cc in range(1, n+1):\n            comp = (lab_img==cc)\n            v = int(comp.sum())\n            z,y,x = np.where(comp)\n            z0,z1 = int(z.min()), int(z.max())+1\n            y0,y1 = int(y.min()), int(y.max())+1\n            x0,x1 = int(x.min()), int(x.max())+1\n            cz,cy,cx = int(z.mean()), int(y.mean()), int(x.mean())\n            out.append({\n                \"label\": lab,\n                \"voxels\": v,\n                \"bbox\": (z0,y0,x0,z1,y1,x1),\n                \"centroid\": (cz,cy,cx),\n                \"dims\": (z1-z0, y1-y0, x1-x0)\n            })\n    return out\n\ndef blob_score(voxels, dims):\n    \"\"\"Saccular 'şişkinlik' sezgisi: hacim & izotropiye yakınlık.\"\"\"\n    dz,dy,dx = dims\n    # izotropi ~ min/max oranı\n    sphericity = min(dz,dy,dx) / (max(dz,dy,dx)+1e-6)\n    # boyut önceliği (çok küçük gürültüyü ve çok büyük trunk'ı azalt)\n    # 80..8000 aralığını tercih\n    v = voxels\n    size_pref = np.exp(-((np.log1p(v) - np.log(800))**2) / (2*(np.log(6)**2)))\n    return float(0.6*sphericity + 0.4*size_pref)\n\ndef small_3d_cnn(in_ch=1, nclass=2):\n    import torch.nn as nn\n    return nn.Sequential(\n        nn.Conv3d(in_ch,16,3,padding=1), nn.ReLU(), nn.MaxPool3d(2),\n        nn.Conv3d(16,32,3,padding=1),    nn.ReLU(), nn.MaxPool3d(2),\n        nn.Conv3d(32,64,3,padding=1),    nn.ReLU(), nn.AdaptiveAvgPool3d(1),\n        nn.Flatten(), nn.Linear(64, nclass)\n    )\n\ndef crop_around(img, center, size=(48,96,96)):\n    Z,Y,X = img.shape\n    dz,dy,dx = size; cz,cy,cx = center\n    z0=max(0,cz-dz//2); z1=min(Z,z0+dz)\n    y0=max(0,cy-dy//2); y1=min(Y,y0+dy)\n    x0=max(0,cx-dx//2); x1=min(X,x0+dx)\n    crop = img[z0:z1,y0:y1,x0:x1]\n    # pad gerekirse\n    pad = [(0,0),(0,0),(0,0)]\n    if crop.shape!=(dz,dy,dx):\n        pad = [(0, dz-crop.shape[0]), (0, dy-crop.shape[1]), (0, dx-crop.shape[2])]\n        crop = np.pad(crop, ((0,pad[0][1]),(0,pad[1][1]),(0,pad[2][1])), mode=\"edge\")\n    return crop\n\n# --------- 1) DICOM → NIfTI ---------\nnii_path = ensure_nii(SERIES_ID)\nprint(\"NIfTI:\", nii_path)\n\n# --------- 2) nnU-Net tahmini ---------\nseg_path = run_nnunet(nii_path)\nprint(\"Seg:\", seg_path)\n\n# --------- 3) Aday çıkarımı & (opsiyonel) CNN skoru ---------\nimg = nib.load(nii_path).get_fdata().astype(np.float32)\nseg = nib.load(seg_path).get_fdata().astype(np.int16)\n\n# Normalle\nimg_n = norm_clip(img)\n\n# Sınıf başına bileşenleri topla\ncomps = connected_components_by_class(seg)\ndf = pd.DataFrame(comps)\nif df.empty:\n    raise RuntimeError(\"Hiç segment bulunamadı.\")\n\n# Heuristik skor hesapla\ndf[\"blob_score\"] = df.apply(lambda r: blob_score(r[\"voxels\"], r[\"dims\"]), axis=1)\n# Klinik açıdan daha anlamlı sınıflara küçük bonus\ndf[\"loc_bonus\"] = df[\"label\"].apply(lambda l: 0.15 if l in ANEURYSMY_LOCATIONS else 0.0)\ndf[\"heuristic_score\"] = df[\"blob_score\"] + df[\"loc_bonus\"]\n\n# Adayları heuristik ile sırala (en çok 20)\ncands = df.sort_values(\"heuristic_score\", ascending=False).head(20).reset_index(drop=True)\n\n# (Opsiyonel) CNN varsa aday crop'ları puanla\ncnn_used = False\ncnn_probs = None\nif Path(CNN_WEIGHTS).exists():\n    try:\n        import torch\n        device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n        net = small_3d_cnn().to(device)\n        net.load_state_dict(torch.load(CNN_WEIGHTS, map_location=device))\n        net.eval()\n        crops=[]\n        for r in cands.itertuples():\n            cz,cy,cx = r.centroid\n            crop = crop_around(img_n, (int(cz),int(cy),int(cx)))\n            crops.append(crop[None,None,...])           # (1,1,D,H,W)\n        X = torch.from_numpy(np.concatenate(crops,0)).float().to(device)\n        with torch.no_grad():\n            logits = net(X); prob = torch.softmax(logits, dim=1)[:,1].cpu().numpy()\n        cands[\"cnn_prob\"] = prob\n        cnn_probs = prob\n        cnn_used = True\n    except Exception as e:\n        print(\"[CNN] kullanılamadı:\", e)\n\n# Nihai skor: (CNN varsa) 0.7*cnn + 0.3*heuristic, yoksa heuristic\nif cnn_used:\n    cands[\"final_score\"] = 0.7*cands[\"cnn_prob\"] + 0.3*cands[\"heuristic_score\"]\nelse:\n    cands[\"final_score\"] = cands[\"heuristic_score\"]\n\n# En iyi aday\nbest = cands.iloc[0]\npred_has_aneurysm = bool(best[\"final_score\"] >= (0.6 if cnn_used else 0.75))\npred_label_id = int(best[\"label\"])\npred_label_name = LABELS.get(pred_label_id, f\"Class {pred_label_id}\")\n\n# --------- 4) Görseller & Rapor ---------\n# 3 dilim (axial, coronal, sagittal) üstüne en iyi adayın konturunu çizelim\ncz,cy,cx = map(int, best[\"centroid\"])\nmask_best = (seg==pred_label_id).astype(np.uint8)\n# sadece en yakın küçük çevre\nlab,n = ndi.label(mask_best)\nlbl_at_centroid = lab[max(cz,0), max(cy,0), max(cx,0)]\nmask_best = (lab==lbl_at_centroid)\n\ndef overlay_slice(ax, base, mask, title):\n    ax.imshow(base, cmap=\"gray\")\n    ax.contour(mask.astype(float), levels=[0.5], colors=\"magenta\", linewidths=1.0)\n    ax.set_title(title); ax.axis(\"off\")\n\nfig = plt.figure(figsize=(14,4.5))\nax1 = fig.add_subplot(1,3,1)\noverlay_slice(ax1, img_n[cz,:,:], mask_best[cz,:,:], f\"Axial z={cz}\")\nax2 = fig.add_subplot(1,3,2)\noverlay_slice(ax2, img_n[:,cy,:], mask_best[:,cy,:], f\"Coronal y={cy}\")\nax3 = fig.add_subplot(1,3,3)\noverlay_slice(ax3, img_n[:,:,cx], mask_best[:,:,cx], f\"Sagittal x={cx}\")\nviz_path = VIZ_DIR/\"overlay.png\"; fig.tight_layout(); fig.savefig(viz_path, dpi=200); plt.close(fig)\n\n# MIP'ler\nfor axis, name in [(0,\"ax0\"),(1,\"ax1\"),(2,\"ax2\")]:\n    mip = img_n.max(axis=axis)\n    mask_mip = mask_best.max(axis=axis)\n    plt.figure(figsize=(6,5))\n    plt.imshow(mip, cmap=\"gray\"); plt.contour(mask_mip.astype(float), levels=[0.5], colors=\"cyan\", linewidths=0.8)\n    plt.title(f\"MIP axis={axis}\"); plt.axis(\"off\")\n    plt.savefig(VIZ_DIR/f\"mip_{name}.png\", dpi=180); plt.close()\n\n# Özet CSV/JSON\nsummary = {\n    \"series_id\": SERIES_ID,\n    \"nii\": str(nii_path),\n    \"seg\": str(seg_path),\n    \"pred_has_aneurysm\": pred_has_aneurysm,\n    \"pred_vessel_label_id\": pred_label_id,\n    \"pred_vessel_label_name\": pred_label_name,\n    \"final_score\": float(best[\"final_score\"]),\n    \"cnn_used\": cnn_used,\n}\n(pd.DataFrame(comps)\n   .assign(label_name=lambda d: d[\"label\"].map(LABELS))\n   .to_csv(BASE/\"components.csv\", index=False))\nwith open(BASE/\"summary.json\",\"w\") as f: json.dump(summary, f, indent=2)\n\nprint(\"\\n==== SONUÇ ====\")\nprint(\"Aneurizma var mı?:\", \"EVET\" if pred_has_aneurysm else \"HAYIR\")\nprint(f\"Olası damar: {pred_label_id} - {pred_label_name}\")\nprint(f\"Skor: {summary['final_score']:.3f} | CNN kullanıldı mı?: {cnn_used}\")\nprint(\"Görseller:\", viz_path, \"| MIP'ler:\", list((VIZ_DIR).glob(\"mip_*.png\")))\nprint(\"Ayrıntılar:\", BASE/\"summary.json\", \"| Bileşenler:\", BASE/\"components.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T13:58:11.979594Z","iopub.execute_input":"2025-08-14T13:58:11.97994Z","iopub.status.idle":"2025-08-14T14:03:26.134233Z","shell.execute_reply.started":"2025-08-14T13:58:11.979905Z","shell.execute_reply":"2025-08-14T14:03:26.133339Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# DICOM -> NIfTI -> nnU-Net inference (Python API) — MODEL_DIR düzeltildi\n\nimport os, subprocess, time, shutil\nfrom pathlib import Path\nimport torch\nfrom nnunetv2.inference.predict_from_raw_data import nnUNetPredictor\n\n# --- Girdiler ---\nSERIES_DIR = \"/kaggle/input/rsna-intracranial-aneurysm-detection/series/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381\"\nMODEL_DIR  = \"/kaggle/working/nnUNet_results/Dataset100_RSNAIA_CoW/nnUNetTrainer__nnUNetPlans__3d_fullres\"  # <- fold_0 DEĞİL!\nFOLDS      = (0,)\nCKPT_NAME  = \"checkpoint_best.pth\"\n\nTMP_NIFTI = Path(\"/kaggle/working/tmp_eval_nifti\"); TMP_NIFTI.mkdir(parents=True, exist_ok=True)\nEVAL_IN   = Path(\"/kaggle/working/eval_in\");        EVAL_IN.mkdir(parents=True, exist_ok=True)\nOUT_DIR   = Path(\"/kaggle/working/eval_pred\");      OUT_DIR.mkdir(parents=True, exist_ok=True)\n\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Device:\", DEVICE)\n\n# --- 1) DICOM -> NIfTI ---\nprint(\"\\n== DICOM -> NIfTI ==\")\nsubprocess.run([\"dcm2niix\",\"-z\",\"y\",\"-o\",str(TMP_NIFTI),SERIES_DIR], check=True)\nnii_list = sorted(TMP_NIFTI.glob(\"*.nii.gz\"), key=lambda p: p.stat().st_mtime, reverse=True)\nassert nii_list, \"dcm2niix çıktı üretmedi.\"\nsrc = nii_list[0]\ndst = EVAL_IN / (src.stem + \"_0000.nii.gz\")\nshutil.copy2(src, dst)\nprint(\"NIfTI:\", src)\nprint(\"Inference girişi:\", dst)\n\n# --- 2) nnU-Net inference (Python API) ---\nprint(\"\\n== nnU-Net inference (Python API) ==\")\n# Kök klasörde dataset.json / plans.json olmalı:\nassert (Path(MODEL_DIR)/\"dataset.json\").exists(), \"dataset.json kök klasörde bulunamadı!\"\nassert (Path(MODEL_DIR)/\"plans.json\").exists(), \"plans.json kök klasörde bulunamadı!\"\n# fold_0 içinde checkpoint olmalı:\nassert (Path(MODEL_DIR)/\"fold_0\"/CKPT_NAME).exists(), f\"{CKPT_NAME} bulunamadı!\"\n\npred = nnUNetPredictor(\n    tile_step_size=0.5,\n    use_gaussian=True,\n    use_mirroring=True,                 # TTA açık\n    perform_everything_on_device=True,\n    device=DEVICE,\n    verbose=True\n)\n\npred.initialize_from_trained_model_folder(\n    model_training_output_dir=MODEL_DIR,\n    use_folds=FOLDS,\n    checkpoint_name=CKPT_NAME\n)\n\ncases = [[str(dst)]]\nt0 = time.time()\npred.predict_from_files(\n    list_of_lists_or_source_folder=cases,\n    output_folder_or_list_of_truncated_output_files=str(OUT_DIR),\n    save_probabilities=False,\n    num_processes_segmentation_export=1\n)\ndt = time.time() - t0\nprint(f\"\\n✅ Tahmin tamamlandı. Süre: {dt:.1f} s\")\nprint(\"Çıktılar:\", [p.name for p in sorted(OUT_DIR.iterdir())])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T16:54:58.174144Z","iopub.execute_input":"2025-08-14T16:54:58.174452Z","iopub.status.idle":"2025-08-14T16:59:57.780434Z","shell.execute_reply.started":"2025-08-14T16:54:58.174425Z","shell.execute_reply":"2025-08-14T16:59:57.779426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === Yan yana GT vs. Prediction (tek hücre) ===\nimport os\nfrom pathlib import Path\nimport numpy as np\nimport nibabel as nib\nimport matplotlib.pyplot as plt\nfrom scipy.ndimage import zoom\n\n# ---------- KULLANICI AYARLARI ----------\n# nnU-Net tahmin çıktısı (genelde /kaggle/working/eval_pred/case.nii.gz)\npred_path = \"/kaggle/working/eval_pred/case.nii.gz\"\n\n# GT maske (cowseg) - bu YOLU kendi vakana göre değiştir\ngt_path = \"/kaggle/input/rsna-intracranial-aneurysm-detection/segmentations/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381_cowseg.nii\"\n\n# Görselde gösterilecek dilim (z-ekseni). None => otomatik (maskenin en dolu olduğu dilim)\nz = None\n\n# İsteğe bağlı: gri-tonlu arkaplan hacim (otomatik arama)\n# /kaggle/working/eval_in içine dcm2niix -> _0000.nii.gz oluşturuyoruz\nimg_candidates = sorted(Path(\"/kaggle/working/eval_in\").glob(\"*.nii*\"), key=lambda p: p.stat().st_mtime, reverse=True)\nimg_path = str(img_candidates[0]) if img_candidates else None  # bulunamazsa None kalır\n\n# ---------- YARDIMCILAR ----------\ndef load_nifti(path, dtype=None):\n    ni = nib.load(path)\n    arr = ni.get_fdata()\n    if dtype is not None:\n        arr = arr.astype(dtype)\n    return arr, ni.affine\n\ndef ensure_channel0(img_path):\n    \"\"\"nnU-Net girişi gibi _0000 son ekli tek-kanal adı üretmek için değil,\n    burada sadece dosya mevcut mu diye kontrol için kullanıyoruz.\"\"\"\n    return img_path\n\ndef resample_labels_to_shape(lbl, target_shape):\n    \"\"\" Sadece şekle uydurmak için en basit yaklaşım: nearest-neighbor zoom.\n        Affine farklılıklarını dikkate almaz. (Genelde gerekmez; dcm2niix -> nnUNet çıktısı aynı uzama dönüyor.)\n    \"\"\"\n    if tuple(lbl.shape) == tuple(target_shape):\n        return lbl\n    scale = np.array(target_shape) / np.array(lbl.shape)\n    return zoom(lbl, zoom=scale, order=0)\n\ndef dice_score(gt, pr, cls):\n    gt_bin = (gt == cls)\n    pr_bin = (pr == cls)\n    inter = (gt_bin & pr_bin).sum()\n    denom = gt_bin.sum() + pr_bin.sum()\n    if denom == 0:\n        return np.nan  # o sınıf yoksa NaN\n    return 2.0 * inter / denom\n\n# ---------- YÜKLE ----------\npred, aff_pred = load_nifti(pred_path, dtype=np.int16)\ngt,   aff_gt   = load_nifti(gt_path,   dtype=np.int16)\n\n# Gerekirse pred'i GT şekline uydur (etiket olduğu için NN)\nif pred.shape != gt.shape:\n    pred_rs = resample_labels_to_shape(pred, gt.shape)\nelse:\n    pred_rs = pred\n\n# Arkaplan görüntü (varsa)\nimg = None\nif img_path and Path(img_path).exists():\n    # img NIfTI tek kanallı hacim\n    img, aff_img = load_nifti(img_path, dtype=np.float32)\n    # img'i de GT şekline uydur (görüntü olduğu için lineer; ama scipy zoom sadece order=0/1/3... -> 1 kullanalım)\n    if img.shape != gt.shape:\n        scale = np.array(gt.shape) / np.array(img.shape)\n        img = zoom(img, zoom=scale, order=1)\n\n# ---------- HANGİ DİLİM? ----------\nif z is None:\n    # GT veya pred üzerinde en yoğun sınıf (arka plan hariç) piksellerinin en çok olduğu dilimi bul\n    nonbg_gt = (gt > 0).sum(axis=(1,2))\n    nonbg_pr = (pred_rs > 0).sum(axis=(1,2))\n    z = int(np.argmax(nonbg_gt + nonbg_pr))\n\nz = int(np.clip(z, 0, gt.shape[0]-1))\n\n# ---------- DICE HESAPLARI ----------\nclasses = sorted(list(set(np.unique(gt)) | set(np.unique(pred_rs))))\nif 0 in classes:\n    classes.remove(0)  # arkaplan hariç\nper_class = {c: dice_score(gt, pred_rs, c) for c in classes}\nvalid_dice = [v for v in per_class.values() if not np.isnan(v)]\nmacro_dice = float(np.mean(valid_dice)) if valid_dice else np.nan\n\nprint(\"Hacim şekli (Z,Y,X):\", gt.shape)\nprint(\"Seçilen z:\", z)\nprint(\"Sınıf sayısı (arka plan hariç):\", len(classes))\nprint(\"Macro Dice (GT vs Pred): {:.4f}\".format(macro_dice))\nprint(\"Per-class Dice:\")\nfor c in classes:\n    print(\"  {:2d}: {}\".format(c, \"NaN\" if np.isnan(per_class[c]) else f\"{per_class[c]:.4f}\"))\n\n# ---------- GÖRSELLEŞTİRME ----------\n# Basit bir etiket renk haritası (0..13 arası için yeterli)\nimport matplotlib\ncmap = matplotlib.cm.get_cmap('tab20', 14)  # 14 farklı renk\n\ndef show_overlay(ax, base, mask, title):\n    if base is not None:\n        v = np.percentile(base, [1, 99])\n        ax.imshow(base, cmap='gray', vmin=v[0], vmax=v[1])\n        # maskeyi yarı saydam bindir\n        m = mask.copy()\n        m[m==0] = -1  # arkaplan görünmesin\n        im = ax.imshow(m, cmap=cmap, alpha=0.45, vmin=-1, vmax=13)\n    else:\n        im = ax.imshow(mask, cmap=cmap, vmin=0, vmax=13)\n    ax.set_title(title, fontsize=12)\n    ax.axis('off')\n    return im\n\nfig, axs = plt.subplots(1, 3 if img is not None else 2, figsize=(15, 5))\nif img is not None:\n    show_overlay(axs[0], img[z], np.zeros_like(gt[z]), \"Görüntü (z={})\".format(z))\n    show_overlay(axs[1], img[z], gt[z], \"GT maske\")\n    im = show_overlay(axs[2], img[z], pred_rs[z], \"Tahmin maske\")\nelse:\n    show_overlay(axs[0], None, gt[z], \"GT maske (z={})\".format(z))\n    im = show_overlay(axs[1], None, pred_rs[z], \"Tahmin maske\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-14T17:02:27.94156Z","iopub.execute_input":"2025-08-14T17:02:27.9419Z","iopub.status.idle":"2025-08-14T17:02:36.610564Z","shell.execute_reply.started":"2025-08-14T17:02:27.941873Z","shell.execute_reply":"2025-08-14T17:02:36.609665Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"****FOLD_1 BAŞLANGIÇ****","metadata":{}},{"cell_type":"code","source":"# ===== Ortam & Path Setup =====\nimport os\nfrom pathlib import Path\nimport inspect, re\nimport nnunetv2, torch\n\n# ---- nnU-Net pathleri\nRAW = \"/kaggle/working/nnUNet_raw\"\nPRE = \"/kaggle/working/nnUNet_preprocessed\"\nRES = \"/kaggle/working/nnUNet_results\"\nfor p in (RAW, PRE, RES):\n    Path(p).mkdir(parents=True, exist_ok=True)\n\nos.environ.update({\n    \"nnUNet_raw\": RAW,\n    \"nnUNet_preprocessed\": PRE,\n    \"nnUNet_results\": RES,\n    \"CUDA_VISIBLE_DEVICES\": \"0\",\n    \"PYTHONUNBUFFERED\": \"1\",\n    \"TORCH_COMPILE_DISABLE\": \"1\",\n    \"nnUNet_compile\": \"0\",\n    \"ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS\": \"2\",\n    \"OMP_NUM_THREADS\": \"2\",\n    \"OPENBLAS_NUM_THREADS\": \"2\",\n    \"MKL_NUM_THREADS\": \"2\",\n    \"NUMEXPR_NUM_THREADS\": \"2\",\n})\n\n# ---- Patch: TORCHINDUCTOR_COMPILE_THREADS string fix\nrt = Path(inspect.getfile(nnunetv2)).parent / \"run\" / \"run_training.py\"\ntxt = rt.read_text()\nfixed = re.sub(\n    r\"os\\.environ\\[\\s*['\\\"]TORCHINDUCTOR_COMPILE_THREADS['\\\"]\\s*\\]\\s*=\\s*1\",\n    \"os.environ['TORCHINDUCTOR_COMPILE_THREADS'] = \\\"1\\\"\",\n    txt\n)\nif fixed != txt:\n    rt.write_text(fixed)\n    print(\"[PATCH] TORCHINDUCTOR_COMPILE_THREADS -> '1'\")\n\nprint(f\"torch {torch.__version__} | cuda={torch.cuda.is_available()} | dev={(torch.cuda.get_device_name(0) if torch.cuda.is_available() else '-')}\")\nprint(\"nnunetv2:\", getattr(nnunetv2, \"__version__\", \"ok\"))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-17T18:38:16.81749Z","iopub.execute_input":"2025-08-17T18:38:16.818234Z","iopub.status.idle":"2025-08-17T18:38:20.149851Z","shell.execute_reply.started":"2025-08-17T18:38:16.818197Z","shell.execute_reply":"2025-08-17T18:38:20.148976Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ===== Fold-1 training + checkpoint temizleyici (best & latest hariç sil) =====\nimport os, time, threading, subprocess\nfrom pathlib import Path\n\n# ---- Sabitler (gerekirse değiştir)\nDATASET_ID   = \"100\"\nCONFIG       = \"3d_fullres\"\nFOLD         = \"1\"                      # fold_1\nTRAINER      = \"nnUNetTrainer\"\nRES          = Path(os.environ[\"nnUNet_results\"])\nMODEL_DIR    = RES / \"Dataset100_RSNAIA_CoW\" / f\"{TRAINER}__nnUNetPlans__{CONFIG}\"\nFOLD_DIR     = MODEL_DIR / f\"fold_{FOLD}\"\n\nFOLD_DIR.mkdir(parents=True, exist_ok=True)\nprint(f\"Model klasörü: {FOLD_DIR}\")\n\n# ---- Eğitim komutu\ncmd = [\n    \"python\",\"-u\",\"-m\",\"nnunetv2.run.run_training\",\n    DATASET_ID, CONFIG, FOLD\n]\nprint(\"[RUN]\", \" \".join(cmd))\n\n# ---- Checkpoint temizleyici: best + latest harici .pth'leri sil\ndef cleaner(stop_event):\n    kept = {\"checkpoint_best.pth\", \"checkpoint_latest.pth\"}\n    size_cache = {}\n    while not stop_event.is_set():\n        try:\n            if FOLD_DIR.exists():\n                # Aşırı agresif olmasın: yalnızca 2 dakikadan eski ve boyutu değişmeyen dosyaları sil\n                for p in FOLD_DIR.glob(\"checkpoint_*.pth\"):\n                    if p.name in kept: \n                        continue\n                    age = time.time() - p.stat().st_mtime\n                    size_prev = size_cache.get(p, None)\n                    size_now  = p.stat().st_size\n                    size_cache[p] = size_now\n                    if age > 120 and size_prev == size_now:\n                        try:\n                            p.unlink()\n                        except Exception:\n                            pass\n        except Exception:\n            pass\n        stop_event.wait(30)  # 30 sn'de bir kontrol\n\n# ---- Eğitim sürecini başlat + eşzamanlı temizleyici\nstop_evt = threading.Event()\nt = threading.Thread(target=cleaner, args=(stop_evt,), daemon=True)\nt.start()\n\nwant_prefixes = (\"Epoch \", \"Current learning rate:\", \"train_loss\", \"val_loss\", \"Yayy!\", \"Using device:\")\nlast_epoch = None\nt0 = time.time()\n\nproc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)\ntry:\n    for line in proc.stdout:\n        s = line.strip()\n        if s.startswith(\"Epoch \"):\n            try:\n                ep = int(s.split()[1])\n            except:\n                ep = None\n            if ep is None or ep != last_epoch:\n                last_epoch = ep\n                print(s)\n        elif s.startswith(want_prefixes):\n            print(s)\nexcept KeyboardInterrupt:\n    print(\"\\n[STOP] kullanıcı durdurdu, süreç sonlandırılıyor…\")\n    try: proc.terminate()\n    except: pass\n\nrc = proc.wait()\nstop_evt.set()\nt.join(timeout=2)\n\nprint(f\"\\n[EXIT] rc={rc} | elapsed={(time.time()-t0)/60:.1f} min\")\nprint(\"Kalan checkpoint'ler:\", [p.name for p in sorted(FOLD_DIR.glob('checkpoint_*.pth'))])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-17T18:38:25.309882Z","iopub.execute_input":"2025-08-17T18:38:25.31031Z","execution_failed":"2025-08-18T06:35:34.232Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}