lyimo commited on
Commit
daef258
·
verified ·
1 Parent(s): e2640a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -231
app.py CHANGED
@@ -1,242 +1,135 @@
1
- import os
2
- import gradio as gr
3
- import numpy as np
4
- from datetime import datetime, timedelta
5
- import folium
6
  from folium import plugins
7
- import requests
8
- from geopy.geocoders import Nominatim
9
- from geopy.exc import GeocoderTimedOut
10
- import pandas as pd
11
- from scipy import stats
12
-
13
- # Load environment variables
14
- load_dotenv()
15
-
16
- class TobaccoAnalyzer:
17
- def __init__(self):
18
- self.api_key = os.getenv('OPENWEATHER_API_KEY', 'default_key')
19
- self.optimal_conditions = {
20
- 'temperature': {'min': 20, 'max': 30},
21
- 'humidity': {'min': 60, 'max': 80},
22
- 'rainfall': {'min': 500/365, 'max': 1200/365}
23
- }
24
- self.geolocator = Nominatim(user_agent="tobacco_analyzer")
25
- self.seasons = {
26
- 1: 'Winter', 2: 'Winter', 3: 'Spring',
27
- 4: 'Spring', 5: 'Spring', 6: 'Summer',
28
- 7: 'Summer', 8: 'Summer', 9: 'Fall',
29
- 10: 'Fall', 11: 'Fall', 12: 'Winter'
30
- }
31
-
32
- def geocode_location(self, location_name):
33
- """Convert location name to coordinates"""
34
- try:
35
- location = self.geolocator.geocode(location_name)
36
- if location:
37
- return {
38
- 'lat': location.latitude,
39
- 'lon': location.longitude,
40
- 'address': location.address
41
- }
42
- return None
43
- except GeocoderTimedOut:
44
- return None
45
-
46
- def get_weather_data(self, lat, lon, historical_days=90, forecast_days=90):
47
- """Get historical and forecast weather data"""
48
- historical_data = []
49
-
50
- # Get historical data
51
- for day in range(historical_days):
52
- date = datetime.now() - timedelta(days=day)
53
- url = f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={self.api_key}&units=metric&dt={int(date.timestamp())}"
54
- try:
55
- response = requests.get(url)
56
- if response.status_code == 200:
57
- data = response.json()
58
- weather_data = {
59
- 'date': date,
60
- 'temperature': data['main']['temp'],
61
- 'humidity': data['main']['humidity'],
62
- 'rainfall': data.get('rain', {}).get('1h', 0) * 24,
63
- 'type': 'historical',
64
- 'description': data['weather'][0]['description']
65
- }
66
- historical_data.append(weather_data)
67
- except Exception as e:
68
- print(f"Error fetching historical data: {e}")
69
-
70
- # Get forecast data
71
- forecast_data = []
72
- try:
73
- forecast_url = f"https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={self.api_key}&units=metric"
74
- response = requests.get(forecast_url)
75
- if response.status_code == 200:
76
- data = response.json()
77
- for item in data['list']:
78
- forecast = {
79
- 'date': datetime.fromtimestamp(item['dt']),
80
- 'temperature': item['main']['temp'],
81
- 'humidity': item['main']['humidity'],
82
- 'rainfall': item.get('rain', {}).get('3h', 0) * 8,
83
- 'type': 'forecast_5day',
84
- 'description': item['weather'][0]['description']
85
- }
86
- forecast_data.append(forecast)
87
-
88
- except Exception as e:
89
- print(f"Error fetching forecast data: {e}")
90
-
91
- if not historical_data and not forecast_data:
92
- return None
93
-
94
- # Combine and process data
95
- all_data = pd.DataFrame(historical_data + forecast_data)
96
- if not all_data.empty:
97
- all_data = all_data.sort_values('date')
98
- all_data['month'] = all_data['date'].dt.month
99
- all_data['season'] = all_data['month'].map(self.seasons)
100
-
101
- # Calculate rolling averages
102
- all_data['temp_7day_avg'] = all_data['temperature'].rolling(window=7, min_periods=1).mean()
103
- all_data['humidity_7day_avg'] = all_data['humidity'].rolling(window=7, min_periods=1).mean()
104
- all_data['rainfall_7day_avg'] = all_data['rainfall'].rolling(window=7, min_periods=1).mean()
105
-
106
- return all_data
107
-
108
- def analyze_trends(self, df):
109
- """Analyze weather trends and patterns"""
110
- try:
111
- historical = df[df['type'] == 'historical']
112
- forecast = df[df['type'].isin(['forecast_5day', 'forecast_extended'])]
113
-
114
- if historical.empty:
115
- return None
116
-
117
- analysis = {
118
- 'historical': {
119
- 'temperature': {
120
- 'mean': historical['temperature'].mean(),
121
- 'std': historical['temperature'].std(),
122
- 'trend': stats.linregress(range(len(historical)), historical['temperature'])[0]
123
- },
124
- 'humidity': {
125
- 'mean': historical['humidity'].mean(),
126
- 'std': historical['humidity'].std(),
127
- 'trend': stats.linregress(range(len(historical)), historical['humidity'])[0]
128
- },
129
- 'rainfall': {
130
- 'mean': historical['rainfall'].mean(),
131
- 'std': historical['rainfall'].std(),
132
- 'trend': stats.linregress(range(len(historical)), historical['rainfall'])[0]
133
- }
134
- }
135
- }
136
-
137
- if not forecast.empty:
138
- analysis['forecast'] = {
139
- 'temperature': {
140
- 'mean': forecast['temperature'].mean(),
141
- 'std': forecast['temperature'].std(),
142
- },
143
- 'humidity': {
144
- 'mean': forecast['humidity'].mean(),
145
- 'std': forecast['humidity'].std(),
146
- },
147
- 'rainfall': {
148
- 'mean': forecast['rainfall'].mean(),
149
- 'std': forecast['rainfall'].std(),
150
- }
151
- }
152
-
153
- return analysis
154
- except Exception as e:
155
- print(f"Error in trend analysis: {e}")
156
- return None
157
 
 
158
  def process_example(location_name):
