Tracy André commited on
Commit
bc49a9e
·
1 Parent(s): 0a62aa3
Files changed (2) hide show
  1. analyzer.py +81 -2
  2. interface.py +37 -4
analyzer.py CHANGED
@@ -391,6 +391,73 @@ class AgricultureAnalyzer:
391
 
392
  return parcels_info
393
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
  def filter_data_by_parcel(self, parcel_id):
395
  """Filtre les données par parcelle"""
396
  if self.df is None or parcel_id is None or parcel_id == "ALL":
@@ -421,6 +488,7 @@ class AgricultureAnalyzer:
421
  parcel_id_converted = parcel_id
422
 
423
  filtered_data = filtered_data[filtered_data['numparcell'] == parcel_id_converted]
 
424
  except (ValueError, TypeError):
425
  # En cas d'erreur de conversion, essayer tel quel
426
  filtered_data = filtered_data[filtered_data['numparcell'] == parcel_id]
@@ -433,10 +501,21 @@ class AgricultureAnalyzer:
433
  filtered_data = self.filter_data_by_year_and_parcel(year, parcel_id)
434
 
435
  if filtered_data is None or len(filtered_data) == 0:
 
 
 
 
436
  if parcel_id and parcel_id != "ALL":
437
- return None, f"❌ Aucune donnée pour l'année {year} et la parcelle {parcel_id}"
 
 
 
 
 
438
  else:
439
- return None, f"❌ Aucune donnée pour l'année {year}"
 
 
440
 
441
  # Sélectionner les colonnes les plus importantes pour l'affichage
442
  display_cols = []
 
391
 
392
  return parcels_info
393
 
394
+ def get_available_parcels_for_year(self, year):
395
+ """Retourne la liste des parcelles disponibles pour une année donnée"""
396
+ if self.df is None or len(self.df) == 0:
397
+ return [("Toutes les parcelles", "ALL")]
398
+
399
+ # Filtrer par année si spécifiée
400
+ if year is not None:
401
+ year_data = self.df[self.df['millesime'] == year]
402
+ else:
403
+ year_data = self.df
404
+
405
+ if len(year_data) == 0:
406
+ return [("Toutes les parcelles", "ALL")]
407
+
408
+ # Créer une liste avec numéro et nom de parcelle si disponible
409
+ parcels_info = []
410
+
411
+ if 'nomparc' in year_data.columns:
412
+ # Grouper par parcelle et prendre le premier nom (en cas de doublons)
413
+ parcels_data = year_data.groupby('numparcell')['nomparc'].first().reset_index()
414
+ for _, row in parcels_data.iterrows():
415
+ parcel_id = str(row['numparcell'])
416
+ parcel_name = str(row['nomparc']) if pd.notna(row['nomparc']) else ""
417
+ if parcel_name and parcel_name != "nan":
418
+ display_name = f"{parcel_id} - {parcel_name}"
419
+ else:
420
+ display_name = parcel_id
421
+ parcels_info.append((display_name, parcel_id))
422
+ else:
423
+ # Seulement les numéros de parcelles
424
+ unique_parcels = sorted(year_data['numparcell'].dropna().unique())
425
+ parcels_info = [(str(p), str(p)) for p in unique_parcels]
426
+
427
+ # Ajouter l'option "Toutes les parcelles" en premier
428
+ parcels_info.insert(0, ("Toutes les parcelles", "ALL"))
429
+
430
+ return parcels_info
431
+
432
+ def get_available_years_for_parcel(self, parcel_id):
433
+ """Retourne la liste des années disponibles pour une parcelle donnée"""
434
+ if self.df is None or len(self.df) == 0:
435
+ return ["Toutes les années"]
436
+
437
+ # Filtrer par parcelle si spécifiée
438
+ if parcel_id is not None and parcel_id != "ALL":
439
+ try:
440
+ # Convertir en entier si c'est une chaîne
441
+ if isinstance(parcel_id, str) and parcel_id.isdigit():
442
+ parcel_id_converted = int(parcel_id)
443
+ else:
444
+ parcel_id_converted = parcel_id
445
+
446
+ parcel_data = self.df[self.df['numparcell'] == parcel_id_converted]
447
+ except (ValueError, TypeError):
448
+ parcel_data = self.df[self.df['numparcell'] == parcel_id]
449
+ else:
450
+ parcel_data = self.df
451
+
452
+ if len(parcel_data) == 0:
453
+ return ["Toutes les années"]
454
+
455
+ # Récupérer les années disponibles et les trier
456
+ available_years = sorted(parcel_data['millesime'].dropna().unique())
457
+ year_choices = ["Toutes les années"] + [str(year) for year in available_years]
458
+
459
+ return year_choices
460
+
461
  def filter_data_by_parcel(self, parcel_id):
