Spaces:
Sleeping
Sleeping
merge into single app
Browse files- .gitignore +1 -0
- Esri_XML_to_wayback_csv.ipynb +319 -0
- app.py +267 -496
- functions.py +358 -0
- wayback.csv +176 -0
- wayback.parquet +3 -0
.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
*.pyc
|
Esri_XML_to_wayback_csv.ipynb
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": 8,
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"outputs": [],
|
| 8 |
+
"source": [
|
| 9 |
+
"import xml.etree.ElementTree as ET\n",
|
| 10 |
+
"import requests\n",
|
| 11 |
+
"import csv"
|
| 12 |
+
]
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"cell_type": "code",
|
| 16 |
+
"execution_count": 9,
|
| 17 |
+
"metadata": {},
|
| 18 |
+
"outputs": [],
|
| 19 |
+
"source": [
|
| 20 |
+
"xml_url = \"https://wayback.maptiles.arcgis.com/arcgis/rest/services/world_imagery/mapserver/wmts/1.0.0/wmtscapabilities.xml\""
|
| 21 |
+
]
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"cell_type": "code",
|
| 25 |
+
"execution_count": 10,
|
| 26 |
+
"metadata": {},
|
| 27 |
+
"outputs": [],
|
| 28 |
+
"source": [
|
| 29 |
+
"# parse the xml\n",
|
| 30 |
+
"xml = requests.get(xml_url).text\n",
|
| 31 |
+
"root = ET.fromstring(xml)"
|
| 32 |
+
]
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"cell_type": "code",
|
| 36 |
+
"execution_count": 12,
|
| 37 |
+
"metadata": {},
|
| 38 |
+
"outputs": [],
|
| 39 |
+
"source": [
|
| 40 |
+
"# Namespace definitions\n",
|
| 41 |
+
"namespaces = {\n",
|
| 42 |
+
" 'ows': 'https://www.opengis.net/ows/1.1',\n",
|
| 43 |
+
" '': 'https://www.opengis.net/wmts/1.0' # Default namespace\n",
|
| 44 |
+
"}\n",
|
| 45 |
+
"\n",
|
| 46 |
+
"# Open CSV file for writing\n",
|
| 47 |
+
"with open('wayback.csv', 'w', newline='') as csv_file:\n",
|
| 48 |
+
" writer = csv.writer(csv_file)\n",
|
| 49 |
+
"\n",
|
| 50 |
+
" # Write header row\n",
|
| 51 |
+
" writer.writerow([\n",
|
| 52 |
+
" 'Title', \n",
|
| 53 |
+
" 'Identifier', \n",
|
| 54 |
+
" 'LowerCorner', \n",
|
| 55 |
+
" 'UpperCorner', \n",
|
| 56 |
+
" 'Format', \n",
|
| 57 |
+
" 'TileMatrixSetLinks', \n",
|
| 58 |
+
" 'ResourceURL_Template'\n",
|
| 59 |
+
" ])\n",
|
| 60 |
+
"\n",
|
| 61 |
+
" # Extract and write data\n",
|
| 62 |
+
" for layer in root.findall('.//Layer', namespaces):\n",
|
| 63 |
+
" title = layer.find('ows:Title', namespaces).text\n",
|
| 64 |
+
" identifier = layer.find('ows:Identifier', namespaces).text\n",
|
| 65 |
+
"\n",
|
| 66 |
+
" bounding_box = layer.find('ows:BoundingBox/ows:LowerCorner', namespaces)\n",
|
| 67 |
+
" lower_corner = bounding_box.text if bounding_box is not None else ''\n",
|
| 68 |
+
"\n",
|
| 69 |
+
" bounding_box = layer.find('ows:BoundingBox/ows:UpperCorner', namespaces)\n",
|
| 70 |
+
" upper_corner = bounding_box.text if bounding_box is not None else ''\n",
|
| 71 |
+
"\n",
|
| 72 |
+
" fmt = layer.find('Format', namespaces).text if layer.find('Format', namespaces) else ''\n",
|
| 73 |
+
"\n",
|
| 74 |
+
" tile_matrix_links = [tms.text for tms in layer.findall('TileMatrixSetLink/TileMatrixSet', namespaces)]\n",
|
| 75 |
+
" tile_matrix_set_links = ', '.join(tile_matrix_links)\n",
|
| 76 |
+
"\n",
|
| 77 |
+
" resource_url = layer.find('ResourceURL', namespaces)\n",
|
| 78 |
+
" resource_url_template = resource_url.get('template') if resource_url is not None else ''\n",
|
| 79 |
+
"\n",
|
| 80 |
+
" writer.writerow([\n",
|
| 81 |
+
" title,\n",
|
| 82 |
+
" identifier,\n",
|
| 83 |
+
" lower_corner,\n",
|
| 84 |
+
" upper_corner,\n",
|
| 85 |
+
" fmt,\n",
|
| 86 |
+
" tile_matrix_set_links,\n",
|
| 87 |
+
" resource_url_template\n",
|
| 88 |
+
" ])"
|
| 89 |
+
]
|
| 90 |
+
},
|
| 91 |
+
{
|
| 92 |
+
"cell_type": "markdown",
|
| 93 |
+
"metadata": {},
|
| 94 |
+
"source": [
|
| 95 |
+
"# Parse dates"
|
| 96 |
+
]
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"cell_type": "code",
|
| 100 |
+
"execution_count": 1,
|
| 101 |
+
"metadata": {},
|
| 102 |
+
"outputs": [
|
| 103 |
+
{
|
| 104 |
+
"data": {
|
| 105 |
+
"text/html": [
|
| 106 |
+
"<div>\n",
|
| 107 |
+
"<style scoped>\n",
|
| 108 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
| 109 |
+
" vertical-align: middle;\n",
|
| 110 |
+
" }\n",
|
| 111 |
+
"\n",
|
| 112 |
+
" .dataframe tbody tr th {\n",
|
| 113 |
+
" vertical-align: top;\n",
|
| 114 |
+
" }\n",
|
| 115 |
+
"\n",
|
| 116 |
+
" .dataframe thead th {\n",
|
| 117 |
+
" text-align: right;\n",
|
| 118 |
+
" }\n",
|
| 119 |
+
"</style>\n",
|
| 120 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 121 |
+
" <thead>\n",
|
| 122 |
+
" <tr style=\"text-align: right;\">\n",
|
| 123 |
+
" <th></th>\n",
|
| 124 |
+
" <th>Title</th>\n",
|
| 125 |
+
" <th>Identifier</th>\n",
|
| 126 |
+
" <th>LowerCorner</th>\n",
|
| 127 |
+
" <th>UpperCorner</th>\n",
|
| 128 |
+
" <th>Format</th>\n",
|
| 129 |
+
" <th>TileMatrixSetLinks</th>\n",
|
| 130 |
+
" <th>ResourceURL_Template</th>\n",
|
| 131 |
+
" </tr>\n",
|
| 132 |
+
" </thead>\n",
|
| 133 |
+
" <tbody>\n",
|
| 134 |
+
" <tr>\n",
|
| 135 |
+
" <th>0</th>\n",
|
| 136 |
+
" <td>World Imagery (Wayback 2024-10-10)</td>\n",
|
| 137 |
+
" <td>WB_2024_R11</td>\n",
|
| 138 |
+
" <td>-2.003750722959434E7 -2.003750722959434E7</td>\n",
|
| 139 |
+
" <td>2.003750722959434E7 2.003750722959434E7</td>\n",
|
| 140 |
+
" <td>NaN</td>\n",
|
| 141 |
+
" <td>default028mm, GoogleMapsCompatible</td>\n",
|
| 142 |
+
" <td>https://wayback.maptiles.arcgis.com/arcgis/res...</td>\n",
|
| 143 |
+
" </tr>\n",
|
| 144 |
+
" <tr>\n",
|
| 145 |
+
" <th>1</th>\n",
|
| 146 |
+
" <td>World Imagery (Wayback 2024-09-19)</td>\n",
|
| 147 |
+
" <td>WB_2024_R10</td>\n",
|
| 148 |
+
" <td>-2.003750722959434E7 -2.003750722959434E7</td>\n",
|
| 149 |
+
" <td>2.003750722959434E7 2.003750722959434E7</td>\n",
|
| 150 |
+
" <td>NaN</td>\n",
|
| 151 |
+
" <td>default028mm, GoogleMapsCompatible</td>\n",
|
| 152 |
+
" <td>https://wayback.maptiles.arcgis.com/arcgis/res...</td>\n",
|
| 153 |
+
" </tr>\n",
|
| 154 |
+
" </tbody>\n",
|
| 155 |
+
"</table>\n",
|
| 156 |
+
"</div>"
|
| 157 |
+
],
|
| 158 |
+
"text/plain": [
|
| 159 |
+
" Title Identifier \\\n",
|
| 160 |
+
"0 World Imagery (Wayback 2024-10-10) WB_2024_R11 \n",
|
| 161 |
+
"1 World Imagery (Wayback 2024-09-19) WB_2024_R10 \n",
|
| 162 |
+
"\n",
|
| 163 |
+
" LowerCorner \\\n",
|
| 164 |
+
"0 -2.003750722959434E7 -2.003750722959434E7 \n",
|
| 165 |
+
"1 -2.003750722959434E7 -2.003750722959434E7 \n",
|
| 166 |
+
"\n",
|
| 167 |
+
" UpperCorner Format \\\n",
|
| 168 |
+
"0 2.003750722959434E7 2.003750722959434E7 NaN \n",
|
| 169 |
+
"1 2.003750722959434E7 2.003750722959434E7 NaN \n",
|
| 170 |
+
"\n",
|
| 171 |
+
" TileMatrixSetLinks \\\n",
|
| 172 |
+
"0 default028mm, GoogleMapsCompatible \n",
|
| 173 |
+
"1 default028mm, GoogleMapsCompatible \n",
|
| 174 |
+
"\n",
|
| 175 |
+
" ResourceURL_Template \n",
|
| 176 |
+
"0 https://wayback.maptiles.arcgis.com/arcgis/res... \n",
|
| 177 |
+
"1 https://wayback.maptiles.arcgis.com/arcgis/res... "
|
| 178 |
+
]
|
| 179 |
+
},
|
| 180 |
+
"execution_count": 1,
|
| 181 |
+
"metadata": {},
|
| 182 |
+
"output_type": "execute_result"
|
| 183 |
+
}
|
| 184 |
+
],
|
| 185 |
+
"source": [
|
| 186 |
+
"import pandas as pd\n",
|
| 187 |
+
"\n",
|
| 188 |
+
"df = pd.read_csv('wayback.csv')\n",
|
| 189 |
+
"df.head(2)"
|
| 190 |
+
]
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"cell_type": "code",
|
| 194 |
+
"execution_count": 3,
|
| 195 |
+
"metadata": {},
|
| 196 |
+
"outputs": [
|
| 197 |
+
{
|
| 198 |
+
"data": {
|
| 199 |
+
"text/html": [
|
| 200 |
+
"<div>\n",
|
| 201 |
+
"<style scoped>\n",
|
| 202 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
| 203 |
+
" vertical-align: middle;\n",
|
| 204 |
+
" }\n",
|
| 205 |
+
"\n",
|
| 206 |
+
" .dataframe tbody tr th {\n",
|
| 207 |
+
" vertical-align: top;\n",
|
| 208 |
+
" }\n",
|
| 209 |
+
"\n",
|
| 210 |
+
" .dataframe thead th {\n",
|
| 211 |
+
" text-align: right;\n",
|
| 212 |
+
" }\n",
|
| 213 |
+
"</style>\n",
|
| 214 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 215 |
+
" <thead>\n",
|
| 216 |
+
" <tr style=\"text-align: right;\">\n",
|
| 217 |
+
" <th></th>\n",
|
| 218 |
+
" <th>Title</th>\n",
|
| 219 |
+
" <th>Identifier</th>\n",
|
| 220 |
+
" <th>LowerCorner</th>\n",
|
| 221 |
+
" <th>UpperCorner</th>\n",
|
| 222 |
+
" <th>Format</th>\n",
|
| 223 |
+
" <th>TileMatrixSetLinks</th>\n",
|
| 224 |
+
" <th>ResourceURL_Template</th>\n",
|
| 225 |
+
" <th>date</th>\n",
|
| 226 |
+
" </tr>\n",
|
| 227 |
+
" </thead>\n",
|
| 228 |
+
" <tbody>\n",
|
| 229 |
+
" <tr>\n",
|
| 230 |
+
" <th>0</th>\n",
|
| 231 |
+
" <td>World Imagery (Wayback 2024-10-10)</td>\n",
|
| 232 |
+
" <td>WB_2024_R11</td>\n",
|
| 233 |
+
" <td>-2.003750722959434E7 -2.003750722959434E7</td>\n",
|
| 234 |
+
" <td>2.003750722959434E7 2.003750722959434E7</td>\n",
|
| 235 |
+
" <td>NaN</td>\n",
|
| 236 |
+
" <td>default028mm, GoogleMapsCompatible</td>\n",
|
| 237 |
+
" <td>https://wayback.maptiles.arcgis.com/arcgis/res...</td>\n",
|
| 238 |
+
" <td>2024-10-10</td>\n",
|
| 239 |
+
" </tr>\n",
|
| 240 |
+
" <tr>\n",
|
| 241 |
+
" <th>1</th>\n",
|
| 242 |
+
" <td>World Imagery (Wayback 2024-09-19)</td>\n",
|
| 243 |
+
" <td>WB_2024_R10</td>\n",
|
| 244 |
+
" <td>-2.003750722959434E7 -2.003750722959434E7</td>\n",
|
| 245 |
+
" <td>2.003750722959434E7 2.003750722959434E7</td>\n",
|
| 246 |
+
" <td>NaN</td>\n",
|
| 247 |
+
" <td>default028mm, GoogleMapsCompatible</td>\n",
|
| 248 |
+
" <td>https://wayback.maptiles.arcgis.com/arcgis/res...</td>\n",
|
| 249 |
+
" <td>2024-09-19</td>\n",
|
| 250 |
+
" </tr>\n",
|
| 251 |
+
" </tbody>\n",
|
| 252 |
+
"</table>\n",
|
| 253 |
+
"</div>"
|
| 254 |
+
],
|
| 255 |
+
"text/plain": [
|
| 256 |
+
" Title Identifier \\\n",
|
| 257 |
+
"0 World Imagery (Wayback 2024-10-10) WB_2024_R11 \n",
|
| 258 |
+
"1 World Imagery (Wayback 2024-09-19) WB_2024_R10 \n",
|
| 259 |
+
"\n",
|
| 260 |
+
" LowerCorner \\\n",
|
| 261 |
+
"0 -2.003750722959434E7 -2.003750722959434E7 \n",
|
| 262 |
+
"1 -2.003750722959434E7 -2.003750722959434E7 \n",
|
| 263 |
+
"\n",
|
| 264 |
+
" UpperCorner Format \\\n",
|
| 265 |
+
"0 2.003750722959434E7 2.003750722959434E7 NaN \n",
|
| 266 |
+
"1 2.003750722959434E7 2.003750722959434E7 NaN \n",
|
| 267 |
+
"\n",
|
| 268 |
+
" TileMatrixSetLinks \\\n",
|
| 269 |
+
"0 default028mm, GoogleMapsCompatible \n",
|
| 270 |
+
"1 default028mm, GoogleMapsCompatible \n",
|
| 271 |
+
"\n",
|
| 272 |
+
" ResourceURL_Template date \n",
|
| 273 |
+
"0 https://wayback.maptiles.arcgis.com/arcgis/res... 2024-10-10 \n",
|
| 274 |
+
"1 https://wayback.maptiles.arcgis.com/arcgis/res... 2024-09-19 "
|
| 275 |
+
]
|
| 276 |
+
},
|
| 277 |
+
"execution_count": 3,
|
| 278 |
+
"metadata": {},
|
| 279 |
+
"output_type": "execute_result"
|
| 280 |
+
}
|
| 281 |
+
],
|
| 282 |
+
"source": [
|
| 283 |
+
"df['date'] = df['Title'].str.extract(r'(\\d{4}-\\d{2}-\\d{2})')\n",
|
| 284 |
+
"df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')\n",
|
| 285 |
+
"df.head(2)"
|
| 286 |
+
]
|
| 287 |
+
},
|
| 288 |
+
{
|
| 289 |
+
"cell_type": "code",
|
| 290 |
+
"execution_count": 4,
|
| 291 |
+
"metadata": {},
|
| 292 |
+
"outputs": [],
|
| 293 |
+
"source": [
|
| 294 |
+
"df.to_parquet('wayback.parquet', index=False)"
|
| 295 |
+
]
|
| 296 |
+
}
|
| 297 |
+
],
|
| 298 |
+
"metadata": {
|
| 299 |
+
"kernelspec": {
|
| 300 |
+
"display_name": "zeel_py310",
|
| 301 |
+
"language": "python",
|
| 302 |
+
"name": "python3"
|
| 303 |
+
},
|
| 304 |
+
"language_info": {
|
| 305 |
+
"codemirror_mode": {
|
| 306 |
+
"name": "ipython",
|
| 307 |
+
"version": 3
|
| 308 |
+
},
|
| 309 |
+
"file_extension": ".py",
|
| 310 |
+
"mimetype": "text/x-python",
|
| 311 |
+
"name": "python",
|
| 312 |
+
"nbconvert_exporter": "python",
|
| 313 |
+
"pygments_lexer": "ipython3",
|
| 314 |
+
"version": "3.10.15"
|
| 315 |
+
}
|
| 316 |
+
},
|
| 317 |
+
"nbformat": 4,
|
| 318 |
+
"nbformat_minor": 2
|
| 319 |
+
}
|
app.py
CHANGED
|
@@ -1,41 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
from datetime import datetime
|
| 3 |
import ee
|
| 4 |
import json
|
| 5 |
-
import geemap
|
| 6 |
import numpy as np
|
| 7 |
import geemap.foliumap as gee_folium
|
| 8 |
import leafmap.foliumap as leaf_folium
|
| 9 |
import streamlit as st
|
| 10 |
import pandas as pd
|
| 11 |
-
import geopandas as gpd
|
| 12 |
-
from shapely.ops import transform
|
| 13 |
-
from functools import reduce
|
| 14 |
import plotly.express as px
|
| 15 |
import branca.colormap as cm
|
| 16 |
-
import folium
|
| 17 |
-
import pyproj
|
| 18 |
-
from io import StringIO, BytesIO
|
| 19 |
-
import requests
|
| 20 |
-
import kml2geojson
|
| 21 |
|
| 22 |
-
|
| 23 |
-
print(folium.__version__)
|
| 24 |
-
print(geemap.Report())
|
| 25 |
|
| 26 |
st.set_page_config(layout="wide")
|
| 27 |
-
m = st.markdown(
|
| 28 |
-
"""
|
| 29 |
-
<style>
|
| 30 |
-
div.stButton > button:first-child {
|
| 31 |
-
background-color: #006400;
|
| 32 |
-
color:#ffffff;
|
| 33 |
-
}
|
| 34 |
-
</style>""",
|
| 35 |
-
unsafe_allow_html=True,
|
| 36 |
-
)
|
| 37 |
|
| 38 |
-
#
|
|
|
|
|
|
|
| 39 |
st.write(
|
| 40 |
f"""
|
| 41 |
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
@@ -46,42 +31,57 @@ st.write(
|
|
| 46 |
unsafe_allow_html=True,
|
| 47 |
)
|
| 48 |
|
| 49 |
-
|
| 50 |
# Title
|
| 51 |
-
#
|
|
|
|
| 52 |
st.markdown(
|
| 53 |
f"""
|
| 54 |
-
<h1 style="text-align: center;">
|
| 55 |
""",
|
| 56 |
unsafe_allow_html=True,
|
| 57 |
)
|
| 58 |
|
| 59 |
############################################
|
| 60 |
-
#
|
| 61 |
############################################
|
| 62 |
-
st.write("<h2><div style='text-align: center;'>User Inputs</div></h2>", unsafe_allow_html=True)
|
| 63 |
|
| 64 |
# Input: GeoJSON/KML file
|
| 65 |
file_url = st.query_params.get("file_url", None)
|
| 66 |
if file_url is None:
|
| 67 |
-
file_url = st.file_uploader("Upload KML/GeoJSON file", type=["geojson", "kml"
|
| 68 |
|
| 69 |
-
def show_credits():
|
| 70 |
-
# Add credits
|
| 71 |
-
st.write(
|
| 72 |
-
"""
|
| 73 |
-
<div style="display: flex; justify-content: center; align-items: center; margin-top: 20px;">
|
| 74 |
-
<p style="text-align: left;">This tool is developed by <a href="https://sustainability-lab.github.io/">Sustainability Lab</a>, <a href="https://www.iitgn.ac.in/">IIT Gandhinagar</a> and supported by <a href="https://forests.gujarat.gov.in/">Gujarat Forest Department</a></p>""",
|
| 75 |
-
unsafe_allow_html=True,
|
| 76 |
-
)
|
| 77 |
-
|
| 78 |
if file_url is None:
|
| 79 |
st.warning(
|
| 80 |
-
|
| 81 |
)
|
| 82 |
-
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
with st.expander("Advanced Settings"):
|
| 86 |
st.write("Select the vegetation indices to calculate:")
|
| 87 |
all_veg_indices = ["NDVI", "EVI", "EVI2"]
|
|
@@ -102,384 +102,36 @@ with st.expander("Advanced Settings"):
|
|
| 102 |
value = col.number_input(f"{name}", value=default)
|
| 103 |
evi_vars[name] = value
|
| 104 |
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
elif file_url.startswith("https://drive.google.com/open?id="):
|
| 117 |
-
ID = file_url.replace("https://drive.google.com/open?id=", "")
|
| 118 |
-
file_url = f"https://drive.google.com/uc?id={ID}"
|
| 119 |
-
|
| 120 |
-
response = requests.get(file_url)
|
| 121 |
-
bytes_data = BytesIO(response.content)
|
| 122 |
-
string_data = response.text
|
| 123 |
-
else:
|
| 124 |
-
bytes_data = BytesIO(file_url.getvalue())
|
| 125 |
-
string_data = file_url.getvalue().decode("utf-8")
|
| 126 |
-
|
| 127 |
-
if string_data.startswith("<?xml"):
|
| 128 |
-
geojson = kml2geojson.convert(bytes_data)
|
| 129 |
-
features = geojson[0]["features"]
|
| 130 |
-
epsg = 4326
|
| 131 |
-
input_gdf = gpd.GeoDataFrame.from_features(features, crs=f"EPSG:{epsg}")
|
| 132 |
-
else:
|
| 133 |
-
input_gdf = gpd.read_file(bytes_data)
|
| 134 |
-
|
| 135 |
-
return input_gdf
|
| 136 |
-
|
| 137 |
-
def find_best_epsg(geometry):
|
| 138 |
-
if geometry.geom_type == 'Polygon':
|
| 139 |
-
centroid = geometry.centroid
|
| 140 |
-
else:
|
| 141 |
-
st.error("Geometry is not Polygon !!!")
|
| 142 |
-
st.stop()
|
| 143 |
-
common_epsg_codes = [7756, #Andhra Pradesh
|
| 144 |
-
7757, #Arunachal Pradesh
|
| 145 |
-
7758, #Assam
|
| 146 |
-
7759, #Bihar
|
| 147 |
-
7760, #Delhi
|
| 148 |
-
7761, #Gujarat
|
| 149 |
-
7762, #Haryana
|
| 150 |
-
7763, #HimachalPradesh
|
| 151 |
-
7764, #JammuAndKashmir
|
| 152 |
-
7765, #Jharkhand
|
| 153 |
-
7766, #MadhyaPradesh
|
| 154 |
-
7767, #Maharastra
|
| 155 |
-
7768, #Manipur
|
| 156 |
-
7769, #Meghalaya
|
| 157 |
-
7770, #Nagaland
|
| 158 |
-
7772, #Orissa
|
| 159 |
-
7773, #Punjab
|
| 160 |
-
7774, #Rajasthan
|
| 161 |
-
7775, #UttarPradesh
|
| 162 |
-
7776, #Uttaranchal
|
| 163 |
-
7777, #A&N
|
| 164 |
-
7778, #Chattisgarh
|
| 165 |
-
7779, #Goa
|
| 166 |
-
7780, #Karnataka
|
| 167 |
-
7781, #Kerala
|
| 168 |
-
7782, #Lakshadweep
|
| 169 |
-
7783, #Mizoram
|
| 170 |
-
7784, #Sikkim
|
| 171 |
-
7785, #TamilNadu
|
| 172 |
-
7786, #Tripura
|
| 173 |
-
7787, #WestBengal
|
| 174 |
-
7771, #NE India
|
| 175 |
-
7755, #India
|
| 176 |
-
]
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
for epsg in common_epsg_codes:
|
| 180 |
-
crs = pyproj.CRS.from_epsg(epsg)
|
| 181 |
-
area_of_use = crs.area_of_use.bounds # Get the bounding box of the area of use
|
| 182 |
-
|
| 183 |
-
#check if centroid of polygon lies in teh bounds of the crs
|
| 184 |
-
if (area_of_use[0] <= centroid.x <= area_of_use[2]) and (area_of_use[1] <= centroid.y <= area_of_use[3]):
|
| 185 |
-
return epsg # Return the best suitable EPSG code
|
| 186 |
-
|
| 187 |
-
def daterange_str_to_dates(daterange_str):
|
| 188 |
-
start_date, end_date = daterange_str.split("-")
|
| 189 |
-
start_date = pd.to_datetime(start_date)
|
| 190 |
-
end_date = pd.to_datetime(end_date)
|
| 191 |
-
return start_date, end_date
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
def daterange_dates_to_str(start_date, end_date):
|
| 195 |
-
return f"{start_date.strftime('%Y/%m/%d')}-{end_date.strftime('%Y/%m/%d')}"
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
def daterange_str_to_year(daterange_str):
|
| 199 |
-
start_date, _ = daterange_str.split("-")
|
| 200 |
-
year = pd.to_datetime(start_date).year
|
| 201 |
-
return year
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
def shape_3d_to_2d(shape):
|
| 205 |
-
if shape.has_z:
|
| 206 |
-
return transform(lambda x, y, z: (x, y), shape)
|
| 207 |
-
else:
|
| 208 |
-
return shape
|
| 209 |
-
|
| 210 |
-
def preprocess_gdf(gdf):
|
| 211 |
-
gdf["geometry"] = gdf["geometry"].apply(shape_3d_to_2d)
|
| 212 |
-
gdf["geometry"] = gdf.buffer(0) # Fixes some invalid geometries
|
| 213 |
-
return gdf
|
| 214 |
-
|
| 215 |
-
def to_best_crs(gdf):
|
| 216 |
-
best_epsg_code = find_best_epsg(gdf["geometry"].iloc[0])
|
| 217 |
-
gdf = gdf.to_crs(epsg=best_epsg_code)
|
| 218 |
-
return gdf
|
| 219 |
-
|
| 220 |
-
def is_valid_polygon(geometry_gdf):
|
| 221 |
-
geometry = geometry_gdf.geometry.item()
|
| 222 |
-
return (geometry.type == "Polygon") and (not geometry.is_empty)
|
| 223 |
-
|
| 224 |
-
def add_geometry_to_maps(map_list, opacity=0.0):
|
| 225 |
-
for m in map_list:
|
| 226 |
-
m.add_gdf(
|
| 227 |
-
buffer_geometry_gdf,
|
| 228 |
-
layer_name="Geometry Buffer",
|
| 229 |
-
style_function=lambda x: {"color": "red", "fillOpacity": opacity, "fillColor": "red"},
|
| 230 |
-
)
|
| 231 |
-
m.add_gdf(
|
| 232 |
-
geometry_gdf,
|
| 233 |
-
layer_name="Geometry",
|
| 234 |
-
style_function=lambda x: {"color": "blue", "fillOpacity": opacity, "fillColor": "blue"},
|
| 235 |
-
)
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
def get_dem_slope_maps(buffer_ee_geometry):
|
| 239 |
-
# Create the map for DEM
|
| 240 |
-
dem_map = gee_folium.Map(controls={'scale':'bottomleft'})
|
| 241 |
-
dem_map.add_tile_layer(
|
| 242 |
-
wayback_mapping[latest_date], name=f"Esri Wayback - {latest_date.replace('-', '/')}", attribution="Esri"
|
| 243 |
-
)
|
| 244 |
-
|
| 245 |
-
dem_layer = ee.Image("USGS/SRTMGL1_003")
|
| 246 |
-
# Set the target resolution to 10 meters
|
| 247 |
-
target_resolution = 10
|
| 248 |
-
dem_layer = (
|
| 249 |
-
dem_layer.resample("bilinear").reproject(crs="EPSG:4326", scale=target_resolution).clip(buffer_ee_geometry)
|
| 250 |
-
)
|
| 251 |
-
|
| 252 |
-
# Generate contour lines using elevation thresholds
|
| 253 |
-
terrain = ee.Algorithms.Terrain(dem_layer)
|
| 254 |
-
contour_interval = 1
|
| 255 |
-
contours = (
|
| 256 |
-
terrain.select("elevation").subtract(terrain.select("elevation").mod(contour_interval)).rename("contours")
|
| 257 |
-
)
|
| 258 |
-
|
| 259 |
-
# Calculate the minimum and maximum values
|
| 260 |
-
stats = contours.reduceRegion(reducer=ee.Reducer.minMax(), scale=10, maxPixels=1e13)
|
| 261 |
-
max_value = stats.get("contours_max").getInfo()
|
| 262 |
-
min_value = stats.get("contours_min").getInfo()
|
| 263 |
-
vis_params = {"min": min_value, "max": max_value, "palette": ["blue", "green", "yellow", "red"]}
|
| 264 |
-
dem_map.addLayer(contours, vis_params, "Contours")
|
| 265 |
-
# Create a colormap
|
| 266 |
-
cmap = cm.LinearColormap(colors=vis_params["palette"], vmin=vis_params["min"], vmax=vis_params["max"])
|
| 267 |
-
tick_size = int((max_value-min_value)/4)
|
| 268 |
-
dem_map.add_legend(title="Elevation (m)",
|
| 269 |
-
legend_dict={'{}-{} m'.format(min_value, min_value+tick_size): '#0000FF',
|
| 270 |
-
'{}-{} m'.format(min_value+tick_size, min_value+2*tick_size): '#00FF00',
|
| 271 |
-
'{}-{} m'.format(min_value+2*tick_size, min_value+3*tick_size): '#FFFF00',
|
| 272 |
-
'{}-{} m'.format(min_value+3*tick_size, max_value): '#FF0000'},
|
| 273 |
-
position='bottomright', draggable=False)
|
| 274 |
-
|
| 275 |
-
# Create the map for Slope
|
| 276 |
-
slope_map = gee_folium.Map(controls={'scale':'bottomleft'})
|
| 277 |
-
slope_map.add_tile_layer(
|
| 278 |
-
wayback_mapping[latest_date], name=f"Esri Wayback - {latest_date.replace('-', '/')}", attribution="Esri"
|
| 279 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
.clip(buffer_ee_geometry)
|
| 287 |
-
.rename("slope")
|
| 288 |
-
)
|
| 289 |
-
# Calculate the minimum and maximum values
|
| 290 |
-
stats = slope_layer.reduceRegion(reducer=ee.Reducer.minMax(), scale=10, maxPixels=1e13)
|
| 291 |
-
max_value = int(stats.get("slope_max").getInfo())
|
| 292 |
-
min_value = int(stats.get("slope_min").getInfo())
|
| 293 |
-
vis_params = {"min": min_value, "max": max_value, "palette": ["blue", "green", "yellow", "red"]}
|
| 294 |
-
slope_map.addLayer(slope_layer, vis_params, "Slope Layer")
|
| 295 |
-
# Create a colormap
|
| 296 |
-
colormap = cm.LinearColormap(colors=vis_params["palette"], vmin=vis_params["min"], vmax=vis_params["max"])
|
| 297 |
-
tick_size=int((max_value-min_value)/4)
|
| 298 |
-
slope_map.add_legend(title="Slope (degrees)",
|
| 299 |
-
legend_dict={'{}-{} deg'.format(min_value, min_value+tick_size): '#0000FF',
|
| 300 |
-
'{}-{} deg'.format(min_value+tick_size, min_value+2*tick_size): '#00FF00',
|
| 301 |
-
'{}-{} deg'.format(min_value+2*tick_size, min_value+3*tick_size): '#FFFF00',
|
| 302 |
-
'{}-{} deg'.format(min_value+3*tick_size, max_value): '#FF0000'},
|
| 303 |
-
position='bottomright', draggable=False)
|
| 304 |
-
return dem_map, slope_map
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
def add_indices(image, nir_band, red_band, blue_band):
|
| 308 |
-
# Add negative cloud
|
| 309 |
-
neg_cloud = image.select("MSK_CLDPRB").multiply(-1).rename("Neg_MSK_CLDPRB")
|
| 310 |
-
nir = image.select(nir_band).divide(10000)
|
| 311 |
-
red = image.select(red_band).divide(10000)
|
| 312 |
-
blue = image.select(blue_band).divide(10000)
|
| 313 |
-
numerator = nir.subtract(red)
|
| 314 |
-
ndvi = (numerator).divide(nir.add(red)).rename("NDVI").clamp(-1, 1)
|
| 315 |
-
# EVI formula taken from: https://en.wikipedia.org/wiki/Enhanced_vegetation_index
|
| 316 |
-
|
| 317 |
-
denominator = nir.add(red.multiply(evi_vars["C1"])).subtract(blue.multiply(evi_vars["C2"])).add(evi_vars["L"])
|
| 318 |
-
evi = numerator.divide(denominator).multiply(evi_vars["G"]).rename("EVI").clamp(-1, 1)
|
| 319 |
-
evi2 = (
|
| 320 |
-
numerator.divide(nir.add(evi_vars["L"]).add(red.multiply(evi_vars["C"])))
|
| 321 |
-
.multiply(evi_vars["G"])
|
| 322 |
-
.rename("EVI2")
|
| 323 |
-
.clamp(-1, 1)
|
| 324 |
)
|
| 325 |
-
return image.addBands([neg_cloud, ndvi, evi, evi2])
|
| 326 |
-
|
| 327 |
-
def get_histogram(image, geometry, bins):
|
| 328 |
-
# Get image values as a list
|
| 329 |
-
values = image.reduceRegion(
|
| 330 |
-
reducer=ee.Reducer.toList(),
|
| 331 |
-
geometry=geometry,
|
| 332 |
-
scale=10,
|
| 333 |
-
maxPixels=1e13
|
| 334 |
-
).get('NDVI')
|
| 335 |
-
|
| 336 |
-
# Convert values to a NumPy array
|
| 337 |
-
values_array = np.array(values.getInfo())
|
| 338 |
-
|
| 339 |
-
# Compute the histogram on bins
|
| 340 |
-
hist, bin_edges = np.histogram(values_array, bins=bins)
|
| 341 |
-
|
| 342 |
-
return hist, bin_edges
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
def process_date(daterange, satellite, veg_indices):
|
| 346 |
-
start_date, end_date = daterange
|
| 347 |
-
daterange_str = daterange_dates_to_str(start_date, end_date)
|
| 348 |
-
prefix = f"Processing {satellite} - {daterange_str}"
|
| 349 |
-
try:
|
| 350 |
-
attrs = satellites[satellite]
|
| 351 |
-
collection = attrs["collection"]
|
| 352 |
-
collection = collection.filterBounds(buffer_ee_geometry)
|
| 353 |
-
collection = collection.filterDate(start_date, end_date)
|
| 354 |
-
|
| 355 |
-
bucket = {}
|
| 356 |
-
for veg_index in veg_indices:
|
| 357 |
-
mosaic_veg_index = collection.qualityMosaic(veg_index)
|
| 358 |
-
fc = geemap.zonal_stats(
|
| 359 |
-
mosaic_veg_index, ee_feature_collection, scale=attrs["scale"], return_fc=True
|
| 360 |
-
).getInfo()
|
| 361 |
-
mean_veg_index = fc["features"][0]["properties"][veg_index]
|
| 362 |
-
bucket[veg_index] = mean_veg_index
|
| 363 |
-
fc = geemap.zonal_stats(
|
| 364 |
-
mosaic_veg_index, buffer_ee_feature_collection, scale=attrs["scale"], return_fc=True
|
| 365 |
-
).getInfo()
|
| 366 |
-
buffer_mean_veg_index = fc["features"][0]["properties"][veg_index]
|
| 367 |
-
bucket[f"{veg_index}_buffer"] = buffer_mean_veg_index
|
| 368 |
-
bucket[f"{veg_index}_ratio"] = mean_veg_index / buffer_mean_veg_index
|
| 369 |
-
bucket[f"mosaic_{veg_index}"] = mosaic_veg_index
|
| 370 |
-
|
| 371 |
-
# Get median mosaic
|
| 372 |
-
bucket["mosaic_visual_max_ndvi"] = collection.qualityMosaic("NDVI")
|
| 373 |
-
bucket["mosaic_visual_median"] = collection.median()
|
| 374 |
-
bucket["image_visual_least_cloud"] = collection.sort("CLOUDY_PIXEL_PERCENTAGE").first()
|
| 375 |
-
|
| 376 |
-
if satellite == "COPERNICUS/S2_SR_HARMONIZED":
|
| 377 |
-
cloud_mask_probability = fc["features"][0]["properties"]["MSK_CLDPRB"] / 100
|
| 378 |
-
else:
|
| 379 |
-
cloud_mask_probability = None
|
| 380 |
-
bucket["Cloud (0 to 1)"] = cloud_mask_probability
|
| 381 |
-
result_df.loc[daterange_str, list(bucket.keys())] = list(bucket.values())
|
| 382 |
-
count = collection.size().getInfo()
|
| 383 |
-
suffix = f" - Processed {count} images"
|
| 384 |
-
write_info(f"{prefix}{suffix}")
|
| 385 |
-
except Exception as e:
|
| 386 |
-
print(e)
|
| 387 |
-
suffix = f" - Imagery not available"
|
| 388 |
-
write_info(f"{prefix}{suffix}")
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
def write_info(info):
|
| 392 |
-
st.write(f"<span style='color:#006400;'>{info}</span>", unsafe_allow_html=True)
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
############################################
|
| 396 |
-
# One time setup
|
| 397 |
-
############################################
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
def one_time_setup():
|
| 401 |
-
credentials_path = os.path.expanduser("~/.config/earthengine/credentials")
|
| 402 |
-
if os.path.exists(credentials_path):
|
| 403 |
-
pass # Earth Engine credentials already exist
|
| 404 |
-
elif "EE" in os.environ: # write the credentials to the file
|
| 405 |
-
ee_credentials = os.environ.get("EE")
|
| 406 |
-
os.makedirs(os.path.dirname(credentials_path), exist_ok=True)
|
| 407 |
-
with open(credentials_path, "w") as f:
|
| 408 |
-
f.write(ee_credentials)
|
| 409 |
-
else:
|
| 410 |
-
raise ValueError(
|
| 411 |
-
f"Earth Engine credentials not found at {credentials_path} or in the environment variable 'EE'"
|
| 412 |
-
)
|
| 413 |
-
|
| 414 |
-
ee.Initialize()
|
| 415 |
-
|
| 416 |
-
satellites = {
|
| 417 |
-
"COPERNICUS/S2_SR_HARMONIZED": {
|
| 418 |
-
"scale": 10,
|
| 419 |
-
"collection": ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
|
| 420 |
-
.select(
|
| 421 |
-
["B2", "B4", "B8", "MSK_CLDPRB", "TCI_R", "TCI_G", "TCI_B"],
|
| 422 |
-
["Blue", "Red", "NIR", "MSK_CLDPRB", "R", "G", "B"],
|
| 423 |
-
)
|
| 424 |
-
.map(lambda image: add_indices(image, nir_band="NIR", red_band="Red", blue_band="Blue")),
|
| 425 |
-
},
|
| 426 |
-
}
|
| 427 |
-
st.session_state.satellites = satellites
|
| 428 |
-
with open("wayback_imagery.json") as f:
|
| 429 |
-
st.session_state.wayback_mapping = json.load(f)
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
if "one_time_setup_done" not in st.session_state:
|
| 433 |
-
one_time_setup()
|
| 434 |
-
st.session_state.one_time_setup_done = True
|
| 435 |
-
|
| 436 |
-
satellites = st.session_state.satellites
|
| 437 |
-
wayback_mapping = st.session_state.wayback_mapping
|
| 438 |
-
|
| 439 |
-
############################################
|
| 440 |
-
# App
|
| 441 |
-
############################################
|
| 442 |
-
|
| 443 |
-
# Input: Satellite Sources
|
| 444 |
-
st.markdown(f"Satellite source: `{list(satellites.keys())[0]}`")
|
| 445 |
-
satellite_selected = {}
|
| 446 |
-
for satellite in satellites:
|
| 447 |
-
satellite_selected[satellite] = satellite
|
| 448 |
-
|
| 449 |
-
# Date range input
|
| 450 |
-
max_year = datetime.now().year
|
| 451 |
-
jan_1 = pd.to_datetime(f"{max_year}/01/01", format="%Y/%m/%d")
|
| 452 |
-
dec_31 = pd.to_datetime(f"{max_year}/12/31", format="%Y/%m/%d")
|
| 453 |
-
nov_15 = pd.to_datetime(f"{max_year}/11/15", format="%Y/%m/%d")
|
| 454 |
-
dec_15 = pd.to_datetime(f"{max_year}/12/15", format="%Y/%m/%d")
|
| 455 |
-
input_daterange = st.date_input(
|
| 456 |
-
"Date Range (Ignore year. App will compute indices for this date range in each year starting from \"Minimum Year\" to \"Maximum Year\")", (nov_15, dec_15), jan_1, dec_31
|
| 457 |
-
)
|
| 458 |
-
cols = st.columns(2)
|
| 459 |
-
with cols[0]:
|
| 460 |
-
min_year = int(st.number_input("Minimum Year", value=2019, min_value=2015, step=1))
|
| 461 |
-
with cols[1]:
|
| 462 |
-
max_year = int(st.number_input("Maximum Year", value=max_year, min_value=2015, step=1))
|
| 463 |
-
|
| 464 |
-
buffer = st.number_input("Buffer (m)", value=50, min_value=0, step=1)
|
| 465 |
-
|
| 466 |
-
input_gdf = get_gdf_from_file_url(file_url)
|
| 467 |
-
input_gdf = preprocess_gdf(input_gdf)
|
| 468 |
|
| 469 |
if len(input_gdf) > 1:
|
| 470 |
st.warning(f"Only the first polygon in the KML will be processed; all other geometries will be ignored.")
|
| 471 |
|
| 472 |
# input_geometry_idx = st.selectbox("Select the geometry", input_gdf.index, format_func=format_fn)
|
| 473 |
|
| 474 |
-
for i in range(len(input_gdf)):
|
| 475 |
-
geometry_gdf = input_gdf[input_gdf.index == i]
|
| 476 |
-
if is_valid_polygon(geometry_gdf):
|
| 477 |
-
break
|
| 478 |
-
else:
|
| 479 |
-
st.error(f"No polygon found inside KML. Please check the KML file.")
|
| 480 |
-
st.stop()
|
| 481 |
-
|
| 482 |
-
geometry_gdf = to_best_crs(geometry_gdf)
|
| 483 |
outer_geometry_gdf = geometry_gdf.copy()
|
| 484 |
outer_geometry_gdf["geometry"] = outer_geometry_gdf["geometry"].buffer(buffer)
|
| 485 |
buffer_geometry_gdf = (
|
|
@@ -487,81 +139,178 @@ buffer_geometry_gdf = (
|
|
| 487 |
) # reset index forces GeoSeries to GeoDataFrame
|
| 488 |
buffer_geometry_gdf["Name"] = "Buffer"
|
| 489 |
|
| 490 |
-
# Derived Inputs
|
| 491 |
-
ee_geometry = ee.Geometry(geometry_gdf.to_crs(4326).geometry.item().__geo_interface__)
|
| 492 |
-
ee_feature_collection = ee.FeatureCollection(ee_geometry)
|
| 493 |
-
buffer_ee_geometry = ee.Geometry(buffer_geometry_gdf.to_crs(4326).geometry.item().__geo_interface__)
|
| 494 |
-
buffer_ee_feature_collection = ee.FeatureCollection(buffer_ee_geometry)
|
| 495 |
-
outer_ee_geometry = ee.Geometry(outer_geometry_gdf.to_crs(4326).geometry.item().__geo_interface__)
|
| 496 |
-
outer_ee_feature_collection = ee.FeatureCollection(outer_ee_geometry)
|
| 497 |
-
|
| 498 |
# visualize the geometry
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 504 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
# m.add_layer(buffer_ee_feature_collection)
|
| 506 |
-
add_geometry_to_maps([m], opacity=0.3)
|
| 507 |
-
write_info(
|
| 508 |
-
|
| 509 |
-
<div style="text-align: center;">
|
| 510 |
-
|
| 511 |
-
</div>
|
| 512 |
-
"""
|
| 513 |
-
)
|
| 514 |
m.to_streamlit()
|
| 515 |
|
| 516 |
# Generate stats
|
|
|
|
|
|
|
|
|
|
| 517 |
stats_df = pd.DataFrame(
|
| 518 |
{
|
| 519 |
"Area (m^2)": geometry_gdf.area.item(),
|
| 520 |
"Perimeter (m)": geometry_gdf.length.item(),
|
| 521 |
"Points": str(json.loads(geometry_gdf.to_crs(4326).to_json())["features"][0]["geometry"]["coordinates"]),
|
| 522 |
-
|
|
|
|
|
|
|
| 523 |
)
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
# f"""| Metric | Value |
|
| 527 |
-
# | --- | --- |
|
| 528 |
-
# | Area (m^2) | {stats_df['Area (m^2)'].item():.2f} m^2 = {stats_df['Area (m^2)'].item()/10000:.2f} ha |
|
| 529 |
-
# | Perimeter (m) | {stats_df['Perimeter (m)'].item():.2f} m |
|
| 530 |
-
# """
|
| 531 |
-
# )
|
| 532 |
st.markdown(
|
| 533 |
f"""
|
| 534 |
<div style="display: flex; justify-content: center;">
|
| 535 |
-
<table style="border-collapse: collapse;
|
| 536 |
<tr>
|
| 537 |
-
<th style="border: 1px solid black;
|
| 538 |
-
<th style="border: 1px solid black;
|
|
|
|
| 539 |
</tr>
|
| 540 |
<tr>
|
| 541 |
-
<td style="border: 1px solid black;
|
| 542 |
-
<td style="border: 1px solid black;
|
|
|
|
| 543 |
</tr>
|
| 544 |
<tr>
|
| 545 |
-
<td style="border: 1px solid black;
|
| 546 |
-
<td style="border: 1px solid black;
|
|
|
|
| 547 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 548 |
</table>
|
| 549 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 550 |
""",
|
| 551 |
-
unsafe_allow_html=True
|
| 552 |
)
|
| 553 |
|
| 554 |
stats_csv = stats_df.to_csv(index=False)
|
| 555 |
st.download_button("Download Geometry Metrics", stats_csv, "geometry_metrics.csv", "text/csv", use_container_width=True)
|
| 556 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
# Submit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 558 |
submit = st.button("Calculate Vegetation Indices", use_container_width=True)
|
| 559 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
if submit:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 561 |
st.write("<h2><div style='text-align: center;'>Results</div></h2>", unsafe_allow_html=True)
|
| 562 |
if not any(satellite_selected.values()):
|
| 563 |
st.error("Please select at least one satellite source")
|
| 564 |
-
|
| 565 |
|
| 566 |
# Create range
|
| 567 |
start_day = input_daterange[0].day
|
|
@@ -583,7 +332,16 @@ if submit:
|
|
| 583 |
with st.spinner(f"Processing {satellite} ..."):
|
| 584 |
progress_bar = st.progress(0)
|
| 585 |
for i, daterange in enumerate(dates):
|
| 586 |
-
process_date(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 587 |
progress_bar.progress((i + 1) / len(dates))
|
| 588 |
|
| 589 |
st.session_state.result = result_df
|
|
@@ -591,6 +349,9 @@ if submit:
|
|
| 591 |
print("Printing result...")
|
| 592 |
if "result" in st.session_state:
|
| 593 |
result_df = st.session_state.result
|
|
|
|
|
|
|
|
|
|
| 594 |
print(result_df.columns)
|
| 595 |
|
| 596 |
# drop rows with all NaN values
|
|
@@ -606,8 +367,13 @@ if "result" in st.session_state:
|
|
| 606 |
result_df[column] = pd.to_numeric(result_df[column], errors="ignore")
|
| 607 |
|
| 608 |
df_numeric = result_df.select_dtypes(include=["float64"])
|
| 609 |
-
|
| 610 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
df_numeric_csv = df_numeric.to_csv(index=True)
|
| 612 |
st.download_button(
|
| 613 |
"Download Time Series Data", df_numeric_csv, "vegetation_indices.csv", "text/csv", use_container_width=True
|
|
@@ -619,23 +385,6 @@ if "result" in st.session_state:
|
|
| 619 |
fig.update_layout(xaxis=dict(tickvals=df_numeric.index, ticktext=df_numeric.index))
|
| 620 |
st.plotly_chart(fig)
|
| 621 |
|
| 622 |
-
st.write(
|
| 623 |
-
"<h3><div style='text-align: center;'>DEM and Slope from SRTM at 30m resolution</div></h3>",
|
| 624 |
-
unsafe_allow_html=True,
|
| 625 |
-
)
|
| 626 |
-
cols = st.columns(2)
|
| 627 |
-
dem_map, slope_map = get_dem_slope_maps(ee.Geometry(geometry_gdf.to_crs(4326).geometry.item().__geo_interface__))
|
| 628 |
-
for col, param_map, title in zip(cols, [dem_map, slope_map], ["DEM Map", "Slope Map"]):
|
| 629 |
-
with col:
|
| 630 |
-
param_map.add_gdf(
|
| 631 |
-
geometry_gdf,
|
| 632 |
-
layer_name="Geometry",
|
| 633 |
-
style_function=lambda x: {"color": "blue", "fillOpacity": 0.0, "fillColor": "blue"},
|
| 634 |
-
)
|
| 635 |
-
write_info(f"""<div style="text-align: center;">{title}</div>""")
|
| 636 |
-
param_map.addLayerControl()
|
| 637 |
-
param_map.to_streamlit()
|
| 638 |
-
|
| 639 |
st.write(
|
| 640 |
"<h3><div style='text-align: center;'>Visual Comparison between Two Years</div></h3>", unsafe_allow_html=True
|
| 641 |
)
|
|
@@ -660,7 +409,11 @@ if "result" in st.session_state:
|
|
| 660 |
mosaic = result_df.loc[daterange_str, f"mosaic_{veg_index}"]
|
| 661 |
with col:
|
| 662 |
m = gee_folium.Map()
|
| 663 |
-
m.add_tile_layer(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
veg_index_layer = gee_folium.ee_tile_layer(mosaic, {"bands": [veg_index], "min": 0, "max": 1})
|
| 665 |
|
| 666 |
if satellite == "COPERNICUS/S2_SR_HARMONIZED":
|
|
@@ -669,34 +422,40 @@ if "result" in st.session_state:
|
|
| 669 |
else:
|
| 670 |
raise ValueError(f"Unknown satellite: {satellite}")
|
| 671 |
|
| 672 |
-
if veg_index==
|
| 673 |
-
bins=[-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 1]
|
| 674 |
histogram, bin_edges = get_histogram(mosaic.select(veg_index), ee_geometry, bins)
|
| 675 |
total_pix = np.sum(histogram)
|
| 676 |
formatted_histogram = [f"{h*100/total_pix:.2f}" for h in histogram]
|
| 677 |
print(histogram, bin_edges, bins, formatted_histogram)
|
| 678 |
-
m.add_legend(
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
m.add_layer(mosaic.select(veg_index).clip(outer_ee_geometry), ndvi_vis_params)
|
| 692 |
-
|
| 693 |
# add colorbar
|
| 694 |
# m.add_colorbar(colors=["#000000", "#00FF00"], vmin=0.0, vmax=1.0)
|
| 695 |
-
|
| 696 |
-
if veg_index!=
|
| 697 |
m.add_layer(mosaic.select(veg_index).clip(outer_ee_geometry), vis_params)
|
| 698 |
m.add_child(colormap)
|
| 699 |
-
add_geometry_to_maps([m])
|
| 700 |
m.to_streamlit()
|
| 701 |
|
| 702 |
for name, key in zip(
|
|
@@ -708,14 +467,13 @@ if "result" in st.session_state:
|
|
| 708 |
for col, daterange_str in zip(cols, [year_1, year_2]):
|
| 709 |
start_date, end_date = daterange_str_to_dates(daterange_str)
|
| 710 |
mid_date = start_date + (end_date - start_date) / 2
|
| 711 |
-
esri_date = min(wayback_mapping.keys(), key=lambda x: abs(pd.to_datetime(x) - mid_date))
|
| 712 |
with col:
|
| 713 |
m = gee_folium.Map()
|
| 714 |
visual_mosaic = result_df.loc[daterange_str, key]
|
| 715 |
# visual_layer = gee_folium.ee_tile_layer(mosaic, {"bands": ["R", "G", "B"], "min": min_all, "max": max_all})
|
| 716 |
|
| 717 |
m.add_layer(visual_mosaic.select(["R", "G", "B"]))
|
| 718 |
-
add_geometry_to_maps([m])
|
| 719 |
m.to_streamlit()
|
| 720 |
|
| 721 |
st.write("<h3><div style='text-align: center;'>Esri RGB Imagery</div></h3>", unsafe_allow_html=True)
|
|
@@ -723,18 +481,31 @@ if "result" in st.session_state:
|
|
| 723 |
for col, daterange_str in zip(cols, [year_1, year_2]):
|
| 724 |
start_date, end_date = daterange_str_to_dates(daterange_str)
|
| 725 |
mid_date = start_date + (end_date - start_date) / 2
|
| 726 |
-
esri_date = min(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
with col:
|
| 728 |
m = leaf_folium.Map()
|
| 729 |
-
m.add_tile_layer(
|
| 730 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 731 |
write_info(
|
| 732 |
f"""
|
| 733 |
<div style="text-align: center;">
|
| 734 |
-
Esri Imagery - {esri_date.
|
| 735 |
</div>
|
| 736 |
"""
|
| 737 |
)
|
| 738 |
m.to_streamlit()
|
| 739 |
|
| 740 |
-
|
|
|
|
|
|
| 1 |
+
##############################################
|
| 2 |
+
# Imports
|
| 3 |
+
##############################################
|
| 4 |
+
|
| 5 |
import os
|
| 6 |
from datetime import datetime
|
| 7 |
import ee
|
| 8 |
import json
|
|
|
|
| 9 |
import numpy as np
|
| 10 |
import geemap.foliumap as gee_folium
|
| 11 |
import leafmap.foliumap as leaf_folium
|
| 12 |
import streamlit as st
|
| 13 |
import pandas as pd
|
|
|
|
|
|
|
|
|
|
| 14 |
import plotly.express as px
|
| 15 |
import branca.colormap as cm
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
+
from functions import *
|
|
|
|
|
|
|
| 18 |
|
| 19 |
st.set_page_config(layout="wide")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
+
############################################
|
| 22 |
+
# IITGN and GDF Logo
|
| 23 |
+
############################################
|
| 24 |
st.write(
|
| 25 |
f"""
|
| 26 |
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
|
|
| 31 |
unsafe_allow_html=True,
|
| 32 |
)
|
| 33 |
|
| 34 |
+
############################################
|
| 35 |
# Title
|
| 36 |
+
############################################
|
| 37 |
+
|
| 38 |
st.markdown(
|
| 39 |
f"""
|
| 40 |
+
<h1 style="text-align: center;">Kamlan: KML Analyzer</h1>
|
| 41 |
""",
|
| 42 |
unsafe_allow_html=True,
|
| 43 |
)
|
| 44 |
|
| 45 |
############################################
|
| 46 |
+
# KML/GeoJSON input
|
| 47 |
############################################
|
|
|
|
| 48 |
|
| 49 |
# Input: GeoJSON/KML file
|
| 50 |
file_url = st.query_params.get("file_url", None)
|
| 51 |
if file_url is None:
|
| 52 |
+
file_url = st.file_uploader("Upload KML/GeoJSON file", type=["geojson", "kml"])
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
if file_url is None:
|
| 55 |
st.warning(
|
| 56 |
+
"Please provide a KML or GeoJSON URL as a query parameter, e.g., `https://sustainabilitylabiitgn-ndvi-perg.hf.space?file_url=<your_file_url>` or upload a file."
|
| 57 |
)
|
| 58 |
+
force_stop()
|
| 59 |
+
|
| 60 |
+
# process the file
|
| 61 |
+
|
| 62 |
+
if ("cached_file_url" in st.session_state) and (st.session_state.cached_file_url == file_url):
|
| 63 |
+
input_gdf = st.session_state.input_gdf
|
| 64 |
+
geometry_gdf = st.session_state.geometry_gdf
|
| 65 |
+
else:
|
| 66 |
+
input_gdf = get_gdf_from_file_url(file_url)
|
| 67 |
+
input_gdf = preprocess_gdf(input_gdf)
|
| 68 |
+
|
| 69 |
+
for i in range(len(input_gdf)):
|
| 70 |
+
geometry_gdf = input_gdf[input_gdf.index == i]
|
| 71 |
+
if is_valid_polygon(geometry_gdf):
|
| 72 |
+
break
|
| 73 |
+
else:
|
| 74 |
+
st.error(f"No polygon found inside KML. Please check the KML file.")
|
| 75 |
+
force_stop()
|
| 76 |
|
| 77 |
+
geometry_gdf = to_best_crs(geometry_gdf)
|
| 78 |
+
st.session_state.input_gdf = input_gdf
|
| 79 |
+
st.session_state.geometry_gdf = geometry_gdf
|
| 80 |
+
st.session_state.cached_file_url = file_url
|
| 81 |
+
|
| 82 |
+
############################################
|
| 83 |
+
# App
|
| 84 |
+
############################################
|
| 85 |
with st.expander("Advanced Settings"):
|
| 86 |
st.write("Select the vegetation indices to calculate:")
|
| 87 |
all_veg_indices = ["NDVI", "EVI", "EVI2"]
|
|
|
|
| 102 |
value = col.number_input(f"{name}", value=default)
|
| 103 |
evi_vars[name] = value
|
| 104 |
|
| 105 |
+
# Date range input
|
| 106 |
+
max_year = datetime.now().year
|
| 107 |
+
jan_1 = pd.to_datetime(f"{max_year}/01/01", format="%Y/%m/%d")
|
| 108 |
+
dec_31 = pd.to_datetime(f"{max_year}/12/31", format="%Y/%m/%d")
|
| 109 |
+
nov_15 = pd.to_datetime(f"{max_year}/11/15", format="%Y/%m/%d")
|
| 110 |
+
dec_15 = pd.to_datetime(f"{max_year}/12/15", format="%Y/%m/%d")
|
| 111 |
+
input_daterange = st.date_input(
|
| 112 |
+
'Date Range (Ignore year. App will compute indices for this date range in each year starting from "Minimum Year" to "Maximum Year")',
|
| 113 |
+
(nov_15, dec_15),
|
| 114 |
+
jan_1,
|
| 115 |
+
dec_31,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
)
|
| 117 |
+
cols = st.columns(2)
|
| 118 |
+
with cols[0]:
|
| 119 |
+
min_year = int(st.number_input("Minimum Year", value=2019, min_value=2015, step=1))
|
| 120 |
+
with cols[1]:
|
| 121 |
+
max_year = int(st.number_input("Maximum Year", value=max_year, min_value=2015, step=1))
|
| 122 |
|
| 123 |
+
buffer = st.number_input("Buffer (m)", value=50, min_value=0, step=1)
|
| 124 |
+
map_type = st.radio(
|
| 125 |
+
"",
|
| 126 |
+
["Esri Satellite Map", "Google Hybrid Map (displays place names)", "Google Satellite Map"],
|
| 127 |
+
horizontal=True,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
if len(input_gdf) > 1:
|
| 131 |
st.warning(f"Only the first polygon in the KML will be processed; all other geometries will be ignored.")
|
| 132 |
|
| 133 |
# input_geometry_idx = st.selectbox("Select the geometry", input_gdf.index, format_func=format_fn)
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
outer_geometry_gdf = geometry_gdf.copy()
|
| 136 |
outer_geometry_gdf["geometry"] = outer_geometry_gdf["geometry"].buffer(buffer)
|
| 137 |
buffer_geometry_gdf = (
|
|
|
|
| 139 |
) # reset index forces GeoSeries to GeoDataFrame
|
| 140 |
buffer_geometry_gdf["Name"] = "Buffer"
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
# visualize the geometry
|
| 143 |
+
wayback_df = pd.read_parquet("./wayback.parquet").set_index("date")
|
| 144 |
+
first_item = wayback_df.iloc[0]
|
| 145 |
+
wayback_title = "Esri " + first_item["Title"]
|
| 146 |
+
wayback_url = (
|
| 147 |
+
first_item["ResourceURL_Template"]
|
| 148 |
+
.replace("{TileMatrixSet}", "GoogleMapsCompatible")
|
| 149 |
+
.replace("{TileMatrix}", "{z}")
|
| 150 |
+
.replace("{TileRow}", "{y}")
|
| 151 |
+
.replace("{TileCol}", "{x}")
|
| 152 |
)
|
| 153 |
+
# print(wayback_url)
|
| 154 |
+
|
| 155 |
+
m = leaf_folium.Map()
|
| 156 |
+
if map_type == "Google Hybrid Map (displays place names)":
|
| 157 |
+
m.add_basemap("HYBRID")
|
| 158 |
+
elif map_type == "Google Satellite Map":
|
| 159 |
+
m.add_basemap("SATELLITE")
|
| 160 |
+
elif map_type == "Esri Satellite Map":
|
| 161 |
+
m.add_wms_layer(
|
| 162 |
+
wayback_url,
|
| 163 |
+
layers="0",
|
| 164 |
+
name=wayback_title,
|
| 165 |
+
attribution="Esri",
|
| 166 |
+
)
|
| 167 |
+
else:
|
| 168 |
+
st.error("Invalid map type")
|
| 169 |
+
force_stop()
|
| 170 |
+
|
| 171 |
# m.add_layer(buffer_ee_feature_collection)
|
| 172 |
+
add_geometry_to_maps([m], geometry_gdf, buffer_geometry_gdf, opacity=0.3)
|
| 173 |
+
# write_info(
|
| 174 |
+
# f"""
|
| 175 |
+
# <div style="text-align: center;">
|
| 176 |
+
# Latest Esri Imagery - {latest_date.replace('-', '/')}
|
| 177 |
+
# </div>
|
| 178 |
+
# """
|
| 179 |
+
# )
|
| 180 |
m.to_streamlit()
|
| 181 |
|
| 182 |
# Generate stats
|
| 183 |
+
centroid = geometry_gdf.to_crs(4326).centroid.item()
|
| 184 |
+
centroid_lon = centroid.xy[0][0]
|
| 185 |
+
centroid_lat = centroid.xy[1][0]
|
| 186 |
stats_df = pd.DataFrame(
|
| 187 |
{
|
| 188 |
"Area (m^2)": geometry_gdf.area.item(),
|
| 189 |
"Perimeter (m)": geometry_gdf.length.item(),
|
| 190 |
"Points": str(json.loads(geometry_gdf.to_crs(4326).to_json())["features"][0]["geometry"]["coordinates"]),
|
| 191 |
+
"Centroid": f"({centroid_lat:.6f}, {centroid_lon:.6f})",
|
| 192 |
+
},
|
| 193 |
+
index=[0],
|
| 194 |
)
|
| 195 |
+
|
| 196 |
+
gmaps_redirect_url = f"http://maps.google.com/maps?q={centroid_lat},{centroid_lon}&layer=satellite"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
st.markdown(
|
| 198 |
f"""
|
| 199 |
<div style="display: flex; justify-content: center;">
|
| 200 |
+
<table style="border-collapse: collapse; text-align: center;">
|
| 201 |
<tr>
|
| 202 |
+
<th style="border: 1px solid black; text-align: left;">Metric</th>
|
| 203 |
+
<th style="border: 1px solid black; text-align: right;">Value</th>
|
| 204 |
+
<th style="border: 1px solid black; text-align: left;">Unit</th>
|
| 205 |
</tr>
|
| 206 |
<tr>
|
| 207 |
+
<td style="border: 1px solid black; text-align: left;">Area</td>
|
| 208 |
+
<td style="border: 1px solid black; text-align: right;">{stats_df['Area (m^2)'].item()/10000:.2f}</td>
|
| 209 |
+
<td style="border: 1px solid black; text-align: left;">ha</td>
|
| 210 |
</tr>
|
| 211 |
<tr>
|
| 212 |
+
<td style="border: 1px solid black; text-align: left;">Perimeter</td>
|
| 213 |
+
<td style="border: 1px solid black; text-align: right;">{stats_df['Perimeter (m)'].item():.2f}</td>
|
| 214 |
+
<td style="border: 1px solid black; text-align: left;">m</td>
|
| 215 |
</tr>
|
| 216 |
+
<tr>
|
| 217 |
+
<td style="border: 1px solid black; text-align: left;">Centroid</td>
|
| 218 |
+
<td style="border: 1px solid black; text-align: right;">({centroid_lat:.6f}, {centroid_lon:.6f})</td>
|
| 219 |
+
<td style="border: 1px solid black; text-align: left;">(lat, lon)</td>
|
| 220 |
</table>
|
| 221 |
</div>
|
| 222 |
+
<div style="text-align: center; margin-bottom: 10px;">
|
| 223 |
+
<a href="{gmaps_redirect_url}" target="_blank">
|
| 224 |
+
<button>View on Google Maps</button>
|
| 225 |
+
</a>
|
| 226 |
+
</div>
|
| 227 |
""",
|
| 228 |
+
unsafe_allow_html=True,
|
| 229 |
)
|
| 230 |
|
| 231 |
stats_csv = stats_df.to_csv(index=False)
|
| 232 |
st.download_button("Download Geometry Metrics", stats_csv, "geometry_metrics.csv", "text/csv", use_container_width=True)
|
| 233 |
|
| 234 |
+
st.write(
|
| 235 |
+
"<h3><div style='text-align: center;'>DEM and Slope from SRTM at 30m resolution</div></h3>",
|
| 236 |
+
unsafe_allow_html=True,
|
| 237 |
+
)
|
| 238 |
+
cols = st.columns(2)
|
| 239 |
+
|
| 240 |
+
if ("cached_dem_maps" in st.session_state) and (st.session_state.cached_file_url == file_url):
|
| 241 |
+
dem_map = st.session_state.dem_map
|
| 242 |
+
slope_map = st.session_state.slope_map
|
| 243 |
+
else:
|
| 244 |
+
dem_map, slope_map = get_dem_slope_maps(
|
| 245 |
+
ee.Geometry(geometry_gdf.to_crs(4326).geometry.item().__geo_interface__), wayback_url, wayback_title
|
| 246 |
+
)
|
| 247 |
+
st.session_state.dem_map = dem_map
|
| 248 |
+
st.session_state.slope_map = slope_map
|
| 249 |
+
st.session_state.cached_dem_maps = True
|
| 250 |
+
|
| 251 |
+
for col, param_map, title in zip(cols, [dem_map, slope_map], ["DEM Map", "Slope Map"]):
|
| 252 |
+
with col:
|
| 253 |
+
param_map.add_gdf(
|
| 254 |
+
geometry_gdf,
|
| 255 |
+
layer_name="Geometry",
|
| 256 |
+
style_function=lambda x: {"color": "blue", "fillOpacity": 0.0, "fillColor": "blue"},
|
| 257 |
+
)
|
| 258 |
+
write_info(f"""<div style="text-align: center;">{title}</div>""")
|
| 259 |
+
param_map.addLayerControl()
|
| 260 |
+
param_map.to_streamlit()
|
| 261 |
+
|
| 262 |
# Submit
|
| 263 |
+
m = st.markdown(
|
| 264 |
+
"""
|
| 265 |
+
<style>
|
| 266 |
+
div.stButton > button:first-child {
|
| 267 |
+
background-color: #006400;
|
| 268 |
+
color:#ffffff;
|
| 269 |
+
}
|
| 270 |
+
</style>""",
|
| 271 |
+
unsafe_allow_html=True,
|
| 272 |
+
)
|
| 273 |
submit = st.button("Calculate Vegetation Indices", use_container_width=True)
|
| 274 |
|
| 275 |
+
# Derived Inputs
|
| 276 |
+
ee_geometry = ee.Geometry(geometry_gdf.to_crs(4326).geometry.item().__geo_interface__)
|
| 277 |
+
ee_feature_collection = ee.FeatureCollection(ee_geometry)
|
| 278 |
+
buffer_ee_geometry = ee.Geometry(buffer_geometry_gdf.to_crs(4326).geometry.item().__geo_interface__)
|
| 279 |
+
buffer_ee_feature_collection = ee.FeatureCollection(buffer_ee_geometry)
|
| 280 |
+
outer_ee_geometry = ee.Geometry(outer_geometry_gdf.to_crs(4326).geometry.item().__geo_interface__)
|
| 281 |
+
outer_ee_feature_collection = ee.FeatureCollection(outer_ee_geometry)
|
| 282 |
+
|
| 283 |
if submit:
|
| 284 |
+
satellites = {
|
| 285 |
+
"COPERNICUS/S2_SR_HARMONIZED": {
|
| 286 |
+
"scale": 10,
|
| 287 |
+
"collection": ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
|
| 288 |
+
.select(
|
| 289 |
+
["B2", "B4", "B8", "MSK_CLDPRB", "TCI_R", "TCI_G", "TCI_B"],
|
| 290 |
+
["Blue", "Red", "NIR", "MSK_CLDPRB", "R", "G", "B"],
|
| 291 |
+
)
|
| 292 |
+
.map(lambda image: add_indices(image, nir_band="NIR", red_band="Red", blue_band="Blue", evi_vars=evi_vars)),
|
| 293 |
+
},
|
| 294 |
+
}
|
| 295 |
+
satellite = list(satellites.keys())[0]
|
| 296 |
+
st.session_state.satellites = satellites
|
| 297 |
+
st.session_state.satellite = satellite
|
| 298 |
+
|
| 299 |
+
# Run one-time setup
|
| 300 |
+
if "one_time_setup_done" not in st.session_state:
|
| 301 |
+
one_time_setup()
|
| 302 |
+
st.session_state.one_time_setup_done = True
|
| 303 |
+
|
| 304 |
+
# Input: Satellite Sources
|
| 305 |
+
st.markdown(f"Satellite source: `{satellite}`")
|
| 306 |
+
satellite_selected = {}
|
| 307 |
+
for satellite in satellites:
|
| 308 |
+
satellite_selected[satellite] = satellite
|
| 309 |
+
|
| 310 |
st.write("<h2><div style='text-align: center;'>Results</div></h2>", unsafe_allow_html=True)
|
| 311 |
if not any(satellite_selected.values()):
|
| 312 |
st.error("Please select at least one satellite source")
|
| 313 |
+
force_stop()
|
| 314 |
|
| 315 |
# Create range
|
| 316 |
start_day = input_daterange[0].day
|
|
|
|
| 332 |
with st.spinner(f"Processing {satellite} ..."):
|
| 333 |
progress_bar = st.progress(0)
|
| 334 |
for i, daterange in enumerate(dates):
|
| 335 |
+
process_date(
|
| 336 |
+
daterange,
|
| 337 |
+
satellite,
|
| 338 |
+
veg_indices,
|
| 339 |
+
satellites,
|
| 340 |
+
buffer_ee_geometry,
|
| 341 |
+
ee_feature_collection,
|
| 342 |
+
buffer_ee_feature_collection,
|
| 343 |
+
result_df,
|
| 344 |
+
)
|
| 345 |
progress_bar.progress((i + 1) / len(dates))
|
| 346 |
|
| 347 |
st.session_state.result = result_df
|
|
|
|
| 349 |
print("Printing result...")
|
| 350 |
if "result" in st.session_state:
|
| 351 |
result_df = st.session_state.result
|
| 352 |
+
satellites = st.session_state.satellites
|
| 353 |
+
satellite = st.session_state.satellite
|
| 354 |
+
|
| 355 |
print(result_df.columns)
|
| 356 |
|
| 357 |
# drop rows with all NaN values
|
|
|
|
| 367 |
result_df[column] = pd.to_numeric(result_df[column], errors="ignore")
|
| 368 |
|
| 369 |
df_numeric = result_df.select_dtypes(include=["float64"])
|
| 370 |
+
# df_numeric.index.name = "Date Range"
|
| 371 |
+
html = df_numeric.style.format(precision=2).set_properties(**{"text-align": "right"}).to_html()
|
| 372 |
+
st.write(
|
| 373 |
+
f"""<div style="display: flex; justify-content: center;">
|
| 374 |
+
{html}</div>""",
|
| 375 |
+
unsafe_allow_html=True,
|
| 376 |
+
)
|
| 377 |
df_numeric_csv = df_numeric.to_csv(index=True)
|
| 378 |
st.download_button(
|
| 379 |
"Download Time Series Data", df_numeric_csv, "vegetation_indices.csv", "text/csv", use_container_width=True
|
|
|
|
| 385 |
fig.update_layout(xaxis=dict(tickvals=df_numeric.index, ticktext=df_numeric.index))
|
| 386 |
st.plotly_chart(fig)
|
| 387 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
st.write(
|
| 389 |
"<h3><div style='text-align: center;'>Visual Comparison between Two Years</div></h3>", unsafe_allow_html=True
|
| 390 |
)
|
|
|
|
| 409 |
mosaic = result_df.loc[daterange_str, f"mosaic_{veg_index}"]
|
| 410 |
with col:
|
| 411 |
m = gee_folium.Map()
|
| 412 |
+
m.add_tile_layer(
|
| 413 |
+
wayback_url,
|
| 414 |
+
name=wayback_title,
|
| 415 |
+
attribution="Esri",
|
| 416 |
+
)
|
| 417 |
veg_index_layer = gee_folium.ee_tile_layer(mosaic, {"bands": [veg_index], "min": 0, "max": 1})
|
| 418 |
|
| 419 |
if satellite == "COPERNICUS/S2_SR_HARMONIZED":
|
|
|
|
| 422 |
else:
|
| 423 |
raise ValueError(f"Unknown satellite: {satellite}")
|
| 424 |
|
| 425 |
+
if veg_index == "NDVI":
|
| 426 |
+
bins = [-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 1]
|
| 427 |
histogram, bin_edges = get_histogram(mosaic.select(veg_index), ee_geometry, bins)
|
| 428 |
total_pix = np.sum(histogram)
|
| 429 |
formatted_histogram = [f"{h*100/total_pix:.2f}" for h in histogram]
|
| 430 |
print(histogram, bin_edges, bins, formatted_histogram)
|
| 431 |
+
m.add_legend(
|
| 432 |
+
title="NDVI Class/Value",
|
| 433 |
+
legend_dict={
|
| 434 |
+
"<0:Waterbody ({}%)".format(formatted_histogram[0]): "#0000FF",
|
| 435 |
+
"0-0.1: Open ({}%)".format(formatted_histogram[1]): "#FF0000",
|
| 436 |
+
"0.1-0.2: Highly Degraded ({}%)".format(formatted_histogram[2]): "#FFFF00",
|
| 437 |
+
"0.2-0.3: Degraded ({}%)".format(formatted_histogram[3]): "#FFA500",
|
| 438 |
+
"0.3-0.4: Moderately Degraded ({}%)".format(formatted_histogram[4]): "#00FE00",
|
| 439 |
+
"0.4-0.5: Dense ({}%)".format(formatted_histogram[5]): "#00A400",
|
| 440 |
+
">0.5: Very Dense ({}%)".format(formatted_histogram[6]): "#006D00",
|
| 441 |
+
},
|
| 442 |
+
position="bottomright",
|
| 443 |
+
draggable=False,
|
| 444 |
+
)
|
| 445 |
+
ndvi_vis_params = {
|
| 446 |
+
"min": -0.1,
|
| 447 |
+
"max": 0.6,
|
| 448 |
+
"palette": ["#0000FF", "#FF0000", "#FFFF00", "#FFA500", "#00FE00", "#00A400", "#006D00"],
|
| 449 |
+
}
|
| 450 |
m.add_layer(mosaic.select(veg_index).clip(outer_ee_geometry), ndvi_vis_params)
|
| 451 |
+
|
| 452 |
# add colorbar
|
| 453 |
# m.add_colorbar(colors=["#000000", "#00FF00"], vmin=0.0, vmax=1.0)
|
| 454 |
+
|
| 455 |
+
if veg_index != "NDVI":
|
| 456 |
m.add_layer(mosaic.select(veg_index).clip(outer_ee_geometry), vis_params)
|
| 457 |
m.add_child(colormap)
|
| 458 |
+
add_geometry_to_maps([m], geometry_gdf, buffer_geometry_gdf)
|
| 459 |
m.to_streamlit()
|
| 460 |
|
| 461 |
for name, key in zip(
|
|
|
|
| 467 |
for col, daterange_str in zip(cols, [year_1, year_2]):
|
| 468 |
start_date, end_date = daterange_str_to_dates(daterange_str)
|
| 469 |
mid_date = start_date + (end_date - start_date) / 2
|
|
|
|
| 470 |
with col:
|
| 471 |
m = gee_folium.Map()
|
| 472 |
visual_mosaic = result_df.loc[daterange_str, key]
|
| 473 |
# visual_layer = gee_folium.ee_tile_layer(mosaic, {"bands": ["R", "G", "B"], "min": min_all, "max": max_all})
|
| 474 |
|
| 475 |
m.add_layer(visual_mosaic.select(["R", "G", "B"]))
|
| 476 |
+
add_geometry_to_maps([m], geometry_gdf, buffer_geometry_gdf)
|
| 477 |
m.to_streamlit()
|
| 478 |
|
| 479 |
st.write("<h3><div style='text-align: center;'>Esri RGB Imagery</div></h3>", unsafe_allow_html=True)
|
|
|
|
| 481 |
for col, daterange_str in zip(cols, [year_1, year_2]):
|
| 482 |
start_date, end_date = daterange_str_to_dates(daterange_str)
|
| 483 |
mid_date = start_date + (end_date - start_date) / 2
|
| 484 |
+
esri_date = min(wayback_df.index, key=lambda x: abs(x - mid_date))
|
| 485 |
+
esri_url = (
|
| 486 |
+
wayback_df.loc[esri_date, "ResourceURL_Template"]
|
| 487 |
+
.replace("{TileMatrixSet}", "GoogleMapsCompatible")
|
| 488 |
+
.replace("{TileMatrix}", "{z}")
|
| 489 |
+
.replace("{TileRow}", "{y}")
|
| 490 |
+
.replace("{TileCol}", "{x}")
|
| 491 |
+
)
|
| 492 |
+
esri_title = "Esri " + wayback_df.loc[esri_date, "Title"]
|
| 493 |
with col:
|
| 494 |
m = leaf_folium.Map()
|
| 495 |
+
m.add_tile_layer(
|
| 496 |
+
esri_url,
|
| 497 |
+
name=esri_title,
|
| 498 |
+
attribution="Esri",
|
| 499 |
+
)
|
| 500 |
+
add_geometry_to_maps([m], geometry_gdf, buffer_geometry_gdf)
|
| 501 |
write_info(
|
| 502 |
f"""
|
| 503 |
<div style="text-align: center;">
|
| 504 |
+
Esri Imagery - {esri_date.strftime('%Y-%m-%d')}
|
| 505 |
</div>
|
| 506 |
"""
|
| 507 |
)
|
| 508 |
m.to_streamlit()
|
| 509 |
|
| 510 |
+
|
| 511 |
+
show_credits()
|
functions.py
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from datetime import datetime
|
| 3 |
+
import ee
|
| 4 |
+
import json
|
| 5 |
+
import geemap
|
| 6 |
+
import numpy as np
|
| 7 |
+
import geemap.foliumap as gee_folium
|
| 8 |
+
import leafmap.foliumap as leaf_folium
|
| 9 |
+
import streamlit as st
|
| 10 |
+
import pandas as pd
|
| 11 |
+
import geopandas as gpd
|
| 12 |
+
from shapely.ops import transform
|
| 13 |
+
from functools import reduce
|
| 14 |
+
import plotly.express as px
|
| 15 |
+
import branca.colormap as cm
|
| 16 |
+
import folium
|
| 17 |
+
import pyproj
|
| 18 |
+
from io import StringIO, BytesIO
|
| 19 |
+
import requests
|
| 20 |
+
import kml2geojson
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def force_stop():
|
| 24 |
+
show_credits()
|
| 25 |
+
st.stop()
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def one_time_setup():
|
| 29 |
+
credentials_path = os.path.expanduser("~/.config/earthengine/credentials")
|
| 30 |
+
if os.path.exists(credentials_path):
|
| 31 |
+
pass # Earth Engine credentials already exist
|
| 32 |
+
elif "EE" in os.environ: # write the credentials to the file
|
| 33 |
+
ee_credentials = os.environ.get("EE")
|
| 34 |
+
os.makedirs(os.path.dirname(credentials_path), exist_ok=True)
|
| 35 |
+
with open(credentials_path, "w") as f:
|
| 36 |
+
f.write(ee_credentials)
|
| 37 |
+
else:
|
| 38 |
+
raise ValueError(
|
| 39 |
+
f"Earth Engine credentials not found at {credentials_path} or in the environment variable 'EE'"
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
ee.Initialize()
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def show_credits():
|
| 46 |
+
# Add credits
|
| 47 |
+
st.write(
|
| 48 |
+
"""
|
| 49 |
+
<div style="display: flex; justify-content: center; align-items: center; margin-top: 20px;">
|
| 50 |
+
<p style="text-align: center;">Developed by <a href="https://sustainability-lab.github.io/">Sustainability Lab</a>, <a href="https://www.iitgn.ac.in/">IIT Gandhinagar</a></p>
|
| 51 |
+
</div>
|
| 52 |
+
<div style="display: flex; justify-content: center; align-items: center;">
|
| 53 |
+
<p style="text-align: center;"> Supported by <a href="https://forests.gujarat.gov.in/">Gujarat Forest Department</a>
|
| 54 |
+
</p>
|
| 55 |
+
</div>
|
| 56 |
+
""",
|
| 57 |
+
unsafe_allow_html=True,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def get_gdf_from_file_url(file_url):
|
| 62 |
+
if isinstance(file_url, str):
|
| 63 |
+
if file_url.startswith("https://drive.google.com/file/d/"):
|
| 64 |
+
ID = file_url.replace("https://drive.google.com/file/d/", "").split("/")[0]
|
| 65 |
+
file_url = f"https://drive.google.com/uc?id={ID}"
|
| 66 |
+
elif file_url.startswith("https://drive.google.com/open?id="):
|
| 67 |
+
ID = file_url.replace("https://drive.google.com/open?id=", "")
|
| 68 |
+
file_url = f"https://drive.google.com/uc?id={ID}"
|
| 69 |
+
|
| 70 |
+
response = requests.get(file_url)
|
| 71 |
+
bytes_data = BytesIO(response.content)
|
| 72 |
+
string_data = response.text
|
| 73 |
+
else:
|
| 74 |
+
bytes_data = BytesIO(file_url.getvalue())
|
| 75 |
+
string_data = file_url.getvalue().decode("utf-8")
|
| 76 |
+
|
| 77 |
+
if string_data.startswith("<?xml"):
|
| 78 |
+
geojson = kml2geojson.convert(bytes_data)
|
| 79 |
+
features = geojson[0]["features"]
|
| 80 |
+
epsg = 4326
|
| 81 |
+
input_gdf = gpd.GeoDataFrame.from_features(features, crs=f"EPSG:{epsg}")
|
| 82 |
+
else:
|
| 83 |
+
input_gdf = gpd.read_file(bytes_data)
|
| 84 |
+
|
| 85 |
+
return input_gdf
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
# Function of find best suited statewise EPSG code
|
| 89 |
+
def find_best_epsg(geometry):
|
| 90 |
+
if geometry.geom_type == "Polygon":
|
| 91 |
+
centroid = geometry.centroid
|
| 92 |
+
else:
|
| 93 |
+
st.error("Geometry is not Polygon !!!")
|
| 94 |
+
st.stop()
|
| 95 |
+
common_epsg_codes = [
|
| 96 |
+
7756, # Andhra Pradesh
|
| 97 |
+
7757, # Arunachal Pradesh
|
| 98 |
+
7758, # Assam
|
| 99 |
+
7759, # Bihar
|
| 100 |
+
7760, # Delhi
|
| 101 |
+
7761, # Gujarat
|
| 102 |
+
7762, # Haryana
|
| 103 |
+
7763, # HimachalPradesh
|
| 104 |
+
7764, # JammuAndKashmir
|
| 105 |
+
7765, # Jharkhand
|
| 106 |
+
7766, # MadhyaPradesh
|
| 107 |
+
7767, # Maharastra
|
| 108 |
+
7768, # Manipur
|
| 109 |
+
7769, # Meghalaya
|
| 110 |
+
7770, # Nagaland
|
| 111 |
+
7772, # Orissa
|
| 112 |
+
7773, # Punjab
|
| 113 |
+
7774, # Rajasthan
|
| 114 |
+
7775, # UttarPradesh
|
| 115 |
+
7776, # Uttaranchal
|
| 116 |
+
7777, # A&N
|
| 117 |
+
7778, # Chattisgarh
|
| 118 |
+
7779, # Goa
|
| 119 |
+
7780, # Karnataka
|
| 120 |
+
7781, # Kerala
|
| 121 |
+
7782, # Lakshadweep
|
| 122 |
+
7783, # Mizoram
|
| 123 |
+
7784, # Sikkim
|
| 124 |
+
7785, # TamilNadu
|
| 125 |
+
7786, # Tripura
|
| 126 |
+
7787, # WestBengal
|
| 127 |
+
7771, # NE India
|
| 128 |
+
7755, # India
|
| 129 |
+
]
|
| 130 |
+
|
| 131 |
+
for epsg in common_epsg_codes:
|
| 132 |
+
crs = pyproj.CRS.from_epsg(epsg)
|
| 133 |
+
area_of_use = crs.area_of_use.bounds # Get the bounding box of the area of use
|
| 134 |
+
|
| 135 |
+
# check if centroid of polygon lies in teh bounds of the crs
|
| 136 |
+
if (area_of_use[0] <= centroid.x <= area_of_use[2]) and (area_of_use[1] <= centroid.y <= area_of_use[3]):
|
| 137 |
+
return epsg # Return the best suitable EPSG code
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def daterange_str_to_dates(daterange_str):
|
| 141 |
+
start_date, end_date = daterange_str.split("-")
|
| 142 |
+
start_date = pd.to_datetime(start_date)
|
| 143 |
+
end_date = pd.to_datetime(end_date)
|
| 144 |
+
return start_date, end_date
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def daterange_dates_to_str(start_date, end_date):
|
| 148 |
+
return f"{start_date.strftime('%Y/%m/%d')}-{end_date.strftime('%Y/%m/%d')}"
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
def daterange_str_to_year(daterange_str):
|
| 152 |
+
start_date, _ = daterange_str.split("-")
|
| 153 |
+
year = pd.to_datetime(start_date).year
|
| 154 |
+
return year
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def shape_3d_to_2d(shape):
|
| 158 |
+
if shape.has_z:
|
| 159 |
+
return transform(lambda x, y, z: (x, y), shape)
|
| 160 |
+
else:
|
| 161 |
+
return shape
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def preprocess_gdf(gdf):
|
| 165 |
+
gdf["geometry"] = gdf["geometry"].apply(shape_3d_to_2d)
|
| 166 |
+
gdf["geometry"] = gdf.buffer(0) # Fixes some invalid geometries
|
| 167 |
+
return gdf
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def to_best_crs(gdf):
|
| 171 |
+
best_epsg_code = find_best_epsg(gdf["geometry"].iloc[0])
|
| 172 |
+
gdf = gdf.to_crs(epsg=best_epsg_code)
|
| 173 |
+
return gdf
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
def is_valid_polygon(geometry_gdf):
|
| 177 |
+
geometry = geometry_gdf.geometry.item()
|
| 178 |
+
return (geometry.type == "Polygon") and (not geometry.is_empty)
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
def add_geometry_to_maps(map_list, geometry_gdf, buffer_geometry_gdf, opacity=0.0):
|
| 182 |
+
for m in map_list:
|
| 183 |
+
m.add_gdf(
|
| 184 |
+
buffer_geometry_gdf,
|
| 185 |
+
layer_name="Geometry Buffer",
|
| 186 |
+
style_function=lambda x: {"color": "red", "fillOpacity": opacity, "fillColor": "red"},
|
| 187 |
+
)
|
| 188 |
+
m.add_gdf(
|
| 189 |
+
geometry_gdf,
|
| 190 |
+
layer_name="Geometry",
|
| 191 |
+
style_function=lambda x: {"color": "blue", "fillOpacity": opacity, "fillColor": "blue"},
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def get_dem_slope_maps(ee_geometry, wayback_url, wayback_title):
|
| 196 |
+
# Create the map for DEM
|
| 197 |
+
dem_map = gee_folium.Map(controls={"scale": "bottomleft"})
|
| 198 |
+
dem_map.add_tile_layer(wayback_url, name=wayback_title, attribution="Esri")
|
| 199 |
+
|
| 200 |
+
dem_layer = ee.Image("USGS/SRTMGL1_003")
|
| 201 |
+
# Set the target resolution to 10 meters
|
| 202 |
+
target_resolution = 10
|
| 203 |
+
dem_layer = dem_layer.resample("bilinear").reproject(crs="EPSG:4326", scale=target_resolution).clip(ee_geometry)
|
| 204 |
+
|
| 205 |
+
# Generate contour lines using elevation thresholds
|
| 206 |
+
terrain = ee.Algorithms.Terrain(dem_layer)
|
| 207 |
+
contour_interval = 1
|
| 208 |
+
contours = (
|
| 209 |
+
terrain.select("elevation").subtract(terrain.select("elevation").mod(contour_interval)).rename("contours")
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
# Calculate the minimum and maximum values
|
| 213 |
+
stats = contours.reduceRegion(reducer=ee.Reducer.minMax(), scale=10, maxPixels=1e13)
|
| 214 |
+
max_value = stats.get("contours_max").getInfo()
|
| 215 |
+
min_value = stats.get("contours_min").getInfo()
|
| 216 |
+
vis_params = {"min": min_value, "max": max_value, "palette": ["blue", "green", "yellow", "red"]}
|
| 217 |
+
dem_map.addLayer(contours, vis_params, "Contours")
|
| 218 |
+
# Create a colormap
|
| 219 |
+
cmap = cm.LinearColormap(colors=vis_params["palette"], vmin=vis_params["min"], vmax=vis_params["max"])
|
| 220 |
+
tick_size = int((max_value - min_value) / 4)
|
| 221 |
+
dem_map.add_legend(
|
| 222 |
+
title="Elevation (m)",
|
| 223 |
+
legend_dict={
|
| 224 |
+
"{}-{} m".format(min_value, min_value + tick_size): "#0000FF",
|
| 225 |
+
"{}-{} m".format(min_value + tick_size, min_value + 2 * tick_size): "#00FF00",
|
| 226 |
+
"{}-{} m".format(min_value + 2 * tick_size, min_value + 3 * tick_size): "#FFFF00",
|
| 227 |
+
"{}-{} m".format(min_value + 3 * tick_size, max_value): "#FF0000",
|
| 228 |
+
},
|
| 229 |
+
position="bottomright",
|
| 230 |
+
draggable=False,
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
# Create the map for Slope
|
| 234 |
+
slope_map = gee_folium.Map(controls={"scale": "bottomleft"})
|
| 235 |
+
slope_map.add_tile_layer(wayback_url, name=wayback_title, attribution="Esri")
|
| 236 |
+
|
| 237 |
+
# Calculate slope from the DEM
|
| 238 |
+
slope_layer = (
|
| 239 |
+
ee.Terrain.slope(
|
| 240 |
+
ee.Image("USGS/SRTMGL1_003").resample("bilinear").reproject(crs="EPSG:4326", scale=target_resolution)
|
| 241 |
+
)
|
| 242 |
+
.clip(ee_geometry)
|
| 243 |
+
.rename("slope")
|
| 244 |
+
)
|
| 245 |
+
# Calculate the minimum and maximum values
|
| 246 |
+
stats = slope_layer.reduceRegion(reducer=ee.Reducer.minMax(), scale=10, maxPixels=1e13)
|
| 247 |
+
max_value = int(stats.get("slope_max").getInfo())
|
| 248 |
+
min_value = int(stats.get("slope_min").getInfo())
|
| 249 |
+
vis_params = {"min": min_value, "max": max_value, "palette": ["blue", "green", "yellow", "red"]}
|
| 250 |
+
slope_map.addLayer(slope_layer, vis_params, "Slope Layer")
|
| 251 |
+
# Create a colormap
|
| 252 |
+
colormap = cm.LinearColormap(colors=vis_params["palette"], vmin=vis_params["min"], vmax=vis_params["max"])
|
| 253 |
+
tick_size = int((max_value - min_value) / 4)
|
| 254 |
+
slope_map.add_legend(
|
| 255 |
+
title="Slope (degrees)",
|
| 256 |
+
legend_dict={
|
| 257 |
+
"{}-{} deg".format(min_value, min_value + tick_size): "#0000FF",
|
| 258 |
+
"{}-{} deg".format(min_value + tick_size, min_value + 2 * tick_size): "#00FF00",
|
| 259 |
+
"{}-{} deg".format(min_value + 2 * tick_size, min_value + 3 * tick_size): "#FFFF00",
|
| 260 |
+
"{}-{} deg".format(min_value + 3 * tick_size, max_value): "#FF0000",
|
| 261 |
+
},
|
| 262 |
+
position="bottomright",
|
| 263 |
+
draggable=False,
|
| 264 |
+
)
|
| 265 |
+
return dem_map, slope_map
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
def add_indices(image, nir_band, red_band, blue_band, evi_vars):
|
| 269 |
+
# Add negative cloud
|
| 270 |
+
neg_cloud = image.select("MSK_CLDPRB").multiply(-1).rename("Neg_MSK_CLDPRB")
|
| 271 |
+
nir = image.select(nir_band).divide(10000)
|
| 272 |
+
red = image.select(red_band).divide(10000)
|
| 273 |
+
blue = image.select(blue_band).divide(10000)
|
| 274 |
+
numerator = nir.subtract(red)
|
| 275 |
+
ndvi = (numerator).divide(nir.add(red)).rename("NDVI").clamp(-1, 1)
|
| 276 |
+
# EVI formula taken from: https://en.wikipedia.org/wiki/Enhanced_vegetation_index
|
| 277 |
+
|
| 278 |
+
denominator = nir.add(red.multiply(evi_vars["C1"])).subtract(blue.multiply(evi_vars["C2"])).add(evi_vars["L"])
|
| 279 |
+
evi = numerator.divide(denominator).multiply(evi_vars["G"]).rename("EVI").clamp(-1, 1)
|
| 280 |
+
evi2 = (
|
| 281 |
+
numerator.divide(nir.add(evi_vars["L"]).add(red.multiply(evi_vars["C"])))
|
| 282 |
+
.multiply(evi_vars["G"])
|
| 283 |
+
.rename("EVI2")
|
| 284 |
+
.clamp(-1, 1)
|
| 285 |
+
)
|
| 286 |
+
return image.addBands([neg_cloud, ndvi, evi, evi2])
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
def get_histogram(image, geometry, bins):
|
| 290 |
+
# Get image values as a list
|
| 291 |
+
values = image.reduceRegion(reducer=ee.Reducer.toList(), geometry=geometry, scale=10, maxPixels=1e13).get("NDVI")
|
| 292 |
+
|
| 293 |
+
# Convert values to a NumPy array
|
| 294 |
+
values_array = np.array(values.getInfo())
|
| 295 |
+
|
| 296 |
+
# Compute the histogram on bins
|
| 297 |
+
hist, bin_edges = np.histogram(values_array, bins=bins)
|
| 298 |
+
|
| 299 |
+
return hist, bin_edges
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
def process_date(
|
| 303 |
+
daterange,
|
| 304 |
+
satellite,
|
| 305 |
+
veg_indices,
|
| 306 |
+
satellites,
|
| 307 |
+
buffer_ee_geometry,
|
| 308 |
+
ee_feature_collection,
|
| 309 |
+
buffer_ee_feature_collection,
|
| 310 |
+
result_df,
|
| 311 |
+
):
|
| 312 |
+
start_date, end_date = daterange
|
| 313 |
+
daterange_str = daterange_dates_to_str(start_date, end_date)
|
| 314 |
+
prefix = f"Processing {satellite} - {daterange_str}"
|
| 315 |
+
try:
|
| 316 |
+
attrs = satellites[satellite]
|
| 317 |
+
collection = attrs["collection"]
|
| 318 |
+
collection = collection.filterBounds(buffer_ee_geometry)
|
| 319 |
+
collection = collection.filterDate(start_date, end_date)
|
| 320 |
+
|
| 321 |
+
bucket = {}
|
| 322 |
+
for veg_index in veg_indices:
|
| 323 |
+
mosaic_veg_index = collection.qualityMosaic(veg_index)
|
| 324 |
+
fc = geemap.zonal_stats(
|
| 325 |
+
mosaic_veg_index, ee_feature_collection, scale=attrs["scale"], return_fc=True
|
| 326 |
+
).getInfo()
|
| 327 |
+
mean_veg_index = fc["features"][0]["properties"][veg_index]
|
| 328 |
+
bucket[veg_index] = mean_veg_index
|
| 329 |
+
fc = geemap.zonal_stats(
|
| 330 |
+
mosaic_veg_index, buffer_ee_feature_collection, scale=attrs["scale"], return_fc=True
|
| 331 |
+
).getInfo()
|
| 332 |
+
buffer_mean_veg_index = fc["features"][0]["properties"][veg_index]
|
| 333 |
+
bucket[f"{veg_index}_buffer"] = buffer_mean_veg_index
|
| 334 |
+
bucket[f"{veg_index}_ratio"] = mean_veg_index / buffer_mean_veg_index
|
| 335 |
+
bucket[f"mosaic_{veg_index}"] = mosaic_veg_index
|
| 336 |
+
|
| 337 |
+
# Get median mosaic
|
| 338 |
+
bucket["mosaic_visual_max_ndvi"] = collection.qualityMosaic("NDVI")
|
| 339 |
+
bucket["mosaic_visual_median"] = collection.median()
|
| 340 |
+
bucket["image_visual_least_cloud"] = collection.sort("CLOUDY_PIXEL_PERCENTAGE").first()
|
| 341 |
+
|
| 342 |
+
if satellite == "COPERNICUS/S2_SR_HARMONIZED":
|
| 343 |
+
cloud_mask_probability = fc["features"][0]["properties"]["MSK_CLDPRB"] / 100
|
| 344 |
+
else:
|
| 345 |
+
cloud_mask_probability = None
|
| 346 |
+
bucket["Cloud (0 to 1)"] = cloud_mask_probability
|
| 347 |
+
result_df.loc[daterange_str, list(bucket.keys())] = list(bucket.values())
|
| 348 |
+
count = collection.size().getInfo()
|
| 349 |
+
suffix = f" - Processed {count} images"
|
| 350 |
+
write_info(f"{prefix}{suffix}")
|
| 351 |
+
except Exception as e:
|
| 352 |
+
print(e)
|
| 353 |
+
suffix = f" - Imagery not available"
|
| 354 |
+
write_info(f"{prefix}{suffix}")
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
def write_info(info):
|
| 358 |
+
st.write(f"<span style='color:#006400;'>{info}</span>", unsafe_allow_html=True)
|
wayback.csv
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Title,Identifier,LowerCorner,UpperCorner,Format,TileMatrixSetLinks,ResourceURL_Template
|
| 2 |
+
World Imagery (Wayback 2024-10-10),WB_2024_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/56450/{TileMatrix}/{TileRow}/{TileCol}
|
| 3 |
+
World Imagery (Wayback 2024-09-19),WB_2024_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/20337/{TileMatrix}/{TileRow}/{TileCol}
|
| 4 |
+
World Imagery (Wayback 2024-08-15),WB_2024_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/32553/{TileMatrix}/{TileRow}/{TileCol}
|
| 5 |
+
World Imagery (Wayback 2024-06-27),WB_2024_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/39767/{TileMatrix}/{TileRow}/{TileCol}
|
| 6 |
+
World Imagery (Wayback 2024-06-06),WB_2024_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/12428/{TileMatrix}/{TileRow}/{TileCol}
|
| 7 |
+
World Imagery (Wayback 2024-05-09),WB_2024_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/52930/{TileMatrix}/{TileRow}/{TileCol}
|
| 8 |
+
World Imagery (Wayback 2024-03-28),WB_2024_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13968/{TileMatrix}/{TileRow}/{TileCol}
|
| 9 |
+
World Imagery (Wayback 2024-03-07),WB_2024_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/60013/{TileMatrix}/{TileRow}/{TileCol}
|
| 10 |
+
World Imagery (Wayback 2024-02-08),WB_2024_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/37965/{TileMatrix}/{TileRow}/{TileCol}
|
| 11 |
+
World Imagery (Wayback 2024-01-18),WB_2024_R00,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/41468/{TileMatrix}/{TileRow}/{TileCol}
|
| 12 |
+
World Imagery (Wayback 2023-12-07),WB_2023_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/56102/{TileMatrix}/{TileRow}/{TileCol}
|
| 13 |
+
World Imagery (Wayback 2023-11-01),WB_2023_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/12457/{TileMatrix}/{TileRow}/{TileCol}
|
| 14 |
+
World Imagery (Wayback 2023-10-11),WB_2023_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/1034/{TileMatrix}/{TileRow}/{TileCol}
|
| 15 |
+
World Imagery (Wayback 2023-08-31),WB_2023_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/64776/{TileMatrix}/{TileRow}/{TileCol}
|
| 16 |
+
World Imagery (Wayback 2023-08-10),WB_2023_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/17632/{TileMatrix}/{TileRow}/{TileCol}
|
| 17 |
+
World Imagery (Wayback 2023-06-29),WB_2023_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/47963/{TileMatrix}/{TileRow}/{TileCol}
|
| 18 |
+
World Imagery (Wayback 2023-06-13),WB_2023_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/25982/{TileMatrix}/{TileRow}/{TileCol}
|
| 19 |
+
World Imagery (Wayback 2023-05-03),WB_2023_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/46399/{TileMatrix}/{TileRow}/{TileCol}
|
| 20 |
+
World Imagery (Wayback 2023-04-05),WB_2023_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/37890/{TileMatrix}/{TileRow}/{TileCol}
|
| 21 |
+
World Imagery (Wayback 2023-03-15),WB_2023_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/44873/{TileMatrix}/{TileRow}/{TileCol}
|
| 22 |
+
World Imagery (Wayback 2023-02-23),WB_2023_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/57965/{TileMatrix}/{TileRow}/{TileCol}
|
| 23 |
+
World Imagery (Wayback 2023-01-11),WB_2023_R00,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11475/{TileMatrix}/{TileRow}/{TileCol}
|
| 24 |
+
World Imagery (Wayback 2022-12-14),WB_2022_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/45134/{TileMatrix}/{TileRow}/{TileCol}
|
| 25 |
+
World Imagery (Wayback 2022-11-02),WB_2022_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/7110/{TileMatrix}/{TileRow}/{TileCol}
|
| 26 |
+
World Imagery (Wayback 2022-10-12),WB_2022_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/44988/{TileMatrix}/{TileRow}/{TileCol}
|
| 27 |
+
World Imagery (Wayback 2022-09-21),WB_2022_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/47471/{TileMatrix}/{TileRow}/{TileCol}
|
| 28 |
+
World Imagery (Wayback 2022-08-31),WB_2022_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/45441/{TileMatrix}/{TileRow}/{TileCol}
|
| 29 |
+
World Imagery (Wayback 2022-08-10),WB_2022_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/17825/{TileMatrix}/{TileRow}/{TileCol}
|
| 30 |
+
World Imagery (Wayback 2022-07-20),WB_2022_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13851/{TileMatrix}/{TileRow}/{TileCol}
|
| 31 |
+
World Imagery (Wayback 2022-06-29),WB_2022_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/4905/{TileMatrix}/{TileRow}/{TileCol}
|
| 32 |
+
World Imagery (Wayback 2022-06-08),WB_2022_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/44710/{TileMatrix}/{TileRow}/{TileCol}
|
| 33 |
+
World Imagery (Wayback 2022-05-18),WB_2022_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5314/{TileMatrix}/{TileRow}/{TileCol}
|
| 34 |
+
World Imagery (Wayback 2022-04-27),WB_2022_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/16245/{TileMatrix}/{TileRow}/{TileCol}
|
| 35 |
+
World Imagery (Wayback 2022-04-06),WB_2022_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/48232/{TileMatrix}/{TileRow}/{TileCol}
|
| 36 |
+
World Imagery (Wayback 2022-03-16),WB_2022_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/10321/{TileMatrix}/{TileRow}/{TileCol}
|
| 37 |
+
World Imagery (Wayback 2022-02-24),WB_2022_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/10312/{TileMatrix}/{TileRow}/{TileCol}
|
| 38 |
+
World Imagery (Wayback 2022-02-02),WB_2022_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/26083/{TileMatrix}/{TileRow}/{TileCol}
|
| 39 |
+
World Imagery (Wayback 2022-01-12),WB_2022_R00,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/42663/{TileMatrix}/{TileRow}/{TileCol}
|
| 40 |
+
World Imagery (Wayback 2021-12-21),WB_2021_R17,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/26120/{TileMatrix}/{TileRow}/{TileCol}
|
| 41 |
+
World Imagery (Wayback 2021-11-30),WB_2021_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/48624/{TileMatrix}/{TileRow}/{TileCol}
|
| 42 |
+
World Imagery (Wayback 2021-11-03),WB_2021_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/42403/{TileMatrix}/{TileRow}/{TileCol}
|
| 43 |
+
World Imagery (Wayback 2021-10-13),WB_2021_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/16749/{TileMatrix}/{TileRow}/{TileCol}
|
| 44 |
+
World Imagery (Wayback 2021-09-22),WB_2021_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/51313/{TileMatrix}/{TileRow}/{TileCol}
|
| 45 |
+
World Imagery (Wayback 2021-09-01),WB_2021_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/47568/{TileMatrix}/{TileRow}/{TileCol}
|
| 46 |
+
World Imagery (Wayback 2021-08-11),WB_2021_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/51423/{TileMatrix}/{TileRow}/{TileCol}
|
| 47 |
+
World Imagery (Wayback 2021-07-21),WB_2021_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/8432/{TileMatrix}/{TileRow}/{TileCol}
|
| 48 |
+
World Imagery (Wayback 2021-06-30),WB_2021_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13534/{TileMatrix}/{TileRow}/{TileCol}
|
| 49 |
+
World Imagery (Wayback 2021-06-09),WB_2021_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/48376/{TileMatrix}/{TileRow}/{TileCol}
|
| 50 |
+
World Imagery (Wayback 2021-05-19),WB_2021_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/15423/{TileMatrix}/{TileRow}/{TileCol}
|
| 51 |
+
World Imagery (Wayback 2021-04-28),WB_2021_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/27659/{TileMatrix}/{TileRow}/{TileCol}
|
| 52 |
+
World Imagery (Wayback 2021-04-08),WB_2021_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/6863/{TileMatrix}/{TileRow}/{TileCol}
|
| 53 |
+
World Imagery (Wayback 2021-03-17),WB_2021_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5359/{TileMatrix}/{TileRow}/{TileCol}
|
| 54 |
+
World Imagery (Wayback 2021-02-24),WB_2021_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9812/{TileMatrix}/{TileRow}/{TileCol}
|
| 55 |
+
World Imagery (Wayback 2021-01-13),WB_2021_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/1049/{TileMatrix}/{TileRow}/{TileCol}
|
| 56 |
+
World Imagery (Wayback 2020-12-16),WB_2020_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/29260/{TileMatrix}/{TileRow}/{TileCol}
|
| 57 |
+
World Imagery (Wayback 2020-11-18),WB_2020_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/20753/{TileMatrix}/{TileRow}/{TileCol}
|
| 58 |
+
World Imagery (Wayback 2020-10-14),WB_2020_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/119/{TileMatrix}/{TileRow}/{TileCol}
|
| 59 |
+
World Imagery (Wayback 2020-09-23),WB_2020_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/19187/{TileMatrix}/{TileRow}/{TileCol}
|
| 60 |
+
World Imagery (Wayback 2020-09-02),WB_2020_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9181/{TileMatrix}/{TileRow}/{TileCol}
|
| 61 |
+
World Imagery (Wayback 2020-08-12),WB_2020_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/6049/{TileMatrix}/{TileRow}/{TileCol}
|
| 62 |
+
World Imagery (Wayback 2020-07-22),WB_2020_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9549/{TileMatrix}/{TileRow}/{TileCol}
|
| 63 |
+
World Imagery (Wayback 2020-07-01),WB_2020_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/18289/{TileMatrix}/{TileRow}/{TileCol}
|
| 64 |
+
World Imagery (Wayback 2020-06-10),WB_2020_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11135/{TileMatrix}/{TileRow}/{TileCol}
|
| 65 |
+
World Imagery (Wayback 2020-05-20),WB_2020_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/32645/{TileMatrix}/{TileRow}/{TileCol}
|
| 66 |
+
World Imagery (Wayback 2020-04-29),WB_2020_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/15045/{TileMatrix}/{TileRow}/{TileCol}
|
| 67 |
+
World Imagery (Wayback 2020-04-08),WB_2020_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/26751/{TileMatrix}/{TileRow}/{TileCol}
|
| 68 |
+
World Imagery (Wayback 2020-03-23),WB_2020_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/16062/{TileMatrix}/{TileRow}/{TileCol}
|
| 69 |
+
World Imagery (Wayback 2020-02-20),WB_2020_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/8495/{TileMatrix}/{TileRow}/{TileCol}
|
| 70 |
+
World Imagery (Wayback 2020-01-30),WB_2020_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/21485/{TileMatrix}/{TileRow}/{TileCol}
|
| 71 |
+
World Imagery (Wayback 2020-01-08),WB_2020_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/23001/{TileMatrix}/{TileRow}/{TileCol}
|
| 72 |
+
World Imagery (Wayback 2019-12-12),WB_2019_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/4756/{TileMatrix}/{TileRow}/{TileCol}
|
| 73 |
+
World Imagery (Wayback 2019-10-30),WB_2019_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11060/{TileMatrix}/{TileRow}/{TileCol}
|
| 74 |
+
World Imagery (Wayback 2019-10-09),WB_2019_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11351/{TileMatrix}/{TileRow}/{TileCol}
|
| 75 |
+
World Imagery (Wayback 2019-09-18),WB_2019_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9892/{TileMatrix}/{TileRow}/{TileCol}
|
| 76 |
+
World Imagery (Wayback 2019-08-28),WB_2019_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/30442/{TileMatrix}/{TileRow}/{TileCol}
|
| 77 |
+
World Imagery (Wayback 2019-08-07),WB_2019_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/17216/{TileMatrix}/{TileRow}/{TileCol}
|
| 78 |
+
World Imagery (Wayback 2019-07-17),WB_2019_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/16681/{TileMatrix}/{TileRow}/{TileCol}
|
| 79 |
+
World Imagery (Wayback 2019-06-26),WB_2019_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/645/{TileMatrix}/{TileRow}/{TileCol}
|
| 80 |
+
World Imagery (Wayback 2019-06-05),WB_2019_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/12576/{TileMatrix}/{TileRow}/{TileCol}
|
| 81 |
+
World Imagery (Wayback 2019-05-15),WB_2019_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9598/{TileMatrix}/{TileRow}/{TileCol}
|
| 82 |
+
World Imagery (Wayback 2019-04-24),WB_2019_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/18063/{TileMatrix}/{TileRow}/{TileCol}
|
| 83 |
+
World Imagery (Wayback 2019-04-03),WB_2019_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/18691/{TileMatrix}/{TileRow}/{TileCol}
|
| 84 |
+
World Imagery (Wayback 2019-03-13),WB_2019_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/4383/{TileMatrix}/{TileRow}/{TileCol}
|
| 85 |
+
World Imagery (Wayback 2019-02-21),WB_2019_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/17677/{TileMatrix}/{TileRow}/{TileCol}
|
| 86 |
+
World Imagery (Wayback 2019-01-31),WB_2019_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/25944/{TileMatrix}/{TileRow}/{TileCol}
|
| 87 |
+
World Imagery (Wayback 2019-01-09),WB_2019_R00,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/6036/{TileMatrix}/{TileRow}/{TileCol}
|
| 88 |
+
World Imagery (Wayback 2018-12-14),WB_2018_R17,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/23448/{TileMatrix}/{TileRow}/{TileCol}
|
| 89 |
+
World Imagery (Wayback 2018-11-29),WB_2018_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/239/{TileMatrix}/{TileRow}/{TileCol}
|
| 90 |
+
World Imagery (Wayback 2018-11-07),WB_2018_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/3201/{TileMatrix}/{TileRow}/{TileCol}
|
| 91 |
+
World Imagery (Wayback 2018-10-17),WB_2018_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/18820/{TileMatrix}/{TileRow}/{TileCol}
|
| 92 |
+
World Imagery (Wayback 2018-09-26),WB_2018_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/14426/{TileMatrix}/{TileRow}/{TileCol}
|
| 93 |
+
World Imagery (Wayback 2018-09-06),WB_2018_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/2168/{TileMatrix}/{TileRow}/{TileCol}
|
| 94 |
+
World Imagery (Wayback 2018-08-15),WB_2018_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/1858/{TileMatrix}/{TileRow}/{TileCol}
|
| 95 |
+
World Imagery (Wayback 2018-07-25),WB_2018_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/14829/{TileMatrix}/{TileRow}/{TileCol}
|
| 96 |
+
World Imagery (Wayback 2018-06-27),WB_2018_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11334/{TileMatrix}/{TileRow}/{TileCol}
|
| 97 |
+
World Imagery (Wayback 2018-06-06),WB_2018_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/8249/{TileMatrix}/{TileRow}/{TileCol}
|
| 98 |
+
World Imagery (Wayback 2018-05-16),WB_2018_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/32337/{TileMatrix}/{TileRow}/{TileCol}
|
| 99 |
+
World Imagery (Wayback 2018-04-25),WB_2018_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/1296/{TileMatrix}/{TileRow}/{TileCol}
|
| 100 |
+
World Imagery (Wayback 2018-04-11),WB_2018_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/20399/{TileMatrix}/{TileRow}/{TileCol}
|
| 101 |
+
World Imagery (Wayback 2018-03-28),WB_2018_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/7072/{TileMatrix}/{TileRow}/{TileCol}
|
| 102 |
+
World Imagery (Wayback 2018-03-14),WB_2018_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/8255/{TileMatrix}/{TileRow}/{TileCol}
|
| 103 |
+
World Imagery (Wayback 2018-02-23),WB_2018_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13067/{TileMatrix}/{TileRow}/{TileCol}
|
| 104 |
+
World Imagery (Wayback 2018-01-31),WB_2018_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/10768/{TileMatrix}/{TileRow}/{TileCol}
|
| 105 |
+
World Imagery (Wayback 2018-01-18),WB_2018_R00,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13045/{TileMatrix}/{TileRow}/{TileCol}
|
| 106 |
+
World Imagery (Wayback 2018-01-08),WB_2017_R21,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13161/{TileMatrix}/{TileRow}/{TileCol}
|
| 107 |
+
World Imagery (Wayback 2017-11-16),WB_2017_R19,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/25521/{TileMatrix}/{TileRow}/{TileCol}
|
| 108 |
+
World Imagery (Wayback 2017-10-25),WB_2017_R18,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/23264/{TileMatrix}/{TileRow}/{TileCol}
|
| 109 |
+
World Imagery (Wayback 2017-10-04),WB_2017_R17,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/15212/{TileMatrix}/{TileRow}/{TileCol}
|
| 110 |
+
World Imagery (Wayback 2017-09-13),WB_2017_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/18358/{TileMatrix}/{TileRow}/{TileCol}
|
| 111 |
+
World Imagery (Wayback 2017-08-30),WB_2017_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/25379/{TileMatrix}/{TileRow}/{TileCol}
|
| 112 |
+
World Imagery (Wayback 2017-08-10),WB_2017_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/14035/{TileMatrix}/{TileRow}/{TileCol}
|
| 113 |
+
World Imagery (Wayback 2017-07-14),WB_2017_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/3319/{TileMatrix}/{TileRow}/{TileCol}
|
| 114 |
+
World Imagery (Wayback 2017-06-27),WB_2017_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/4073/{TileMatrix}/{TileRow}/{TileCol}
|
| 115 |
+
World Imagery (Wayback 2017-06-14),WB_2017_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/14765/{TileMatrix}/{TileRow}/{TileCol}
|
| 116 |
+
World Imagery (Wayback 2017-05-31),WB_2017_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/14342/{TileMatrix}/{TileRow}/{TileCol}
|
| 117 |
+
World Imagery (Wayback 2017-05-17),WB_2017_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/20365/{TileMatrix}/{TileRow}/{TileCol}
|
| 118 |
+
World Imagery (Wayback 2017-05-03),WB_2017_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/784/{TileMatrix}/{TileRow}/{TileCol}
|
| 119 |
+
World Imagery (Wayback 2017-04-19),WB_2017_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/1052/{TileMatrix}/{TileRow}/{TileCol}
|
| 120 |
+
World Imagery (Wayback 2017-03-29),WB_2017_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5205/{TileMatrix}/{TileRow}/{TileCol}
|
| 121 |
+
World Imagery (Wayback 2017-03-15),WB_2017_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/29387/{TileMatrix}/{TileRow}/{TileCol}
|
| 122 |
+
World Imagery (Wayback 2017-02-27),WB_2017_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/31026/{TileMatrix}/{TileRow}/{TileCol}
|
| 123 |
+
World Imagery (Wayback 2017-02-08),WB_2017_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/27946/{TileMatrix}/{TileRow}/{TileCol}
|
| 124 |
+
World Imagery (Wayback 2017-01-25),WB_2017_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9486/{TileMatrix}/{TileRow}/{TileCol}
|
| 125 |
+
World Imagery (Wayback 2017-01-11),WB_2017_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/577/{TileMatrix}/{TileRow}/{TileCol}
|
| 126 |
+
World Imagery (Wayback 2016-12-20),WB_2016_R22,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/18966/{TileMatrix}/{TileRow}/{TileCol}
|
| 127 |
+
World Imagery (Wayback 2016-12-07),WB_2016_R21,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/6678/{TileMatrix}/{TileRow}/{TileCol}
|
| 128 |
+
World Imagery (Wayback 2016-11-16),WB_2016_R20,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/21750/{TileMatrix}/{TileRow}/{TileCol}
|
| 129 |
+
World Imagery (Wayback 2016-10-25),WB_2016_R19,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/4222/{TileMatrix}/{TileRow}/{TileCol}
|
| 130 |
+
World Imagery (Wayback 2016-10-12),WB_2016_R18,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13770/{TileMatrix}/{TileRow}/{TileCol}
|
| 131 |
+
World Imagery (Wayback 2016-09-14),WB_2016_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/6984/{TileMatrix}/{TileRow}/{TileCol}
|
| 132 |
+
World Imagery (Wayback 2016-08-31),WB_2016_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9175/{TileMatrix}/{TileRow}/{TileCol}
|
| 133 |
+
World Imagery (Wayback 2016-08-11),WB_2016_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/23601/{TileMatrix}/{TileRow}/{TileCol}
|
| 134 |
+
World Imagery (Wayback 2016-07-20),WB_2016_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5097/{TileMatrix}/{TileRow}/{TileCol}
|
| 135 |
+
World Imagery (Wayback 2016-07-06),WB_2016_R12,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/13240/{TileMatrix}/{TileRow}/{TileCol}
|
| 136 |
+
World Imagery (Wayback 2016-06-13),WB_2016_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11509/{TileMatrix}/{TileRow}/{TileCol}
|
| 137 |
+
World Imagery (Wayback 2016-05-11),WB_2016_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/8551/{TileMatrix}/{TileRow}/{TileCol}
|
| 138 |
+
World Imagery (Wayback 2016-04-28),WB_2016_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5769/{TileMatrix}/{TileRow}/{TileCol}
|
| 139 |
+
World Imagery (Wayback 2016-04-20),WB_2016_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/388/{TileMatrix}/{TileRow}/{TileCol}
|
| 140 |
+
World Imagery (Wayback 2016-03-16),WB_2016_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/19085/{TileMatrix}/{TileRow}/{TileCol}
|
| 141 |
+
World Imagery (Wayback 2016-03-02),WB_2016_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/20443/{TileMatrix}/{TileRow}/{TileCol}
|
| 142 |
+
World Imagery (Wayback 2016-02-17),WB_2016_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11262/{TileMatrix}/{TileRow}/{TileCol}
|
| 143 |
+
World Imagery (Wayback 2016-02-04),WB_2016_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/6354/{TileMatrix}/{TileRow}/{TileCol}
|
| 144 |
+
World Imagery (Wayback 2016-01-13),WB_2016_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/3515/{TileMatrix}/{TileRow}/{TileCol}
|
| 145 |
+
World Imagery (Wayback 2015-12-16),WB_2015_R23,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/28163/{TileMatrix}/{TileRow}/{TileCol}
|
| 146 |
+
World Imagery (Wayback 2015-11-18),WB_2015_R20,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/8781/{TileMatrix}/{TileRow}/{TileCol}
|
| 147 |
+
World Imagery (Wayback 2015-10-28),WB_2015_R18,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11092/{TileMatrix}/{TileRow}/{TileCol}
|
| 148 |
+
World Imagery (Wayback 2015-10-14),WB_2015_R17,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/10850/{TileMatrix}/{TileRow}/{TileCol}
|
| 149 |
+
World Imagery (Wayback 2015-09-30),WB_2015_R16,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/3630/{TileMatrix}/{TileRow}/{TileCol}
|
| 150 |
+
World Imagery (Wayback 2015-09-16),WB_2015_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/1431/{TileMatrix}/{TileRow}/{TileCol}
|
| 151 |
+
World Imagery (Wayback 2015-09-02),WB_2015_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/30584/{TileMatrix}/{TileRow}/{TileCol}
|
| 152 |
+
World Imagery (Wayback 2015-08-19),WB_2015_R13,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/28219/{TileMatrix}/{TileRow}/{TileCol}
|
| 153 |
+
World Imagery (Wayback 2015-07-08),WB_2015_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/24007/{TileMatrix}/{TileRow}/{TileCol}
|
| 154 |
+
World Imagery (Wayback 2015-06-24),WB_2015_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11952/{TileMatrix}/{TileRow}/{TileCol}
|
| 155 |
+
World Imagery (Wayback 2015-05-13),WB_2015_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/19930/{TileMatrix}/{TileRow}/{TileCol}
|
| 156 |
+
World Imagery (Wayback 2015-04-30),WB_2015_R07,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/23880/{TileMatrix}/{TileRow}/{TileCol}
|
| 157 |
+
World Imagery (Wayback 2015-04-15),WB_2015_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/9203/{TileMatrix}/{TileRow}/{TileCol}
|
| 158 |
+
World Imagery (Wayback 2015-03-25),WB_2015_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/2730/{TileMatrix}/{TileRow}/{TileCol}
|
| 159 |
+
World Imagery (Wayback 2015-03-18),WB_2015_R04,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/15084/{TileMatrix}/{TileRow}/{TileCol}
|
| 160 |
+
World Imagery (Wayback 2015-02-18),WB_2015_R02,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/10443/{TileMatrix}/{TileRow}/{TileCol}
|
| 161 |
+
World Imagery (Wayback 2015-01-21),WB_2015_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/20222/{TileMatrix}/{TileRow}/{TileCol}
|
| 162 |
+
World Imagery (Wayback 2014-12-30),WB_2014_R21,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5844/{TileMatrix}/{TileRow}/{TileCol}
|
| 163 |
+
World Imagery (Wayback 2014-12-18),WB_2014_R20,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/14720/{TileMatrix}/{TileRow}/{TileCol}
|
| 164 |
+
World Imagery (Wayback 2014-12-03),WB_2014_R19,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/23383/{TileMatrix}/{TileRow}/{TileCol}
|
| 165 |
+
World Imagery (Wayback 2014-11-12),WB_2014_R18,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/30195/{TileMatrix}/{TileRow}/{TileCol}
|
| 166 |
+
World Imagery (Wayback 2014-10-29),WB_2014_R17,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11019/{TileMatrix}/{TileRow}/{TileCol}
|
| 167 |
+
World Imagery (Wayback 2014-10-01),WB_2014_R15,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/22692/{TileMatrix}/{TileRow}/{TileCol}
|
| 168 |
+
World Imagery (Wayback 2014-09-17),WB_2014_R14,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/25586/{TileMatrix}/{TileRow}/{TileCol}
|
| 169 |
+
World Imagery (Wayback 2014-07-30),WB_2014_R11,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/5232/{TileMatrix}/{TileRow}/{TileCol}
|
| 170 |
+
World Imagery (Wayback 2014-07-02),WB_2014_R10,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/3026/{TileMatrix}/{TileRow}/{TileCol}
|
| 171 |
+
World Imagery (Wayback 2014-06-25),WB_2014_R09,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/11033/{TileMatrix}/{TileRow}/{TileCol}
|
| 172 |
+
World Imagery (Wayback 2014-06-11),WB_2014_R08,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/31144/{TileMatrix}/{TileRow}/{TileCol}
|
| 173 |
+
World Imagery (Wayback 2014-05-14),WB_2014_R06,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/16513/{TileMatrix}/{TileRow}/{TileCol}
|
| 174 |
+
World Imagery (Wayback 2014-04-30),WB_2014_R05,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/19819/{TileMatrix}/{TileRow}/{TileCol}
|
| 175 |
+
World Imagery (Wayback 2014-03-26),WB_2014_R03,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/4230/{TileMatrix}/{TileRow}/{TileCol}
|
| 176 |
+
World Imagery (Wayback 2014-02-20),WB_2014_R01,-2.003750722959434E7 -2.003750722959434E7,2.003750722959434E7 2.003750722959434E7,,"default028mm, GoogleMapsCompatible",https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/{TileMatrixSet}/MapServer/tile/10/{TileMatrix}/{TileRow}/{TileCol}
|
wayback.parquet
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a240ea2d4bc920e20358948a42dbe0d204f4e2240a5584dbf94a4e07b70de34f
|
| 3 |
+
size 13682
|