Repository: CS-SI/eodag
Pull request #932 (2023-11-21 13:38:43)

feat: download assets subset
if a regex expression is passed in the parameter `asset` in the download only the assets matching this expression are downloaded (only working if the provider API returns individual assets and not a zip file); implemented for the `HTTPDownload` and `AwsDownload` plugins (s3rest plugin not used anymore after removal of mundi).

Client mode usage:
```py
path = dag.download(eo_product, asset=asset_key, **optional_download_kwargs)
# or
path = eo_product.assets[asset_key].download(**optional_download_kwargs)
```
Server mode usage:
http://127.0.0.1:5000/path/to/some/item/download/asset_key


github-actions[bot]: ## Test Results
       4 files  ±0         4 suites  ±0   3m 33s [:stopwatch:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "duration of all tests") ±0s
   433 tests +1     430 [:heavy_check_mark:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "passed tests") +1    3 [:zzz:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "skipped / disabled tests") ±0  0 [:x:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "failed tests") ±0 
1 732 runs  +4  1 656 [:heavy_check_mark:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "passed tests") +4  76 [:zzz:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "skipped / disabled tests") ±0  0 [:x:](https://github.com/EnricoMi/publish-unit-test-result-action/blob/v2.11.0/README.md#the-symbols "failed tests") ±0 

Results for commit fbc191f1. ± Comparison against base commit a3f82968.

[test-results]:data:application/gzip;base64,H4sIALizXGUC/02Myw7CIBQFf6Vh7aIXykN/xgDlJsS2GAor47+LWKHLmXMyL4J+cTu5DdNlIHv2qcGco04+bAUpsCLKlOrIGt33bG1VY1cP/yyqf1D7pYj+cDGGeJiYt28TJKMH/ZsguGjq15RNnJqVz0kb1tWnAgSNhSsgKOuEEWJyXGpGYaQzGiVRSA5WAyry/gBA/ibECAEAAA==

github-actions[bot]: <strong>Code Coverage (Ubuntu)</strong>

| File | Coverage |   |
| - | :-: | :-: |
| **All files** | `82%` | :white_check_mark: |

_Minimum allowed coverage is `70%`_

<p align="right">Generated by :monkey: cobertura-action against fbc191f18ce6b664e57a32102dfb87f6751ca1f8 </p>
github-actions[bot]: <strong>Code Coverage (Windows)</strong>

| File | Coverage |   |
| - | :-: | :-: |
| **All files** | `76%` | :white_check_mark: |

_Minimum allowed coverage is `70%`_

<p align="right">Generated by :monkey: cobertura-action against fbc191f18ce6b664e57a32102dfb87f6751ca1f8 </p>
jlahovnik: > Please filter assets keys instead of title or href

done

Patch:
diff --git a/docs/notebooks/api_user_guide/7_download.ipynb b/docs/notebooks/api_user_guide/7_download.ipynb
index 4317884d..d8a31eea 100644
--- a/docs/notebooks/api_user_guide/7_download.ipynb
+++ b/docs/notebooks/api_user_guide/7_download.ipynb
@@ -1111,17 +1111,243 @@
     "offline_product.location"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Download assets"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Searching on some providers (mainly STAC providers) returns products having an `assets` attribute listing single files that can be individually donwloaded."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "search_results, total_count = dag.search(\n",
+    "    productType=\"S2_MSI_L2A\", \n",
+    "    provider=\"planetary_computer\"\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['AOT',\n",
+       " 'B01',\n",
+       " 'B02',\n",
+       " 'B03',\n",
+       " 'B04',\n",
+       " 'B05',\n",
+       " 'B06',\n",
+       " 'B07',\n",
+       " 'B08',\n",
+       " 'B09',\n",
+       " 'B11',\n",
+       " 'B12',\n",
+       " 'B8A',\n",
+       " 'SCL',\n",
+       " 'WVP',\n",
+       " 'visual',\n",
+       " 'preview',\n",
+       " 'safe-manifest',\n",
+       " 'granule-metadata',\n",
+       " 'inspire-metadata',\n",
+       " 'product-metadata',\n",
+       " 'datastrip-metadata',\n",
+       " 'tilejson',\n",
+       " 'rendered_preview']"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# view assets keys\n",
+    "[*search_results[0].assets]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'href': 'https://sentinel2l2a01.blob.core.windows.net/sentinel2-l2/04/V/DM/2023/11/30/S2B_MSIL2A_20231130T221859_N0509_R115_T04VDM_20231130T231119.SAFE/GRANULE/L2A_T04VDM_A035176_20231130T221857/IMG_DATA/R20m/T04VDM_20231130T221859_B05_20m.tif', 'proj:bbox': [399960.0, 6590220.0, 509760.0, 6700020.0], 'proj:shape': [5490, 5490], 'proj:transform': [20.0, 0.0, 399960.0, 0.0, -20.0, 6700020.0], 'gsd': 20.0, 'type': 'image/tiff; application=geotiff; profile=cloud-optimized', 'roles': ['data'], 'title': 'Band 5 - Vegetation red edge 1 - 20m', 'eo:bands': [{'name': 'B05', 'common_name': 'rededge', 'description': 'Band 5 - Vegetation red edge 1', 'center_wavelength': 0.704, 'full_width_half_max': 0.019}]}"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# view single asset content\n",
+    "search_results[0].assets[\"B05\"]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Configure provider for download, if not already done"
+   ]
+  },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [],
-   "source": []
+   "source": [
+    "dag.update_providers_config(f\"\"\"\n",
+    "    planetary_computer:\n",
+    "        auth:\n",
+    "            credentials:\n",
+    "                apikey: PLEASE_CHANGE_ME\n",
+    "        download:\n",
+    "            outputs_prefix: {os.path.abspath(workspace)}\n",
+    "\"\"\")\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Download several assets using core `download()` method, allowing regex in `asset` parameter to identify assets to download"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "2b3b72362500471a90132f82de014fe8",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "0.00B [00:00, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "'/home/sylvain/workspace/eodag/docs/notebooks/api_user_guide/eodag_workspace_download/S2B_MSIL2A_20231130T221859_R115_T04VDM_20231130T231119'"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "path = dag.download(search_results[0], asset=r\"B0[23]\")\n",
+    "path"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "T04VDM_20231130T221859_B02_10m.tif  T04VDM_20231130T221859_B03_10m.tif\n"
+     ]
+    }
+   ],
+   "source": [
+    "! ls {path}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Download a single asset using `asset.download()` method"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "dbfd4d0a51d64b6b978aa1629e21b0f8",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "0.00B [00:00, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "'/home/sylvain/workspace/eodag/docs/notebooks/api_user_guide/eodag_workspace_download/S2B_MSIL2A_20231130T221859_R115_T04VDM_20231130T231119'"
+      ]
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "path = search_results[0].assets[\"B05\"].download()\n",
+    "path"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "T04VDM_20231130T221859_B02_10m.tif  T04VDM_20231130T221859_B05_20m.tif\n",
+      "T04VDM_20231130T221859_B03_10m.tif\n"
+     ]
+    }
+   ],
+   "source": [
+    "! ls {path}"
+   ]
   }
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3.8.10 64-bit",
+   "display_name": "Python 3 (ipykernel)",
    "language": "python",
    "name": "python3"
   },
