{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":9549659,"sourceType":"datasetVersion","datasetId":5818458},{"sourceId":9552062,"sourceType":"datasetVersion","datasetId":5820093},{"sourceId":9552264,"sourceType":"datasetVersion","datasetId":5820241},{"sourceId":193417638,"sourceType":"kernelVersion"}],"dockerImageVersionId":30747,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Siamese Network Inference for Axial T2 Series","metadata":{}},{"cell_type":"markdown","source":"For a more details of the method see:\nhttps://www.kaggle.com/competitions/rsna-2024-lumbar-spine-degenerative-classification/discussion/539686","metadata":{}},{"cell_type":"markdown","source":"# Axial T2 Level/Key Point Patch Extractor (YOLOv9)","metadata":{}},{"cell_type":"code","source":"!pip install -q --no-index --find-links /kaggle/input/ultralytics ultralytics","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-12T11:32:44.214583Z","iopub.execute_input":"2024-10-12T11:32:44.214854Z","iopub.status.idle":"2024-10-12T11:32:56.388800Z","shell.execute_reply.started":"2024-10-12T11:32:44.214832Z","shell.execute_reply":"2024-10-12T11:32:56.387731Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport re\nimport time\nimport random\nimport glob\nimport pandas as pd\nimport numpy as np\nimport cv2\nimport pydicom\nimport torch\nimport timm\n\nimport pandas as pd\nimport numpy as np\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport matplotlib.pyplot as plt\n\nfrom tqdm import tqdm\nfrom pathlib import Path\nfrom pprint import pprint\nfrom PIL import Image\nfrom torch.utils.data import Dataset, DataLoader, Subset\nfrom collections import defaultdict\nfrom torchvision import transforms\nfrom collections import defaultdict\nfrom pydicom.pixel_data_handlers.util import (\n    apply_voi_lut,\n    apply_color_lut,\n    apply_modality_lut,\n)\nfrom ultralytics import YOLO","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:32:56.390362Z","iopub.execute_input":"2024-10-12T11:32:56.390700Z","iopub.status.idle":"2024-10-12T11:32:56.399036Z","shell.execute_reply.started":"2024-10-12T11:32:56.390668Z","shell.execute_reply":"2024-10-12T11:32:56.398045Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"RSNA_ROOT_DIR = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification\"\n\nLEVELS = ['l1_l2', 'l2_l3', 'l3_l4', 'l4_l5', 'l5_s1']\nCLASSES = ['Normal_Mild', 'Moderate', 'Severe']\n\nDATASET_TYPE = \"test\"\nTEST_SERIES_DESCRIPTIONS_CSV = f\"{DATASET_TYPE}_series_descriptions.csv\"\nTEST_IMAGES_ROOT_DIR = os.path.join(RSNA_ROOT_DIR, f\"{DATASET_TYPE}_images\")\nTEST_DF = pd.read_csv(os.path.join(RSNA_ROOT_DIR, TEST_SERIES_DESCRIPTIONS_CSV))\nDEBUG = len(TEST_DF.study_id.unique()) == 1\n\nYOLO_PT_AXIAL_T2_PATH = \"/kaggle/input/rsna24-pt-yolo-axial-t2/best.pt\"    \nSIAMESE_AXIAL_T2_REFIMG_ROOT_DIR = '/kaggle/input/rsna24-refimages-axial-t2-saimese/refimages'\nSIAMESE_AXIAL_T2_PT_LIST = sorted(glob.glob('/kaggle/input/rsna24-pt-axial-t2-siamese/to_upload/*.pth'))\n\nPATCH_IMAGES_DIR = \"/kaggle/working/patches\"\nos.makedirs(PATCH_IMAGES_DIR, exist_ok=True)\naxial_t2_dir = os.path.join(PATCH_IMAGES_DIR, \"Axial_T2\")\nos.makedirs(axial_t2_dir, exist_ok=True)\n\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-12T11:32:56.400085Z","iopub.execute_input":"2024-10-12T11:32:56.400335Z","iopub.status.idle":"2024-10-12T11:32:56.416580Z","shell.execute_reply.started":"2024-10-12T11:32:56.400313Z","shell.execute_reply":"2024-10-12T11:32:56.415779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def convert_to_dict(d):\n    from collections import defaultdict\n    if isinstance(d, defaultdict):\n        d = {k: convert_to_dict(v) for k, v in d.items()}\n    return d\n\ndef atoi(text):\n    return int(text) if text.isdigit() else text\n\ndef natural_keys(text):    \n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]\n\ndef convert_dicom_to_image(dcm_path):\n    dicom = pydicom.dcmread(dcm_path)    \n    arr = dicom.pixel_array\n    if dicom.PhotometricInterpretation == \"PALETTE COLOR\":\n        arr = apply_color_lut(arr, dicom)\n    arr = apply_modality_lut(arr, dicom)\n    arr = apply_voi_lut(arr, dicom, index=0)\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        arr = np.amax(arr) - arr\n\n    lower, upper = np.percentile(arr, (1, 99))\n    arr = np.clip(arr, lower, upper)\n    arr = arr - np.min(arr)\n    arr = arr / np.max(arr)\n    arr = (arr * 255).astype(np.uint8)\n    return arr\n\ndef visualize_detections(image, p0, p1, level, side):\n    image_rgb = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)\n    image_rgb = cv2.rectangle(image_rgb, p0, p1, color=(10, 10, 200), thickness=2)    \n    plt.imshow(image_rgb)\n    text = f\"{level}_{side}\"\n    x_position = 50  # X coordinate for text\n    y_position = 50  # Y coordinate for text\n    plt.text(x_position, y_position, text, color='red', fontsize=15, \n             fontweight='bold', backgroundcolor='white')    \n    plt.axis('off')  # To hide axis labels\n    plt.show()                                ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-10-12T11:32:56.417949Z","iopub.execute_input":"2024-10-12T11:32:56.418336Z","iopub.status.idle":"2024-10-12T11:32:56.430560Z","shell.execute_reply.started":"2024-10-12T11:32:56.418306Z","shell.execute_reply":"2024-10-12T11:32:56.429607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_axial_t2_patches():    \n    detector = YOLO(YOLO_PT_AXIAL_T2_PATH)    \n    study_ids = TEST_DF.study_id.unique()    \n    for study_id in tqdm(study_ids):\n        df = TEST_DF[(TEST_DF.study_id == study_id) & (TEST_DF.series_description == \"Axial T2\")]\n        if len(df):\n            axial_t2_series_ids = df[df.series_description == \"Axial T2\"]['series_id'].unique()\n            for series_id in axial_t2_series_ids:\n                read_dir = os.path.join(RSNA_ROOT_DIR, TEST_IMAGES_ROOT_DIR, str(study_id), str(series_id))\n                dcm_paths = sorted(glob.glob(os.path.join(read_dir, \"*.dcm\")), key=natural_keys)            \n                dcm_conf_per_class = defaultdict(list)\n                dcm_conf_per_class_print = defaultdict(lambda: defaultdict(list))\n                for dcm_path in dcm_paths:\n                    image = convert_dicom_to_image(dcm_path)\n                    detection = detector.predict(source=cv2.cvtColor(image, cv2.COLOR_GRAY2RGB), verbose=False)        \n                    for row in detection[0].boxes.data:\n                        row = row.cpu().numpy()\n                        class_id = int(row[-1])\n                        dcm_conf_per_class[class_id].append(\n                            # x0     y0      x1      y1     confidence\n                            (row[0], row[1], row[2], row[3], row[4], image, int(Path(dcm_path).stem))\n                        )\n                dcm_conf_per_class = convert_to_dict(dcm_conf_per_class)\n\n                sorted_dcm = defaultdict(lambda: defaultdict())\n                for class_id in dcm_conf_per_class.keys():\n                    if len(dcm_conf_per_class[class_id]):\n                        dcm_conf_per_class[class_id] = sorted(dcm_conf_per_class[class_id], key=lambda x: x[4])\n                        side = \"left\" if class_id < 5 else \"right\"\n                        level = LEVELS[class_id % 5]\n                        sorted_dcm[level][side] = dcm_conf_per_class[class_id]\n\n                best_dcm = defaultdict(lambda: defaultdict())            \n                for level in sorted_dcm.keys():\n                    if 'left' in sorted_dcm[level]:\n                        best_dcm[level]['left'] = sorted_dcm[level]['left'][-1]\n\n                    if 'right' in sorted_dcm[level]:\n                        best_dcm[level]['right'] = sorted_dcm[level]['right'][-1]\n\n                    if 'left' in sorted_dcm[level] and 'right' in sorted_dcm[level]:\n                        if sorted_dcm[level]['left'][-1][4] > 0.5 and sorted_dcm[level]['right'][-1][4] < 0.5: # higher confidence at left!\n                            best_dcm_number = sorted_dcm[level]['left'][-1][-1]\n                            found = False\n                            for i in range(len(sorted_dcm[level]['right'])):\n                                if sorted_dcm[level]['right'][i][-1] == best_dcm_number:\n                                    found = True\n                                    best_dcm[level]['right'] = sorted_dcm[level]['right'][i]                                                                \n                            if not found:\n                                # take x0, y0, x1, y1 from the best right, but the image and the dcm_number from the best left, confidence is not important anymore!\n                                best_dcm[level]['right'] = (best_dcm[level]['right'][0], best_dcm[level]['right'][1], best_dcm[level]['right'][2], best_dcm[level]['right'][3], 0, sorted_dcm[level]['left'][-1][-2], sorted_dcm[level]['left'][-1][-1])\n                    if 'left' in sorted_dcm[level] and 'right' in sorted_dcm[level]:\n                        if sorted_dcm[level]['left'][-1][4] < 0.5 and sorted_dcm[level]['right'][-1][4] > 0.5:\n                            best_dcm_number = sorted_dcm[level]['right'][-1][-1]\n                            found = False\n                            for i in range(len(sorted_dcm[level]['left'])):\n                                if sorted_dcm[level]['left'][i][-1] == best_dcm_number:\n                                    found = True\n                                    best_dcm[level]['left'] = sorted_dcm[level]['left'][i]\n                            if not found:\n                                # take x0, y0, x1, y1 from the best left, but the image and the dcm_number from the best right, confidence is not important anymore!\n                                best_dcm[level]['left'] = (best_dcm[level]['left'][0], best_dcm[level]['left'][1], best_dcm[level]['left'][2], best_dcm[level]['left'][3], 0, sorted_dcm[level]['right'][-1][-2], sorted_dcm[level]['right'][-1][-1])\n\n                for level in best_dcm.keys():\n                    for side in best_dcm[level].keys():                    \n                        data = best_dcm[level][side]\n                        if DEBUG: print(level, side, data[0], data[1], data[2], data[3], data[4], data[-1])\n                        x0, y0 = data[0], data[1]\n                        x1, y1 = data[2], data[3]\n                        xc = int(np.round((x0 + x1) / 2.0))\n                        yc = int(np.round((y0 + y1) / 2.0))\n                        width = data[5].shape[1]\n                        patch_size_half = int(np.round(0.1 * width / 2))\n                        x0, y0 = int(np.round(xc)) - patch_size_half, int(np.round(yc)) - patch_size_half\n                        x1, y1 = int(np.round(xc)) + patch_size_half, int(np.round(yc)) + patch_size_half                \n                        target_dir = os.path.join(axial_t2_dir, str(study_id), level)\n                        os.makedirs(target_dir, exist_ok=True)\n                        png_path = os.path.join(target_dir, f\"{study_id}_{series_id}_{side}_{data[6]:04}.png\")\n                        cv2.imwrite(png_path, data[5][y0:y1, x0:x1])                        \n                        if DEBUG: visualize_detections(data[5], (x0, y0), (x1, y1), level, side)\n","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:32:56.432219Z","iopub.execute_input":"2024-10-12T11:32:56.432576Z","iopub.status.idle":"2024-10-12T11:32:56.461985Z","shell.execute_reply.started":"2024-10-12T11:32:56.432551Z","shell.execute_reply":"2024-10-12T11:32:56.461196Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"extract_axial_t2_patches()","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:32:56.463040Z","iopub.execute_input":"2024-10-12T11:32:56.463308Z","iopub.status.idle":"2024-10-12T11:33:00.288712Z","shell.execute_reply.started":"2024-10-12T11:32:56.463286Z","shell.execute_reply":"2024-10-12T11:33:00.287521Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if DEBUG:\n    import os\n    for dirname, _, filenames in os.walk(PATCH_IMAGES_DIR):\n        for filename in filenames:\n            print(os.path.join(dirname, filename))    ","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.290784Z","iopub.execute_input":"2024-10-12T11:33:00.292134Z","iopub.status.idle":"2024-10-12T11:33:00.298290Z","shell.execute_reply.started":"2024-10-12T11:33:00.292085Z","shell.execute_reply":"2024-10-12T11:33:00.297272Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Grading the detected Level/Keypoints in Axial T2 Patches","metadata":{}},{"cell_type":"code","source":"class SiameseNetwork(nn.Module):\n    def __init__(self, model_name='resnet50', pretrained=True):\n        super(SiameseNetwork, self).__init__()\n        \n        self.backbone = timm.create_model(model_name, pretrained=pretrained)\n        if hasattr(self.backbone, 'fc'):\n            # e.g. ResNet-like models\n            self.backbone.fc = nn.Identity()\n        elif hasattr(self.backbone, 'classifier'):\n            # e.g. EfficientNet-like models\n            self.backbone.classifier = nn.Identity()\n        \n        self.similarity = nn.CosineSimilarity(dim=1)\n                \n        self.class_embeddings = None\n        \n    def forward_once(self, x):\n        return self.backbone(x)\n\n    def precompute_class_embeddings(self, reference_images_per_class):\n        self.class_embeddings = {}\n        for class_label, images in reference_images_per_class.items():\n            with torch.no_grad():\n                # Pre-compute embedding for each reference image\n                embeddings = [self.forward_once(image.unsqueeze(0)) for image in images]\n                embeddings = torch.stack(embeddings)\n                self.class_embeddings[class_label] = embeddings\n    \n    def forward(self, img1, img2=None):\n        if img2 is not None:\n            # Standard Siamese comparison between two images\n            embedding1 = self.forward_once(img1)\n            embedding2 = self.forward_once(img2)\n            similarity_score = self.similarity(embedding1, embedding2)\n            return similarity_score\n        \n        else:\n            # Compare the test image(s) to the precomputed class embeddings            \n            embedding1 = self.forward_once(img1)\n            similarity_scores = {}\n            \n            for class_label, class_embedding in self.class_embeddings.items():\n                num_ref = class_embedding.shape[0]\n                class_embedding = class_embedding.permute(1, 2, 0)                \n                similarity_scores[class_label] = self.similarity(\n                    embedding1.unsqueeze(2).repeat(1, 1, num_ref), class_embedding\n                ).cpu().numpy()\n            \n            return similarity_scores","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.299723Z","iopub.execute_input":"2024-10-12T11:33:00.300351Z","iopub.status.idle":"2024-10-12T11:33:00.312500Z","shell.execute_reply.started":"2024-10-12T11:33:00.300324Z","shell.execute_reply":"2024-10-12T11:33:00.311669Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def siamese_base_inference(model, test_image_path, device, transform, classes, mode='mean'):\n    assert mode in ['max', 'mean']\n    \n    # Load the test image and apply transformation\n    test_image = Image.open(test_image_path).convert('RGB')\n    test_image = transform(test_image).unsqueeze(0).to(device)\n\n    # Infer test image similarity scores\n    with torch.no_grad():\n        class_scores = model(test_image)\n\n    # Post-process scores\n    for cls in class_scores.keys():\n        ones = class_scores[cls] > 0.6\n        zeros = class_scores[cls] < 0.4\n        class_scores[cls][ones] = 1.0\n        class_scores[cls][zeros] = 0.0\n\n    # Average/Max the similarity scores for each class\n    if mode == 'max':\n        class_scores = {cls: np.max(scores) for cls, scores in class_scores.items()}\n    elif mode == 'mean':\n        class_scores = {cls: np.mean(scores) for cls, scores in class_scores.items()}\n    \n    # Convert scores to a list in the same order as classes\n    scores = torch.tensor([class_scores[cls] for cls in classes], device=device)\n    \n    # Normalize scores -> probabilities\n    probabilities = scores / scores.sum()    \n    probabilities = probabilities.cpu().numpy()\n    \n    return probabilities","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.313508Z","iopub.execute_input":"2024-10-12T11:33:00.313782Z","iopub.status.idle":"2024-10-12T11:33:00.326247Z","shell.execute_reply.started":"2024-10-12T11:33:00.313754Z","shell.execute_reply":"2024-10-12T11:33:00.325344Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_reference_images(root_dir, transform, device, num_ref_images=5):\n    random.seed(42) # For reproducibility \n    ref_images_per_class = defaultdict(lambda: defaultdict())\n    for level in sorted(LEVELS):\n        for cls in CLASSES:\n            class_path = os.path.join(root_dir, level, cls)\n            img_paths = [os.path.join(class_path, img) for img in os.listdir(class_path) if img.endswith('.png')]\n\n            # Select a few reference images per class\n            samples_of_class = random.sample(img_paths, min(len(img_paths), num_ref_images))\n            samples_of_class = [Image.open(s).convert('RGB') for s in samples_of_class]\n            ref_images_per_class[level][cls] = [transform(img).to(device) for img in samples_of_class]\n    \n    return ref_images_per_class","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.327293Z","iopub.execute_input":"2024-10-12T11:33:00.327549Z","iopub.status.idle":"2024-10-12T11:33:00.335754Z","shell.execute_reply.started":"2024-10-12T11:33:00.327527Z","shell.execute_reply":"2024-10-12T11:33:00.334850Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_siamese_pts(pt_path_list: list, model_name: str, transform, device):\n    ref_images_per_class = load_reference_images(SIAMESE_AXIAL_T2_REFIMG_ROOT_DIR, transform, device, num_ref_images=40)\n    \n    models = defaultdict(list)\n    for model_path in tqdm(pt_path_list):\n        level = \"_\".join(Path(model_path).stem.split(\"_\")[0:2])        \n        model = SiameseNetwork(model_name=model_name, pretrained=False)\n        model.load_state_dict(torch.load(model_path))\n        model.to(device)\n        model.eval()\n        model.precompute_class_embeddings(ref_images_per_class[level])\n        models[level].append(model)\n    return models","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.341085Z","iopub.execute_input":"2024-10-12T11:33:00.341597Z","iopub.status.idle":"2024-10-12T11:33:00.348582Z","shell.execute_reply.started":"2024-10-12T11:33:00.341570Z","shell.execute_reply":"2024-10-12T11:33:00.347820Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def siamese_avg_inference(models, test_image_path, transform, device, classes):\n    probabilities = []\n    for model in models:\n        probabilities.append(siamese_base_inference(model, test_image_path, device, transform, classes))    \n    probabilities = np.stack(probabilities, axis=0)\n    probabilities = np.mean(probabilities, axis=0)\n    return probabilities","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.349595Z","iopub.execute_input":"2024-10-12T11:33:00.349897Z","iopub.status.idle":"2024-10-12T11:33:00.357573Z","shell.execute_reply.started":"2024-10-12T11:33:00.349873Z","shell.execute_reply":"2024-10-12T11:33:00.356754Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def siamese_axial_t2_inference(df):    \n    predictions = defaultdict(list)\n\n    transform = transforms.Compose([\n        transforms.Resize((224, 224)),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n    ])\n    \n    print(\"Loading folds' pre-trained models...\")\n    fold_models = load_siamese_pts(SIAMESE_AXIAL_T2_PT_LIST, model_name='resnet18', transform=transform, device=DEVICE)\n    print(\"Loading folds' pre-trained models...Done\")\n    \n    classes = ['Normal_Mild', 'Moderate', 'Severe']    \n\n    start_time = time.time()\n    for study_id, sid_data in df.groupby('study_id'):\n        processed = False\n        for series_id, serid_data in sid_data.groupby('series_id'):\n            if serid_data.series_description.values[0] != \"Axial T2\":\n                continue\n            processed = True\n            for level in sorted(LEVELS):\n                for side in ['left', 'right']:\n                    input_dir = os.path.join(PATCH_IMAGES_DIR, \"Axial_T2\", str(study_id), level, f\"{study_id}_{series_id}_{side}*.png\")\n                    patches = glob.glob(input_dir)\n                    if len(patches):\n                        probabilities = [\n                            siamese_avg_inference(fold_models[level], p, transform, DEVICE, classes)\n                            for p in patches\n                        ]                    \n                        probabilities = np.stack(probabilities, axis=0)\n                        probabilities = np.mean(probabilities, axis=0)\n                    else:\n                        print(f\"Nothing found for {input_dir}\")\n                        probabilities = np.ones((3,)) / 3\n                    predictions[f\"{study_id}_{side}_subarticular_stenosis_{level}\"].append(probabilities)\n\n        if not processed: # We have to provide predictions even if there is no Axial T2 series for some study ids\n            print(f\"No Axial T2 series for study_id: {study_id}\")\n            for level in sorted(LEVELS):\n                for side in ['left', 'right']:\n                    probabilities = np.ones((3,)) / 3\n                    predictions[f\"{study_id}_{side}_subarticular_stenosis_{level}\"].append(probabilities)\n            \n        \n    for key, value in predictions.items():\n        predictions[key] = np.mean(np.stack(value, axis=0), axis=0)\n    \n    end_time = time.time()\n    execution_time = end_time - start_time\n    print(\"Execution time:\", execution_time, \"seconds\")\n    \n    predictions_df = pd.DataFrame(\n        [(key, value[0], value[1], value[2]) for key, value in predictions.items()],\n        columns=['row_id', 'normal_mild', 'moderate', 'severe']\n    )\n    \n    return predictions_df","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.358571Z","iopub.execute_input":"2024-10-12T11:33:00.358929Z","iopub.status.idle":"2024-10-12T11:33:00.373549Z","shell.execute_reply.started":"2024-10-12T11:33:00.358898Z","shell.execute_reply":"2024-10-12T11:33:00.372572Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"siamese_axial_t2_predictions_df = siamese_axial_t2_inference(df=TEST_DF)","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:00.374735Z","iopub.execute_input":"2024-10-12T11:33:00.375140Z","iopub.status.idle":"2024-10-12T11:33:16.038539Z","shell.execute_reply.started":"2024-10-12T11:33:00.375110Z","shell.execute_reply":"2024-10-12T11:33:16.037455Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"siamese_axial_t2_predictions_df.head(10)","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:16.039956Z","iopub.execute_input":"2024-10-12T11:33:16.040314Z","iopub.status.idle":"2024-10-12T11:33:16.052873Z","shell.execute_reply.started":"2024-10-12T11:33:16.040280Z","shell.execute_reply":"2024-10-12T11:33:16.051904Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if not DEBUG:\n    import shutil\n    shutil.rmtree(PATCH_IMAGES_DIR)","metadata":{"execution":{"iopub.status.busy":"2024-10-12T11:33:16.053890Z","iopub.execute_input":"2024-10-12T11:33:16.054131Z","iopub.status.idle":"2024-10-12T11:33:16.064083Z","shell.execute_reply.started":"2024-10-12T11:33:16.054110Z","shell.execute_reply":"2024-10-12T11:33:16.063357Z"},"trusted":true},"outputs":[],"execution_count":null}]}