{"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":[{"sourceType":"competition","sourceId":99552,"databundleVersionId":13851420},{"sourceType":"datasetVersion","sourceId":14731498,"datasetId":9413671,"databundleVersionId":15579483},{"sourceType":"modelInstanceVersion","sourceId":774110,"databundleVersionId":15931392,"modelInstanceId":591157,"modelId":603482},{"sourceType":"modelInstanceVersion","sourceId":773938,"databundleVersionId":15929470,"modelInstanceId":591018,"modelId":603365},{"sourceType":"modelInstanceVersion","sourceId":774112,"databundleVersionId":15931402,"modelInstanceId":591159,"modelId":603484},{"sourceType":"modelInstanceVersion","sourceId":773940,"databundleVersionId":15929484,"modelInstanceId":591020,"modelId":603367},{"sourceType":"modelInstanceVersion","sourceId":774115,"databundleVersionId":15931418,"modelInstanceId":591162,"modelId":603487},{"sourceType":"modelInstanceVersion","sourceId":773943,"databundleVersionId":15929491,"modelInstanceId":591023,"modelId":603369},{"sourceType":"modelInstanceVersion","sourceId":774117,"databundleVersionId":15931433,"modelInstanceId":591164,"modelId":603489},{"sourceType":"modelInstanceVersion","sourceId":773945,"databundleVersionId":15929501,"modelInstanceId":591024,"modelId":603370},{"sourceType":"modelInstanceVersion","sourceId":774119,"databundleVersionId":15931452,"modelInstanceId":591166,"modelId":603491},{"sourceType":"modelInstanceVersion","sourceId":773947,"databundleVersionId":15929514,"modelInstanceId":591026,"modelId":603372},{"sourceType":"modelInstanceVersion","sourceId":743184,"databundleVersionId":15601808,"modelInstanceId":567209,"modelId":579548}],"dockerImageVersionId":31090,"isInternetEnabled":false,"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\nimport os\n\n#for 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,"execution":{"iopub.status.busy":"2026-03-05T06:26:29.888609Z","iopub.execute_input":"2026-03-05T06:26:29.888842Z","iopub.status.idle":"2026-03-05T06:26:30.144213Z","shell.execute_reply.started":"2026-03-05T06:26:29.888823Z","shell.execute_reply":"2026-03-05T06:26:30.14346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, sys, shutil, copy\nfrom collections import Counter\n\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nfrom omegaconf import DictConfig\nimport glob\nimport pydoc\n\nsys.path.insert(0, '/kaggle/input/timm-1-0-20/timm-1.0.20/')\n\nimport pydicom\n\nimport torch\nimport timm\n\nimport kaggle_evaluation.rsna_inference_server\n\n\nprint(f'torch version: {torch.__version__}')\nprint(f'timm version: {timm.__version__}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:26:32.084436Z","iopub.execute_input":"2026-03-05T06:26:32.084996Z","iopub.status.idle":"2026-03-05T06:26:50.492554Z","shell.execute_reply.started":"2026-03-05T06:26:32.084973Z","shell.execute_reply":"2026-03-05T06:26:50.491825Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ID_COL = 'SeriesInstanceUID'\n\nLABEL_COLS = [\n    'Left Infraclinoid Internal Carotid Artery',\n    'Right Infraclinoid Internal Carotid Artery',\n    'Left Supraclinoid Internal Carotid Artery',\n    'Right Supraclinoid Internal Carotid Artery',\n    'Left Middle Cerebral Artery',\n    'Right Middle Cerebral Artery',\n    'Anterior Communicating Artery',\n    'Left Anterior Cerebral Artery',\n    'Right Anterior Cerebral Artery',\n    'Left Posterior Communicating Artery',\n    'Right Posterior Communicating Artery',\n    'Basilar Tip',\n    'Other Posterior Circulation',\n    'Aneurysm Present',\n]\n\nNUM_CLASSES = len(LABEL_COLS)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:22.211921Z","iopub.execute_input":"2026-03-05T06:27:22.212843Z","iopub.status.idle":"2026-03-05T06:27:22.217707Z","shell.execute_reply.started":"2026-03-05T06:27:22.212807Z","shell.execute_reply":"2026-03-05T06:27:22.216862Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"INPUT_VOLUME_CHANNELS = 3\nIN_CHANNELS = 3\n\nCROP_BACKBONE_MODEL_NAME = 'resnet18'\nCROP_DEPTH_SIZE = 48\nCROP_BACKBONE_CFG = DictConfig({\n    'target_type': 'timm.create_model',\n    'kwargs': {\n        'model_name': 'vit_small_plus_patch16_dinov3.lvd1689m',\n        'pretrained': False,\n        'in_chans': 3,\n        'global_pool': '',\n        'num_classes': 0,\n    },\n})\nCROP_INPUT_SIZE = [128, 128]\nCROP_MODEL_CHECKPOINT_FILE = \"/kaggle/input/vesselroibboxextractor-loss-00-20260129-153709/pytorch/default/1/best_loss_checkpoint_vesselroibboxextractor_00_20260129_153709.pth\"\n\nCLASSIFIER_BACKBONE_MODEL_NAME = 'resnet18'\nCLASSIFIER_INPUT_SIZE = [352, 352]\nCLASSIFIER_MODEL_CHECKPOINT_FILES = [\n    # best acc\n    \"/kaggle/input/models/wissunpower/diseasedetector-00-acc-20260224-172817/pytorch/default/1/best_acc_checkpoint_diseasedetector_00_20260224_172817.pth\",\n    \"/kaggle/input/models/wissunpower/diseasedetector-01-acc-20260226-150114/pytorch/default/1/best_acc_checkpoint_diseasedetector_01_20260226_150114.pth\",\n    \"/kaggle/input/models/wissunpower/diseasedetector-02-acc-20260228-035434/pytorch/default/1/best_acc_checkpoint_diseasedetector_02_20260228_035434.pth\",\n    \"/kaggle/input/models/wissunpower/diseasedetector-03-acc-20260301-225028/pytorch/default/1/best_acc_checkpoint_diseasedetector_03_20260301_225028.pth\",\n    \"/kaggle/input/models/wissunpower/diseasedetector-04-acc-20260303-172040/pytorch/default/1/best_acc_checkpoint_diseasedetector_04_20260303_172040.pth\",\n\n    # best loss\n    # \"/kaggle/input/models/wissunpower/diseasedetector-00-loss-20260224-172817/pytorch/default/1/best_loss_checkpoint_diseasedetector_00_20260224_172817.pth\",\n    # \"/kaggle/input/models/wissunpower/diseasedetector-01-loss-20260226-150114/pytorch/default/1/best_loss_checkpoint_diseasedetector_01_20260226_150114.pth\",\n    # \"/kaggle/input/models/wissunpower/diseasedetector-02-loss-20260228-035434/pytorch/default/1/best_loss_checkpoint_diseasedetector_02_20260228_035434.pth\",\n    # \"/kaggle/input/models/wissunpower/diseasedetector-03-loss-20260301-225028/pytorch/default/1/best_loss_checkpoint_diseasedetector_03_20260301_225028.pth\",\n    # \"/kaggle/input/models/wissunpower/diseasedetector-04-loss-20260303-172040/pytorch/default/1/best_loss_checkpoint_diseasedetector_04_20260303_172040.pth\",\n]\n\nPREPROCESS_CROP_OPT = DictConfig({\n    'enable': False,\n    'info_file_path': '',\n})\nPREPROCESS_RESIZE_OPT = DictConfig({\n    'enable': False,\n    'target_shape': [352, 352],\n    'mode': 'bilinear',\n})\n\nBATCH_SIZE = 16","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:31.678231Z","iopub.execute_input":"2026-03-05T06:27:31.67872Z","iopub.status.idle":"2026-03-05T06:27:31.685879Z","shell.execute_reply.started":"2026-03-05T06:27:31.678694Z","shell.execute_reply":"2026-03-05T06:27:31.685132Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DICOMToNPYPreprocessor:\n    def __init__(self\n                 , crop: DictConfig\n                 , resize: DictConfig\n                 ):\n        self.crop_opt = crop\n        self.resize_opt = resize\n\n        if self.crop_opt.enable:\n            self.crop_info = np.load(crop.info_file_path, allow_pickle=True).item()\n\n    def __call__(self, dcm_set_path: str) -> tuple[np.ndarray, list]:\n        files = np.array(glob.glob(os.path.join(dcm_set_path, '*.dcm')))\n\n        dcms = [pydicom.dcmread(file) for file in files]\n\n        shapes = [(d.Rows, d.Columns) for d in dcms]\n        most_common_shape = Counter(shapes).most_common(1)[0][0]\n        \n        valid_data = []\n        for d, file in zip(dcms, files):\n            if (d.Rows, d.Columns) == most_common_shape:\n                valid_data.append([d, file])\n        \n        if len(valid_data) > 1:\n            valid_data.sort(key=lambda x: float(x[0].ImagePositionPatient[2]))\n        \n        #volume = np.stack([dcm.pixel_array for dcm in valid_dcms])\n        \n        #t = time.time()\n        volume = np.stack([dcm[0].pixel_array for dcm in valid_data])\n        \n        if volume.shape[0] == 1:\n            volume = volume[0]\n            valid_data = [valid_data[0]] * volume.shape[0]\n        \n        if self.crop_opt.enable:\n            series_uid = os.path.basename(dcm_set_path)\n            height, width = volume.shape[-2:]\n            x1, x2, y1, y2 = self.crop_info[series_uid]\n            volume = volume[:\n                      , int(y1 * height * 0.9):int(y2 * height * 1.1)\n                      , int(x1 * width * 0.9):int(x2 * width * 1.1)]\n\n        if self.resize_opt.enable:\n            volume = torch.from_numpy(volume.astype(np.float32)).unsqueeze(0)\n            volume = torch.nn.functional.interpolate(volume, (self.resize_opt.target_shape[0], self.resize_opt.target_shape[1])\n                                                 , mode=self.resize_opt.mode, align_corners=False)\n            volume = volume.squeeze(0).numpy()\n        \n        return volume, valid_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:38.134194Z","iopub.execute_input":"2026-03-05T06:27:38.134522Z","iopub.status.idle":"2026-03-05T06:27:38.147325Z","shell.execute_reply.started":"2026-03-05T06:27:38.134498Z","shell.execute_reply":"2026-03-05T06:27:38.146323Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class VesselROIBBoxExtractor(torch.nn.Module):\n    def __init__(self\n                 , depth_size: int\n                 , backbone: DictConfig):\n        super(VesselROIBBoxExtractor, self).__init__()\n\n        backbone_type = pydoc.locate(backbone.target_type)\n        self.backbone = backbone_type(**backbone.kwargs)\n\n        num_features = self.backbone.num_features\n\n        self.head = torch.nn.Linear(num_features * depth_size // backbone.kwargs.in_chans, 4)\n        \n        gain = torch.nn.init.calculate_gain('linear')\n        torch.nn.init.xavier_uniform_(self.head.weight, gain)\n        self.head.bias.data.fill_(0)\n    \n    def forward(self, volumes: torch.Tensor) -> torch.Tensor:\n        if 4 == len(volumes.shape):\n            volumes.unsqueeze(0)\n        \n        batch_size, num_groups, channels, height, width = volumes.shape\n\n        volumes = volumes.reshape(batch_size * num_groups, channels, height, width)\n        features = self.backbone(volumes)\n\n        features = features.mean(1)\n\n        features = features.reshape(batch_size, num_groups, -1)\n        features = features.flatten(1, 2)\n\n        logits = self.head(features)\n\n        logits = logits.sigmoid()\n\n        return logits\n    \n    @torch.no_grad()\n    def inference(self, volumes: torch.Tensor) -> torch.Tensor:\n        if 4 == len(volumes.shape):\n            volumes = volumes.unsqueeze(0)\n        \n        predict = self.forward(volumes)\n        \n        return predict","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:41.218011Z","iopub.execute_input":"2026-03-05T06:27:41.218568Z","iopub.status.idle":"2026-03-05T06:27:41.225055Z","shell.execute_reply.started":"2026-03-05T06:27:41.218543Z","shell.execute_reply":"2026-03-05T06:27:41.224493Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DiseaseDetector(torch.nn.Module):\n    def __init__(self\n                 , num_classes: int\n                 , backbone\n                 ):\n        super(DiseaseDetector, self).__init__()\n\n        self.num_classes = num_classes\n        self.backbone = backbone\n\n        num_features = self.backbone.num_features\n\n        self.avg_pool = torch.nn.AdaptiveAvgPool2d(1)\n\n        self.head = torch.nn.Linear(num_features, self.num_classes)\n        \n        gain = torch.nn.init.calculate_gain('linear')\n        torch.nn.init.xavier_uniform_(self.head.weight, gain)\n        self.head.bias.data.fill_(0)\n    \n    def forward(self, images: torch.Tensor) -> torch.Tensor:\n        features = self.backbone(images)\n\n        if len(features.shape) == 3:\n            features = features.mean(1)\n        elif len(features.shape) > 3:\n            features = self.avg_pool(features).flatten(1, 3)\n\n        logits = self.head(features)\n\n        return logits\n    \n    @torch.no_grad()\n    def inference(self, image: torch.Tensor) -> torch.Tensor:\n        if 3 == len(image.shape):\n            image = image.unsqueeze(0)\n        \n        predict = self.forward(image)\n        \n        return predict.sigmoid()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:47.988974Z","iopub.execute_input":"2026-03-05T06:27:47.989805Z","iopub.status.idle":"2026-03-05T06:27:47.995946Z","shell.execute_reply.started":"2026-03-05T06:27:47.989769Z","shell.execute_reply":"2026-03-05T06:27:47.995405Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else 'cpu')\nprint(f'device: {device}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:50.620005Z","iopub.execute_input":"2026-03-05T06:27:50.620816Z","iopub.status.idle":"2026-03-05T06:27:50.919384Z","shell.execute_reply.started":"2026-03-05T06:27:50.620781Z","shell.execute_reply":"2026-03-05T06:27:50.918612Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"crop_model = VesselROIBBoxExtractor(depth_size=CROP_DEPTH_SIZE, backbone=CROP_BACKBONE_CFG)\ncrop_model.load_state_dict(torch.load(CROP_MODEL_CHECKPOINT_FILE, map_location='cpu'))\ncrop_model = crop_model.to(device)\ncrop_model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:27:56.178969Z","iopub.execute_input":"2026-03-05T06:27:56.179555Z","iopub.status.idle":"2026-03-05T06:27:57.619389Z","shell.execute_reply.started":"2026-03-05T06:27:56.17953Z","shell.execute_reply":"2026-03-05T06:27:57.618804Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"classifier_models = []\n\nfor model_checkpoint_file in CLASSIFIER_MODEL_CHECKPOINT_FILES:\n    classifier_backbone_model = timm.create_model(CLASSIFIER_BACKBONE_MODEL_NAME, pretrained=False, in_chans=IN_CHANNELS, global_pool='', num_classes=0)\n    # classifier_backbone_model\n    \n    classifier_model = DiseaseDetector(num_classes=NUM_CLASSES, backbone=classifier_backbone_model)\n    classifier_model.load_state_dict(torch.load(model_checkpoint_file, map_location='cpu'))\n    classifier_model = classifier_model.to(device)\n    # classifier_model\n\n    classifier_models.append(copy.deepcopy(classifier_model))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:01.043069Z","iopub.execute_input":"2026-03-05T06:28:01.043914Z","iopub.status.idle":"2026-03-05T06:28:03.35189Z","shell.execute_reply.started":"2026-03-05T06:28:01.043889Z","shell.execute_reply":"2026-03-05T06:28:03.351336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preprocessor = DICOMToNPYPreprocessor(crop=PREPROCESS_CROP_OPT, resize=PREPROCESS_RESIZE_OPT)\npreprocessor","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:04.659829Z","iopub.execute_input":"2026-03-05T06:28:04.660595Z","iopub.status.idle":"2026-03-05T06:28:04.664955Z","shell.execute_reply.started":"2026-03-05T06:28:04.660569Z","shell.execute_reply":"2026-03-05T06:28:04.664256Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def crop_preprocessing(volume):\n    \n    volume = volume[np.linspace(0, len(volume)-1, CROP_DEPTH_SIZE).astype(np.int16)]\n    \n    volume = volume.reshape(CROP_DEPTH_SIZE//IN_CHANNELS, IN_CHANNELS, volume.shape[1], volume.shape[2])\n        \n    volume = torch.as_tensor((volume - volume.min()) / (volume.max() - volume.min())).float()\n    \n    volume = torch.nn.functional.interpolate(volume, CROP_INPUT_SIZE, mode='bilinear')\n    \n    return volume","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:09.721Z","iopub.execute_input":"2026-03-05T06:28:09.721716Z","iopub.status.idle":"2026-03-05T06:28:09.726414Z","shell.execute_reply.started":"2026-03-05T06:28:09.721691Z","shell.execute_reply":"2026-03-05T06:28:09.725498Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def crop_predict(volume):\n    \n    volume = crop_preprocessing(volume)\n    volume = volume.unsqueeze(0)\n    \n    #config.volume = volume\n\n    crop_model.eval()\n\n    with torch.no_grad():\n\n        volume = volume.to(device)\n        \n        with torch.autocast(device_type=str(device)):\n            logits = crop_model(volume)\n        outputs = logits.float().detach().cpu().numpy()\n    \n    return outputs[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:10.817211Z","iopub.execute_input":"2026-03-05T06:28:10.817717Z","iopub.status.idle":"2026-03-05T06:28:10.82226Z","shell.execute_reply.started":"2026-03-05T06:28:10.817695Z","shell.execute_reply":"2026-03-05T06:28:10.821426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def bin_preprocessing(volume: np.ndarray) -> torch.Tensor:\n    volume = torch.as_tensor(volume).to(torch.float32)\n\n    D = volume.shape[0]\n\n    volume_last = torch.stack([volume[i-2] if i-2>-1 else volume[i] for i in range(D)])\n    volume_next = torch.stack([volume[i+2] if i+2<D else volume[i] for i in range(D)])\n    #volume_next = volume_last #Bug in training, to be corrected further in training\n    \n    volume = torch.stack([volume_last, volume, volume_next], 1)\n\n    d = volume.shape[0]\n    vmin = volume.view(d, -1).min(dim=1).values.view(d, 1, 1, 1)\n    vmax = volume.view(d, -1).max(dim=1).values.view(d, 1, 1, 1)\n    volume = ((volume - vmin) / (vmax - vmin + 1e-8)).float()\n    \n    volume = torch.nn.functional.interpolate(volume, CLASSIFIER_INPUT_SIZE, mode='bilinear')\n\n    return volume","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:12.169784Z","iopub.execute_input":"2026-03-05T06:28:12.170043Z","iopub.status.idle":"2026-03-05T06:28:12.175993Z","shell.execute_reply.started":"2026-03-05T06:28:12.170022Z","shell.execute_reply":"2026-03-05T06:28:12.175472Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def bin_predict(volume: np.ndarray) -> np.ndarray:\n    \n    volume = bin_preprocessing(volume)\n    \n    with torch.no_grad():\n        total_outputs = []\n\n        for classifier_model in classifier_models:\n            classifier_model.eval()\n            \n            outputs = []\n            \n            for i in range(0, volume.shape[0], BATCH_SIZE):\n                start_idx = i\n                end_idx = min(i + BATCH_SIZE, volume.shape[0])\n                batch_images = volume[start_idx:end_idx]\n                \n                batch_images = batch_images.to(device).float()\n                \n                with torch.autocast(device_type=str(device)):\n                    logits = classifier_model(batch_images)\n                \n                outs = logits.float().sigmoid().detach().cpu().numpy()\n                \n                outputs.extend(outs)\n            \n            outputs = np.stack(outputs)\n\n            total_outputs.append(outputs)\n        \n        total_outputs = np.stack(total_outputs).mean(0)\n\n    return total_outputs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:18.434281Z","iopub.execute_input":"2026-03-05T06:28:18.434545Z","iopub.status.idle":"2026-03-05T06:28:18.44033Z","shell.execute_reply.started":"2026-03-05T06:28:18.434525Z","shell.execute_reply":"2026-03-05T06:28:18.439555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict(series_path: str) -> pl.DataFrame | pd.DataFrame:\n\n    series_uid = os.path.basename(series_path)\n\n    try:\n        volume, valid_data = preprocessor(series_path)\n\n        x1, x2, y1, y2 = crop_predict(volume)\n        \n        height, width = volume.shape[-2:]\n        volume = volume[:, int(y1*height*0.9):int(y2*height*1.1), int(x1*width*0.9):int(x2*width*1.1)]\n\n        predictions = bin_predict(volume=volume)\n\n        final_pred = predictions.max(0)\n\n        result_df = pl.DataFrame(\n            data=[[series_uid] + final_pred.tolist()],\n            schema=[ID_COL, *LABEL_COLS],\n            orient='row'\n        )\n    except Exception as e:\n        # Return a fallback dataframe with the correct schema\n        result_df = pl.DataFrame(\n            data=[[series_uid] + [0.1] * len(LABEL_COLS)],\n            schema=[ID_COL, *LABEL_COLS],\n            orient='row'\n        )\n    finally:\n        # This code is required to prevent \"out of disk space\" and \"directory not empty\" errors.\n        # It deletes the shared folder and then immediately recreates it, ensuring it's\n        # empty and ready for the next prediction.\n\n        # shared_dir = '/kaggle/shared'\n        shared_dir = './shared'\n        shutil.rmtree(shared_dir, ignore_errors=True)\n        os.makedirs(shared_dir, exist_ok=True)\n    \n    return result_df.drop(ID_COL)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:24.442368Z","iopub.execute_input":"2026-03-05T06:28:24.443069Z","iopub.status.idle":"2026-03-05T06:28:24.448945Z","shell.execute_reply.started":"2026-03-05T06:28:24.443044Z","shell.execute_reply":"2026-03-05T06:28:24.448335Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = predict('/kaggle/input/rsna-intracranial-aneurysm-detection/series/1.2.826.0.1.3680043.8.498.10035643165968342618460849823699311381')\nresults.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:25.756063Z","iopub.execute_input":"2026-03-05T06:28:25.756344Z","iopub.status.idle":"2026-03-05T06:28:34.817843Z","shell.execute_reply.started":"2026-03-05T06:28:25.756323Z","shell.execute_reply":"2026-03-05T06:28:34.817245Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inference_server = kaggle_evaluation.rsna_inference_server.RSNAInferenceServer(predict)\n\nif os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n    inference_server.serve()\nelse:\n    inference_server.run_local_gateway()\n    display(pl.read_parquet('/kaggle/working/submission.parquet'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:28:46.229807Z","iopub.execute_input":"2026-03-05T06:28:46.230279Z","iopub.status.idle":"2026-03-05T06:29:14.899974Z","shell.execute_reply.started":"2026-03-05T06:28:46.230256Z","shell.execute_reply":"2026-03-05T06:29:14.899264Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for dirname, _, filenames in os.walk('./'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:29:29.043197Z","iopub.execute_input":"2026-03-05T06:29:29.043478Z","iopub.status.idle":"2026-03-05T06:29:29.048009Z","shell.execute_reply.started":"2026-03-05T06:29:29.043451Z","shell.execute_reply":"2026-03-05T06:29:29.047453Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport subprocess\nfrom IPython.display import FileLink, display\n\ndef download_file(path, download_file_name):\n    os.chdir('/kaggle/working/')\n    zip_name = f\"/kaggle/working/{download_file_name}.zip\"\n    command = f\"zip {zip_name} {path} -r\"\n    result = subprocess.run(command, shell=True, capture_output=True, text=True)\n    if result.returncode != 0:\n        print(\"Unable to run zip command!\")\n        print(result.stderr)\n        return\n    display(FileLink(f'{download_file_name}.zip'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:29:33.808979Z","iopub.execute_input":"2026-03-05T06:29:33.809675Z","iopub.status.idle":"2026-03-05T06:29:33.814038Z","shell.execute_reply.started":"2026-03-05T06:29:33.809649Z","shell.execute_reply":"2026-03-05T06:29:33.813377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"download_file('./submission.parquet', 'submission')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T06:29:36.153354Z","iopub.execute_input":"2026-03-05T06:29:36.153632Z","iopub.status.idle":"2026-03-05T06:29:36.171621Z","shell.execute_reply.started":"2026-03-05T06:29:36.153609Z","shell.execute_reply":"2026-03-05T06:29:36.170901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}