@@ -1135,7 +1361,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.10"
+   "version": "3.10.12"
   },
   "vscode": {
    "interpreter": {
@@ -1145,204 +1371,164 @@
   "widgets": {
    "application/vnd.jupyter.widget-state+json": {
     "state": {
-     "00f74c9afcee41f781080736e4b1b2bb": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "01fe9acbf32c4e9f85fe4808dc168a7a": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "02f22b40afa244f58e3af27e9fc77886": {
+     "01cda13104c04e9987f5fc3fb3d12e3c": {
       "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
+      "model_module_version": "2.0.0",
       "model_name": "LayoutModel",
       "state": {}
      },
-     "03e06789065b4af2af8cbeebaf8fcd8d": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
+     "0e3c2a8e89fe4af4b6fcb07db3036276": {
+      "model_module": "@jupyter-widgets/base",
+      "model_module_version": "2.0.0",
+      "model_name": "LayoutModel",
       "state": {
-       "layout": "IPY_MODEL_4cef95ea6f3c4b57966f14bfd05443ac",
-       "style": "IPY_MODEL_5e08ebacc2e547869cc52977b723cc0c",
-       "value": "Extracting files from S2A_MSIL1C_20201226T105451_N0209_R051_T31TCK_20201226T130209.zip: 100%"
+       "flex": "2"
       }
      },
-     "04a03a9173fb4bbfbc23410f3adce072": {
+     "12bd52f10fcd4a1681b2c2ce9f0ab728": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HTMLModel",
       "state": {
-       "description_width": ""
+       "layout": "IPY_MODEL_70d76df867bf4026bbc93ce1b4d6cac9",
+       "style": "IPY_MODEL_5a907a533bf44c68bcc5978db19a34f5",
+       "value": "S2B_MSIL2A_20231130T221859_R115_T04VDM_20231130T231119: "
       }
      },
-     "0655c8b70af64a26b25bf7326b78d82e": {
+     "1876178fca154473b30e125beeb2b8fe": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HTMLStyleModel",
       "state": {
-       "layout": "IPY_MODEL_17ae13e6a8a6446db465bcc94c8bc39b",
-       "style": "IPY_MODEL_763143b8898945969c8effe0a64b09a4",
-       "value": " 34.8k/34.8k [00:00&lt;00:00, 293kB/s]"
+       "description_width": "",
+       "font_size": null,
+       "text_color": null
       }
      },
-     "07909752099f404eb16272abde2c49de": {
+     "1e862fc0cfd1445bad4592a15f2efbad": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
+      "model_module_version": "2.0.0",
+      "model_name": "FloatProgressModel",
       "state": {
-       "layout": "IPY_MODEL_0f77844e8f274624a3a444b59dc647a0",
-       "style": "IPY_MODEL_bb193001221f4c609dfe808ac234ed48",
-       "value": "quicklooks/S2B_MSIL1C_20201111T105259_N0209_R051_T31TCK_20201111T130651: 100%"
+       "bar_style": "success",
+       "layout": "IPY_MODEL_b4db254a24894672b72b84ba384fed32",
+       "max": 27396501,
+       "style": "IPY_MODEL_c02892dee90c44f4865ab1c89d141d50",
+       "value": 27396501
       }
      },
-     "09ed254fab5948e788dbf109df540e47": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "0d2e58c337ba419a8f57cba7ee7edaaa": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "0e4a22a56c35441787891e03a4d82f84": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
+     "229601dc5e0743d8b13e0f5d8f7548c4": {
+      "model_module": "@jupyter-widgets/controls",
+      "model_module_version": "2.0.0",
+      "model_name": "ProgressStyleModel",
       "state": {
-       "flex": "2"
+       "description_width": ""
       }
      },
-     "0f77844e8f274624a3a444b59dc647a0": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "0ff348ae46564d968020db92ca112bda": {
+     "259ba31dfb6d443ab8daa1237188de5f": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HTMLStyleModel",
       "state": {
-       "layout": "IPY_MODEL_d7d98c90410e405fb06ca685a4e110d7",
-       "style": "IPY_MODEL_5a8509581a6043e68f68fa66e43727e2",
-       "value": "quicklooks/S2A_MSIL1C_20201229T110451_N0209_R094_T31TCL_20201229T131620: 100%"
+       "description_width": "",
+       "font_size": null,
+       "text_color": null
       }
      },
-     "10090630957349eab6a987405d9aa8c5": {
+     "2b3b72362500471a90132f82de014fe8": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
+      "model_module_version": "2.0.0",
       "model_name": "HBoxModel",
       "state": {
        "children": [
-        "IPY_MODEL_22d94bd1aec24f3da650e0cc29dac906",
-        "IPY_MODEL_e79bd3627dc54cf8ad30dc99ed906dd4",
-        "IPY_MODEL_d09a2f4728cc4550b1a54f8805d9b599"
+        "IPY_MODEL_c571bee4657d4dffa8b63e216c5a675e",
+        "IPY_MODEL_1e862fc0cfd1445bad4592a15f2efbad",
+        "IPY_MODEL_a7a3065894874ab99725a3cc2117a5a9"
        ],
-       "layout": "IPY_MODEL_fb659e31419940758f6495224b0c556b"
+       "layout": "IPY_MODEL_c0537c8d38804e2b927492e42b95d2c6"
       }
      },
-     "1030ffa146c54cafb45d8f44bbee952a": {
+     "3068616e2e454125884c3361e9d95019": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "117ca44508454e2d8688ec994a1e4de0": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
+      "model_module_version": "2.0.0",
       "model_name": "HTMLModel",
       "state": {
-       "layout": "IPY_MODEL_d680ca0387114bec8b7d8db3fc69ce75",
-       "style": "IPY_MODEL_04a03a9173fb4bbfbc23410f3adce072",
-       "value": " 0.00/? [00:00&lt;?, ?B/s]"
+       "layout": "IPY_MODEL_eef129ae4a464b9aa082df0c3f13eaad",
+       "style": "IPY_MODEL_1876178fca154473b30e125beeb2b8fe",
+       "value": " 7.77M/? [00:01&lt;00:00, 7.96MB/s]"
       }
      },
-     "1429f1fdbbe84d9b993b910e600516ff": {
+     "5a907a533bf44c68bcc5978db19a34f5": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HTMLStyleModel",
       "state": {
-       "description_width": ""
+       "description_width": "",
+       "font_size": null,
+       "text_color": null
       }
      },
-     "16de0fec1e8e428eb2d447371233bbea": {
+     "64886108403149bd8cb2b69b16e91794": {
       "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
+      "model_module_version": "2.0.0",
       "model_name": "LayoutModel",
       "state": {
-       "flex": "2"
+       "display": "inline-flex",
+       "flex_flow": "row wrap",
+       "width": "100%"
       }
      },
-     "1772512a86e547dabd6e04d4efd3c34e": {
+     "6939b84ef0c046b6aefe5511c58c20e6": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HTMLStyleModel",
       "state": {
-       "layout": "IPY_MODEL_8c2d666a4f514e4ab9d27d1f75fa76d1",
-       "style": "IPY_MODEL_423d59f141b1415aae4239116e4080a0",
-       "value": "quicklooks/S2A_MSIL1C_20201226T105451_N0209_R051_T31TCK_20201226T130209: 100%"
+       "description_width": "",
+       "font_size": null,
+       "text_color": null
       }
      },
-     "17ae13e6a8a6446db465bcc94c8bc39b": {
+     "70d76df867bf4026bbc93ce1b4d6cac9": {
       "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
+      "model_module_version": "2.0.0",
       "model_name": "LayoutModel",
       "state": {}
      },
-     "17b2ffad2f654ad58d6252635ac48dcb": {
+     "a5434e9264a7431fb8f89119d71677ee": {
       "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
+      "model_module_version": "2.0.0",
       "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
+      "state": {}
      },
-     "17bf04fa819b40219e9beadabb29b7c5": {
+     "a7a3065894874ab99725a3cc2117a5a9": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
+      "model_module_version": "2.0.0",
       "model_name": "HTMLModel",
       "state": {
-       "layout": "IPY_MODEL_ff22fadc6c5f45b0b0a3b5f66675972e",
-       "style": "IPY_MODEL_2f57d7b1ff074bf5b3b38f85935a8385",
-       "value": "quicklooks/S2A_MSIL1C_20201116T105331_N0209_R051_T31TCL_20201116T130215: 100%"
+       "layout": "IPY_MODEL_01cda13104c04e9987f5fc3fb3d12e3c",
+       "style": "IPY_MODEL_259ba31dfb6d443ab8daa1237188de5f",
+       "value": " 54.8M/? [00:07&lt;00:00, 10.1MB/s]"
       }
      },
-     "183a21f5ddfb4dc38c02884e5304b958": {
+     "b4db254a24894672b72b84ba384fed32": {
       "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
+      "model_module_version": "2.0.0",
       "model_name": "LayoutModel",
-      "state": {}
+      "state": {
+       "flex": "2"
+      }
      },
-     "18db9b4f07684178aa762e848300efdd": {
+     "c02892dee90c44f4865ab1c89d141d50": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
+      "model_module_version": "2.0.0",
+      "model_name": "ProgressStyleModel",
       "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_e1af015f87604c1da38e9b239e2cb245",
-       "max": 31027,
-       "style": "IPY_MODEL_467f80b29a6649778f074cc9415d13fe",
-       "value": 31027
+       "description_width": ""
       }
      },
-     "196653d86ddb488690b2ac1c22e9ad62": {
+     "c0537c8d38804e2b927492e42b95d2c6": {
       "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
+      "model_module_version": "2.0.0",
       "model_name": "LayoutModel",
       "state": {
        "display": "inline-flex",
@@ -1350,1876 +1536,45 @@
        "width": "100%"
       }
      },
-     "19822930690b497893863b9e99f3a241": {
+     "c571bee4657d4dffa8b63e216c5a675e": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HTMLModel",
       "state": {
-       "children": [
-        "IPY_MODEL_03e06789065b4af2af8cbeebaf8fcd8d",
-        "IPY_MODEL_647afe974789478d80398973b73e85af",
-        "IPY_MODEL_d0a814b63c6142b9b719fe15eddbff08"
-       ],
-       "layout": "IPY_MODEL_e40f15bb04334d218372168c6cca289a"
+       "layout": "IPY_MODEL_a5434e9264a7431fb8f89119d71677ee",
+       "style": "IPY_MODEL_6939b84ef0c046b6aefe5511c58c20e6",
+       "value": "S2B_MSIL2A_20231130T221859_R115_T04VDM_20231130T231119: "
       }
      },
-     "1aedf149d7024a77983ffa6f98273a77": {
+     "dbfd4d0a51d64b6b978aa1629e21b0f8": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
+      "model_module_version": "2.0.0",
+      "model_name": "HBoxModel",
       "state": {
-       "description_width": ""
+       "children": [
+        "IPY_MODEL_12bd52f10fcd4a1681b2c2ce9f0ab728",
+        "IPY_MODEL_f2662afd51ce4245a1d22f1bf9fa7840",
+        "IPY_MODEL_3068616e2e454125884c3361e9d95019"
+       ],
+       "layout": "IPY_MODEL_64886108403149bd8cb2b69b16e91794"
       }
      },
-     "1b4dc95217cf4b4f8b2504330cb59737": {
+     "eef129ae4a464b9aa082df0c3f13eaad": {
+      "model_module": "@jupyter-widgets/base",
+      "model_module_version": "2.0.0",
+      "model_name": "LayoutModel",
+      "state": {}
+     },
+     "f2662afd51ce4245a1d22f1bf9fa7840": {
       "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
+      "model_module_version": "2.0.0",
       "model_name": "FloatProgressModel",
       "state": {
        "bar_style": "success",
-       "layout": "IPY_MODEL_7dca97d9546e42659b1c9c5d39c5c538",
-       "max": 59709,
-       "style": "IPY_MODEL_6721216acd9943cb8db0e9a90556e429",
-       "value": 59709
-      }
-     },
-     "1cef912b3ce946719ce39005deeaf6b1": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_469f00f2dabc488ba416390c34ffeec4",
-       "style": "IPY_MODEL_8b6e207b90d64b2e930880d7126fe7da",
-       "value": "Downloaded products: 100%"
-      }
-     },
-     "1d069dea16364e8e90ee3d0e0c7545f3": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_69813a07faed41a193b488f17a39652a",
-       "style": "IPY_MODEL_00f74c9afcee41f781080736e4b1b2bb",
-       "value": "quicklooks/S2A_MSIL1C_20201119T110341_N0209_R094_T31TCL_20201119T131255: 100%"
-      }
-     },
-     "1f42625a6b974229a7904fbc6dff7b90": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "1fa040c68d4c485aaa765e8b75b3b1fa": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_262cee5dc0714675aa4b96a10eec5d69",
-        "IPY_MODEL_cb510d4f2af346b49443e75d5594f645",
-        "IPY_MODEL_34e4abd13c064f37891a10e6c7478c83"
-       ],
-       "layout": "IPY_MODEL_633e812d87144aa2a1b9ad445d8bc19b"
-      }
-     },
-     "219820c194b843e78067877129a0c3a1": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "21b2328036e946929a68e99d432251d9": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_07909752099f404eb16272abde2c49de",
-        "IPY_MODEL_9966a4cf14d4446ca4ede9c0ed788343",
-        "IPY_MODEL_568e21db9e87479697943fe919ec3013"
-       ],
-       "layout": "IPY_MODEL_6c7a04f5d93c4f928997b285d31f5a8f"
-      }
-     },
-     "22d94bd1aec24f3da650e0cc29dac906": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_85508941196c49d29cce45b5331cbe56",
-       "style": "IPY_MODEL_c3a6159390414ae98dfa57c983bccc8b"
-      }
-     },
-     "244bae2d8b5340cb8af3f6f39d9e92ce": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "24aada7c6196411988ccc56032f72f50": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "262cee5dc0714675aa4b96a10eec5d69": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_beb1dd42c7534718814f736fb88e27a9",
-       "style": "IPY_MODEL_5e6a11e680454c6a98c412df1a40cd13",
-       "value": "This will be displayed:  50%"
-      }
-     },
-     "271171c6018d468ab8ed7b10aa40a590": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "291884d7015249aa8c319ffeebbab550": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_9a9113ea4e3746f7a271fe941a2d06d8",
-       "max": 2,
-       "style": "IPY_MODEL_c51adc32d6014f3a8364637c5db3b460",
-       "value": 2
-      }
-     },
-     "29af2523e95c4d5dbaa9adb76b492817": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "2a46ccd2f87649e6899a26d07aedcad8": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_1cef912b3ce946719ce39005deeaf6b1",
-        "IPY_MODEL_453fc9821906409fadeb299d4e019e9e",
-        "IPY_MODEL_5d3ccd320d2a4ec09478f4a9b6f2f641"
-       ],
-       "layout": "IPY_MODEL_6d4c95edeb814b6f889c64d2ffccb3f4"
-      }
-     },
-     "2a8c51f87edd4f5390baccd3c3598b0b": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "2ac768193be742dcbb21d451eb315444": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "2aee8cada4644f5b999c901717bd8738": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_0e4a22a56c35441787891e03a4d82f84",
-       "max": 42572,
-       "style": "IPY_MODEL_653e24b71d3d413584c6fcfe53c6491d",
-       "value": 42572
-      }
-     },
-     "2ea68e5c5f9c43078d92d6c6f647af0e": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "2f57d7b1ff074bf5b3b38f85935a8385": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "305f43107aa14767acbf1dbb13346807": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "30f9dc5197754e75a8876bbb71d8f5e8": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "327873754896413ab5405ed2b7806929": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_17b2ffad2f654ad58d6252635ac48dcb",
-       "max": 74912,
-       "style": "IPY_MODEL_e29ee39192ff46f88283e71ff431a230",
-       "value": 74912
-      }
-     },
-     "32dafad1ddd3406d9bd5b63401f8c5da": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "34e4abd13c064f37891a10e6c7478c83": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_df40ca64039946c8a5b4ffe39368b108",
-       "style": "IPY_MODEL_39e9af7de34641838c6c8697ad250f33",
-       "value": " 1.00/2.00 [00:00&lt;00:00, 21.0B/s]"
-      }
-     },
-     "3796a6c56004488695fd34f1afb0e7a9": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "380cbc0470cf47cd821b014c1cd6217c": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "38edd85961d74c818defdcb64537bc96": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "3992b9075025477fb04563159c7c7bd6": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "39e9af7de34641838c6c8697ad250f33": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "3d99bda929054df2b820476f0c82d4e9": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_d8a77bdbda5040ee9622c50eda3cb028",
-       "style": "IPY_MODEL_bc05430de9944e8598b226b573283653",
-       "value": " 115/115 [00:03&lt;00:00, 30.89file/s]"
-      }
-     },
-     "3e868360b7374cc9989c323a0fd11dd2": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "3f4a4c1b6411425fac29c4cee5a60017": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_d1ad41f5d8c745daa87fa01040f39f81",
-       "style": "IPY_MODEL_a6b4a137291f4a47a1c7a60510cb93bd",
-       "value": " 52.9k/52.9k [00:00&lt;00:00, 367kB/s]"
-      }
-     },
-     "40d77e0163074d4888606cd4e0bfe001": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_1d069dea16364e8e90ee3d0e0c7545f3",
-        "IPY_MODEL_b5341318f45a401693961d59df314378",
-        "IPY_MODEL_b108c9a755cf45918f1c52794bc87a00"
-       ],
-       "layout": "IPY_MODEL_8b52c95044fb4166befc4129abf7d9f7"
-      }
-     },
-     "423d59f141b1415aae4239116e4080a0": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "43136fd323c940dea9c1ae793e46ad18": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "43ff9d824e6d400b833c8b00b80e1abb": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "453fc9821906409fadeb299d4e019e9e": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_95f30579e5e048a6be63dac3dd30ef08",
-       "max": 2,
-       "style": "IPY_MODEL_fc3e5a300d8b4889930d2bb0e16d95c9",
-       "value": 2
-      }
-     },
-     "467f80b29a6649778f074cc9415d13fe": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "469f00f2dabc488ba416390c34ffeec4": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "4a1f7023a808454d8b773ba80d5af471": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_f3eb570e7b594a4f9e8d9ef35fe64cf8",
-       "style": "IPY_MODEL_923a18a82c8c4a89b96ab1efafa0066b",
-       "value": "S2A_MSIL1C_20201229T110451_N0209_R094_T31TCL_20201229T131620: "
-      }
-     },
-     "4a85e182af6c407b824cc9d4858ae610": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "4aafddc26bc148e08383e043cc377f05": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_8aa1f40dda0542d9853e50f7aefd36fa",
-       "style": "IPY_MODEL_e1462a2b6de348cc8f33d8a89899638f",
-       "value": "quicklooks/S2A_MSIL1C_20201226T105451_N0209_R051_T31TCL_20201226T130209: 100%"
-      }
-     },
-     "4cef95ea6f3c4b57966f14bfd05443ac": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "4de63a52aaf648c884a6a64b3579f511": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "4e0c490a8eb74c86a4256f5969a965ae": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "537aff289e3e42af89557bd5604b555f": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "53e42af2060247eea722a9f51c31e1f2": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_3992b9075025477fb04563159c7c7bd6",
-       "style": "IPY_MODEL_1aedf149d7024a77983ffa6f98273a77",
-       "value": "S2A_MSIL1C_20201226T105451_N0209_R051_T31TCK_20201226T130209: "
-      }
-     },
-     "568e21db9e87479697943fe919ec3013": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_d1b8e9aa118c434baea4ce3fed2fd41e",
-       "style": "IPY_MODEL_ed73c4698dc14453b87fc7969bf2dc2f",
-       "value": " 44.5k/44.5k [00:00&lt;00:00, 624kB/s]"
-      }
-     },
-     "5711172ea3ed4d1e85191a0239a9b591": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "57741e62b5c7426292ad04776bc517fd": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "5a8509581a6043e68f68fa66e43727e2": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "5d02707ed9dd4e04abe112d64a628b32": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "5d3ccd320d2a4ec09478f4a9b6f2f641": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_4de63a52aaf648c884a6a64b3579f511",
-       "style": "IPY_MODEL_1429f1fdbbe84d9b993b910e600516ff",
-       "value": " 2/2 [06:52&lt;00:00, 218.54s/product]"
-      }
-     },
-     "5e08ebacc2e547869cc52977b723cc0c": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "5e6a11e680454c6a98c412df1a40cd13": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "5e91084fed10434faa41c5f526a112c0": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "6057fe1d2b4f4a63ac381bdb00f9f3ac": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "6108654b209c4914b3def12ccd3ab861": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "61bdd92fb2334ac58ad23d70fade3968": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "633e812d87144aa2a1b9ad445d8bc19b": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "647afe974789478d80398973b73e85af": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_a243ca5f69584f4589b61bc9ae7cdaf8",
-       "max": 115,
-       "style": "IPY_MODEL_7b9e16093a8f4cb69422d655fd3fe4db",
-       "value": 115
-      }
-     },
-     "653e24b71d3d413584c6fcfe53c6491d": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "6721216acd9943cb8db0e9a90556e429": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "6946468fcf3d4f5db4445e83fe2c758b": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_4aafddc26bc148e08383e043cc377f05",
-        "IPY_MODEL_1b4dc95217cf4b4f8b2504330cb59737",
-        "IPY_MODEL_9d382c1b2f6e4cfbbcdce072a7c77b49"
-       ],
-       "layout": "IPY_MODEL_57741e62b5c7426292ad04776bc517fd"
-      }
-     },
-     "69813a07faed41a193b488f17a39652a": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "69b6401afcfc4489b652038bb1e658c2": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "6a986a0d90e2472cbc303acfbf30e5e0": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_db7c123e3cd142e2b4813c6e3a960fa4",
-       "style": "IPY_MODEL_b53fb4232fe7496891ef2765c9328a8d",
-       "value": " 74.9k/74.9k [00:00&lt;00:00, 602kB/s]"
-      }
-     },
-     "6be28f31ff9745108093212ce6dedfdc": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_fb52dc0b1568450fa88389e4962955ab",
-        "IPY_MODEL_18db9b4f07684178aa762e848300efdd",
-        "IPY_MODEL_7e835bce4cb64430a1b7998a1fc9eb1d"
-       ],
-       "layout": "IPY_MODEL_196653d86ddb488690b2ac1c22e9ad62"
-      }
-     },
-     "6c05528d741e41f5adb4a90353b5ef53": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_afe75eb3f8954c14aaa6f8bedcb255b0",
-       "max": 25159,
-       "style": "IPY_MODEL_3e868360b7374cc9989c323a0fd11dd2",
-       "value": 25159
-      }
-     },
-     "6c7a04f5d93c4f928997b285d31f5a8f": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "6cab70ca773d492f91e28b04cfaeacc0": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_93250f4992a447b882fa86981875f801",
-        "IPY_MODEL_dbaf5b346f674c0a858ef6a848bec165",
-        "IPY_MODEL_3d99bda929054df2b820476f0c82d4e9"
-       ],
-       "layout": "IPY_MODEL_e09230db12fc49c4aa9b1cc4132579ff"
-      }
-     },
-     "6cb651aedc51425fbec47f27a6be9ae7": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "6d4c95edeb814b6f889c64d2ffccb3f4": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "6da46c359b144e90873b48f934030125": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "6eb037657e4e47cfa08d92ef1aff5b3d": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "6f46281c8a0f4de1a0c77d763556ee86": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_6108654b209c4914b3def12ccd3ab861",
-       "max": 1,
-       "style": "IPY_MODEL_2a8c51f87edd4f5390baccd3c3598b0b",
-       "value": 1
-      }
-     },
-     "70f39c06c0934426a3e978eadbe01ccf": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_4a1f7023a808454d8b773ba80d5af471",
-        "IPY_MODEL_dde500cb7b8242fab6e440a9396831d9",
-        "IPY_MODEL_e563fc133b25432bb2c2adf5fe702eb6"
-       ],
-       "layout": "IPY_MODEL_8373ec08012c4b8ca3656fd644eb51af"
-      }
-     },
-     "759a7904c1764b55811cc6b9389af4ac": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "763143b8898945969c8effe0a64b09a4": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "79c9f30f27cf4ce59dbfd6586d89d0b7": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_16de0fec1e8e428eb2d447371233bbea",
-       "max": 34820,
-       "style": "IPY_MODEL_9db50f66074e4a06bc02552d9e17fc9a",
-       "value": 34820
-      }
-     },
-     "7ad860a453894c48bb11adee1c6b87a1": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_5e91084fed10434faa41c5f526a112c0",
-       "max": 69185,
-       "style": "IPY_MODEL_83a9ef2bfc0c48a7b920d0fe0274373f",
-       "value": 69185
-      }
-     },
-     "7b52af387bf645948ebdf25e04af668a": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "7b9e16093a8f4cb69422d655fd3fe4db": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "7dca97d9546e42659b1c9c5d39c5c538": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "7e835bce4cb64430a1b7998a1fc9eb1d": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_09ed254fab5948e788dbf109df540e47",
-       "style": "IPY_MODEL_5711172ea3ed4d1e85191a0239a9b591",
-       "value": " 31.0k/31.0k [00:00&lt;00:00, 198kB/s]"
-      }
-     },
-     "81f3d64165f14f66baf8a9e86386bf02": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "820742df10c54b21b2051bdb2c7a9bae": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "8373ec08012c4b8ca3656fd644eb51af": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "83a9ef2bfc0c48a7b920d0fe0274373f": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "83d277cb7bb04b97b12313b01f7ed2e6": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "8468c2a9b6114623aa155b2c59ceeaa5": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "85508941196c49d29cce45b5331cbe56": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "8942010860f947888d5965798ee45afc": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "89cd99569f774d3b825a5318beca64b7": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "8a61e9f8cd4d4d6592946cae74efbad0": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_f8d37b2d5b3e4173b2948c1733e079de",
-       "style": "IPY_MODEL_1f42625a6b974229a7904fbc6dff7b90",
-       "value": "quicklooks/S2B_MSIL1C_20201114T110319_N0209_R094_T31TCL_20201114T120840: 100%"
-      }
-     },
-     "8aa1f40dda0542d9853e50f7aefd36fa": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "8b52c95044fb4166befc4129abf7d9f7": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "8b6e207b90d64b2e930880d7126fe7da": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "8c193e75fb464c47b1214ebd94ebbaff": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_bcc14a89d764416386ec6d59b5505a46",
-       "style": "IPY_MODEL_83d277cb7bb04b97b12313b01f7ed2e6",
-       "value": " 25.2k/25.2k [00:00&lt;00:00, 1.56MB/s]"
-      }
-     },
-     "8c2d666a4f514e4ab9d27d1f75fa76d1": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "8c93479c548e422f80ece4ab82230c60": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "8ddead9fd363442399080031ff27a935": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_53e42af2060247eea722a9f51c31e1f2",
-        "IPY_MODEL_ccb1fcd06dcc4d6db3f76f6de45d7a57",
-        "IPY_MODEL_117ca44508454e2d8688ec994a1e4de0"
-       ],
-       "layout": "IPY_MODEL_89cd99569f774d3b825a5318beca64b7"
-      }
-     },
-     "902870969f25419dbcd664d9e8436096": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_4a85e182af6c407b824cc9d4858ae610",
-       "style": "IPY_MODEL_d78f00ee13ea477a8ab73eec4d28431c",
-       "value": "Extracting files from S2A_MSIL1C_20201229T110451_N0209_R094_T31TCL_20201229T131620.zip: 100%"
-      }
-     },
-     "9229a49e42494e979d82b203ecf1791f": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "923a18a82c8c4a89b96ab1efafa0066b": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "93250f4992a447b882fa86981875f801": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_a9056f384e7d45b5b677e2de78c98dec",
-       "style": "IPY_MODEL_38edd85961d74c818defdcb64537bc96",
-       "value": "Extracting files from S2A_MSIL1C_20201116T105331_N0209_R051_T31TCK_20201116T130215.zip: 100%"
-      }
-     },
-     "937e9ea300ab4447b78a13effec6c492": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "95b0991836ff42e3b094b13ffdfaffae": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_c574e7d53d034842b4f7a7ceee91d0fd",
-       "style": "IPY_MODEL_6057fe1d2b4f4a63ac381bdb00f9f3ac",
-       "value": " 2/2 [00:00&lt;00:00, 16.06product/s]"
-      }
-     },
-     "95f30579e5e048a6be63dac3dd30ef08": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "9966a4cf14d4446ca4ede9c0ed788343": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_9c34f40fb5a947f0be3bf9b7346a8a56",
-       "max": 44538,
-       "style": "IPY_MODEL_d8f1ca3388a24da1b11ca6c3a92d4b5b",
-       "value": 44538
-      }
-     },
-     "9a5ba9ed24b846cb9cc1c0a0421ba9a0": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "9a9113ea4e3746f7a271fe941a2d06d8": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "9b57cb5be33146a2bd4000e377f3883c": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_ac4ba49caaae4f1d8374c4408e57cd72",
-       "style": "IPY_MODEL_820742df10c54b21b2051bdb2c7a9bae",
-       "value": " 69.2k/69.2k [00:00&lt;00:00, 497kB/s]"
-      }
-     },
-     "9bf4a38a541242fea78eefc7fa72de07": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "9c02540b8038464094375e39f05d6369": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "9c34f40fb5a947f0be3bf9b7346a8a56": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "9c52e67acb594733928a16672fb66c3a": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "bar_color": "purple",
-       "description_width": ""
-      }
-     },
-     "9d382c1b2f6e4cfbbcdce072a7c77b49": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_24aada7c6196411988ccc56032f72f50",
-       "style": "IPY_MODEL_43136fd323c940dea9c1ae793e46ad18",
-       "value": " 59.7k/59.7k [00:00&lt;00:00, 441kB/s]"
-      }
-     },
-     "9db50f66074e4a06bc02552d9e17fc9a": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "9db842c9e7d54eb1b85831fa450aa367": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_43ff9d824e6d400b833c8b00b80e1abb",
-       "style": "IPY_MODEL_b5d1a593f9934df88a65e374560a4d4e",
-       "value": " 115/115 [00:02&lt;00:00, 57.15file/s]"
-      }
-     },
-     "9f26eea696724aedb1b4ca0594efc65c": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "a1336165c66b4c2aa434c1a3fec3f64c": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "a22e380414424faa81abc918334decf4": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "a243ca5f69584f4589b61bc9ae7cdaf8": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "a36cc750caed485da743a68e269f73e8": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "a626306a00ca4710a9044d2f697fcae3": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "a6b4a137291f4a47a1c7a60510cb93bd": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "a9056f384e7d45b5b677e2de78c98dec": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "aafa0a3dbe8b415ebafbaed2c8947a3b": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "ac4ba49caaae4f1d8374c4408e57cd72": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "ae684630e6744654b7e470539dde03b2": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "afe75eb3f8954c14aaa6f8bedcb255b0": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "b108c9a755cf45918f1c52794bc87a00": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_3796a6c56004488695fd34f1afb0e7a9",
-       "style": "IPY_MODEL_ceba04b837714aeaac109a633fbe3277",
-       "value": " 26.2k/26.2k [00:00&lt;00:00, 609kB/s]"
-      }
-     },
-     "b17b293c653148ffafdcf1cca9b8c820": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_b535ae02f7274b7d98f1e000a952b6c2",
-        "IPY_MODEL_79c9f30f27cf4ce59dbfd6586d89d0b7",
-        "IPY_MODEL_0655c8b70af64a26b25bf7326b78d82e"
-       ],
-       "layout": "IPY_MODEL_feff37ac49ab455db2692829d288f2bd"
-      }
-     },
-     "b453a291ecb6475796dacd159268dbb8": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "b5341318f45a401693961d59df314378": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_a22e380414424faa81abc918334decf4",
-       "max": 26177,
-       "style": "IPY_MODEL_2ea68e5c5f9c43078d92d6c6f647af0e",
-       "value": 26177
-      }
-     },
-     "b535ae02f7274b7d98f1e000a952b6c2": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_69b6401afcfc4489b652038bb1e658c2",
-       "style": "IPY_MODEL_bd31817f2f5d46fe93f9d0c65408d4df",
-       "value": "quicklooks/S2B_MSIL1C_20201231T105349_N0209_R051_T31TCL_20201231T120402: 100%"
-      }
-     },
-     "b53fb4232fe7496891ef2765c9328a8d": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "b5d1a593f9934df88a65e374560a4d4e": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "b80a0b834b0141b6ad4d0b107e2711ce": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "bb193001221f4c609dfe808ac234ed48": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "bc05430de9944e8598b226b573283653": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "bcc14a89d764416386ec6d59b5505a46": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "bd31817f2f5d46fe93f9d0c65408d4df": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "beb1dd42c7534718814f736fb88e27a9": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "bff2e9acb0f14a2b9b861637fcabca23": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "c3a6159390414ae98dfa57c983bccc8b": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "c4d2e6939a674cc6893de18514a4e708": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "c51adc32d6014f3a8364637c5db3b460": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "c574e7d53d034842b4f7a7ceee91d0fd": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "c7f9c5c92ea0496481f279da544b6d0b": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "c84044d9182c4a079b5e6544984f275e": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_183a21f5ddfb4dc38c02884e5304b958",
-       "style": "IPY_MODEL_2ac768193be742dcbb21d451eb315444",
-       "value": " 42.6k/42.6k [00:00&lt;00:00, 269kB/s]"
-      }
-     },
-     "c8c953e4721f4c5ba4c5b887a0677040": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_8468c2a9b6114623aa155b2c59ceeaa5",
-       "max": 115,
-       "style": "IPY_MODEL_32dafad1ddd3406d9bd5b63401f8c5da",
-       "value": 115
-      }
-     },
-     "c94db8bcfcec4543aacf46bb9bb8b2b8": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_f71b8ecf5faa40598267a71a222b731e",
-        "IPY_MODEL_6f46281c8a0f4de1a0c77d763556ee86",
-        "IPY_MODEL_d9e1075a05034b2daf5ae4af1022aa94"
-       ],
-       "layout": "IPY_MODEL_c7f9c5c92ea0496481f279da544b6d0b"
-      }
-     },
-     "cb510d4f2af346b49443e75d5594f645": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "danger",
-       "layout": "IPY_MODEL_7b52af387bf645948ebdf25e04af668a",
-       "max": 2,
-       "style": "IPY_MODEL_9a5ba9ed24b846cb9cc1c0a0421ba9a0",
-       "value": 1
-      }
-     },
-     "cbc05aeb9102482fb012e888d154cdab": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "ccb1fcd06dcc4d6db3f76f6de45d7a57": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_9f26eea696724aedb1b4ca0594efc65c",
-       "max": 1,
-       "style": "IPY_MODEL_b453a291ecb6475796dacd159268dbb8"
-      }
-     },
-     "ccf12fa726af4e32abfd15d20fb1e0b1": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_902870969f25419dbcd664d9e8436096",
-        "IPY_MODEL_c8c953e4721f4c5ba4c5b887a0677040",
-        "IPY_MODEL_9db842c9e7d54eb1b85831fa450aa367"
-       ],
-       "layout": "IPY_MODEL_305f43107aa14767acbf1dbb13346807"
-      }
-     },
-     "ceba04b837714aeaac109a633fbe3277": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "d09a2f4728cc4550b1a54f8805d9b599": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_759a7904c1764b55811cc6b9389af4ac",
-       "style": "IPY_MODEL_1030ffa146c54cafb45d8f44bbee952a",
-       "value": " 1.00/? [00:01&lt;00:00, 1.37s/B]"
-      }
-     },
-     "d0a814b63c6142b9b719fe15eddbff08": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_a36cc750caed485da743a68e269f73e8",
-       "style": "IPY_MODEL_bff2e9acb0f14a2b9b861637fcabca23",
-       "value": " 115/115 [00:03&lt;00:00, 31.10file/s]"
-      }
-     },
-     "d1ad41f5d8c745daa87fa01040f39f81": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "d1b8e9aa118c434baea4ce3fed2fd41e": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "d644b0b5219743c38fbc79ec5f2a413e": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "d680ca0387114bec8b7d8db3fc69ce75": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "d712e591f1c841d29e07865dfe94bc05": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_fd45fe078ae142b7becc36f21ab7b455",
-        "IPY_MODEL_291884d7015249aa8c319ffeebbab550",
-        "IPY_MODEL_95b0991836ff42e3b094b13ffdfaffae"
-       ],
-       "layout": "IPY_MODEL_8c93479c548e422f80ece4ab82230c60"
-      }
-     },
-     "d78f00ee13ea477a8ab73eec4d28431c": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "d7d98c90410e405fb06ca685a4e110d7": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "d8a77bdbda5040ee9622c50eda3cb028": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "d8f1ca3388a24da1b11ca6c3a92d4b5b": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "d9e1075a05034b2daf5ae4af1022aa94": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_29af2523e95c4d5dbaa9adb76b492817",
-       "style": "IPY_MODEL_271171c6018d468ab8ed7b10aa40a590",
-       "value": " 1.00/? [00:00&lt;00:00, 24.9B/s]"
-      }
-     },
-     "db7c123e3cd142e2b4813c6e3a960fa4": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "db9a46b90c7640ee906189a5981cde64": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_8a61e9f8cd4d4d6592946cae74efbad0",
-        "IPY_MODEL_6c05528d741e41f5adb4a90353b5ef53",
-        "IPY_MODEL_8c193e75fb464c47b1214ebd94ebbaff"
-       ],
-       "layout": "IPY_MODEL_8942010860f947888d5965798ee45afc"
-      }
-     },
-     "dbaf5b346f674c0a858ef6a848bec165": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_6cb651aedc51425fbec47f27a6be9ae7",
-       "max": 115,
-       "style": "IPY_MODEL_937e9ea300ab4447b78a13effec6c492",
-       "value": 115
-      }
-     },
-     "dde500cb7b8242fab6e440a9396831d9": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_a1336165c66b4c2aa434c1a3fec3f64c",
-       "max": 1,
-       "style": "IPY_MODEL_6da46c359b144e90873b48f934030125"
-      }
-     },
-     "df40ca64039946c8a5b4ffe39368b108": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "e09230db12fc49c4aa9b1cc4132579ff": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "e1310103b37240b3b96f00504aed1fb6": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_0ff348ae46564d968020db92ca112bda",
-        "IPY_MODEL_2aee8cada4644f5b999c901717bd8738",
-        "IPY_MODEL_c84044d9182c4a079b5e6544984f275e"
-       ],
-       "layout": "IPY_MODEL_30f9dc5197754e75a8876bbb71d8f5e8"
-      }
-     },
-     "e1462a2b6de348cc8f33d8a89899638f": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "e1462a75fc5746f8b2665fb669861945": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_17bf04fa819b40219e9beadabb29b7c5",
-        "IPY_MODEL_327873754896413ab5405ed2b7806929",
-        "IPY_MODEL_6a986a0d90e2472cbc303acfbf30e5e0"
-       ],
-       "layout": "IPY_MODEL_61bdd92fb2334ac58ad23d70fade3968"
-      }
-     },
-     "e1af015f87604c1da38e9b239e2cb245": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "flex": "2"
-      }
-     },
-     "e29ee39192ff46f88283e71ff431a230": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "e40f15bb04334d218372168c6cca289a": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "e563fc133b25432bb2c2adf5fe702eb6": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_aafa0a3dbe8b415ebafbaed2c8947a3b",
-       "style": "IPY_MODEL_01fe9acbf32c4e9f85fe4808dc168a7a",
-       "value": " 0.00/? [00:00&lt;?, ?B/s]"
-      }
-     },
-     "e566de2185874613b49505c7bfa726d5": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_d644b0b5219743c38fbc79ec5f2a413e",
-       "max": 52886,
-       "style": "IPY_MODEL_b80a0b834b0141b6ad4d0b107e2711ce",
-       "value": 52886
-      }
-     },
-     "e6f0b799d36e46a6bb529a17984ef7a1": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_1772512a86e547dabd6e04d4efd3c34e",
-        "IPY_MODEL_e566de2185874613b49505c7bfa726d5",
-        "IPY_MODEL_3f4a4c1b6411425fac29c4cee5a60017"
-       ],
-       "layout": "IPY_MODEL_4e0c490a8eb74c86a4256f5969a965ae"
-      }
-     },
-     "e79bd3627dc54cf8ad30dc99ed906dd4": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "info",
-       "layout": "IPY_MODEL_a626306a00ca4710a9044d2f697fcae3",
-       "max": 1,
-       "style": "IPY_MODEL_9c52e67acb594733928a16672fb66c3a",
-       "value": 1
-      }
-     },
-     "ebe893f80b9d47819bf914a4ba064a53": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_02f22b40afa244f58e3af27e9fc77886",
-       "style": "IPY_MODEL_81f3d64165f14f66baf8a9e86386bf02",
-       "value": " 3/3 [00:00&lt;00:00, 69.06carrots/s]"
-      }
-     },
-     "ed73c4698dc14453b87fc7969bf2dc2f": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "DescriptionStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "ef0b8dcba1224b96909517a948065519": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "f07dea83351848c990a11322e82a5478": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "FloatProgressModel",
-      "state": {
-       "bar_style": "success",
-       "layout": "IPY_MODEL_537aff289e3e42af89557bd5604b555f",
-       "max": 3,
-       "style": "IPY_MODEL_6eb037657e4e47cfa08d92ef1aff5b3d",
-       "value": 3
-      }
-     },
-     "f1fbb8e667ea4f85a22303514788c234": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_ff7272062b0d44f6a7f6481d2164f25e",
-        "IPY_MODEL_f07dea83351848c990a11322e82a5478",
-        "IPY_MODEL_ebe893f80b9d47819bf914a4ba064a53"
-       ],
-       "layout": "IPY_MODEL_ae684630e6744654b7e470539dde03b2"
-      }
-     },
-     "f2523b74e59e4205b0ec0ebd2e765940": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_c4d2e6939a674cc6893de18514a4e708",
-       "style": "IPY_MODEL_9bf4a38a541242fea78eefc7fa72de07",
-       "value": "quicklooks/S2A_MSIL1C_20201116T105331_N0209_R051_T31TCK_20201116T130215: 100%"
-      }
-     },
-     "f3eb570e7b594a4f9e8d9ef35fe64cf8": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "f71b8ecf5faa40598267a71a222b731e": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_cbc05aeb9102482fb012e888d154cdab",
-       "style": "IPY_MODEL_244bae2d8b5340cb8af3f6f39d9e92ce",
-       "value": "This will be also displayed: "
-      }
-     },
-     "f8d37b2d5b3e4173b2948c1733e079de": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "f9006c9cb3914908a0822081edcf9d3d": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HBoxModel",
-      "state": {
-       "children": [
-        "IPY_MODEL_f2523b74e59e4205b0ec0ebd2e765940",
-        "IPY_MODEL_7ad860a453894c48bb11adee1c6b87a1",
-        "IPY_MODEL_9b57cb5be33146a2bd4000e377f3883c"
-       ],
-       "layout": "IPY_MODEL_9c02540b8038464094375e39f05d6369"
-      }
-     },
-     "fb52dc0b1568450fa88389e4962955ab": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_ef0b8dcba1224b96909517a948065519",
-       "style": "IPY_MODEL_219820c194b843e78067877129a0c3a1",
-       "value": "quicklooks/S2B_MSIL1C_20201231T105349_N0209_R051_T31TCK_20201231T120402: 100%"
-      }
-     },
-     "fb659e31419940758f6495224b0c556b": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "300px"
-      }
-     },
-     "fc3e5a300d8b4889930d2bb0e16d95c9": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "ProgressStyleModel",
-      "state": {
-       "description_width": ""
-      }
-     },
-     "fd45fe078ae142b7becc36f21ab7b455": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_0d2e58c337ba419a8f57cba7ee7edaaa",
-       "style": "IPY_MODEL_5d02707ed9dd4e04abe112d64a628b32",
-       "value": "Downloaded products: 100%"
-      }
-     },
-     "feff37ac49ab455db2692829d288f2bd": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {
-       "display": "inline-flex",
-       "flex_flow": "row wrap",
-       "width": "100%"
-      }
-     },
-     "ff22fadc6c5f45b0b0a3b5f66675972e": {
-      "model_module": "@jupyter-widgets/base",
-      "model_module_version": "1.2.0",
-      "model_name": "LayoutModel",
-      "state": {}
-     },
-     "ff7272062b0d44f6a7f6481d2164f25e": {
-      "model_module": "@jupyter-widgets/controls",
-      "model_module_version": "1.5.0",
-      "model_name": "HTMLModel",
-      "state": {
-       "layout": "IPY_MODEL_9229a49e42494e979d82b203ecf1791f",
-       "style": "IPY_MODEL_380cbc0470cf47cd821b014c1cd6217c",
-       "value": "Eating carrots: 100%"
+       "layout": "IPY_MODEL_0e3c2a8e89fe4af4b6fcb07db3036276",
+       "max": 3887409,
+       "style": "IPY_MODEL_229601dc5e0743d8b13e0f5d8f7548c4",
+       "value": 3887409
       }
      }
     },
