Tracy André commited on
Commit
8b09855
·
1 Parent(s): 1cbf4ed
Files changed (6) hide show
  1. debug_parcelles.py +38 -0
  2. mcp_server.py +96 -25
  3. quick_test.py +29 -0
  4. requirements.txt +1 -2
  5. test_analysis.py +109 -0
  6. test_gradio.py +45 -0
debug_parcelles.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Debug des noms de parcelles
3
+ """
4
+
5
+ from data_loader import AgriculturalDataLoader
6
+
7
+ def debug_plot_names():
8
+ loader = AgriculturalDataLoader()
9
+ df = loader.load_all_files()
10
+
11
+ print("🔍 Analyse des noms de parcelles...")
12
+
13
+ # Toutes les parcelles uniques
14
+ all_plots = df['plot_name'].unique()
15
+ print(f"Nombre total de parcelles: {len(all_plots)}")
16
+
17
+ # Chercher des variations de "Champ ferme Bas"
18
+ champ_ferme_variants = [p for p in all_plots if 'champ' in p.lower() and 'ferme' in p.lower()]
19
+ print(f"\nVariantes de 'Champ ferme':")
20
+ for variant in sorted(champ_ferme_variants):
21
+ count = len(df[df['plot_name'] == variant])
22
+ print(f" '{variant}': {count} interventions")
23
+
24
+ # Parcelles les plus fréquentes
25
+ plot_counts = df['plot_name'].value_counts().head(10)
26
+ print(f"\nTop 10 des parcelles par nombre d'interventions:")
27
+ for plot, count in plot_counts.items():
28
+ print(f" '{plot}': {count} interventions")
29
+
30
+ # Vérifier les herbicides par parcelle
31
+ herbicide_df = df[df['is_herbicide'] == True]
32
+ herbicide_plots = herbicide_df['plot_name'].value_counts().head(10)
33
+ print(f"\nTop 10 des parcelles avec herbicides:")
34
+ for plot, count in herbicide_plots.items():
35
+ print(f" '{plot}': {count} applications herbicides")
36
+
37
+ if __name__ == "__main__":
38
+ debug_plot_names()
mcp_server.py CHANGED
@@ -92,44 +92,93 @@ analyzer = WeedPressureAnalyzer()
92
  def analyze_herbicide_trends(years_range, plot_filter):
93
  """Analyze herbicide usage trends over time."""
94
  try:
95
- if len(years_range) == 2:
 
96
  years = list(range(int(years_range[0]), int(years_range[1]) + 1))
 
 
97
  else:
98
- years = [int(y) for y in years_range]
 
 
99
 
100
  ift_data = analyzer.calculate_herbicide_ift(years=years)
101
 
102
  if len(ift_data) == 0:
103
- return None, "Aucune donnée d'herbicides trouvée."
104
 
105
- if plot_filter != "Toutes":
 
106
  ift_data = ift_data[ift_data['plot_name'] == plot_filter]
107
 
 
 
 
 
108
  fig = px.line(ift_data,
109
  x='year',
110
  y='ift_herbicide',
111
  color='plot_name',
112
- title=f'Évolution de l\'IFT Herbicides',
113
- labels={'ift_herbicide': 'IFT Herbicides', 'year': 'Année'})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  summary = f"""
116
- 📊 **Analyse de l'IFT Herbicides**
117
 
118
- **Statistiques:**
119
- - IFT moyen: {ift_data['ift_herbicide'].mean():.2f}
120
- - IFT maximum: {ift_data['ift_herbicide'].max():.2f}
121
- - Nombre de parcelles: {ift_data['plot_name'].nunique()}
 
 
 
 
 
 
 
 
 
 
122
 
123
  **Interprétation:**
