Appendix
Appendix
```python
import torch
import [Link] as nn
import random
import numpy as np
import logging
from confi[Link]fig import DATA_DIR, BATCH_SIZE, EPOCHS, LR, IMG_SIZE, SEED, MODEL_PATH, DEVICE
def get_model(num_classes):
model = models.resnet50(pretrained=True)
num_features = [Link].in_features
return model
def train_model(data_dir=None):
if data_dir is None:
data_dir = DATA_DIR
torch.manual_seed(SEED)
[Link](SEED)
[Link](SEED)
dataset = [Link](data_dir)
classes = [Link]
train_dataset.[Link] = train_transform
val_dataset.[Link] = val_transform
model = get_model(len(classes))
model = [Link](DEVICE)
criterion = [Link]()
best_val_loss = float("inf")
train_losses = []
val_losses = []
[Link]()
running_loss = 0
images = [Link](DEVICE)
labels = [Link](DEVICE)
outputs = model(images)
optimizer.zero_grad()
[Link]()
[Link]()
running_loss += [Link]()
train_losses.append(train_loss)
[Link]()
val_loss = 0
with torch.no_grad():
labels = [Link](DEVICE)
outputs = model(images)
val_loss += [Link]()
val_losses.append(val_loss)
[Link](val_loss)
best_val_loss = val_loss
[Link](model.state_dict(), MODEL_PATH)
plt.figure(figsize=(8,5))
[Link](train_losses, label="train")
[Link](val_losses, label="validation")
[Link]("Training Curve")
[Link]("Epoch")
[Link]("Loss")
[Link]()
[Link]fig("model_perf/training_curve.png")
[Link]()
```
```python
import torch
import logging
model = get_model(len(CLASSES))
model.load_state_dict([Link](MODEL_PATH, map_location=DEVICE))
model = [Link](DEVICE)
[Link]()
def predict(image_file):
image = preprocess_image(image_file)
image = [Link](DEVICE)
with torch.no_grad():
outputs = model(image)
_, pred = [Link](outputs, 1)
predicted_class = CLASSES[[Link]()]
return predicted_class
```
B.3 API Module
Description: This module provides a REST API using FastAPI for model training and prediction. It includes endpoints for training the model and predicting hazards from uploaded images. The prediction
endpoint extracts coordinates from image filenames, uses regional defaults if not found, and invokes the LangGraph agent to generate comprehensive reports. Key design decisions include using FastAPI
for automatic API documentation, handling file uploads with proper MIME types, and integrating coordinate extraction for location-aware reporting.
```python
import logging
import re
app = FastAPI(title="GaiaGuard API", description="AI-powered environmental hazard detection from satellite images")
graph = build_graph()
def extract_coords(filename):
if match:
@[Link]("/train")
def train():
result = train_model()
return {"status": result}
@[Link]("/predict")
hazard = predict(BytesIO(image_bytes))
state = {
"hazard": hazard,
"image_bytes": image_bytes,
"lat": lat,
"lon": lon
result = [Link](state)
return {
"hazard": hazard,
"report": [Link]("report"),
"weather": [Link]("weather"),
"seismic": [Link]("seismic"),
"aqi": [Link]("aqi"),
"news": [Link]("news"),
"location": {"lat": lat, "lon": lon, "is_default": lat in [v[0] for v in HAZARD_LOCATIONS.values()]}
}
```
```python
class AgentState(TypedDict):
hazard: str
report: str
image_bytes: bytes
lat: float
lon: float
weather: dict
seismic: dict
aqi: dict
news: list
def build_graph():
builder = StateGraph(AgentState)
builder.add_node("report_node", generate_report)
builder.set_entry_point("report_node")
builder.set_finish_point("report_node")
return [Link]()
# From [Link]
import os
import base64
def get_llm(model_name):
def generate_report(state):
hazard = state["hazard"]
image_bytes = [Link]("image_bytes")
lat = [Link]("lat")
lon = [Link]("lon")
weather_data = {"temperature": "25°C", "condition": "Mainly Clear", "humidity": "50%", "wind_speed": "12 km/h"}
if pm25_value is None:
pm25_value = simulate_air_quality(hazard)
simulated_count = simulate_seismic_activity()
if simulated_count > 0:
seismic_data["count_last_7d"] = simulated_count
seismic_data["simulated"] = True
ground_context = f"""
- Weather: {weather_data}
- Recent News: {news_data if news_data else "No significant regional news reported."}
"""
prompt_text = f"""
The deep learning model detected the following hazard: {hazard}.
{ground_context}
1. **Verification**: Look at the attached satellite image AND the ground data context. Use your intelligence to cross-reference the visual evidence with the real-time data.
2. **Reporting**: Generate a comprehensive and professional incident report. Crucially, **do not just list the data**; synthesize it.
1. **Incident Summary**: A professional overview of the hazard, incorporating the specific location context and immediate implications.
2. **Ground Condition Analysis**: Analyze how the current weather/AQI/seismic data a ects the scale and progression of the incident.
3. **Ecological & Health Assessment**: Detailed assessment of risks to biodiversity, air quality, and local communities.
Do not include headers, metadata, or 'Prepared By' fields. Tone: Professional, data-driven, and urgent. Length: 300-500 words.
"""
report_content = ""
try:
llm = get_llm(model_name)
if image_bytes:
image_data = base64.b64encode(image_bytes).decode("utf-8")
message = HumanMessage(
content=[
response = [Link]([message])
else:
response = [Link]([message])
if isinstance([Link], list):
report_content = "".join([[Link]("text", "") if isinstance(part, dict) else str(part) for part in [Link]])
else:
report_content = [Link]
break
except Exception as e:
if model_name == models_to_try[-1]:
return {
"report": report_content,
"weather": weather_data,
"seismic": seismic_data,
"aqi": aqi_data,
"news": news_data
```
```python
import streamlit as st
import requests
[Link]("""
Our AI analyzes the image, cross-references it with **real-time weather, seismic, and air quality data**, and generates a comprehensive professional report.
""")
file = st.file_uploader("Choose a satellite image (PNG, JPG, JPEG)", type=["png", "jpg", "jpeg"])
if file:
file_bytes = fi[Link]()
image = [Link](BytesIO(file_bytes))
with col2:
try:
response = [Link](
"[Link]
if response.status_code == 200:
data = [Link]()
[Link]("Analysis Complete!")
else:
[Link](" **No location metadata found in image filename.** Using default regional analysis.")
[Link]()
[Link](" Real-Time Ground Data")
m1, m2 = [Link](2)
weather = [Link]("weather")
if weather:
else:
[Link]("Weather", "N/A")
aqi = [Link]("aqi")
if aqi:
else:
with ec1:
[Link]("**Weather Details:**")
[Link](weather)
else:
else:
with ec2:
[Link]("**Related News:**")
if news:
for n in news:
else:
[Link]()
[Link](report)
```
```python
# configs/confi[Link]
import torch
DATA_DIR = "merged_dataset"
MODEL_PATH = "models/gaia_guard_best_model.pt"
IMG_SIZE = 224
BATCH_SIZE = 64
EPOCHS = 5
LR = 1e-4
SEED = 42
CLASSES = [
"hurricane_damage",
"normal",
"oil_spill",
"wildfire"
if [Link].is_available():
DEVICE = "cuda"
elif [Link].is_available():
DEVICE = "mps"
else:
DEVICE = "cpu"
GEMINI_PRIMARY_MODEL = "gemini-2.0-flash"
GEMINI_FALLBACK_MODEL = "gemini-flash-latest"
# utils/[Link]
IMG_SIZE = 224
train_transform = [Link]([
[Link](IMG_SIZE),
[Link](),
[Link](),
[Link](20),
[Link]()
])
val_transform = [Link]([
[Link]((IMG_SIZE, IMG_SIZE)),
[Link]()
])
def preprocess_image(file):
fi[Link](0)
image = [Link](file).convert("RGB")
return val_transform(image).unsqueeze(0)
# dataset_builder.py (excerpt)
import os
import random
import shutil
OUTPUT = "merged_dataset"
TARGET = {
"wildfire": 1500,
"hurricane_damage": 1500,
"oil_spill": 1200,
"normal": 2000
for c in TARGET:
[Link](f"{OUTPUT}/{c}", exist_ok=True)
def get_images(folder):
imgs = []
imgs += list(Path(folder).glob(ext))
return imgs
imgs = get_images(src_folder)
if len(imgs) == 0:
return
[Link](img, dst_folder)
```
B.7 Data Fetching and Simulation Tools
Description: This module provides functions to fetch real-time environmental data from external APIs and simulate data when APIs are unavailable. It includes weather data from OpenWeatherMap,
seismic data from USGS, air quality from OpenAQ, and news from NewsAPI. Simulation functions generate realistic values based on hazard types for fallback scenarios. Key design decisions include
implementing timeout handling, API key management via environment variables, and hazard-specific simulation logic to maintain data relevance.
```python
import requests
import os
import logging
import random
api_key = [Link]("OPENWEATHER_API_KEY")
if not api_key:
return {"temperature": "22°C", "condition": "Clear", "humidity": "45%", "wind_speed": "10 km/h"}
try:
url = f"[Link]
if response.status_code == 200:
data = [Link]()
return {
"temperature": f"{data['main']['temp']}°C",
"condition": data['weather'][0]['description'],
"humidity": f"{data['main']['humidity']}%",
"wind_speed": f"{data['wind']['speed']} m/s"
except Exception as e:
pass
return None
try:
url = f"[Link]
if response.status_code == 200:
data = [Link]()
if count > 0:
latest = data['features'][0]['properties']
return {
"count_last_7d": count,
"latest_magnitude": latest['mag'],
"latest_place": latest['place'],
except Exception as e:
pass
return None
headers = {}
try:
url = f"[Link]
if response.status_code == 200:
data = [Link]()
if data['results']:
location = data['results'][0]
pm25_found = False
latest = [Link]('latestValue')
aqi[param] = latest
if param == 'pm25':
pm25_found = True
if not pm25_found:
return None
return aqi
except Exception as e:
pass
return None
def simulate_air_quality(hazard_type):
hazard_type = hazard_type.lower()
if "wildfire" in hazard_type:
else:
def simulate_seismic_activity():
r = [Link]()
if r < 0.80:
return 0
return 1
else:
return 2
api_key = [Link]("NEWS_API_KEY")
if not api_key:
return []
try:
query = f"{hazard} environmental impact"
url = f"[Link]
if response.status_code == 200:
except Exception as e:
pass
return []
B.8 Project Screenshots
Description: This section contains visual representations of the GaiaGuard system in action, including the Streamlit dashboard interface, API documentation, and sample analysis results. These
screenshots demonstrate the user experience and system capabilities.
*Figure B.1: Main dashboard interface showing image upload and analysis features.*
Listing B.9: Analysis Results Screenshot
*Figure B.2: Sample analysis results displaying hazard classification and environmental data.
B.10 Model Performance Metrics
*Figure B.3: Visual representations of model training performance and evaluation metrics.
Listing B.11: Training Loss Curve
*Figure B.5: Confusion matrix showing classification accuracy across hazard types.*