diff --git a/eodag/api/product/_assets.py b/eodag/api/product/_assets.py
new file mode 100644
index 00000000..c7a28a72
--- /dev/null
+++ b/eodag/api/product/_assets.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+# Copyright 2023, CS GROUP - France, https://www.csgroup.eu/
+#
+# This file is part of EODAG project
+#     https://www.github.com/CS-SI/EODAG
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from collections import UserDict
+
+
+class AssetsDict(UserDict):
+    """A UserDict object listing assets contained in a
+    :class:`~eodag.api.product._product.EOProduct` resulting from a search.
+
+    :param product: Product resulting from a search
+    :type product: :class:`~eodag.api.product._product.EOProduct`
+    :param args: (optional) Arguments used to init the dictionary
+    :type args: Any
+    :param kwargs: (optional) Additional named-arguments used to init the dictionary
+    :type kwargs: Any
+    """
+
+    def __init__(self, product, *args, **kwargs):
+        self.product = product
+        super(AssetsDict, self).__init__(*args, **kwargs)
+
+    def __setitem__(self, key, value):
+        super().__setitem__(key, Asset(self.product, key, value))
+
+    def as_dict(self):
+        """Builds a representation of AssetsDict to enable its serialization
+
+        :returns: The representation of a :class:`~eodag.api.product._assets.AssetsDict`
+                  as a Python dict
+        :rtype: dict
+        """
+        return {k: v.as_dict() for k, v in self.data.items()}
+
+
+class Asset(UserDict):
+    """A UserDict object containg one of the assets of a
+    :class:`~eodag.api.product._product.EOProduct` resulting from a search.
+
+    :param product: Product resulting from a search
+    :type product: :class:`~eodag.api.product._product.EOProduct`
+    :param key: asset key
+    :type key: str
+    :param args: (optional) Arguments used to init the dictionary
+    :type args: Any
+    :param kwargs: (optional) Additional named-arguments used to init the dictionary
+    :type kwargs: Any
+    """
+
+    def __init__(self, product, key, *args, **kwargs):
+        self.product = product
+        self.key = key
+        super(Asset, self).__init__(*args, **kwargs)
+
+    def as_dict(self):
+        """Builds a representation of Asset to enable its serialization
+
+        :returns: The representation of a :class:`~eodag.api.product._assets.Asset` as a
+                  Python dict
+        :rtype: dict
+        """
+        return self.data
+
+    def download(self, **kwargs):
+        """Downloads a single asset
+
+        :param kwargs: (optional) Additional named-arguments passed to `plugin.download()`
+        :type kwargs: Any
+        """
+        return self.product.download(asset=self.key, **kwargs)
diff --git a/eodag/api/product/_product.py b/eodag/api/product/_product.py
index ef5db84a..9c1f7b93 100644
--- a/eodag/api/product/_product.py
+++ b/eodag/api/product/_product.py
@@ -26,6 +26,7 @@ from requests import RequestException
 from shapely import geometry, wkb, wkt
 from shapely.errors import ShapelyError
 