124
- - IFT < 1.0: Pression faible ✅
125
- - IFT 1.0-2.0: Pression modérée ⚠️
126
- - IFT > 2.0: Pression élevée ❌
127
  """
128
 
129
  return fig, summary
130
 
131
  except Exception as e:
132
- return None, f"Erreur: {str(e)}"
 
 
 
133
 
134
  def predict_future_weed_pressure():
135
  """Predict weed pressure for the next 3 years."""
@@ -236,10 +285,12 @@ def generate_technical_alternatives(herbicide_family):
236
  def get_available_plots():
237
  """Get available plots."""
238
  try:
239
- plots = analyzer.data_loader.get_plots_available()
 
240
  return ["Toutes"] + plots
241
- except:
242
- return ["Toutes"]
 
243
 
244
  # Create Gradio Interface
245
  def create_mcp_interface():
@@ -252,17 +303,37 @@ def create_mcp_interface():
252
 
253
  with gr.Tabs():
254
  with gr.Tab("📈 Analyse Tendances"):
255
- with gr.Row():
256
- years_slider = gr.Slider(2014, 2024, value=[2020, 2024], step=1, label="Période")
257
- plot_dropdown = gr.Dropdown(choices=get_available_plots(), value="Toutes", label="Parcelle")
258
 
259
- analyze_btn = gr.Button("🔍 Analyser", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
 
261
  with gr.Row():
262
- trends_plot = gr.Plot()
263
- trends_summary = gr.Markdown()
 
 
264
 
265
- analyze_btn.click(analyze_herbicide_trends, [years_slider, plot_dropdown], [trends_plot, trends_summary])
 
 
 
 
266
 
267
  with gr.Tab("🔮 Prédictions"):
268
  predict_btn = gr.Button("🎯 Prédire 2025-2027", variant="primary")
 
92
  def analyze_herbicide_trends(years_range, plot_filter):
93
  """Analyze herbicide usage trends over time."""
94
  try:
95
+ # Gestion du slider Gradio qui peut retourner différents formats
96
+ if isinstance(years_range, list) and len(years_range) == 2:
97
  years = list(range(int(years_range[0]), int(years_range[1]) + 1))
98
+ elif isinstance(years_range, (int, float)):
99
+ years = [int(years_range)]
100
  else:
101
+ years = list(range(2014, 2025)) # Par défaut
102
+
103
+ # Debug line removed for production
104
 
105
  ift_data = analyzer.calculate_herbicide_ift(years=years)
106
 
107
  if len(ift_data) == 0:
108
+ return None, "Aucune donnée d'herbicides trouvée pour la période sélectionnée."
109
 
110
+ # Filtrage par parcelle si nécessaire
111
+ if plot_filter and plot_filter != "Toutes":
112
  ift_data = ift_data[ift_data['plot_name'] == plot_filter]
113
 
114
+ if len(ift_data) == 0:
115
+ return None, f"Aucune donnée trouvée pour la parcelle '{plot_filter}' sur la période {years[0]}-{years[-1]}."
116
+
117
+ # Création du graphique
118
  fig = px.line(ift_data,
119
  x='year',
120
  y='ift_herbicide',
121
  color='plot_name',
122
+ title=f'Évolution de l\'IFT Herbicides ({years[0]}-{years[-1]})',
123
+ labels={'ift_herbicide': 'IFT Herbicides', 'year': 'Année'},
124
+ markers=True)
125
+
126
+ fig.update_layout(
127
+ height=500,
128
+ xaxis_title="Année",
129
+ yaxis_title="IFT Herbicides",
130
+ legend_title="Parcelle"
131
+ )
132
+
133
+ # Ajout d'une ligne de référence IFT = 2.0
134
+ fig.add_hline(y=2.0, line_dash="dash", line_color="red",
135
+ annotation_text="Seuil IFT élevé (2.0)", annotation_position="top right")
136
+ fig.add_hline(y=1.0, line_dash="dash", line_color="orange",
137
+ annotation_text="Seuil IFT modéré (1.0)", annotation_position="bottom right")
138
+
139
+ # Calcul des statistiques
140
+ ift_mean = ift_data['ift_herbicide'].mean()
141
+ ift_max = ift_data['ift_herbicide'].max()
142
+ ift_min = ift_data['ift_herbicide'].min()
143
+ n_plots = ift_data['plot_name'].nunique()
144
+ n_records = len(ift_data)
145
+
146
+ # Classification des niveaux de risque
147
+ low_risk = len(ift_data[ift_data['ift_herbicide'] < 1.0])
148
+ moderate_risk = len(ift_data[(ift_data['ift_herbicide'] >= 1.0) & (ift_data['ift_herbicide'] < 2.0)])
149
+ high_risk = len(ift_data[ift_data['ift_herbicide'] >= 2.0])
150
 
151
  summary = f"""
