Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -100,19 +100,18 @@ def process_excel(file, places_column):
|
|
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
|
104 |
-
|
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
|
114 |
for idx, row in df.iterrows():
|
115 |
if pd.isna(row[places_column]):
|
|
|
|
|
116 |
continue
|
117 |
|
118 |
location = str(row[places_column]).strip()
|
@@ -124,121 +123,61 @@ def process_excel(file, places_column):
|
|
124 |
except:
|
125 |
locations = [location]
|
126 |
|
127 |
-
# Process
|
128 |
-
|
129 |
for loc in locations:
|
130 |
point = geocoder.get_coords(loc)
|
131 |
if point:
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
137 |
coords.append(point)
|
138 |
processed_count += 1
|
|
|
139 |
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
|
|
145 |
|
146 |
# Create the map
|
147 |
-
|
|
|
|
|
|
|
|
|
148 |
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
153 |
|
154 |
-
|
155 |
-
|
156 |
|
157 |
-
|
|
|
158 |
|
159 |
-
|
160 |
-
|
161 |
-
|
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 |
-
|
197 |
-
for
|
198 |
-
|
199 |
-
|
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">
|
@@ -250,36 +189,48 @@ def create_map(df, location_col):
|
|
250 |
"""
|
251 |
|
252 |
folium.Marker(
|
253 |
-
location=
|
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 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
|
284 |
# Corrected model loading function based on official usage example
|
285 |
|
|
|
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 a new DataFrame to store expanded rows
|
104 |
+
expanded_rows = []
|
|
|
|
|
|
|
105 |
|
106 |
geocoder = SafeGeocoder()
|
107 |
coords = []
|
108 |
processed_count = 0
|
109 |
|
110 |
+
# Process each row
|
111 |
for idx, row in df.iterrows():
|
112 |
if pd.isna(row[places_column]):
|
113 |
+
# Keep rows with no location as-is
|
114 |
+
expanded_rows.append(row.to_dict())
|
115 |
continue
|
116 |
|
117 |
location = str(row[places_column]).strip()
|
|
|
123 |
except:
|
124 |
locations = [location]
|
125 |
|
126 |
+
# Process each location in the comma-separated list
|
127 |
+
location_rows_added = False
|
128 |
for loc in locations:
|
129 |
point = geocoder.get_coords(loc)
|
130 |
if point:
|
131 |
+
# Create a new row for this location
|
132 |
+
new_row = row.copy()
|
133 |
+
new_row_dict = new_row.to_dict()
|
134 |
+
new_row_dict[places_column] = loc # Replace with just this location
|
135 |
+
new_row_dict['latitude'] = point[0]
|
136 |
+
new_row_dict['longitude'] = point[1]
|
137 |
+
|
138 |
+
# Add the row to our expanded rows list
|
139 |
+
expanded_rows.append(new_row_dict)
|
140 |
+
|
141 |
coords.append(point)
|
142 |
processed_count += 1
|
143 |
+
location_rows_added = True
|
144 |
|
145 |
+
# If none of the locations could be geocoded, keep the original row
|
146 |
+
if not location_rows_added:
|
147 |
+
expanded_rows.append(row.to_dict())
|
148 |
+
|
149 |
+
# Convert the list of dictionaries to a DataFrame
|
150 |
+
expanded_df = pd.DataFrame(expanded_rows)
|
151 |
|
152 |
# Create the map
|
153 |
+
m = folium.Map(
|
154 |
+
location=[20, 0],
|
155 |
+
zoom_start=2,
|
156 |
+
control_scale=True
|
157 |
+
)
|
158 |
|
159 |
+
folium.TileLayer(
|
160 |
+
tiles=MAP_TILES["GreenMap"]["url"],
|
161 |
+
attr=MAP_TILES["GreenMap"]["attr"],
|
162 |
+
name="GreenMap",
|
163 |
+
overlay=False,
|
164 |
+
control=False
|
165 |
+
).add_to(m)
|
166 |
|
167 |
+
Fullscreen().add_to(m)
|
168 |
+
MeasureControl(position='topright', primary_length_unit='kilometers').add_to(m)
|
169 |
|
170 |
+
# Add markers directly here
|
171 |
+
marker_cluster = MarkerCluster(name="Locations").add_to(m)
|
172 |
|
173 |
+
for idx, row in expanded_df.iterrows():
|
174 |
+
if 'latitude' in row and 'longitude' in row and not pd.isna(row['latitude']) and not pd.isna(row['longitude']):
|
175 |
+
location = row[places_column] if not pd.isna(row[places_column]) else "Unknown"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
|
177 |
+
additional_info = ""
|
178 |
+
for col in expanded_df.columns:
|
179 |
+
if col not in [places_column, 'latitude', 'longitude'] and not pd.isna(row[col]):
|
180 |
+
additional_info += f"<br><b>{col}:</b> {row[col]}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
|
182 |
popup_content = f"""
|
183 |
<div style="min-width: 200px; max-width: 300px">
|
|
|
189 |
"""
|
190 |
|
191 |
folium.Marker(
|
192 |
+
location=(row['latitude'], row['longitude']),
|
193 |
popup=folium.Popup(popup_content, max_width=300),
|
194 |
tooltip=location,
|
195 |
icon=folium.Icon(color="blue", icon="info-sign")
|
196 |
).add_to(marker_cluster)
|
197 |
+
|
198 |
+
if coords:
|
199 |
+
m.fit_bounds(coords)
|
200 |
+
|
201 |
+
custom_css = """
|
202 |
+
<style>
|
203 |
+
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap');
|
204 |
+
.leaflet-container {
|
205 |
+
font-family: 'Source Sans Pro', sans-serif;
|
206 |
+
}
|
207 |
+
.leaflet-popup-content {
|
208 |
+
font-family: 'Source Sans Pro', sans-serif;
|
209 |
+
}
|
210 |
+
.leaflet-popup-content h4 {
|
211 |
+
font-weight: 600;
|
212 |
+
margin-bottom: 8px;
|
213 |
+
}
|
214 |
+
</style>
|
215 |
+
"""
|
216 |
+
m.get_root().header.add_child(folium.Element(custom_css))
|
217 |
+
|
218 |
+
# Save the expanded DataFrame to Excel
|
219 |
+
with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp:
|
220 |
+
processed_path = tmp.name
|
221 |
+
expanded_df.to_excel(processed_path, index=False)
|
222 |
+
|
223 |
+
total_locations = df[places_column].count()
|
224 |
+
success_rate = (processed_count / total_locations * 100) if total_locations > 0 else 0
|
225 |
+
|
226 |
+
stats = f"Gefunden: {processed_count} von {total_locations} Orten ({success_rate:.1f}%)"
|
227 |
+
|
228 |
+
return m._repr_html_(), stats, processed_path
|
229 |
+
except Exception as e:
|
230 |
+
import traceback
|
231 |
+
trace = traceback.format_exc()
|
232 |
+
print(f"Error processing file: {e}\n{trace}")
|
233 |
+
return None, f"Fehler bei der Verarbeitung der Datei: {str(e)}", None
|
234 |
|
235 |
# Corrected model loading function based on official usage example
|
236 |
|