+from eodag.api.product._assets import AssetsDict
 from eodag.api.product.drivers import DRIVERS, NoDriver
 from eodag.api.product.metadata_mapping import NOT_AVAILABLE, NOT_MAPPED
 from eodag.plugins.download.base import DEFAULT_DOWNLOAD_TIMEOUT, DEFAULT_DOWNLOAD_WAIT
@@ -90,6 +91,7 @@ class EOProduct:
         self.provider = provider
         self.product_type = kwargs.get("productType")
         self.location = self.remote_location = properties.get("downloadLink", "")
+        self.assets = AssetsDict(self)
         self.properties = {
             key: value
             for key, value in properties.items()
@@ -175,6 +177,7 @@ class EOProduct:
             "type": "Feature",
             "geometry": geometry.mapping(self.geometry),
             "id": self.properties["id"],
+            "assets": self.assets.as_dict(),
             "properties": {
                 "eodag_product_type": self.product_type,
                 "eodag_provider": self.provider,
@@ -210,6 +213,7 @@ class EOProduct:
         obj.search_intersection = geometry.shape(
             feature["properties"]["eodag_search_intersection"]
         )
+        obj.assets = AssetsDict(obj, feature.get("assets", {}))
         return obj
 
     # Implementation of geo-interface protocol (See
diff --git a/eodag/plugins/download/aws.py b/eodag/plugins/download/aws.py
index a4c98b54..7f59a744 100644
--- a/eodag/plugins/download/aws.py
+++ b/eodag/plugins/download/aws.py
@@ -239,7 +239,14 @@ class AwsDownload(Download):
             product.product_type, {}
         )
 
-        build_safe = product_conf.get("build_safe", False)
+        # do not try to build SAFE if asset filter is used
+        asset_filter = kwargs.get("asset", None)
+        if asset_filter:
+            build_safe = False
+        else:
+            build_safe = product_conf.get("build_safe", False)
+
+        ignore_assets = getattr(self.config, "ignore_assets", False)
 
         # product conf overrides provider conf for "flatten_top_dirs"
         flatten_top_dirs = product_conf.get(
@@ -268,11 +275,25 @@ class AwsDownload(Download):
                     "SAFE metadata fetch format %s not implemented" % fetch_format
                 )
         # if assets are defined, use them instead of scanning product.location
-        if hasattr(product, "assets") and not getattr(
-            self.config, "ignore_assets", False
-        ):
+        if len(product.assets) > 0 and not ignore_assets:
+            if asset_filter:
+                filter_regex = re.compile(asset_filter)
+                assets_keys = getattr(product, "assets", {}).keys()
+                assets_keys = list(filter(filter_regex.fullmatch, assets_keys))
+                filtered_assets = {
+                    a_key: getattr(product, "assets", {})[a_key]
+                    for a_key in assets_keys
+                }
+                assets_values = [a for a in filtered_assets.values() if "href" in a]
+                if not assets_values:
+                    raise NotAvailableError(
+                        rf"No asset key matching re.fullmatch(r'{asset_filter}') was found in {product}"
+                    )
+            else:
+                assets_values = getattr(product, "assets", {}).values()
+
             bucket_names_and_prefixes = []
-            for complementary_url in getattr(product, "assets", {}).values():
+            for complementary_url in assets_values:
                 bucket_names_and_prefixes.append(
                     self.get_product_bucket_name_and_prefix(
                         product, complementary_url.get("href", "")
@@ -371,6 +392,20 @@ class AwsDownload(Download):
 
         unique_product_chunks = set(product_chunks)
 
+        # if asset_filter is used with ignore_assets, apply filtering on listed prefixes
+        if asset_filter and ignore_assets:
+            filter_regex = re.compile(asset_filter)
+            unique_product_chunks = set(
+                filter(
+                    lambda c: filter_regex.fullmatch(os.path.basename(c.key)),
+                    unique_product_chunks,
+                )
+            )
+            if not unique_product_chunks:
+                raise NotAvailableError(
+                    rf"No file basename matching re.fullmatch(r'{asset_filter}') was found in {product.remote_location}"
+                )
+
         total_size = sum([p.size for p in unique_product_chunks])
 
         # download
@@ -432,12 +467,14 @@ class AwsDownload(Download):
         if build_safe:
             self.check_manifest_file_list(product_local_path)
 
-        # save hash/record file
-        with open(record_filename, "w") as fh:
-            fh.write(product.remote_location)
-        logger.debug("Download recorded in %s", record_filename)
+        if asset_filter is None:
+            # save hash/record file
+            with open(record_filename, "w") as fh:
+                fh.write(product.remote_location)
+            logger.debug("Download recorded in %s", record_filename)
+
+            product.location = path_to_uri(product_local_path)
 
-        product.location = path_to_uri(product_local_path)
         return product_local_path
 
     def get_rio_env(self, bucket_name, prefix, auth_dict):
diff --git a/eodag/plugins/download/http.py b/eodag/plugins/download/http.py
index b0647e76..1cbbccaf 100644
--- a/eodag/plugins/download/http.py
+++ b/eodag/plugins/download/http.py
@@ -18,6 +18,7 @@
 
 import logging
 import os
+import re
 import shutil
 import zipfile
 from datetime import datetime
@@ -381,9 +382,7 @@ class HTTPDownload(Download):
             return fs_path
 
         # download assets if exist instead of remote_location
-        if hasattr(product, "assets") and not getattr(
-            self.config, "ignore_assets", False
-        ):
+        if len(product.assets) > 0 and not getattr(self.config, "ignore_assets", False):
             try:
                 fs_path = self._download_assets(
                     product,
@@ -394,8 +393,11 @@ class HTTPDownload(Download):
                     **kwargs,
                 )
                 return fs_path
-            except NotAvailableError:
-                pass
+            except NotAvailableError as e:
+                if kwargs.get("asset", None) is not None:
+                    raise NotAvailableError(e).with_traceback(e.__traceback__)
+                else:
+                    pass
 
         url = product.remote_location
 
@@ -483,28 +485,54 @@ class HTTPDownload(Download):
         :rtype: dict
         """
         # download assets if exist instead of remote_location
-        if hasattr(product, "assets") and not getattr(
-            self.config, "ignore_assets", False
-        ):
+        if len(product.assets) > 0 and not getattr(self.config, "ignore_assets", False):
             try:
+                assets_values = self._get_assets_values(product, **kwargs)
+
                 chunks_tuples = self._stream_download_assets(
-                    product, auth, progress_callback, **kwargs
+                    product,
+                    auth,
+                    progress_callback,
+                    assets_values=assets_values,
+                    **kwargs,
                 )
 
-                outputs_filename = (
-                    sanitize(product.properties["title"])
-                    if "title" in product.properties
-                    else sanitize(product.properties.get("id", "download"))
-                )
-                return dict(
-                    content=stream_zip(chunks_tuples),
-                    media_type="application/zip",
-                    headers={
-                        "content-disposition": f"attachment; filename={outputs_filename}.zip",
-                    },
-                )
-            except NotAvailableError:
-                pass
+                if len(assets_values) == 1:
+                    # start reading chunks to set asset.headers
+                    first_chunks_tuple = next(chunks_tuples)
+
+                    # update headers
+                    assets_values[0].headers[
+                        "content-disposition"
+                    ] = f"attachment; filename={assets_values[0].filename}"
+                    if assets_values[0].get("type", None):
+                        assets_values[0].headers["content-type"] = assets_values[0][
+                            "type"
+                        ]
+
+                    return dict(
+                        content=chain(iter([first_chunks_tuple]), chunks_tuples),
+                        headers=assets_values[0].headers,
+                    )
+
+                else:
+                    outputs_filename = (
+                        sanitize(product.properties["title"])
+                        if "title" in product.properties
+                        else sanitize(product.properties.get("id", "download"))
+                    )
+                    return dict(
+                        content=stream_zip(chunks_tuples),
+                        media_type="application/zip",
+                        headers={
+                            "content-disposition": f"attachment; filename={outputs_filename}.zip",
+                        },
+                    )
+            except NotAvailableError as e:
+                if kwargs.get("asset", None) is not None:
+                    raise NotAvailableError(e).with_traceback(e.__traceback__)
+                else:
+                    pass
 
         chunks = self._stream_download(
             product, auth, progress_callback, wait, timeout, **kwargs
@@ -646,6 +674,29 @@ class HTTPDownload(Download):
                         progress_callback(len(chunk))
                         yield chunk
 
+    def _get_assets_values(
+        self,
+        product,
+        **kwargs,
+    ):
+        asset_filter = kwargs.get("asset", None)
+        if asset_filter:
+            filter_regex = re.compile(asset_filter)
+            assets_keys = getattr(product, "assets", {}).keys()
+            assets_keys = list(filter(filter_regex.fullmatch, assets_keys))
+            filtered_assets = {
+                a_key: getattr(product, "assets", {})[a_key] for a_key in assets_keys
+            }
+            assets_values = [a for a in filtered_assets.values() if "href" in a]
+            if not assets_values:
+                raise NotAvailableError(
+                    rf"No asset key matching re.fullmatch(r'{asset_filter}') was found in {product}"
+                )
+            else:
+                return assets_values
+        else:
+            return [a for a in getattr(product, "assets", {}).values() if "href" in a]
+
     def _stream_download_assets(
         self,
         product,
@@ -660,13 +711,12 @@ class HTTPDownload(Download):
         assets_urls = [
             a["href"] for a in getattr(product, "assets", {}).values() if "href" in a
         ]
-        assets_values = [
-            a for a in getattr(product, "assets", {}).values() if "href" in a
-        ]
 
         if not assets_urls:
             raise NotAvailableError("No assets available for %s" % product)
 
+        assets_values = kwargs.get("assets_values", [])
+
         # get extra parameters to pass to the query
         params = kwargs.pop("dl_url_params", None) or getattr(
             self.config, "dl_url_params", {}
@@ -693,9 +743,10 @@ class HTTPDownload(Download):
             asset_rel_path_parts_sanitized = [
                 sanitize(part) for part in asset_rel_path_parts
             ]
-            asset["rel_path"] = os.path.join(*asset_rel_path_parts_sanitized)
-            asset_rel_paths_list.append(asset["rel_path"])
-        assets_common_subdir = os.path.commonpath(asset_rel_paths_list)
+            asset.rel_path = os.path.join(*asset_rel_path_parts_sanitized)
+            asset_rel_paths_list.append(asset.rel_path)
+        if asset_rel_paths_list:
+            assets_common_subdir = os.path.commonpath(asset_rel_paths_list)
 
         # product conf overrides provider conf for "flatten_top_dirs"
         product_conf = getattr(self.config, "products", {}).get(
@@ -725,38 +776,45 @@ class HTTPDownload(Download):
                 try:
                     stream.raise_for_status()
                 except RequestException as e:
-                    self._handle_asset_exception(e, asset)
+                    raise_errors = True if len(assets_values) == 1 else False
+                    self._handle_asset_exception(e, asset, raise_errors=raise_errors)
                 else:
                     asset_rel_path = (
-                        asset["rel_path"]
-                        .replace(assets_common_subdir, "")
-                        .strip(os.sep)
+                        asset.rel_path.replace(assets_common_subdir, "").strip(os.sep)
                         if flatten_top_dirs
-                        else asset["rel_path"]
+                        else asset.rel_path
                     )
                     asset_rel_dir = os.path.dirname(asset_rel_path)
 
-                    if not asset.get("filename", None):
+                    if not getattr(asset, "filename", None):
                         # try getting filename in GET header if was not found in HEAD result
                         asset_content_disposition = stream.headers.get(
                             "content-disposition", None
                         )
                         if asset_content_disposition:
-                            asset["filename"] = parse_header(
+                            asset.filename = parse_header(
                                 asset_content_disposition
                             ).get_param("filename", None)
 
-                    if not asset.get("filename", None):
+                    if not getattr(asset, "filename", None):
                         # default filename extracted from path
-                        asset["filename"] = os.path.basename(asset["rel_path"])
-
-                    yield (
-                        os.path.join(asset_rel_dir, asset["filename"]),
-                        modified_at,
-                        perms,
-                        NO_COMPRESSION_64,
-                        get_chunks(stream),
-                    )
+                        asset.filename = os.path.basename(asset.rel_path)
+
+                    asset.rel_path = os.path.join(asset_rel_dir, asset.filename)
+
+                    if len(assets_values) == 1:
+                        # apply headers to asset
+                        product.assets[assets_values[0].key].headers = stream.headers
+                        yield from get_chunks(stream)
+                    else:
+                        # several assets to zip
+                        yield (
+                            asset.rel_path,
+                            modified_at,
+                            perms,
+                            NO_COMPRESSION_64,
+                            get_chunks(stream),
+                        )
 
     def _download_assets(
         self,
@@ -771,15 +829,13 @@ class HTTPDownload(Download):
         assets_urls = [
             a["href"] for a in getattr(product, "assets", {}).values() if "href" in a
         ]
-        assets_values = [
-            a for a in getattr(product, "assets", {}).values() if "href" in a
-        ]
-
         if not assets_urls:
             raise NotAvailableError("No assets available for %s" % product)
 
+        assets_values = self._get_assets_values(product, **kwargs)
+
         chunks_tuples = self._stream_download_assets(
-            product, auth, progress_callback, **kwargs
+            product, auth, progress_callback, assets_values=assets_values, **kwargs
         )
 
         # remove existing incomplete file
@@ -804,6 +860,12 @@ class HTTPDownload(Download):
                 local_assets_count += 1
                 continue
 
+        if len(assets_values) == 1 and local_assets_count == 0:
+            # start reading chunks to set asset.rel_path
+            first_chunks_tuple = next(chunks_tuples)
+            chunks = chain(iter([first_chunks_tuple]), chunks_tuples)
+            chunks_tuples = [(assets_values[0].rel_path, None, None, None, chunks)]
+
         for chunk_tuple in chunks_tuples:
             asset_path = chunk_tuple[0]
             asset_chunks = chunk_tuple[4]
@@ -840,14 +902,15 @@ class HTTPDownload(Download):
         if flatten_top_dirs:
             flatten_top_directories(fs_dir_path)
 
-        # save hash/record file
-        with open(record_filename, "w") as fh:
-            fh.write(product.remote_location)
-        logger.debug("Download recorded in %s", record_filename)
+        if kwargs.get("asset", None) is None:
+            # save hash/record file
+            with open(record_filename, "w") as fh:
+                fh.write(product.remote_location)
+            logger.debug("Download recorded in %s", record_filename)
 
         return fs_dir_path
 
-    def _handle_asset_exception(self, e, asset):
+    def _handle_asset_exception(self, e, asset, raise_errors=False):
         # check if error is identified as auth_error in provider conf
         auth_errors = getattr(self.config, "auth_error_code", [None])
         if not isinstance(auth_errors, list):
@@ -861,6 +924,8 @@ class HTTPDownload(Download):
                     self.provider,
                 )
             )
+        elif raise_errors:
+            raise DownloadError(e)
         else:
             logger.warning("Unexpected error: %s" % e)
             logger.warning("Skipping %s" % asset["href"])
@@ -879,25 +944,25 @@ class HTTPDownload(Download):
                     timeout=HTTP_REQ_TIMEOUT,
                 ).headers
 
-                if not asset.get("size", 0):
+                if not getattr(asset, "size", 0):
                     # size from HEAD header / Content-length
-                    asset["size"] = int(asset_headers.get("Content-length", 0))
+                    asset.size = int(asset_headers.get("Content-length", 0))
 
-                if not asset.get("size", 0) or not asset.get("filename", 0):
+                if not getattr(asset, "size", 0) or not getattr(asset, "filename", 0):
                     # header content-disposition
                     header_content_disposition = parse_header(
                         asset_headers.get("content-disposition", "")
                     )
-                if not asset.get("size", 0):
+                if not getattr(asset, "size", 0):
                     # size from HEAD header / content-disposition / size
-                    asset["size"] = int(header_content_disposition.get_param("size", 0))
-                if not asset.get("filename", 0):
+                    asset.size = int(header_content_disposition.get_param("size", 0))
+                if not getattr(asset, "filename", 0):
                     # filename from HEAD header / content-disposition / size
-                    asset["filename"] = header_content_disposition.get_param(
+                    asset.filename = header_content_disposition.get_param(
                         "filename", None
                     )
 
-                if not asset.get("size", 0):
+                if not getattr(asset, "size", 0):
                     # GET request for size
                     with requests.get(
                         asset["href"],
@@ -908,79 +973,18 @@ class HTTPDownload(Download):
                         timeout=DEFAULT_STREAM_REQUESTS_TIMEOUT,
                     ) as stream:
                         # size from GET header / Content-length
-                        asset["size"] = int(stream.headers.get("Content-length", 0))
-                        if not asset.get("size", 0):
+                        asset.size = int(stream.headers.get("Content-length", 0))
+                        if not getattr(asset, "size", 0):
                             # size from GET header / content-disposition / size
-                            asset["size"] = int(
+                            asset.size = int(
                                 parse_header(
                                     stream.headers.get("content-disposition", "")
                                 ).get_param("size", 0)
                             )
 
-                total_size += asset["size"]
+                total_size += asset.size
         return total_size
 
-    def _stream_assets(self, product, auth=None, progress_callback=None, **kwargs):
-        assets_values = [
-            a for a in getattr(product, "assets", {}).values() if "href" in a
-        ]
-
-        # get extra parameters to pass to the query
-        params = kwargs.pop("dl_url_params", None) or getattr(
-            self.config, "dl_url_params", {}
-        )
-
-        total_size = self._get_asset_sizes(assets_values, auth, params)
-        progress_callback.reset(total_size)
-
-        # zipped files properties
-        modified_at = datetime.now()
-        perms = 0o600
-
-        def get_chunks(stream):
-            for chunk in stream.iter_content(chunk_size=64 * 1024):
-                if chunk:
-                    progress_callback(len(chunk))
-                    yield chunk
-
-        for asset in assets_values:
-            with requests.get(
-                asset["href"],
-                stream=True,
-                auth=auth,
-                params=params,
-                headers=USER_AGENT,
-                timeout=DEFAULT_STREAM_REQUESTS_TIMEOUT,
-            ) as stream:
-                try:
-                    stream.raise_for_status()
-                except RequestException as e:
-                    self._handle_asset_exception(e, asset)
-                else:
-                    asset_rel_path = urlparse(asset["href"]).path.strip("/")
-
-                    if not asset.get("filename", None):
-                        # try getting filename in GET header if was not found in HEAD result
-                        asset_content_disposition = stream.headers.get(
-                            "content-disposition", None
-                        )
-                        if asset_content_disposition:
-                            asset["filename"] = parse_header(
-                                asset_content_disposition
-                            ).get_param("filename", None)
-
-                    if not asset.get("filename", None):
-                        # default filename extracted from path
-                        asset["filename"] = os.path.basename(asset_rel_path)
-
-                    yield (
-                        asset["filename"],
-                        modified_at,
-                        perms,
-                        NO_COMPRESSION_64,
-                        get_chunks(stream),
-                    )
-
     def download_all(
         self,
         products,
diff --git a/eodag/plugins/search/qssearch.py b/eodag/plugins/search/qssearch.py
index 5f40fff7..6c4b18d9 100644
--- a/eodag/plugins/search/qssearch.py
+++ b/eodag/plugins/search/qssearch.py
@@ -1162,6 +1162,6 @@ class StacSearch(PostJsonSearch):
 
         # move assets from properties to product's attr
         for product in products:
-            product.assets = product.properties.pop("assets", {})
+            product.assets.update(product.properties.pop("assets", {}))
 
         return products
diff --git a/eodag/rest/server.py b/eodag/rest/server.py
index 8fdcac83..5f2e3a0c 100755
--- a/eodag/rest/server.py
+++ b/eodag/rest/server.py
@@ -323,7 +323,7 @@ class SearchBody(BaseModel):
     include_in_schema=False,
 )
 def stac_collections_item_download(collection_id, item_id, request: Request):
-    """STAC collection item local download"""
+    """STAC collection item download"""
     logger.debug(f"URL: {request.url}")
 
     arguments = dict(request.query_params)
@@ -334,6 +334,25 @@ def stac_collections_item_download(collection_id, item_id, request: Request):
     )
 
 
+@router.get(
+    "/collections/{collection_id}/items/{item_id}/download/{asset_filter}",
+    tags=["Data"],
+    include_in_schema=False,
+)
+def stac_collections_item_download_asset(
+    collection_id, item_id, asset_filter, request: Request
+):
+    """STAC collection item asset download"""
+    logger.debug(f"URL: {request.url}")
+
+    arguments = dict(request.query_params)
+    provider = arguments.pop("provider", None)
+
+    return download_stac_item_by_id_stream(
+        catalogs=[collection_id], item_id=item_id, provider=provider, asset=asset_filter
+    )
+
+
 @router.get(
     "/collections/{collection_id}/items/{item_id}",
     tags=["Data"],
@@ -476,6 +495,7 @@ def collections(request: Request):
         arguments=arguments,
         provider=provider,
     )
+
     return jsonable_encoder(response)
 
 
@@ -485,7 +505,7 @@ def collections(request: Request):
     include_in_schema=False,
 )
 def stac_catalogs_item_download(catalogs, item_id, request: Request):
-    """STAC item local download"""
+    """STAC Catalog item download"""
     logger.debug(f"URL: {request.url}")
 
     arguments = dict(request.query_params)
@@ -498,6 +518,27 @@ def stac_catalogs_item_download(catalogs, item_id, request: Request):
     )
 
 
+@router.get(
+    "/catalogs/{catalogs:path}/items/{item_id}/download/{asset_filter}",
+    tags=["Data"],
+    include_in_schema=False,
+)
+def stac_catalogs_item_download_asset(
+    catalogs, item_id, asset_filter, request: Request
+):
+    """STAC Catalog item asset download"""
+    logger.debug(f"URL: {request.url}")
+
+    arguments = dict(request.query_params)
+    provider = arguments.pop("provider", None)
+
+    catalogs = catalogs.strip("/").split("/")
+
+    return download_stac_item_by_id_stream(
+        catalogs=catalogs, item_id=item_id, provider=provider, asset=asset_filter
+    )
+
+
 @router.get(
     "/catalogs/{catalogs:path}/items/{item_id}",
     tags=["Data"],
diff --git a/eodag/rest/stac.py b/eodag/rest/stac.py
index 46b74b7b..03eb4821 100644
--- a/eodag/rest/stac.py
+++ b/eodag/rest/stac.py
@@ -222,18 +222,18 @@ class StacItem(StacCommon):
                 },
             )
 
+            product_dict = deepcopy(product.__dict__)
+            product_dict["assets"] = product.assets.as_dict()
+
             product_item = jsonpath_parse_dict_items(
                 item_model,
                 {
-                    "product": product.__dict__,
+                    "product": product_dict,
                     "providers": [provider_dict],
                 },
             )
-            # add origin assets to product assets
-            origin_assets = product_item["assets"].pop("origin_assets")
-            if getattr(product, "assets", False):
-                product_item["assets"] = dict(product_item["assets"], **origin_assets)
-            # append provider query-arg to download link if specified
+
+            # append provider query-arg to download link
             if self.provider:
                 parts = urlparse(product_item["assets"]["downloadLink"]["href"])
                 query_dict = parse_qs(parts.query)
@@ -247,6 +247,30 @@ class StacItem(StacCommon):
                     "href"
                 ] = f"{without_arg_url}?{urlencode(query_dict, doseq=True)}"
 
+            # add origin assets to product assets
+            origin_assets = product_item["assets"].pop("origin_assets")
+            if getattr(product, "assets", False):
+                # replace origin asset urls with eodag-server ones
+                for asset_key, asset_value in origin_assets.items():
+
+                    parts = urlparse(product_item["assets"]["downloadLink"]["href"])
+                    if parts.query:
+                        query_dict = parse_qs(parts.query)
+                        without_arg_url = (
+                            f"{parts.scheme}://{parts.netloc}{parts.path}"
+                            if parts.scheme
+                            else f"{parts.netloc}{parts.path}"
+                        ) + f"/{asset_key}"
+                        origin_assets[asset_key][
+                            "href"
+                        ] = f"{without_arg_url}?{urlencode(query_dict, doseq=True)}"
+                    else:
+                        origin_assets[asset_key][
+                            "href"
+                        ] = f"{product_item['assets']['downloadLink']['href']}/{asset_key}"
+
+                product_item["assets"] = dict(product_item["assets"], **origin_assets)
+
             # apply conversion if needed
             for prop_key, prop_val in need_conversion.items():
                 conv_func, conv_args = prop_val
@@ -478,11 +502,14 @@ class StacItem(StacCommon):
             catalogs=[product_type],
         )
 
+        product_dict = deepcopy(product.__dict__)
+        product_dict["assets"] = product.assets.as_dict()
+
         # parse jsonpath
         product_item = jsonpath_parse_dict_items(
             item_model,
             {
-                "product": product.__dict__,
+                "product": product_dict,
                 "providers": provider_dict,
             },
         )
diff --git a/eodag/rest/utils.py b/eodag/rest/utils.py
index a377fd22..41879e88 100644
--- a/eodag/rest/utils.py
+++ b/eodag/rest/utils.py
@@ -597,7 +597,7 @@ def get_stac_item_by_id(url, item_id, catalogs, root="/", provider=None):
         return None
 
 
-def download_stac_item_by_id_stream(catalogs, item_id, provider=None):
+def download_stac_item_by_id_stream(catalogs, item_id, provider=None, asset=None):
     """Download item
 
     :param catalogs: Catalogs list (only first is used as product_type)
@@ -606,9 +606,7 @@ def download_stac_item_by_id_stream(catalogs, item_id, provider=None):
     :type item_id: str
     :param provider: (optional) Chosen provider
     :type provider: str
-    :param zip: if the downloaded filed should be zipped
-    :type zip: str
-    :returns: a stream of the downloaded data (either as a zip or the individual assets)
+    :returns: a stream of the downloaded data (zip file)
     :rtype: StreamingResponse
     """
     product_type = catalogs[0]
@@ -658,13 +656,13 @@ def download_stac_item_by_id_stream(catalogs, item_id, provider=None):
     )
     try:
         download_stream_dict = product.downloader._stream_download_dict(
-            product, auth=auth
+            product, auth=auth, asset=asset
         )
     except NotImplementedError:
         logger.warning(
             f"Download streaming not supported for {product.downloader}: downloading locally then delete"
         )
-        product_path = eodag_api.download(product, extract=False)
+        product_path = eodag_api.download(product, extract=False, asset=asset)
         if os.path.isdir(product_path):
             # do not zip if dir contains only one file
             all_filenames = next(os.walk(product_path), (None, None, []))[2]


Test patch:
diff --git a/tests/units/test_download_plugins.py b/tests/units/test_download_plugins.py
index a9c3cf43..32097b13 100644
--- a/tests/units/test_download_plugins.py
+++ b/tests/units/test_download_plugins.py
@@ -15,6 +15,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+import io
 import os
 import shutil
 import stat
@@ -180,7 +181,11 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
             self.product.remote_location
         ) = "http://somewhere/dowload_from_location"
         self.product.properties["id"] = "someproduct"
-        self.product.assets = {"foo": {"href": "http://somewhere/download_asset"}}
+        self.product.assets.clear()
+        self.product.assets.update({"foo": {"href": "http://somewhere/download_asset"}})
+        mock_requests_get.return_value.__enter__.return_value.iter_content.side_effect = lambda *x, **y: io.BytesIO(
+            b"some content"
+        )
 
         # download asset if ignore_assets = False
         plugin.config.ignore_assets = False
@@ -234,9 +239,13 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         plugin = self.get_download_plugin(self.product)
         self.product.location = self.product.remote_location = "http://somewhere"
         self.product.properties["id"] = "someproduct"
-        self.product.assets = {
-            "foo": {"href": "http://somewhere/mal:for;matted/something?foo=bar#baz"}
-        }
+        self.product.assets.clear()
+        self.product.assets.update(
+            {"foo": {"href": "http://somewhere/mal:for;matted/something?foo=bar#baz"}}
+        )
+        mock_requests_get.return_value.__enter__.return_value.iter_content.return_value = io.BytesIO(
+            b"some content"
+        )
         mock_requests_get.return_value.__enter__.return_value.headers = {
             "content-disposition": ""
         }
@@ -282,7 +291,11 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         plugin = self.get_download_plugin(self.product)
         self.product.location = self.product.remote_location = "http://somewhere"
         self.product.properties["id"] = "someproduct"
-        self.product.assets = {"foo": {"href": "http://somewhere/something"}}
+        self.product.assets.clear()
+        self.product.assets.update({"foo": {"href": "http://somewhere/something"}})
+        mock_requests_get.return_value.__enter__.return_value.iter_content.return_value = io.BytesIO(
+            b"some content"
+        )
         mock_requests_get.return_value.__enter__.return_value.headers = {
             "content-disposition": '; filename = "somethingelse"'
         }
@@ -298,6 +311,47 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
             )
         )
 
+    @mock.patch("eodag.plugins.download.http.requests.head", autospec=True)
+    @mock.patch("eodag.plugins.download.http.requests.get", autospec=True)
+    def test_plugins_download_http_asset_filter(
+        self, mock_requests_get, mock_requests_head
+    ):
+        """HTTPDownload.download() must create an outputfile"""
+
+        plugin = self.get_download_plugin(self.product)
+        self.product.location = self.product.remote_location = "http://somewhere"
+        self.product.properties["id"] = "someproduct"
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "somewhere": {"href": "http://somewhere/something", "title": "foo"},
+                "elsewhere": {"href": "http://elsewhere/anything", "title": "boo"},
+            }
+        )
+        mock_requests_get.return_value.__enter__.return_value.iter_content.return_value = io.BytesIO(
+            b"some content"
+        )
+        mock_requests_get.return_value.__enter__.return_value.headers = {
+            "content-disposition": '; filename = "somethingelse"'
+        }
+        mock_requests_head.return_value.headers = {"content-disposition": ""}
+
+        path = plugin.download(
+            self.product, outputs_prefix=self.output_dir, asset="else.*"
+        )
+
+        self.assertEqual(path, os.path.join(self.output_dir, "dummy_product"))
+        self.assertTrue(os.path.isdir(path))
+        self.assertTrue(
+            os.path.isfile(
+                os.path.join(self.output_dir, "dummy_product", "somethingelse")
+            )
+        )
+        self.assertEqual(2, mock_requests_get.call_count)
+        self.product.location = self.product.remote_location = "http://elsewhere"
+        plugin.download(self.product, outputs_prefix=self.output_dir)
+        self.assertEqual(6, mock_requests_get.call_count)
+
     @mock.patch("eodag.plugins.download.http.requests.head", autospec=True)
     @mock.patch("eodag.plugins.download.http.requests.get", autospec=True)
     def test_plugins_download_http_assets_filename_from_head(
@@ -308,7 +362,11 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         plugin = self.get_download_plugin(self.product)
         self.product.location = self.product.remote_location = "http://somewhere"
         self.product.properties["id"] = "someproduct"
-        self.product.assets = {"foo": {"href": "http://somewhere/something"}}
+        self.product.assets.clear()
+        self.product.assets.update({"foo": {"href": "http://somewhere/something"}})
+        mock_requests_get.return_value.__enter__.return_value.iter_content.return_value = io.BytesIO(
+            b"some content"
+        )
         mock_requests_get.return_value.__enter__.return_value.headers = {
             "content-disposition": '; filename = "somethingelse"'
         }
@@ -336,15 +394,21 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
 
         plugin = self.get_download_plugin(self.product)
         self.product.location = self.product.remote_location = "http://somewhere"
-        self.product.assets = {
-            "foo": {"href": "http://somewhere/a"},
-            "bar": {"href": "http://somewhere/b"},
-        }
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "foo": {"href": "http://somewhere/a"},
+                "bar": {"href": "http://somewhere/b"},
+            }
+        )
 
         mock_requests_head.return_value.headers = {
             "Content-length": "1",
             "content-disposition": '; size = "2"',
         }
+        mock_requests_get.return_value.__enter__.return_value.iter_content.return_value = io.BytesIO(
+            b"some content"
+        )
         mock_requests_get.return_value.__enter__.return_value.headers = {
             "Content-length": "3",
             "content-disposition": '; size = "4"',
@@ -359,10 +423,13 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         mock_requests_head.return_value.headers.pop("Content-length")
         mock_progress_callback_reset.reset_mock()
         self.product.location = "http://somewhere"
-        self.product.assets = {
-            "foo": {"href": "http://somewhere/a"},
-            "bar": {"href": "http://somewhere/b"},
-        }
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "foo": {"href": "http://somewhere/a"},
+                "bar": {"href": "http://somewhere/b"},
+            }
+        )
         with TemporaryDirectory() as temp_dir:
             plugin.download(self.product, outputs_prefix=temp_dir)
         mock_progress_callback_reset.assert_called_once_with(mock.ANY, total=2 + 2)
@@ -371,24 +438,33 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         mock_requests_head.return_value.headers.pop("content-disposition")
         mock_progress_callback_reset.reset_mock()
         self.product.location = "http://somewhere"
-        self.product.assets = {
-            "foo": {"href": "http://somewhere/a"},
-            "bar": {"href": "http://somewhere/b"},
-        }
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "foo": {"href": "http://somewhere/a"},
+                "bar": {"href": "http://somewhere/b"},
+            }
+        )
         with TemporaryDirectory() as temp_dir:
             plugin.download(self.product, outputs_prefix=temp_dir)
         mock_progress_callback_reset.assert_called_once_with(mock.ANY, total=3 + 3)
 
         # size from GET / content-disposition
+        mock_requests_get.return_value.__enter__.return_value.iter_content.return_value = io.BytesIO(
+            b"some content"
+        )
         mock_requests_get.return_value.__enter__.return_value.headers.pop(
             "Content-length"
         )
         mock_progress_callback_reset.reset_mock()
         self.product.location = "http://somewhere"
-        self.product.assets = {
-            "foo": {"href": "http://somewhere/a"},
-            "bar": {"href": "http://somewhere/b"},
-        }
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "foo": {"href": "http://somewhere/a"},
+                "bar": {"href": "http://somewhere/b"},
+            }
+        )
         with TemporaryDirectory() as temp_dir:
             plugin.download(self.product, outputs_prefix=temp_dir)
         mock_progress_callback_reset.assert_called_once_with(mock.ANY, total=4 + 4)
@@ -401,13 +477,16 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         plugin = self.get_download_plugin(self.product)
         self.product.location = self.product.remote_location = "http://somewhere"
         self.product.properties["id"] = "someproduct"
-        self.product.assets = {
-            "foo": {
-                "href": path_to_uri(
-                    os.path.abspath(os.path.join(os.sep, "somewhere", "something"))
-                )
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "foo": {
+                    "href": path_to_uri(
+                        os.path.abspath(os.path.join(os.sep, "somewhere", "something"))
+                    )
+                }
             }
-        }
+        )
 
         path = plugin.download(self.product, outputs_prefix=self.output_dir)
 
@@ -423,27 +502,30 @@ class TestDownloadPluginHttp(BaseDownloadPluginTest):
         plugin = self.get_download_plugin(self.product)
         self.product.location = self.product.remote_location = "http://somewhere"
         self.product.properties["id"] = "someproduct"
-        self.product.assets = {
-            "foo": {
-                "href": path_to_uri(
-                    os.path.abspath(os.path.join(os.sep, "somewhere", "something"))
-                )
-            },
-            "bar": {
-                "href": path_to_uri(
-                    os.path.abspath(
-                        os.path.join(os.sep, "somewhere", "something", "else")
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "foo": {
+                    "href": path_to_uri(
+                        os.path.abspath(os.path.join(os.sep, "somewhere", "something"))
                     )
-                )
-            },
-            "baz": {
-                "href": path_to_uri(
-                    os.path.abspath(
-                        os.path.join(os.sep, "somewhere", "another", "thing")
+                },
+                "bar": {
+                    "href": path_to_uri(
+                        os.path.abspath(
+                            os.path.join(os.sep, "somewhere", "something", "else")
+                        )
                     )
-                )
-            },
-        }
+                },
+                "baz": {
+                    "href": path_to_uri(
+                        os.path.abspath(
+                            os.path.join(os.sep, "somewhere", "another", "thing")
+                        )
+                    )
+                },
+            }
+        )
 
         path = plugin.download(self.product, outputs_prefix=self.output_dir)
 
@@ -976,10 +1058,13 @@ class TestDownloadPluginAws(BaseDownloadPluginTest):
         plugin = self.get_download_plugin(self.product)
         self.product.properties["tileInfo"] = "http://example.com/tileInfo.json"
         self.product.properties["tilePath"] = "http://example.com/tilePath"
-        self.product.assets = {
-            "file1": {"href": "http://example.com/path/to/file1"},
-            "file2": {"href": "http://example.com/path/to/file2"},
-        }
+        self.product.assets.clear()
+        self.product.assets.update(
+            {
+                "file1": {"href": "http://example.com/path/to/file1"},
+                "file2": {"href": "http://example.com/path/to/file2"},
+            }
+        )
         execpected_output = os.path.join(
             self.output_dir, self.product.properties["title"]
         )
@@ -1022,6 +1107,13 @@ class TestDownloadPluginAws(BaseDownloadPluginTest):
 
         self.assertEqual(path, execpected_output)
 
+        # with filter for assets
+        self.product.properties["title"] = "newTitle"
+        setattr(self.product, "location", "file://path/to/file")
+        plugin.download(self.product, outputs_prefix=self.output_dir, asset="file1")
+        # 3 additional calls
+        self.assertEqual(7, mock_get_chunk_dest_path.call_count)
+
 
 class TestDownloadPluginS3Rest(BaseDownloadPluginTest):
     def setUp(self):
diff --git a/tests/units/test_stac_utils.py b/tests/units/test_stac_utils.py
index f1ea97b5..265a8d7c 100644
--- a/tests/units/test_stac_utils.py
+++ b/tests/units/test_stac_utils.py
@@ -433,9 +433,9 @@ class TestStacUtils(unittest.TestCase):
 
         response = self.rest_utils.search_stac_items(
             url="http://foo/search",
-            arguments={},
+            arguments={"collections": "S2_MSI_L2A"},
             root="http://foo",
-            catalogs=["S2_MSI_L2A"],
+            catalogs=[],
             provider="earth_search",
         )
 
@@ -445,11 +445,18 @@ class TestStacUtils(unittest.TestCase):
         self.assertTrue(
             "downloadLink", "thumbnail" in response["features"][0]["assets"].keys()
         )
-        # check that assets from the provider response search are also in the response
+        # check that assets from the provider response search are reformatted in the response
+        product_id = self.earth_search_resp_search_json["features"][0]["properties"][
+            "sentinel:product_id"
+        ]
         for (k, v) in self.earth_search_resp_search_json["features"][0][
             "assets"
         ].items():
-            self.assertIn((k, v), response["features"][0]["assets"].items())
+            self.assertIn(k, response["features"][0]["assets"].keys())
+            self.assertEqual(
+                response["features"][0]["assets"][k]["href"],
+                f"http://foo/collections/S2_MSI_L2A/items/{product_id}/download/{k}?provider=earth_search",
+            )
         # preferred provider should not be changed
         self.assertEqual("peps", self.rest_utils.eodag_api.get_preferred_provider()[0])