159
- """Process example inputs"""
160
  try:
161
  return analyze_location(location_name)
162
  except Exception as e:
163
  print(f"Error processing example: {e}")
164
  return None, None, f"Error processing example: {str(e)}", None
165
 
166
- def analyze_location(location_name):
167
- """Main analysis function"""
168
- try:
169
- analyzer = TobaccoAnalyzer()
170
-
171
- # Get coordinates
172
- location_data = analyzer.geocode_location(location_name)
173
- if not location_data:
174
- return None, None, "Location not found. Please try a different location name.", None
175
-
176
- lat, lon = location_data['lat'], location_data['lon']
177
-
178
- # Get weather data
179
- df = analyzer.get_weather_data(lat, lon)
180
- if df is None or df.empty:
181
- return None, None, "Unable to fetch weather data. Please try again.", None
182
-
183
- # Calculate scores
184
- historical = df[df['type'] == 'historical']
185
-
186
- temp_mean = historical['temperature'].mean()
187
- humidity_mean = historical['humidity'].mean()
188
- rainfall_mean = historical['rainfall'].mean()
189
-
190
- temp_score = np.clip((temp_mean - 15) / (30 - 15), 0, 1)
191
- humidity_score = np.clip((humidity_mean - 50) / (80 - 50), 0, 1)
192
- rainfall_score = np.clip(rainfall_mean / 5, 0, 1)
193
-
194
- # Get trends
195
- trends = analyzer.analyze_trends(df)
196
-
197
- # Calculate overall score
198
- overall_score = np.mean([temp_score, humidity_score, rainfall_score])
199
- overall_score = np.clip(overall_score, 0, 1)
200
-
201
- # Create visualizations
202
- weather_plot = create_weather_plot(df, analyzer.optimal_conditions)
203
- gauge_plot = create_gauge_chart(overall_score)
204
- map_html = create_map(lat, lon, overall_score)
205
-
206
- # Create analysis text
207
- analysis_text = create_analysis_text(location_data, historical, trends, overall_score,
208
- temp_score, humidity_score, rainfall_score)
209
-
210
- return weather_plot, gauge_plot, analysis_text, map_html
211
-
212
- except Exception as e:
213
- error_message = f"An error occurred: {str(e)}"
214
- print(f"Error details: {e}")
215
- return None, None, error_message, None
216
 
217
- # Create Gradio interface
218
- demo = gr.Interface(
219
- fn=analyze_location,
220
- inputs=[
221
- gr.Textbox(label="Enter Location", placeholder="e.g., Tabora, Tanzania")
222
- ],
223
- outputs=[
224
- gr.Plot(label="Weather Analysis"),
225
- gr.Plot(label="Growing Conditions Score"),
226
- gr.Textbox(label="Analysis Results", lines=15),
227
- gr.HTML(label="Location Analysis")
228
- ],
229
- title="🌱 Tobacco Growth Prediction for Credit Scoring",
230
- description="Enter a location to analyze growing conditions and credit risk.",
231
- examples=[
232
- ["Tabora, Tanzania"],
233
- ["Urambo, Tabora, Tanzania"],
234
- ["Sikonge, Tabora, Tanzania"],
235
- ["Nzega, Tabora, Tanzania"]
236
- ],
237
- cache_examples=True
238
- )
239
 
240
- # Launch the app
241
- if __name__ == "__main__":
242
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Add these imports to your existing imports if not already present
 
 
 
 
2
  from folium import plugins
3
+ import branca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ # Add this function to handle example processing
6
  def process_example(location_name):
7
+ """Process example inputs with proper error handling"""
8
  try:
9
  return analyze_location(location_name)
