{"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":[{"sourceId":36363,"databundleVersionId":4050810,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport pandas as pd\nimport json\nimport numpy as np\nimport tensorflow as tf\nimport tensorflow_hub as hub\nfrom PIL import Image, ImageDraw, ImageFont\nimport matplotlib.pyplot as plt\nimport ipywidgets as widgets\nfrom IPython.display import display, HTML, clear_output\nimport io\nimport pydicom\nimport random\nimport cv2\nfrom scipy import ndimage\n\n# -------------------------------\n# 🛠 Enhanced Configuration\n# -------------------------------\nIMG_SIZE = 512\nCONFIDENCE_THRESHOLD = 0.3\nDEFAULT_IMAGE_SIZE = (1024, 1024)\nVERTEBRAE_NAMES = {1: \"C1\", 2: \"C2\", 3: \"C3\", 4: \"C4\", 5: \"C5\", 6: \"C6\", 7: \"C7\"}\n\n# -------------------------------\n# 🔍 Improved Kaggle Dataset Path Detection\n# -------------------------------\ndef find_dataset_path(filename):\n    \"\"\"Find file path in Kaggle input directory\"\"\"\n    for root, _, files in os.walk(\"/kaggle/input\"):\n        if filename in files:\n            return os.path.join(root, filename)\n    return None\n\ndef find_folder_path(foldername):\n    \"\"\"Find folder path in Kaggle input directory\"\"\"\n    for root, dirs, _ in os.walk(\"/kaggle/input\"):\n        if foldername in dirs:\n            return os.path.join(root, foldername)\n    return None\n\n# -------------------------------\n# 🩻 Enhanced Medical Image Processing\n# -------------------------------\nclass EnhancedFractureDetector:\n    def __init__(self):\n        self.model = None\n        self.df = None\n        self.IMAGE_DIR = None\n        self.load_datasets()\n        self.load_model()\n        \n    def load_datasets(self):\n        \"\"\"Load and prepare medical datasets with error handling\"\"\"\n        print(\"🔍 Locating datasets...\")\n        TRAIN_CSV = find_dataset_path(\"train.csv\")\n        self.IMAGE_DIR = find_folder_path(\"train_images\")\n        \n        # Load dataset if available\n        if TRAIN_CSV and os.path.exists(TRAIN_CSV):\n            print(f\"✅ Found train.csv at: {TRAIN_CSV}\")\n            self.df = pd.read_csv(TRAIN_CSV)\n            print(f\"Loaded {len(self.df)} records\")\n            # Add dummy slice numbers for visualization\n            self.df['Slice'] = [f\"{i:04d}\" for i in range(1, len(self.df)+1)]\n        else:\n            print(\"⚠️ train.csv not found. Using demo mode.\")\n            self.df = pd.DataFrame({\n                'StudyInstanceUID': ['demo_study'],\n                'Slice': ['0001'],\n                'patient_overall': [0]\n            })\n            \n        if not self.IMAGE_DIR:\n            print(\"⚠️ train_images folder not found. Using sample images.\")\n            self.IMAGE_DIR = \"/kaggle/input\"  # Fallback path\n    \n    def load_model(self):\n        \"\"\"Load the fracture detection model with improved initialization\"\"\"\n        print(\"\\n🚀 Loading fracture detection model...\")\n        LOCAL_KAGGLE_PATH = '/kaggle/input/tensorflow-efficientdet/tensorflow2/efficientdet/d0/1'\n        TFHUB_URL = \"https://tfhub.dev/tensorflow/efficientdet/d0/1\"\n        \n        try:\n            if os.path.exists(LOCAL_KAGGLE_PATH):\n                MODEL_PATH = LOCAL_KAGGLE_PATH\n                print(f\"✅ Using Kaggle model: {MODEL_PATH}\")\n            else:\n                MODEL_PATH = TFHUB_URL\n                print(f\"🌐 Using TF Hub model: {MODEL_PATH}\")\n                \n            self.model = hub.load(MODEL_PATH)\n            print(\"✅ Model loaded successfully\")\n        except Exception as e:\n            print(f\"❌ Model loading failed: {str(e)}\")\n            self.model = None\n    \n    def enhance_image_contrast(self, image):\n        \"\"\"Apply CLAHE contrast enhancement for better fracture visibility\"\"\"\n        if image.mode != 'L':\n            image = image.convert('L')\n        img_array = np.array(image)\n        clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))\n        enhanced = clahe.apply(img_array)\n        return Image.fromarray(enhanced).convert('RGB')\n    \n    def detect_fractures(self, image):\n        \"\"\"\n        Detect fractures with enhanced processing\n        Returns:\n            Tuple (annotated_image, fracture_count, highest_confidence, boxes_info)\n        \"\"\"\n        if self.model is None:\n            raise ValueError(\"Model not loaded\")\n        \n        try:\n            # Preprocess image with contrast enhancement\n            enhanced_img = self.enhance_image_contrast(image)\n            resized_img = enhanced_img.resize((IMG_SIZE, IMG_SIZE))\n            image_tensor = tf.cast(tf.convert_to_tensor(np.array(resized_img)), dtype=tf.uint8)[tf.newaxis, ...]\n            \n            # Run detection\n            predictions = self.model(image_tensor)\n            \n            # Process predictions\n            boxes = predictions['detection_boxes'][0].numpy()\n            scores = predictions['detection_scores'][0].numpy()\n            labels = predictions['detection_classes'][0].numpy().astype(int)\n            \n            # Filter predictions\n            valid_detections = scores > CONFIDENCE_THRESHOLD\n            confident_boxes = boxes[valid_detections]\n            confident_scores = scores[valid_detections]\n            confident_labels = labels[valid_detections]\n\n            # Annotate image\n            annotated_image = resized_img.copy()\n            draw = ImageDraw.Draw(annotated_image)\n            \n            fracture_count = 0\n            boxes_info = []\n            for box, score, label in zip(confident_boxes, confident_scores, confident_labels):\n                ymin, xmin, ymax, xmax = box\n                # Convert normalized coordinates to pixel values\n                left, right = xmin * IMG_SIZE, xmax * IMG_SIZE\n                top, bottom = ymin * IMG_SIZE, ymax * IMG_SIZE\n                \n                # Store box info for vertebrae mapping\n                box_info = {\n                    'coords': (left, top, right, bottom),\n                    'score': score,\n                    'label': label\n                }\n                boxes_info.append(box_info)\n                \n                # Draw bounding box\n                draw.rectangle([(left, top), (right, bottom)], outline=\"red\", width=3)\n                \n                # Label with confidence score\n                draw.text((left, top-20), f\"Fracture: {score:.2f}\", fill=\"red\")\n                fracture_count += 1\n\n            return annotated_image, fracture_count, confident_scores.max() if fracture_count > 0 else 0, boxes_info\n        except Exception as e:\n            print(f\"❌ Detection error: {str(e)}\")\n            return image, 0, 0, []\n\n    def map_to_vertebrae(self, boxes_info, original_size):\n        \"\"\"\n        Map detected boxes to cervical vertebrae regions\n        Returns list of tuples (vertebrae_name, confidence)\n        \"\"\"\n        if not boxes_info:\n            return []\n        \n        # Calculate vertical segments for vertebrae\n        height = original_size[1]\n        segment_height = height // 7\n        vertebrae_mapping = []\n        \n        for box in boxes_info:\n            left, top, right, bottom = box['coords']\n            # Scale box to original image size\n            center_y = (top + bottom) / 2 * (original_size[1] / IMG_SIZE)\n            \n            # Determine vertebrae position (C1-C7)\n            vertebrae_idx = min(7, max(1, int(center_y / segment_height) + 1))\n            vertebrae_name = VERTEBRAE_NAMES.get(vertebrae_idx, f\"C{vertebrae_idx}\")\n            \n            vertebrae_mapping.append((vertebrae_name, box['score']))\n        \n        return vertebrae_mapping\n    \n    def visualize_random_fracture(self):\n        \"\"\"Visualize a random fracture case from the dataset\"\"\"\n        if self.df is None or len(self.df) == 0:\n            print(\"⚠️ No dataset available for visualization\")\n            return\n            \n        # Select a random case\n        random_row = self.df.sample(1).iloc[0]\n        study_id = random_row['StudyInstanceUID']\n        slice_num = random_row['Slice']\n        \n        try:\n            # Construct DICOM path\n            dicom_path = os.path.join(self.IMAGE_DIR, study_id, f\"{slice_num}.dcm\")\n            \n            if not os.path.exists(dicom_path):\n                # Try alternative naming\n                dicom_path = os.path.join(self.IMAGE_DIR, study_id, f\"{int(slice_num):04d}.dcm\")\n            \n            if not os.path.exists(dicom_path):\n                print(f\"⚠️ DICOM file not found: {dicom_path}\")\n                return\n                \n            print(f\"\\n🔍 Visualizing: {study_id}/{slice_num}.dcm\")\n            \n            # Load DICOM\n            dcm = pydicom.dcmread(dicom_path)\n            image = Image.fromarray(dcm.pixel_array)\n            \n            # Detect fractures\n            result_img, fracture_count, max_conf, boxes_info = self.detect_fractures(image)\n            \n            # Map to vertebrae\n            vertebrae_results = self.map_to_vertebrae(boxes_info, image.size)\n            \n            # Create visualization\n            fig, ax = plt.subplots(1, 2, figsize=(20, 10))\n            \n            # Original image\n            ax[0].imshow(image, cmap='gray')\n            ax[0].set_title(\"Original Image\")\n            ax[0].axis('off')\n            \n            # Detection result\n            ax[1].imshow(result_img)\n            ax[1].set_title(f\"Fracture Detection: {fracture_count} regions found\")\n            ax[1].axis('off')\n            \n            # Add diagnostic report\n            report_text = f\"Diagnostic Report:\\n\"\n            report_text += f\"• Fractures detected: {fracture_count}\\n\"\n            report_text += f\"• Highest confidence: {max_conf:.2f}\\n\"\n            \n            if vertebrae_results:\n                report_text += \"\\nVertebrae involvement:\\n\"\n                for vertebrae, conf in vertebrae_results:\n                    report_text += f\"• {vertebrae}: {conf:.2f} confidence\\n\"\n            \n            plt.figtext(0.5, 0.01, report_text, ha=\"center\", fontsize=12, \n                        bbox={\"facecolor\":\"orange\", \"alpha\":0.2, \"pad\":5})\n            \n            plt.tight_layout()\n            plt.show()\n            \n        except Exception as e:\n            print(f\"❌ Visualization error: {str(e)}\")\n\n# -------------------------------\n# 📱 Enhanced Interactive Widget\n# -------------------------------\ndef create_enhanced_ui(detector):\n    \"\"\"Create interactive UI for fracture detection\"\"\"\n    # Create widgets\n    upload_btn = widgets.FileUpload(\n        accept='.jpg,.jpeg,.png,.dcm,.dicom',\n        description='Upload X-ray',\n        multiple=False\n    )\n    \n    threshold_slider = widgets.FloatSlider(\n        value=CONFIDENCE_THRESHOLD,\n        min=0.1,\n        max=0.9,\n        step=0.05,\n        description='Confidence:',\n        continuous_update=False\n    )\n    \n    sample_btn = widgets.Button(description=\"Show Random Sample\")\n    output_area = widgets.Output()\n    \n    # Button click handlers\n    def on_sample_click(b):\n        with output_area:\n            output_area.clear_output()\n            detector.visualize_random_fracture()\n            \n    def on_upload(change):\n        with output_area:\n            output_area.clear_output()\n            files = change['new']\n            if not files:\n                return\n                \n            file_info = files[0]\n            fname = file_info['name']\n            file_data = file_info['content']\n            global CONFIDENCE_THRESHOLD\n            CONFIDENCE_THRESHOLD = threshold_slider.value\n            \n            print(f\"\\n🔍 Analyzing: {fname} (Confidence: {CONFIDENCE_THRESHOLD})...\")\n            try:\n                # Handle DICOM files\n                if fname.lower().endswith(('.dcm', '.dicom')):\n                    dicom = pydicom.dcmread(io.BytesIO(file_data))\n                    image = Image.fromarray(dicom.pixel_array)\n                    original_img = image.copy()\n                # Handle standard images\n                else:\n                    image = Image.open(io.BytesIO(file_data))\n                    original_img = image.copy()\n                \n                # Run detection\n                result_img, fracture_count, max_conf, boxes_info = detector.detect_fractures(image)\n                vertebrae_results = detector.map_to_vertebrae(boxes_info, original_img.size)\n                \n                # Display results\n                fig, ax = plt.subplots(1, 2, figsize=(20, 10))\n                \n                # Original image\n                ax[0].imshow(original_img, cmap='gray')\n                ax[0].set_title(\"Original Image\")\n                ax[0].axis('off')\n                \n                # Detection result\n                ax[1].imshow(result_img)\n                ax[1].set_title(f\"Fracture Detection: {fracture_count} regions found\")\n                ax[1].axis('off')\n                \n                # Add diagnostic report\n                report_text = f\"Diagnostic Report:\\n\"\n                report_text += f\"• Fractures detected: {fracture_count}\\n\"\n                report_text += f\"• Highest confidence: {max_conf:.2f}\\n\"\n                report_text += f\"• Confidence threshold: {CONFIDENCE_THRESHOLD}\\n\"\n                \n                if vertebrae_results:\n                    report_text += \"\\nVertebrae involvement:\\n\"\n                    for vertebrae, conf in vertebrae_results:\n                        report_text += f\"• {vertebrae}: {conf:.2f} confidence\\n\"\n                \n                if fracture_count == 0:\n                    report_text += \"\\n✅ RESULT: No fractures detected\"\n                else:\n                    report_text += \"\\n⚠️ RESULT: Potential fractures detected - Clinical review recommended\"\n                \n                plt.figtext(0.5, 0.01, report_text, ha=\"center\", fontsize=12, \n                            bbox={\"facecolor\":\"orange\", \"alpha\":0.2, \"pad\":5})\n                \n                plt.tight_layout()\n                plt.show()\n                \n            except Exception as e:\n                print(f\"❌ Processing failed: {str(e)}\")\n    \n    # Connect handlers\n    sample_btn.on_click(on_sample_click)\n    upload_btn.observe(on_upload, names='value')\n    \n    # Create UI layout\n    controls = widgets.VBox([\n        widgets.HBox([upload_btn, sample_btn]),\n        threshold_slider\n    ])\n    \n    # Display UI\n    display(HTML(\"<h1 style='color:#1e3c72;'>🦴 Medical Fracture Detection System</h1>\"))\n    display(HTML(\"<p style='font-size:16px;'>Upload X-ray or DICOM image for fracture detection</p>\"))\n    display(controls)\n    display(output_area)\n\n# -------------------------------\n# 🚀 Initialize and Run System\n# -------------------------------\nprint(\"=\"*70)\nprint(\"🦴 ENHANCED MEDICAL FRACTURE DETECTION SYSTEM\")\nprint(\"=\"*70)\n\n# Initialize detector\ndetector = EnhancedFractureDetector()\n\n# Create UI\ncreate_enhanced_ui(detector)\n\nprint(\"\\n\" + \"=\"*70)\nprint(\"✅ SYSTEM READY - Upload an X-ray image or click 'Show Random Sample'\")\nprint(\"=\"*70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-15T20:48:54.730016Z","iopub.execute_input":"2025-08-15T20:48:54.730646Z","iopub.status.idle":"2025-08-15T20:50:16.515415Z","shell.execute_reply.started":"2025-08-15T20:48:54.730617Z","shell.execute_reply":"2025-08-15T20:50:16.514534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport tensorflow as tf\nimport tensorflow_hub as hub\nfrom PIL import Image, ImageDraw\nimport matplotlib.pyplot as plt\nimport ipywidgets as widgets\nfrom IPython.display import display\nimport io\nimport pydicom\n\n# Configuration settings\nIMG_SIZE = 512\nCONFIDENCE_THRESHOLD = 0.2  # Minimum confidence score for fracture detection\n\n# Model path configuration (Kaggle or TensorFlow Hub)\nLOCAL_KAGGLE_PATH = '/kaggle/input/tensorflow-efficientdet/tensorflow2/efficientdet/d0/1'\nTFHUB_URL = \"https://tfhub.dev/tensorflow/efficientdet/d0/1\"\n\n# Check for Kaggle model first\nif os.path.exists(LOCAL_KAGGLE_PATH):\n    MODEL_PATH = LOCAL_KAGGLE_PATH\n    print(f\"✅ Local Kaggle model found at: {MODEL_PATH}\")\nelse:\n    MODEL_PATH = TFHUB_URL\n    print(f\"🌐 Using TF Hub model: {MODEL_PATH}\")\n\n# Load EfficientDet model\nprint(\"🚀 Loading fracture detection model...\")\ndetector = hub.load(MODEL_PATH)\nprint(\"✅ Model loaded successfully\")\n\ndef detect_fractures(image, model, confidence_threshold=0.2):\n    \"\"\"\n    Detect fractures in medical images using EfficientDet model\n    Args:\n        image: PIL Image object\n        model: Pre-trained EfficientDet model\n        confidence_threshold: Minimum confidence score for detection\n    \n    Returns:\n        Annotated image with bounding boxes\n    \"\"\"\n    # Preprocess image\n    image = image.convert('RGB').resize((IMG_SIZE, IMG_SIZE))\n    image_tensor = tf.cast(tf.convert_to_tensor(np.array(image)), dtype=tf.uint8)[tf.newaxis, ...]\n    \n    # Run detection\n    predictions = model(image_tensor)\n    \n    # Process predictions\n    boxes = predictions['detection_boxes'][0].numpy()\n    scores = predictions['detection_scores'][0].numpy()\n    labels = predictions['detection_classes'][0].numpy().astype(int)\n    \n    # Filter predictions by confidence\n    valid_detections = scores > confidence_threshold\n    confident_boxes = boxes[valid_detections]\n    confident_scores = scores[valid_detections]\n    confident_labels = labels[valid_detections]\n\n    # Annotate image\n    annotated_image = image.copy()\n    draw = ImageDraw.Draw(annotated_image)\n    \n    fracture_count = 0\n    for box, score, label in zip(confident_boxes, confident_scores, confident_labels):\n        ymin, xmin, ymax, xmax = box\n        # Convert normalized coordinates to pixel values\n        left, right = xmin * IMG_SIZE, xmax * IMG_SIZE\n        top, bottom = ymin * IMG_SIZE, ymax * IMG_SIZE\n        \n        # Draw bounding box (medical fractures in red)\n        draw.rectangle([(left, top), (right, bottom)], outline=\"red\", width=3)\n        \n        # Label with confidence score\n        draw.text((left, top-20), f\"Fracture: {score:.2f}\", fill=\"red\")\n        fracture_count += 1\n\n    # Print diagnostic information\n    print(\"\\n\" + \"=\"*50)\n    print(\"DIAGNOSTIC REPORT:\")\n    print(f\"• Fractures detected: {fracture_count}\")\n    print(f\"• Confidence threshold: {confidence_threshold}\")\n    if fracture_count > 0:\n        print(f\"• Highest confidence: {confident_scores.max():.2f}\")\n    print(\"=\"*50 + \"\\n\")\n    \n    if fracture_count == 0:\n        print(\"✅ RESULT: No fractures detected with high confidence\")\n    else:\n        print(f\"⚠️ RESULT: Potential fractures detected ({fracture_count} regions)\")\n    \n    return annotated_image\n\n# File upload widget\nupload_btn = widgets.FileUpload(\n    accept='.jpg,.jpeg,.png,.dcm',\n    description='Upload X-ray',\n    multiple=False\n)\noutput_area = widgets.Output()\n\ndef process_upload(change):\n    \"\"\"Process uploaded medical images\"\"\"\n    with output_area:\n        output_area.clear_output()\n        files = upload_btn.value\n        \n        # Check if any files were uploaded\n        if not files:\n            print(\"⚠️ No files uploaded\")\n            return\n            \n        # Get first uploaded file (widget returns tuple of dicts)\n        file_info = files[0]  # Access first element in tuple\n        fname = file_info['name']\n        file_data = file_info['content']\n        \n        print(f\"\\n🔍 Analyzing: {fname}...\")\n        try:\n            # Handle DICOM files\n            if fname.lower().endswith('.dcm'):\n                dicom = pydicom.dcmread(io.BytesIO(file_data))\n                image = Image.fromarray(dicom.pixel_array)\n            # Handle standard images\n            else:\n                image = Image.open(io.BytesIO(file_data))\n            \n            # Run fracture detection\n            result = detect_fractures(image, detector, CONFIDENCE_THRESHOLD)\n            \n            # Display results\n            plt.figure(figsize=(12, 8))\n            plt.imshow(result)\n            plt.title(\"Fracture Detection Result\\n(Red boxes indicate potential fractures)\")\n            plt.axis('off')\n            plt.show()\n            \n        except Exception as error:\n            print(f\"❌ Processing failed: {str(error)}\")\n\n# Setup widget interaction\nupload_btn.observe(process_upload, names='value')\n\n# Display interface\nprint(\"\\n\" + \"=\"*50)\nprint(\"🩻 MEDICAL FRACTURE DETECTION SYSTEM\")\nprint(\"=\"*50)\nprint(\"➡️ Upload X-ray image (JPG/PNG) or DICOM scan:\")\ndisplay(upload_btn, output_area)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-15T20:35:28.506644Z","iopub.execute_input":"2025-08-15T20:35:28.507165Z","iopub.status.idle":"2025-08-15T20:36:47.639877Z","shell.execute_reply.started":"2025-08-15T20:35:28.507141Z","shell.execute_reply":"2025-08-15T20:36:47.639118Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# File upload widget\nupload_btn = widgets.FileUpload(\n    accept='.jpg,.jpeg,.png,.dcm',\n    description='Upload X-ray',\n    multiple=False\n)\noutput_area = widgets.Output()\n\ndef process_upload(change):\n    \"\"\"Process uploaded medical images\"\"\"\n    with output_area:\n        output_area.clear_output()\n        files = upload_btn.value\n        \n        # Check if any files were uploaded\n        if not files:\n            print(\"⚠️ No files uploaded\")\n            return\n            \n        # Get first uploaded file (widget returns tuple of dicts)\n        file_info = files[0]  # Access first element in tuple\n        fname = file_info['name']\n        file_data = file_info['content']\n        \n        print(f\"\\n🔍 Analyzing: {fname}...\")\n        try:\n            # Handle DICOM files\n            if fname.lower().endswith('.dcm'):\n                dicom = pydicom.dcmread(io.BytesIO(file_data))\n                image = Image.fromarray(dicom.pixel_array)\n            # Handle standard images\n            else:\n                image = Image.open(io.BytesIO(file_data))\n            \n            # Run fracture detection\n            result = detect_fractures(image, detector, CONFIDENCE_THRESHOLD)\n            \n            # Display results\n            plt.figure(figsize=(12, 8))\n            plt.imshow(result)\n            plt.title(\"Fracture Detection Result\\n(Red boxes indicate potential fractures)\")\n            plt.axis('off')\n            plt.show()\n            \n        except Exception as error:\n            print(f\"❌ Processing failed: {str(error)}\")\n\n# Setup widget interaction\nupload_btn.observe(process_upload, names='value')\n\n# Display interface\nprint(\"\\n\" + \"=\"*50)\nprint(\"🩻 MEDICAL FRACTURE DETECTION SYSTEM\")\nprint(\"=\"*50)\nprint(\"➡️ Upload X-ray image (JPG/PNG) or DICOM scan:\")\ndisplay(upload_btn, output_area)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-15T21:02:32.127709Z","iopub.execute_input":"2025-08-15T21:02:32.128546Z","iopub.status.idle":"2025-08-15T21:02:32.144998Z","shell.execute_reply.started":"2025-08-15T21:02:32.128513Z","shell.execute_reply":"2025-08-15T21:02:32.143943Z"}},"outputs":[],"execution_count":null}]}