Files
remote-sensing/01.train_ODC_local_with_Mic_supplyer.ipynb
T

2096 lines
160 KiB
Plaintext
Raw Normal View History

2025-12-21 14:34:18 +07:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 6,
"id": "912ed572-1658-406b-976c-cd6de2d4e89e",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" XGBoost version: 3.1.2\n",
"✅ All modules loaded successfully\n",
"CPU times: user 975 μs, sys: 0 ns, total: 975 μs\n",
"Wall time: 948 μs\n"
]
}
],
"source": [
"%%time\n",
"%matplotlib inline\n",
"\n",
"# Import Microsoft Planetary Computer libraries\n",
"import planetary_computer\n",
"from pystac_client import Client\n",
"from odc.stac import load as stac_load\n",
"\n",
"# Standard imports\n",
"import xarray as xr\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay\n",
"import geopandas as gpd\n",
"\n",
"# XGBoost for GPU training\n",
"import xgboost as xgb\n",
"\n",
"from xgboost import XGBClassifier\n",
"\n",
"print(f\" XGBoost version: {xgb.__version__}\")\n",
"\n",
"print(\"✅ All modules loaded successfully\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "d824dc4f-994b-4d1c-8d24-ce6674da141c",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"✅ Connected to Microsoft Planetary Computer\n",
"\n",
"======================================================================\n",
"CPU times: user 40.4 ms, sys: 4.03 ms, total: 44.5 ms\n",
"Wall time: 776 ms\n"
]
}
],
"source": [
"%%time\n",
"# Kết nối tới Microsoft Planetary Computer STAC\n",
"from pystac_client import Client\n",
"\n",
"# KHÔNG dùng modifier ở catalog level để tránh items bị convert thành dict\n",
"catalog = Client.open(\n",
" \"https://planetarycomputer.microsoft.com/api/stac/v1\"\n",
")\n",
"print(\"✅ Connected to Microsoft Planetary Computer\")\n",
"\n",
"print(\"\\n\" + \"=\"*70)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "1e113730",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"CONFIGURATION\n",
"======================================================================\n",
"\n",
"📍 Area of Interest:\n",
" Longitude: 105.6 to 106.2\n",
" Latitude: 9.3 to 9.8\n",
"\n",
"📅 Time Range: 2023-03-01/2023-05-31\n",
" ⚠️ Optimized for personal computer (3 months, reduced area)\n",
"\n",
"🗺️ CRS: EPSG:32648\n",
" Resolution: 20m (reduced from 10m for smaller data size)\n",
"======================================================================\n",
"CPU times: user 258 μs, sys: 0 ns, total: 258 μs\n",
"Wall time: 246 μs\n"
]
}
],
"source": [
"%%time\n",
"# 🌍 Định nghĩa khu vực và thời gian\n",
"print(\"=\"*70)\n",
"print(\"CONFIGURATION\")\n",
"print(\"=\"*70)\n",
"\n",
"# Khu vực quan tâm (Vietnam - Mekong Delta) - GIẢM DIỆN TÍCH ~40%\n",
"bbox = [105.6, 9.3, 106.2, 9.8] # [min_lon, min_lat, max_lon, max_lat]\n",
"\n",
"# GIẢM THỜI GIAN xuống 3 tháng để giảm kích thước dữ liệu cho PC\n",
"time_range = \"2023-03-01/2023-05-31\" # 3 tháng (mùa khô)\n",
"\n",
"print(f\"\\n📍 Area of Interest:\")\n",
"print(f\" Longitude: {bbox[0]} to {bbox[2]}\")\n",
"print(f\" Latitude: {bbox[1]} to {bbox[3]}\")\n",
"print(f\"\\n📅 Time Range: {time_range}\")\n",
"print(f\" ⚠️ Optimized for personal computer (3 months, reduced area)\")\n",
"print(f\"\\n🗺️ CRS: EPSG:32648\")\n",
"print(f\" Resolution: 20m (reduced from 10m for smaller data size)\")\n",
"\n",
"print(\"=\"*70)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "3cd69645",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"LOADING SENTINEL-2 L2A\n",
"======================================================================\n",
"\n",
"🔍 Searching for Sentinel-2 scenes...\n",
"✅ Found 22 Sentinel-2 scenes\n",
"⚠️ Limiting to 12 scenes for personal computer\n",
" Selected 12 scenes evenly distributed\n",
"\n",
"📋 Sample scenes:\n",
" [1] 2023-05-17 - Cloud: 27.73279%\n",
" [2] 2023-05-15 - Cloud: 21.273129%\n",
" [3] 2023-05-02 - Cloud: 20.527479%\n",
" [4] 2023-05-02 - Cloud: 20.524253%\n",
" [5] 2023-04-15 - Cloud: 29.471546%\n",
"\n",
"🔑 Signing STAC items...\n",
"\n",
"⏳ Loading Sentinel-2 data...\n",
"\n",
"✅ Sentinel-2 loaded!\n",
" Shape: {'y': 2774, 'x': 3301, 'time': 7}\n",
" Variables: ['red', 'nir', 'scl']\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"<timed exec>:54: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.\n"
]
},
{
"data": {
"text/html": [
"<div><svg style=\"position: absolute; width: 0; height: 0; overflow: hidden\">\n",
"<defs>\n",
"<symbol id=\"icon-database\" viewBox=\"0 0 32 32\">\n",
"<path d=\"M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z\"></path>\n",
"<path d=\"M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n",
"<path d=\"M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n",
"</symbol>\n",
"<symbol id=\"icon-file-text2\" viewBox=\"0 0 32 32\">\n",
"<path d=\"M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z\"></path>\n",
"<path d=\"M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"<path d=\"M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"<path d=\"M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"</symbol>\n",
"</defs>\n",
"</svg>\n",
"<style>/* CSS stylesheet for displaying xarray objects in jupyterlab.\n",
" *\n",
" */\n",
"\n",
":root {\n",
" --xr-font-color0: var(\n",
" --jp-content-font-color0,\n",
" var(--pst-color-text-base rgba(0, 0, 0, 1))\n",
" );\n",
" --xr-font-color2: var(\n",
" --jp-content-font-color2,\n",
" var(--pst-color-text-base, rgba(0, 0, 0, 0.54))\n",
" );\n",
" --xr-font-color3: var(\n",
" --jp-content-font-color3,\n",
" var(--pst-color-text-base, rgba(0, 0, 0, 0.38))\n",
" );\n",
" --xr-border-color: var(\n",
" --jp-border-color2,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 10))\n",
" );\n",
" --xr-disabled-color: var(\n",
" --jp-layout-color3,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 40))\n",
" );\n",
" --xr-background-color: var(\n",
" --jp-layout-color0,\n",
" var(--pst-color-on-background, white)\n",
" );\n",
" --xr-background-color-row-even: var(\n",
" --jp-layout-color1,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 5))\n",
" );\n",
" --xr-background-color-row-odd: var(\n",
" --jp-layout-color2,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 15))\n",
" );\n",
"}\n",
"\n",
"html[theme=\"dark\"],\n",
"html[data-theme=\"dark\"],\n",
"body[data-theme=\"dark\"],\n",
"body.vscode-dark {\n",
" --xr-font-color0: var(\n",
" --jp-content-font-color0,\n",
" var(--pst-color-text-base, rgba(255, 255, 255, 1))\n",
" );\n",
" --xr-font-color2: var(\n",
" --jp-content-font-color2,\n",
" var(--pst-color-text-base, rgba(255, 255, 255, 0.54))\n",
" );\n",
" --xr-font-color3: var(\n",
" --jp-content-font-color3,\n",
" var(--pst-color-text-base, rgba(255, 255, 255, 0.38))\n",
" );\n",
" --xr-border-color: var(\n",
" --jp-border-color2,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 10))\n",
" );\n",
" --xr-disabled-color: var(\n",
" --jp-layout-color3,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 40))\n",
" );\n",
" --xr-background-color: var(\n",
" --jp-layout-color0,\n",
" var(--pst-color-on-background, #111111)\n",
" );\n",
" --xr-background-color-row-even: var(\n",
" --jp-layout-color1,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 5))\n",
" );\n",
" --xr-background-color-row-odd: var(\n",
" --jp-layout-color2,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 15))\n",
" );\n",
"}\n",
"\n",
".xr-wrap {\n",
" display: block !important;\n",
" min-width: 300px;\n",
" max-width: 700px;\n",
"}\n",
"\n",
".xr-text-repr-fallback {\n",
" /* fallback to plain text repr when CSS is not injected (untrusted notebook) */\n",
" display: none;\n",
"}\n",
"\n",
".xr-header {\n",
" padding-top: 6px;\n",
" padding-bottom: 6px;\n",
" margin-bottom: 4px;\n",
" border-bottom: solid 1px var(--xr-border-color);\n",
"}\n",
"\n",
".xr-header > div,\n",
".xr-header > ul {\n",
" display: inline;\n",
" margin-top: 0;\n",
" margin-bottom: 0;\n",
"}\n",
"\n",
".xr-obj-type,\n",
".xr-array-name {\n",
" margin-left: 2px;\n",
" margin-right: 10px;\n",
"}\n",
"\n",
".xr-obj-type {\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-sections {\n",
" padding-left: 0 !important;\n",
" display: grid;\n",
" grid-template-columns: 150px auto auto 1fr 0 20px 0 20px;\n",
"}\n",
"\n",
".xr-section-item {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-section-item input {\n",
" display: inline-block;\n",
" opacity: 0;\n",
" height: 0;\n",
"}\n",
"\n",
".xr-section-item input + label {\n",
" color: var(--xr-disabled-color);\n",
" border: 2px solid transparent !important;\n",
"}\n",
"\n",
".xr-section-item input:enabled + label {\n",
" cursor: pointer;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-section-item input:focus + label {\n",
" border: 2px solid var(--xr-font-color0) !important;\n",
"}\n",
"\n",
".xr-section-item input:enabled + label:hover {\n",
" color: var(--xr-font-color0);\n",
"}\n",
"\n",
".xr-section-summary {\n",
" grid-column: 1;\n",
" color: var(--xr-font-color2);\n",
" font-weight: 500;\n",
"}\n",
"\n",
".xr-section-summary > span {\n",
" display: inline-block;\n",
" padding-left: 0.5em;\n",
"}\n",
"\n",
".xr-section-summary-in:disabled + label {\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-section-summary-in + label:before {\n",
" display: inline-block;\n",
" content: \"►\";\n",
" font-size: 11px;\n",
" width: 15px;\n",
" text-align: center;\n",
"}\n",
"\n",
".xr-section-summary-in:disabled + label:before {\n",
" color: var(--xr-disabled-color);\n",
"}\n",
"\n",
".xr-section-summary-in:checked + label:before {\n",
" content: \"▼\";\n",
"}\n",
"\n",
".xr-section-summary-in:checked + label > span {\n",
" display: none;\n",
"}\n",
"\n",
".xr-section-summary,\n",
".xr-section-inline-details {\n",
" padding-top: 4px;\n",
" padding-bottom: 4px;\n",
"}\n",
"\n",
".xr-section-inline-details {\n",
" grid-column: 2 / -1;\n",
"}\n",
"\n",
".xr-section-details {\n",
" display: none;\n",
" grid-column: 1 / -1;\n",
" margin-bottom: 5px;\n",
"}\n",
"\n",
".xr-section-summary-in:checked ~ .xr-section-details {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-array-wrap {\n",
" grid-column: 1 / -1;\n",
" display: grid;\n",
" grid-template-columns: 20px auto;\n",
"}\n",
"\n",
".xr-array-wrap > label {\n",
" grid-column: 1;\n",
" vertical-align: top;\n",
"}\n",
"\n",
".xr-preview {\n",
" color: var(--xr-font-color3);\n",
"}\n",
"\n",
".xr-array-preview,\n",
".xr-array-data {\n",
" padding: 0 5px !important;\n",
" grid-column: 2;\n",
"}\n",
"\n",
".xr-array-data,\n",
".xr-array-in:checked ~ .xr-array-preview {\n",
" display: none;\n",
"}\n",
"\n",
".xr-array-in:checked ~ .xr-array-data,\n",
".xr-array-preview {\n",
" display: inline-block;\n",
"}\n",
"\n",
".xr-dim-list {\n",
" display: inline-block !important;\n",
" list-style: none;\n",
" padding: 0 !important;\n",
" margin: 0;\n",
"}\n",
"\n",
".xr-dim-list li {\n",
" display: inline-block;\n",
" padding: 0;\n",
" margin: 0;\n",
"}\n",
"\n",
".xr-dim-list:before {\n",
" content: \"(\";\n",
"}\n",
"\n",
".xr-dim-list:after {\n",
" content: \")\";\n",
"}\n",
"\n",
".xr-dim-list li:not(:last-child):after {\n",
" content: \",\";\n",
" padding-right: 5px;\n",
"}\n",
"\n",
".xr-has-index {\n",
" font-weight: bold;\n",
"}\n",
"\n",
".xr-var-list,\n",
".xr-var-item {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-var-item > div,\n",
".xr-var-item label,\n",
".xr-var-item > .xr-var-name span {\n",
" background-color: var(--xr-background-color-row-even);\n",
" border-color: var(--xr-background-color-row-odd);\n",
" margin-bottom: 0;\n",
" padding-top: 2px;\n",
"}\n",
"\n",
".xr-var-item > .xr-var-name:hover span {\n",
" padding-right: 5px;\n",
"}\n",
"\n",
".xr-var-list > li:nth-child(odd) > div,\n",
".xr-var-list > li:nth-child(odd) > label,\n",
".xr-var-list > li:nth-child(odd) > .xr-var-name span {\n",
" background-color: var(--xr-background-color-row-odd);\n",
" border-color: var(--xr-background-color-row-even);\n",
"}\n",
"\n",
".xr-var-name {\n",
" grid-column: 1;\n",
"}\n",
"\n",
".xr-var-dims {\n",
" grid-column: 2;\n",
"}\n",
"\n",
".xr-var-dtype {\n",
" grid-column: 3;\n",
" text-align: right;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-var-preview {\n",
" grid-column: 4;\n",
"}\n",
"\n",
".xr-index-preview {\n",
" grid-column: 2 / 5;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-var-name,\n",
".xr-var-dims,\n",
".xr-var-dtype,\n",
".xr-preview,\n",
".xr-attrs dt {\n",
" white-space: nowrap;\n",
" overflow: hidden;\n",
" text-overflow: ellipsis;\n",
" padding-right: 10px;\n",
"}\n",
"\n",
".xr-var-name:hover,\n",
".xr-var-dims:hover,\n",
".xr-var-dtype:hover,\n",
".xr-attrs dt:hover {\n",
" overflow: visible;\n",
" width: auto;\n",
" z-index: 1;\n",
"}\n",
"\n",
".xr-var-attrs,\n",
".xr-var-data,\n",
".xr-index-data {\n",
" display: none;\n",
" border-top: 2px dotted var(--xr-background-color);\n",
" padding-bottom: 20px !important;\n",
" padding-top: 10px !important;\n",
"}\n",
"\n",
".xr-var-attrs-in + label,\n",
".xr-var-data-in + label,\n",
".xr-index-data-in + label {\n",
" padding: 0 1px;\n",
"}\n",
"\n",
".xr-var-attrs-in:checked ~ .xr-var-attrs,\n",
".xr-var-data-in:checked ~ .xr-var-data,\n",
".xr-index-data-in:checked ~ .xr-index-data {\n",
" display: block;\n",
"}\n",
"\n",
".xr-var-data > table {\n",
" float: right;\n",
"}\n",
"\n",
".xr-var-data > pre,\n",
".xr-index-data > pre,\n",
".xr-var-data > table > tbody > tr {\n",
" background-color: transparent !important;\n",
"}\n",
"\n",
".xr-var-name span,\n",
".xr-var-data,\n",
".xr-index-name div,\n",
".xr-index-data,\n",
".xr-attrs {\n",
" padding-left: 25px !important;\n",
"}\n",
"\n",
".xr-attrs,\n",
".xr-var-attrs,\n",
".xr-var-data,\n",
".xr-index-data {\n",
" grid-column: 1 / -1;\n",
"}\n",
"\n",
"dl.xr-attrs {\n",
" padding: 0;\n",
" margin: 0;\n",
" display: grid;\n",
" grid-template-columns: 125px auto;\n",
"}\n",
"\n",
".xr-attrs dt,\n",
".xr-attrs dd {\n",
" padding: 0;\n",
" margin: 0;\n",
" float: left;\n",
" padding-right: 10px;\n",
" width: auto;\n",
"}\n",
"\n",
".xr-attrs dt {\n",
" font-weight: normal;\n",
" grid-column: 1;\n",
"}\n",
"\n",
".xr-attrs dt:hover span {\n",
" display: inline-block;\n",
" background: var(--xr-background-color);\n",
" padding-right: 10px;\n",
"}\n",
"\n",
".xr-attrs dd {\n",
" grid-column: 2;\n",
" white-space: pre-wrap;\n",
" word-break: break-all;\n",
"}\n",
"\n",
".xr-icon-database,\n",
".xr-icon-file-text2,\n",
".xr-no-icon {\n",
" display: inline-block;\n",
" vertical-align: middle;\n",
" width: 1em;\n",
" height: 1.5em !important;\n",
" stroke-width: 0;\n",
" stroke: currentColor;\n",
" fill: currentColor;\n",
"}\n",
"\n",
".xr-var-attrs-in:checked + label > .xr-icon-file-text2,\n",
".xr-var-data-in:checked + label > .xr-icon-database,\n",
".xr-index-data-in:checked + label > .xr-icon-database {\n",
" color: var(--xr-font-color0);\n",
" filter: drop-shadow(1px 1px 5px var(--xr-font-color2));\n",
" stroke-width: 0.8px;\n",
"}\n",
"</style><pre class='xr-text-repr-fallback'>&lt;xarray.Dataset&gt; Size: 769MB\n",
"Dimensions: (y: 2774, x: 3301, time: 7)\n",
"Coordinates:\n",
" * y (y) float64 22kB 1.084e+06 1.084e+06 ... 1.028e+06 1.028e+06\n",
" * x (x) float64 26kB 5.658e+05 5.658e+05 ... 6.318e+05 6.318e+05\n",
" spatial_ref int32 4B 32648\n",
" * time (time) datetime64[ns] 56B 2023-03-23T03:05:29.024000 ... 202...\n",
"Data variables:\n",
" red (time, y, x) float32 256MB nan nan nan ... 1.917e+03 1.926e+03\n",
" nir (time, y, x) float32 256MB nan nan nan ... 1.374e+03 1.386e+03\n",
" scl (time, y, x) float32 256MB nan nan nan nan ... 6.0 6.0 6.0 6.0</pre><div class='xr-wrap' style='display:none'><div class='xr-header'><div class='xr-obj-type'>xarray.Dataset</div></div><ul class='xr-sections'><li class='xr-section-item'><input id='section-4e563d85-d1e9-444d-ae77-6fca4c7b935a' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-4e563d85-d1e9-444d-ae77-6fca4c7b935a' class='xr-section-summary' title='Expand/collapse section'>Dimensions:</label><div class='xr-section-inline-details'><ul class='xr-dim-list'><li><span class='xr-has-index'>y</span>: 2774</li><li><span class='xr-has-index'>x</span>: 3301</li><li><span class='xr-has-index'>time</span>: 7</li></ul></div><div class='xr-section-details'></div></li><li class='xr-section-item'><input id='section-eded884c-cb8a-4e62-b7c0-489c02a7f71b' class='xr-section-summary-in' type='checkbox' checked><label for='section-eded884c-cb8a-4e62-b7c0-489c02a7f71b' class='xr-section-summary' >Coordinates: <span>(4)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>y</span></div><div class='xr-var-dims'>(y)</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>1.084e+06 1.084e+06 ... 1.028e+06</div><input id='attrs-8cdd6133-d876-4a93-8267-62a7379e46c5' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-8cdd6133-d876-4a93-8267-62a7379e46c5' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-e1fae210-0eba-4138-b371-d7edd3dbf633' class='xr-var-data-in' type='checkbox'><label for='data-e1fae210-0eba-4138-b371-d7edd3dbf633' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>metre</dd><dt><span>resolution :</span></dt><dd>-20.0</dd><dt><span>crs :</span></dt><dd>EPSG:32648</dd></dl></div><div class='xr-var-data'><pre>array([1083530., 1083510., 1083490., ..., 1028110., 1028090., 1028070.])</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>x</span></div><div class='xr-var-dims'>(x)</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>5.658e+05 5.658e+05 ... 6.318e+05</div><input id='attrs-16408b9e-edc7-484f-a689-8b6e164b0d01' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-16408b9e-edc7-484f-a689-8b6e164b0d01' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-846a003e-8e4d-48ca-9ffc-9da9372a93a2' class='xr-var-data-in' type='checkbox'><label for='data-846a003e-8e4d-48ca-9ffc-9da9372a93a2' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>metre</dd><dt><span>resolution :</span></dt><dd>20.0</dd><dt><span>crs :</span></dt><dd>EPSG:32648</dd></dl></div><div class='xr-var-data'><pre>array([565790., 565810., 565830., ..., 631750., 631770., 631790.])</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>spatial_ref</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>int32</div><div class='xr-var-preview xr-preview'>32648</div><input id='attrs-3a26691b-3982-4fe3-a7db-547c1dfe5ba7' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-3a26691b-3982-4fe3-a7db-547c1dfe5ba7' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-e6e71c5b-d3dc-41d8-9d86-62d80baa11c9' class='xr-var-data-in' type='checkbox'><label for='data-e6e71c5b-d3dc-41d8-9d86-62d80baa11c9' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-
" &#x27;2023-04-05T03:15:19.024000000&#x27;, &#x27;2023-04-15T03:15:19.024000000&#x27;,\n",
" &#x27;2023-05-02T03:05:29.024000000&#x27;, &#x27;2023-05-15T03:15:19.024000000&#x27;,\n",
" &#x27;2023-05-17T03:05:21.024000000&#x27;], dtype=&#x27;datetime64[ns]&#x27;)</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-3a1eb748-da5f-4a2b-b06f-2c89093444bd' class='xr-section-summary-in' type='checkbox' checked><label for='section-3a1eb748-da5f-4a2b-b06f-2c89093444bd' class='xr-section-summary' >Data variables: <span>(3)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>red</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>nan nan nan ... 1.917e+03 1.926e+03</div><input id='attrs-dcd3ed38-7792-4483-8805-96526b415ffb' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-dcd3ed38-7792-4483-8805-96526b415ffb' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-e66dac4d-c0f4-44bb-8796-1ed6000c9c1c' class='xr-var-data-in' type='checkbox'><label for='data-e66dac4d-c0f4-44bb-8796-1ed6000c9c1c' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([[[ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" ...,\n",
" [ nan, nan, nan, ..., 2071., 2056., 2052.],\n",
" [ nan, nan, nan, ..., 2048., 2066., 2044.],\n",
" [ nan, nan, nan, ..., 2052., 2037., 2029.]],\n",
"\n",
" [[ 2035., 2062., 2560., ..., nan, nan, nan],\n",
" [ 2144., 2087., 2428., ..., nan, nan, nan],\n",
" [ 2020., 2241., 2690., ..., nan, nan, nan],\n",
" ...,\n",
" [ 1282., 1294., 1286., ..., nan, nan, nan],\n",
" [ 1299., 1241., 1244., ..., nan, nan, nan],\n",
" [ 1294., 1272., 1243., ..., nan, nan, nan]],\n",
"\n",
" [[ 2191., 2198., 2004., ..., nan, nan, nan],\n",
" [ 2217., 2013., 1967., ..., nan, nan, nan],\n",
" [ 2095., 1871., 1903., ..., nan, nan, nan],\n",
" ...,\n",
"...\n",
" [ nan, nan, nan, ..., 3364., 2611., 2589.],\n",
" [ nan, nan, nan, ..., 3907., 3024., 2603.],\n",
" [ nan, nan, nan, ..., 3906., 3139., 2855.]],\n",
"\n",
" [[ 1240., 1241., 1275., ..., nan, nan, nan],\n",
" [ 1261., 1259., 1299., ..., nan, nan, nan],\n",
" [ 1272., 1271., 1330., ..., nan, nan, nan],\n",
" ...,\n",
" [ 7910., 8718., 10069., ..., nan, nan, nan],\n",
" [ 8295., 9471., 10406., ..., nan, nan, nan],\n",
" [ 9175., 9526., 9140., ..., nan, nan, nan]],\n",
"\n",
" [[ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" ...,\n",
" [ nan, nan, nan, ..., 1926., 1954., 1923.],\n",
" [ nan, nan, nan, ..., 1917., 1919., 1920.],\n",
" [ nan, nan, nan, ..., 1891., 1917., 1926.]]],\n",
" dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>nir</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>nan nan nan ... 1.374e+03 1.386e+03</div><input id='attrs-165c0049-0b0c-4d49-87a0-3ecebeb5956b' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-165c0049-0b0c-4d49-87a0-3ecebeb5956b' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-134de6d1-9579-4355-a320-26326f0c8405' class='xr-var-data-in' type='checkbox'><label for='data-134de6d1-9579-4355-a320-26326f0c8405' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([[[ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" ...,\n",
" [ nan, nan, nan, ..., 1402., 1403., 1403.],\n",
" [ nan, nan, nan, ..., 1388., 1408., 1388.],\n",
" [ nan, nan, nan, ..., 1410., 1380., 1389.]],\n",
"\n",
" [[ 2724., 2790., 3475., ..., nan, nan, nan],\n",
" [ 2878., 2817., 3199., ..., nan, nan, nan],\n",
" [ 2672., 2906., 3600., ..., nan, nan, nan],\n",
" ...,\n",
" [ 4441., 4641., 4398., ..., nan, nan, nan],\n",
" [ 4029., 4162., 4204., ..., nan, nan, nan],\n",
" [ 4103., 3978., 4071., ..., nan, nan, nan]],\n",
"\n",
" [[ 2396., 2373., 2166., ..., nan, nan, nan],\n",
" [ 2345., 2202., 2126., ..., nan, nan, nan],\n",
" [ 2258., 2079., 2126., ..., nan, nan, nan],\n",
" ...,\n",
"...\n",
" [ nan, nan, nan, ..., 2780., 1958., 1842.],\n",
" [ nan, nan, nan, ..., 3328., 2654., 1897.],\n",
" [ nan, nan, nan, ..., 3453., 2780., 2226.]],\n",
"\n",
" [[ 4065., 4067., 4678., ..., nan, nan, nan],\n",
" [ 3656., 4450., 4393., ..., nan, nan, nan],\n",
" [ 3808., 5130., 4127., ..., nan, nan, nan],\n",
" ...,\n",
" [ 7555., 7988., 8643., ..., nan, nan, nan],\n",
" [ 7765., 8659., 10020., ..., nan, nan, nan],\n",
" [ 8191., 9379., 10163., ..., nan, nan, nan]],\n",
"\n",
" [[ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" [ nan, nan, nan, ..., nan, nan, nan],\n",
" ...,\n",
" [ nan, nan, nan, ..., 1389., 1395., 1370.],\n",
" [ nan, nan, nan, ..., 1365., 1369., 1386.],\n",
" [ nan, nan, nan, ..., 1387., 1374., 1386.]]],\n",
" dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>scl</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>nan nan nan nan ... 6.0 6.0 6.0 6.0</div><input id='attrs-2b7068cc-b2fd-4932-9f3f-7f40b249796a' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-2b7068cc-b2fd-4932-9f3f-7f40b249796a' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-d0ed6142-7a61-4011-bd82-9f6639fe6ae7' class='xr-var-data-in' type='checkbox'><label for='data-d0ed6142-7a61-4011-bd82-9f6639fe6ae7' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([[[nan, nan, nan, ..., nan, nan, nan],\n",
" [nan, nan, nan, ..., nan, nan, nan],\n",
" [nan, nan, nan, ..., nan, nan, nan],\n",
" ...,\n",
" [nan, nan, nan, ..., 6., 6., 6.],\n",
" [nan, nan, nan, ..., 6., 6., 6.],\n",
" [nan, nan, nan, ..., 6., 6., 6.]],\n",
"\n",
" [[ 5., 5., 5., ..., nan, nan, nan],\n",
" [ 5., 5., 5., ..., nan, nan, nan],\n",
" [ 5., 5., 5., ..., nan, nan, nan],\n",
" ...,\n",
" [ 4., 4., 4., ..., nan, nan, nan],\n",
" [ 4., 4., 4., ..., nan, nan, nan],\n",
" [ 4., 4., 4., ..., nan, nan, nan]],\n",
"\n",
" [[ 5., 5., 5., ..., nan, nan, nan],\n",
" [ 5., 5., 5., ..., nan, nan, nan],\n",
" [ 5., 5., 5., ..., nan, nan, nan],\n",
" ...,\n",
"...\n",
" ...,\n",
" [nan, nan, nan, ..., 8., 8., 8.],\n",
" [nan, nan, nan, ..., 8., 8., 8.],\n",
" [nan, nan, nan, ..., 8., 8., 8.]],\n",
"\n",
" [[ 4., 4., 4., ..., nan, nan, nan],\n",
" [ 4., 4., 4., ..., nan, nan, nan],\n",
" [ 4., 4., 4., ..., nan, nan, nan],\n",
" ...,\n",
" [ 9., 9., 9., ..., nan, nan, nan],\n",
" [ 9., 9., 9., ..., nan, nan, nan],\n",
" [ 9., 9., 9., ..., nan, nan, nan]],\n",
"\n",
" [[nan, nan, nan, ..., nan, nan, nan],\n",
" [nan, nan, nan, ..., nan, nan, nan],\n",
" [nan, nan, nan, ..., nan, nan, nan],\n",
" ...,\n",
" [nan, nan, nan, ..., 6., 6., 6.],\n",
" [nan, nan, nan, ..., 6., 6., 6.],\n",
" [nan, nan, nan, ..., 6., 6., 6.]]], dtype=float32)</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-24b0c7e2-99ef-4f17-950a-e6d1b90d9364' class='xr-section-summary-in' type='checkbox' ><label for='section-24b0c7e2-99ef-4f17-950a-e6d1b90d9364' class='xr-section-summary' >Indexes: <span>(3)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-index-name'><div>y</div></div><div class='xr-index-preview'>PandasIndex</div><input type='checkbox' disabled/><label></label><input id='index-fbc95b49-e450-4185-ba0b-dfa1a8e40fb4' class='xr-index-data-in' type='checkbox'/><label for='index-fbc95b49-e450-4185-ba0b-dfa1a8e40fb4' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(Index([1083530.0, 1083510.0, 1083490.0, 1083470.0, 1083450.0, 1083430.0,\n",
" 1083410.0, 1083390.0, 1083370.0, 1083350.0,\n",
" ...\n",
" 1028250.0, 1028230.0, 1028210.0, 1028190.0, 1028170.0, 1028150.0,\n",
" 1028130.0, 1028110.0, 1028090.0, 1028070.0],\n",
" dtype=&#x27;float64&#x27;, name=&#x27;y&#x27;, length=2774))</pre></div></li><li class='xr-var-item'><div class='xr-index-name'><div>x</div></div><div class='xr-index-preview'>PandasIndex</div><input type='checkbox' disabled/><label></label><input id='index-21ea4ba7-5e83-4ad3-b702-775403fb0467' class='xr-index-data-in' type='checkbox'/><label for='index-21ea4ba7-5e83-4ad3-b702-775403fb0467' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(Index([565790.0, 565810.0, 565830.0, 565850.0, 565870.0, 565890.0, 565910.0,\n",
" 565930.0, 565950.0, 565970.0,\n",
" ...\n",
" 631610.0, 631630.0, 631650.0, 631670.0, 631690.0, 631710.0, 631730.0,\n",
" 631750.0, 631770.0, 631790.0],\n",
" dtype=&#x27;float64&#x27;, name=&#x27;x&#x27;, length=3301))</pre></div></li><li class='xr-var-item'><div class='xr-index-name'><div>time</div></div><div class='xr-index-preview'>PandasIndex</div><input type='checkbox' disabled/><label></label><input id='index-d33006ac-40ba-4ca5-9d13-9a3d4f7f3b32' class='xr-index-data-in' type='checkbox'/><label for='index-d33006ac-40ba-4ca5-9d13-9a3d4f7f3b32' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(DatetimeIndex([&#x27;2023-03-23 03:05:29.024000&#x27;, &#x27;2023-03-26 03:15:19.024000&#x27;,\n",
" &#x27;2023-04-05 03:15:19.024000&#x27;, &#x27;2023-04-15 03:15:19.024000&#x27;,\n",
" &#x27;2023-05-02 03:05:29.024000&#x27;, &#x27;2023-05-15 03:15:19.024000&#x27;,\n",
" &#x27;2023-05-17 03:05:21.024000&#x27;],\n",
" dtype=&#x27;datetime64[ns]&#x27;, name=&#x27;time&#x27;, freq=None))</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-51904105-0728-44eb-8df1-89ddb68c7a64' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-51904105-0728-44eb-8df1-89ddb68c7a64' class='xr-section-summary' title='Expand/collapse section'>Attributes: <span>(0)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><dl class='xr-attrs'></dl></div></li></ul></div></div>"
],
"text/plain": [
"<xarray.Dataset> Size: 769MB\n",
"Dimensions: (y: 2774, x: 3301, time: 7)\n",
"Coordinates:\n",
" * y (y) float64 22kB 1.084e+06 1.084e+06 ... 1.028e+06 1.028e+06\n",
" * x (x) float64 26kB 5.658e+05 5.658e+05 ... 6.318e+05 6.318e+05\n",
" spatial_ref int32 4B 32648\n",
" * time (time) datetime64[ns] 56B 2023-03-23T03:05:29.024000 ... 202...\n",
"Data variables:\n",
" red (time, y, x) float32 256MB nan nan nan ... 1.917e+03 1.926e+03\n",
" nir (time, y, x) float32 256MB nan nan nan ... 1.374e+03 1.386e+03\n",
" scl (time, y, x) float32 256MB nan nan nan nan ... 6.0 6.0 6.0 6.0"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 12.5 s, sys: 974 ms, total: 13.5 s\n",
"Wall time: 2min 25s\n"
]
}
],
"source": [
"%%time\n",
"# 📡 LOAD SENTINEL-2 FROM MICROSOFT PLANETARY COMPUTER\n",
"print(\"=\"*70)\n",
"print(\"LOADING SENTINEL-2 L2A\")\n",
"print(\"=\"*70)\n",
"\n",
"print(\"\\n🔍 Searching for Sentinel-2 scenes...\")\n",
"query_s2 = catalog.search(\n",
" collections=[\"sentinel-2-l2a\"],\n",
" bbox=bbox,\n",
" datetime=time_range,\n",
" query={\"eo:cloud_cover\": {\"lt\": 30}} # Cloud cover < 30% (giảm từ 50%)\n",
")\n",
"\n",
"items_s2 = list(query_s2.item_collection())\n",
"print(f\"✅ Found {len(items_s2)} Sentinel-2 scenes\")\n",
"\n",
"# GIỚI HẠN SỐ LƯỢNG SCENES cho PC cá nhân\n",
"max_scenes = 12 # Giảm xuống 12 scenes để tối ưu cho PC\n",
"if len(items_s2) > max_scenes:\n",
" print(f\"⚠️ Limiting to {max_scenes} scenes for personal computer\")\n",
" # Chọn scenes đều đặn trong khoảng thời gian\n",
" step = len(items_s2) // max_scenes\n",
" items_s2 = items_s2[::step][:max_scenes]\n",
" print(f\" Selected {len(items_s2)} scenes evenly distributed\")\n",
"\n",
"if len(items_s2) > 0:\n",
" # Show first few scenes\n",
" print(f\"\\n📋 Sample scenes:\")\n",
" for i, item in enumerate(items_s2[:5]):\n",
" date = item.datetime.strftime(\"%Y-%m-%d\")\n",
" cloud = item.properties.get(\"eo:cloud_cover\", \"N/A\")\n",
" print(f\" [{i+1}] {date} - Cloud: {cloud}%\")\n",
" \n",
" # Re-sign items to ensure fresh URLs (keep as pystac objects)\n",
" print(f\"\\n🔑 Signing STAC items...\")\n",
" items_s2 = [planetary_computer.sign(item) for item in items_s2]\n",
" \n",
" # Load Sentinel-2 data (without Dask chunks)\n",
" print(f\"\\n⏳ Loading Sentinel-2 data...\")\n",
" ds_s2 = stac_load(\n",
" items_s2,\n",
" bands=[\"B04\", \"B08\", \"SCL\"], # Red (B04), NIR (B08), Scene Classification (SCL)\n",
" crs=\"EPSG:32648\",\n",
" resolution=20, # 20m resolution (4x smaller data than 10m)\n",
" bbox=bbox,\n",
" patch_url=planetary_computer.sign, # Re-sign URLs during loading\n",
" fail_on_error=False, # Skip problematic tiles instead of crashing\n",
" )\n",
" \n",
" # Rename bands to simpler names\n",
" ds_s2 = ds_s2.rename({\"B04\": \"red\", \"B08\": \"nir\", \"SCL\": \"scl\"})\n",
" \n",
" print(f\"\\n✅ Sentinel-2 loaded!\")\n",
" print(f\" Shape: {dict(ds_s2.dims)}\")\n",
" print(f\" Variables: {list(ds_s2.data_vars)}\")\n",
" display(ds_s2)\n",
"else:\n",
" print(f\"❌ No Sentinel-2 scenes found\")\n",
"\n",
" ds_s2 = Noneprint(\"=\"*70)\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "435f9f78-a9a4-4226-86ca-d4bec42d454e",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"LOADING SENTINEL-1 RTC\n",
"======================================================================\n",
"\n",
"🔍 Searching for Sentinel-1 scenes...\n",
"✅ Found 22 Sentinel-1 scenes\n",
"⚠️ Limiting to 12 scenes for personal computer\n",
" Selected 12 scenes evenly distributed\n",
"\n",
"📋 Sample scenes:\n",
" [1] 2023-05-29 - Orbit: ascending\n",
" [2] 2023-05-29 - Orbit: ascending\n",
" [3] 2023-05-17 - Orbit: ascending\n",
" [4] 2023-05-17 - Orbit: ascending\n",
" [5] 2023-05-05 - Orbit: ascending\n",
"\n",
"🔑 Signing STAC items...\n",
"\n",
"⏳ Loading Sentinel-1 data...\n",
"\n",
"🔄 Converting to dB...\n",
"\n",
"✅ Sentinel-1 loaded!\n",
" Shape: {'y': 2774, 'x': 3301, 'time': 12}\n",
" Variables: ['vv', 'vh', 'vv_db', 'vh_db']\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"<timed exec>:55: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.\n"
]
},
{
"data": {
"text/html": [
"<div><svg style=\"position: absolute; width: 0; height: 0; overflow: hidden\">\n",
"<defs>\n",
"<symbol id=\"icon-database\" viewBox=\"0 0 32 32\">\n",
"<path d=\"M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z\"></path>\n",
"<path d=\"M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n",
"<path d=\"M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n",
"</symbol>\n",
"<symbol id=\"icon-file-text2\" viewBox=\"0 0 32 32\">\n",
"<path d=\"M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z\"></path>\n",
"<path d=\"M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"<path d=\"M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"<path d=\"M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"</symbol>\n",
"</defs>\n",
"</svg>\n",
"<style>/* CSS stylesheet for displaying xarray objects in jupyterlab.\n",
" *\n",
" */\n",
"\n",
":root {\n",
" --xr-font-color0: var(\n",
" --jp-content-font-color0,\n",
" var(--pst-color-text-base rgba(0, 0, 0, 1))\n",
" );\n",
" --xr-font-color2: var(\n",
" --jp-content-font-color2,\n",
" var(--pst-color-text-base, rgba(0, 0, 0, 0.54))\n",
" );\n",
" --xr-font-color3: var(\n",
" --jp-content-font-color3,\n",
" var(--pst-color-text-base, rgba(0, 0, 0, 0.38))\n",
" );\n",
" --xr-border-color: var(\n",
" --jp-border-color2,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 10))\n",
" );\n",
" --xr-disabled-color: var(\n",
" --jp-layout-color3,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 40))\n",
" );\n",
" --xr-background-color: var(\n",
" --jp-layout-color0,\n",
" var(--pst-color-on-background, white)\n",
" );\n",
" --xr-background-color-row-even: var(\n",
" --jp-layout-color1,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 5))\n",
" );\n",
" --xr-background-color-row-odd: var(\n",
" --jp-layout-color2,\n",
" hsl(from var(--pst-color-on-background, white) h s calc(l - 15))\n",
" );\n",
"}\n",
"\n",
"html[theme=\"dark\"],\n",
"html[data-theme=\"dark\"],\n",
"body[data-theme=\"dark\"],\n",
"body.vscode-dark {\n",
" --xr-font-color0: var(\n",
" --jp-content-font-color0,\n",
" var(--pst-color-text-base, rgba(255, 255, 255, 1))\n",
" );\n",
" --xr-font-color2: var(\n",
" --jp-content-font-color2,\n",
" var(--pst-color-text-base, rgba(255, 255, 255, 0.54))\n",
" );\n",
" --xr-font-color3: var(\n",
" --jp-content-font-color3,\n",
" var(--pst-color-text-base, rgba(255, 255, 255, 0.38))\n",
" );\n",
" --xr-border-color: var(\n",
" --jp-border-color2,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 10))\n",
" );\n",
" --xr-disabled-color: var(\n",
" --jp-layout-color3,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 40))\n",
" );\n",
" --xr-background-color: var(\n",
" --jp-layout-color0,\n",
" var(--pst-color-on-background, #111111)\n",
" );\n",
" --xr-background-color-row-even: var(\n",
" --jp-layout-color1,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 5))\n",
" );\n",
" --xr-background-color-row-odd: var(\n",
" --jp-layout-color2,\n",
" hsl(from var(--pst-color-on-background, #111111) h s calc(l + 15))\n",
" );\n",
"}\n",
"\n",
".xr-wrap {\n",
" display: block !important;\n",
" min-width: 300px;\n",
" max-width: 700px;\n",
"}\n",
"\n",
".xr-text-repr-fallback {\n",
" /* fallback to plain text repr when CSS is not injected (untrusted notebook) */\n",
" display: none;\n",
"}\n",
"\n",
".xr-header {\n",
" padding-top: 6px;\n",
" padding-bottom: 6px;\n",
" margin-bottom: 4px;\n",
" border-bottom: solid 1px var(--xr-border-color);\n",
"}\n",
"\n",
".xr-header > div,\n",
".xr-header > ul {\n",
" display: inline;\n",
" margin-top: 0;\n",
" margin-bottom: 0;\n",
"}\n",
"\n",
".xr-obj-type,\n",
".xr-array-name {\n",
" margin-left: 2px;\n",
" margin-right: 10px;\n",
"}\n",
"\n",
".xr-obj-type {\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-sections {\n",
" padding-left: 0 !important;\n",
" display: grid;\n",
" grid-template-columns: 150px auto auto 1fr 0 20px 0 20px;\n",
"}\n",
"\n",
".xr-section-item {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-section-item input {\n",
" display: inline-block;\n",
" opacity: 0;\n",
" height: 0;\n",
"}\n",
"\n",
".xr-section-item input + label {\n",
" color: var(--xr-disabled-color);\n",
" border: 2px solid transparent !important;\n",
"}\n",
"\n",
".xr-section-item input:enabled + label {\n",
" cursor: pointer;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-section-item input:focus + label {\n",
" border: 2px solid var(--xr-font-color0) !important;\n",
"}\n",
"\n",
".xr-section-item input:enabled + label:hover {\n",
" color: var(--xr-font-color0);\n",
"}\n",
"\n",
".xr-section-summary {\n",
" grid-column: 1;\n",
" color: var(--xr-font-color2);\n",
" font-weight: 500;\n",
"}\n",
"\n",
".xr-section-summary > span {\n",
" display: inline-block;\n",
" padding-left: 0.5em;\n",
"}\n",
"\n",
".xr-section-summary-in:disabled + label {\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-section-summary-in + label:before {\n",
" display: inline-block;\n",
" content: \"►\";\n",
" font-size: 11px;\n",
" width: 15px;\n",
" text-align: center;\n",
"}\n",
"\n",
".xr-section-summary-in:disabled + label:before {\n",
" color: var(--xr-disabled-color);\n",
"}\n",
"\n",
".xr-section-summary-in:checked + label:before {\n",
" content: \"▼\";\n",
"}\n",
"\n",
".xr-section-summary-in:checked + label > span {\n",
" display: none;\n",
"}\n",
"\n",
".xr-section-summary,\n",
".xr-section-inline-details {\n",
" padding-top: 4px;\n",
" padding-bottom: 4px;\n",
"}\n",
"\n",
".xr-section-inline-details {\n",
" grid-column: 2 / -1;\n",
"}\n",
"\n",
".xr-section-details {\n",
" display: none;\n",
" grid-column: 1 / -1;\n",
" margin-bottom: 5px;\n",
"}\n",
"\n",
".xr-section-summary-in:checked ~ .xr-section-details {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-array-wrap {\n",
" grid-column: 1 / -1;\n",
" display: grid;\n",
" grid-template-columns: 20px auto;\n",
"}\n",
"\n",
".xr-array-wrap > label {\n",
" grid-column: 1;\n",
" vertical-align: top;\n",
"}\n",
"\n",
".xr-preview {\n",
" color: var(--xr-font-color3);\n",
"}\n",
"\n",
".xr-array-preview,\n",
".xr-array-data {\n",
" padding: 0 5px !important;\n",
" grid-column: 2;\n",
"}\n",
"\n",
".xr-array-data,\n",
".xr-array-in:checked ~ .xr-array-preview {\n",
" display: none;\n",
"}\n",
"\n",
".xr-array-in:checked ~ .xr-array-data,\n",
".xr-array-preview {\n",
" display: inline-block;\n",
"}\n",
"\n",
".xr-dim-list {\n",
" display: inline-block !important;\n",
" list-style: none;\n",
" padding: 0 !important;\n",
" margin: 0;\n",
"}\n",
"\n",
".xr-dim-list li {\n",
" display: inline-block;\n",
" padding: 0;\n",
" margin: 0;\n",
"}\n",
"\n",
".xr-dim-list:before {\n",
" content: \"(\";\n",
"}\n",
"\n",
".xr-dim-list:after {\n",
" content: \")\";\n",
"}\n",
"\n",
".xr-dim-list li:not(:last-child):after {\n",
" content: \",\";\n",
" padding-right: 5px;\n",
"}\n",
"\n",
".xr-has-index {\n",
" font-weight: bold;\n",
"}\n",
"\n",
".xr-var-list,\n",
".xr-var-item {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-var-item > div,\n",
".xr-var-item label,\n",
".xr-var-item > .xr-var-name span {\n",
" background-color: var(--xr-background-color-row-even);\n",
" border-color: var(--xr-background-color-row-odd);\n",
" margin-bottom: 0;\n",
" padding-top: 2px;\n",
"}\n",
"\n",
".xr-var-item > .xr-var-name:hover span {\n",
" padding-right: 5px;\n",
"}\n",
"\n",
".xr-var-list > li:nth-child(odd) > div,\n",
".xr-var-list > li:nth-child(odd) > label,\n",
".xr-var-list > li:nth-child(odd) > .xr-var-name span {\n",
" background-color: var(--xr-background-color-row-odd);\n",
" border-color: var(--xr-background-color-row-even);\n",
"}\n",
"\n",
".xr-var-name {\n",
" grid-column: 1;\n",
"}\n",
"\n",
".xr-var-dims {\n",
" grid-column: 2;\n",
"}\n",
"\n",
".xr-var-dtype {\n",
" grid-column: 3;\n",
" text-align: right;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-var-preview {\n",
" grid-column: 4;\n",
"}\n",
"\n",
".xr-index-preview {\n",
" grid-column: 2 / 5;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-var-name,\n",
".xr-var-dims,\n",
".xr-var-dtype,\n",
".xr-preview,\n",
".xr-attrs dt {\n",
" white-space: nowrap;\n",
" overflow: hidden;\n",
" text-overflow: ellipsis;\n",
" padding-right: 10px;\n",
"}\n",
"\n",
".xr-var-name:hover,\n",
".xr-var-dims:hover,\n",
".xr-var-dtype:hover,\n",
".xr-attrs dt:hover {\n",
" overflow: visible;\n",
" width: auto;\n",
" z-index: 1;\n",
"}\n",
"\n",
".xr-var-attrs,\n",
".xr-var-data,\n",
".xr-index-data {\n",
" display: none;\n",
" border-top: 2px dotted var(--xr-background-color);\n",
" padding-bottom: 20px !important;\n",
" padding-top: 10px !important;\n",
"}\n",
"\n",
".xr-var-attrs-in + label,\n",
".xr-var-data-in + label,\n",
".xr-index-data-in + label {\n",
" padding: 0 1px;\n",
"}\n",
"\n",
".xr-var-attrs-in:checked ~ .xr-var-attrs,\n",
".xr-var-data-in:checked ~ .xr-var-data,\n",
".xr-index-data-in:checked ~ .xr-index-data {\n",
" display: block;\n",
"}\n",
"\n",
".xr-var-data > table {\n",
" float: right;\n",
"}\n",
"\n",
".xr-var-data > pre,\n",
".xr-index-data > pre,\n",
".xr-var-data > table > tbody > tr {\n",
" background-color: transparent !important;\n",
"}\n",
"\n",
".xr-var-name span,\n",
".xr-var-data,\n",
".xr-index-name div,\n",
".xr-index-data,\n",
".xr-attrs {\n",
" padding-left: 25px !important;\n",
"}\n",
"\n",
".xr-attrs,\n",
".xr-var-attrs,\n",
".xr-var-data,\n",
".xr-index-data {\n",
" grid-column: 1 / -1;\n",
"}\n",
"\n",
"dl.xr-attrs {\n",
" padding: 0;\n",
" margin: 0;\n",
" display: grid;\n",
" grid-template-columns: 125px auto;\n",
"}\n",
"\n",
".xr-attrs dt,\n",
".xr-attrs dd {\n",
" padding: 0;\n",
" margin: 0;\n",
" float: left;\n",
" padding-right: 10px;\n",
" width: auto;\n",
"}\n",
"\n",
".xr-attrs dt {\n",
" font-weight: normal;\n",
" grid-column: 1;\n",
"}\n",
"\n",
".xr-attrs dt:hover span {\n",
" display: inline-block;\n",
" background: var(--xr-background-color);\n",
" padding-right: 10px;\n",
"}\n",
"\n",
".xr-attrs dd {\n",
" grid-column: 2;\n",
" white-space: pre-wrap;\n",
" word-break: break-all;\n",
"}\n",
"\n",
".xr-icon-database,\n",
".xr-icon-file-text2,\n",
".xr-no-icon {\n",
" display: inline-block;\n",
" vertical-align: middle;\n",
" width: 1em;\n",
" height: 1.5em !important;\n",
" stroke-width: 0;\n",
" stroke: currentColor;\n",
" fill: currentColor;\n",
"}\n",
"\n",
".xr-var-attrs-in:checked + label > .xr-icon-file-text2,\n",
".xr-var-data-in:checked + label > .xr-icon-database,\n",
".xr-index-data-in:checked + label > .xr-icon-database {\n",
" color: var(--xr-font-color0);\n",
" filter: drop-shadow(1px 1px 5px var(--xr-font-color2));\n",
" stroke-width: 0.8px;\n",
"}\n",
"</style><pre class='xr-text-repr-fallback'>&lt;xarray.Dataset&gt; Size: 2GB\n",
"Dimensions: (y: 2774, x: 3301, time: 12)\n",
"Coordinates:\n",
" * y (y) float64 22kB 1.084e+06 1.084e+06 ... 1.028e+06 1.028e+06\n",
" * x (x) float64 26kB 5.658e+05 5.658e+05 ... 6.318e+05 6.318e+05\n",
" spatial_ref int32 4B 32648\n",
" * time (time) datetime64[ns] 96B 2023-04-11T11:11:31.308452 ... 202...\n",
"Data variables:\n",
" vv (time, y, x) float32 440MB -3.277e+04 -3.277e+04 ... -3.277e+04\n",
" vh (time, y, x) float32 440MB -3.277e+04 -3.277e+04 ... -3.277e+04\n",
" vv_db (time, y, x) float32 440MB nan nan nan nan ... nan nan nan nan\n",
" vh_db (time, y, x) float32 440MB nan nan nan nan ... nan nan nan nan</pre><div class='xr-wrap' style='display:none'><div class='xr-header'><div class='xr-obj-type'>xarray.Dataset</div></div><ul class='xr-sections'><li class='xr-section-item'><input id='section-48d25f44-3d5f-44c4-9984-12078921b767' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-48d25f44-3d5f-44c4-9984-12078921b767' class='xr-section-summary' title='Expand/collapse section'>Dimensions:</label><div class='xr-section-inline-details'><ul class='xr-dim-list'><li><span class='xr-has-index'>y</span>: 2774</li><li><span class='xr-has-index'>x</span>: 3301</li><li><span class='xr-has-index'>time</span>: 12</li></ul></div><div class='xr-section-details'></div></li><li class='xr-section-item'><input id='section-cefc86b0-1417-43c3-9f64-f350487c7bae' class='xr-section-summary-in' type='checkbox' checked><label for='section-cefc86b0-1417-43c3-9f64-f350487c7bae' class='xr-section-summary' >Coordinates: <span>(4)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>y</span></div><div class='xr-var-dims'>(y)</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>1.084e+06 1.084e+06 ... 1.028e+06</div><input id='attrs-0eb3bbfe-423a-4b01-8fa5-61040cf3fcd1' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-0eb3bbfe-423a-4b01-8fa5-61040cf3fcd1' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-c6a50eb4-e745-4b62-bd2c-607afc242326' class='xr-var-data-in' type='checkbox'><label for='data-c6a50eb4-e745-4b62-bd2c-607afc242326' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>metre</dd><dt><span>resolution :</span></dt><dd>-20.0</dd><dt><span>crs :</span></dt><dd>EPSG:32648</dd></dl></div><div class='xr-var-data'><pre>array([1083530., 1083510., 1083490., ..., 1028110., 1028090., 1028070.])</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>x</span></div><div class='xr-var-dims'>(x)</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>5.658e+05 5.658e+05 ... 6.318e+05</div><input id='attrs-cfdb14ad-521a-4027-adc1-84c97d174847' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-cfdb14ad-521a-4027-adc1-84c97d174847' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-bae72e13-e1da-4fe5-a575-31124fd5cb64' class='xr-var-data-in' type='checkbox'><label for='data-bae72e13-e1da-4fe5-a575-31124fd5cb64' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>metre</dd><dt><span>resolution :</span></dt><dd>20.0</dd><dt><span>crs :</span></dt><dd>EPSG:32648</dd></dl></div><div class='xr-var-data'><pre>array([565790., 565810., 565830., ..., 631750., 631770., 631790.])</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>spatial_ref</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>int32</div><div class='xr-var-preview xr-preview'>32648</div><input id='attrs-99fee921-224e-4ee6-9324-689610ebb7b9' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-99fee921-224e-4ee6-9324-689610ebb7b9' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-7e23f893-f80f-49e0-b52b-44655ee9f7d5' class='xr-var-data-in' type='checkbox'><label for='data-7e23f893-f80f-49e0-b52b-44655ee9f7d5' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr
" &#x27;2023-04-22T22:46:11.669312000&#x27;, &#x27;2023-04-23T11:11:31.513504000&#x27;,\n",
" &#x27;2023-04-23T11:11:58.523290000&#x27;, &#x27;2023-05-04T22:46:12.328825000&#x27;,\n",
" &#x27;2023-05-05T11:11:32.160443000&#x27;, &#x27;2023-05-05T11:11:59.178349000&#x27;,\n",
" &#x27;2023-05-17T11:11:32.867879000&#x27;, &#x27;2023-05-17T11:11:59.891046000&#x27;,\n",
" &#x27;2023-05-29T11:11:33.480861000&#x27;, &#x27;2023-05-29T11:12:00.491409000&#x27;],\n",
" dtype=&#x27;datetime64[ns]&#x27;)</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-4f68871b-9ad6-4d3a-9574-cc0a7c0efe51' class='xr-section-summary-in' type='checkbox' checked><label for='section-4f68871b-9ad6-4d3a-9574-cc0a7c0efe51' class='xr-section-summary' >Data variables: <span>(4)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>vv</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>-3.277e+04 ... -3.277e+04</div><input id='attrs-7185693f-8a6a-4ec0-933f-899954459c8d' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-7185693f-8a6a-4ec0-933f-899954459c8d' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-50bb2a58-99d3-4851-810e-bb5c02efa4b2' class='xr-var-data-in' type='checkbox'><label for='data-50bb2a58-99d3-4851-810e-bb5c02efa4b2' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>nodata :</span></dt><dd>-32768</dd></dl></div><div class='xr-var-data'><pre>array([[[-3.27680000e+04, -3.27680000e+04, -3.27680000e+04, ...,\n",
" 2.69922972e-01, 2.39311606e-01, 1.48275137e-01],\n",
" [-3.27680000e+04, -3.27680000e+04, -3.27680000e+04, ...,\n",
" 2.80399889e-01, 1.79079548e-01, 1.71904087e-01],\n",
" [-3.27680000e+04, -3.27680000e+04, -3.27680000e+04, ...,\n",
" 2.62121648e-01, 4.99169677e-01, 5.18820047e-01],\n",
" ...,\n",
" [ 9.63703692e-02, 9.27014947e-02, 1.41044334e-01, ...,\n",
" 1.67655945e-02, 1.13825658e-02, 7.53090298e-03],\n",
" [ 1.21362977e-01, 1.53534919e-01, 1.54887989e-01, ...,\n",
" 1.18996780e-02, 7.22124008e-03, 8.94887559e-03],\n",
" [ 1.40187085e-01, 1.43613145e-01, 1.53412595e-01, ...,\n",
" 7.97165558e-03, 5.89693291e-03, 1.21060479e-02]],\n",
"\n",
" [[ 1.92549631e-01, 3.35060716e-01, 2.92650491e-01, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" [ 1.59623355e-01, 2.68875718e-01, 3.09906065e-01, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" [ 1.29058421e-01, 1.76203713e-01, 1.44357711e-01, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
"...\n",
" 1.40124923e-02, 1.86983664e-02, 2.77337898e-02],\n",
" [ 3.41572672e-01, 2.31136754e-01, 1.22129455e-01, ...,\n",
" 1.68878958e-02, 1.60078611e-02, 2.15534531e-02],\n",
" [ 3.34728718e-01, 1.93130448e-01, 1.16422415e-01, ...,\n",
" 1.49259586e-02, 1.91468988e-02, 1.53189301e-02]],\n",
"\n",
" [[ 2.01995030e-01, 1.92913145e-01, 1.97124958e-01, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" [ 1.87873095e-01, 1.79152444e-01, 2.29280218e-01, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" [ 2.06380323e-01, 2.33311683e-01, 2.01342508e-01, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" ...,\n",
" [-3.27680000e+04, -3.27680000e+04, -3.27680000e+04, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" [-3.27680000e+04, -3.27680000e+04, -3.27680000e+04, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04],\n",
" [-3.27680000e+04, -3.27680000e+04, -3.27680000e+04, ...,\n",
" -3.27680000e+04, -3.27680000e+04, -3.27680000e+04]]],\n",
" dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>vh</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>-3.277e+04 ... -3.277e+04</div><input id='attrs-b013f4c0-76f9-437d-b52a-5813a02814f1' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-b013f4c0-76f9-437d-b52a-5813a02814f1' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-8a4d4745-d4bd-4665-aabe-4d68b7a92775' class='xr-var-data-in' type='checkbox'><label for='data-8a4d4745-d4bd-4665-aabe-4d68b7a92775' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>nodata :</span></dt><dd>-32768</dd></dl></div><div class='xr-var-data'><pre>array([[[-3.2768000e+04, -3.2768000e+04, -3.2768000e+04, ...,\n",
" 5.7597220e-02, 5.4324944e-02, 5.5184130e-02],\n",
" [-3.2768000e+04, -3.2768000e+04, -3.2768000e+04, ...,\n",
" 4.1105211e-02, 4.6177238e-02, 6.9814801e-02],\n",
" [-3.2768000e+04, -3.2768000e+04, -3.2768000e+04, ...,\n",
" 5.8089536e-02, 7.9484530e-02, 5.0897941e-02],\n",
" ...,\n",
" [ 2.9909361e-02, 4.4590965e-02, 3.7466008e-02, ...,\n",
" 1.7120006e-03, 2.4200426e-03, 2.0317526e-03],\n",
" [ 3.4148626e-02, 4.9092196e-02, 3.7940368e-02, ...,\n",
" 1.1375681e-03, 2.2063411e-03, 2.0408719e-03],\n",
" [ 3.1482033e-02, 3.7801184e-02, 2.9957248e-02, ...,\n",
" 1.3905684e-03, 1.8907794e-03, 1.7309467e-03]],\n",
"\n",
" [[ 3.4820329e-02, 2.6318308e-02, 1.5325809e-02, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" [ 2.6467143e-02, 3.2469962e-02, 2.4710242e-02, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" [ 3.2198720e-02, 4.4570472e-02, 3.8672999e-02, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
"...\n",
" [ 3.2152828e-02, 2.9749943e-02, 2.8792452e-02, ...,\n",
" 2.9391954e-03, 1.1841693e-03, 2.1481749e-03],\n",
" [ 3.8886297e-02, 2.5501370e-02, 1.8822463e-02, ...,\n",
" 2.3227420e-03, 1.7014297e-03, 3.0512135e-03],\n",
" [ 3.2982059e-02, 3.3030216e-02, 1.9935342e-02, ...,\n",
" 1.8559876e-03, 1.5505330e-03, 2.7016480e-03]],\n",
"\n",
" [[ 3.0381918e-02, 2.1821173e-02, 1.6987311e-02, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" [ 2.0493472e-02, 2.4975603e-02, 2.4544537e-02, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" [ 2.5123015e-02, 1.4230552e-02, 2.2678960e-02, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" ...,\n",
" [-3.2768000e+04, -3.2768000e+04, -3.2768000e+04, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" [-3.2768000e+04, -3.2768000e+04, -3.2768000e+04, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04],\n",
" [-3.2768000e+04, -3.2768000e+04, -3.2768000e+04, ...,\n",
" -3.2768000e+04, -3.2768000e+04, -3.2768000e+04]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>vv_db</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>nan nan nan nan ... nan nan nan nan</div><input id='attrs-0c4a7429-f0ad-4769-9ce2-7826da33272f' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-0c4a7429-f0ad-4769-9ce2-7826da33272f' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-b3cab312-f90f-40e6-8c6a-77c4f323316b' class='xr-var-data-in' type='checkbox'><label for='data-b3cab312-f90f-40e6-8c6a-77c4f323316b' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([[[ nan, nan, nan, ..., -5.6876016,\n",
" -6.2103624, -8.289317 ],\n",
" [ nan, nan, nan, ..., -5.5222216,\n",
" -7.46954 , -7.647138 ],\n",
" [ nan, nan, nan, ..., -5.8149714,\n",
" -3.017518 , -2.8498328],\n",
" ...,\n",
" [-10.160565 , -10.329132 , -8.506443 , ..., -17.755812 ,\n",
" -19.437597 , -21.23153 ],\n",
" [ -9.159138 , -8.137928 , -8.099823 , ..., -19.244648 ,\n",
" -21.413881 , -20.482315 ],\n",
" [ -8.53292 , -8.428058 , -8.14139 , ..., -20.984516 ,\n",
" -22.29374 , -19.169977 ]],\n",
"\n",
" [[ -7.1545734, -4.748765 , -5.336508 , ..., nan,\n",
" nan, nan],\n",
" [ -7.969036 , -5.704484 , -5.0876994, ..., nan,\n",
" nan, nan],\n",
" [ -8.892137 , -7.5398493, -8.405601 , ..., nan,\n",
" nan, nan],\n",
"...\n",
" [ -7.6710267, -8.486804 , -9.900598 , ..., -18.534847 ,\n",
" -17.281963 , -15.569907 ],\n",
" [ -4.665169 , -6.36131 , -9.131796 , ..., -17.724245 ,\n",
" -17.956667 , -16.664831 ],\n",
" [ -4.7530704, -7.1414924, -9.339634 , ..., -18.260578 ,\n",
" -17.179016 , -18.147715 ]],\n",
"\n",
" [[ -6.946593 , -7.146382 , -7.0525837, ..., nan,\n",
" nan, nan],\n",
" [ -7.2613544, -7.467773 , -6.396334 , ..., nan,\n",
" nan, nan],\n",
" [ -6.8533173, -6.320635 , -6.960645 , ..., nan,\n",
" nan, nan],\n",
" ...,\n",
" [ nan, nan, nan, ..., nan,\n",
" nan, nan],\n",
" [ nan, nan, nan, ..., nan,\n",
" nan, nan],\n",
" [ nan, nan, nan, ..., nan,\n",
" nan, nan]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>vh_db</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>nan nan nan nan ... nan nan nan nan</div><input id='attrs-7de41df1-ab32-43cf-a8d2-900fe3103726' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-7de41df1-ab32-43cf-a8d2-900fe3103726' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-14373362-4cc4-4f63-8841-050bd8111757' class='xr-var-data-in' type='checkbox'><label for='data-14373362-4cc4-4f63-8841-050bd8111757' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([[[ nan, nan, nan, ..., -12.395985 ,\n",
" -12.650007 , -12.581859 ],\n",
" [ nan, nan, nan, ..., -13.861032 ,\n",
" -13.3557205, -11.560525 ],\n",
" [ nan, nan, nan, ..., -12.35902 ,\n",
" -10.997173 , -12.932998 ],\n",
" ...,\n",
" [-15.241928 , -13.50753 , -14.263625 , ..., -27.664963 ,\n",
" -26.16177 , -26.921291 ],\n",
" [-14.666267 , -13.089875 , -14.208984 , ..., -29.440228 ,\n",
" -26.563272 , -26.901844 ],\n",
" [-15.019371 , -14.224947 , -15.234981 , ..., -28.568077 ,\n",
" -27.233591 , -27.617165 ]],\n",
"\n",
" [[-14.581671 , -15.7974205, -18.145767 , ..., nan,\n",
" nan, nan],\n",
" [-15.772929 , -14.885182 , -16.07123 , ..., nan,\n",
" nan, nan],\n",
" [-14.921614 , -13.509527 , -14.125921 , ..., nan,\n",
" nan, nan],\n",
"...\n",
" [-14.927808 , -15.265139 , -15.407213 , ..., -25.317717 ,\n",
" -29.265862 , -26.679304 ],\n",
" [-14.102035 , -15.934364 , -17.253235 , ..., -26.33999 ,\n",
" -27.69186 , -25.155275 ],\n",
" [-14.817223 , -14.810886 , -17.003763 , ..., -27.31425 ,\n",
" -28.09519 , -25.683712 ]],\n",
"\n",
" [[-15.173847 , -16.611217 , -17.698753 , ..., nan,\n",
" nan, nan],\n",
" [-16.883844 , -16.02484 , -16.100452 , ..., nan,\n",
" nan, nan],\n",
" [-15.999283 , -18.467783 , -16.44377 , ..., nan,\n",
" nan, nan],\n",
" ...,\n",
" [ nan, nan, nan, ..., nan,\n",
" nan, nan],\n",
" [ nan, nan, nan, ..., nan,\n",
" nan, nan],\n",
" [ nan, nan, nan, ..., nan,\n",
" nan, nan]]], dtype=float32)</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-3d82d3de-546c-4ba9-b8a3-5e286b0480c7' class='xr-section-summary-in' type='checkbox' ><label for='section-3d82d3de-546c-4ba9-b8a3-5e286b0480c7' class='xr-section-summary' >Indexes: <span>(3)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-index-name'><div>y</div></div><div class='xr-index-preview'>PandasIndex</div><input type='checkbox' disabled/><label></label><input id='index-f9b88385-42df-44f6-b960-369716c47432' class='xr-index-data-in' type='checkbox'/><label for='index-f9b88385-42df-44f6-b960-369716c47432' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(Index([1083530.0, 1083510.0, 1083490.0, 1083470.0, 1083450.0, 1083430.0,\n",
" 1083410.0, 1083390.0, 1083370.0, 1083350.0,\n",
" ...\n",
" 1028250.0, 1028230.0, 1028210.0, 1028190.0, 1028170.0, 1028150.0,\n",
" 1028130.0, 1028110.0, 1028090.0, 1028070.0],\n",
" dtype=&#x27;float64&#x27;, name=&#x27;y&#x27;, length=2774))</pre></div></li><li class='xr-var-item'><div class='xr-index-name'><div>x</div></div><div class='xr-index-preview'>PandasIndex</div><input type='checkbox' disabled/><label></label><input id='index-c8eaf763-2417-4a9e-b666-bdc3124be03f' class='xr-index-data-in' type='checkbox'/><label for='index-c8eaf763-2417-4a9e-b666-bdc3124be03f' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(Index([565790.0, 565810.0, 565830.0, 565850.0, 565870.0, 565890.0, 565910.0,\n",
" 565930.0, 565950.0, 565970.0,\n",
" ...\n",
" 631610.0, 631630.0, 631650.0, 631670.0, 631690.0, 631710.0, 631730.0,\n",
" 631750.0, 631770.0, 631790.0],\n",
" dtype=&#x27;float64&#x27;, name=&#x27;x&#x27;, length=3301))</pre></div></li><li class='xr-var-item'><div class='xr-index-name'><div>time</div></div><div class='xr-index-preview'>PandasIndex</div><input type='checkbox' disabled/><label></label><input id='index-831543ae-7072-40ec-b62d-d31c309ff1ec' class='xr-index-data-in' type='checkbox'/><label for='index-831543ae-7072-40ec-b62d-d31c309ff1ec' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(DatetimeIndex([&#x27;2023-04-11 11:11:31.308452&#x27;, &#x27;2023-04-11 11:11:58.319940&#x27;,\n",
" &#x27;2023-04-22 22:46:11.669312&#x27;, &#x27;2023-04-23 11:11:31.513504&#x27;,\n",
" &#x27;2023-04-23 11:11:58.523290&#x27;, &#x27;2023-05-04 22:46:12.328825&#x27;,\n",
" &#x27;2023-05-05 11:11:32.160443&#x27;, &#x27;2023-05-05 11:11:59.178349&#x27;,\n",
" &#x27;2023-05-17 11:11:32.867879&#x27;, &#x27;2023-05-17 11:11:59.891046&#x27;,\n",
" &#x27;2023-05-29 11:11:33.480861&#x27;, &#x27;2023-05-29 11:12:00.491409&#x27;],\n",
" dtype=&#x27;datetime64[ns]&#x27;, name=&#x27;time&#x27;, freq=None))</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-9d9ececa-11b9-4ca0-9318-0f1d436a5411' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-9d9ececa-11b9-4ca0-9318-0f1d436a5411' class='xr-section-summary' title='Expand/collapse section'>Attributes: <span>(0)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><dl class='xr-attrs'></dl></div></li></ul></div></div>"
],
"text/plain": [
"<xarray.Dataset> Size: 2GB\n",
"Dimensions: (y: 2774, x: 3301, time: 12)\n",
"Coordinates:\n",
" * y (y) float64 22kB 1.084e+06 1.084e+06 ... 1.028e+06 1.028e+06\n",
" * x (x) float64 26kB 5.658e+05 5.658e+05 ... 6.318e+05 6.318e+05\n",
" spatial_ref int32 4B 32648\n",
" * time (time) datetime64[ns] 96B 2023-04-11T11:11:31.308452 ... 202...\n",
"Data variables:\n",
" vv (time, y, x) float32 440MB -3.277e+04 -3.277e+04 ... -3.277e+04\n",
" vh (time, y, x) float32 440MB -3.277e+04 -3.277e+04 ... -3.277e+04\n",
" vv_db (time, y, x) float32 440MB nan nan nan nan ... nan nan nan nan\n",
" vh_db (time, y, x) float32 440MB nan nan nan nan ... nan nan nan nan"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 17.3 s, sys: 3.14 s, total: 20.4 s\n",
"Wall time: 3min 44s\n"
]
}
],
"source": [
"%%time\n",
"# 📡 LOAD SENTINEL-1 FROM MICROSOFT PLANETARY COMPUTER\n",
"print(\"=\"*70)\n",
"print(\"LOADING SENTINEL-1 RTC\")\n",
"print(\"=\"*70)\n",
"\n",
"print(\"\\n🔍 Searching for Sentinel-1 scenes...\")\n",
"query_s1 = catalog.search(\n",
" collections=[\"sentinel-1-rtc\"],\n",
" bbox=bbox,\n",
" datetime=time_range,\n",
")\n",
"\n",
"items_s1 = list(query_s1.item_collection())\n",
"print(f\"✅ Found {len(items_s1)} Sentinel-1 scenes\")\n",
"\n",
"# GIỚI HẠN SỐ LƯỢNG SCENES cho PC cá nhân\n",
"max_scenes = 12 # Giảm xuống 12 scenes để tối ưu cho PC\n",
"if len(items_s1) > max_scenes:\n",
" print(f\"⚠️ Limiting to {max_scenes} scenes for personal computer\")\n",
" # Chọn scenes đều đặn trong khoảng thời gian\n",
" step = len(items_s1) // max_scenes\n",
" items_s1 = items_s1[::step][:max_scenes]\n",
" print(f\" Selected {len(items_s1)} scenes evenly distributed\")\n",
"\n",
"if len(items_s1) > 0:\n",
" # Show first few scenes\n",
" print(f\"\\n📋 Sample scenes:\")\n",
" for i, item in enumerate(items_s1[:5]):\n",
" date = item.datetime.strftime(\"%Y-%m-%d\")\n",
" orbit = item.properties.get(\"sat:orbit_state\", \"N/A\")\n",
" print(f\" [{i+1}] {date} - Orbit: {orbit}\")\n",
" \n",
" # Re-sign items to ensure fresh URLs (keep as pystac objects)\n",
" print(f\"\\n🔑 Signing STAC items...\")\n",
" items_s1 = [planetary_computer.sign(item) for item in items_s1]\n",
" \n",
" # Load Sentinel-1 data (without Dask chunks)\n",
" print(f\"\\n⏳ Loading Sentinel-1 data...\")\n",
" ds_s1 = stac_load(\n",
" items_s1,\n",
" bands=[\"vv\", \"vh\"], # VV and VH polarizations\n",
" crs=\"EPSG:32648\",\n",
" resolution=20, # 20m resolution (4x smaller data than 10m)\n",
" bbox=bbox,\n",
" patch_url=planetary_computer.sign, # Re-sign URLs during loading\n",
" fail_on_error=False, # Skip problematic tiles instead of crashing\n",
" )\n",
" \n",
" # Convert to dB (Microsoft S1 is in linear power)\n",
" print(f\"\\n🔄 Converting to dB...\")\n",
" ds_s1['vv_db'] = 10 * np.log10(ds_s1['vv'].where(ds_s1['vv'] > 0))\n",
" ds_s1['vh_db'] = 10 * np.log10(ds_s1['vh'].where(ds_s1['vh'] > 0))\n",
" \n",
" print(f\"\\n✅ Sentinel-1 loaded!\")\n",
" print(f\" Shape: {dict(ds_s1.dims)}\")\n",
" print(f\" Variables: {list(ds_s1.data_vars)}\")\n",
" display(ds_s1)\n",
"else:\n",
" print(f\"❌ No Sentinel-1 scenes found\")\n",
"\n",
" ds_s1 = Noneprint(\"=\"*70)\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "d2585562-88aa-4c7d-bf70-1f6affcf65d4",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"DATA PROCESSING\n",
"======================================================================\n",
"\n",
"[1] Calculating NDVI...\n",
"✅ NDVI calculated\n",
" Shape: (7, 2774, 3301)\n",
" Time steps: 7\n",
"\n",
"[2] Applying cloud mask...\n",
"✅ Cloud mask applied\n",
"\n",
"[3] Computing mean NDVI across time...\n",
"✅ Mean NDVI computed\n",
" Shape: (2774, 3301)\n",
"======================================================================\n",
"CPU times: user 735 ms, sys: 538 ms, total: 1.27 s\n",
"Wall time: 1.26 s\n"
]
}
],
"source": [
"%%time\n",
"# 🌿 CALCULATE NDVI AND PROCESS DATA\n",
"print(\"=\"*70)\n",
"print(\"DATA PROCESSING\")\n",
"print(\"=\"*70)\n",
"\n",
"if ds_s2 is not None:\n",
" print(\"\\n[1] Calculating NDVI...\")\n",
" # NDVI = (NIR - Red) / (NIR + Red)\n",
" ndvi = (ds_s2['nir'] - ds_s2['red']) / (ds_s2['nir'] + ds_s2['red'] + 1e-8)\n",
" \n",
" print(f\"✅ NDVI calculated\")\n",
" print(f\" Shape: {ndvi.shape}\")\n",
" print(f\" Time steps: {len(ndvi.time)}\")\n",
" \n",
" # Cloud masking using SCL band\n",
" print(f\"\\n[2] Applying cloud mask...\")\n",
" # SCL values: 1=defective, 3=cloud shadow, 8=cloud medium, 9=cloud high, 10=cirrus\n",
" cloud_mask = ds_s2['scl'].isin([1, 3, 8, 9, 10])\n",
" ndvi_masked = ndvi.where(~cloud_mask)\n",
" \n",
" print(f\"✅ Cloud mask applied\")\n",
" \n",
" # Temporal aggregation (mean over time)\n",
" print(f\"\\n[3] Computing mean NDVI across time...\")\n",
" ndvi_mean = ndvi_masked.mean(dim='time')\n",
" \n",
" # Data already in memory, no need to compute() again\n",
" print(f\"✅ Mean NDVI computed\")\n",
" print(f\" Shape: {ndvi_mean.shape}\")\n",
" \n",
"else:\n",
" print(\"❌ No Sentinel-2 data to process\")\n",
" ndvi_mean = None\n",
"\n",
"print(\"=\"*70)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2e955884-d4af-422d-a8e6-d436199540e0",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"FEATURE EXTRACTION\n",
"======================================================================\n",
"\n",
"[1] Loading training data from: train/ST_training data_updated_1130points_new.shp\n",
"✅ Loaded 1130 training points\n",
" Available columns: ['No', 'X', 'Y', 'LU2022', 'Hientrang', 'HT_code', 'geometry']\n",
" Using label column: 'HT_code'\n",
" Classes: [0, 1, 2, 3, 4, 5, 6, 7]\n",
"\n",
"[2] Extracting features at training points...\n",
"✅ Extracted features for 638 valid points\n",
" Skipped 492 points (outside extent or NaN values)\n",
" Feature shape: (638, 3)\n",
" Feature names: ['NDVI_mean', 'VH_dB_mean', 'VV_dB_mean']\n",
"\n",
" Class distribution:\n",
" Class 0: 62 samples (9.7%)\n",
" Class 1: 114 samples (17.9%)\n",
" Class 3: 112 samples (17.6%)\n",
" Class 4: 104 samples (16.3%)\n",
" Class 5: 43 samples (6.7%)\n",
" Class 6: 150 samples (23.5%)\n",
" Class 7: 53 samples (8.3%)\n",
"======================================================================\n",
"CPU times: user 4.08 s, sys: 117 ms, total: 4.19 s\n",
"Wall time: 4.06 s\n"
]
}
],
"source": [
"%%time\n",
"# 🎯 EXTRACT TRAINING DATA FEATURES\n",
"print(\"=\"*70)\n",
"print(\"FEATURE EXTRACTION\")\n",
"print(\"=\"*70)\n",
"\n",
"# Check if required data is available\n",
"if 'ndvi_mean' not in globals() or 'ds_s1' not in globals():\n",
" print(\"❌ Error: Please run Cell 6 (DATA PROCESSING) first!\")\n",
" print(\" Required variables: ndvi_mean, ds_s1\")\n",
" raise RuntimeError(\"Missing required data. Run cells in order: Cell 4 → Cell 5 → Cell 6 → Cell 7\")\n",
"\n",
"# Load training shapefile\n",
"import geopandas as gpd\n",
"\n",
"train_path = 'train/ST_training data_updated_1130points_new.shp'\n",
"print(f\"\\n[1] Loading training data from: {train_path}\")\n",
"train_gdf = gpd.read_file(train_path)\n",
"\n",
"# Ensure CRS matches\n",
"if train_gdf.crs != 'EPSG:32648':\n",
" print(f\" Reprojecting from {train_gdf.crs} to EPSG:32648...\")\n",
" train_gdf = train_gdf.to_crs('EPSG:32648')\n",
"\n",
"print(f\"✅ Loaded {len(train_gdf)} training points\")\n",
"print(f\" Available columns: {list(train_gdf.columns)}\")\n",
"\n",
"# Auto-detect label column (look for common names)\n",
"label_column = None\n",
"for col in ['HT_code', 'Ma_LU', 'LU2022', 'class', 'Class', 'CLASS', 'label', 'Label', 'LABEL', 'LU_CODE', 'LU_code']:\n",
" if col in train_gdf.columns:\n",
" label_column = col\n",
" break\n",
"\n",
"if label_column is None:\n",
" print(f\"❌ Cannot find label column. Available columns: {list(train_gdf.columns)}\")\n",
" print(f\" Please check your shapefile and update the code.\")\n",
"else:\n",
" print(f\" Using label column: '{label_column}'\")\n",
" print(f\" Classes: {sorted(train_gdf[label_column].unique())}\")\n",
" \n",
" # Extract features at each training point\n",
" print(f\"\\n[2] Extracting features at training points...\")\n",
" \n",
" features = []\n",
" labels = []\n",
" skipped = 0\n",
" \n",
" for idx, row in train_gdf.iterrows():\n",
" point = row.geometrychro\n",
" x_coord = point.x\n",
" y_coord = point.y\n",
" label = row[label_column]\n",
" \n",
" # Extract NDVI at this location\n",
" if ndvi_mean is not None and ds_s1 is not None:\n",
" try:\n",
" ndvi_val = ndvi_mean.sel(x=x_coord, y=y_coord, method='nearest').values\n",
" \n",
" # Extract Sentinel-1 VH/VV at this location (mean across time)\n",
" # Data already in memory, no need to compute()\n",
" vh_val = ds_s1['vh_db'].sel(x=x_coord, y=y_coord, method='nearest').mean(dim='time').values\n",
" vv_val = ds_s1['vv_db'].sel(x=x_coord, y=y_coord, method='nearest').mean(dim='time').values\n",
" \n",
" # Create feature vector: [NDVI, VH_dB, VV_dB]\n",
" feature_vec = [ndvi_val, vh_val, vv_val]\n",
" \n",
" # Only add if all features are valid (not NaN)\n",
" if not np.isnan(feature_vec).any():\n",
" features.append(feature_vec)\n",
" labels.append(label)\n",
" else:\n",
" skipped += 1\n",
" except Exception as e:\n",
" # Skip points outside the data extent\n",
" skipped += 1\n",
" continue\n",
" \n",
" features = np.array(features)\n",
" labels = np.array(labels)\n",
" \n",
" print(f\"✅ Extracted features for {len(features)} valid points\")\n",
" print(f\" Skipped {skipped} points (outside extent or NaN values)\")\n",
" print(f\" Feature shape: {features.shape}\")\n",
" print(f\" Feature names: ['NDVI_mean', 'VH_dB_mean', 'VV_dB_mean']\")\n",
" print(f\"\\n Class distribution:\")\n",
" unique, counts = np.unique(labels, return_counts=True)\n",
" for cls, cnt in zip(unique, counts):\n",
" print(f\" Class {cls}: {cnt} samples ({cnt/len(labels)*100:.1f}%)\")\n",
"\n",
"print(\"=\"*70)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "f1a14379-ed6e-4897-9ca4-2669743fab40",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"MODEL TRAINING - GPU ACCELERATED\n",
"======================================================================\n",
"\n",
"[1] Encoding labels...\n",
"✅ Original classes: [0 1 3 4 5 6 7]\n",
" Encoded as: [0 1 2 3 4 5 6]\n",
"\n",
"[2] Splitting data (80% train, 20% test)...\n",
"✅ Training samples: 510\n",
" Testing samples: 128\n",
"\n",
"[3] Training XGBoost classifier on RTX 4060 GPU...\n",
" GPU Settings: device='cuda:0'\n",
"✅ Model trained on GPU\n",
"\n",
"[4] Evaluating model...\n",
"✅ Training accuracy: 1.0000\n",
" Testing accuracy: 0.5781\n",
"\n",
"[5] Classification Report:\n",
" precision recall f1-score support\n",
"\n",
" 0 0.27 0.25 0.26 12\n",
" 1 0.54 0.65 0.59 23\n",
" 3 0.57 0.55 0.56 22\n",
" 4 0.52 0.57 0.55 21\n",
" 5 0.80 0.44 0.57 9\n",
" 6 0.85 0.73 0.79 30\n",
" 7 0.43 0.55 0.48 11\n",
"\n",
" accuracy 0.58 128\n",
" macro avg 0.57 0.53 0.54 128\n",
"weighted avg 0.60 0.58 0.58 128\n",
"\n",
"\n",
"[6] Confusion Matrix:\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA3cAAAMWCAYAAABSm3/pAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAih9JREFUeJzs3Xd8FOXaxvFr0jYJJKGGJBAg9F6kBl6qCkbloIKKihSxgoWDFRvoUYLoUYoCFhCUI3CUIhYUkKYC0gSBIwiCEEooQRIIkECY9w/IypIACS47w+zvy2c+urMzu9dmssneuZ95xjBN0xQAAAAA4IoWYHUAAAAAAMDfR3EHAAAAAA5AcQcAAAAADkBxBwAAAAAOQHEHAAAAAA5AcQcAAAAADkBxBwAAAAAOQHEHAAAAAA5AcQcAAAAADkBxBwAAAAAOQHEHv/fLL7+od+/eSkhIUGhoqIoWLaqrrrpKw4YN08GDBy/rc//8889q06aNoqKiZBiGhg8f7vXnMAxDgwcP9vrjXsyECRNkGIYMw9DChQvz3G+apqpUqSLDMNS2bdtLeo7Ro0drwoQJhdpn4cKF5810uS1atEgBAQF69tln89z3+++/q2jRouratWue+7788kt17txZcXFxCgkJUUREhBo2bKhBgwZpx44dHtu2bdvW/XU3DEPBwcGqWLGi+vTpo+3bt1+211ZQS5Ys0eDBg3Xo0KFC7ffDDz/ojjvuUPny5eVyuVSkSBHVrl1bjz/+uDZu3Oixba9evTy+Bi6XS9WrV9egQYN0/Phxj+2KFi163ucsWrSoevXqddFsuc9zvm1ffvll9zZ//PFHQV5ugfTq1UsVK1a8pH3btm1b4PfdiRMnVKNGDQ0dOtS97uz3t2EYCgoKUmxsrLp166bNmze78529zfmWXr166cCBAypTpoxatWqlU6dOeTx/dna26tevr4SEBB0+fLjAr/F///ufXC6XDMPQypUr89y/b98+9erVS6VKlVJ4eLgSExP13Xff5ftYmZmZevHFF1WtWjW5XC6VLFlS7dq1c7/Ws79WL730kipWrCiXy6UaNWpo1KhReR7v7rvv1k033VTg1wIABWYCfuy9994zg4KCzNq1a5vvvPOOuWDBAnPOnDnmkCFDzISEBPOmm266rM/foEEDs2rVqubXX39tLl261NyzZ4/Xn2Pp0qVmSkqK1x/3Yj788ENTkhkREWF27949z/0LFixw39+mTZtLeo7atWsXet/09HRz6dKlZnp6+iU959/12GOPmYGBgeZPP/3kXpeTk2O2bNnSLF26tLlv3z6P9T169DAlmUlJSeaECRPMhQsXmrNnzzZffvllMyEhwSxXrpzH47dp08asVKmSuXTpUnPp0qXmokWLzHfeeceMjo424+PjzczMTJ+91vy8/vrrpiRz27ZtBd7nueeeMyWZiYmJ5rvvvmvOnz/fnDNnjvnGG2+YdevWNSWZJ0+edG/fs2dPMywszP01+Prrr827777blGTedtttHtsVKVLkvM9bpEgRs2fPnhfNl/t9HB4ebmZkZHjcd+rUKTMhIcGMjIws9Ou+mJ49e5oVKlS4pH3btGlT4PfO8OHDzejoaPPIkSPudbnv7w8//NBcunSpuWDBAvOVV14xw8LCzOjoaPPgwYPmli1b3Mdg6dKl5jvvvGNKMocMGeKxfsuWLaZpmuaMGTNMSeYbb7zh8fzPPPOMaRiGOX/+/AK/vpMnT5rNmjUz4+LiTEnmihUrPO4/fvy4WadOHbNcuXLmpEmTzDlz5pidO3c2g4KCzIULF3pse/jwYbNx48ZmXFycOXLkSHPhwoXm559/bj799NPmmjVrPLa99957TZfLZQ4bNsxcsGCBO/urr77qsd2WLVvMoKAg87vvvivwawKAgqC4g99asmSJGRgYaF533XXm8ePH89yflZVlfv7555c1Q1BQkPnQQw9d1uewSu6Hv3vvvdcMCwvLU0x1797dTExMvKQCLVdh9s3OzjZPnDhxSc/jTUePHjWrVatm1qhRwzx27Jhpmqb52muvmZLMadOmeWw7ZMgQU5KZnJyc72OdOHHCfPvttz3WtWnTxqxdu3aebceNG2dKMr/99lsvvZJLU9ji7pNPPjElmQ8++KB56tSpPPefOnXKfPvtt/MUd/kVba1atTIlmTt37rzgdrkKU9x1797dDAsLM9977z2P++bNm2dKMu+7774rsrg7ceKEWbZsWfOZZ57xWJ/7/j63aHrppZdMSeb48ePzPFbuH3Q+/fTT8z5f9+7dzdDQUPN///ufaZp//Zx+5JFHCvCq/vL666+bZcuWNUeMGJFvztxCc8mSJR6vtVatWmbTpk09tn3sscfMIkWKmL///vsFn3P9+vWmYRjmkCFDPNbfd999ZlhYmJmWluax/sYbbzSvvfbaQr0uALgYhmXCbw0ZMkSGYei9996Ty+XKc39ISIj+8Y9/uG+fOnVKw4YNU40aNeRyuRQdHa0ePXpo586dHvu1bdtWderU0YoVK9SqVSuFh4erUqVKGjp0qHu4Ue6QppMnT2rMmDHu4UmSNHjwYPf/ny13n7OHdc2fP19t27ZVyZIlFRYWpvLly6tLly46evSoe5v8hmWuX79enTt3VvHixRUaGqoGDRpo4sSJHtvkDl+cPHmynnvuOcXFxSkyMlLXXHONNm3aVLAvsqQ77rhDkjR58mT3uvT0dE2bNk333HNPvvu89NJLatasmUqUKKHIyEhdddVVGjdunEzTdG9TsWJFbdiwQYsWLXJ//XKHqOVm//jjj/X444+rbNmycrlc2rJlS55hmQcOHFB8fLxatGihEydOuB//f//7n4oUKaK77767wK+1IMLCwjRhwgT99ttvevbZZ7V+/Xq9+OKLuuuuu3TLLbe4t8vOztawYcNUp04dPfPMM/k+VlBQkPr161eg542KipIkBQcHe6z/4YcfdPXVVysiIkLh4eFq0aKFvvrqqzz7F+R75tSpU3rllVdUvXp1hYWFqVixYqpXr55GjBgh6fT39pNPPilJSkhIuOCw3VyvvPKKSpUqpbfeeivf94VhGOrXr58CAwMv+jVo3ry5JF2W4alRUVG6+eabNX78eI/148ePV8uWLVWtWrV89xs/frzq16+v0NBQlShRQjfffLN+/fXXPNtNmDBB1atXl8vlUs2aNfXRRx/l+3jZ2dl65ZVX3D+nSpcurd69e2v//v2X9LpmzZqlXbt2Ffh90LhxY0nS3r17L+n5Ro4cqRIlSqhnz57KyMhQz5493T8/C2rz5s168cUXNXr0aEVGRua7zYwZM1S9enUlJia61wUFBal79+5avny5du3aJUk6evSoPvjgA916662qVKnSBZ935syZMk1TvXv39ljfu3dvHTt2TN98843H+rvvvlvz5s3T77//XuDXBgAXQ3EHv5STk6P58+erUaNGio+PL9A+Dz30kJ5++mlde+21mjVrlv71r3/pm2++UYsWLXTgwAGPbVNTU3XXXXepe/fumjVrlpKSkjRw4EBNmjRJknTDDTdo6dKlkqSuXbtq6dKl7tsF9ccff+iGG25QSEiIxo8fr2+++UZDhw5VkSJFlJ2dfd79Nm3apBYtWmjDhg0aOXKkpk+frlq1aqlXr14aNmxYnu2fffZZbd++XR988IHee+89bd68WZ06dVJOTk6BckZGRqpr164eH3onT56sgIAA3X777ed9bQ888ID++9//avr06brlllv0yCOP6F//+pd7mxkzZqhSpUpq2LCh++s3Y8YMj8cZOHCgduzYobFjx+qLL75QdHR0nucqVaqUpkyZohUrVujpp5+WdPoD3a233qry5ctr7NixBXqdhZGYmKgnnnhCI0aM0D/+8Q+VLFkyz3k5K1eu1KFDh9SpU6dLeo6TJ0/q5MmTOnr0qJYvX66XX35ZlSpVUosWLdzbLFq0SO3bt1d6errGjRunyZMnKyIiQp06ddLUqVPd2xX0e2bYsGEaPHiw7rjjDn311VeaOnWq+vTp4z6/7t5779UjjzwiSZo+fbr7uF111VX5vobdu3frf//7n6699lqFhoZ
"text/plain": [
"<Figure size 1000x800 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"CPU times: user 6.04 s, sys: 889 ms, total: 6.93 s\n",
"Wall time: 6.3 s\n"
]
}
],
"source": [
"%%time\n",
"# 🤖 TRAIN XGBOOST MODEL ON GPU (RTX 4060)\n",
"print(\"=\"*70)\n",
"print(\"MODEL TRAINING - GPU ACCELERATED\")\n",
"print(\"=\"*70)\n",
"\n",
"from xgboost import XGBClassifier\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.preprocessing import LabelEncoder\n",
"from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# Encode labels to ensure they are 0, 1, 2, ... n-1\n",
"print(\"\\n[1] Encoding labels...\")\n",
"label_encoder = LabelEncoder()\n",
"labels_encoded = label_encoder.fit_transform(labels)\n",
"print(f\"✅ Original classes: {label_encoder.classes_}\")\n",
"print(f\" Encoded as: {np.unique(labels_encoded)}\")\n",
"\n",
"# Split data\n",
"print(\"\\n[2] Splitting data (80% train, 20% test)...\")\n",
"X_train, X_test, y_train, y_test = train_test_split(\n",
" features, labels_encoded, test_size=0.2, random_state=42, stratify=labels_encoded\n",
")\n",
"print(f\"✅ Training samples: {len(X_train)}\")\n",
"print(f\" Testing samples: {len(X_test)}\")\n",
"\n",
"# Train XGBoost on GPU\n",
"print(\"\\n[3] Training XGBoost classifier on RTX 4060 GPU...\")\n",
"print(\" GPU Settings: device='cuda:0'\")\n",
"\n",
"xgb_model = XGBClassifier(\n",
" n_estimators=100,\n",
" max_depth=20,\n",
" learning_rate=0.1,\n",
" device='cuda:0', # Use GPU (updated from deprecated gpu_id)\n",
" tree_method='hist', # Use hist with device for GPU training\n",
" random_state=42,\n",
" eval_metric='mlogloss', # Multi-class log loss\n",
" verbosity=1 # Show GPU training progress\n",
")\n",
"\n",
"xgb_model.fit(X_train, y_train)\n",
"print(f\"✅ Model trained on GPU\")\n",
"\n",
"# Evaluate\n",
"print(\"\\n[4] Evaluating model...\")\n",
"train_score = xgb_model.score(X_train, y_train)\n",
"test_score = xgb_model.score(X_test, y_test)\n",
"print(f\"✅ Training accuracy: {train_score:.4f}\")\n",
"print(f\" Testing accuracy: {test_score:.4f}\")\n",
"\n",
"# Classification report\n",
"print(\"\\n[5] Classification Report:\")\n",
"y_pred = xgb_model.predict(X_test)\n",
"print(classification_report(y_test, y_pred, target_names=[str(c) for c in label_encoder.classes_]))\n",
"\n",
"# Confusion matrix\n",
"print(\"\\n[6] Confusion Matrix:\")\n",
"fig, ax = plt.subplots(figsize=(10, 8))\n",
"cm = confusion_matrix(y_test, y_pred)\n",
"disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=label_encoder.classes_)\n",
"disp.plot(ax=ax, cmap='Blues', values_format='d')\n",
"plt.title('Confusion Matrix - XGBoost GPU Model (RTX 4060)')\n",
"plt.tight_layout()\n",
"plt.show()\n",
"\n",
"print(\"=\"*70)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "33dd516d-9824-499e-96b9-5cd9224c194c",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"SAVING MODEL & CLEANUP\n",
"======================================================================\n",
"\n",
"[1] Saving model to: model_train/model_xgboost_gpu_20251212_125754.joblib\n",
"✅ Model and label encoder saved\n",
"✅ Model info saved to: model_train/model_xgboost_gpu_20251212_125754_info.json\n",
"\n",
"[2] Cleanup complete\n",
"======================================================================\n",
"\n",
"======================================================================\n",
"🎉 TRAINING COMPLETE!\n",
"CPU times: user 104 ms, sys: 3.86 ms, total: 108 ms\n",
"Wall time: 14.3 ms\n"
]
}
],
"source": [
"%%time\n",
"# 💾 SAVE MODEL AND CLEANUP\n",
"print(\"=\"*70)\n",
"print(\"SAVING MODEL & CLEANUP\")\n",
"print(\"=\"*70)\n",
"\n",
"import joblib\n",
"from datetime import datetime\n",
"\n",
"# Save model and label encoder\n",
"model_filename = f\"model_train/model_xgboost_gpu_{datetime.now().strftime('%Y%m%d_%H%M%S')}.joblib\"\n",
"print(f\"\\n[1] Saving model to: {model_filename}\")\n",
"joblib.dump({'model': xgb_model, 'label_encoder': label_encoder}, model_filename)\n",
"print(f\"✅ Model and label encoder saved\")\n",
"\n",
"# Save model info\n",
"info = {\n",
" \"timestamp\": datetime.now().isoformat(),\n",
" \"data_source\": \"Microsoft Planetary Computer STAC\",\n",
" \"collections\": [\"sentinel-2-l2a\", \"sentinel-1-rtc\"],\n",
" \"features\": [\"NDVI_mean\", \"VH_dB_mean\", \"VV_dB_mean\"],\n",
" \"training_samples\": len(X_train),\n",
" \"testing_samples\": len(X_test),\n",
" \"train_accuracy\": float(train_score),\n",
" \"test_accuracy\": float(test_score),\n",
" \"model_type\": \"XGBClassifier\",\n",
" \"device\": \"cuda:0\",\n",
" \"gpu_device\": \"RTX 4060\",\n",
" \"tree_method\": \"hist\",\n",
" \"n_estimators\": 100,\n",
" \"max_depth\": 20,\n",
" \"learning_rate\": 0.1\n",
"}\n",
"\n",
"import json\n",
"info_filename = model_filename.replace('.joblib', '_info.json')\n",
"with open(info_filename, 'w') as f:\n",
" json.dump(info, f, indent=2)\n",
"print(f\"✅ Model info saved to: {info_filename}\")\n",
"\n",
"# No cleanup needed (Dask removed)\n",
"print(\"\\n[2] Cleanup complete\")\n",
"\n",
"print(\"=\"*70)\n",
"\n",
"print(\"\\n\" + \"=\"*70)\n",
"\n",
"print(\"🎉 TRAINING COMPLETE!\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "env_01",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.18"
}
},
"nbformat": 4,
"nbformat_minor": 5
}