10
  except Exception as e:
11
  print(f"Error processing example: {e}")
12
  return None, None, f"Error processing example: {str(e)}", None
13
 
14
+ # Update your create_map function inside VisualizationHandler class
15
+ def create_map(self, lat, lon, score):
16
+ """Create an enhanced interactive map with weather and terrain analysis"""
17
+ m = folium.Map(location=[lat, lon], zoom_start=13)
18
+
19
+ # Add main analysis circle
20
+ color = self.get_color_for_score(score)
21
+ folium.Circle(
22
+ radius=2000, # 2km radius
23
+ location=[lat, lon],
24
+ popup=f'Growing Suitability Score: {score:.2f}',
25
+ color=color,
26
+ fill=True,
27
+ fillOpacity=0.4
28
+ ).add_to(m)
29
+
30
+ # Add terrain analysis circles
31
+ for radius in [1000, 1500]:
32
+ folium.Circle(
33
+ radius=radius,
34
+ location=[lat, lon],
35
+ color=color,
36
+ fill=False,
37
+ weight=1
38
+ ).add_to(m)
39
+
40
+ # Add custom legend
41
+ legend_html = """
42
+ <div style="position: fixed; bottom: 50px; left: 50px; z-index: 1000; background-color: white;
43
+ padding: 10px; border-radius: 5px; border: 2px solid grey;">
44
+ <h4>Suitability Score</h4>
45
+ <div><i style="background: green"></i> High (>0.8)</div>
46
+ <div><i style="background: yellow"></i> Good (>0.6)</div>
47
+ <div><i style="background: orange"></i> Moderate (>0.4)</div>
48
+ <div><i style="background: red"></i> Low (<0.4)</div>
49
+ </div>
50
+ """
51
+ m.get_root().html.add_child(folium.Element(legend_html))
52
+
53
+ # Add measurement tool
54
+ plugins.MeasureControl(position='topright').add_to(m)
55
+
56
+ # Add fullscreen option
57
+ plugins.Fullscreen().add_to(m)
58
+
59
+ # Add mini map
60
+ minimap = plugins.MiniMap()
61
+ m.add_child(minimap)
62
+
63
+ return m._repr_html_()
64
 
65
+ # Update the Gradio interface section
66
+ iface = gr.Blocks(theme=gr.themes.Base())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
+ with iface:
69
+ gr.Markdown(
70
+ """
71
+ # 🌱 Tobacco Growth Prediction for Credit Scoring
72
+ Enter a location in Tanzania to analyze growing conditions and assess credit risk.
73
+ """
74
+ )
75
+
76
+ with gr.Row():
77
+ location_input = gr.Textbox(
78
+ label="Enter Location",
79
+ placeholder="e.g., Tabora, Tanzania",
80
+ lines=1
81
+ )
82
+ analyze_button = gr.Button("📊 Analyze", variant="primary")
83
+
84
+ with gr.Tabs():
85
+ with gr.TabItem("📊 Analysis Results"):
86
+ with gr.Row():
87
+ analysis_text = gr.Textbox(
88
+ label="Comprehensive Analysis",
89
+ lines=15,
90
+ interactive=False
91
+ )
92
+
93
+ with gr.Row():
94
+ weather_plot = gr.Plot(label="Weather Analysis")
95
+
96
+ with gr.Row():
97
+ with gr.Column(scale=1):
98
+ score_gauge = gr.Plot(label="Suitability Score")
99
+ with gr.Column(scale=1):
100
+ location_map = gr.HTML(label="Location Analysis")
101
+
102
+ with gr.TabItem("ℹ️ Help"):
103
+ gr.Markdown("""
104
+ ### How to Use:
105
+ 1. Enter a location name in Tanzania (preferably in Tabora region)
106
+ 2. Click 'Analyze' to get comprehensive results
107
+ 3. View the analysis in different tabs
108
+
109
+ ### Understanding Results:
110
+ - Weather Analysis: Shows historical and forecast patterns
111
+ - Suitability Score: Overall assessment of growing conditions
112
+ - Location Analysis: Interactive map with terrain analysis
113
+ """)
114
+
115
+ # Set up examples with proper handling
116
+ gr.Examples(
117
+ examples=[
118
+ ["Tabora, Tanzania"],
119
+ ["Urambo, Tabora, Tanzania"],
120
+ ["Sikonge, Tabora, Tanzania"],
121
+ ["Nzega, Tabora, Tanzania"]
122
+ ],
123
+ inputs=location_input,
124
+ outputs=[weather_plot, score_gauge, analysis_text, location_map],
125
+ fn=process_example,
126
+ cache_examples=True,
127
+ preprocess=True
128
+ )
129
+
130
+ # Handle button click
131
+ analyze_button.click(
132
+ fn=analyze_location,
133
+ inputs=[location_input],
134
+ outputs=[weather_plot, score_gauge, analysis_text, location_map]
135
+ )