{"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":[{"sourceType":"competition","sourceId":97984,"databundleVersionId":14096757}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"📜 Description\n\nThis notebook provides a simple 6‑cell starter baseline for the PhysioNet ECG Image Digitization Competition. It demonstrates how to load metadata, preprocess ECG images, build a CNN backbone, run inference, and generate outputs in the required submission format. Designed for educational purposes — not guaranteed to reach finalist level. Participants are encouraged to extend the model architecture, adjust hyperparameters, and refine signal reconstruction methods to improve performance.","metadata":{}},{"cell_type":"code","source":"# =========================\n# Cell 1 — Imports & Config\n# =========================\nimport os, gc, random\nimport numpy as np\nimport pandas as pd\nimport torch\nimport timm\nimport cv2\nfrom torch.utils.data import Dataset, DataLoader\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nSEED = 42\nrandom.seed(SEED)\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)\n\nDATA_DIR = \"/kaggle/input/physionet-ecg-image-digitization\"\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nCONFIG = {\n    \"img_size\": 512,\n    \"batch_size\": 16,\n    \"model_name\": \"resnet18\",\n    \"device\": DEVICE\n}\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Cell 2 — Load Metadata\n# =========================\ntrain_meta = pd.read_csv(os.path.join(DATA_DIR, \"train.csv\"))\ntest_meta  = pd.read_csv(os.path.join(DATA_DIR, \"test.csv\"))\n\nprint(\"Train meta shape:\", train_meta.shape)\nprint(\"Test meta shape:\", test_meta.shape)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Cell 3 — Dataset & Preprocessing\n# =========================\nclass ECGDataset(Dataset):\n    def __init__(self, df, img_dir, transforms=None):\n        self.df = df\n        self.img_dir = img_dir\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        img_path = os.path.join(self.img_dir, f\"{row['id']}.png\")\n        img = cv2.imread(img_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        if self.transforms:\n            img = self.transforms(image=img)['image']\n        return img, row.get('value', 0.0)\n\ntransforms = A.Compose([\n    A.Resize(CONFIG['img_size'], CONFIG['img_size']),\n    A.Normalize(),\n    ToTensorV2()\n])\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Cell 4 — Model Definition\n# =========================\nclass ECGModel(torch.nn.Module):\n    def __init__(self, model_name=\"resnet18\"):\n        super().__init__()\n        self.backbone = timm.create_model(model_name, pretrained=True, num_classes=1)\n        \n    def forward(self, x):\n        return self.backbone(x)\n\nmodel = ECGModel(CONFIG[\"model_name\"]).to(CONFIG[\"device\"])\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Cell 5 — Inference\n# =========================\ntest_ds = ECGDataset(test_meta, os.path.join(DATA_DIR, \"test\"), transforms=transforms)\ntest_loader = DataLoader(test_ds, batch_size=CONFIG[\"batch_size\"], shuffle=False)\n\nmodel.eval()\npreds = []\n\nwith torch.no_grad():\n    for imgs, _ in test_loader:\n        imgs = imgs.to(CONFIG[\"device\"])\n        out = model(imgs)\n        preds.append(out.cpu().numpy())\n\npreds = np.concatenate(preds)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Cell 6 — Submission\n# =========================\nsubmission = pd.DataFrame({\n    \"id\": test_meta[\"id\"],\n    \"value\": preds.flatten()\n})\n\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv saved\")\nsubmission.head()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}