{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":36363,"databundleVersionId":4050810,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q python-gdcm pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg pydicom","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:02:47.536489Z","iopub.execute_input":"2026-02-06T08:02:47.536744Z","iopub.status.idle":"2026-02-06T08:02:55.033429Z","shell.execute_reply.started":"2026-02-06T08:02:47.53672Z","shell.execute_reply":"2026-02-06T08:02:55.032322Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport os\nimport glob\nimport warnings\n\n# Налаштування\nwarnings.filterwarnings('ignore')\nsns.set_style(\"whitegrid\")\nplt.rcParams['figure.figsize'] = (12, 6)\n\n# Шляхи до даних\nBASE_PATH = '/kaggle/input/rsna-2022-cervical-spine-fracture-detection'\nTRAIN_CSV = f'{BASE_PATH}/train.csv'\nTRAIN_IMAGES_DIR = f'{BASE_PATH}/train_images'\n\n\n# 1. ЗАВАНТАЖЕННЯ ДАНИХ\n\nprint(\" 1. ЗАВАНТАЖЕННЯ ТАБЛИЦІ \")\n\nif os.path.exists(TRAIN_CSV):\n    df_train = pd.read_csv(TRAIN_CSV)\n    print(f\"Дані успішно завантажено. Розмір: {df_train.shape}\")\n    print(f\"Кількість унікальних пацієнтів: {df_train['StudyInstanceUID'].nunique()}\")\nelse:\n    print(f\"❌ ПОМИЛКА: Файл {TRAIN_CSV} не знайдено. Перевірте, чи додано датасет.\")\n    df_train = None\n\n\n# 2. ПОЯСНЮВАЛЬНИЙ АНАЛІЗ (EDA)\n\nif df_train is not None:\n    print(\"\\n 2. АНАЛІЗ ЗБАЛАНСОВАНОСТІ КЛАСІВ \")\n    \n    # 2.1. Загальний баланс (хворий / здоровий)\n    plt.figure(figsize=(8, 5))\n    ax = sns.countplot(data=df_train, x='patient_overall', palette='coolwarm')\n    plt.title('Баланс класів: Здорові (0) vs З переломом (1)')\n    \n    # Додаємо цифри на стовпчики\n    for p in ax.patches:\n        ax.annotate(f'{int(p.get_height())}', (p.get_x() + p.get_width() / 2., p.get_height()),\n                    ha='center', va='bottom')\n    plt.show()\n\n    # 2.2. Деталізація по хребцях (C1-C7)\n    cols = ['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7']\n    sums = df_train[cols].sum().sort_values(ascending=False)\n    \n    plt.figure(figsize=(10, 6))\n    sns.barplot(x=sums.index, y=sums.values, palette='viridis')\n    plt.title('Кількість переломів за типом хребця')\n    plt.ylabel('Кількість випадків')\n    plt.show()\n    \n    print(\"Статистика переломів:\")\n    print(sums)\n\n\n# 3. ВІЗУАЛІЗАЦІЯ ЗОБРАЖЕНЬ (DICOM)\n\nprint(\"\\n 3. ВІЗУАЛІЗАЦІЯ DICOM \")\n\ndef read_dcm(path):\n    \"\"\"Читає та обробляє DICOM файл\"\"\"\n    try:\n        dcm = pydicom.dcmread(path)\n        \n        # Отримання пікселів (тут раніше була помилка)\n        pixel_data = dcm.pixel_array\n        \n        # Корекція яскравості/контрасту (LUT) для кращої видимості\n        if 'VOILUTSequence' in dcm or 'WindowCenter' in dcm:\n            pixel_data = apply_voi_lut(pixel_data, dcm)\n            \n        # Нормалізація (Min-Max) для відображення як картинки\n        if np.max(pixel_data) != 0:\n            pixel_data = pixel_data - np.min(pixel_data)\n            pixel_data = pixel_data / np.max(pixel_data)\n            pixel_data = (pixel_data * 255).astype(np.uint8)\n            \n        return pixel_data\n    except Exception as e:\n        print(f\"Помилка читання {os.path.basename(path)}: {e}\")\n        return np.zeros((512, 512))\n\nif df_train is not None:\n    # Знаходимо пацієнта з переломом\n    patient_id = df_train[df_train['patient_overall'] == 1]['StudyInstanceUID'].iloc[0]\n    path_to_slices = os.path.join(TRAIN_IMAGES_DIR, patient_id)\n    \n    # Отримуємо всі файли та сортуємо їх по номерах (1.dcm, 2.dcm...)\n    slice_files = glob.glob(os.path.join(path_to_slices, \"*.dcm\"))\n    slice_files.sort(key=lambda x: int(os.path.basename(x).split('.')[0]))\n    \n    print(f\"Пацієнт ID: {patient_id}\")\n    print(f\"Кількість слайсів: {len(slice_files)}\")\n    \n    if len(slice_files) > 0:\n        # Показуємо 5 рівномірно вибраних зрізів\n        indices = np.linspace(0, len(slice_files)-1, 5, dtype=int)\n        \n        fig, axes = plt.subplots(1, 5, figsize=(20, 5))\n        for i, idx in enumerate(indices):\n            img = read_dcm(slice_files[idx])\n            \n            axes[i].imshow(img, cmap='bone')\n            axes[i].set_title(f\"Slice {idx}\")\n            axes[i].axis('off')\n        \n        plt.suptitle(f'КТ-скан шийного відділу (Пацієнт {patient_id})', fontsize=16)\n        plt.show()\n    else:\n        print(\"Зображень не знайдено.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:03:49.774068Z","iopub.execute_input":"2026-02-06T08:03:49.774661Z","iopub.status.idle":"2026-02-06T08:03:53.678196Z","shell.execute_reply.started":"2026-02-06T08:03:49.774619Z","shell.execute_reply":"2026-02-06T08:03:53.677194Z"}},"outputs":[],"execution_count":null}]}