{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"}],"dockerImageVersionId":30786,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport cv2\nimport tensorflow as tf\nfrom sklearn.model_selection import KFold\nfrom tensorflow.keras import layers, models\nfrom glob import glob\n\n# Configuration Parameters\nIMG_SIZE = [512, 512]\nIN_CHANS = 30\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\nBATCH_SIZE = 1\n\n# Define paths\nrd = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification'\nOUTPUT_DIR = '/kaggle/working/'\n\n# Read CSV files\ndf = pd.read_csv(f'{rd}/test_series_descriptions.csv')\nstudy_ids = df['study_id'].unique()\nsample_sub = pd.read_csv(f'{rd}/sample_submission.csv')\nLABELS = list(sample_sub.columns[1:])\nCONDITIONS = ['spinal_canal_stenosis', 'left_neural_foraminal_narrowing', 'right_neural_foraminal_narrowing', 'left_subarticular_stenosis', 'right_subarticular_stenosis']\nLEVELS = ['l1_l2', 'l2_l3', 'l3_l4', 'l4_l5', 'l5_s1']\n\n# Helper Functions\ndef read_dcm_image(file_path):\n    dicom_data = pydicom.dcmread(file_path)\n    image = dicom_data.pixel_array\n    image = (image - np.min(image)) / (np.max(image) - np.min(image) + 1e-6) * 255\n    image_resized = cv2.resize(image, (IMG_SIZE[0], IMG_SIZE[1]))\n    return image_resized.astype(np.uint8)\n\ndef get_image_paths(study_id, series_desc):\n    series_paths = df[df['study_id'] == study_id][df['series_description'] == series_desc]['series_id']\n    image_files = []\n    for series_id in series_paths:\n        series_images = glob(f'{rd}/test_images/{study_id}/{series_id}/*.dcm')\n        image_files.extend(sorted(series_images))\n    return image_files\n\n# Dataset Class\nclass RSNA24TestDataset(tf.keras.utils.Sequence):\n    def __init__(self, study_ids, batch_size, transform=None):\n        self.study_ids = study_ids\n        self.batch_size = batch_size\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.study_ids)\n\n    def __getitem__(self, idx):\n        study_id = self.study_ids[idx]\n        # Create an empty array with the correct dimensions (batch_size, height, width, channels)\n        x = np.zeros((self.batch_size, IMG_SIZE[0], IMG_SIZE[1], IN_CHANS), dtype=np.uint8)\n\n        \n        # Load Sagittal T1 images\n        allimgs_st1 = get_image_paths(study_id, 'Sagittal T1')\n        if len(allimgs_st1) > 0:\n            for j, img_path in enumerate(allimgs_st1[:10]):\n                img = read_dcm_image(img_path)\n                # Assign the image to the first batch index \n                x[0, ..., j] = img\n        \n        # Load Sagittal T2 images\n        allimgs_st2 = get_image_paths(study_id, 'Sagittal T2/STIR')\n        if len(allimgs_st2) > 0:\n            for j, img_path in enumerate(allimgs_st2[:10]):\n                img = read_dcm_image(img_path)\n                x[0, ..., j + 10] = img\n\n        # Load Axial T2 images\n        allimgs_at2 = get_image_paths(study_id, 'Axial T2')\n        if len(allimgs_at2) > 0:\n            for j, img_path in enumerate(allimgs_at2[:10]):\n                img = read_dcm_image(img_path)\n                x[0, ..., j + 20] = img\n        \n        if self.transform:\n            x = self.transform(x)\n        \n        return x, study_id\n\n\n# Model Definition\ndef build_model(input_shape, num_classes):\n    inputs = layers.Input(shape=input_shape)\n    \n    # Create a base DenseNet model\n    base_model = tf.keras.applications.DenseNet201(include_top=False, input_tensor=inputs, weights=None) # Set weights to None\n    x = base_model.output\n    x = layers.GlobalAveragePooling2D()(x)\n    \n    # Add output layer for classification\n    outputs = layers.Dense(num_classes, activation='softmax')(x)\n    \n    model = models.Model(inputs, outputs)\n    return model\n\n# Compile the model\nmodel = build_model((IMG_SIZE[0], IMG_SIZE[1], IN_CHANS), N_CLASSES)\nmodel.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n# Inference\ndef predict_study(dataset, model):\n    predictions = []\n    for batch_x, study_id in dataset:\n        preds = model.predict(batch_x)\n        predictions.append(preds)\n    return np.concatenate(predictions)\n\n# Dataset and DataLoader setup\ntest_dataset = RSNA24TestDataset(study_ids, BATCH_SIZE)\npredictions = predict_study(test_dataset, model)\n\n# Generate submission\nsub = pd.DataFrame()\nsub['row_id'] = [f\"{study_id}_{cond}_{level}\" for study_id in study_ids for cond in CONDITIONS for level in LEVELS]\n\n# Reshape predictions to match the number of LABELS\npredictions = predictions.reshape(-1, len(LABELS))\n\nsub[LABELS] = predictions\nsub.to_csv('submission.csv', index=False)\n\npd.read_csv('submission.csv').head()","metadata":{"execution":{"iopub.status.busy":"2024-10-06T10:30:56.980943Z","iopub.execute_input":"2024-10-06T10:30:56.981451Z","iopub.status.idle":"2024-10-06T10:31:30.520711Z","shell.execute_reply.started":"2024-10-06T10:30:56.981401Z","shell.execute_reply":"2024-10-06T10:31:30.519133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}