Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- README.md +53 -12
- app.py +181 -0
- app_cachea.py +75 -0
- app_cdse_v0.py +127 -0
- requirements.txt +192 -0
README.md
CHANGED
|
@@ -1,12 +1,53 @@
|
|
| 1 |
-
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Sentinel-2 Image Browser
|
| 2 |
+
|
| 3 |
+
This application allows you to browse and view Sentinel-2 satellite imagery from the Copernicus Data Space Ecosystem. You can search by coordinates, select various landscapes, and filter by cloud cover.
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
## Installation
|
| 7 |
+
|
| 8 |
+
1. Clone the repository:
|
| 9 |
+
|
| 10 |
+
```bash
|
| 11 |
+
git clone git@github.com:pretty-map/mooc-pretty-map.git
|
| 12 |
+
cd mooc-pretty-map
|
| 13 |
+
```
|
| 14 |
+
|
| 15 |
+
2. Create and activate a conda environment:
|
| 16 |
+
|
| 17 |
+
```bash
|
| 18 |
+
conda create -n map python==3.13.2
|
| 19 |
+
conda activate map
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
3. Install the required dependencies:
|
| 23 |
+
|
| 24 |
+
```bash
|
| 25 |
+
pip install -r requirements.txt
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
3. Set up your credentials by creating a `.env` file in the root directory with the following content:
|
| 29 |
+
|
| 30 |
+
```bash
|
| 31 |
+
touch .env
|
| 32 |
+
```
|
| 33 |
+
then:
|
| 34 |
+
|
| 35 |
+
```
|
| 36 |
+
DESTINE_USERNAME=username
|
| 37 |
+
DESTINE_PASSWORD=password
|
| 38 |
+
ACCESS_KEY_ID=username
|
| 39 |
+
SECRET_ACCESS_KEY=password
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
## Running the Application
|
| 43 |
+
|
| 44 |
+
Start the application with:
|
| 45 |
+
|
| 46 |
+
```bash
|
| 47 |
+
python app_cdse_v0.py
|
| 48 |
+
```
|
| 49 |
+
or
|
| 50 |
+
|
| 51 |
+
```bash
|
| 52 |
+
python app_cdse_v1.py
|
| 53 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import numpy as np
|
| 4 |
+
import io
|
| 5 |
+
import random
|
| 6 |
+
from PIL import Image
|
| 7 |
+
from dotenv import load_dotenv
|
| 8 |
+
import pystac_client
|
| 9 |
+
from datetime import datetime
|
| 10 |
+
from src.auth.auth import S3Connector
|
| 11 |
+
from src.utils.utils import extract_s3_path_from_url
|
| 12 |
+
from src.utils.stac_client import ProductDownloader
|
| 13 |
+
|
| 14 |
+
# Load environment variables
|
| 15 |
+
load_dotenv()
|
| 16 |
+
|
| 17 |
+
# Get credentials from environment variables
|
| 18 |
+
ACCESS_KEY_ID = os.environ.get("ACCESS_KEY_ID")
|
| 19 |
+
SECRET_ACCESS_KEY = os.environ.get("SECRET_ACCESS_KEY")
|
| 20 |
+
ENDPOINT_URL = 'https://eodata.dataspace.copernicus.eu'
|
| 21 |
+
# Initialize the connector
|
| 22 |
+
s3_connector = S3Connector(
|
| 23 |
+
endpoint_url=ENDPOINT_URL,
|
| 24 |
+
access_key_id=ACCESS_KEY_ID,
|
| 25 |
+
secret_access_key=SECRET_ACCESS_KEY
|
| 26 |
+
)
|
| 27 |
+
# Connect to S3
|
| 28 |
+
s3_connector.connect()
|
| 29 |
+
s3_client = s3_connector.get_s3_client()
|
| 30 |
+
ENDPOINT_STAC = "https://stac.dataspace.copernicus.eu/v1/"
|
| 31 |
+
catalog = pystac_client.Client.open(ENDPOINT_STAC)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def fetch_sentinel_image(longitude, latitude, date_from, date_to, cloud_cover):
|
| 35 |
+
"""Fetch a Sentinel image based on criteria."""
|
| 36 |
+
try:
|
| 37 |
+
# Use the coordinates from inputs
|
| 38 |
+
LON, LAT = float(longitude), float(latitude)
|
| 39 |
+
|
| 40 |
+
# Use the date range from inputs
|
| 41 |
+
date_range = f"{date_from}/{date_to}"
|
| 42 |
+
|
| 43 |
+
cloud_query = f"eo:cloud_cover<{cloud_cover}"
|
| 44 |
+
|
| 45 |
+
items_txt = catalog.search(
|
| 46 |
+
collections=['sentinel-2-l2a'],
|
| 47 |
+
intersects=dict(type="Point", coordinates=[LON, LAT]),
|
| 48 |
+
datetime=date_range,
|
| 49 |
+
query=[cloud_query]
|
| 50 |
+
).item_collection()
|
| 51 |
+
|
| 52 |
+
if len(items_txt) == 0:
|
| 53 |
+
return None, f"No images found for the specified criteria at coordinates ({LON}, {LAT}) with cloud cover < {cloud_cover}%."
|
| 54 |
+
|
| 55 |
+
# Randomly select an image from the available items
|
| 56 |
+
selected_item = random.choice(items_txt)
|
| 57 |
+
|
| 58 |
+
# Format datetime for readability
|
| 59 |
+
datetime_str = selected_item.properties.get('datetime', 'N/A')
|
| 60 |
+
try:
|
| 61 |
+
dt = datetime.fromisoformat(datetime_str.replace('Z', '+00:00'))
|
| 62 |
+
formatted_date = dt.strftime('%Y-%m-%d %H:%M:%S UTC')
|
| 63 |
+
except:
|
| 64 |
+
formatted_date = datetime_str
|
| 65 |
+
|
| 66 |
+
# Extract metadata for display
|
| 67 |
+
metadata = f"""
|
| 68 |
+
## Product Information
|
| 69 |
+
- **Location**: {LAT}°N, {LON}°E
|
| 70 |
+
- **Date**: {formatted_date}
|
| 71 |
+
- **Cloud Cover**: {selected_item.properties.get('eo:cloud_cover', 'N/A')}%
|
| 72 |
+
- **Cloud Cover Threshold**: < {cloud_cover}%
|
| 73 |
+
- **Satellite**: {selected_item.properties.get('platform', 'N/A')}
|
| 74 |
+
- **Product ID**: {selected_item.id}
|
| 75 |
+
- **Items Found**: {len(items_txt)} matching products
|
| 76 |
+
"""
|
| 77 |
+
|
| 78 |
+
# Get the TCI_60m asset from the randomly selected item
|
| 79 |
+
product_url = extract_s3_path_from_url(selected_item.assets['TCI_60m'].href)
|
| 80 |
+
print(f"Selected product URL: {product_url}")
|
| 81 |
+
|
| 82 |
+
# Initialize the handler with the S3 connector
|
| 83 |
+
handler = ProductDownloader(s3_client=s3_client, bucket_name='eodata')
|
| 84 |
+
|
| 85 |
+
# Get the image content as bytes
|
| 86 |
+
product_bytes, filename = handler.get_product_content(product_url)
|
| 87 |
+
print(f"Downloaded {filename}, content size: {len(product_bytes)} bytes")
|
| 88 |
+
|
| 89 |
+
# Convert to PIL Image
|
| 90 |
+
img = Image.open(io.BytesIO(product_bytes))
|
| 91 |
+
|
| 92 |
+
return img, metadata
|
| 93 |
+
|
| 94 |
+
except ValueError as ve:
|
| 95 |
+
error_message = f"Invalid input: {str(ve)}. Please ensure longitude and latitude are valid numbers."
|
| 96 |
+
print(error_message)
|
| 97 |
+
return None, error_message
|
| 98 |
+
except Exception as e:
|
| 99 |
+
error_message = f"Error: {str(e)}"
|
| 100 |
+
print(error_message)
|
| 101 |
+
return None, error_message
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
# Create Gradio interface
|
| 105 |
+
with gr.Blocks(title="Sentinel Product Viewer") as demo:
|
| 106 |
+
gr.Markdown("# Sentinel-2 Product Viewer")
|
| 107 |
+
gr.Markdown("Browse and view Sentinel-2 satellite product")
|
| 108 |
+
|
| 109 |
+
with gr.Row():
|
| 110 |
+
with gr.Column(scale=1):
|
| 111 |
+
# Location inputs
|
| 112 |
+
with gr.Row():
|
| 113 |
+
longitude = gr.Number(label="Longitude", value=15.0, minimum=-180, maximum=180)
|
| 114 |
+
latitude = gr.Number(label="Latitude", value=50.0, minimum=-90, maximum=90)
|
| 115 |
+
|
| 116 |
+
# Date range inputs
|
| 117 |
+
with gr.Row():
|
| 118 |
+
date_from = gr.Textbox(label="Date From (YYYY-MM-DD)", value="2024-05-01")
|
| 119 |
+
date_to = gr.Textbox(label="Date To (YYYY-MM-DD)", value="2025-02-01")
|
| 120 |
+
|
| 121 |
+
# Cloud cover slider
|
| 122 |
+
cloud_cover = gr.Slider(
|
| 123 |
+
label="Max Cloud Cover (%)",
|
| 124 |
+
minimum=0,
|
| 125 |
+
maximum=100,
|
| 126 |
+
value=50,
|
| 127 |
+
step=5
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
# Diverse landscape location buttons
|
| 131 |
+
gr.Markdown("### Diverse Locations")
|
| 132 |
+
with gr.Row():
|
| 133 |
+
italy_btn = gr.Button("Italy")
|
| 134 |
+
amazon_btn = gr.Button("Amazon Rainforest")
|
| 135 |
+
with gr.Row():
|
| 136 |
+
tokyo_btn = gr.Button("Tokyo")
|
| 137 |
+
great_barrier_btn = gr.Button("Great Barrier Reef")
|
| 138 |
+
|
| 139 |
+
with gr.Row():
|
| 140 |
+
iceland_btn = gr.Button("Iceland Glacier")
|
| 141 |
+
canada_btn = gr.Button("Baffin Island")
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
fetch_btn = gr.Button("Fetch Random Image", variant="primary")
|
| 147 |
+
|
| 148 |
+
with gr.Column(scale=2):
|
| 149 |
+
image_output = gr.Image(type="pil", label="Sentinel-2 Image")
|
| 150 |
+
metadata_output = gr.Markdown(label="Image Metadata")
|
| 151 |
+
|
| 152 |
+
# Button click handlers for diverse landscapes
|
| 153 |
+
italy_btn.click(lambda: (12.39, 42.05), outputs=[longitude, latitude])
|
| 154 |
+
amazon_btn.click(lambda: (-64.7, -3.42), outputs=[longitude, latitude])
|
| 155 |
+
tokyo_btn.click(lambda: (139.70, 35.65), outputs=[longitude, latitude])
|
| 156 |
+
great_barrier_btn.click(lambda: (150.97, -20.92), outputs=[longitude, latitude])
|
| 157 |
+
|
| 158 |
+
iceland_btn.click(lambda: (-18.17, 64.61), outputs=[longitude, latitude])
|
| 159 |
+
# rice_terraces_btn.click(lambda: (121.1, 16.9), outputs=[longitude, latitude])
|
| 160 |
+
canada_btn.click(lambda: (-71.56, 67.03), outputs=[longitude, latitude])
|
| 161 |
+
|
| 162 |
+
# Main search button
|
| 163 |
+
fetch_btn.click(
|
| 164 |
+
fn=fetch_sentinel_image,
|
| 165 |
+
inputs=[longitude, latitude, date_from, date_to, cloud_cover],
|
| 166 |
+
outputs=[image_output, metadata_output]
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
gr.Markdown("## About")
|
| 170 |
+
gr.Markdown("""
|
| 171 |
+
This application allows you to browse and view Sentinel-2 satellite imagery using the Copernicus Data Space Ecosystem.
|
| 172 |
+
|
| 173 |
+
- **Location**: Enter longitude and latitude coordinates or select distinctive landscapes
|
| 174 |
+
- **TCI Images**: The images shown are true color (RGB) composites at 60m resolution
|
| 175 |
+
- **Date Range**: Specify the date range to search for images
|
| 176 |
+
- **Cloud Cover**: Adjust the maximum acceptable cloud cover percentage
|
| 177 |
+
- **Random Selection**: A random image that matches the criteria will be selected for display
|
| 178 |
+
""")
|
| 179 |
+
|
| 180 |
+
if __name__ == "__main__":
|
| 181 |
+
demo.launch(share=True)
|
app_cachea.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import numpy as np
|
| 4 |
+
from io import BytesIO
|
| 5 |
+
from PIL import Image
|
| 6 |
+
from dotenv import load_dotenv
|
| 7 |
+
|
| 8 |
+
from src.utils.stac_client import download_sentinel_image
|
| 9 |
+
|
| 10 |
+
# Load environment variables
|
| 11 |
+
load_dotenv()
|
| 12 |
+
USERNAME = os.environ.get("DESTINE_USERNAME")
|
| 13 |
+
PASSWORD = os.environ.get("DESTINE_PASSWORD")
|
| 14 |
+
|
| 15 |
+
def fetch_sentinel_image(date_from, date_to):
|
| 16 |
+
"""Fetch a Sentinel image based on criteria."""
|
| 17 |
+
# Validate date format
|
| 18 |
+
# Download the image
|
| 19 |
+
content, metadata = download_sentinel_image(
|
| 20 |
+
username=USERNAME,
|
| 21 |
+
password=PASSWORD,
|
| 22 |
+
start_date=date_from,
|
| 23 |
+
end_date= date_to
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
# Handle error case
|
| 27 |
+
if isinstance(content, str):
|
| 28 |
+
return None, content
|
| 29 |
+
|
| 30 |
+
# Convert to PIL Image
|
| 31 |
+
try:
|
| 32 |
+
img = Image.open(BytesIO(content))
|
| 33 |
+
|
| 34 |
+
# Create metadata string
|
| 35 |
+
metadata_str = "\n".join([
|
| 36 |
+
f"**Date:** {metadata.get('datetime', 'Unknown')}",
|
| 37 |
+
# f"**Cloud Cover:** {metadata.get('cloud_cover', 'Unknown')}%",
|
| 38 |
+
f"**Filename:** {metadata.get('filename', 'Unknown')}"
|
| 39 |
+
])
|
| 40 |
+
|
| 41 |
+
return img, metadata_str
|
| 42 |
+
except Exception as e:
|
| 43 |
+
return None, f"Error processing image: {str(e)}"
|
| 44 |
+
|
| 45 |
+
# Create Gradio interface
|
| 46 |
+
with gr.Blocks(title="Sentinel Image Viewer") as demo:
|
| 47 |
+
gr.Markdown("# Sentinel-2 Image Viewer")
|
| 48 |
+
gr.Markdown("Browse and view Sentinel-2 satellite imagery")
|
| 49 |
+
|
| 50 |
+
with gr.Row():
|
| 51 |
+
with gr.Column(scale=1):
|
| 52 |
+
date_from = gr.Textbox(label="Date From (YYYY-MM-DD)", value="2024-12-15")
|
| 53 |
+
date_to = gr.Textbox(label="Date To (YYYY-MM-DD)", value="2024-12-30")
|
| 54 |
+
fetch_btn = gr.Button("Fetch Image")
|
| 55 |
+
|
| 56 |
+
with gr.Column(scale=2):
|
| 57 |
+
image_output = gr.Image(type="pil", label="Sentinel-2 Image")
|
| 58 |
+
metadata_output = gr.Markdown(label="Image Metadata")
|
| 59 |
+
|
| 60 |
+
fetch_btn.click(
|
| 61 |
+
fn=fetch_sentinel_image,
|
| 62 |
+
inputs=[date_from, date_to],
|
| 63 |
+
outputs=[image_output, metadata_output]
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
gr.Markdown("## About")
|
| 67 |
+
gr.Markdown("""
|
| 68 |
+
This application allows you to browse and view Sentinel-2 satellite imagery using the DESTINE API.
|
| 69 |
+
|
| 70 |
+
- **TCI Images**: The images shown are true color (RGB) composites at 60m resolution.
|
| 71 |
+
- **Date Range**: Specify the date range to search for images.
|
| 72 |
+
""")
|
| 73 |
+
|
| 74 |
+
if __name__ == "__main__":
|
| 75 |
+
demo.launch(share=True)
|
app_cdse_v0.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import numpy as np
|
| 4 |
+
import io
|
| 5 |
+
import random
|
| 6 |
+
from PIL import Image
|
| 7 |
+
from dotenv import load_dotenv
|
| 8 |
+
import pystac_client
|
| 9 |
+
from datetime import datetime
|
| 10 |
+
from src.auth.auth import S3Connector
|
| 11 |
+
from src.utils.utils import extract_s3_path_from_url
|
| 12 |
+
from src.utils.stac_client import ProductDownloader
|
| 13 |
+
|
| 14 |
+
# Load environment variables
|
| 15 |
+
load_dotenv()
|
| 16 |
+
|
| 17 |
+
# Get credentials from environment variables
|
| 18 |
+
ACCESS_KEY_ID = os.environ.get("ACCESS_KEY_ID")
|
| 19 |
+
SECRET_ACCESS_KEY = os.environ.get("SECRET_ACCESS_KEY")
|
| 20 |
+
ENDPOINT_URL = 'https://eodata.dataspace.copernicus.eu'
|
| 21 |
+
# Initialize the connector
|
| 22 |
+
s3_connector = S3Connector(
|
| 23 |
+
endpoint_url=ENDPOINT_URL,
|
| 24 |
+
access_key_id=ACCESS_KEY_ID,
|
| 25 |
+
secret_access_key=SECRET_ACCESS_KEY
|
| 26 |
+
)
|
| 27 |
+
# Connect to S3
|
| 28 |
+
s3_connector.connect()
|
| 29 |
+
s3_client = s3_connector.get_s3_client()
|
| 30 |
+
ENDPOINT_STAC = "https://stac.dataspace.copernicus.eu/v1/"
|
| 31 |
+
catalog = pystac_client.Client.open(ENDPOINT_STAC)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def fetch_sentinel_image(date_from, date_to):
|
| 35 |
+
"""Fetch a Sentinel image based on criteria."""
|
| 36 |
+
try:
|
| 37 |
+
# Search for Sentinel-2 products
|
| 38 |
+
LON, LAT = 15, 50
|
| 39 |
+
|
| 40 |
+
# Use the date range from inputs
|
| 41 |
+
date_range = f"{date_from}/{date_to}"
|
| 42 |
+
|
| 43 |
+
items_txt = catalog.search(
|
| 44 |
+
collections=['sentinel-2-l2a'],
|
| 45 |
+
intersects=dict(type="Point", coordinates=[LON, LAT]),
|
| 46 |
+
datetime=date_range,
|
| 47 |
+
query=["eo:cloud_cover<10"]
|
| 48 |
+
).item_collection()
|
| 49 |
+
|
| 50 |
+
if len(items_txt) == 0:
|
| 51 |
+
return None, "No images found for the specified criteria."
|
| 52 |
+
|
| 53 |
+
# Randomly select an image from the available items
|
| 54 |
+
selected_item = random.choice(items_txt)
|
| 55 |
+
|
| 56 |
+
# Format datetime for readability
|
| 57 |
+
datetime_str = selected_item.properties.get('datetime', 'N/A')
|
| 58 |
+
try:
|
| 59 |
+
dt = datetime.fromisoformat(datetime_str.replace('Z', '+00:00'))
|
| 60 |
+
formatted_date = dt.strftime('%Y-%m-%d %H:%M:%S UTC')
|
| 61 |
+
except:
|
| 62 |
+
formatted_date = datetime_str
|
| 63 |
+
|
| 64 |
+
# Extract metadata for display
|
| 65 |
+
metadata = f"""
|
| 66 |
+
## Product Information
|
| 67 |
+
- **Date**: {formatted_date}
|
| 68 |
+
- **Cloud Cover**: {selected_item.properties.get('eo:cloud_cover', 'N/A')}%
|
| 69 |
+
- **Satellite**: {selected_item.properties.get('platform', 'N/A')}
|
| 70 |
+
- **Product ID**: {selected_item.id}
|
| 71 |
+
- **Items Found**: {len(items_txt)} matching products
|
| 72 |
+
"""
|
| 73 |
+
|
| 74 |
+
# Get the TCI_60m asset from the randomly selected item
|
| 75 |
+
product_url = extract_s3_path_from_url(selected_item.assets['TCI_60m'].href)
|
| 76 |
+
print(f"Selected product URL: {product_url}")
|
| 77 |
+
|
| 78 |
+
# Initialize the handler with the S3 connector
|
| 79 |
+
handler = ProductDownloader(s3_client=s3_client, bucket_name='eodata')
|
| 80 |
+
|
| 81 |
+
# Get the image content as bytes
|
| 82 |
+
product_bytes, filename = handler.get_product_content(product_url)
|
| 83 |
+
print(f"Downloaded {filename}, content size: {len(product_bytes)} bytes")
|
| 84 |
+
|
| 85 |
+
# Convert to PIL Image
|
| 86 |
+
img = Image.open(io.BytesIO(product_bytes))
|
| 87 |
+
|
| 88 |
+
return img, metadata
|
| 89 |
+
|
| 90 |
+
except Exception as e:
|
| 91 |
+
error_message = f"Error: {str(e)}"
|
| 92 |
+
print(error_message)
|
| 93 |
+
return None, error_message
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
# Create Gradio interface
|
| 97 |
+
with gr.Blocks(title="Sentinel Image Viewer") as demo:
|
| 98 |
+
gr.Markdown("# Sentinel-2 Image Viewer")
|
| 99 |
+
gr.Markdown("Browse and view Sentinel-2 satellite imagery")
|
| 100 |
+
|
| 101 |
+
with gr.Row():
|
| 102 |
+
with gr.Column(scale=1):
|
| 103 |
+
date_from = gr.Textbox(label="Date From (YYYY-MM-DD)", value="2024-05-01")
|
| 104 |
+
date_to = gr.Textbox(label="Date To (YYYY-MM-DD)", value="2024-05-30")
|
| 105 |
+
fetch_btn = gr.Button("Fetch Random Image")
|
| 106 |
+
|
| 107 |
+
with gr.Column(scale=2):
|
| 108 |
+
image_output = gr.Image(type="pil", label="Sentinel-2 Image")
|
| 109 |
+
metadata_output = gr.Markdown(label="Image Metadata")
|
| 110 |
+
|
| 111 |
+
fetch_btn.click(
|
| 112 |
+
fn=fetch_sentinel_image,
|
| 113 |
+
inputs=[date_from, date_to],
|
| 114 |
+
outputs=[image_output, metadata_output]
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
gr.Markdown("## About")
|
| 118 |
+
gr.Markdown("""
|
| 119 |
+
This application allows you to browse and view Sentinel-2 satellite imagery using the Copernicus Data Space Ecosystem.
|
| 120 |
+
|
| 121 |
+
- **TCI Images**: The images shown are true color (RGB) composites at 60m resolution.
|
| 122 |
+
- **Date Range**: Specify the date range to search for images.
|
| 123 |
+
- **Random Selection**: A random image that matches the criteria will be selected for display.
|
| 124 |
+
""")
|
| 125 |
+
|
| 126 |
+
if __name__ == "__main__":
|
| 127 |
+
demo.launch(share=True)
|
requirements.txt
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
aiohttp==3.11.16
|
| 2 |
+
backports.tarfile==1.2.0
|
| 3 |
+
bokeh==3.7.2
|
| 4 |
+
boto3==1.37.26
|
| 5 |
+
bottleneck==1.4.2
|
| 6 |
+
brotli==1.1.0
|
| 7 |
+
cartopy==0.24.1
|
| 8 |
+
cffi==1.17.1
|
| 9 |
+
conflator==0.1.7
|
| 10 |
+
crc32c==2.7.1
|
| 11 |
+
distributed==2025.3.0
|
| 12 |
+
dotenv==0.9.9
|
| 13 |
+
exceptiongroup==1.2.2
|
| 14 |
+
flox==0.10.1
|
| 15 |
+
folium==0.19.5
|
| 16 |
+
geodatasets==2024.8.0
|
| 17 |
+
geopandas==1.0.1
|
| 18 |
+
gradio==5.23.3
|
| 19 |
+
h2==4.2.0
|
| 20 |
+
h5netcdf==1.6.1
|
| 21 |
+
importlib-metadata==8.6.1
|
| 22 |
+
ipykernel==6.29.5
|
| 23 |
+
isort==6.0.1
|
| 24 |
+
jaraco.collections==5.1.0
|
| 25 |
+
lxml==5.3.1
|
| 26 |
+
lz4==4.4.4
|
| 27 |
+
nbformat==5.10.4
|
| 28 |
+
nc-time-axis==1.4.1
|
| 29 |
+
netcdf4==1.7.2
|
| 30 |
+
numbagg==0.9.0
|
| 31 |
+
opt-einsum==3.4.0
|
| 32 |
+
pickleshare==0.7.5
|
| 33 |
+
pyarrow==19.0.1
|
| 34 |
+
pysocks==1.7.1
|
| 35 |
+
pystac-client==0.8.6
|
| 36 |
+
rasterio==1.4.3
|
| 37 |
+
seaborn==0.13.2
|
| 38 |
+
sentinelsat==1.2.1
|
| 39 |
+
sparse==0.16.0
|
| 40 |
+
tomli==2.0.1
|
| 41 |
+
xarray==2025.3.1
|
| 42 |
+
zarr==3.0.6
|
| 43 |
+
zstandard==0.23.0
|
| 44 |
+
# affine==2.4.0 # Installed as dependency for rasterio
|
| 45 |
+
# aiofiles==23.2.1 # Installed as dependency for gradio
|
| 46 |
+
# aiohappyeyeballs==2.6.1 # Installed as dependency for aiohttp
|
| 47 |
+
# aiosignal==1.3.2 # Installed as dependency for aiohttp
|
| 48 |
+
# annotated-types==0.7.0 # Installed as dependency for pydantic
|
| 49 |
+
# anyio==4.9.0 # Installed as dependency for gradio, httpx, starlette
|
| 50 |
+
# argparse==1.4.0 # Installed as dependency for conflator
|
| 51 |
+
# asttokens==3.0.0 # Installed as dependency for stack-data
|
| 52 |
+
# attrs==25.3.0 # Installed as dependency for aiohttp, jsonschema, rasterio, referencing
|
| 53 |
+
# audioop-lts==0.2.1 # Installed as dependency for gradio
|
| 54 |
+
# autocommand==2.2.2 # Installed as dependency for jaraco.text
|
| 55 |
+
# botocore==1.37.26 # Installed as dependency for boto3, s3transfer
|
| 56 |
+
# branca==0.8.1 # Installed as dependency for folium
|
| 57 |
+
# certifi==2025.1.31 # Installed as dependency for httpcore, httpx, netcdf4, pyogrio, pyproj, rasterio, requests
|
| 58 |
+
# cftime==1.6.4.post1 # Installed as dependency for nc-time-axis, netcdf4
|
| 59 |
+
# charset-normalizer==3.4.1 # Installed as dependency for requests
|
| 60 |
+
# click==8.1.8 # Installed as dependency for click-plugins, cligj, dask, distributed, geomet, rasterio, sentinelsat, typer, uvicorn
|
| 61 |
+
# click-plugins==1.1.1 # Installed as dependency for rasterio
|
| 62 |
+
# cligj==0.7.2 # Installed as dependency for rasterio
|
| 63 |
+
# cloudpickle==3.1.1 # Installed as dependency for dask, distributed
|
| 64 |
+
# comm==0.2.2 # Installed as dependency for ipykernel
|
| 65 |
+
# contourpy==1.3.1 # Installed as dependency for bokeh, matplotlib
|
| 66 |
+
# cycler==0.12.1 # Installed as dependency for matplotlib
|
| 67 |
+
# dask==2025.3.0 # Installed as dependency for distributed
|
| 68 |
+
# debugpy==1.8.13 # Installed as dependency for ipykernel
|
| 69 |
+
# decorator==5.2.1 # Installed as dependency for ipython
|
| 70 |
+
# deprecated==1.2.18 # Installed as dependency for numcodecs
|
| 71 |
+
# donfig==0.8.1.post1 # Installed as dependency for zarr
|
| 72 |
+
# executing==2.1.0 # Installed as dependency for stack-data
|
| 73 |
+
# fastapi==0.115.12 # Installed as dependency for gradio
|
| 74 |
+
# fastjsonschema==2.21.1 # Installed as dependency for nbformat
|
| 75 |
+
# ffmpy==0.5.0 # Installed as dependency for gradio
|
| 76 |
+
# filelock==3.18.0 # Installed as dependency for huggingface-hub
|
| 77 |
+
# fonttools==4.56.0 # Installed as dependency for matplotlib
|
| 78 |
+
# frozenlist==1.5.0 # Installed as dependency for aiohttp, aiosignal
|
| 79 |
+
# fsspec==2025.3.2 # Installed as dependency for dask, gradio-client, huggingface-hub
|
| 80 |
+
# geojson==3.2.0 # Installed as dependency for sentinelsat
|
| 81 |
+
# geomet==1.1.0 # Installed as dependency for sentinelsat
|
| 82 |
+
# gradio-client==1.8.0 # Installed as dependency for gradio
|
| 83 |
+
# groovy==0.1.2 # Installed as dependency for gradio
|
| 84 |
+
# h11==0.14.0 # Installed as dependency for httpcore, uvicorn
|
| 85 |
+
# h5py==3.13.0 # Installed as dependency for h5netcdf
|
| 86 |
+
# hpack==4.1.0 # Installed as dependency for h2
|
| 87 |
+
# html2text==2024.2.26 # Installed as dependency for sentinelsat
|
| 88 |
+
# httpcore==1.0.7 # Installed as dependency for httpx
|
| 89 |
+
# httpx==0.28.1 # Installed as dependency for gradio, gradio-client, safehttpx
|
| 90 |
+
# huggingface-hub==0.30.1 # Installed as dependency for gradio, gradio-client
|
| 91 |
+
# hyperframe==6.1.0 # Installed as dependency for h2
|
| 92 |
+
# idna==3.10 # Installed as dependency for anyio, httpx, requests, yarl
|
| 93 |
+
# inflect==7.3.1 # Installed as dependency for jaraco.text
|
| 94 |
+
# iniconfig==2.1.0 # Installed as dependency for pytest
|
| 95 |
+
# ipython==9.0.2 # Installed as dependency for ipykernel
|
| 96 |
+
# ipython-pygments-lexers==1.1.1 # Installed as dependency for ipython
|
| 97 |
+
# jaraco.context==5.3.0 # Installed as dependency for jaraco.text
|
| 98 |
+
# jaraco.functools==4.0.1 # Installed as dependency for jaraco.text
|
| 99 |
+
# jaraco.text==3.12.1 # Installed as dependency for jaraco.collections
|
| 100 |
+
# jedi==0.19.2 # Installed as dependency for ipython
|
| 101 |
+
# jinja2==3.1.6 # Installed as dependency for bokeh, branca, distributed, folium, gradio
|
| 102 |
+
# jmespath==1.0.1 # Installed as dependency for boto3, botocore
|
| 103 |
+
# jsonschema==4.23.0 # Installed as dependency for nbformat
|
| 104 |
+
# jsonschema-specifications==2024.10.1 # Installed as dependency for jsonschema
|
| 105 |
+
# jupyter-client==8.6.3 # Installed as dependency for ipykernel
|
| 106 |
+
# jupyter-core==5.7.2 # Installed as dependency for ipykernel, jupyter-client, nbformat
|
| 107 |
+
# kiwisolver==1.4.8 # Installed as dependency for matplotlib
|
| 108 |
+
# llvmlite==0.44.0 # Installed as dependency for numba
|
| 109 |
+
# locket==1.0.0 # Installed as dependency for distributed, partd
|
| 110 |
+
# markdown-it-py==3.0.0 # Installed as dependency for rich
|
| 111 |
+
# markupsafe==3.0.2 # Installed as dependency for gradio, jinja2
|
| 112 |
+
# matplotlib==3.10.1 # Installed as dependency for cartopy, nc-time-axis, seaborn
|
| 113 |
+
# matplotlib-inline==0.1.7 # Installed as dependency for ipykernel, ipython
|
| 114 |
+
# mdurl==0.1.2 # Installed as dependency for markdown-it-py
|
| 115 |
+
# more-itertools==10.3.0 # Installed as dependency for inflect, jaraco.functools, jaraco.text
|
| 116 |
+
# msgpack==1.1.0 # Installed as dependency for distributed
|
| 117 |
+
# multidict==6.2.0 # Installed as dependency for aiohttp, yarl
|
| 118 |
+
# narwhals==1.33.0 # Installed as dependency for bokeh
|
| 119 |
+
# nest-asyncio==1.6.0 # Installed as dependency for ipykernel
|
| 120 |
+
# numba==0.61.0 # Installed as dependency for numbagg, sparse
|
| 121 |
+
# numcodecs==0.15.1 # Installed as dependency for zarr
|
| 122 |
+
# numpy==2.1.3 # Installed as dependency for bokeh, bottleneck, cartopy, cftime, contourpy, flox, folium, geopandas, gradio, h5py, matplotlib, nc-time-axis, netcdf4, numba, numbagg, numcodecs, numpy-groupies, pandas, pyogrio, rasterio, scipy, seaborn, shapely, sparse, xarray, zarr
|
| 123 |
+
# numpy-groupies==0.11.2 # Installed as dependency for flox
|
| 124 |
+
# orjson==3.10.16 # Installed as dependency for gradio
|
| 125 |
+
# packaging==24.2 # Installed as dependency for bokeh, cartopy, dask, distributed, flox, geopandas, gradio, gradio-client, h5netcdf, huggingface-hub, ipykernel, matplotlib, pooch, pyogrio, pytest, xarray, zarr
|
| 126 |
+
# pandas==2.2.3 # Installed as dependency for bokeh, flox, geopandas, gradio, seaborn, xarray
|
| 127 |
+
# parso==0.8.4 # Installed as dependency for jedi
|
| 128 |
+
# partd==1.4.2 # Installed as dependency for dask
|
| 129 |
+
# pexpect==4.9.0 # Installed as dependency for ipython
|
| 130 |
+
# pillow==11.1.0 # Installed as dependency for bokeh, gradio, matplotlib
|
| 131 |
+
# platformdirs==4.3.7 # Installed as dependency for jupyter-core, pooch
|
| 132 |
+
# pluggy==1.5.0 # Installed as dependency for pytest
|
| 133 |
+
# pooch==1.8.2 # Installed as dependency for geodatasets
|
| 134 |
+
# prompt-toolkit==3.0.50 # Installed as dependency for ipython
|
| 135 |
+
# propcache==0.3.1 # Installed as dependency for aiohttp, yarl
|
| 136 |
+
# psutil==7.0.0 # Installed as dependency for distributed, ipykernel
|
| 137 |
+
# ptyprocess==0.7.0 # Installed as dependency for pexpect
|
| 138 |
+
# pure-eval==0.2.3 # Installed as dependency for stack-data
|
| 139 |
+
# pycparser==2.22 # Installed as dependency for cffi
|
| 140 |
+
# pydantic==2.11.1 # Installed as dependency for conflator, fastapi, gradio
|
| 141 |
+
# pydantic-core==2.33.0 # Installed as dependency for pydantic
|
| 142 |
+
# pydub==0.25.1 # Installed as dependency for gradio
|
| 143 |
+
# pygments==2.19.1 # Installed as dependency for ipython, ipython-pygments-lexers, rich
|
| 144 |
+
# pyogrio==0.10.0 # Installed as dependency for geopandas
|
| 145 |
+
# pyparsing==3.2.3 # Installed as dependency for matplotlib, rasterio
|
| 146 |
+
# pyproj==3.7.1 # Installed as dependency for cartopy, geopandas
|
| 147 |
+
# pyshp==2.3.1 # Installed as dependency for cartopy
|
| 148 |
+
# pystac==1.12.2 # Installed as dependency for pystac-client
|
| 149 |
+
# pytest==8.3.5 # Installed as dependency for conflator
|
| 150 |
+
# python-dateutil==2.9.0.post0 # Installed as dependency for botocore, jupyter-client, matplotlib, pandas, pystac, pystac-client
|
| 151 |
+
# python-dotenv==1.1.0 # Installed as dependency for dotenv
|
| 152 |
+
# python-multipart==0.0.20 # Installed as dependency for gradio
|
| 153 |
+
# pytz==2025.2 # Installed as dependency for pandas
|
| 154 |
+
# pyyaml==6.0.2 # Installed as dependency for bokeh, conflator, dask, distributed, donfig, gradio, huggingface-hub
|
| 155 |
+
# pyzmq==26.3.0 # Installed as dependency for ipykernel, jupyter-client
|
| 156 |
+
# referencing==0.36.2 # Installed as dependency for jsonschema, jsonschema-specifications
|
| 157 |
+
# requests==2.32.3 # Installed as dependency for folium, huggingface-hub, pooch, pystac-client, sentinelsat
|
| 158 |
+
# rich==14.0.0 # Installed as dependency for rich-argparse, typer
|
| 159 |
+
# rich-argparse==1.7.0 # Installed as dependency for conflator
|
| 160 |
+
# rpds-py==0.24.0 # Installed as dependency for jsonschema, referencing
|
| 161 |
+
# ruff==0.11.2 # Installed as dependency for gradio
|
| 162 |
+
# s3transfer==0.11.4 # Installed as dependency for boto3
|
| 163 |
+
# safehttpx==0.1.6 # Installed as dependency for gradio
|
| 164 |
+
# scipy==1.15.2 # Installed as dependency for flox
|
| 165 |
+
# semantic-version==2.10.0 # Installed as dependency for gradio
|
| 166 |
+
# shapely==2.0.7 # Installed as dependency for cartopy, geopandas
|
| 167 |
+
# shellingham==1.5.4 # Installed as dependency for typer
|
| 168 |
+
# six==1.17.0 # Installed as dependency for python-dateutil
|
| 169 |
+
# sniffio==1.3.1 # Installed as dependency for anyio
|
| 170 |
+
# sortedcontainers==2.4.0 # Installed as dependency for distributed
|
| 171 |
+
# stack-data==0.6.3 # Installed as dependency for ipython
|
| 172 |
+
# starlette==0.46.1 # Installed as dependency for fastapi, gradio
|
| 173 |
+
# tblib==3.1.0 # Installed as dependency for distributed
|
| 174 |
+
# tomlkit==0.13.2 # Installed as dependency for gradio
|
| 175 |
+
# toolz==1.0.0 # Installed as dependency for dask, distributed, flox, partd
|
| 176 |
+
# tornado==6.4.2 # Installed as dependency for bokeh, distributed, ipykernel, jupyter-client
|
| 177 |
+
# tqdm==4.67.1 # Installed as dependency for huggingface-hub, sentinelsat
|
| 178 |
+
# traitlets==5.14.3 # Installed as dependency for comm, ipykernel, ipython, jupyter-client, jupyter-core, matplotlib-inline, nbformat
|
| 179 |
+
# typeguard==4.3.0 # Installed as dependency for inflect
|
| 180 |
+
# typer==0.15.2 # Installed as dependency for gradio
|
| 181 |
+
# typing-extensions==4.13.0 # Installed as dependency for fastapi, gradio, gradio-client, huggingface-hub, pydantic, pydantic-core, typeguard, typer, typing-inspection, zarr
|
| 182 |
+
# typing-inspection==0.4.0 # Installed as dependency for pydantic
|
| 183 |
+
# tzdata==2025.2 # Installed as dependency for pandas
|
| 184 |
+
# urllib3==2.3.0 # Installed as dependency for botocore, distributed, requests
|
| 185 |
+
# uvicorn==0.34.0 # Installed as dependency for gradio
|
| 186 |
+
# wcwidth==0.2.13 # Installed as dependency for prompt-toolkit
|
| 187 |
+
# websockets==15.0.1 # Installed as dependency for gradio-client
|
| 188 |
+
# wrapt==1.17.2 # Installed as dependency for deprecated
|
| 189 |
+
# xyzservices==2025.1.0 # Installed as dependency for bokeh, folium
|
| 190 |
+
# yarl==1.18.3 # Installed as dependency for aiohttp
|
| 191 |
+
# zict==3.0.0 # Installed as dependency for distributed
|
| 192 |
+
# zipp==3.21.0 # Installed as dependency for importlib-metadata
|