152
+ 📊 **Analyse de l'IFT Herbicides ({years[0]}-{years[-1]})**
153
 
154
+ **Période analysée:** {years[0]} à {years[-1]}
155
+ **Parcelle(s):** {plot_filter if plot_filter != "Toutes" else "Toutes les parcelles"}
156
+
157
+ **Statistiques globales:**
158
+ - IFT moyen: {ift_mean:.2f}
159
+ - IFT minimum: {ift_min:.2f}
160
+ - IFT maximum: {ift_max:.2f}
161
+ - Nombre de parcelles: {n_plots}
162
+ - Nombre d'observations: {n_records}
163
+
164
+ **Répartition des niveaux de pression:**
165
+ - 🟢 Faible (IFT < 1.0): {low_risk} observations ({low_risk/n_records*100:.1f}%)
166
+ - 🟡 Modérée (1.0 ≤ IFT < 2.0): {moderate_risk} observations ({moderate_risk/n_records*100:.1f}%)
167
+ - 🔴 Élevée (IFT ≥ 2.0): {high_risk} observations ({high_risk/n_records*100:.1f}%)
168
 
169
  **Interprétation:**
170
+ - IFT < 1.0: Pression adventices faible ✅
171
+ - 1.0 ≤ IFT < 2.0: Pression adventices modérée ⚠️
172
+ - IFT 2.0: Pression adventices élevée ❌
173
  """
174
 
175
  return fig, summary
176
 
177
  except Exception as e:
178
+ import traceback
179
+ error_msg = f"Erreur dans l'analyse: {str(e)}\n{traceback.format_exc()}"
180
+ print(error_msg)
181
+ return None, error_msg
182
 
183
  def predict_future_weed_pressure():
184
  """Predict weed pressure for the next 3 years."""
 
285
  def get_available_plots():
286
  """Get available plots."""
287
  try:
288
+ df = analyzer.load_data()
289
+ plots = sorted(df['plot_name'].dropna().unique().tolist())
290
  return ["Toutes"] + plots
291
+ except Exception as e:
292
+ print(f"Erreur lors du chargement des parcelles: {e}")
293
+ return ["Toutes", "Champ ferme Bas", "Etang Milieu", "Lann Chebot"]
294
 
295
  # Create Gradio Interface
296
  def create_mcp_interface():
 
303
 
304
  with gr.Tabs():
305
  with gr.Tab("📈 Analyse Tendances"):
306
+ gr.Markdown("### Analyser l'évolution de l'IFT herbicides par parcelle et période")
 
 
307
 
308
+ with gr.Row():
309
+ with gr.Column():
310
+ years_slider = gr.Slider(
311
+ minimum=2014,
312
+ maximum=2025,
313
+ value=[2020, 2025],
314
+ step=1,
315
+ label="Période d'analyse",
316
+ info="Sélectionnez la plage d'années à analyser"
317
+ )
318
+ plot_dropdown = gr.Dropdown(
319
+ choices=get_available_plots(),
320
+ value="Toutes",
321
+ label="Filtrer par parcelle",
322
+ info="Choisissez une parcelle spécifique ou toutes"
323
+ )
324
+ analyze_btn = gr.Button("🔍 Analyser les Tendances", variant="primary", size="lg")
325
 
326
  with gr.Row():
327
+ with gr.Column(scale=2):
328
+ trends_plot = gr.Plot(label="Graphique d'évolution")
329
+ with gr.Column(scale=1):
330
+ trends_summary = gr.Markdown(label="Résumé statistique")
331
 
332
+ analyze_btn.click(
333
+ analyze_herbicide_trends,
334
+ inputs=[years_slider, plot_dropdown],
335
+ outputs=[trends_plot, trends_summary]
336
+ )
337
 
338
  with gr.Tab("🔮 Prédictions"):
339
  predict_btn = gr.Button("🎯 Prédire 2025-2027", variant="primary")
quick_test.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test rapide de l'interface complète
3
+ """
4
+
5
+ import gradio as gr
6
+ from mcp_server import create_mcp_interface
7
+
8
+ if __name__ == "__main__":
9
+ print("🚀 Test de l'interface Gradio complète...")
10
+
11
+ try:
12
+ demo = create_mcp_interface()
13
+ print("✅ Interface créée avec succès")
14
+
15
+ # Test de lancement (sans vraiment lancer)
16
+ print("✅ Interface prête pour le déploiement")
17
+
18
+ # Test d'une fonction
19
+ from mcp_server import analyze_herbicide_trends
20
+ fig, summary = analyze_herbicide_trends([2022, 2024], "Toutes")
21
+ if fig is not None:
22
+ print("✅ Fonction d'analyse fonctionnelle")
23
+ else:
24
+ print("❌ Problème avec l'analyse")
25
+
26
+ except Exception as e:
27
+ print(f"❌ Erreur: {e}")
28
+ import traceback
29
+ traceback.print_exc()
requirements.txt CHANGED
@@ -1,5 +1,4 @@
1
- gradio>=4.44.0
2
- pandas>=2.0.0
3
  numpy>=1.24.0
