tobacco / app.py
lyimo's picture
Update app.py
b940cb3 verified
import os
import urllib.request
import time
import gradio as gr
import numpy as np
from part1_data import TobaccoAnalyzer
from part2_visualization import VisualizationHandler
from part3 import SAMAnalyzer
# Model setup
MODEL_PATH = 'sam_vit_h_4b8939.pth'
def download_with_progress(url, filename):
if os.path.exists(filename):
print(f"Model already exists at {filename}")
return
print(f"Downloading {filename}...")
start_time = time.time()
urllib.request.urlretrieve(url, filename)
end_time = time.time()
print(f"Download completed in {end_time - start_time:.2f} seconds")
# Download SAM model if it doesn't exist
if not os.path.exists(MODEL_PATH):
try:
download_with_progress(
'https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth',
MODEL_PATH
)
except Exception as e:
print(f"Error downloading SAM model: {e}")
print("Please ensure you have internet connection and sufficient disk space.")
def analyze_location(location_name):
"""Main analysis function with enhanced historical and forecast data"""
try:
analyzer = TobaccoAnalyzer()
visualizer = VisualizationHandler(analyzer.optimal_conditions)
# Get coordinates from location name
location_data = analyzer.geocode_location(location_name)
if not location_data:
return None, None, "Location not found. Please try a different location name.", None
lat, lon = location_data['lat'], location_data['lon']
# Get weather data
df = analyzer.get_weather_data(lat, lon, historical_days=90, forecast_days=90)
if df is None or df.empty:
return None, None, "Unable to fetch weather data. Please try again.", None
# Separate historical and forecast data
historical = df[df['type'] == 'historical']
forecast = df[df['type'] != 'historical']
if historical.empty:
return None, None, "No historical data available.", None
# Calculate base scores
temp_score = np.clip((historical['temperature'].mean() - 15) / (30 - 15), 0, 1)
humidity_score = np.clip((historical['humidity'].mean() - 50) / (80 - 50), 0, 1)
rainfall_score = np.clip(historical['rainfall'].mean() / 5, 0, 1)
ndvi_score = np.clip((historical['estimated_ndvi'].mean() + 1) / 2, 0, 1)
# Get trends analysis
trends = analyzer.analyze_trends(df)
if trends is None:
return None, None, "Error calculating trends.", None
# Calculate overall score
weights = {
'temperature': 0.3,
'humidity': 0.2,
'rainfall': 0.2,
'ndvi': 0.3
}
overall_score = (
temp_score * weights['temperature'] +
humidity_score * weights['humidity'] +
rainfall_score * weights['rainfall'] +
ndvi_score * weights['ndvi']
)
# Create visualizations
time_series_plot = visualizer.create_interactive_plots(df)
gauge_plot = visualizer.create_gauge_chart(overall_score)
location_map = visualizer.create_enhanced_map(lat, lon, overall_score, historical['estimated_ndvi'].mean())
# Generate analysis text
analysis_text = f"""
📍 Location Analysis:
Location: {location_data['address']}
Coordinates: {lat:.4f}°N, {lon:.4f}°E
Region: {location_data['region'] if location_data['region'] else 'Unknown'}
🌡️ Historical Weather Analysis (Past 90 Days):
Temperature: {historical['temperature'].mean():.1f}°C (±{historical['temperature'].std():.1f}°C)
Daily Range: {historical['temp_range'].mean():.1f}°C
Humidity: {historical['humidity'].mean():.1f}% (±{historical['humidity'].std():.1f}%)
Rainfall: {historical['rainfall'].mean():.1f}mm/day (±{historical['rainfall'].std():.1f}mm)
🌿 Vegetation Analysis:
Current NDVI: {historical['estimated_ndvi'].mean():.2f}
Minimum NDVI: {historical['estimated_ndvi'].min():.2f}
Maximum NDVI: {historical['estimated_ndvi'].max():.2f}
Vegetation Status: {get_vegetation_status(historical['estimated_ndvi'].mean())}
🔮 Forecast Analysis (Next 90 Days):
Temperature: {forecast['temperature'].mean():.1f}°C (±{forecast['temperature'].std():.1f}°C)
Humidity: {forecast['humidity'].mean():.1f}% (±{forecast['humidity'].std():.1f}%)
Rainfall: {forecast['rainfall'].mean():.1f}mm/day (±{forecast['rainfall'].std():.1f}mm)
Expected NDVI: {forecast['estimated_ndvi'].mean():.2f}
📊 Growing Condition Scores:
Temperature Score: {temp_score:.2f}
Humidity Score: {humidity_score:.2f}
Rainfall Score: {rainfall_score:.2f}
Vegetation Score: {ndvi_score:.2f}
Overall Score: {overall_score:.2f}
🎯 Recommendations:
{get_recommendations(overall_score, ndvi_score)}
⚠️ Risk Factors:
{get_risk_factors(df, trends)}
📝 Additional Notes:
• Growing Season: {is_growing_season(historical['season'].iloc[-1])}
• Weather Stability: {get_weather_stability(historical)}
• Long-term Outlook: {get_long_term_outlook(trends)}
"""
return location_map, analysis_text, time_series_plot, gauge_plot
except Exception as e:
error_message = f"An error occurred: {str(e)}"
print(f"Error details: {e}")
return None, None, error_message, None
def process_and_analyze_image(image):
"""Process and analyze uploaded satellite image"""
try:
if image is None:
return None, "Please upload an image first.", "No image provided"
print("Starting image analysis...")
analyzer = SAMAnalyzer(model_path=MODEL_PATH)
print("Processing image...")
veg_index, health_analysis, fig = analyzer.process_image(image)
if veg_index is None:
return None, "Error processing image.", "Image processing failed"
analysis_text = f"""
🌿 Vegetation Analysis Results:
📊 Average Vegetation Index: {health_analysis['average_index']:.2f}
🌱 Vegetation Distribution:
• Low Vegetation: {health_analysis['health_distribution']['low_vegetation']*100:.1f}%
• Moderate Vegetation: {health_analysis['health_distribution']['moderate_vegetation']*100:.1f}%
• High Vegetation: {health_analysis['health_distribution']['high_vegetation']*100:.1f}%
📋 Overall Health Status: {health_analysis['overall_health']}
"""
debug_msg = "Analysis completed successfully"
return fig, analysis_text, debug_msg
except Exception as e:
error_msg = f"Error during analysis: {str(e)}"
print(error_msg)
return None, None, error_msg
def get_vegetation_status(ndvi):
"""Get detailed vegetation status based on NDVI value"""
if ndvi < 0:
return "Very Low - Bare soil or water bodies"
elif ndvi < 0.1:
return "Low - Very sparse vegetation"
elif ndvi < 0.2:
return "Sparse - Stressed vegetation"
elif ndvi < 0.3:
return "Moderate - Typical agricultural land"
elif ndvi < 0.4:
return "Good - Healthy vegetation"
elif ndvi < 0.5:
return "High - Very healthy vegetation"
elif ndvi < 0.6:
return "Very High - Dense vegetation"
else:
return "Dense - Very dense, healthy vegetation"
def get_recommendations(score, ndvi):
"""Get detailed recommendations based on scores"""
if score >= 0.8 and ndvi >= 0.6:
return """
✅ Excellent conditions for tobacco growing
• Proceed with standard planting schedule
• Regular monitoring recommended
• Consider expansion opportunities
"""
elif score >= 0.6:
return """
👍 Good conditions with some considerations
• Implement basic risk mitigation measures
• Regular monitoring essential
• Consider crop insurance
"""
elif score >= 0.4:
return """
⚠️ Marginal conditions - proceed with caution
• Enhanced monitoring required
• Strong risk mitigation needed
• Crop insurance strongly recommended
• Consider alternative timing
"""
else:
return """
❌ Poor conditions - high risk
• Not recommended for planting
• Consider alternative locations
• Extensive risk mitigation needed
• Alternative crops suggested
"""
def get_risk_factors(df, trends):
"""Analyze and return risk factors"""
risks = []
if df['temp_range'].mean() > 15:
risks.append("• High daily temperature variations")
if trends['historical']['temperature']['trend'] < 0:
risks.append("• Declining temperature trend")
if df['rainfall'].std() > df['rainfall'].mean():
risks.append("• Inconsistent rainfall patterns")
if trends['historical']['rainfall']['trend'] < 0:
risks.append("• Decreasing rainfall trend")
if trends['historical']['ndvi']['trend'] < 0:
risks.append("• Declining vegetation health")
return "\n".join(risks) if risks else "No major risk factors identified"
def is_growing_season(season):
"""Check if current season is suitable for growing"""
season_suitability = {
'Main': "Prime growing season - Optimal conditions",
'Early': "Early growing season - Good potential",
'Late': "Late growing season - Monitor closely",
'Dry': "Dry season - Higher risk period"
}
return season_suitability.get(season, "Season not identified")
def get_weather_stability(df):
"""Assess weather stability"""
temp_std = df['temperature'].std()
if temp_std < 2:
return "Very stable weather patterns"
elif temp_std < 4:
return "Moderately stable weather"
return "Unstable weather patterns - higher risk"
def get_long_term_outlook(trends):
"""Assess long-term outlook based on trends"""
temp_trend = trends['historical']['temperature']['trend']
rain_trend = trends['historical']['rainfall']['trend']
if temp_trend > 0 and rain_trend > 0:
return "Improving conditions"
elif temp_trend < 0 and rain_trend < 0:
return "Deteriorating conditions"
return "Mixed conditions - monitor closely"
# Create Gradio interface
with gr.Blocks(theme=gr.themes.Base()) as demo:
gr.Markdown(
"""
# 🌱 Agricultural Credit Risk Assessment System
## Weather, Vegetation, and Credit Scoring Analysis for Tobacco Farming
"""
)
with gr.Tab("📊 Location Analysis"):
with gr.Row():
location_input = gr.Textbox(
label="Enter Location",
placeholder="e.g., Tabora, Tanzania",
scale=4
)
analyze_button = gr.Button("Analyze", variant="primary", scale=1)
with gr.Row():
with gr.Column(scale=2):
location_map = gr.HTML(label="NDVI Analysis Map")
with gr.Column(scale=1):
analysis_text = gr.Textbox(
label="Analysis Results",
lines=25,
show_label=False
)
with gr.Row():
weather_plot = gr.Plot(label="Weather Analysis")
with gr.Row():
score_gauge = gr.Plot(label="Growing Conditions Score")
gr.Examples(
examples=[
["Tabora, Tanzania"],
["Urambo, Tabora, Tanzania"],
["Sikonge, Tabora, Tanzania"],
["Nzega, Tabora, Tanzania"]
],
inputs=location_input,
outputs=[location_map, analysis_text, weather_plot, score_gauge],
fn=analyze_location,
cache_examples=True
)
analyze_button.click(
fn=analyze_location,
inputs=[location_input],
outputs=[location_map, analysis_text, weather_plot, score_gauge]
)
with gr.Tab("🛰️ Satellite Image Analysis"):
gr.Markdown("""
## Satellite Image Analysis with SAM2
Upload a satellite or aerial image to analyze vegetation health using advanced segmentation.
""")
with gr.Row():
image_input = gr.Image(
label="Upload Satellite/Aerial Image",
type="numpy"
)
with gr.Row():
analyze_image_button = gr.Button("🔍 Analyze Image", variant="primary")
with gr.Row():
image_plot = gr.Plot(
label="Vegetation Analysis Results"
)
with gr.Row():
image_analysis = gr.Textbox(
label="Analysis Results",
lines=10
)
debug_output = gr.Textbox(
label="Debug Information",
lines=3,
visible=True
)
analyze_image_button.click(
fn=process_and_analyze_image,
inputs=[image_input],
outputs=[image_plot, image_analysis, debug_output]
)
# Launch the app
if __name__ == "__main__":
demo.launch()