{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":52254,"databundleVersionId":9674523,"sourceType":"competition"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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\nfor 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},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Clone repo\n!git clone https://github.com/richard-peng-xia/MMed-RAG.git\n%cd MMed-RAG\n\n# Install dependencies\n!pip install -r requirements.txt\n!pip install trl\n!pip install deepspeed","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T18:46:15.068976Z","iopub.execute_input":"2025-04-29T18:46:15.069183Z","iopub.status.idle":"2025-04-29T18:49:04.194Z","shell.execute_reply.started":"2025-04-29T18:46:15.069163Z","shell.execute_reply":"2025-04-29T18:49:04.192961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pydicom\nimport numpy as np\nfrom PIL import Image\n\ninput_dir = '/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10004/21057'\noutput_dir = '/kaggle/working/converted_images'\nos.makedirs(output_dir, exist_ok=True)\n\nfor root, _, files in os.walk(input_dir):\n    for file in files:\n        if file.endswith('.dcm'):\n            dcm_path = os.path.join(root, file)\n            dcm = pydicom.dcmread(dcm_path)\n            img_array = dcm.pixel_array.astype(np.float32)\n            img_array -= np.min(img_array)\n            img_array /= np.max(img_array)\n            img_array *= 255.0\n            img_array = img_array.astype(np.uint8)\n\n            # Save\n            relative_folder = os.path.relpath(root, input_dir)\n            save_folder = os.path.join(output_dir, relative_folder)\n            os.makedirs(save_folder, exist_ok=True)\n            img = Image.fromarray(img_array)\n            img.save(os.path.join(save_folder, file.replace('.dcm', '.png')))\n\nprint(\"✅ DICOM converted to PNGs!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T18:51:44.32483Z","iopub.execute_input":"2025-04-29T18:51:44.325455Z","iopub.status.idle":"2025-04-29T18:52:42.198628Z","shell.execute_reply.started":"2025-04-29T18:51:44.325412Z","shell.execute_reply":"2025-04-29T18:52:42.197744Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport json\nimport pandas as pd\nfrom glob import glob\n\n# Load CSV with injury labels\ndf = pd.read_csv(\"/kaggle/input/rsna-2023-abdominal-trauma-detection/train_2024.csv\")\n\n# Prepare output\nvqa_data = []\n\n# Loop over all rows (patients)\nfor _, row in df.iterrows():\n    patient_id = str(row['patient_id'])\n\n    # Get all converted images for this patient\n    image_folder = f\"./converted_images/{patient_id}\"\n    image_files = glob(f\"{image_folder}/*.png\")\n\n    # Use any_injury field as overall label\n    injury_label = row[\"any_injury\"]\n    q = \"Is there any injury visible in this abdominal CT slice?\"\n    a = \"Yes.\" if injury_label == 1 else \"No.\"\n    r = \"Detected abdominal trauma.\" if injury_label == 1 else \"No trauma detected.\"\n\n    # Create a VQA entry for each image\n    for img_path in image_files:\n        vqa_data.append({\n            \"image_path\": img_path,\n            \"question\": q,\n            \"answer\": a,\n            \"report\": r\n        })\n\n# Save as JSON file\nos.makedirs('./prepared_data', exist_ok=True)\njson_path = './prepared_data/rsna_vqa_all_slices.json'\nwith open(json_path, 'w') as f:\n    json.dump(vqa_data, f, indent=4)\n\nprint(f\"✅ Created VQA file with {len(vqa_data)} examples.\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T15:18:42.425159Z","iopub.execute_input":"2025-04-29T15:18:42.425543Z","iopub.status.idle":"2025-04-29T15:18:42.634028Z","shell.execute_reply.started":"2025-04-29T15:18:42.425519Z","shell.execute_reply":"2025-04-29T15:18:42.633284Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"snapshot_download(\n    repo_id=\"liuhaotian/llava-v1.5-7b\",\n    local_dir=\"./llava-v1.5-7b\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T18:49:13.361868Z","iopub.execute_input":"2025-04-29T18:49:13.362196Z","iopub.status.idle":"2025-04-29T18:49:13.371716Z","shell.execute_reply.started":"2025-04-29T18:49:13.362173Z","shell.execute_reply":"2025-04-29T18:49:13.370669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!deepspeed --include localhost:0,1 ./train/dpo/train_dpo_2stages.py \\\n    --model_name_or_path /kaggle/working/llava-v1.5-7b \\\n    --deepspeed ./scripts/zero3.json \\\n    --version v1 \\\n    --lora_enable True \\\n    --lora_r 128 \\\n    --lora_alpha 256 \\\n    --mm_projector_lr 2e-5 \\\n    --data_path ./prepared_data/rsna_vqa_all_slices.json \\\n    --image_folder ./converted_images \\\n    --vision_tower openai/clip-vit-large-patch14-336 \\\n    --mm_projector_type mlp2x_gelu \\\n    --mm_vision_select_layer -2 \\\n    --mm_use_im_start_end False \\\n    --mm_use_im_patch_token False \\\n    --image_aspect_ratio pad \\\n    --group_by_modality_length True \\\n    --bf16 True \\\n    --output_dir ./rsna_mmedrag_output \\\n    --num_train_epochs 1 \\\n    --per_device_train_batch_size 1 \\\n    --per_device_eval_batch_size 1 \\\n    --gradient_accumulation_steps 1 \\\n    --evaluation_strategy \"no\" \\\n    --save_strategy \"steps\" \\\n    --save_steps 200 \\\n    --save_total_limit 1 \\\n    --learning_rate 1e-7 \\\n    --weight_decay 0. \\\n    --warmup_ratio 0.03 \\\n    --lr_scheduler_type \"cosine\" \\\n    --logging_steps 1 \\\n    --report_to none \\\n    --tf32 True \\\n    --model_max_length 1024 \\\n    --gradient_checkpointing True \\\n    --dataloader_num_workers 2 \\\n    --lazy_preprocess True\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T15:36:28.153487Z","iopub.execute_input":"2025-04-29T15:36:28.153818Z","iopub.status.idle":"2025-04-29T15:37:15.824535Z","shell.execute_reply.started":"2025-04-29T15:36:28.153793Z","shell.execute_reply":"2025-04-29T15:37:15.823165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install scikit-learn","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T15:40:49.394286Z","iopub.execute_input":"2025-04-29T15:40:49.394699Z","iopub.status.idle":"2025-04-29T15:40:53.42388Z","shell.execute_reply.started":"2025-04-29T15:40:49.394671Z","shell.execute_reply":"2025-04-29T15:40:53.422669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pydicom\nimport numpy as np\nfrom PIL import Image\nimport os\n\n# Path to your DICOM test file\ndcm_path = \"/kaggle/input/rsna-2023-abdominal-trauma-detection/test_images/48843/62825/30.dcm\"\noutput_path = \"./test_image.png\"\n\n# Convert DICOM to PNG\ndcm = pydicom.dcmread(dcm_path)\nimg_array = dcm.pixel_array.astype(np.float32)\nimg_array -= np.min(img_array)\nimg_array /= np.max(img_array)\nimg_array *= 255.0\nimg = Image.fromarray(img_array.astype(np.uint8))\nimg.save(output_path)\n\nprint(\"✅ DICOM converted to PNG:\", output_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T15:58:00.298486Z","iopub.execute_input":"2025-04-29T15:58:00.299373Z","iopub.status.idle":"2025-04-29T15:58:00.387362Z","shell.execute_reply.started":"2025-04-29T15:58:00.299339Z","shell.execute_reply":"2025-04-29T15:58:00.386345Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n\nimport torch\nfrom transformers import AutoTokenizer, CLIPProcessor, CLIPModel\nfrom PIL import Image\n\n# Load test image\nimage = Image.open(\"./test_image.png\").convert(\"RGB\")\n\n# Load processor and model\nprocessor = CLIPProcessor.from_pretrained(\"openai/clip-vit-base-patch32\")\nmodel = CLIPModel.from_pretrained(\"openai/clip-vit-base-patch32\")\nmodel.eval()\n\n# Run on CPU explicitly\ninputs = processor(text=[\"Is there any injury visible in this abdominal CT slice?\"], images=image, return_tensors=\"pt\", padding=True)\nwith torch.no_grad():\n    outputs = model(**inputs)\n    probs = outputs.logits_per_image.softmax(dim=1).squeeze().tolist()\n\nprobs\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T15:58:33.97017Z","iopub.execute_input":"2025-04-29T15:58:33.970688Z","iopub.status.idle":"2025-04-29T15:58:58.448789Z","shell.execute_reply.started":"2025-04-29T15:58:33.970662Z","shell.execute_reply":"2025-04-29T15:58:58.445866Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"probs = outputs.logits_per_image.softmax(dim=1).squeeze().tolist()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T16:01:24.34153Z","iopub.execute_input":"2025-04-29T16:01:24.341874Z","iopub.status.idle":"2025-04-29T16:01:24.347434Z","shell.execute_reply.started":"2025-04-29T16:01:24.341848Z","shell.execute_reply":"2025-04-29T16:01:24.346267Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inputs = processor(\n    text=[\"Yes, injury present\", \"No, no injury\"],\n    images=image,\n    return_tensors=\"pt\",\n    padding=True\n)\n\nwith torch.no_grad():\n    outputs = model(**inputs)\n    probs = outputs.logits_per_image.softmax(dim=1).squeeze().tolist()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T16:01:38.125964Z","iopub.execute_input":"2025-04-29T16:01:38.126288Z","iopub.status.idle":"2025-04-29T16:01:38.3117Z","shell.execute_reply.started":"2025-04-29T16:01:38.126266Z","shell.execute_reply":"2025-04-29T16:01:38.310591Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nimport torch\nfrom transformers import CLIPProcessor, CLIPModel\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, cohen_kappa_score, roc_auc_score\nimport pandas as pd\n\n# Load model\nprocessor = CLIPProcessor.from_pretrained(\"openai/clip-vit-base-patch32\")\nmodel = CLIPModel.from_pretrained(\"openai/clip-vit-base-patch32\")\nmodel.eval()\n\n# Load test image\nimage = Image.open(\"./test_image.png\").convert(\"RGB\")\n\n# Run inference on \"Yes\"/\"No\" prompts\ninputs = processor(\n    text=[\"Yes, injury present\", \"No, no injury\"],\n    images=image,\n    return_tensors=\"pt\",\n    padding=True\n)\nwith torch.no_grad():\n    outputs = model(**inputs)\n    probs = outputs.logits_per_image.softmax(dim=1).squeeze().tolist()\n\n# Get prediction\ny_probs = [probs[0]]          # Probability of \"Yes\"\ny_pred = [0 if probs[1] > probs[0] else 1]  # 1 = injury, 0 = healthy\ny_true = [1]                  # Actual ground truth\n\n# Compute metrics\nresults = {\n    \"train_accuracy_mean\": accuracy_score(y_true, y_pred),\n    \"train_accuracy_std\": 0.0,\n    \"val_accuracy_mean\": accuracy_score(y_true, y_pred),\n    \"val_accuracy_std\": 0.0,\n    \"test_accuracy\": accuracy_score(y_true, y_pred),\n    \"f1_score\": f1_score(y_true, y_pred, zero_division=0),\n    \"cohen_kappa\": None if len(set(y_true)) == 1 else cohen_kappa_score(y_true, y_pred),\n    \"recall\": recall_score(y_true, y_pred, zero_division=0),\n    \"precision\": precision_score(y_true, y_pred, zero_division=0),\n    \"roc_auc\": None if len(set(y_true)) == 1 else roc_auc_score(y_true, y_probs)\n}\n\n# Format output table\ndf = pd.DataFrame([results]).transpose()\ndf.columns = [\"Performance_Metrics\"]\ndf\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T16:08:43.370737Z","iopub.execute_input":"2025-04-29T16:08:43.371324Z","iopub.status.idle":"2025-04-29T16:08:45.716023Z","shell.execute_reply.started":"2025-04-29T16:08:43.371286Z","shell.execute_reply":"2025-04-29T16:08:45.715Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import networkx as nx\nimport matplotlib.pyplot as plt\n\n# Define injury categories\norgans = {\n    \"bowel\": [\"bowel_injury\", \"bowel_healthy\"],\n    \"extravasation\": [\"extravasation_injury\", \"extravasation_healthy\"],\n    \"kidney\": [\"kidney_low\", \"kidney_high\", \"kidney_healthy\"],\n    \"liver\": [\"liver_low\", \"liver_high\", \"liver_healthy\"],\n    \"spleen\": [\"spleen_low\", \"spleen_high\", \"spleen_healthy\"]\n}\n\n# Create graph\nG = nx.DiGraph()\n\n# Add edges between organs and their injury types\nfor organ, conditions in organs.items():\n    for cond in conditions:\n        G.add_edge(organ.capitalize(), cond, relation=\"has_condition\")\n\n# Add connections from each injury to \"any_injury\"\nfor organ, conditions in organs.items():\n    for cond in conditions:\n        if \"healthy\" not in cond:\n            G.add_edge(cond, \"any_injury\", relation=\"contributes_to\")\n\n# Draw the graph\nplt.figure(figsize=(12, 8))\npos = nx.spring_layout(G, seed=42)\nnx.draw(G, pos, with_labels=True, node_color='lightblue', edge_color='gray', node_size=2200, font_size=9)\nedge_labels = nx.get_edge_attributes(G, 'relation')\nnx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8)\nplt.title(\"Knowledge Graph: Organ Injuries and Relations to Any Injury\")\nplt.axis('off')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T16:13:55.386868Z","iopub.execute_input":"2025-04-29T16:13:55.387435Z","iopub.status.idle":"2025-04-29T16:13:56.270262Z","shell.execute_reply.started":"2025-04-29T16:13:55.387374Z","shell.execute_reply":"2025-04-29T16:13:56.269081Z"}},"outputs":[],"execution_count":null}]}