4
  plotly>=5.0.0
5
  datasets>=2.14.0
 
1
+ gradio[mcp]>=5.46.0pandas>=2.0.0
 
2
  numpy>=1.24.0
3
  plotly>=5.0.0
4
  datasets>=2.14.0
test_analysis.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Script de test pour diagnostiquer les problèmes d'analyse des tendances
3
+ """
4
+
5
+ import pandas as pd
6
+ import numpy as np
7
+ from data_loader import AgriculturalDataLoader
8
+
9
+ def test_data_loading():
10
+ """Test du chargement des données"""
11
+ print("🔍 Test du chargement des données...")
12
+
13
+ try:
14
+ loader = AgriculturalDataLoader()
15
+ df = loader.load_all_files()
16
+
17
+ print(f"✅ Données chargées: {len(df)} lignes")
18
+ print(f"📋 Colonnes disponibles: {list(df.columns)}")
19
+ print(f"📊 Types de données:")
20
+ print(df.dtypes)
21
+
22
+ return df
23
+ except Exception as e:
24
+ print(f"❌ Erreur lors du chargement: {e}")
25
+ return None
26
+
27
+ def test_herbicide_analysis(df):
28
+ """Test de l'analyse des herbicides"""
29
+ print("\n🧪 Test de l'analyse des herbicides...")
30
+
31
+ if df is None:
32
+ return
33
+
34
+ # Vérifier les colonnes nécessaires
35
+ required_cols = ['is_herbicide', 'plot_name', 'year', 'crop_type', 'produit', 'plot_surface']
36
+ missing_cols = [col for col in required_cols if col not in df.columns]
37
+
38
+ if missing_cols:
39
+ print(f"❌ Colonnes manquantes: {missing_cols}")
40
+ return
41
+
42
+ # Filtrer les herbicides
43
+ herbicide_df = df[df['is_herbicide'] == True].copy()
44
+ print(f"📊 Nombre d'applications herbicides: {len(herbicide_df)}")
45
+
46
+ if len(herbicide_df) == 0:
47
+ print("❌ Aucune donnée d'herbicides trouvée")
48
+ print("🔍 Vérification des valeurs 'is_herbicide':")
49
+ print(df['is_herbicide'].value_counts())
50
+
51
+ print("🔍 Vérification des familles de produits:")
52
+ if 'familleprod' in df.columns:
53
+ print(df['familleprod'].value_counts())
54
+
55
+ return
56
+
57
+ print(f"✅ Données herbicides trouvées: {len(herbicide_df)} applications")
58
+
59
+ # Test du calcul IFT
60
+ print("\n📈 Test du calcul IFT...")
61
+
62
+ try:
63
+ ift_summary = herbicide_df.groupby(['plot_name', 'year', 'crop_type']).agg({
64
+ 'produit': 'count',
65
+ 'plot_surface': 'first',
66
+ 'quantitetot': 'sum'
67
+ }).reset_index()
68
+
69
+ ift_summary['ift_herbicide'] = ift_summary['produit'] / ift_summary['plot_surface']
70
+
71
+ print(f"✅ IFT calculé pour {len(ift_summary)} combinaisons parcelle/année/culture")
72
+ print(f"📊 IFT moyen: {ift_summary['ift_herbicide'].mean():.2f}")
73
+ print(f"📊 IFT max: {ift_summary['ift_herbicide'].max():.2f}")
74
+
75
+ print("\n📋 Échantillon des données IFT:")
76
+ print(ift_summary.head())
77
+
78
+ return ift_summary
79
+
80
+ except Exception as e:
81
+ print(f"❌ Erreur dans le calcul IFT: {e}")
82
+ return None
83
+
84
+ def test_years_and_plots(df):
85
+ """Test des années et parcelles disponibles"""
86
+ print("\n📅 Test des années et parcelles...")
87
+
88
+ if df is None:
89
+ return
90
+
91
+ years = sorted(df['year'].dropna().unique())
92
+ plots = sorted(df['plot_name'].dropna().unique())
93
+
94
+ print(f"📅 Années disponibles: {years}")
95
+ print(f"🏞️ Parcelles disponibles: {plots}")
96
+
97
+ # Test par année
98
+ print("\n📊 Données par année:")
99
+ year_counts = df.groupby('year').size()
100
+ print(year_counts)
101
+
102
+ if __name__ == "__main__":
103
+ print("🚜 Test de l'analyse des tendances herbicides\n")
104
+
105
+ df = test_data_loading()
106
+ test_herbicide_analysis(df)
107
+ test_years_and_plots(df)
108
+
109
+ print("\n✅ Tests terminés")
test_gradio.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Script de test pour l'interface Gradio
3
+ """
4
+
5
+ from mcp_server import analyze_herbicide_trends, get_available_plots
6
+
7
+ def test_function_calls():
8
+ """Test des fonctions individuelles"""
9
+ print("🧪 Test des fonctions...")
10
+
11
+ # Test get_available_plots
12
+ print("\n📋 Test get_available_plots():")
13
+ plots = get_available_plots()
14
+ print(f"Parcelles disponibles: {len(plots)} - {plots[:5]}...")
15
+
16
+ # Test analyze_herbicide_trends avec différents paramètres
17
+ print("\n📈 Test analyze_herbicide_trends():")
18
+
19
+ # Test 1: Période normale
20
+ print("Test 1: Période 2020-2024, toutes parcelles")
21
+ fig, summary = analyze_herbicide_trends([2020, 2024], "Toutes")
22
+ if fig is not None:
23
+ print("✅ Graphique généré avec succès")
24
+ print("📊 Résumé:", summary[:200] + "...")
25
+ else:
26
+ print("❌ Erreur:", summary)
27
+
28
+ # Test 2: Parcelle spécifique
29
+ print("\nTest 2: Période 2020-2024, parcelle spécifique")
30
+ fig, summary = analyze_herbicide_trends([2020, 2024], "Champ ferme W du sol")
31
+ if fig is not None:
32
+ print("✅ Graphique généré avec succès")
33
+ else:
34
+ print("❌ Erreur:", summary)
35
+
36
+ # Test 3: Format année simple
37
+ print("\nTest 3: Année simple")
38
+ fig, summary = analyze_herbicide_trends(2023, "Toutes")
39
+ if fig is not None:
40
+ print("✅ Graphique généré avec succès")
41
+ else:
42
+ print("❌ Erreur:", summary)
43
+
44
+ if __name__ == "__main__":
45
+ test_function_calls()