oberbics commited on
Commit
c22c6d5
·
verified ·
1 Parent(s): 31affe1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +191 -61
app.py CHANGED
@@ -82,74 +82,204 @@ class SafeGeocoder:
82
  self.cache[location] = None
83
  return None
84
 
85
- def process_excel(file, places_column):
86
- if file is None:
87
- return None, "No file uploaded", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  try:
90
- if hasattr(file, 'name'):
91
- df = pd.read_excel(file.name)
92
- elif isinstance(file, bytes):
93
- df = pd.read_excel(io.BytesIO(file))
94
- else:
95
- df = pd.read_excel(file)
96
-
97
- print(f"Spalten in der Excel-Tabelle: {list(df.columns)}")
98
-
99
- if places_column not in df.columns:
100
- return None, f"Spalte '{places_column}' wurde in der Excel-Datei nicht gefunden. Verfügbare Spalten: {', '.join(df.columns)}", None
101
-
102
- # Create coordinates columns
103
- df['latitude'] = None
104
- df['longitude'] = None
105
-
106
- geocoder = SafeGeocoder()
107
- coords = []
108
- processed_count = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
- # Geocode each location and store coordinates in the DataFrame
111
- for idx, row in df.iterrows():
112
- if pd.isna(row[places_column]):
113
- continue
114
-
115
- location = str(row[places_column]).strip()
116
 
