{"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":97984,"databundleVersionId":14096757,"sourceType":"competition"}],"dockerImageVersionId":31153,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"![img](https://i.pinimg.com/736x/37/99/b6/3799b6806aefb5dacb90bc3484d0b6e8.jpg)","metadata":{}},{"cell_type":"code","source":"\"\"\"\nGoal: Understand the problem we solve in this competition.\n\nAuthor: Rudra Prasad Bhuyan\nV1: 25-10-2025 00:15 IST\n\"\"\"\nprint(\"\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.853840Z","iopub.execute_input":"2025-10-25T18:43:51.854582Z","iopub.status.idle":"2025-10-25T18:43:51.859548Z","shell.execute_reply.started":"2025-10-25T18:43:51.854550Z","shell.execute_reply":"2025-10-25T18:43:51.858422Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">About Data</span></h1>\n\n> - **Competition**: https://www.kaggle.com/competitions/physionet-ecg-image-digitization\n> - **Metrics**:\n     - https://en.wikipedia.org/wiki/Signal-to-noise_ratio\n     - https://www.kaggle.com/code/metric/physionet-ecg-signal-extraction-metric/\n> - **Data**: https://www.kaggle.com/competitions/physionet-ecg-image-digitization/data\n> - **My Notebook in same Series**: https://www.kaggle.com/rudraprasadbhuyan/code?query=ecg-","metadata":{}},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">1. Notebook Setup</span></h1>\n","metadata":{}},{"cell_type":"code","source":"# Basic imports\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os\nfrom PIL import Image  \nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.873031Z","iopub.execute_input":"2025-10-25T18:43:51.873366Z","iopub.status.idle":"2025-10-25T18:43:51.878513Z","shell.execute_reply.started":"2025-10-25T18:43:51.873342Z","shell.execute_reply":"2025-10-25T18:43:51.877622Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Paths\ntrain_csv_path = '/kaggle/input/physionet-ecg-image-digitization/train.csv'\ntest_csv_path = '/kaggle/input/physionet-ecg-image-digitization/test.csv'\nsample_submission_path = '/kaggle/input/physionet-ecg-image-digitization/sample_submission.parquet'\n\ntrain_folder = '/kaggle/input/physionet-ecg-image-digitization/train'\ntest_folder = '/kaggle/input/physionet-ecg-image-digitization/test'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.882675Z","iopub.execute_input":"2025-10-25T18:43:51.883312Z","iopub.status.idle":"2025-10-25T18:43:51.887535Z","shell.execute_reply.started":"2025-10-25T18:43:51.883288Z","shell.execute_reply":"2025-10-25T18:43:51.886543Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">2. inspect Metadata</span></h1>\n","metadata":{}},{"cell_type":"code","source":"# Load train and test metadata\ntrain_meta = pd.read_csv(train_csv_path)\ntest_meta = pd.read_csv(test_csv_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.888979Z","iopub.execute_input":"2025-10-25T18:43:51.889305Z","iopub.status.idle":"2025-10-25T18:43:51.905848Z","shell.execute_reply.started":"2025-10-25T18:43:51.889277Z","shell.execute_reply":"2025-10-25T18:43:51.905073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train Meta Data ....\")\ndisplay(train_meta)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.917856Z","iopub.execute_input":"2025-10-25T18:43:51.918130Z","iopub.status.idle":"2025-10-25T18:43:51.929772Z","shell.execute_reply.started":"2025-10-25T18:43:51.918111Z","shell.execute_reply":"2025-10-25T18:43:51.928927Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"| Column    | Meaning                                                                                                        |\n| --------- | -------------------------------------------------------------------------------------------------------------- |\n| `id`      | Unique identifier for each ECG recording / patient sample. Think of it as the **folder name** in `train/[id]`. |\n| `fs`      | Sampling frequency of the ECG signal (in Hz). How many data points are recorded per second.                    |\n| `sig_len` | Total number of points in the ECG signal (length of the time series).                                          |","metadata":{}},{"cell_type":"markdown","source":"\n**Interpretation:**\n\n- ECG sample 7663343 was recorded at 500 Hz, meaning 500 points per second.\n\n- Total signal length = 5000 points → signal duration = 5000 / 500 = 10 seconds. \n\n- So sig_len = fs × duration, usually 10 seconds for most leads (except short ones).","metadata":{}},{"cell_type":"code","source":"print(\"\\nTest Meta Data ....\")\ndisplay(test_meta)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.937785Z","iopub.execute_input":"2025-10-25T18:43:51.938553Z","iopub.status.idle":"2025-10-25T18:43:51.948614Z","shell.execute_reply.started":"2025-10-25T18:43:51.938529Z","shell.execute_reply":"2025-10-25T18:43:51.947822Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"| Column           | Meaning                                                                     |\n| ---------------- | --------------------------------------------------------------------------- |\n| `id`             | Unique ECG recording ID (same as train, but in test).                       |\n| `lead`           | Which of the 12 standard ECG leads (I, II, III, aVR, … V6) this row is for. |\n| `fs`             | Sampling frequency of the signal (points per second).                       |\n| `number_of_rows` | How many data points you are expected to predict for this lead. Usually:    |\n\nFor \n- Lead II → 10 seconds → fs × 10 points\n\n- All other leads → 2.5 seconds → fs × 2.5 points |","metadata":{}},{"cell_type":"markdown","source":"**Interpretation:**\n\n- This is Lead II for sample 1053922973\n\n- Sampling rate = 1000 Hz → 1000 points per second\n\n- Number of points to predict = 10000 → matches 10 seconds × 1000 Hz\n\n- For other leads (like I, III, V1…V6), number_of_rows = fs × 2.5 seconds = 2500 points in this case.","metadata":{}},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">3. Look Sample Images</span></h1>\n","metadata":{}},{"cell_type":"code","source":"train_meta['id']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.957579Z","iopub.execute_input":"2025-10-25T18:43:51.958306Z","iopub.status.idle":"2025-10-25T18:43:51.965343Z","shell.execute_reply.started":"2025-10-25T18:43:51.958283Z","shell.execute_reply":"2025-10-25T18:43:51.964567Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Pick one id\nsample_id = train_meta['id'].iloc[0]\n\n# List all PNGs for that sample\nsample_images = os.listdir(os.path.join(train_folder, str(sample_id)))\nprint(\"Images for sample:\", sample_images)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:51.977842Z","iopub.execute_input":"2025-10-25T18:43:51.978105Z","iopub.status.idle":"2025-10-25T18:43:51.983668Z","shell.execute_reply.started":"2025-10-25T18:43:51.978085Z","shell.execute_reply":"2025-10-25T18:43:51.982742Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Open a few images\nfor img_name in sample_images[:7]:  \n    img_path = os.path.join(train_folder, str(sample_id), img_name)\n    img = Image.open(img_path)\n    plt.figure(figsize=(8,4))\n    plt.imshow(img)\n    plt.title(img_name)\n    plt.axis('off')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:43:52.003094Z","iopub.execute_input":"2025-10-25T18:43:52.003652Z","iopub.status.idle":"2025-10-25T18:44:01.424931Z","shell.execute_reply.started":"2025-10-25T18:43:52.003628Z","shell.execute_reply":"2025-10-25T18:44:01.423926Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">4. Look Sample Data</span></h1>\n","metadata":{}},{"cell_type":"code","source":"# Read a sample CSV for first id\nsample_csv_path = os.path.join(train_folder, str(sample_id), f\"{sample_id}.csv\")\nsample_data = pd.read_csv(sample_csv_path)\ndisplay(sample_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:44:01.426534Z","iopub.execute_input":"2025-10-25T18:44:01.427024Z","iopub.status.idle":"2025-10-25T18:44:01.451301Z","shell.execute_reply.started":"2025-10-25T18:44:01.426991Z","shell.execute_reply":"2025-10-25T18:44:01.450379Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"| Column                           | Meaning                                                                                                                    |\n| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| I, II, III, aVR, aVL, aVF, V1–V6 | The **12 standard ECG leads**. Each column contains the **voltage measurements (in mV)** for that lead at each time point. |\n","metadata":{}},{"cell_type":"code","source":"lead_list = test_meta['lead'].to_list()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:44:01.452299Z","iopub.execute_input":"2025-10-25T18:44:01.452579Z","iopub.status.idle":"2025-10-25T18:44:01.456575Z","shell.execute_reply.started":"2025-10-25T18:44:01.452559Z","shell.execute_reply":"2025-10-25T18:44:01.455884Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lead_list = test_meta['lead'].to_list()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:44:01.458216Z","iopub.execute_input":"2025-10-25T18:44:01.458648Z","iopub.status.idle":"2025-10-25T18:44:01.462506Z","shell.execute_reply.started":"2025-10-25T18:44:01.458627Z","shell.execute_reply":"2025-10-25T18:44:01.461648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i in lead_list:\n    plt.figure(figsize=(18,7))\n    plt.plot(sample_data['I'])\n    plt.title(f\"ECG Lead {i} for sample {sample_id}\")\n    plt.xlabel(\"Time (sample points)\")\n    plt.ylabel(\"Voltage (mV)\")\n    plt.show()\n    print(\"\\n\\n\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:44:01.463310Z","iopub.execute_input":"2025-10-25T18:44:01.463521Z","iopub.status.idle":"2025-10-25T18:44:07.102730Z","shell.execute_reply.started":"2025-10-25T18:44:01.463503Z","shell.execute_reply":"2025-10-25T18:44:07.101566Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">5. Inspect the sample Submission</span></h1>\n","metadata":{}},{"cell_type":"code","source":"# Load sample submission\nsample_submission = pd.read_parquet(sample_submission_path)\ndisplay(sample_submission.sample(5))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:44:07.103765Z","iopub.execute_input":"2025-10-25T18:44:07.104003Z","iopub.status.idle":"2025-10-25T18:44:07.168878Z","shell.execute_reply.started":"2025-10-25T18:44:07.103984Z","shell.execute_reply":"2025-10-25T18:44:07.167937Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Why 0s?**\n\n- All 0s = just a template, not real values.\n\n- You must predict ECG voltage values (mV) for each row.\n\n- Each row = one point in time for one lead for one test image.\n\n- Your model’s job = convert ECG image → numerical signal (time series).\n\n- You’ll replace the zeros with your predicted signal.","metadata":{}},{"cell_type":"code","source":"sample_submission[\"value\"].unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-25T18:44:07.169918Z","iopub.execute_input":"2025-10-25T18:44:07.170241Z","iopub.status.idle":"2025-10-25T18:44:07.176586Z","shell.execute_reply.started":"2025-10-25T18:44:07.170211Z","shell.execute_reply":"2025-10-25T18:44:07.175589Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">6. Understanding Evaluation Metric</span></h1>\n","metadata":{}},{"cell_type":"markdown","source":"- Metric: modified signal-to-noise ratio (SNR)\n\n- It compares your predicted ECG time series with the ground truth.\n\n- High SNR → prediction is very close to true signal.\n\n- For now, just know: we’ll need a 1D time series per lead for each test sample.","metadata":{}},{"cell_type":"markdown","source":"# <h1><span style=\"color:#5e17eb; font-weight:bold;\">Resources</span></h1>\n\n- My notesbooks: https://www.kaggle.com/rudraprasadbhuyan/code?query=ecg-\n- Kernels issues: https://www.kaggle.com/code/dansbecker/finding-your-files-in-kaggle-kernels","metadata":{}}]}