Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
| 1 |
-
# app.py
|
| 2 |
-
|
| 3 |
import gradio as gr
|
| 4 |
import numpy as np
|
| 5 |
from datetime import datetime, timedelta
|
|
@@ -9,16 +7,6 @@ import branca.colormap as cm
|
|
| 9 |
from part1_data import TobaccoAnalyzer
|
| 10 |
from part2_visualization import VisualizationHandler
|
| 11 |
|
| 12 |
-
def calculate_ndvi(lat, lon, radius=2000):
|
| 13 |
-
"""Calculate synthetic NDVI based on weather and location data"""
|
| 14 |
-
# Simulate NDVI based on weather conditions and season
|
| 15 |
-
month = datetime.now().month
|
| 16 |
-
# Spring/Summer months typically have higher NDVI
|
| 17 |
-
season_factor = 1.0 if month in [3,4,5,6,7,8] else 0.7
|
| 18 |
-
|
| 19 |
-
base_ndvi = 0.4 # Base NDVI value for agricultural areas
|
| 20 |
-
return base_ndvi * season_factor
|
| 21 |
-
|
| 22 |
def analyze_location(location_name):
|
| 23 |
"""Main analysis function with enhanced historical and forecast data"""
|
| 24 |
try:
|
|
@@ -34,84 +22,97 @@ def analyze_location(location_name):
|
|
| 34 |
|
| 35 |
# Get enhanced weather data
|
| 36 |
df = analyzer.get_weather_data(lat, lon, historical_days=90, forecast_days=90)
|
| 37 |
-
if df.empty:
|
| 38 |
return None, None, "Unable to fetch weather data. Please try again.", None
|
| 39 |
|
| 40 |
-
# Calculate
|
| 41 |
-
ndvi_value = calculate_ndvi(lat, lon)
|
| 42 |
-
ndvi_score = np.clip((ndvi_value + 1) / 2, 0, 1) # Convert -1:1 to 0:1 scale
|
| 43 |
-
|
| 44 |
-
# Calculate weather scores
|
| 45 |
historical = df[df['type'] == 'historical']
|
| 46 |
-
forecast = df[df['type']
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
|
|
|
| 51 |
|
| 52 |
-
#
|
| 53 |
trends = analyzer.analyze_trends(df)
|
|
|
|
| 54 |
|
| 55 |
-
#
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
| 60 |
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
|
|
|
| 66 |
|
| 67 |
# Create visualizations
|
| 68 |
time_series_plot = visualizer.create_interactive_plots(df)
|
| 69 |
gauge_plot = visualizer.create_gauge_chart(overall_score)
|
| 70 |
-
location_map = visualizer.create_enhanced_map(lat, lon, overall_score,
|
| 71 |
|
| 72 |
-
# Generate
|
| 73 |
-
|
|
|
|
| 74 |
|
| 75 |
-
# Generate analysis text
|
| 76 |
analysis_text = f"""
|
| 77 |
📍 Location Analysis:
|
| 78 |
Location: {location_data['address']}
|
| 79 |
Coordinates: {lat:.4f}°N, {lon:.4f}°E
|
|
|
|
| 80 |
|
| 81 |
🌡️ Historical Weather Analysis (Past 90 Days):
|
| 82 |
Temperature: {historical['temperature'].mean():.1f}°C (±{historical['temperature'].std():.1f}°C)
|
|
|
|
| 83 |
Humidity: {historical['humidity'].mean():.1f}% (±{historical['humidity'].std():.1f}%)
|
| 84 |
Rainfall: {historical['rainfall'].mean():.1f}mm/day (±{historical['rainfall'].std():.1f}mm)
|
| 85 |
|
| 86 |
-
🌿 Vegetation Analysis
|
| 87 |
-
NDVI
|
| 88 |
-
Vegetation Status: {
|
| 89 |
-
|
| 90 |
|
| 91 |
📈 Weather Trends:
|
| 92 |
-
Temperature
|
| 93 |
-
Humidity
|
| 94 |
-
Rainfall
|
|
|
|
| 95 |
|
| 96 |
🔮 Forecast Analysis (Next 90 Days):
|
| 97 |
Temperature: {forecast['temperature'].mean():.1f}°C (±{forecast['temperature'].std():.1f}°C)
|
| 98 |
Humidity: {forecast['humidity'].mean():.1f}% (±{forecast['humidity'].std():.1f}%)
|
| 99 |
Rainfall: {forecast['rainfall'].mean():.1f}mm/day (±{forecast['rainfall'].std():.1f}mm)
|
|
|
|
| 100 |
|
| 101 |
📊 Growing Condition Scores:
|
| 102 |
Temperature Score: {temp_score:.2f}
|
| 103 |
Humidity Score: {humidity_score:.2f}
|
| 104 |
Rainfall Score: {rainfall_score:.2f}
|
| 105 |
-
|
| 106 |
Overall Score: {overall_score:.2f}
|
| 107 |
|
| 108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
📝 Additional Notes:
|
| 111 |
-
•
|
| 112 |
-
•
|
| 113 |
-
•
|
| 114 |
-
• Vegetation health is {ndvi_status.lower()}
|
| 115 |
"""
|
| 116 |
|
| 117 |
return time_series_plot, gauge_plot, analysis_text, location_map
|
|
@@ -120,8 +121,25 @@ def analyze_location(location_name):
|
|
| 120 |
error_message = f"An error occurred: {str(e)}"
|
| 121 |
return None, None, error_message, None
|
| 122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
def get_vegetation_status(ndvi):
|
| 124 |
-
"""Get vegetation status based on NDVI value"""
|
| 125 |
if ndvi < 0:
|
| 126 |
return "Very Poor - Bare soil or water"
|
| 127 |
elif ndvi < 0.2:
|
|
@@ -130,26 +148,90 @@ def get_vegetation_status(ndvi):
|
|
| 130 |
return "Moderate - Typical agricultural land"
|
| 131 |
elif ndvi < 0.6:
|
| 132 |
return "Good - Healthy vegetation"
|
| 133 |
-
|
| 134 |
-
return "Excellent - Dense, very healthy vegetation"
|
| 135 |
|
| 136 |
-
def
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
# Create Gradio interface
|
| 148 |
with gr.Blocks(theme=gr.themes.Base()) as iface:
|
| 149 |
gr.Markdown(
|
| 150 |
"""
|
| 151 |
# 🌱 Agricultural Credit Risk Assessment System
|
| 152 |
-
## Weather, Vegetation, and Credit Scoring for Tobacco Farming
|
| 153 |
"""
|
| 154 |
)
|
| 155 |
|
|
@@ -166,12 +248,12 @@ with gr.Blocks(theme=gr.themes.Base()) as iface:
|
|
| 166 |
with gr.Row():
|
| 167 |
analysis_text = gr.Textbox(
|
| 168 |
label="Comprehensive Analysis",
|
| 169 |
-
lines=
|
| 170 |
interactive=False
|
| 171 |
)
|
| 172 |
|
| 173 |
with gr.Row():
|
| 174 |
-
weather_plot = gr.Plot(label="Weather Analysis")
|
| 175 |
|
| 176 |
with gr.Row():
|
| 177 |
with gr.Column(scale=1):
|
|
@@ -182,16 +264,16 @@ with gr.Blocks(theme=gr.themes.Base()) as iface:
|
|
| 182 |
with gr.TabItem("ℹ️ Help"):
|
| 183 |
gr.Markdown("""
|
| 184 |
### Understanding the Analysis:
|
| 185 |
-
- Weather
|
| 186 |
-
- Vegetation Health
|
| 187 |
-
- Credit Risk
|
| 188 |
-
- Location Analysis: Interactive
|
| 189 |
|
| 190 |
### Score Interpretation:
|
| 191 |
-
- 0.8-1.0:
|
| 192 |
-
- 0.6-0.8:
|
| 193 |
-
- 0.4-0.6:
|
| 194 |
-
- 0.0-0.4:
|
| 195 |
""")
|
| 196 |
|
| 197 |
# Set up examples
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
from datetime import datetime, timedelta
|
|
|
|
| 7 |
from part1_data import TobaccoAnalyzer
|
| 8 |
from part2_visualization import VisualizationHandler
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
def analyze_location(location_name):
|
| 11 |
"""Main analysis function with enhanced historical and forecast data"""
|
| 12 |
try:
|
|
|
|
| 22 |
|
| 23 |
# Get enhanced weather data
|
| 24 |
df = analyzer.get_weather_data(lat, lon, historical_days=90, forecast_days=90)
|
| 25 |
+
if df is None or df.empty:
|
| 26 |
return None, None, "Unable to fetch weather data. Please try again.", None
|
| 27 |
|
| 28 |
+
# Calculate scores
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
historical = df[df['type'] == 'historical']
|
| 30 |
+
forecast = df[df['type'] == 'forecast']
|
| 31 |
|
| 32 |
+
# Calculate base scores
|
| 33 |
+
temp_score = np.clip((historical['temperature'].mean() - 15) / (30 - 15), 0, 1)
|
| 34 |
+
humidity_score = np.clip((historical['humidity'].mean() - 50) / (80 - 50), 0, 1)
|
| 35 |
+
rainfall_score = np.clip(historical['rainfall'].mean() / 5, 0, 1)
|
| 36 |
|
| 37 |
+
# Get trends and NDVI
|
| 38 |
trends = analyzer.analyze_trends(df)
|
| 39 |
+
ndvi_score = historical['estimated_ndvi'].mean()
|
| 40 |
|
| 41 |
+
# Calculate combined score
|
| 42 |
+
weights = {
|
| 43 |
+
'temperature': 0.3,
|
| 44 |
+
'humidity': 0.2,
|
| 45 |
+
'rainfall': 0.2,
|
| 46 |
+
'ndvi': 0.3
|
| 47 |
+
}
|
| 48 |
|
| 49 |
+
overall_score = (
|
| 50 |
+
temp_score * weights['temperature'] +
|
| 51 |
+
humidity_score * weights['humidity'] +
|
| 52 |
+
rainfall_score * weights['rainfall'] +
|
| 53 |
+
ndvi_score * weights['ndvi']
|
| 54 |
+
)
|
| 55 |
|
| 56 |
# Create visualizations
|
| 57 |
time_series_plot = visualizer.create_interactive_plots(df)
|
| 58 |
gauge_plot = visualizer.create_gauge_chart(overall_score)
|
| 59 |
+
location_map = visualizer.create_enhanced_map(lat, lon, overall_score, ndvi_score)
|
| 60 |
|
| 61 |
+
# Generate risk assessment
|
| 62 |
+
risk_level = get_risk_level(overall_score)
|
| 63 |
+
risk_details = get_risk_details(overall_score, ndvi_score)
|
| 64 |
|
| 65 |
+
# Generate comprehensive analysis text
|
| 66 |
analysis_text = f"""
|
| 67 |
📍 Location Analysis:
|
| 68 |
Location: {location_data['address']}
|
| 69 |
Coordinates: {lat:.4f}°N, {lon:.4f}°E
|
| 70 |
+
Region: {location_data['region'] if location_data['region'] else 'Unknown'}
|
| 71 |
|
| 72 |
🌡️ Historical Weather Analysis (Past 90 Days):
|
| 73 |
Temperature: {historical['temperature'].mean():.1f}°C (±{historical['temperature'].std():.1f}°C)
|
| 74 |
+
Daily Range: {historical['temp_range'].mean():.1f}°C
|
| 75 |
Humidity: {historical['humidity'].mean():.1f}% (±{historical['humidity'].std():.1f}%)
|
| 76 |
Rainfall: {historical['rainfall'].mean():.1f}mm/day (±{historical['rainfall'].std():.1f}mm)
|
| 77 |
|
| 78 |
+
🌿 Vegetation Analysis:
|
| 79 |
+
NDVI Score: {ndvi_score:.2f}
|
| 80 |
+
Vegetation Status: {get_vegetation_status(ndvi_score)}
|
| 81 |
+
Seasonal Impact: {get_seasonal_impact(df['season'].iloc[-1])}
|
| 82 |
|
| 83 |
📈 Weather Trends:
|
| 84 |
+
Temperature: {trends['historical']['temperature']['trend']:.3f}°C/day
|
| 85 |
+
Humidity: {trends['historical']['humidity']['trend']:.3f}%/day
|
| 86 |
+
Rainfall: {trends['historical']['rainfall']['trend']:.3f}mm/day
|
| 87 |
+
Vegetation: {trends['historical']['ndvi']['trend']:.3f} NDVI/day
|
| 88 |
|
| 89 |
🔮 Forecast Analysis (Next 90 Days):
|
| 90 |
Temperature: {forecast['temperature'].mean():.1f}°C (±{forecast['temperature'].std():.1f}°C)
|
| 91 |
Humidity: {forecast['humidity'].mean():.1f}% (±{forecast['humidity'].std():.1f}%)
|
| 92 |
Rainfall: {forecast['rainfall'].mean():.1f}mm/day (±{forecast['rainfall'].std():.1f}mm)
|
| 93 |
+
Expected NDVI: {forecast['estimated_ndvi'].mean():.2f}
|
| 94 |
|
| 95 |
📊 Growing Condition Scores:
|
| 96 |
Temperature Score: {temp_score:.2f}
|
| 97 |
Humidity Score: {humidity_score:.2f}
|
| 98 |
Rainfall Score: {rainfall_score:.2f}
|
| 99 |
+
Vegetation Score: {ndvi_score:.2f}
|
| 100 |
Overall Score: {overall_score:.2f}
|
| 101 |
|
| 102 |
+
💰 Credit Risk Assessment:
|
| 103 |
+
Risk Level: {risk_level}
|
| 104 |
+
{risk_details}
|
| 105 |
+
|
| 106 |
+
🎯 Recommendations:
|
| 107 |
+
{get_recommendations(overall_score, ndvi_score)}
|
| 108 |
+
|
| 109 |
+
⚠️ Risk Factors:
|
| 110 |
+
{get_risk_factors(df, trends)}
|
| 111 |
|
| 112 |
📝 Additional Notes:
|
| 113 |
+
• Growing Season: {is_growing_season(df['season'].iloc[-1])}
|
| 114 |
+
• Weather Stability: {get_weather_stability(df)}
|
| 115 |
+
• Long-term Outlook: {get_long_term_outlook(trends)}
|
|
|
|
| 116 |
"""
|
| 117 |
|
| 118 |
return time_series_plot, gauge_plot, analysis_text, location_map
|
|
|
|
| 121 |
error_message = f"An error occurred: {str(e)}"
|
| 122 |
return None, None, error_message, None
|
| 123 |
|
| 124 |
+
def get_risk_level(score):
|
| 125 |
+
if score >= 0.8:
|
| 126 |
+
return "Low Risk 🟢"
|
| 127 |
+
elif score >= 0.6:
|
| 128 |
+
return "Moderate Risk 🟡"
|
| 129 |
+
elif score >= 0.4:
|
| 130 |
+
return "High Risk 🟠"
|
| 131 |
+
return "Very High Risk 🔴"
|
| 132 |
+
|
| 133 |
+
def get_risk_details(score, ndvi):
|
| 134 |
+
if score >= 0.8 and ndvi >= 0.6:
|
| 135 |
+
return "Excellent conditions for credit. Consider preferential rates."
|
| 136 |
+
elif score >= 0.6:
|
| 137 |
+
return "Good conditions. Standard credit terms with basic risk mitigation."
|
| 138 |
+
elif score >= 0.4:
|
| 139 |
+
return "Marginal conditions. Higher rates and strong risk mitigation required."
|
| 140 |
+
return "Poor conditions. Credit not recommended without substantial collateral."
|
| 141 |
+
|
| 142 |
def get_vegetation_status(ndvi):
|
|
|
|
| 143 |
if ndvi < 0:
|
| 144 |
return "Very Poor - Bare soil or water"
|
| 145 |
elif ndvi < 0.2:
|
|
|
|
| 148 |
return "Moderate - Typical agricultural land"
|
| 149 |
elif ndvi < 0.6:
|
| 150 |
return "Good - Healthy vegetation"
|
| 151 |
+
return "Excellent - Dense, very healthy vegetation"
|
|
|
|
| 152 |
|
| 153 |
+
def get_seasonal_impact(season):
|
| 154 |
+
seasons = {
|
| 155 |
+
'Main': "Prime growing season - Optimal conditions expected",
|
| 156 |
+
'Early': "Early growing season - Good potential with monitoring",
|
| 157 |
+
'Late': "Late growing season - Moderate risk",
|
| 158 |
+
'Dry': "Dry season - Higher risk period"
|
| 159 |
+
}
|
| 160 |
+
return seasons.get(season, "Unknown season impact")
|
| 161 |
+
|
| 162 |
+
def is_growing_season(season):
|
| 163 |
+
return "Currently in growing season" if season in ['Main', 'Early'] else "Outside main growing season"
|
| 164 |
+
|
| 165 |
+
def get_weather_stability(df):
|
| 166 |
+
std_temp = df['temperature'].std()
|
| 167 |
+
if std_temp < 2:
|
| 168 |
+
return "Very stable weather patterns"
|
| 169 |
+
elif std_temp < 4:
|
| 170 |
+
return "Moderately stable weather"
|
| 171 |
+
return "Unstable weather patterns - higher risk"
|
| 172 |
+
|
| 173 |
+
def get_long_term_outlook(trends):
|
| 174 |
+
temp_trend = trends['historical']['temperature']['trend']
|
| 175 |
+
rain_trend = trends['historical']['rainfall']['trend']
|
| 176 |
+
|
| 177 |
+
if temp_trend > 0 and rain_trend > 0:
|
| 178 |
+
return "Improving conditions"
|
| 179 |
+
elif temp_trend < 0 and rain_trend < 0:
|
| 180 |
+
return "Deteriorating conditions"
|
| 181 |
+
return "Stable conditions"
|
| 182 |
+
|
| 183 |
+
def get_risk_factors(df, trends):
|
| 184 |
+
risk_factors = []
|
| 185 |
+
|
| 186 |
+
# Temperature risks
|
| 187 |
+
if df['temp_range'].mean() > 15:
|
| 188 |
+
risk_factors.append("• High daily temperature variations")
|
| 189 |
+
|
| 190 |
+
# Rainfall risks
|
| 191 |
+
if df['rainfall'].std() > df['rainfall'].mean():
|
| 192 |
+
risk_factors.append("• Inconsistent rainfall patterns")
|
| 193 |
+
|
| 194 |
+
# Trend risks
|
| 195 |
+
if trends['historical']['temperature']['trend'] < 0:
|
| 196 |
+
risk_factors.append("• Declining temperature trend")
|
| 197 |
+
|
| 198 |
+
return "\n".join(risk_factors) if risk_factors else "No major risk factors identified"
|
| 199 |
+
|
| 200 |
+
def get_recommendations(score, ndvi):
|
| 201 |
+
if score >= 0.8 and ndvi >= 0.6:
|
| 202 |
+
return """
|
| 203 |
+
• Proceed with standard credit terms
|
| 204 |
+
• Consider preferential rates
|
| 205 |
+
• Regular monitoring recommended
|
| 206 |
+
"""
|
| 207 |
+
elif score >= 0.6:
|
| 208 |
+
return """
|
| 209 |
+
• Proceed with caution
|
| 210 |
+
• Implement basic risk mitigation
|
| 211 |
+
• More frequent monitoring required
|
| 212 |
+
• Consider crop insurance
|
| 213 |
+
"""
|
| 214 |
+
elif score >= 0.4:
|
| 215 |
+
return """
|
| 216 |
+
• Higher interest rates recommended
|
| 217 |
+
• Strong risk mitigation required
|
| 218 |
+
• Weekly monitoring needed
|
| 219 |
+
• Mandatory crop insurance
|
| 220 |
+
• Consider alternative crops
|
| 221 |
+
"""
|
| 222 |
+
return """
|
| 223 |
+
• Credit not recommended
|
| 224 |
+
• Consider alternative location
|
| 225 |
+
• Extensive risk mitigation needed
|
| 226 |
+
• Alternative farming activities suggested
|
| 227 |
+
"""
|
| 228 |
|
| 229 |
# Create Gradio interface
|
| 230 |
with gr.Blocks(theme=gr.themes.Base()) as iface:
|
| 231 |
gr.Markdown(
|
| 232 |
"""
|
| 233 |
# 🌱 Agricultural Credit Risk Assessment System
|
| 234 |
+
## Integrated Weather, Vegetation, and Credit Scoring for Tobacco Farming
|
| 235 |
"""
|
| 236 |
)
|
| 237 |
|
|
|
|
| 248 |
with gr.Row():
|
| 249 |
analysis_text = gr.Textbox(
|
| 250 |
label="Comprehensive Analysis",
|
| 251 |
+
lines=25,
|
| 252 |
interactive=False
|
| 253 |
)
|
| 254 |
|
| 255 |
with gr.Row():
|
| 256 |
+
weather_plot = gr.Plot(label="Weather and Vegetation Analysis")
|
| 257 |
|
| 258 |
with gr.Row():
|
| 259 |
with gr.Column(scale=1):
|
|
|
|
| 264 |
with gr.TabItem("ℹ️ Help"):
|
| 265 |
gr.Markdown("""
|
| 266 |
### Understanding the Analysis:
|
| 267 |
+
- Weather Data: Historical and forecast patterns
|
| 268 |
+
- Vegetation Health: NDVI analysis
|
| 269 |
+
- Credit Risk: Comprehensive scoring
|
| 270 |
+
- Location Analysis: Interactive mapping
|
| 271 |
|
| 272 |
### Score Interpretation:
|
| 273 |
+
- 0.8-1.0: Low Risk (Excellent conditions)
|
| 274 |
+
- 0.6-0.8: Moderate Risk (Good conditions)
|
| 275 |
+
- 0.4-0.6: High Risk (Marginal conditions)
|
| 276 |
+
- 0.0-0.4: Very High Risk (Poor conditions)
|
| 277 |
""")
|
| 278 |
|
| 279 |
# Set up examples
|