diff --git a/true-color-image/02 Environmental Indicators.ipynb b/true-color-image/02 Environmental Indicators.ipynb new file mode 100644 index 0000000..d9eeef3 --- /dev/null +++ b/true-color-image/02 Environmental Indicators.ipynb @@ -0,0 +1,51 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import folium\n", + "import sentinel_helpers\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# the area you want to create a true color image from; will be the first area\n", + "# returned from nominatim.openstreetmap.com\n", + "region_of_interest = 'Berlin, Germany'\n", + "\n", + "# start and end of the time span from which to select satellite data\n", + "start_date = date(2020, 7, 1)\n", + "end_date = start_date + timedelta(days=31)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/true-color-image/02a Ground Truth Comparison.ipynb b/true-color-image/02a Ground Truth Comparison.ipynb new file mode 100644 index 0000000..cb6cfcd --- /dev/null +++ b/true-color-image/02a Ground Truth Comparison.ipynb @@ -0,0 +1,32 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/true-color-image/02a NDVI.ipynb b/true-color-image/02a NDVI.ipynb index 58d1465..fdb4c74 100644 --- a/true-color-image/02a NDVI.ipynb +++ b/true-color-image/02a NDVI.ipynb @@ -53,22 +53,13 @@ "execution_count": 4, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - ":1: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n", - "\n", - " centroid = tempelhofer_feld['geometry'].centroid # <- this generates a warning about using a geographic CRS which we can ignore\n" - ] - }, { "data": { "text/html": [ - "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" ], "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -77,7 +68,14 @@ } ], "source": [ - "centroid = tempelhofer_feld['geometry'].centroid # <- this generates a warning about using a geographic CRS which we can ignore\n", + "import warnings\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.simplefilter(\"ignore\")\n", + " # ↓ this generates a warning about using a geographic CRS to calculate the\n", + " # centroid which we can safely ignore\n", + " centroid = tempelhofer_feld['geometry'].centroid\n", + "\n", "m = folium.Map([centroid.y, centroid.x], tiles='cartodbpositron')\n", "folium.GeoJson(tempelhofer_feld.to_json()).add_to(m)\n", "m.fit_bounds([[miny, minx], [maxy, maxx]])\n", @@ -91,7 +89,8 @@ "outputs": [], "source": [ "base_path = Path('input/tempelhofer_feld')\n", - "! mkdir -p {base_path}\n", + "base_path.mkdir(exist_ok=True, parents=True)\n", + "\n", "tempelhofer_feld.to_file(base_path / 'tempelhofer_feld.geojson', driver='GeoJSON')" ] }, @@ -515,7 +514,7 @@ "data": { "text/plain": [ "\n", - "[]\n", + "[]\n", "Length: 1, dtype: geometry" ] }, @@ -645,1689 +644,14 @@ "source": [ "import logging\n", "logger = logging.getLogger('sentinelsat')\n", - "logger.setLevel(logging.INFO)" + "logger.setLevel(logging.DEBUG)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7a8ca57202864d5cb6b0f021f84727e5", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1123098179.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "111aa039823c47e9aaa8f37d12cf2da2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=847344116.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f60bc265b048498c8da1b3b4b4d06787", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1123098179.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f90417927a6f4bd5b831698eb97f1cf3", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=857946380.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "22861101c94a45d7bbde67b09fd0e0a7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=847344116.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c762ece96e324442873bc9b53404a634", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=840569783.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "70038f0b16e145d5883663c32aec0ccd", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=857946380.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c06580464e7a4a738f97e6c44728129d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=840140502.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4c41db86d935423492043700c2f6bebf", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=840140502.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c87b6d1fec374ebb9911717538373def", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1147907682.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d69b2f22faef4be6852f1a8d8670e5db", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=840569783.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "16122177724545959b20340890f149bc", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1171722124.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "088acbc5f1d84e83af4789e87600adc2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1147907682.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7a9e53835ac8449191327464aaab23a8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=851533846.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "36965636e56744d5a15d9d48b86e5113", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1171722124.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "38eb20ef0c604e919e48ab19b0ddc5f5", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=868583216.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "887e34b11a1c4e228298bb8b8ca934f8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=851533846.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9de26c0592704e839e9bbf13ccd261d7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=807845214.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b52d9ebd6d4a4ac4b4b2daee46be5488", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=807845214.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "bdd0ad5c188f411ea3e1dd239d19a93d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=827275912.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "715a95cf07494a2c855d345730dc6442", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=868583216.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "718de482a5d7429c8737c8734c6cf58f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1172159462.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2d1eeee5d8e541c6a2f39cacae9a0eb4", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=827275912.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "37c29099f0fc4210985dd09cec35ae86", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=39418123.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a63110c680f44009a7aa287e975a18d2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=39418123.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "08ae5497f6bd4cb492e6a0dbf4e41a17", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=811488530.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f6ba27f573604d7fb3f3d6b353f09f77", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1172159462.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d7092e0233964de289d9a999703bffe1", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1162034273.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a3d30b8f241a4e9eb03456786c01759a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=811488530.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c6044ce5e607431499fd896d93eca3c0", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=885317435.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f6ecdb1ceaf243fe9ea80f52b2d68737", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=885317435.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ea009351da1542d2a3d3493f6091fdfe", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=862342013.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1459bb893aed4c89b11b4430bf43de33", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1162034273.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c4ebdfcd1c2c4742a40e2c2f71c6a4de", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=862525495.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "13d318e1b5574deb8f25f441e11a3159", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=862342013.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "656384232c5740658ce575b4e8b1a0be", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1154911729.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "07cadb783881491fa8a36dfb123c1b85", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=862525495.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6e8927b3bcf141588ec3b6b92ac49c61", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1161524112.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a8fedb7fbba449309530ad4a0e3278ee", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1154911729.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ee8189f29c3241c089183657fb569415", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=26189371.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a51b38ef8fe446b6b055ee3b7bf60819", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=26189371.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "65a6d217d19f43599db094039ec4c3ea", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=36032131.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1200ab0a49184d318eb2a29695b605de", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=36032131.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3374eb13a6794279ac0b6bae9426f993", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=43597371.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "be3c04c3d53b45079939700685796570", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=43597371.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "55e64949183a4c008db371c3fd11d8cd", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1181807217.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "bd8ff730c168483e9ea88f36eca8f8a3", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1161524112.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "541409f526134aae81008c2a66221223", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=804489730.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "313652be61114341956edaf029876047", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1181807217.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3c674e88942749b28f554579d95ea055", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=826662355.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7cc38755fb924b13a1e7edda2a542c54", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=804489730.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f4fe30b35c3e49f89835b4efe2a94f8e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=29408824.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "972fde806ace47e399275f07cabd4bec", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=29408824.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "492e30905c744020a7eb7c137749ed1f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=30694971.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "15088b63e1ed49ed8973de8ab9762cdc", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=30694971.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f12b01c113fe40dcb0b15a34c5ea477c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1146261965.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "503ed2f348344e1bb65ceb13a0af2873", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=826662355.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "870abb136e874dc09f33867f25f28d78", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=31833659.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "be209afb6ea9429bb0e27f0e0bd6ff64", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=31833659.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5b496617236f4133855b0b4201584e2a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1155565213.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "68085496e2284bd8b242757657707e5d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1146261965.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "81ee29e85ff2410dafc847a75d6c430a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=789506436.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a1d6a466012c479cb07a6ce064564f49", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1155565213.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7c782dab0e51457284c5103fcef2a8cf", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=44727864.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "15d8c1dcf1634606a9dd0d41063c304f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=44727864.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2003cc336f0144a98269ded3022bb238", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=31399483.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1820d983a97d4684814c0213dc364f39", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=31399483.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f8ccf1e70d9a4e01884a1fea6d79eef2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=1148131138.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3934ea5166284092bf40ea8436eff0ba", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=789506436.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4a1c3f1a386446db8ad56dfb97b9923b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=802872306.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f888e3e5b4cb432785044c1c53e9b510", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=1148131138.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0b3877781a5540f1b8b92699d1bf1118", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=797592039.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "54ce9071f40742b9bd47c81145335cc9", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=802872306.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "96d29d1f66bc4e03bad5825d6afc8feb", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=800527096.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "eb409f0f941f4c73862adca3af25fc41", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=797592039.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "37aed5880aa843d180c0afd0b3c31112", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=30211641.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "798978a7a4894772981ab806840183e5", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=30211641.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "bb278a0735b94f7aaa6598dfebb96c4d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='Downloading'), FloatProgress(value=0.0, max=758033222.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "059058109be0452b826e702d9e2a5e05", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=800527096.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "143b5534783d4ec8a06c8ed70194deec", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value='MD5 checksumming'), FloatProgress(value=0.0, max=758033222.0), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ "downloaded, triggered, failed = api.download_all(deduped['uuid'].values, directory_path=base_path.absolute())" ] @@ -2379,21 +703,30 @@ "cell_type": "code", "execution_count": 21, "metadata": {}, + "outputs": [], + "source": [ + "product_paths = list(map(lambda x: x['path'], downloaded.values()))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "('zip+file:///home/jovyan/true-color-image/input/tempelhofer_feld_next_try/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.zip!/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.SAFE/GRANULE/L2A_T33UUU_A023371_20191213T102424/IMG_DATA/R10m/T33UUU_20191213T102421_B04_10m.jp2',\n", - " 'zip+file:///home/jovyan/true-color-image/input/tempelhofer_feld_next_try/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.zip!/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.SAFE/GRANULE/L2A_T33UUU_A023371_20191213T102424/IMG_DATA/R10m/T33UUU_20191213T102421_B08_10m.jp2')" + "('zip+file:///home/jovyan/true-color-image/input/tempelhofer_feld/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.zip!/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.SAFE/GRANULE/L2A_T33UUU_A023371_20191213T102424/IMG_DATA/R10m/T33UUU_20191213T102421_B04_10m.jp2',\n", + " 'zip+file:///home/jovyan/true-color-image/input/tempelhofer_feld/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.zip!/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.SAFE/GRANULE/L2A_T33UUU_A023371_20191213T102424/IMG_DATA/R10m/T33UUU_20191213T102421_B08_10m.jp2')" ] }, - "execution_count": 21, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "b04_path, b08_path = sentinel_helpers.scihub_band_paths(list(downloaded.values())[0]['path'], ['B04', 'B08'], '10m')\n", + "b04_path, b08_path = sentinel_helpers.scihub_band_paths(product_paths[0], ['B04', 'B08'], '10m')\n", "b04_path, b08_path" ] }, @@ -2410,17 +743,35 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "subset_path = base_path / 'subset'\n", - "! mkdir -p {subset_path}" + "subset_path.mkdir(exist_ok=True, parents=True)" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.8/site-packages/geopandas/geodataframe.py:422: RuntimeWarning: Sequential read of iterator was interrupted. Resetting iterator. This can negatively impact the performance.\n", + " for feature in features_lst:\n" + ] + } + ], + "source": [ + "cloud_mask = sentinel_helpers.scihub_cloud_mask(product_paths[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ @@ -2440,7 +791,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 30, "metadata": {}, "outputs": [ { @@ -2486,8 +837,8 @@ " out_meta = b04.meta.copy()\n", " \n", " # we reproject the geojson file we fetched above and convert it so that rasterio\n", - " # can use it as a mask\n", - " mask = tempelhofer_feld.to_crs(out_meta['crs']).iloc[0].geometry\n", + " # can use it as a mask; we subtract the cloud mask\n", + " mask = (tempelhofer_feld.to_crs(out_meta['crs']).iloc[0].geometry - cloud_mask)\n", " miny, minx, maxy, maxx = mask.bounds\n", " \n", " # update the dimensions and save as geotiff, not jp2\n", @@ -2499,8 +850,10 @@ " }) \n", " out_name = Path(b04_path).name.replace('B04', 'NDVI').replace('.jp2', '.tif')\n", " \n", - " ! mkdir -p output\n", - " with r.open(Path('output') / out_name, 'w+', **out_meta) as dst:\n", + " output_path = Path('output') / out_name\n", + " output_path.parent.mkdir(exist_ok=True, parents=True)\n", + " \n", + " with r.open(output_path, 'w+', **out_meta) as dst:\n", " # we take only the part out of our source raster that we actually need\n", " # crop=True clips off the borders\n", " b04, transform_b04 = rasterio.mask.mask(b04, shapes=[mask], crop=True)\n", diff --git a/true-color-image/02b Timeseries.ipynb b/true-color-image/02b Timeseries.ipynb index fc876a4..9eaea17 100644 --- a/true-color-image/02b Timeseries.ipynb +++ b/true-color-image/02b Timeseries.ipynb @@ -21,7 +21,7 @@ "base_path = Path('input/tempelhofer_feld/')\n", "input_files = list(base_path.glob('*.zip'))\n", "area_of_interest = gpd.read_file(base_path / 'tempelhofer_feld.geojson')\n", - "ndvi_path = base_path / 'ndvi'" + "ndvi_path = Path('output') / 'ndvi'" ] }, { @@ -34,7 +34,7 @@ "import rasterio.mask\n", "import rasterio.plot as rplt\n", "import numpy as np\n", - "from sentinel_helpers import scihub_normalize_range\n", + "from sentinel_helpers import scihub_normalize_range, scihub_cloud_mask\n", "from zipfile import BadZipFile" ] }, @@ -44,13 +44,25 @@ "metadata": {}, "outputs": [], "source": [ - "def calculate_ndvi(raster_file):\n", + "# uncomment this cell to remove previous calculations\n", + "# ! rm -rf {ndvi_path / '*.tif'}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_ndvi(product_path):\n", " global area_of_interest\n", " \n", " try:\n", - " b04_path, b08_path = scihub_band_paths(raster_file, ['B04', 'B08'], '10m')\n", + " b04_path, b08_path = scihub_band_paths(product_path, ['B04', 'B08'], '10m')\n", + " cloud_mask = scihub_cloud_mask(product_path)\n", " except BadZipFile:\n", - " print(f'Problem reading {raster_file}, skipping it')\n", + " # This is due to a problem of Scihub\n", + " print(f'{product_path}: Problem reading product, skipping it')\n", " return\n", "\n", " with r.open(b04_path, 'r') as b04, r.open(b08_path, 'r') as b08:\n", @@ -58,10 +70,16 @@ " out_meta = b04.meta.copy()\n", "\n", " # we reproject the geojson file we fetched above and convert it so that rasterio\n", - " # can use it as a mask\n", - " mask = area_of_interest.to_crs(out_meta['crs']).iloc[0].geometry\n", + " # can use it as a mask; we subtract the cloud mask to avoid irregularities\n", + " reprojected = area_of_interest.to_crs(out_meta['crs']).iloc[0].geometry\n", + " mask = reprojected.difference(cloud_mask)\n", + " \n", + " if mask.area / reprojected.area < 0.25:\n", + " print(f'{product_path}: Area is covered by clouds, skipping it')\n", + " return\n", + " \n", " miny, minx, maxy, maxx = mask.bounds\n", - "\n", + " \n", " # update the dimensions and save as geotiff, not jp2\n", " out_meta.update({\n", " 'width': maxx - minx,\n", @@ -69,14 +87,15 @@ " 'driver': 'GTiff',\n", " 'dtype': 'float32'\n", " }) \n", + " \n", " out_name = Path(b04_path).name.replace('B04', 'NDVI').replace('.jp2', '.tif')\n", "\n", - " ! mkdir -p {ndvi_path}\n", + " ndvi_path.mkdir(exist_ok=True, parents=True)\n", " with r.open(ndvi_path / out_name, 'w+', **out_meta) as dst:\n", " # we take only the part out of our source raster that we actually need\n", " # crop=True clips off the borders\n", - " b04, transform_b04 = rasterio.mask.mask(b04, shapes=[mask], crop=True)\n", - " b08, _ = rasterio.mask.mask(b08, shapes=[mask], crop=True) # we ignore the returned transform because it's identical to the previous one\n", + " b04, transform_b04 = rasterio.mask.mask(b04, shapes=[mask], crop=True, nodata=-999)\n", + " b08, _ = rasterio.mask.mask(b08, shapes=[mask], crop=True, nodata=-999) # we ignore the returned transform because it's identical to the previous one\n", "\n", " b04 = scihub_normalize_range(b04).astype('f4') # <- f4 = float32\n", " b08 = scihub_normalize_range(b08).astype('f4')\n", @@ -97,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -106,13 +125,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "d6bb63ba04f94679ab26c02235782b3c", + "model_id": "da8f523cda004cf281e368debdddb9c5", "version_major": 2, "version_minor": 0 }, @@ -127,30 +146,33 @@ "name": "stdout", "output_type": "stream", "text": [ - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip, skipping itProblem reading input/tempelhofer_feld/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip, skipping it\n", + "input/tempelhofer_feld/S2B_MSIL2A_20190330T101029_N0211_R022_T33UUU_20190330T144328.zip: Area is covered by clouds, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190626T102031_N0212_R065_T33UUU_20190626T125319.zip: Area is covered by clouds, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip: Problem reading product, skipping it\n", + "input/tempelhofer_feld/S2B_MSIL2A_20190320T101029_N0211_R022_T33UUU_20190320T195148.zip: Area is covered by clouds, skipping it\n", "\n", - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip, skipping it\n", - "Problem reading input/tempelhofer_feld/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip, skipping it\n", - "\n", - "CPU times: user 179 ms, sys: 154 ms, total: 333 ms\n", - "Wall time: 23.7 s\n" + "CPU times: user 191 ms, sys: 172 ms, total: 363 ms\n", + "Wall time: 12 s\n" ] } ], "source": [ "%%time\n", "\n", - "pool = Pool()\n", - "\n", - "for _ in tqdm(pool.imap_unordered(calculate_ndvi, input_files), total=len(input_files)):\n", - " # this loop is only here so we can get the progress bar\n", - " pass" + "# we parallelize the NDVI calculation using a Python threadpool\n", + "with Pool() as pool:\n", + " for _ in tqdm(pool.imap_unordered(calculate_ndvi, input_files), total=len(input_files)):\n", + " # this loop is only here so we can get the progress bar\n", + " pass" ] }, { @@ -162,14 +184,14 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "31\n" + "28\n" ] } ], @@ -177,6 +199,136 @@ "! ls -l {ndvi_path} | wc -l" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plot the NDVI\n", + "\n", + "See [02c Multithreading.ipynb](./02c Multithreading.ipynb) for a performance comparison of single vs multi-threaded iteration to average the ndvi." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "from numpy import ma" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "output_files = list(ndvi_path.glob('*.tif'))" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "def average(file_path):\n", + " with r.open(file_path) as src:\n", + " # masked=True makes sure to respect the nodata value and reads the data\n", + " # as a numpy MaskedArray, which lets us use `numpy.ma`'s methods\n", + " data = src.read(1, masked=True)\n", + " return file_path, ma.average(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2f61f096377440319738f5ea049f24b5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=27.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "CPU times: user 48.5 ms, sys: 165 ms, total: 213 ms\n", + "Wall time: 754 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "with Pool() as pool:\n", + " averages = [avg for avg in tqdm(pool.map(average, output_files), total=len(output_files))]" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [], + "source": [ + "paths, vals = zip(*averages)\n", + "dates = map(lambda p: p.name.split('_')[1], paths)\n", + "df = pd.DataFrame(\n", + " vals, index=pd.DatetimeIndex(dates)\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "df.plot()" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/true-color-image/02c Corrupted Zip File.ipynb b/true-color-image/02c Corrupted Zip File.ipynb index 4db52b0..8575ed2 100644 --- a/true-color-image/02c Corrupted Zip File.ipynb +++ b/true-color-image/02c Corrupted Zip File.ipynb @@ -4,65 +4,67 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Problems with Zipfiles\n", + "## Corrupted Zipfiles\n", "\n", - "Some of the downloaded zip files are suspiciously small:" + "Out of the 40 files we were trying to download, some needed to be fetched from the [Long-Term Archive](https://scihub.copernicus.eu/userguide/#LTA_Long_Term_Archive_Access).\n", + "After retrying the download several times, all files could be retrieved.\n", + "However, some of the downloaded zip files are suspiciously small:" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "1.2G input/tempelhofer_feld_next_try/S2B_MSIL2A_20190601T102029_N0212_R065_T33UUU_20190601T135040.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2A_MSIL2A_20190825T102031_N0213_R065_T33UUU_20190825T134836.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2A_MSIL2A_20191014T102031_N0213_R065_T32UQD_20191014T130941.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2A_MSIL2A_20190726T102031_N0213_R065_T33UUU_20190726T125507.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2A_MSIL2A_20190626T102031_N0212_R065_T33UUU_20190626T125319.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2A_MSIL2A_20190417T102031_N0211_R065_T33UUU_20190417T130913.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2B_MSIL2A_20190711T102029_N0213_R065_T33UUU_20190711T135545.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2B_MSIL2A_20190402T102029_N0211_R065_T33UUU_20190402T135010.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2B_MSIL2A_20191029T102039_N0213_R065_T32UQD_20191029T134629.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2B_MSIL2A_20190422T102029_N0211_R065_T32UQD_20190422T133643.zip\n", - "1.1G input/tempelhofer_feld_next_try/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.zip\n", - "845M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190723T101031_N0213_R022_T33UUU_20190723T125722.zip\n", - "829M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190911T101021_N0213_R022_T33UUU_20190911T143947.zip\n", - "823M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190713T101031_N0213_R022_T33UUU_20190713T135651.zip\n", - "823M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190718T101039_N0213_R022_T33UUU_20190718T131731.zip\n", - "819M input/tempelhofer_feld_next_try/S2A_MSIL2A_20191210T101411_N0213_R022_T33UUU_20191210T114322.zip\n", - "813M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190921T101031_N0213_R022_T33UUU_20190921T130515.zip\n", - "809M input/tempelhofer_feld_next_try/S2A_MSIL2A_20191220T101431_N0213_R022_T33UUU_20191220T115219.zip\n", - "802M input/tempelhofer_feld_next_try/S2B_MSIL2A_20191205T101309_N0213_R022_T33UUU_20191205T122401.zip\n", - "802M input/tempelhofer_feld_next_try/S2A_MSIL2A_20191130T101401_N0213_R022_T33UUU_20191130T115440.zip\n", - "789M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190827T101029_N0213_R022_T32UQD_20190827T134854.zip\n", - "789M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190519T101039_N0212_R022_T33UUU_20190519T132053.zip\n", - "774M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190728T101029_N0213_R022_T32UQD_20190728T134658.zip\n", - "771M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190906T101029_N0213_R022_T32UQD_20190906T133832.zip\n", - "768M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190529T101039_N0212_R022_T32UQD_20190529T130331.zip\n", - "766M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190330T101029_N0211_R022_T33UUU_20190330T144328.zip\n", - "764M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190218T101059_N0211_R022_T32UQD_20190218T161620.zip\n", - "761M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190320T101029_N0211_R022_T33UUU_20190320T195148.zip\n", - "753M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190409T101029_N0211_R022_T32UQD_20190409T134504.zip\n", - "723M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.zip\n", - " 43M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip\n", - " 42M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip\n", - " 38M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip\n", - " 35M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip\n", - " 31M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip\n", - " 30M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip\n", - " 30M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip\n", - " 29M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip\n", - " 29M input/tempelhofer_feld_next_try/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip\n", - " 25M input/tempelhofer_feld_next_try/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip\n" + " 25M input/tempelhofer_feld/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip\n", + " 29M input/tempelhofer_feld/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip\n", + " 29M input/tempelhofer_feld/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip\n", + " 30M input/tempelhofer_feld/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip\n", + " 30M input/tempelhofer_feld/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip\n", + " 31M input/tempelhofer_feld/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip\n", + " 35M input/tempelhofer_feld/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip\n", + " 38M input/tempelhofer_feld/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip\n", + " 42M input/tempelhofer_feld/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip\n", + " 43M input/tempelhofer_feld/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip\n", + "723M input/tempelhofer_feld/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.zip\n", + "753M input/tempelhofer_feld/S2B_MSIL2A_20190409T101029_N0211_R022_T32UQD_20190409T134504.zip\n", + "761M input/tempelhofer_feld/S2B_MSIL2A_20190320T101029_N0211_R022_T33UUU_20190320T195148.zip\n", + "764M input/tempelhofer_feld/S2B_MSIL2A_20190218T101059_N0211_R022_T32UQD_20190218T161620.zip\n", + "766M input/tempelhofer_feld/S2B_MSIL2A_20190330T101029_N0211_R022_T33UUU_20190330T144328.zip\n", + "768M input/tempelhofer_feld/S2B_MSIL2A_20190529T101039_N0212_R022_T32UQD_20190529T130331.zip\n", + "771M input/tempelhofer_feld/S2B_MSIL2A_20190906T101029_N0213_R022_T32UQD_20190906T133832.zip\n", + "774M input/tempelhofer_feld/S2B_MSIL2A_20190728T101029_N0213_R022_T32UQD_20190728T134658.zip\n", + "789M input/tempelhofer_feld/S2B_MSIL2A_20190519T101039_N0212_R022_T33UUU_20190519T132053.zip\n", + "789M input/tempelhofer_feld/S2B_MSIL2A_20190827T101029_N0213_R022_T32UQD_20190827T134854.zip\n", + "802M input/tempelhofer_feld/S2A_MSIL2A_20191130T101401_N0213_R022_T33UUU_20191130T115440.zip\n", + "802M input/tempelhofer_feld/S2B_MSIL2A_20191205T101309_N0213_R022_T33UUU_20191205T122401.zip\n", + "809M input/tempelhofer_feld/S2A_MSIL2A_20191220T101431_N0213_R022_T33UUU_20191220T115219.zip\n", + "813M input/tempelhofer_feld/S2A_MSIL2A_20190921T101031_N0213_R022_T33UUU_20190921T130515.zip\n", + "819M input/tempelhofer_feld/S2A_MSIL2A_20191210T101411_N0213_R022_T33UUU_20191210T114322.zip\n", + "823M input/tempelhofer_feld/S2B_MSIL2A_20190718T101039_N0213_R022_T33UUU_20190718T131731.zip\n", + "823M input/tempelhofer_feld/S2A_MSIL2A_20190713T101031_N0213_R022_T33UUU_20190713T135651.zip\n", + "829M input/tempelhofer_feld/S2A_MSIL2A_20190911T101021_N0213_R022_T33UUU_20190911T143947.zip\n", + "845M input/tempelhofer_feld/S2A_MSIL2A_20190723T101031_N0213_R022_T33UUU_20190723T125722.zip\n", + "1.1G input/tempelhofer_feld/S2A_MSIL2A_20191213T102421_N0213_R065_T33UUU_20191213T120011.zip\n", + "1.1G input/tempelhofer_feld/S2B_MSIL2A_20190422T102029_N0211_R065_T32UQD_20190422T133643.zip\n", + "1.1G input/tempelhofer_feld/S2B_MSIL2A_20191029T102039_N0213_R065_T32UQD_20191029T134629.zip\n", + "1.1G input/tempelhofer_feld/S2B_MSIL2A_20190402T102029_N0211_R065_T33UUU_20190402T135010.zip\n", + "1.1G input/tempelhofer_feld/S2B_MSIL2A_20190711T102029_N0213_R065_T33UUU_20190711T135545.zip\n", + "1.1G input/tempelhofer_feld/S2A_MSIL2A_20190417T102031_N0211_R065_T33UUU_20190417T130913.zip\n", + "1.1G input/tempelhofer_feld/S2A_MSIL2A_20190626T102031_N0212_R065_T33UUU_20190626T125319.zip\n", + "1.1G input/tempelhofer_feld/S2A_MSIL2A_20190726T102031_N0213_R065_T33UUU_20190726T125507.zip\n", + "1.1G input/tempelhofer_feld/S2A_MSIL2A_20191014T102031_N0213_R065_T32UQD_20191014T130941.zip\n", + "1.1G input/tempelhofer_feld/S2A_MSIL2A_20190825T102031_N0213_R065_T33UUU_20190825T134836.zip\n", + "1.2G input/tempelhofer_feld/S2B_MSIL2A_20190601T102029_N0212_R065_T33UUU_20190601T135040.zip\n" ] } ], "source": [ - "! ls -Ssh input/tempelhofer_feld_next_try/*.zip " + "! ls -rSsh input/tempelhofer_feld/*.zip" ] }, { @@ -95,9 +97,16 @@ "! ls -S input/tempelhofer_feld/*.zip | tail -n1 | xargs unzip" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What does the API say?" + ] + }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -107,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -116,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -134,7 +143,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -144,13 +153,12 @@ "Name: size, dtype: object" ] }, - "execution_count": 17, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# we can see that the size given by the scihub api is way larger\n", "res['size']" ] }, @@ -158,59 +166,110 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Do the downloads fail repeatedly?" + "We can see that the size given by the scihub api is way larger." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Do the downloads fail repeatedly?\n", + "\n", + "All files have been downloaded again to another folder, `input/tempelhofer_feld_test`." ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "input/tempelhofer_feld/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip\n", - "input/tempelhofer_feld/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip\n", - "input/tempelhofer_feld/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip\n", - "input/tempelhofer_feld/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip\n" + "9ca05754c4cc5ff9d2bddf99e2e9e753 input/tempelhofer_feld/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip\n", + "5424cf8c0dd4384382366b37af9ee995 input/tempelhofer_feld/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip\n", + "f2050867b04f8911dfcd1412846f5f0e input/tempelhofer_feld/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip\n", + "5c41f18b6c9745df406dbca49c50b0c7 input/tempelhofer_feld/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip\n", + "8e9dc7b716056f702912d11197fab44c input/tempelhofer_feld/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip\n", + "7241ca7fc6ccca5eb8935efe1b834697 input/tempelhofer_feld/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip\n", + "7d2b67dac6f36f1d8744ec2ef296445f input/tempelhofer_feld/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip\n", + "b078b9d41e7be70a89961214d4adb72b input/tempelhofer_feld/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip\n", + "f4a2910be181bd1c85fba14e05ce69b1 input/tempelhofer_feld/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip\n", + "53e1beb3f29dc1dc5b20745c3d66568e input/tempelhofer_feld/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip\n" ] } ], "source": [ - "! find input/tempelhofer_feld -type f -size -500M -name '*.zip'" + "! find input/tempelhofer_feld -type f -size -500M -name '*.zip' | xargs md5sum" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "input/tempelhofer_feld_test/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip\n", - "input/tempelhofer_feld_test/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip\n", - "input/tempelhofer_feld_test/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip\n", - "input/tempelhofer_feld_test/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip\n" + "9ca05754c4cc5ff9d2bddf99e2e9e753 input/tempelhofer_feld_test/S2A_MSIL2A_20190603T101031_N0212_R022_T33UUU_20190603T114652.zip\n", + "5424cf8c0dd4384382366b37af9ee995 input/tempelhofer_feld_test/S2A_MSIL2A_20190404T101031_N0211_R022_T32UQD_20190404T174806.zip\n", + "f2050867b04f8911dfcd1412846f5f0e input/tempelhofer_feld_test/S2A_MSIL2A_20190216T102111_N0211_R065_T33UUU_20190216T130428.zip\n", + "5c41f18b6c9745df406dbca49c50b0c7 input/tempelhofer_feld_test/S2B_MSIL2A_20190419T101029_N0211_R022_T33UUU_20190419T132322.zip\n", + "8e9dc7b716056f702912d11197fab44c input/tempelhofer_feld_test/S2A_MSIL2A_20190407T102021_N0211_R065_T33UUU_20190407T134109.zip\n", + "7241ca7fc6ccca5eb8935efe1b834697 input/tempelhofer_feld_test/S2B_MSIL2A_20190512T102029_N0212_R065_T33UUU_20190512T134103.zip\n", + "7d2b67dac6f36f1d8744ec2ef296445f input/tempelhofer_feld_test/S2A_MSIL2A_20190613T101031_N0212_R022_T33UUU_20190614T125329.zip\n", + "b078b9d41e7be70a89961214d4adb72b input/tempelhofer_feld_test/S2A_MSIL2A_20190424T101031_N0211_R022_T32UQD_20190424T162325.zip\n", + "f4a2910be181bd1c85fba14e05ce69b1 input/tempelhofer_feld_test/S2A_MSIL2A_20190822T101031_N0213_R022_T32UQD_20190822T143621.zip\n", + "53e1beb3f29dc1dc5b20745c3d66568e input/tempelhofer_feld_test/S2A_MSIL2A_20190623T101031_N0212_R022_T33UUU_20190623T132509.zip\n" ] } ], "source": [ - "! find input/tempelhofer_feld_test -type f -size -500M -name '*.zip'" + "! find input/tempelhofer_feld_test -type f -size -500M -name '*.zip' | xargs md5sum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The downloads are failing in exactly the same way when trying the downloads repeatedly." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Manual Download" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"https://scihub.copernicus.eu/apihub/odata/v1/Products('bedec483-5ee1-4264-8dfa-a3b53ce364f7')/$value\"" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "res['link'].iloc[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When following the link above, the target file is 25MB.\n", + "This points towards an error on the side of scihub." ] }, { diff --git a/true-color-image/02c Multithreading.ipynb b/true-color-image/02c Multithreading.ipynb new file mode 100644 index 0000000..efc69c5 --- /dev/null +++ b/true-color-image/02c Multithreading.ipynb @@ -0,0 +1,288 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multi-Threading Comparison\n", + "\n", + "This notebook contains a performance comparison of different methods to process the NDVI calculations.\n", + "\n", + "The `%%timeit` cell magic runs the cell content multiple times and outputs statistics on those multiple runs, thereby reducing factors such as garbage collection pauses etc." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from multiprocessing import Pool, cpu_count\n", + "from numpy import ma\n", + "from pathlib import Path\n", + "import rasterio as r" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of files: 27\n" + ] + } + ], + "source": [ + "test_files = list(Path('output/ndvi').glob('*.tif'))\n", + "print(f'Number of files: {len(test_files)}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The function we test with:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def average(file_path):\n", + " with r.open(file_path) as src:\n", + " data = src.read(1, masked=True)\n", + " return file_path, ma.average(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## In a single process\n", + "### Time to process a single file" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "36.2 ms ± 42.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "average(test_files[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Time to process all files" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "980 ms ± 7.38 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "averages = [avg for avg in map(average, test_files)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Increasing the list size" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.86 s ± 10.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "averages = [avg for avg in map(average, test_files * 5)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Time when using a worker pool\n", + "\n", + "Number of CPUs the multiprocessing pools can access:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cpu_count()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### On One element" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "277 ms ± 3.92 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "with Pool() as pool:\n", + " averages = [avg for avg in pool.map(average, test_files[:1])]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### On the complete list" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "630 ms ± 8.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "with Pool() as pool:\n", + " averages = [avg for avg in pool.map(average, test_files)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Increasing the list size" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.1 s ± 20 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "with Pool() as pool:\n", + " averages = [avg for avg in pool.map(average, test_files * 5)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Result\n", + "\n", + "As we can see when processing a single element, multiprocessing comes with an overhead.\n", + "When the list to be processed is sufficiently large, we get a reduction in processing time of roughly 30%-50%, depending on list size.\n", + "\n", + "Averaging the masked array is a fairly simple operation that scales in $O(N)$ with the size of the input array.\n", + "The time reduction should be even higher for more complex tasks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/true-color-image/02d Cloud Masks.ipynb b/true-color-image/02d Cloud Masks.ipynb new file mode 100644 index 0000000..3d9d6ce --- /dev/null +++ b/true-color-image/02d Cloud Masks.ipynb @@ -0,0 +1,315 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Dealing with cloud masks\n", + "\n", + "The products contain several raster and vector files that represent cloud masks or cloud propabilities.\n", + "\n", + "This notebook explores the contents of these files and evaluates how a helper for dealing with cloud masks can be implemented." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from sentinel_helpers import scihub_band_paths\n", + "product_path = 'input/tempelhofer_feld/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.zip'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'zip+file://input/tempelhofer_feld/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.zip!/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.SAFE/GRANULE/L2A_T32UQD_A018609_20190114T101352/QI_DATA/MSK_CLDPRB_20m.jp2'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "raster_cloud_mask = scihub_band_paths(product_path, ['MSK_CLDPRB'], '20m')[0]\n", + "raster_cloud_mask" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import rasterio as r\n", + "import rasterio.plot as rplt" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "with r.open(raster_cloud_mask) as mask:\n", + " rplt.show(mask.read() > 64, transform=mask.transform)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can find out the vector cloud mask path by manipulating the path to the raster cloud mask:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'zip+file://input/tempelhofer_feld/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.zip!/S2A_MSIL2A_20190114T101351_N0211_R022_T32UQD_20190114T113404.SAFE/GRANULE/L2A_T32UQD_A018609_20190114T101352/QI_DATA/MSK_CLOUDS_B00.gml'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector_cloud_mask = raster_cloud_mask.replace(raster_cloud_mask.split('/')[-1], 'MSK_CLOUDS_B00.gml')\n", + "vector_cloud_mask" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Trying to read the cloud mask from the zip file" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gpd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Fiona needs very long to open the GML file, the following lines are commented out because they did not terminate in an acceptable time (< 5min):" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "#with fiona.open(vector_cloud_mask) as f:\n", + "# pass" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# gpd.read_file(vector_cloud_mask)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The workaround is to unpack the vector file before opening it:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.8/site-packages/geopandas/geodataframe.py:422: RuntimeWarning: Sequential read of iterator was interrupted. Resetting iterator. This can negatively impact the performance.\n", + " for feature in features_lst:\n", + ":21: RuntimeWarning: Sequential read of iterator was interrupted. Resetting iterator. This can negatively impact the performance.\n", + " cloud_mask_fiona = unary_union([shape(f['geometry']) for f in features])\n" + ] + } + ], + "source": [ + "import fiona\n", + "from pathlib import Path\n", + "from shapely.geometry import shape\n", + "from shapely.ops import unary_union\n", + "from tempfile import TemporaryDirectory\n", + "from zipfile import ZipFile\n", + "\n", + "tmp_path = vector_cloud_mask.replace('zip+file://', '')\n", + "zip_path, file_path = tmp_path.split('!/')\n", + "\n", + "with TemporaryDirectory() as tmp_dir, ZipFile(zip_path) as f:\n", + " f.extract(file_path, tmp_dir)\n", + " tmp_path = Path(tmp_dir) / file_path\n", + " \n", + " # read with geopandas\n", + " cloud_mask_geopandas = gpd.read_file(tmp_path)['geometry'].unary_union\n", + " \n", + " # skip geopandas and read with fiona; this generates a RuntimeWarning\n", + " # about performance\n", + " with fiona.open(tmp_path) as features:\n", + " cloud_mask_fiona = unary_union([shape(f['geometry']) for f in features])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cloud_mask_geopandas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can skip `geopandas`geopandas and use `fiona` directly:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cloud_mask_fiona" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the aspect ratio is different than the raster file plotted above." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using the helper function" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sentinel_helpers import scihub_cloud_mask\n", + "scihub_cloud_mask(product_path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/true-color-image/sentinel_helpers.py b/true-color-image/sentinel_helpers.py index 5021ac3..b133f5e 100644 --- a/true-color-image/sentinel_helpers.py +++ b/true-color-image/sentinel_helpers.py @@ -1,6 +1,5 @@ import urllib.parse from pathlib import Path -import zipfile import fiona import geopandas as gpd @@ -9,6 +8,15 @@ import numpy as np import rasterio as r from rasterio.warp import calculate_default_transform, reproject, Resampling +from shapely.geometry import shape +from shapely.geometry.polygon import Polygon +from shapely.ops import unary_union + +from tempfile import TemporaryDirectory +from zipfile import ZipFile + +import warnings + def search_osm(place): ''' Returns a GeoDataFrame with results from OpenStreetMap Nominatim for the given search string. @@ -73,7 +81,7 @@ def scihub_band_paths(p, bands, resolution=None): if p.suffix == '.zip': # when dealing with zip files we have to read the filenames from the # archive first - with zipfile.ZipFile(p) as f: + with ZipFile(p) as f: files = f.namelist() rasters = [f for f in files if f.endswith('.jp2')] else: @@ -93,14 +101,48 @@ def scihub_band_paths(p, bands, resolution=None): return rasters -def scihub_bgr_paths(raster_path, resolution=None): +def scihub_bgr_paths(product_path, resolution=None): ''' A convenence function to return the paths to the blue, green and red bands - in the downloaded product at `raster_path`. + in the downloaded product at `product_path`. ''' - return scihub_band_paths(raster_path, ['B02', 'B03', 'B04'], resolution) + return scihub_band_paths(product_path, ['B02', 'B03', 'B04'], resolution) +def scihub_cloud_mask(product_path): + ''' + Given a `product_path` pointing to a product downlaoded from the Copernicus + Open Access Hub, returns a shapely geometry representing the included cloud + mask. + ''' + with TemporaryDirectory() as tmp_dir: + # we need the temporary directory to work around a problem with reading + # vector files from zip archives + + p = Path(product_path) + if p.suffix == '.zip': + # when dealing with zip files we have to read the filenames from the + # archive first + with ZipFile(p) as f: + files = f.namelist() + file = [f for f in files if f.endswith('MSK_CLOUDS_B00.gml')][0] + f.extract(file, tmp_dir) + file = Path(tmp_dir) / file + else: + file = list(p.glob('**/MSK_CLOUDS_B00.gml'))[0] + + try: + with fiona.open(file) as features: + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + # this returns a warning because the iterator has to be + # rewound; while this is a performance issue, we can ignore it + return unary_union([shape(f['geometry']) for f in features]) + except ValueError: + # empty cloud mask + return Polygon([]) + + def scihub_normalize_range(v): ''' Raster files downloaded from the Copernicus Open Access Hub can contain @@ -113,6 +155,7 @@ def scihub_normalize_range(v): def reproject_raster_image(src, dst, target_crs): ''' + FIXME: UNUSED!? Reprojects `src` into `dst`, given a coordinate reference system `target_crs`. ''' transform, width, height = calculate_default_transform(