{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":224924377,"sourceType":"kernelVersion"},{"sourceId":224929399,"sourceType":"kernelVersion"}],"dockerImageVersionId":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -qU iterative-stratification\n!pip install -qU ultralytics\n!pip install -qU ipywidgets","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:50:34.537898Z","iopub.execute_input":"2025-07-10T06:50:34.538335Z","iopub.status.idle":"2025-07-10T06:50:53.162595Z","shell.execute_reply.started":"2025-07-10T06:50:34.538288Z","shell.execute_reply":"2025-07-10T06:50:53.161467Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom glob import glob\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport matplotlib.pyplot as plt\nimport pydicom\nfrom iterstrat.ml_stratifiers import MultilabelStratifiedKFold\nimport subprocess\nfrom IPython.display import FileLink, display\nimport subprocess\nfrom IPython.display import FileLink, display\nfrom tqdm.notebook import tqdm\ntqdm.pandas()\n\nimport sklearn\nfrom sklearn.isotonic import IsotonicRegression\nimport shutil\nimport ultralytics\nfrom ultralytics import YOLO\nfrom concurrent.futures import ThreadPoolExecutor\nimport torch\nfrom sklearn.cluster import DBSCAN\nfrom sklearn.metrics import mean_squared_error\nfrom multiprocessing import Pool, cpu_count\nimport torch\nfrom torchvision.ops import box_iou\nfrom torchvision.ops import nms\n# from scipy.special import softmax\ndevice='gpu' if torch.cuda.is_available() else 'cpu'\n# device='cpu'\ndevice","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:50:53.163882Z","iopub.execute_input":"2025-07-10T06:50:53.164243Z","iopub.status.idle":"2025-07-10T06:51:05.127743Z","shell.execute_reply.started":"2025-07-10T06:50:53.164199Z","shell.execute_reply":"2025-07-10T06:51:05.126783Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.environ['WANDB_DISABLED'] = 'true'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.128627Z","iopub.execute_input":"2025-07-10T06:51:05.129088Z","iopub.status.idle":"2025-07-10T06:51:05.134345Z","shell.execute_reply.started":"2025-07-10T06:51:05.129061Z","shell.execute_reply":"2025-07-10T06:51:05.132705Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def iou(box1, box2):\n    \"\"\"Compute IoU between two bounding boxes\"\"\"\n    x1, y1, x2, y2 = box1\n    x1_p, y1_p, x2_p, y2_p = box2\n\n    # Compute intersection\n    inter_x1 = max(x1, x1_p)\n    inter_y1 = max(y1, y1_p)\n    inter_x2 = min(x2, x2_p)\n    inter_y2 = min(y2, y2_p)\n\n    inter_area = max(0, inter_x2 - inter_x1) * max(0, inter_y2 - inter_y1)\n\n    # Compute union\n    box1_area = (x2 - x1) * (y2 - y1)\n    box2_area = (x2_p - x1_p) * (y2_p - y1_p)\n\n    union_area = box1_area + box2_area - inter_area\n\n    return inter_area / union_area if union_area > 0 else 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.137342Z","iopub.execute_input":"2025-07-10T06:51:05.137637Z","iopub.status.idle":"2025-07-10T06:51:05.162052Z","shell.execute_reply.started":"2025-07-10T06:51:05.137612Z","shell.execute_reply":"2025-07-10T06:51:05.160759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def add_rowise_iou(row):\n    box1 = [row['x1'], row['y1'],row['x2'], row['y2']]\n    box2 = [row['xmin'], row['ymin'],row['xmax'], row['ymax']]\n    iou_val = iou(box1, box2)\n    return iou_val","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.163975Z","iopub.execute_input":"2025-07-10T06:51:05.164385Z","iopub.status.idle":"2025-07-10T06:51:05.185743Z","shell.execute_reply.started":"2025-07-10T06:51:05.164355Z","shell.execute_reply":"2025-07-10T06:51:05.184563Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tlc_path = \"/kaggle/input/conf2-data-prep-250228/output/processed_data.csv\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.187156Z","iopub.execute_input":"2025-07-10T06:51:05.187567Z","iopub.status.idle":"2025-07-10T06:51:05.206188Z","shell.execute_reply.started":"2025-07-10T06:51:05.187530Z","shell.execute_reply":"2025-07-10T06:51:05.204876Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def clean_spaces(row):\n    if type(row)==str:\n        return \"_\".join(row.lower().replace(\"/\",\" \").split(\" \"))\n    else:\n        return row","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.207118Z","iopub.execute_input":"2025-07-10T06:51:05.207467Z","iopub.status.idle":"2025-07-10T06:51:05.227335Z","shell.execute_reply.started":"2025-07-10T06:51:05.207438Z","shell.execute_reply":"2025-07-10T06:51:05.225870Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tsd_path = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_series_descriptions.csv\"\ntsd = pd.read_csv(tsd_path)\ntsd = tsd.map(clean_spaces)\ntsd = tsd[tsd['series_description']=='sagittal_t2_stir'].copy()\ntsd.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.228455Z","iopub.execute_input":"2025-07-10T06:51:05.228803Z","iopub.status.idle":"2025-07-10T06:51:05.323336Z","shell.execute_reply.started":"2025-07-10T06:51:05.228774Z","shell.execute_reply":"2025-07-10T06:51:05.321979Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_path = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv\"\ntrain = pd.read_csv(train_path)\ntrain = train.map(clean_spaces)\ntrain = train.set_index('study_id')\ntrain = train.melt(var_name = \"condition_level\",value_name = \"severity\",ignore_index=False).reset_index()\ntrain['condition'] = train['condition_level'].astype(str).apply(lambda x: \"_\".join(x.split(\"_\")[:3]))\ntrain['level'] = train['condition_level'].astype(str).apply(lambda x: x.split(\"_\",3)[-1])\ntrain = train[train['condition']=='spinal_canal_stenosis'].reset_index(drop=True).copy()\ntrain = train.merge(tsd)\ntrain = train[train['series_description']=='sagittal_t2_stir'].reset_index(drop=True).copy()\ntrain.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.324493Z","iopub.execute_input":"2025-07-10T06:51:05.324912Z","iopub.status.idle":"2025-07-10T06:51:05.520044Z","shell.execute_reply.started":"2025-07-10T06:51:05.324875Z","shell.execute_reply":"2025-07-10T06:51:05.518714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tlc = pd.read_csv(tlc_path)\ntlc=tlc.fillna(0.0)\ntlc.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.521312Z","iopub.execute_input":"2025-07-10T06:51:05.521716Z","iopub.status.idle":"2025-07-10T06:51:05.649697Z","shell.execute_reply.started":"2025-07-10T06:51:05.521673Z","shell.execute_reply":"2025-07-10T06:51:05.648460Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path = \"/kaggle/input/conf2-model-train-250228\"\nglob(f\"{path}/*\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.650940Z","iopub.execute_input":"2025-07-10T06:51:05.651291Z","iopub.status.idle":"2025-07-10T06:51:05.663636Z","shell.execute_reply.started":"2025-07-10T06:51:05.651262Z","shell.execute_reply":"2025-07-10T06:51:05.662278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_path = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images\"\nmodel_path = \"/kaggle/input/conf2-model-train-250228/level_model_train_results/fold_0/weights/best.pt\"\nmodel = YOLO(model_path)\nsev_model_path = \"/kaggle/input/conf2-model-train-250228/moderate_severe_model_train_results/fold_0/weights/best.pt\"\nsev_model = YOLO(sev_model_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:05.664816Z","iopub.execute_input":"2025-07-10T06:51:05.665159Z","iopub.status.idle":"2025-07-10T06:51:07.554312Z","shell.execute_reply.started":"2025-07-10T06:51:05.665130Z","shell.execute_reply":"2025-07-10T06:51:07.553268Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.names","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.558222Z","iopub.execute_input":"2025-07-10T06:51:07.558575Z","iopub.status.idle":"2025-07-10T06:51:07.565589Z","shell.execute_reply.started":"2025-07-10T06:51:07.558547Z","shell.execute_reply":"2025-07-10T06:51:07.564443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sev_model.names","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.567189Z","iopub.execute_input":"2025-07-10T06:51:07.567479Z","iopub.status.idle":"2025-07-10T06:51:07.588746Z","shell.execute_reply.started":"2025-07-10T06:51:07.567455Z","shell.execute_reply":"2025-07-10T06:51:07.587727Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"config = {}\nconfig['image_size'] = (640,640)\nconfig['w'] = 0.1\nconfig['h'] = 0.1\n# base_path = \"rsna_2024_lsdc_input/train_images\"\nclass_to_name_map  = {0: 'l1_l2',\n 1: 'l2_l3',\n 2: 'l3_l4',\n 3: 'l4_l5',\n 4: 'l5_s1',\n 5: 'moderate_severe'\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.589793Z","iopub.execute_input":"2025-07-10T06:51:07.590196Z","iopub.status.idle":"2025-07-10T06:51:07.609367Z","shell.execute_reply.started":"2025-07-10T06:51:07.590158Z","shell.execute_reply":"2025-07-10T06:51:07.608189Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tlc.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.610526Z","iopub.execute_input":"2025-07-10T06:51:07.610951Z","iopub.status.idle":"2025-07-10T06:51:07.649509Z","shell.execute_reply.started":"2025-07-10T06:51:07.610893Z","shell.execute_reply":"2025-07-10T06:51:07.648346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tlc.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.650630Z","iopub.execute_input":"2025-07-10T06:51:07.651073Z","iopub.status.idle":"2025-07-10T06:51:07.673454Z","shell.execute_reply.started":"2025-07-10T06:51:07.651026Z","shell.execute_reply":"2025-07-10T06:51:07.672190Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def clean_spaces(row):\n    if type(row)==str:\n        return \"_\".join(row.lower().replace(\"/\",\" \").split(\" \"))\n    else:\n        return row","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.674626Z","iopub.execute_input":"2025-07-10T06:51:07.675010Z","iopub.status.idle":"2025-07-10T06:51:07.698191Z","shell.execute_reply.started":"2025-07-10T06:51:07.674945Z","shell.execute_reply":"2025-07-10T06:51:07.696430Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"columns = ['study_id','series_id','series_description','fold']\nstudy_id_to_fold_map  = tlc[columns].drop_duplicates(subset=columns )\nstudy_id_to_fold_map.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.699749Z","iopub.execute_input":"2025-07-10T06:51:07.700574Z","iopub.status.idle":"2025-07-10T06:51:07.737047Z","shell.execute_reply.started":"2025-07-10T06:51:07.700463Z","shell.execute_reply":"2025-07-10T06:51:07.736037Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tsd.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.738431Z","iopub.execute_input":"2025-07-10T06:51:07.738724Z","iopub.status.idle":"2025-07-10T06:51:07.748428Z","shell.execute_reply.started":"2025-07-10T06:51:07.738696Z","shell.execute_reply":"2025-07-10T06:51:07.747200Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"t = train\nt.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.749500Z","iopub.execute_input":"2025-07-10T06:51:07.749781Z","iopub.status.idle":"2025-07-10T06:51:07.775183Z","shell.execute_reply.started":"2025-07-10T06:51:07.749756Z","shell.execute_reply":"2025-07-10T06:51:07.773971Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def read_dicom_file(dcmpath,dsize=config['image_size']):\n    dcmfile = pydicom.dcmread(dcmpath)\n    img = dcmfile.pixel_array\n    lower, upper = np.percentile(img, (1, 99))\n    img = np.clip(img, lower, upper)\n    img = img - np.min(img)\n    img = img / np.max(img)\n    img = (img * 255).astype(np.uint8)\n    img = np.stack([img] * 3, axis=-1)\n    stdimg = cv2.resize(img, dsize=dsize, interpolation=cv2.INTER_LANCZOS4)\n    return stdimg","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.776280Z","iopub.execute_input":"2025-07-10T06:51:07.776571Z","iopub.status.idle":"2025-07-10T06:51:07.795474Z","shell.execute_reply.started":"2025-07-10T06:51:07.776546Z","shell.execute_reply":"2025-07-10T06:51:07.794172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def iou(box1, box2):\n    \"\"\"Compute IoU between two bounding boxes\"\"\"\n    x1, y1, x2, y2 = box1\n    x1_p, y1_p, x2_p, y2_p = box2\n\n    # Compute intersection\n    inter_x1 = max(x1, x1_p)\n    inter_y1 = max(y1, y1_p)\n    inter_x2 = min(x2, x2_p)\n    inter_y2 = min(y2, y2_p)\n\n    inter_area = max(0, inter_x2 - inter_x1) * max(0, inter_y2 - inter_y1)\n\n    # Compute union\n    box1_area = (x2 - x1) * (y2 - y1)\n    box2_area = (x2_p - x1_p) * (y2_p - y1_p)\n\n    union_area = box1_area + box2_area - inter_area\n\n    return inter_area / union_area if union_area > 0 else 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.796449Z","iopub.execute_input":"2025-07-10T06:51:07.796760Z","iopub.status.idle":"2025-07-10T06:51:07.816314Z","shell.execute_reply.started":"2025-07-10T06:51:07.796733Z","shell.execute_reply":"2025-07-10T06:51:07.814699Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def compute_iou(box, boxes):\n    # Compute Intersection over Union between a single box and multiple boxes\n    xA = np.maximum(box['xmin'], boxes['xmin'])\n    yA = np.maximum(box['ymin'], boxes['ymin'])\n    xB = np.minimum(box['xmax'], boxes['xmax'])\n    yB = np.minimum(box['ymax'], boxes['ymax'])\n    interArea = np.maximum(0, xB - xA) * np.maximum(0, yB - yA)\n    \n    boxArea = (box['xmax'] - box['xmin']) * (box['ymax'] - box['ymin'])\n    boxesArea = (boxes['xmax'] - boxes['xmin']) * (boxes['ymax'] - boxes['ymin'])\n    iou = interArea / (boxArea + boxesArea - interArea)\n    return iou\n\ndef standard_nms(df, iou_threshold=0.5):\n    # Perform standard NMS and return both kept and suppressed detections.\n    df = df.sort_values('confidence', ascending=False).reset_index(drop=True)\n    keep = []\n    suppressed = []\n    while not df.empty:\n        current = df.iloc[0]\n        keep.append(current)\n        df = df.iloc[1:].reset_index(drop=True)\n        if df.empty:\n            break\n        ious = compute_iou(current, df)\n        # Identify indices to suppress (IoU above threshold)\n        to_suppress = ious[ious > iou_threshold].index\n        # Save suppressed rows for potential reordering later\n        suppressed.append(df.iloc[to_suppress])\n        # Keep the remaining ones\n        df = df.drop(to_suppress).reset_index(drop=True)\n    kept_df = pd.DataFrame(keep)\n    suppressed_df = pd.concat(suppressed) if suppressed else pd.DataFrame()\n    return kept_df, suppressed_df\n\ndef post_nms_reordering(kept_df, suppressed_df, expected_order):\n    \"\"\"\n    expected_order: List defining the anatomical order.\n    For example: ['l1_l2_normal_mild_moderate', 'l2_l3_normal_mild_moderate', 'l3_l4_normal_mild_moderate']\n    \"\"\"\n    # Sort kept detections by their ymin to reflect anatomical vertical order\n    final_df = kept_df.sort_values('ymin').reset_index(drop=True)\n    \n    # Identify missing classes based on expected order\n    present_classes = set(final_df['class_'].unique())\n    missing_classes = [cls for cls in expected_order if cls not in present_classes]\n    \n    # For each missing class, search in suppressed detections for the best candidate\n    for cls in missing_classes:\n        candidates = suppressed_df[suppressed_df['class_'] == cls] .reset_index(drop=True)\n        if not candidates.empty:\n            best_candidate = candidates.loc[candidates['confidence'].idxmax()]\n            if len(best_candidate.shape)!=1:\n                print('best_candidate')\n                display(best_candidate)\n                best_candidate  =best_candidate.iloc[0]\n            # print(\"best_candidate.shape\",best_candidate.shape)\n            # Determine where to insert the candidate\n            target_idx = expected_order.index(cls)\n            insertion_index = None\n            for i, row in final_df.iterrows():\n                row_cls = row['class_']\n                if expected_order.index(row_cls) > target_idx:\n                    insertion_index = i\n                    break\n            if insertion_index is None:\n                insertion_index = len(final_df)\n            # Insert the candidate into the correct position\n            # print('best_candidate',best_candidate)\n            final_df = pd.concat([\n                final_df.iloc[:insertion_index],\n                pd.DataFrame([best_candidate]),\n                final_df.iloc[insertion_index:]\n            ]).reset_index(drop=True)\n    \n    return final_df\n\n# Example usage:\n# Assume df is your initial DataFrame of detections\nexpected_order = [\n    'l1_l2', \n    'l2_l3', \n    'l3_l4',\n    'l4_l5',\n    'l5_s1',\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.817530Z","iopub.execute_input":"2025-07-10T06:51:07.817856Z","iopub.status.idle":"2025-07-10T06:51:07.833158Z","shell.execute_reply.started":"2025-07-10T06:51:07.817829Z","shell.execute_reply":"2025-07-10T06:51:07.831667Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_path","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.834494Z","iopub.execute_input":"2025-07-10T06:51:07.834832Z","iopub.status.idle":"2025-07-10T06:51:07.864441Z","shell.execute_reply.started":"2025-07-10T06:51:07.834802Z","shell.execute_reply":"2025-07-10T06:51:07.863256Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_level_sererity_results(selected_results,selected_sev_results):\n\n    # Create a 2x5 grid (adjust the figure size as needed)\n    fig, axes = plt.subplots(len(selected_results),2, figsize=(20, 10 * len(selected_results)))\n    # axes = axes.flatten()\n    \n    for idx,(r1,r2) in enumerate(zip(selected_results,selected_sev_results)):\n        annotated_img1 = r1.plot()  \n        axes[idx,0].imshow(annotated_img1)\n        # axes[idx,0].axis('off')  # Hide axis ticks and labels\n        annotated_img2 = r2.plot()  \n        axes[idx,1].imshow(annotated_img2)\n        # axes[idx,1].axis('off')  # Hide axis ticks and labels\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.865517Z","iopub.execute_input":"2025-07-10T06:51:07.865821Z","iopub.status.idle":"2025-07-10T06:51:07.886241Z","shell.execute_reply.started":"2025-07-10T06:51:07.865796Z","shell.execute_reply":"2025-07-10T06:51:07.885044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_raw_yolo_results(base_path,study_id,series_id,model, plot_results = False,level_conf = 0.2,sev_conf = 0.1) :\n    pattern = f\"{base_path}/{study_id}/{series_id}/*\"\n    files = glob(pattern)\n    files = sorted(files,key = lambda x: int(x.split(\"/\")[-1][:-4]))\n    instance_numbers = [int(x.split(\"/\")[-1][:-4]) for x in files ]\n    # print(files)\n    images = [read_dicom_file(dcmpath,dsize=config['image_size'])  for dcmpath in files]\n    results = model(images,iou=0.3,verbose=False,max_det=10,conf = 0.4,classes=[0,1,2,3,4])\n    imp_img_path = []\n    idxmin = 0\n    idxmax = 0\n    l = []\n    for idx,(r,file) in enumerate(zip(results,files)):\n        data = r.boxes.data.cpu().detach().numpy()\n        # print(idx,(data,file))\n        if len (data)!=0:\n            l.append(idx)\n    idxmin = max(min(l)-1,0)\n    idxmax = min(max(l)+2,len(files))\n    \n    selected_files = files[idxmin:idxmax]\n    selected_instance_numbers = instance_numbers[idxmin:idxmax]\n    selected_images = [read_dicom_file(dcmpath,dsize=config['image_size'])  for dcmpath in selected_files]    \n\n    selected_results = model(selected_images,iou=0.3,verbose=False,max_det=10,conf = level_conf)\n    \n    list_df = []\n    \n    for r,instance_number in zip(selected_results,selected_instance_numbers):\n        data = r.boxes.data.cpu().detach().numpy()\n        if len (data)==0:\n            data = np.ones((1,6)) *-1\n        df = pd.DataFrame(data,columns = ['xmin','ymin','xmax','ymax','confidence','class_'])\n        df['instance_number'] = instance_number\n        list_df.append(df)\n    study_id_pred = pd.concat(list_df).reset_index(drop=True)\n    study_id_pred = study_id_pred[study_id_pred['class_']!=-1]\n    study_id_pred['class_'] = study_id_pred['class_'].map(class_to_name_map)\n    study_id_pred['study_id'] = study_id\n    study_id_pred['series_id'] = series_id\n    filtered_group = study_id_pred.copy()\n    filtered_group = filtered_group.loc[filtered_group.groupby('class_')['confidence'].idxmax()].reset_index(drop=True)\n    filtered_group_level = filtered_group.sort_values(by = 'ymin').reset_index(drop=True).copy()\n\n    # minval = filtered_group_level.instance_number.unique().min()\n    # maxval = filtered_group_level.instance_number.unique().max()\n    # print(minval,maxval)\n    \n    # idxmin = max(instance_numbers.index(minval)-1,0)    \n    # idxmax = min(instance_numbers.index(maxval)+2,len(instance_numbers))\n    # selected_files = files[idxmin:idxmax]\n    # selected_instance_numbers = instance_numbers[idxmin:idxmax]\n\n    # print(f\"selected_files : {selected_files}\")\n\n    \n    selected_sev_results = sev_model(selected_images,iou=0.3,verbose=False,max_det=10,conf = sev_conf)\n\n    list_df = []\n    \n    for r,instance_number in zip(selected_sev_results,selected_instance_numbers):\n        data = r.boxes.data.cpu().detach().numpy()\n        if len (data)==0:\n            data = np.ones((1,6)) *-1\n        df = pd.DataFrame(data,columns = ['xmin','ymin','xmax','ymax','confidence','class_'])\n        df['instance_number'] = instance_number\n        list_df.append(df)\n    sev_study_id_pred = pd.concat(list_df).reset_index(drop=True).sort_values(by = 'ymin').reset_index(drop=True).copy()\n    sev_study_id_pred = sev_study_id_pred[sev_study_id_pred['class_']==5]\n    sev_study_id_pred['class_'] = sev_study_id_pred['class_'].map(class_to_name_map)\n    sev_study_id_pred['study_id'] = study_id\n    sev_study_id_pred['series_id'] = series_id\n\n    # # Level agnostic NMS across all series images\n    # boxes = torch.tensor(study_id_pred[['xmin','ymin','xmax','ymax']].values)\n    # scores = torch.tensor(study_id_pred['confidence'].values)\n    # iou_threshold = 0.3\n    # keep_indices = nms(boxes, scores, iou_threshold)\n    # filtered_group = study_id_pred.iloc[keep_indices]\n    # filtered_group = filtered_group.reset_index(drop=True)\n    filtered_group = study_id_pred.copy()\n    filtered_group = filtered_group.loc[filtered_group.groupby('class_')['confidence'].idxmax()].reset_index(drop=True)\n    filtered_group_level = filtered_group.sort_values(by = 'ymin').reset_index(drop=True).copy()\n\n\n    severe_res = sev_study_id_pred\n    filtered_levels = filtered_group_level  \n    mapped_classes = []\n    for _, severe_row in severe_res.iterrows():\n        severe_box = severe_row[['xmin', 'ymin', 'xmax', 'ymax']].values\n        best_class = None\n        best_iou = 0\n        \n        for _, normal_row in filtered_levels.iterrows():\n            normal_box = normal_row[['xmin', 'ymin', 'xmax', 'ymax']].values\n            iou_score = iou(severe_box, normal_box)\n            # print(iou_score)\n            if iou_score > best_iou and iou_score>0.5:\n                \n                best_iou = iou_score\n                best_class = normal_row['class_'][:5]\n                # print(best_iou,best_class)\n                break\n        else:\n            best_class = 'unknown'\n        \n        mapped_classes.append(best_class)\n    mapped_classes\n    severe_res = severe_res.copy()\n    severe_res['level'] = mapped_classes\n    severe_res = severe_res.reset_index(drop=True)\n    filtered_severe_res = severe_res.loc[severe_res.groupby('level')['confidence'].idxmax()].reset_index(drop=True)\n    filtered_levels['level'] = filtered_levels['class_']\n    display(filtered_levels)\n    print(filtered_levels.dtypes)\n    display(filtered_severe_res)\n    print(filtered_severe_res.dtypes)\n    final_res= filtered_levels.merge(filtered_severe_res[['confidence', 'instance_number', 'study_id','series_id','level']],\n                                 how='left', on = ['study_id','series_id','level'], suffixes = [\"_level\",\"_moderate_severe\"]).fillna(0)\n    columns = ['study_id', 'series_id', 'level','confidence_level', 'instance_number_level',  \n                 'confidence_moderate_severe', 'instance_number_moderate_severe','xmin', 'ymin', 'xmax', 'ymax',  'class_']\n    final_res = final_res[columns].copy()\n    if plot_results == True:\n        plot_level_sererity_results(selected_results,selected_sev_results)\n    \n    return final_res","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.887494Z","iopub.execute_input":"2025-07-10T06:51:07.887903Z","iopub.status.idle":"2025-07-10T06:51:07.914923Z","shell.execute_reply.started":"2025-07-10T06:51:07.887865Z","shell.execute_reply":"2025-07-10T06:51:07.913770Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"study_id, series_id = 789748240, 1733417008\nstudy_id, series_id = 4155263827,\t766880990\nstudy_id, series_id = 4287160193,\t1507070277\nstudy_id, series_id = 3486932462,\t4137128698\nstudy_id, series_id = 4255570773,\t3386536167\t\nstudy_id, series_id = 4282019580,\t1547999333\t\nstudy_id, series_id = 4279958262,\t2753156679\nstudy_id, series_id = 4262145542,\t4276471335\t\nstudy_id, series_id =  46494080,\t1763376930\nstudy_id, series_id= 10728036, 3491739931\nstudy_id, series_id=  2705618799,\t2492569956\nstudy_id, series_id = 3065863143, 2697592442\nstudy_id, series_id = 1451886888, 823647192\nstudy_id, series_id = 1038453736,\t2377168492 ## \nstudy_id, series_id = 1088270559,  648725109\nstudy_id, series_id = 3889278475,\t1882440493\t\nstudy_id, series_id = 951328272,\t2539892705  # multiple levels \nstudy_id, series_id = 10728036,\t3491739931\nstudy_id, series_id = 1525013622,\t3963700087\nstudy_id, series_id = 75336136, 779328287\nstudy_id, series_id = 75336136, 779328287","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.916262Z","iopub.execute_input":"2025-07-10T06:51:07.916595Z","iopub.status.idle":"2025-07-10T06:51:07.943356Z","shell.execute_reply.started":"2025-07-10T06:51:07.916565Z","shell.execute_reply":"2025-07-10T06:51:07.942137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# c1 = t['study_id']==study_id\n# c2 = tlc['study_id']==study_id \n# display(t[c1])\n# display(tlc[c2])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.944953Z","iopub.execute_input":"2025-07-10T06:51:07.945387Z","iopub.status.idle":"2025-07-10T06:51:07.967590Z","shell.execute_reply.started":"2025-07-10T06:51:07.945348Z","shell.execute_reply":"2025-07-10T06:51:07.966423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nc1 = t['study_id']==study_id\nc2 = tlc['study_id']==study_id \ndisplay(t[c1])\ndisplay(tlc[c2])\nfinal_res= get_raw_yolo_results(base_path,study_id,series_id,model, plot_results = True,level_conf = .2,sev_conf = .1) \n# , selected_results, selected_files, selected_instance_numbers,selected_images\ndisplay(final_res)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:07.968794Z","iopub.execute_input":"2025-07-10T06:51:07.969208Z","iopub.status.idle":"2025-07-10T06:51:25.505979Z","shell.execute_reply.started":"2025-07-10T06:51:07.969169Z","shell.execute_reply":"2025-07-10T06:51:25.498143Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# %%time\n# for fold_ in [f\"fold_{i}\" for i in range(5)]:\n#     tlc = pd.read_csv(tlc_path)\n#     columns = ['study_id','series_id','series_description','fold']\n#     study_id_to_fold_map  = tlc[columns].drop_duplicates(subset=columns )\n#     # tsd_path = ip_files[4]\n#     tsd = pd.read_csv(tsd_path)\n#     tsd = tsd.map(clean_spaces)\n#     tsd = tsd[tsd['series_description']=='sagittal_t2_stir'].copy().reset_index(drop=True)\n#     tsd = tsd.merge(study_id_to_fold_map)\n#     # train_path = ip_files[2]\n#     t = pd.read_csv(train_path)\n#     t = t.map(clean_spaces)\n#     columns = ['study_id'] + [c for c in t.columns if 'spinal' in c] \n#     t = t[columns].copy()\n   \n#     model_path = f\"/kaggle/input/conf2-model-train-250228/level_model_train_results/{fold_}/weights/best.pt\"\n#     sev_model_path = f\"/kaggle/input/conf2-model-train-250228/moderate_severe_model_train_results/{fold_}/weights/best.pt\"\n\n\n#     model = YOLO(model_path)\n#     sev_model = YOLO(sev_model_path)\n\n#     all_results = []\n#     # tsd = tsd.head(13)\n#     for idx,row in tqdm(tsd.iterrows()):\n#         try:\n#             # print(study_id,series_id)\n\n#             study_id = row['study_id']\n#             series_id = row['series_id']\n#             fold = row['fold']\n#             result= get_raw_yolo_results(base_path,study_id,series_id,model,sev_model) #,level_res,severe_res \n#             result['fold'] = fold\n#             all_results.append(result)\n#         except:\n#             print(study_id,series_id)\n#             study_id = row['study_id']\n#             series_id = row['series_id']\n#             fold = row['fold']\n#             columns = {\n#             'study_id':study_id,\n#             'series_id':series_id,\n#             'level':['l1_l2','l2_l3','l3_l4','l4_l5','l5_s1'],\n#             'confidence_level':0,\n#                 'instance_number_level':0,\n#                 'confidence_moderate_severe':0,\n#                 'instance_number_moderate_severe':0,\n#             'xmin':0,\n#             'ymin':0,\n#             'xmax':0, \n#             'ymax':0, \n#             'class_':['l1_l2','l2_l3','l3_l4','l4_l5','l5_s1'],\n#             'fold':fold}\n#             error_prediction = pd.DataFrame(columns)\n#             all_results.append(error_prediction)\n#             print(study_id,series_id)\n\n#     full_result_df = pd.concat(all_results)\n\n#     file_name = f\"final_result_level_level_severe_{fold_}.csv\"\n#     full_result_df.to_csv(f\"{file_name}\",index=False)\n#     print(f\"{file_name} saved successfully.\")\n#     display(full_result_df.isna().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-10T06:51:25.507470Z","iopub.execute_input":"2025-07-10T06:51:25.507810Z","iopub.status.idle":"2025-07-10T06:51:25.513409Z","shell.execute_reply.started":"2025-07-10T06:51:25.507780Z","shell.execute_reply":"2025-07-10T06:51:25.511745Z"}},"outputs":[],"execution_count":null}]}