Spaces:
Sleeping
Sleeping
from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool | |
import datetime | |
import requests | |
import pytz | |
import yaml | |
import os | |
from tools.final_answer import FinalAnswerTool | |
from Gradio_UI import GradioUI | |
# Fetch USGS API credentials from environment variables (set in Hugging Face Spaces secrets) | |
USGS_USERNAME = os.getenv("USGS_USERNAME") | |
USGS_TOKEN = os.getenv("USGS_TOKEN") | |
def fetch_landsat_image(lat_min: float, lon_min: float, lat_max: float, lon_max: float, start_date: str, end_date: str) -> str: | |
"""Fetches download URLs for all available Landsat images from USGS M2M API and returns them as clickable HTML links. | |
Args: | |
lat_min: Minimum latitude of the bounding box | |
lon_min: Minimum longitude of the bounding box | |
lat_max: Maximum latitude of the bounding box | |
lon_max: Maximum longitude of the bounding box | |
start_date: Start date in 'YYYY-MM-DD' format | |
end_date: End date in 'YYYY-MM-DD' format | |
""" | |
if not USGS_USERNAME or not USGS_TOKEN: | |
return "<p>Error: USGS_USERNAME or USGS_TOKEN not set in environment variables.</p>" | |
service_url = "https://m2m.cr.usgs.gov/api/api/json/stable/" | |
def send_request(url, data, api_key=None): | |
json_data = json.dumps(data) | |
headers = {'X-Auth-Token': api_key} if api_key else {} | |
response = requests.post(url, json_data, headers=headers) | |
output = response.json() | |
if output.get('errorCode'): | |
return f"Error: {output['errorCode']} - {output['errorMessage']}" | |
return output['data'] | |
try: | |
# Step 1: Authenticate | |
login_payload = {'username': USGS_USERNAME, 'token': USGS_TOKEN} | |
api_key = send_request(service_url + "login-token", login_payload) | |
if not api_key or isinstance(api_key, str) and "Error" in api_key: | |
return "<p>Authentication failed. Check username and token in secrets.</p>" | |
# Step 2: Search scenes | |
spatial_filter = { | |
'filterType': "mbr", | |
'lowerLeft': {'latitude': lat_min, 'longitude': lon_min}, | |
'upperRight': {'latitude': lat_max, 'longitude': lon_max} | |
} | |
temporal_filter = {'start': start_date, 'end': end_date} | |
search_payload = { | |
'datasetName': 'landsat_ot_c2_l1', | |
'spatialFilter': spatial_filter, | |
'temporalFilter': temporal_filter, | |
'maxResults': 50, | |
'sortField': 'cloudCover', | |
'sortDirection': 'ASC' | |
} | |
scenes = send_request(service_url + "scene-search", search_payload, api_key) | |
if isinstance(scenes, str) and "Error" in scenes: | |
return f"<p>{scenes}</p>" | |
if not scenes['results']: | |
return "<p>No Landsat scenes found for the given area and time range.</p>" | |
# Step 3: Get download options | |
entity_ids = [scene['entityId'] for scene in scenes['results']] | |
download_options_payload = { | |
'datasetName': 'landsat_ot_c2_l1', | |
'entityIds': entity_ids | |
} | |
download_options = send_request(service_url + "download-options", download_options_payload, api_key) | |
if isinstance(download_options, str) and "Error" in download_options: | |
return f"<p>{download_options}</p>" | |
# Step 4: Request downloads | |
downloads = [opt for opt in download_options if opt['available']] | |
if not downloads: | |
return "<p>No available downloads for these scenes.</p>" | |
label = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |
download_request_payload = { | |
'downloads': [{'entityId': opt['entityId'], 'productId': opt['id']} for opt in downloads], | |
'label': label | |
} | |
request_results = send_request(service_url + "download-request", download_request_payload, api_key) | |
if isinstance(request_results, str) and "Error" in request_results: | |
return f"<p>{request_results}</p>" | |
# Step 5: Generate HTML with clickable links | |
urls = [download['url'] for download in request_results['availableDownloads']] | |
if not urls: | |
return "<p>No download URLs immediately available. Try again later.</p>" | |
html_output = f"<p>Found {len(urls)} available Landsat scenes:</p><ul>" | |
for i, (scene, url) in enumerate(zip(scenes['results'][:len(urls)], urls)): | |
html_output += f'<li>Cloud Cover: {scene["cloudCover"]}% - <a href="{url}" target="_blank">Download Scene {i+1}</a></li>' | |
html_output += "</ul>" | |
return html_output | |
except Exception as e: | |
return f"<p>Error fetching Landsat images: {str(e)}</p>" | |
final_answer = FinalAnswerTool() | |
model = HfApiModel( | |
max_tokens=2096, | |
temperature=0.5, | |
model_id='Qwen/Qwen2.5-Coder-32B-Instruct', | |
custom_role_conversions=None, | |
) | |
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) | |
with open("prompts.yaml", "r") as stream: | |
prompt_templates = yaml.safe_load(stream) | |
agent = CodeAgent( | |
model=model, | |
tools=[fetch_landsat_image, final_answer], | |
max_steps=6, | |
verbosity_level=1, | |
grammar=None, | |
planning_interval=None, | |
name=None, | |
description=None, | |
prompt_templates=prompt_templates | |
) | |
# Launch Gradio UI | |
interface = GradioUI(agent) | |
interface.launch(share=False) # 'share=True' for public link in Spaces |