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
|