462
  """Filtre les données par parcelle"""
463
  if self.df is None or parcel_id is None or parcel_id == "ALL":
 
488
  parcel_id_converted = parcel_id
489
 
490
  filtered_data = filtered_data[filtered_data['numparcell'] == parcel_id_converted]
491
+
492
  except (ValueError, TypeError):
493
  # En cas d'erreur de conversion, essayer tel quel
494
  filtered_data = filtered_data[filtered_data['numparcell'] == parcel_id]
 
501
  filtered_data = self.filter_data_by_year_and_parcel(year, parcel_id)
502
 
503
  if filtered_data is None or len(filtered_data) == 0:
504
+ # Construire un message d'erreur informatif avec les données disponibles
505
+ available_years = sorted(self.df['millesime'].unique()) if self.df is not None else []
506
+ available_parcels = sorted(self.df['numparcell'].unique()) if self.df is not None else []
507
+
508
  if parcel_id and parcel_id != "ALL":
509
+ error_msg = f"❌ Aucune donnée pour l'année {year} et la parcelle {parcel_id}\n\n"
510
+ error_msg += f"📅 **Années disponibles**: {', '.join(map(str, available_years))}\n"
511
+ error_msg += f"🏠 **Parcelles disponibles**: {', '.join(map(str, available_parcels[:10]))}"
512
+ if len(available_parcels) > 10:
513
+ error_msg += f" (et {len(available_parcels)-10} autres...)"
514
+ return None, error_msg
515
  else:
516
+ error_msg = f"❌ Aucune donnée pour l'année {year}\n\n"
517
+ error_msg += f"📅 **Années disponibles**: {', '.join(map(str, available_years))}"
518
+ return None, error_msg
519
 
520
  # Sélectionner les colonnes les plus importantes pour l'affichage
521
  display_cols = []
interface.py CHANGED
@@ -253,7 +253,28 @@ class AgricultureInterface:
253
  wrap=True
254
  )
255
 
256
- # Fonction de mise à jour
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  def update_data_view(selected_year, selected_parcel):
258
  # Convertir les sélections
259
  year = None if selected_year == "Toutes les années" else int(selected_year)
@@ -261,8 +282,11 @@ class AgricultureInterface:
261
  # Convertir la sélection de parcelle
262
  parcel_id = None
263
  if selected_parcel != "Toutes les parcelles":
 
 
 
264
  # Récupérer l'ID de la parcelle depuis les données disponibles
265
- for choice in available_parcels:
266
  if choice[0] == selected_parcel:
267
  parcel_id = choice[1] if choice[1] != "ALL" else None
268
  break
@@ -279,8 +303,12 @@ class AgricultureInterface:
279
  data_table
280
  )
281
 
