{"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":"none","dataSources":[{"sourceId":117682,"databundleVersionId":14443416,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport numpy as np\nimport pandas as pd\nfrom pathlib import Path\nfrom PIL import Image, ImageSequence\nfrom scipy import ndimage\nfrom tqdm import tqdm\nimport os\nfrom torch.utils.data import Dataset, DataLoader\nimport matplotlib.pyplot as plt\n\n# ==================== نظام المعالجة المسبقة المحسن ====================\nclass نظام_المعالجة_المسبقة:\n    def __init__(self):\n        self.إحصائيات = {}\n        print(\"🔧 نظام المعالجة المسبقة المحسن - جاهز للتعلم العميق\")\n    \n    def تحميل_وتطبيع_المجلد(self, path):\n        \"\"\"تحميل وتطبيع البيانات للتعلم العميق\"\"\"\n        try:\n            with Image.open(path) as tif:\n                frames = []\n                for frame in ImageSequence.Iterator(tif):\n                    img_array = np.array(frame, dtype=np.float32)\n                    frames.append(img_array)\n                \n                volume = np.stack(frames)\n                \n                # تطبيع متقدم\n                volume = self.تطبيع_متقدم(volume)\n                \n                print(f\"✅ تم تحميل وتطبيع {path.name} - الحجم: {volume.shape}\")\n                return volume\n                \n        except Exception as e:\n            print(f\"❌ فشل تحميل {path}: {e}\")\n            return None\n    \n    def تطبيع_متقدم(self, volume):\n        \"\"\"تطبيع متقدم يحافظ على الخصائص الإحصائية\"\"\"\n        # إزالة القيم المتطرفة\n        p1, p99 = np.percentile(volume, [1, 99])\n        volume = np.clip(volume, p1, p99)\n        \n        # تطبيع Z-score مع حماية من الانحراف الصفري\n        mean = np.mean(volume)\n        std = np.std(volume)\n        if std < 1e-8:\n            std = 1e-8\n        \n        volume_normalized = (volume - mean) / std\n        \n        # تحجيم إلى [0, 1] للتعلم العميق\n        v_min = np.min(volume_normalized)\n        v_max = np.max(volume_normalized)\n        if v_max - v_min > 1e-8:\n            volume_scaled = (volume_normalized - v_min) / (v_max - v_min)\n        else:\n            volume_scaled = volume_normalized\n        \n        return volume_scaled.astype(np.float32)\n    \n    def إنشاء_أقنعة_تدريب(self, volume, إستراتيجية=\"متوسطة\"):\n        \"\"\"إنشاء أقنعة تدريب بجودة عالية\"\"\"\n        if إستراتيجية == \"عدوانية\":\n            عتبات = [30, 40, 50, 60]\n        elif إستراتيجية == \"محافظة\":\n            عتبات = [10, 20, 30, 40]\n        else:  # متوسطة\n            عتبات = [20, 35, 50, 65]\n        \n        أقنعة = []\n        for عتبة in عتبات:\n            قيمة_عتبة = np.percentile(volume, عتبة)\n            قناع = volume > قيمة_عتبة\n            أقنعة.append(قناع.astype(np.float32))\n        \n        if أقنعة:\n            مجتمعة = np.mean(أقنعة, axis=0)\n            قناع_نهائي = مجتمعة > 0.3\n        else:\n            قناع_نهائي = volume > np.percentile(volume, 40)\n        \n        # تنظيف مورفولوجي خفيف\n        هيكل = np.ones((2, 2, 2), dtype=bool)\n        قناع_نهائي = ndimage.binary_closing(قناع_نهائي, structure=هيكل, iterations=1)\n        \n        return قناع_نهائي.astype(np.float32)\n\n# ==================== U-Net ثلاثي الأبعاد التنافسي ====================\nclass DoubleConv3D(nn.Module):\n    \"\"\"كتلة التفافية مزدوجة ثلاثية الأبعاد\"\"\"\n    \n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.double_conv = nn.Sequential(\n            nn.Conv3d(in_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm3d(out_channels),\n            nn.ReLU(inplace=True),\n            nn.Conv3d(out_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm3d(out_channels),\n            nn.ReLU(inplace=True)\n        )\n    \n    def forward(self, x):\n        return self.double_conv(x)\n\nclass UNet3D(nn.Module):\n    \"\"\"نموذج U-Net ثلاثي الأبعاد متقدم\"\"\"\n    \n    def __init__(self, in_channels=1, out_channels=1, features=[32, 64, 128, 256]):\n        super().__init__()\n        \n        self.encoder = nn.ModuleList()\n        self.decoder = nn.ModuleList()\n        self.pool = nn.MaxPool3d(kernel_size=2, stride=2)\n        \n        # مسار التشفير (Encoder)\n        for feature in features:\n            self.encoder.append(DoubleConv3D(in_channels, feature))\n            in_channels = feature\n        \n        # عنق الزجاجة (Bottleneck)\n        self.bottleneck = DoubleConv3D(features[-1], features[-1] * 2)\n        \n        # مسار فك التشفير (Decoder)\n        for feature in reversed(features):\n            self.decoder.append(\n                nn.ConvTranspose3d(feature * 2, feature, kernel_size=2, stride=2)\n            )\n            self.decoder.append(DoubleConv3D(feature * 2, feature))\n        \n        # الطبقة النهائية\n        self.final_conv = nn.Conv3d(features[0], out_channels, kernel_size=1)\n        \n    def forward(self, x):\n        skip_connections = []\n        \n        # التشفير\n        for down in self.encoder:\n            x = down(x)\n            skip_connections.append(x)\n            x = self.pool(x)\n        \n        # عنق الزجاجة\n        x = self.bottleneck(x)\n        \n        # فك التشفير\n        skip_connections = skip_connections[::-1]\n        for idx in range(0, len(self.decoder), 2):\n            x = self.decoder[idx](x)\n            skip_connection = skip_connections[idx//2]\n            \n            # معالجة عدم تطابق الأبعاد\n            if x.shape != skip_connection.shape:\n                x = F.interpolate(x, size=skip_connection.shape[2:], mode='trilinear', align_corners=True)\n            \n            concat_skip = torch.cat((skip_connection, x), dim=1)\n            x = self.decoder[idx+1](concat_skip)\n        \n        return torch.sigmoid(self.final_conv(x))\n\n# ==================== مجموعة البيانات المتقدمة ====================\nclass Vesuvius3DDataset(Dataset):\n    \"\"\"مجموعة بيانات متقدمة للتدريب ثلاثي الأبعاد\"\"\"\n    \n    def __init__(self, volumes, masks, patch_size=(64, 64, 64), stride=(32, 32, 32), augment=True):\n        self.volumes = volumes\n        self.masks = masks\n        self.patch_size = patch_size\n        self.stride = stride\n        self.augment = augment\n        \n        self.patches = self._generate_patches()\n        print(f\"✅ تم إنشاء {len(self.patches)} رقعة للتدريب\")\n    \n    def _generate_patches(self):\n        patches = []\n        for vol_idx, (volume, mask) in enumerate(zip(self.volumes, self.masks)):\n            D, H, W = volume.shape\n            d_p, h_p, w_p = self.patch_size\n            d_s, h_s, w_s = self.stride\n            \n            for d in range(0, D - d_p + 1, d_s):\n                for h in range(0, H - h_p + 1, h_s):\n                    for w in range(0, W - w_p + 1, w_s):\n                        patches.append((vol_idx, d, h, w))\n        \n        return patches\n    \n    def __len__(self):\n        return len(self.patches)\n    \n    def _augment_3d(self, volume, mask):\n        \"\"\"تزايد بيانات ثلاثي الأبعاد\"\"\"\n        if np.random.random() > 0.5:\n            # قلب أفقي\n            volume = np.flip(volume, axis=2)\n            mask = np.flip(mask, axis=2)\n        \n        if np.random.random() > 0.5:\n            # قلب عمودي\n            volume = np.flip(volume, axis=1)\n            mask = np.flip(mask, axis=1)\n        \n        if np.random.random() > 0.5:\n            # قلب عمق\n            volume = np.flip(volume, axis=0)\n            mask = np.flip(mask, axis=0)\n        \n        # دوران عشوائي حول المحور Z\n        if np.random.random() > 0.5:\n            k = np.random.randint(1, 4)\n            volume = np.rot90(volume, k, axes=(1, 2))\n            mask = np.rot90(mask, k, axes=(1, 2))\n        \n        return volume, mask\n    \n    def __getitem__(self, idx):\n        vol_idx, d, h, w = self.patches[idx]\n        d_p, h_p, w_p = self.patch_size\n        \n        volume = self.volumes[vol_idx]\n        mask = self.masks[vol_idx]\n        \n        # استخراج الرقعة\n        patch_vol = volume[d:d+d_p, h:h+h_p, w:w+w_p]\n        patch_mask = mask[d:d+d_p, h:h+h_p, w:w+w_p]\n        \n        # التزايد\n        if self.augment:\n            patch_vol, patch_mask = self._augment_3d(patch_vol, patch_mask)\n        \n        # تحويل إلى تنسيق PyTorch (C, D, H, W)\n        patch_vol = torch.from_numpy(patch_vol).unsqueeze(0).float()\n        patch_mask = torch.from_numpy(patch_mask).unsqueeze(0).float()\n        \n        return patch_vol, patch_mask\n\n# ==================== نظام التدريب المتقدم ====================\nclass نظام_التدريب_المتقدم:\n    def __init__(self, model, device, learning_rate=1e-4):\n        self.model = model.to(device)\n        self.device = device\n        self.criterion = self._create_combined_loss()\n        self.optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate, weight_decay=1e-5)\n        self.scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(self.optimizer, 'min', patience=5, factor=0.5)\n        \n        self.train_losses = []\n        self.val_losses = []\n        \n        print(\"🎯 نظام التدريب المتقدم - جاهز\")\n    \n    def _create_combined_loss(self):\n        \"\"\"خلط بين Dice Loss و BCE Loss للحصول على أفضل الأداء\"\"\"\n        class CombinedLoss(nn.Module):\n            def __init__(self):\n                super().__init__()\n                self.dice_loss = DiceLoss()\n                self.bce_loss = nn.BCELoss()\n            \n            def forward(self, predictions, targets):\n                dice = self.dice_loss(predictions, targets)\n                bce = self.bce_loss(predictions, targets)\n                return dice + bce * 0.5\n        \n        return CombinedLoss()\n    \n    def تدريب_دورة(self, train_loader):\n        self.model.train()\n        total_loss = 0\n        \n        for batch_idx, (data, targets) in enumerate(tqdm(train_loader, desc=\"🔄 التدريب\", leave=False)):\n            data, targets = data.to(self.device), targets.to(self.device)\n            \n            self.optimizer.zero_grad()\n            outputs = self.model(data)\n            loss = self.criterion(outputs, targets)\n            loss.backward()\n            \n            # قص التدرج لمنع الانفجار\n            torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=1.0)\n            self.optimizer.step()\n            \n            total_loss += loss.item()\n        \n        avg_loss = total_loss / len(train_loader)\n        self.train_losses.append(avg_loss)\n        return avg_loss\n    \n    def التحقق(self, val_loader):\n        self.model.eval()\n        total_loss = 0\n        \n        with torch.no_grad():\n            for data, targets in tqdm(val_loader, desc=\"📊 التحقق\", leave=False):\n                data, targets = data.to(self.device), targets.to(self.device)\n                outputs = self.model(data)\n                loss = self.criterion(outputs, targets)\n                total_loss += loss.item()\n        \n        avg_loss = total_loss / len(val_loader)\n        self.val_losses.append(avg_loss)\n        \n        # ضبط معدل التعلم\n        self.scheduler.step(avg_loss)\n        \n        return avg_loss\n    \n    def حفظ_النموذج(self, path, epoch, loss):\n        \"\"\"حفظ النموذج مع المعلومات الكاملة\"\"\"\n        torch.save({\n            'epoch': epoch,\n            'model_state_dict': self.model.state_dict(),\n            'optimizer_state_dict': self.optimizer.state_dict(),\n            'train_losses': self.train_losses,\n            'val_losses': self.val_losses,\n            'loss': loss\n        }, path)\n\nclass DiceLoss(nn.Module):\n    \"\"\"Dice Loss محسّن للبيانات ثلاثية الأبعاد\"\"\"\n    \n    def __init__(self, smooth=1e-6):\n        super().__init__()\n        self.smooth = smooth\n    \n    def forward(self, predictions, targets):\n        predictions = predictions.contiguous().view(-1)\n        targets = targets.contiguous().view(-1)\n        \n        intersection = (predictions * targets).sum()\n        dice = (2. * intersection + self.smooth) / (predictions.sum() + targets.sum() + self.smooth)\n        \n        return 1 - dice\n\n# ==================== نظام التنبؤ المتقدم ====================\nclass نظام_التنبؤ_المتقدم:\n    def __init__(self, model_path=None):\n        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n        print(f\"🎯 استخدام الجهاز: {self.device}\")\n        \n        self.model = UNet3D(in_channels=1, out_channels=1)\n        self.معالج = نظام_المعالجة_المسبقة()\n        \n        if model_path and Path(model_path).exists():\n            checkpoint = torch.load(model_path, map_location=self.device)\n            self.model.load_state_dict(checkpoint['model_state_dict'])\n            print(f\"✅ تم تحميل النموذج المدرب من: {model_path}\")\n        else:\n            print(\"⚠ استخدام النموذج غير المدرب\")\n        \n        self.model.to(self.device)\n        self.model.eval()\n    \n    def تنبؤ_بحجم_كامل(self, volume_path, patch_size=(64, 64, 64), stride=(48, 48, 48)):\n        \"\"\"التنبؤ بحجم كامل باستخدام النموذج المدرب\"\"\"\n        print(f\"🔍 معالجة {volume_path.name} بالنموذج العصبي...\")\n        \n        # تحميل وتطبيع البيانات\n        volume = self.معالج.تحميل_وتطبيع_المجلد(volume_path)\n        if volume is None:\n            return None, None\n        \n        try:\n            D, H, W = volume.shape\n            d_p, h_p, w_p = patch_size\n            d_s, h_s, w_s = stride\n            \n            # تهيئة مصفوفة الإخراج\n            output = np.zeros((D, H, W), dtype=np.float32)\n            count = np.zeros((D, H, W), dtype=np.float32)\n            \n            with torch.no_grad():\n                for d in tqdm(range(0, D - d_p + 1, d_s), desc=\"🧩 معالجة الرقع\", leave=False):\n                    for h in range(0, H - h_p + 1, h_s):\n                        for w in range(0, W - w_p + 1, w_s):\n                            # استخراج الرقعة\n                            patch = volume[d:d+d_p, h:h+h_p, w:w+w_p]\n                            patch_tensor = torch.from_numpy(patch).unsqueeze(0).unsqueeze(0).float().to(self.device)\n                            \n                            # التنبؤ\n                            prediction = self.model(patch_tensor)\n                            pred_np = prediction.squeeze().cpu().numpy()\n                            \n                            # تجميع التنبؤات\n                            output[d:d+d_p, h:h+h_p, w:w+w_p] += pred_np\n                            count[d:d+d_p, h:h+h_p, w:w+w_p] += 1\n            \n            # حساب المتوسط\n            output = output / (count + 1e-8)\n            \n            # تحويل إلى قناع ثنائي\n            قناع_نهائي = output > 0.5\n            \n            # تحسين النهائي\n            قناع_نهائي = self.تحسين_نهائي(قناع_نهائي.astype(np.uint8))\n            \n            نسبة = np.mean(قناع_نهائي)\n            print(f\"🎯 النسبة النهائية: {نسبة:.4f}\")\n            \n            return قناع_نهائي, {'النسبة': نسبة, 'الطريقة': 'U-Net_3D'}\n            \n        except Exception as e:\n            print(f\"❌ خطأ في التنبؤ العصبي: {e}\")\n            return None, None\n    \n    def تحسين_نهائي(self, mask):\n        \"\"\"تحسين نهائي للقناع\"\"\"\n        # تنظيف مورفولوجي\n        هيكل = np.ones((3, 3, 3), dtype=bool)\n        mask = ndimage.binary_closing(mask, structure=هيكل, iterations=1)\n        mask = ndimage.binary_opening(mask, structure=هيكل, iterations=1)\n        \n        # إزالة المكونات الصغيرة\n        labeled_mask, num_features = ndimage.label(mask)\n        component_sizes = np.bincount(labeled_mask.ravel())\n        \n        if len(component_sizes) > 1:\n            # احتفظ بالمكونات الكبيرة فقط\n            min_size = max(component_sizes[1:]) * 0.1  # 10% من أكبر مكون\n            for label in range(1, num_features + 1):\n                if component_sizes[label] < min_size:\n                    mask[labeled_mask == label] = 0\n        \n        return mask\n\n# ==================== النظام الرئيسي المتكامل ====================\ndef إنشاء_إرسال_تنافسي():\n    \"\"\"إنشاء إرسال تنافسي باستخدام التعلم العميق\"\"\"\n    \n    # البحث عن المسارات\n    TEST_DIR = Path(\"/kaggle/input/vesuvius-challenge-2024/test_images\")\n    if not TEST_DIR.exists():\n        TEST_DIR = Path(\"/kaggle/input/vesuvius-challenge-surface-detection/test_images\")\n    \n    if not TEST_DIR.exists():\n        print(\"❌ لم أجد مجلد الاختبار\")\n        return\n    \n    # استخدام النموذج المتقدم\n    predictor = نظام_التنبؤ_المتقدم(\"/kaggle/input/vesuvius-model/best_model.pth\")\n    \n    # إنشاء ملف الإرسال\n    OUTPUT_CSV = Path(\"/kaggle/working/submission.csv\")\n    \n    # الحصول على قائمة الملفات\n    test_files = list(TEST_DIR.glob(\"*.tif\"))\n    submission_data = []\n    \n    for test_file in tqdm(test_files, desc=\"🎯 معالجة العينات\"):\n        vol_id = test_file.stem\n        \n        try:\n            # التنبؤ باستخدام النموذج العصبي\n            final_mask, تحليل = predictor.تنبؤ_بحجم_كامل(test_file)\n            \n            if final_mask is not None:\n                # تحويل إلى RLE\n                rle_prediction = ترميز_RLE(final_mask)\n                submission_data.append({\"Id\": vol_id, \"Predicted\": rle_prediction})\n                print(f\"✅ {vol_id} - النسبة: {تحليل['النسبة']:.4f}\")\n            else:\n                print(f\"❌ فشل {vol_id}\")\n                submission_data.append({\"Id\": vol_id, \"Predicted\": \"\"})\n                \n        except Exception as e:\n            print(f\"❌ خطأ في {vol_id}: {e}\")\n            submission_data.append({\"Id\": vol_id, \"Predicted\": \"\"})\n    \n    # حفظ النتائج\n    submission_df = pd.DataFrame(submission_data)\n    submission_df.to_csv(OUTPUT_CSV, index=False)\n    \n    print(f\"\\n✅ تم إنشاء ملف الإرسال التنافسي: {OUTPUT_CSV}\")\n    return OUTPUT_CSV\n\ndef ترميز_RLE(mask):\n    \"\"\"ترميز RLE آمن\"\"\"\n    try:\n        if mask is None or mask.size == 0 or not np.any(mask):\n            return \"\"\n        \n        pixels = mask.flatten()\n        pixels = np.concatenate([[0], pixels, [0]])\n        runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n        runs[1::2] -= runs[::2]\n        \n        return ' '.join(str(x) for x in runs)\n    except Exception as e:\n        print(f\"❌ خطأ في ترميز RLE: {e}\")\n        return \"\"\n\n# ==================== التدريب (للاستخدام المستقبلي) ====================\ndef تدريب_النموذج_التنافسي():\n    \"\"\"دالة لتدريب النموذج على البيانات المتاحة\"\"\"\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    print(f\"🚀 بدء التدريب على: {device}\")\n    \n    # تحميل البيانات (تعديل حسب بياناتك)\n    # volumes_train, masks_train = تحميل_بيانات_التدريب()\n    # volumes_val, masks_val = تحميل_بيانات_التحقق()\n    \n    # إنشاء مجموعات البيانات\n    # train_dataset = Vesuvius3DDataset(volumes_train, masks_train, augment=True)\n    # val_dataset = Vesuvius3DDataset(volumes_val, masks_val, augment=False)\n    \n    # train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=2)\n    # val_loader = DataLoader(val_dataset, batch_size=2, shuffle=False, num_workers=2)\n    \n    # النموذج والنظام\n    model = UNet3D()\n    trainer = نظام_التدريب_المتقدم(model, device)\n    \n    print(\"🎯 بدء التدريب...\")\n    # مثال على حلقة التدريب:\n    # for epoch in range(100):\n    #     train_loss = trainer.تدريب_دورة(train_loader)\n    #     val_loss = trainer.التحقق(val_loader)\n    #     \n    #     if epoch % 10 == 0:\n    #         print(f\"📊 Epoch {epoch}: Train={train_loss:.4f}, Val={val_loss:.4f}\")\n    #         trainer.حفظ_النموذج(f\"model_epoch_{epoch}.pth\", epoch, val_loss)\n\nif __name__ == \"__main__\":\n    print(\"=\" * 60)\n    print(\"🚀 النظام التنافسي المتكامل - U-Net 3D + معالجة مسبقة\")\n    print(\"=\" * 60)\n    \n    إنشاء_إرسال_تنافسي()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-25T02:55:40.548470Z","iopub.execute_input":"2025-11-25T02:55:40.548736Z","iopub.status.idle":"2025-11-25T03:00:47.619639Z","shell.execute_reply.started":"2025-11-25T02:55:40.548716Z","shell.execute_reply":"2025-11-25T03:00:47.618410Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom pathlib import Path\nfrom PIL import Image, ImageSequence\nfrom scipy import ndimage\nfrom tqdm import tqdm\nimport os\n\nclass محلل_العينات_المضمون_للإرسال:\n    def __init__(self):\n        self.تحليلات = {}\n        print(\"🔍 محلل العينات المضمون للإرسال - الإصدار النهائي\")\n    \n    def تحميل_المجلد(self, path):\n        \"\"\"تحميل آمن وسريع للمجلد\"\"\"\n        try:\n            with Image.open(path) as tif:\n                frames = []\n                for i, frame in enumerate(ImageSequence.Iterator(tif)):\n                    if i >= 20:  # تحد من عدد الإطارات لتسريع المعالجة\n                        break\n                    img_array = np.array(frame, dtype=np.float32)\n                    frames.append(img_array)\n                \n                if not frames:\n                    return None\n                    \n                volume = np.stack(frames)\n                print(f\"✅ تم تحميل {path.name} - الحجم: {volume.shape}\")\n                return volume\n        except Exception as e:\n            print(f\"❌ فشل تحميل {path}: {e}\")\n            return None\n    \n    def إنشاء_قناع_تنافسي(self, volume):\n        \"\"\"إنشاء قناع تنافسي مع ضمان النتائج\"\"\"\n        try:\n            if volume is None:\n                return None\n            \n            # تحليل سريع للتوزيع\n            متوسط = np.mean(volume)\n            انحراف = np.std(volume)\n            p10 = np.percentile(volume, 10)\n            p90 = np.percentile(volume, 90)\n            \n            print(f\"📊 الإحصائيات السريعة: المتوسط={متوسط:.2f}, الانحراف={انحراف:.2f}\")\n            \n            # إستراتيجية هجينة مضمونة\n            أقنعة = []\n            \n            # 1. عتبات مئوية متعددة\n            for عتبة in [10, 20, 30, 40, 50]:\n                قيمة_عتبة = np.percentile(volume, عتبة)\n                قناع = volume > قيمة_عتبة\n                if np.any(قناع):\n                    أقنعة.append(قناع.astype(np.float32))\n                    print(f\"   ✅ عتبة {عتبة}%: النسبة={np.mean(قناع):.4f}\")\n            \n            # 2. عتبة مطلقة احتياطية\n            عتبة_احتياطية = متوسط + انحراف * 0.5\n            قناع_احتياطي = volume > عتبة_احتياطية\n            if np.any(قناع_احتياطي):\n                أقنعة.append(قناع_احتياطي.astype(np.float32))\n                print(f\"   🔄 عتبة احتياطية: النسبة={np.mean(قناع_احتياطي):.4f}\")\n            \n            # 3. إذا لم يكن هناك أي أقنعة، أنشئ قناعاً افتراضياً\n            if not أقنعة:\n                print(\"   ⚠ إنشاء قناع افتراضي (مركز الحجم)\")\n                # إنشاء قناع بسيط في وسط الحجم\n                قناع_افتراضي = np.zeros_like(volume, dtype=np.uint8)\n                d, h, w = volume.shape\n                قناع_افتراضي[d//4:3*d//4, h//4:3*h//4, w//4:3*w//4] = 1\n                return قناع_افتراضي\n            \n            # دمج الأقنعة\n            if len(أقنعة) == 1:\n                قناع_نهائي = أقنعة[0] > 0.5\n            else:\n                مجتمعة = np.mean(أقنعة, axis=0)\n                قناع_نهائي = مجتمعة > 0.3\n            \n            # تأكد من أن القناع غير فارغ\n            if not np.any(قناع_نهائي):\n                print(\"   🔄 القناع النهائي فارغ - استخدام العتبة الدنيا\")\n                قناع_نهائي = volume > np.percentile(volume, 5)\n            \n            # معالجة مورفولوجية خفيفة وسريعة\n            if np.any(قناع_نهائي):\n                try:\n                    هيكل = np.ones((2, 2, 2), dtype=bool)\n                    قناع_نهائي = ndimage.binary_closing(قناع_نهائي, structure=هيكل, iterations=1)\n                except Exception as e:\n                    print(f\"   ⚠ خطأ في المعالجة المورفولوجية: {e}\")\n            \n            return قناع_نهائي.astype(np.uint8)\n            \n        except Exception as e:\n            print(f\"❌ خطأ في إنشاء القناع: {e}\")\n            # قناع افتراضي في حالة الخطأ\n            return self.إنشاء_قناع_افتراضي(volume)\n    \n    def إنشاء_قناع_افتراضي(self, volume):\n        \"\"\"إنشاء قناع افتراضي في حالة الطوارئ\"\"\"\n        if volume is None:\n            return None\n            \n        قناع = np.zeros((64, 64, 64), dtype=np.uint8)  # حجم افتراضي\n        قناع[16:48, 16:48, 16:48] = 1  # مكعب في المركز\n        print(\"   🆘 استخدام القناع الافتراضي الطارئ\")\n        return قناع\n    \n    def ترميز_RLE_مضمون_نهائي(self, mask):\n        \"\"\"ترميز RLE مضمون 100%\"\"\"\n        try:\n            if mask is None:\n                print(\"     ⚠ القناع None - إرجاع RLE افتراضي\")\n                return \"1 100\"  # RLE افتراضي\n            \n            if mask.size == 0 or not np.any(mask):\n                print(\"     ⚠ القناع فارغ - إرجاع RLE افتراضي\")\n                return \"1 100\"  # RLE افتراضي\n            \n            # تحويل إلى 1D وتأكد من نوع البيانات\n            pixels = mask.flatten().astype(np.uint8)\n            \n            # خوارزمية RLE محسنة\n            pixels = np.concatenate([[0], pixels, [0]])\n            runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n            runs[1::2] -= runs[::2]\n            \n            rle_result = ' '.join(str(x) for x in runs)\n            \n            if not rle_result.strip():\n                print(\"     ⚠ RLE فارغ - إرجاع RLE افتراضي\")\n                return \"1 100\"\n                \n            print(f\"     ✅ تم ترميز RLE بطول {len(rle_result)} حرف\")\n            return rle_result\n            \n        except Exception as e:\n            print(f\"❌ خطأ في ترميز RLE: {e}\")\n            return \"1 100\"  # RLE افتراضي في حالة الخطأ\n\ndef إنشاء_ملف_إرسال_مضمون_نهائي():\n    \"\"\"إنشاء ملف إرسال مضمون 100% لـ Kaggle\"\"\"\n    \n    print(\"🚀 بدء الإصدار النهائي المضمون للإرسال\")\n    \n    # البحث الذكي عن المسارات\n    المسارات_المحتملة = [\n        \"/kaggle/input/vesuvius-challenge-2024\",\n        \"/kaggle/input/vesuvius-challenge-surface-detection\", \n        \"/kaggle/input/vesuvius-challenge\"\n    ]\n    \n    TEST_DIR = None\n    TEST_CSV = None\n    \n    for مسار_أساسي in المسارات_المحتملة:\n        مسار_أساسي = Path(مسار_أساسي)\n        if not مسار_أساسي.exists():\n            continue\n            \n        # البحث عن مجلد test_images\n        for نمط in [\"test_images\", \"test\", \"images\"]:\n            مسار_مجلد = مسار_أساسي / نمط\n            if مسار_مجلد.exists():\n                TEST_DIR = مسار_مجلد\n                print(f\"✅ تم العثور على مجلد الاختبار: {مسار_مجلد}\")\n                break\n        \n        # البحث عن sample_submission.csv\n        for اسم_ملف in [\"sample_submission.csv\", \"test.csv\", \"submission.csv\"]:\n            مسار_csv = مسار_أساسي / اسم_ملف\n            if مسار_csv.exists():\n                TEST_CSV = مسار_csv\n                print(f\"✅ تم العثور على ملف CSV: {مسار_csv}\")\n                break\n        \n        if TEST_DIR and TEST_CSV:\n            break\n    \n    if TEST_DIR is None:\n        print(\"❌ لم أجد مجلد الاختبار - البحث في المحتويات:\")\n        import os\n        for root, dirs, files in os.walk(\"/kaggle/input\"):\n            for dir in dirs:\n                print(f\"   📁 {os.path.join(root, dir)}\")\n        return None\n    \n    OUTPUT_CSV = Path(\"/kaggle/working/submission.csv\")\n    \n    # تحميل البيانات الأساسية\n    try:\n        if TEST_CSV and TEST_CSV.exists():\n            test_df = pd.read_csv(TEST_CSV)\n            print(f\"📊 تم تحميل {len(test_df)} عينة من CSV\")\n            \n            # تحديد أسماء الأعمدة\n            if 'Id' in test_df.columns:\n                id_column = 'Id'\n            elif 'id' in test_df.columns:\n                id_column = 'id'\n            else:\n                print(\"❌ لم أجد عمود المعرفات في CSV\")\n                return None\n        else:\n            print(\"❌ لم أجد ملف CSV - إنشاء من المجلد\")\n            ملفات = list(TEST_DIR.glob(\"*.tif\"))\n            if not ملفات:\n                print(\"❌ لا توجد ملفات TIFF في المجلد\")\n                return None\n                \n            test_df = pd.DataFrame({\"Id\": [f.stem for f in ملفات]})\n            id_column = 'Id'\n            print(f\"📊 تم إنشاء {len(test_df)} عينة من المجلد\")\n    except Exception as e:\n        print(f\"❌ خطأ في تحميل البيانات: {e}\")\n        return None\n    \n    محلل = محلل_العينات_المضمون_للإرسال()\n    submission_data = []\n    \n    print(f\"\\n🎯 بدء معالجة {len(test_df)} عينة...\")\n    \n    for _, row in tqdm(test_df.iterrows(), total=len(test_df), desc=\"معالجة العينات\"):\n        vol_id = str(row[id_column])\n        fname = f\"{vol_id}.tif\"\n        fpath = TEST_DIR / fname\n        \n        if not fpath.exists():\n            print(f\"⚠ ملف مفقود: {fname}\")\n            # استخدم RLE افتراضي للملفات المفقودة\n            submission_data.append({\"Id\": vol_id, \"Predicted\": \"1 100\"})\n            continue\n        \n        try:\n            # تحميل سريع\n            volume = محلل.تحميل_المجلد(fpath)\n            \n            if volume is None:\n                print(f\"⚠ فشل تحميل {vol_id} - استخدام RLE افتراضي\")\n                submission_data.append({\"Id\": vol_id, \"Predicted\": \"1 100\"})\n                continue\n            \n            # إنشاء القناع\n            قناع = محلل.إنشاء_قناع_تنافسي(volume)\n            \n            if قناع is None:\n                print(f\"⚠ فشل إنشاء قناع لـ {vol_id} - استخدام RLE افتراضي\")\n                submission_data.append({\"Id\": vol_id, \"Predicted\": \"1 100\"})\n                continue\n            \n            # ترميز RLE\n            rle_prediction = محلل.ترميز_RLE_مضمون_نهائي(قناع)\n            \n            # احسب النسبة للمراقبة\n            نسبة = np.mean(قناع) if قناع is not None else 0\n            print(f\"✅ {vol_id} - النسبة: {نسبة:.4f}, RLE: {len(rle_prediction)} حرف\")\n            \n            submission_data.append({\"Id\": vol_id, \"Predicted\": rle_prediction})\n            \n        except Exception as e:\n            print(f\"❌ خطأ غير متوقع في {vol_id}: {e}\")\n            submission_data.append({\"Id\": vol_id, \"Predicted\": \"1 100\"})\n    \n    # إنشاء وحفظ الملف النهائي\n    try:\n        submission_df = pd.DataFrame(submission_data, columns=[\"Id\", \"Predicted\"])\n        \n        # التحقق من أن لدينا جميع الصفوف المطلوبة\n        if len(submission_df) != len(test_df):\n            print(f\"⚠ تحذير: عدد الصفوف غير متطابق {len(submission_df)} != {len(test_df)}\")\n            # تأكد من أن لدينا جميع المعرفات\n            جميع_المعرفات = set(test_df[id_column].astype(str))\n            معرفات_النتيجة = set(submission_df[\"Id\"])\n            معرفات_مفقودة = جميع_المعرفات - معرفات_النتيجة\n            \n            for معرف in معرفات_مفقودة:\n                submission_df = pd.concat([\n                    submission_df, \n                    pd.DataFrame([{\"Id\": معرف, \"Predicted\": \"1 100\"}])\n                ], ignore_index=True)\n        \n        # حفظ الملف\n        submission_df.to_csv(OUTPUT_CSV, index=False)\n        print(f\"\\n✅ تم حفظ ملف الإرسال: {OUTPUT_CSV}\")\n        \n    except Exception as e:\n        print(f\"❌ خطأ في حفظ الملف: {e}\")\n        return None\n    \n    # التحقق النهائي المكثف\n    if OUTPUT_CSV.exists():\n        try:\n            result_df = pd.read_csv(OUTPUT_CSV)\n            print(f\"\\n🎉 التحقق النهائي من الملف:\")\n            print(f\"   📊 عدد الصفوف: {len(result_df)}\")\n            print(f\"   📁 حجم الملف: {OUTPUT_CSV.stat().st_size} بايت\")\n            \n            if 'Predicted' in result_df.columns:\n                non_empty = result_df['Predicted'].str.len() > 0\n                print(f\"   🎯 العينات غير الفارغة: {non_empty.sum()}/{len(result_df)}\")\n                \n                if non_empty.sum() == 0:\n                    print(\"   ❌ تحذير: جميع العينات فارغة!\")\n                else:\n                    print(\"   ✅ تم إنشاء توقعات بنجاح!\")\n                    \n                # عرض عينة من التوقعات\n                print(f\"\\n   📋 عينة من التوقعات:\")\n                for i in range(min(3, len(result_df))):\n                    row = result_df.iloc[i]\n                    print(f\"      {row['Id']}: RLE طول {len(row['Predicted'])}\")\n            else:\n                print(\"   ❌ خطأ: عمود 'Predicted' غير موجود!\")\n                \n        except Exception as e:\n            print(f\"❌ خطأ في قراءة الملف الناتج: {e}\")\n    else:\n        print(\"❌ فشل إنشاء الملف!\")\n        return None\n    \n    return OUTPUT_CSV\n\n# التشغيل الرئيسي مع معالجة الأخطاء الشاملة\nif __name__ == \"__main__\":\n    print(\"=\" * 60)\n    print(\"🚀 الإصدار النهائي المضمون - تحدي فيزوف\")\n    print(\"=\" * 60)\n    \n    try:\n        ملف_الإرسال = إنشاء_ملف_إرسال_مضمون_نهائي()\n        \n        if ملف_الإرسال and ملف_الإرسال.exists():\n            print(f\"\\n🎉🎉🎉 تم الإنشاء بنجاح! 🎉🎉🎉\")\n            print(f\"📍 قدم هذا الملف: {ملف_الإرسال}\")\n            print(f\"📁 تأكد من وجوده في: /kaggle/working/submission.csv\")\n            \n            # تحقق إضافي\n            import subprocess\n            result = subprocess.run(['ls', '-la', '/kaggle/working/submission.csv'], \n                                  capture_output=True, text=True)\n            if result.returncode == 0:\n                print(f\"🔍 تأكيد النظام: {result.stdout.strip()}\")\n            else:\n                print(\"⚠ تعذر التحقق من الملف عبر النظام\")\n                \n        else:\n            print(\"\\n❌ فشل إنشاء ملف الإرسال\")\n            print(\"🔧 جرب الخطوات التالية:\")\n            print(\"   1. تحقق من أن البيانات محملة بشكل صحيح\")\n            print(\"   2. تأكد من أن المسابقة لا تزال نشطة\")\n            print(\"   3. جرب تشغيل الكود في بيئة Kaggle مباشرة\")\n            \n    except Exception as e:\n        print(f\"❌ خطأ غير متوقع في التشغيل الرئيسي: {e}\")\n        print(\"🆘 استخدم الإصدار الأساسي أو راجع بيانات الإدخال\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-25T20:38:56.084544Z","iopub.execute_input":"2025-11-25T20:38:56.084862Z","iopub.status.idle":"2025-11-25T20:38:58.120015Z","shell.execute_reply.started":"2025-11-25T20:38:56.084838Z","shell.execute_reply":"2025-11-25T20:38:58.118917Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom pathlib import Path\n\ndef تحليل_مفصل_للنتائج():\n    \"\"\"تحليل مفصل لملف الإرسال والنتائج\"\"\"\n    \n    ملف_الإرسال = Path(\"/kaggle/working/submission.csv\")\n    \n    if not ملف_الإرسال.exists():\n        print(\"❌ ملف الإرسال غير موجود\")\n        return\n    \n    # قراءة الملف\n    df = pd.read_csv(ملف_الإرسال)\n    \n    print(\"=\" * 70)\n    print(\"📊 التحليل المفصل لملف الإرسال والنتائج\")\n    print(\"=\" * 70)\n    \n    # المعلومات الأساسية\n    print(f\"📁 الملف: {ملف_الإرسال}\")\n    print(f\"📊 عدد العينات: {len(df)}\")\n    print(f\"📋 الأعمدة: {df.columns.tolist()}\")\n    \n    # تحليل عمود التوقعات\n    if 'Predicted' in df.columns:\n        # حساب الإحصائيات\n        توقعات_فارغة = df['Predicted'].isna().sum()\n        توقعات_سلسلة_فارغة = (df['Predicted'] == '').sum()\n        توقعات_غير_فارغة = len(df) - توقعات_فارغة - توقعات_سلسلة_فارغة\n        \n        print(f\"\\n🎯 تحليل التوقعات:\")\n        print(f\"   ✅ توقعات غير فارغة: {توقعات_غير_فارغة} عينة\")\n        print(f\"   ⚠ توقعات سلسلة فارغة: {توقعات_سلسلة_فارغة} عينة\")\n        print(f\"   ❌ توقعات NaN: {توقعات_فارغة} عينة\")\n        \n        # تحليل أطوال التوقعات\n        if توقعات_غير_فارغة > 0:\n            أطوال = df['Predicted'].str.len()\n            print(f\"\\n📏 إحصائيات أطوال التوقعات:\")\n            print(f\"   📐 متوسط الطول: {أطوال.mean():.0f} حرف\")\n            print(f\"   📏 أقصى طول: {أطوال.max()} حرف\")\n            print(f\"   📏 أقل طول: {أطوال.min()} حرف\")\n            print(f\"   📊 الطول الإجمالي: {أطوال.sum()} حرف\")\n            \n            # تحليل التوزيع\n            print(f\"\\n📈 توزيع أطوال التوقعات:\")\n            for حد in [100, 500, 1000, 5000, 10000]:\n                عدد = (أطوال <= حد).sum()\n                print(f\"   • أقل من {حد} حرف: {عدد} عينة\")\n        \n        # عرض عينات من التوقعات\n        print(f\"\\n🔍 عينات من التوقعات:\")\n        for i in range(min(3, len(df))):\n            عينة = df.iloc[i]\n            توقع = عينة['Predicted']\n            if pd.isna(توقع) or توقع == '':\n                حالة = \"فارغ\"\n            else:\n                حالة = f\"طول {len(توقع)} حرف\"\n            \n            print(f\"   {i+1}. {عينة['Id']}: {حالة}\")\n            \n            # عرض جزء من التوقع إذا كان طويلاً\n            if isinstance(توقع, str) and len(توقع) > 0:\n                عرض = توقع[:100] + \"...\" if len(توقع) > 100 else توقع\n                print(f\"      '{عرض}'\")\n    \n    # التحقق من صحة تنسيق RLE\n    if 'Predicted' in df.columns and توقعات_غير_فارغة > 0:\n        print(f\"\\n🔎 التحقق من صحة تنسيق RLE:\")\n        \n        for i in range(min(2, len(df))):\n            توقع = df.iloc[i]['Predicted']\n            if pd.notna(توقع) and توقع != '':\n                try:\n                    # محاولة تحليل RLE\n                    أجزاء = توقع.split()\n                    if len(أجزاء) % 2 == 0:\n                        print(f\"   ✅ {df.iloc[i]['Id']}: تنسيق RLE صحيح ({len(أجزاء)//2} زوج)\")\n                    else:\n                        print(f\"   ⚠ {df.iloc[i]['Id']}: تنسيق RLE غير صحيح (عدد فردي من الأجزاء)\")\n                except:\n                    print(f\"   ❌ {df.iloc[i]['Id']}: خطأ في تحليل RLE\")\n    \n    # توصيات\n    print(f\"\\n💡 التوصيات:\")\n    if توقعات_غير_فارغة == len(df):\n        print(\"   🎉 ممتاز! جميع العينات تحتوي على توقعات\")\n        print(\"   ✅ يمكنك تقديم الملف للمسابقة\")\n    elif توقعات_غير_فارغة > 0:\n        print(f\"   ⚠ جيد ولكن {len(df) - توقعات_غير_فارغة} عينة فارغة\")\n        print(\"   🔧 قد تحتاج لتحسين الإستراتيجية للعينات الفارغة\")\n    else:\n        print(\"   ❌ خطأ: جميع العينات فارغة\")\n        print(\"   🛑 تحتاج لمراجعة نموذج المعالجة\")\n    \n    return df\n\ndef تحليل_محتوى_RLE():\n    \"\"\"تحليل مفصل لمحتوى ترميزات RLE\"\"\"\n    \n    ملف_الإرسال = Path(\"/kaggle/working/submission.csv\")\n    \n    if not ملف_الإرسال.exists():\n        print(\"❌ ملف الإرسال غير موجود\")\n        return\n    \n    df = pd.read_csv(ملف_الإرسال)\n    \n    if 'Predicted' not in df.columns:\n        print(\"❌ عمود Predicted غير موجود\")\n        return\n    \n    print(\"\\n\" + \"=\" * 70)\n    print(\"🔬 تحليل مفصل لمحتوى ترميزات RLE\")\n    print(\"=\" * 70)\n    \n    for i in range(min(5, len(df))):\n        صف = df.iloc[i]\n        توقع = صف['Predicted']\n        \n        print(f\"\\n📝 العينة {i+1}: {صف['Id']}\")\n        \n        if pd.isna(توقع) or توقع == '':\n            print(\"   ❌ توقع فارغ\")\n            continue\n        \n        # تحليل RLE\n        try:\n            أجزاء = توقع.split()\n            if len(أجزاء) % 2 != 0:\n                print(f\"   ⚠ تنسيق RLE غير صحيح: عدد فردي من الأجزاء ({len(أجزاء)})\")\n                continue\n            \n            أزواج = [(int(أجزاء[j]), int(أجزاء[j+1])) for j in range(0, len(أجزاء), 2)]\n            \n            print(f\"   ✅ عدد أزواج البكسل: {len(أزواج)}\")\n            \n            # إحصائيات عن الأطوال\n            أطوال = [طول for _, طول in أزواج]\n            if أطوال:\n                print(f\"   📊 إحصائيات أطوال البكسل:\")\n                print(f\"      • المتوسط: {np.mean(أطوال):.1f}\")\n                print(f\"      • الأقصى: {max(أطوال)}\")\n                print(f\"      • الأدنى: {min(أطوال)}\")\n                print(f\"      • المجموع: {sum(أطوال)} بيكسل\")\n            \n            # أول 3 أزواج كمثال\n            if len(أزواج) > 0:\n                print(f\"   🔍 أول 3 أزواج (بداية, طول):\")\n                for k in range(min(3, len(أزواج))):\n                    print(f\"      {أزواج[k][0]}, {أزواج[k][1]}\")\n                    \n        except Exception as e:\n            print(f\"   ❌ خطأ في تحليل RLE: {e}\")\n\ndef إنشاء_تقرير_نهائي():\n    \"\"\"إنشاء تقرير نهائي شامل\"\"\"\n    \n    print(\"🚀 بدء التحليل الشامل...\")\n    \n    # التحليل الأساسي\n    df = تحليل_مفصل_للنتائج()\n    \n    if df is not None and len(df) > 0:\n        # تحليل RLE المتقدم\n        تحليل_محتوى_RLE()\n        \n        # معلومات إضافية\n        print(\"\\n\" + \"=\" * 70)\n        print(\"📋 معلومات التقديم للمسابقة\")\n        print(\"=\" * 70)\n        \n        ملف_الإرسال = Path(\"/kaggle/working/submission.csv\")\n        حجم_الملف = ملف_الإرسال.stat().st_size if ملف_الإرسال.exists() else 0\n        \n        print(f\"📁 حجم ملف الإرسال: {حجم_الملف / 1024:.2f} KB\")\n        print(f\"📊 عدد العينات: {len(df)}\")\n        \n        if 'Predicted' in df.columns:\n            غير_فارغ = df['Predicted'].notna() & (df['Predicted'] != '')\n            print(f\"🎯 نسبة العينات غير الفارغة: {غير_فارغ.mean() * 100:.1f}%\")\n            \n            if غير_فارغ.any():\n                print(\"✅ الملف جاهز للتقديم للمسابقة!\")\n            else:\n                print(\"❌ تحذير: لا توجد توقعات في الملف!\")\n        \n        print(f\"\\n📍 مسار الملف: {ملف_الإرسال}\")\n\n# تشغيل التحليل\nif __name__ == \"__main__\":\n    إنشاء_تقرير_نهائي()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-25T21:19:06.829075Z","iopub.execute_input":"2025-11-25T21:19:06.829419Z","iopub.status.idle":"2025-11-25T21:19:06.930665Z","shell.execute_reply.started":"2025-11-25T21:19:06.829393Z","shell.execute_reply":"2025-11-25T21:19:06.929536Z"},"jupyter":{"outputs_hidden":true},"collapsed":true},"outputs":[],"execution_count":null}]}