117
- try:
118
- locations = [loc.strip() for loc in location.split(',') if loc.strip()]
119
- if not locations:
120
- locations = [location]
121
- except:
122
- locations = [location]
123
-
124
- for loc in locations:
125
- point = geocoder.get_coords(loc)
126
- if point:
127
- df.at[idx, 'latitude'] = point[0]
128
- df.at[idx, 'longitude'] = point[1]
129
- coords.append(point)
130
- processed_count += 1
131
- break # Use first successfully geocoded location
132
-
133
- # Create the map
134
- map_html, _ = create_map(df, places_column)
135
-
136
- # Save the updated DataFrame to a new Excel file
137
- with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp:
138
- processed_path = tmp.name
139
- df.to_excel(processed_path, index=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
- total_locations = df[places_column].count()
142
- success_rate = (processed_count / total_locations * 100) if total_locations > 0 else 0
 
 
 
 
 
 
143
 
144
- stats = f"Gefunden: {processed_count} von {total_locations} Orten ({success_rate:.1f}%)"
 
 
 
 
 
145
 
146
- return map_html, stats, processed_path
147
- except Exception as e:
148
- import traceback
149
- trace = traceback.format_exc()
150
- print(f"Error processing file: {e}\n{trace}")
151
- return None, f"Fehler bei der Verarbeitung der Datei: {str(e)}", None
152
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  # Corrected model loading function based on official usage example
155
 
 
82
  self.cache[location] = None
83
  return None
84
 
85
+
86
+ def process_excel(file, places_column):
87
+ if file is None:
88
+ return None, "No file uploaded", None
89
+
90
+ try:
91
+ if hasattr(file, 'name'):
92
+ df = pd.read_excel(file.name)
93
+ elif isinstance(file, bytes):
94
+ df = pd.read_excel(io.BytesIO(file))
95
+ else:
96
+ df = pd.read_excel(file)
97
+
98
+ print(f"Spalten in der Excel-Tabelle: {list(df.columns)}")
99
+
100
+ if places_column not in df.columns:
101
+ return None, f"Spalte '{places_column}' wurde in der Excel-Datei nicht gefunden. Verfügbare Spalten: {', '.join(df.columns)}", None
102
+
103
+ # Create coordinates columns
104
+ df['latitude'] = None
105
+ df['longitude'] = None
106
+ # Add column for structured location data
107
+ df['location_data'] = None
108
+
109
+ geocoder = SafeGeocoder()
110
+ coords = []
111
+ processed_count = 0
112
+
113
+ # Process each location and store as JSON
114
+ for idx, row in df.iterrows():
115
+ if pd.isna(row[places_column]):
116
+ continue
117
+
118
+ location = str(row[places_column]).strip()
119
 
120
  try:
121
+ locations = [loc.strip() for loc in location.split(',') if loc.strip()]
122
+ if not locations:
123
+ locations = [location]
124
+ except:
125
+ locations = [location]
126
+
127
+ # Process all locations and store as JSON
128
+ location_data = []
129
+ for loc in locations:
130
+ point = geocoder.get_coords(loc)
131
+ if point:
132
+ location_data.append({
133
+ 'location': loc,
134
+ 'latitude': point[0],
135
+ 'longitude': point[1]
136
+ })
137
+ coords.append(point)
138
+ processed_count += 1
139
+
140
+ if location_data:
141
+ df.at[idx, 'location_data'] = json.dumps(location_data)
142
+ # Store first location's coordinates in main columns for compatibility
143
+ df.at[idx, 'latitude'] = location_data[0]['latitude']
144
+ df.at[idx, 'longitude'] = location_data[0]['longitude']
145
+
146
+ # Create the map
147
+ map_html, _ = create_map(df, places_column)
148
+
149
+ # Save the updated DataFrame to a new Excel file
150
+ with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp:
151
+ processed_path = tmp.name
152
+ df.to_excel(processed_path, index=False)
153
+
154
+ total_locations = df[places_column].count()
155
+ success_rate = (processed_count / total_locations * 100) if total_locations > 0 else 0
156
+
157
+ stats = f"Gefunden: {processed_count} von {total_locations} Orten ({success_rate:.1f}%)"
158
+
159
+ return map_html, stats, processed_path
160
+ except Exception as e:
161
+ import traceback
162
+ trace = traceback.format_exc()
163
+ print(f"Error processing file: {e}\n{trace}")
164
+ return None, f"Fehler bei der Verarbeitung der Datei: {str(e)}", None
165
+
166
+
167
+ def create_map(df, location_col):
168
+ m = folium.Map(
169
+ location=[20, 0],
170
+ zoom_start=2,
171
+ control_scale=True
172
+ )
173
+
174
+ folium.TileLayer(
175
+ tiles=MAP_TILES["GreenMap"]["url"],
176
+ attr=MAP_TILES["GreenMap"]["attr"],
177
+ name="GreenMap",
178
+ overlay=False,
179
+ control=False
180
+ ).add_to(m)
181
+
182
+ Fullscreen().add_to(m)
183
+ MeasureControl(position='topright', primary_length_unit='kilometers').add_to(m)
184
+
185
+ coords = []
186
+ marker_cluster = MarkerCluster(name="Locations").add_to(m)
187
+ processed_count = 0
188
+
189
+ for idx, row in df.iterrows():
190
+ # Check if we have JSON location data
191
+ if 'location_data' in df.columns and not pd.isna(row['location_data']):
192
+ try:
193
+ # Parse the JSON location data
194
+ location_data = json.loads(row['location_data'])
195
 
196
+ # Process each location in the JSON data
197
+ for loc_item in location_data:
198
+ location_name = loc_item['location']
199
+ point = (loc_item['latitude'], loc_item['longitude'])
 
 
200
 
201
+ # Create additional info for popup
202
+ additional_info = ""
203
+ for col in df.columns:
204
+ if col not in [location_col, 'location_data', 'latitude', 'longitude'] and not pd.isna(row[col]):
205
+ additional_info += f"<br><b>{col}:</b> {row[col]}"
206
+
207
+ # Add marker to map
208
+ popup_content = f"""
209
+ <div style="min-width: 200px; max-width: 300px">
210
+ <h4 style="font-family: 'Source Sans Pro', sans-serif; margin-bottom: 5px;">{location_name}</h4>
211
+ <div style="font-family: 'Source Sans Pro', sans-serif; font-size: 14px;">
212
+ {additional_info}
213
+ </div>
214
+ </div>
215
+ """
216
+
217
+ folium.Marker(
218
+ location=point,
219
+ popup=folium.Popup(popup_content, max_width=300),
220
+ tooltip=location_name,
221
+ icon=folium.Icon(color="blue", icon="info-sign")
222
+ ).add_to(marker_cluster)
223
+
224
+ coords.append(point)
225
+ processed_count += 1
226
+ except (json.JSONDecodeError, KeyError) as e:
227
+ print(f"Error processing JSON location data for row {idx}: {e}")
228
+ # Continue with fallback method if JSON processing fails
229
+
230
+ # Fallback to the old method if no JSON data is present
231
+ elif not pd.isna(row[location_col]):
232
+ location = str(row[location_col]).strip()
233
+
234
+ additional_info = ""
235
+ for col in df.columns:
236
+ if col != location_col and not pd.isna(row[col]):
237
+ additional_info += f"<br><b>{col}:</b> {row[col]}"
238
+
239
+ # If we have latitude and longitude directly
240
+ if 'latitude' in df.columns and 'longitude' in df.columns and not pd.isna(row['latitude']) and not pd.isna(row['longitude']):
241
+ point = (row['latitude'], row['longitude'])
242
 
243
+ popup_content = f"""
244
+ <div style="min-width: 200px; max-width: 300px">
245
+ <h4 style="font-family: 'Source Sans Pro', sans-serif; margin-bottom: 5px;">{location}</h4>
246
+ <div style="font-family: 'Source Sans Pro', sans-serif; font-size: 14px;">
247
+ {additional_info}
248
+ </div>
249
+ </div>
250
+ """
251
 
252
+ folium.Marker(
253
+ location=point,
254
+ popup=folium.Popup(popup_content, max_width=300),
255
+ tooltip=location,
256
+ icon=folium.Icon(color="blue", icon="info-sign")
257
+ ).add_to(marker_cluster)
258
 
259
+ coords.append(point)
260
+ processed_count += 1
261
+
262
+ if coords:
263
+ m.fit_bounds(coords)
264
+
265
+ custom_css = """
266
+ <style>
267
+ @import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap');
268
+ .leaflet-container {
269
+ font-family: 'Source Sans Pro', sans-serif;
270
+ }
271
+ .leaflet-popup-content {
272
+ font-family: 'Source Sans Pro', sans-serif;
273
+ }
274
+ .leaflet-popup-content h4 {
275
+ font-weight: 600;
276
+ margin-bottom: 8px;
277
+ }
278
+ </style>
279
+ """
280
+ m.get_root().header.add_child(folium.Element(custom_css))
281
+
282
+ return m._repr_html_(), processed_count
283
 
284
  # Corrected model loading function based on official usage example
285