282
- # Connecter les événements
283
  year_selector.change(
 
 
 
 
284
  update_data_view,
285
  inputs=[year_selector, parcel_selector],
286
  outputs=[
@@ -292,6 +320,10 @@ class AgricultureInterface:
292
  )
293
 
294
  parcel_selector.change(
 
 
 
 
295
  update_data_view,
296
  inputs=[year_selector, parcel_selector],
297
  outputs=[
@@ -318,12 +350,13 @@ class AgricultureInterface:
318
 
319
  - **Sélection d'année** : Filtrez les données par millésime
320
  - **Sélection de parcelle** : Filtrez les données par parcelle spécifique
 
321
  - **Graphique des interventions** : Types d'interventions les plus fréquents
322
  - **Activité mensuelle** : Répartition des interventions par mois
323
  - **Tableau détaillé** : Données brutes avec colonnes importantes
324
 
325
  > 📝 **Note** : Le tableau est limité à 1000 lignes pour des raisons de performance
326
- > 🔄 **Astuce** : Combinez année et parcelle pour un filtrage précis
327
  """)
328
 
329
  def _safe_create_data_table(self, year, parcel_id=None):
 
253
  wrap=True
254
  )
255
 
256
+ # Fonction de mise à jour des parcelles disponibles selon l'année
257
+ def update_parcel_choices(selected_year):
258
+ year = None if selected_year == "Toutes les années" else int(selected_year)
259
+ parcels_for_year = self.analyzer.get_available_parcels_for_year(year)
260
+ parcel_choices = [choice[0] for choice in parcels_for_year]
261
+ return gr.Dropdown(choices=parcel_choices, value="Toutes les parcelles")
262
+
263
+ # Fonction de mise à jour des années disponibles selon la parcelle
264
+ def update_year_choices(selected_parcel):
265
+ # Convertir la sélection de parcelle en ID
266
+ parcel_id = None
267
+ if selected_parcel != "Toutes les parcelles":
268
+ current_parcels = self.analyzer.get_available_parcels()
269
+ for choice in current_parcels:
270
+ if choice[0] == selected_parcel:
271
+ parcel_id = choice[1] if choice[1] != "ALL" else None
272
+ break
273
+
274
+ years_for_parcel = self.analyzer.get_available_years_for_parcel(parcel_id)
275
+ return gr.Dropdown(choices=years_for_parcel, value="Toutes les années")
276
+
277
+ # Fonction de mise à jour des données
278
  def update_data_view(selected_year, selected_parcel):
279
  # Convertir les sélections
280
  year = None if selected_year == "Toutes les années" else int(selected_year)
 
282
  # Convertir la sélection de parcelle
283
  parcel_id = None
284
  if selected_parcel != "Toutes les parcelles":
285
+ # Récupérer les parcelles à jour pour éviter les problèmes de cache
286
+ current_parcels = self.analyzer.get_available_parcels()
287
+
288
  # Récupérer l'ID de la parcelle depuis les données disponibles
289
+ for choice in current_parcels:
290
  if choice[0] == selected_parcel:
291
  parcel_id = choice[1] if choice[1] != "ALL" else None
292
  break
 
303
  data_table
304
  )
305
 
306
+ # Connecter les événements pour les dropdowns dynamiques
307
  year_selector.change(
308
+ update_parcel_choices,
309
+ inputs=[year_selector],
310
+ outputs=[parcel_selector]
311
+ ).then(
312
  update_data_view,
313
  inputs=[year_selector, parcel_selector],
314
  outputs=[
 
320
  )
321
 
322
  parcel_selector.change(
323
+ update_year_choices,
324
+ inputs=[parcel_selector],
325
+ outputs=[year_selector]
326
+ ).then(
327
  update_data_view,
328
  inputs=[year_selector, parcel_selector],
329
  outputs=[
 
350
 
351
  - **Sélection d'année** : Filtrez les données par millésime
352
  - **Sélection de parcelle** : Filtrez les données par parcelle spécifique
353
+ - **Filtrage intelligent** : Les choix se mettent à jour automatiquement selon votre sélection
354
  - **Graphique des interventions** : Types d'interventions les plus fréquents
355
  - **Activité mensuelle** : Répartition des interventions par mois
356
  - **Tableau détaillé** : Données brutes avec colonnes importantes
357
 
358
  > 📝 **Note** : Le tableau est limité à 1000 lignes pour des raisons de performance
359
+ > 🔄 **Astuce** : Les listes se mettent à jour dynamiquement - sélectionnez une année pour voir ses parcelles !
360
  """)
361
 
362
  def _safe_create_data_table(self, year, parcel_id=None):