Tracy André commited on
Commit
ebeb919
·
1 Parent(s): 3f8bf56
Files changed (5) hide show
  1. .env.example +1 -0
  2. DEPLOY_HF.md +201 -0
  3. app.py +442 -0
  4. requirements.txt +10 -0
  5. sample_data.csv +22 -0
.env.example ADDED
@@ -0,0 +1 @@
 
 
1
+ HF_TOKEN=YOURTOKEN
DEPLOY_HF.md ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚀 Guide de Déploiement sur Hugging Face Spaces
2
+
3
+ ## 📋 Prérequis
4
+
5
+ 1. **Compte Hugging Face** : Créez un compte sur [huggingface.co](https://huggingface.co)
6
+ 2. **Token d'accès** : Générez un token sur [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
7
+ 3. **Dataset HackathonCRA/2024** : Assurez-vous d'avoir accès au dataset
8
+
9
+ ## 🔧 Étapes de Déploiement
10
+
11
+ ### 1. Créer un nouveau Space
12
+
13
+ 1. Allez sur [huggingface.co/new-space](https://huggingface.co/new-space)
14
+ 2. Remplissez les informations :
15
+ - **Space name** : `analyse-adventices-cra` (ou votre nom préféré)
16
+ - **License** : MIT
17
+ - **SDK** : Gradio
18
+ - **Hardware** : CPU basic (gratuit)
19
+
20
+ ### 2. Configurer les fichiers
21
+
22
+ Votre projet contient maintenant tous les fichiers nécessaires :
23
+
24
+ ```
25
+ 📁 Votre projet/
26
+ ├── 📄 app.py # Application Gradio modifiée pour HF
27
+ ├── 📄 requirements.txt # Dépendances avec datasets et huggingface_hub
28
+ ├── 📄 README.md # Métadonnées HF (déjà configuré)
29
+ ├── 📄 Dockerfile # Configuration Docker (optionnel)
30
+ └── 📄 sample_data.csv # Données de fallback
31
+ ```
32
+
33
+ ### 3. Uploader les fichiers
34
+
35
+ **Option A : Interface Web**
36
+ 1. Cliquez sur "Files and versions" dans votre Space
37
+ 2. Uploadez tous les fichiers un par un
38
+
39
+ **Option B : Git (Recommandé)**
40
+ ```bash
41
+ # Cloner votre space
42
+ git clone https://huggingface.co/spaces/VOTRE_USERNAME/VOTRE_SPACE_NAME
43
+
44
+ # Copier vos fichiers
45
+ cp app.py requirements.txt README.md sample_data.csv VOTRE_SPACE_NAME/
46
+
47
+ # Pousser les changements
48
+ cd VOTRE_SPACE_NAME
49
+ git add .
50
+ git commit -m "Ajout de l'application d'analyse des adventices"
51
+ git push
52
+ ```
53
+
54
+ ### 4. Configurer les variables d'environnement
55
+
56
+ 1. Dans votre Space, allez dans **Settings**
57
+ 2. Ajoutez la variable d'environnement :
58
+ - **Name** : `HF_TOKEN`
59
+ - **Value** : Votre token Hugging Face
60
+ - ✅ Cochez "Secret" pour la sécurité
61
+
62
+ ### 5. Vérifier le dataset
63
+
64
+ Assurez-vous que :
65
+ - Le dataset `HackathonCRA/2024` existe
66
+ - Vous avez les permissions pour y accéder
67
+ - Le token a les bonnes permissions
68
+
69
+ ## 🏗️ Structure du Code Modifié
70
+
71
+ ### Chargement des données
72
+ ```python
73
+ # Configuration HF intégrée
74
+ hf_token = os.environ.get("HF_TOKEN")
75
+ dataset_id = "HackathonCRA/2024"
76
+
77
+ # Méthode de fallback robuste
78
+ def load_data(self):
79
+ try:
80
+ # 1. Essayer depuis Hugging Face
81
+ dataset = load_dataset(dataset_id, use_auth_token=hf_token)
82
+ self.df = dataset['train'].to_pandas()
83
+ except:
84
+ # 2. Fallback vers fichiers locaux
85
+ # 3. Génération de données d'exemple si nécessaire
86
+ ```
87
+
88
+ ### Configuration Gradio
89
+ ```python
90
+ # Optimisé pour HF Spaces
91
+ demo.launch(
92
+ server_name="0.0.0.0",
93
+ server_port=7860,
94
+ share=False
95
+ )
96
+ ```
97
+
98
+ ## 🔍 Debugging
99
+
100
+ ### Problèmes courants
101
+
102
+ 1. **Dataset non trouvé**
103
+ - Vérifiez que `HackathonCRA/2024` existe
104
+ - Confirmez les permissions d'accès
105
+ - L'app utilisera des données d'exemple en fallback
106
+
107
+ 2. **Token invalide**
108
+ - Régénérez votre token HF
109
+ - Vérifiez qu'il est bien configuré comme secret
110
+
111
+ 3. **Erreurs de dépendances**
112
+ - Les dépendances sont dans `requirements.txt`
113
+ - HF Spaces installe automatiquement
114
+
115
+ ### Logs utiles
116
+ ```python
117
+ # Ces messages apparaîtront dans les logs HF
118
+ print(f"🤗 Tentative de chargement depuis Hugging Face: {dataset_id}")
119
+ print(f"✅ Données chargées depuis Hugging Face")
120
+ print(f"⚠️ Erreur lors du chargement depuis Hugging Face")
121
+ ```
122
+
123
+ ## 🎯 Fonctionnalités
124
+
125
+ Votre app fonctionnera avec :
126
+ - ✅ **Chargement automatique** depuis le dataset HF
127
+ - ✅ **Fallback robuste** vers données locales/exemple
128
+ - ✅ **Interface Gradio complète** avec tous les onglets
129
+ - ✅ **Visualisations interactives** Plotly
130
+ - ✅ **Analyse des risques** par parcelle
131
+ - ✅ **Recommandations** pour cultures sensibles
132
+
133
+ ## 🚀 Résultat Final
134
+
135
+ Une fois déployé, votre Space sera accessible à l'adresse :
136
+ `https://huggingface.co/spaces/VOTRE_USERNAME/VOTRE_SPACE_NAME`
137
+
138
+ L'application se lancera automatiquement et tentera de charger les données depuis `HackathonCRA/2024` !
139
+
140
+ ---
141
+
142
+ **Bon déploiement ! 🌾✨**
143
+
144
+ Voici comment lancer votre application en local pour tester avant le déploiement :
145
+
146
+ ## 🔧 Lancement en Local
147
+
148
+ ### 1. **Installation des dépendances**
149
+ ```bash
150
+ # Dans votre dossier de projet
151
+ cd /Users/tracyandre/code/hackathon/data
152
+
153
+ # Installer les dépendances
154
+ pip install -r requirements.txt
155
+ ```
156
+
157
+ ### 2. **Configuration des variables d'environnement (optionnel)**
158
+ ```bash
159
+ # Créer un fichier .env (optionnel, pour tester avec le vrai dataset HF)
160
+ echo "HF_TOKEN=votre_token_hugging_face" > .env
161
+
162
+ # Ou exporter directement dans le terminal
163
+ export HF_TOKEN=votre_token_hugging_face
164
+ ```
165
+
166
+ ### 3. **Lancer l'application**
167
+ ```bash
168
+ <code_block_to_apply_changes_from>
169
+ ```
170
+
171
+ ### 4. **Accéder à l'interface**
172
+ Ouvrez votre navigateur et allez à : **http://localhost:7860**
173
+
174
+ ## 🎯 Comportement en Local
175
+
176
+ Votre app va essayer de charger les données dans cet ordre :
177
+ 1. **Dataset HF** `HackathonCRA/2024` (si `HF_TOKEN` configuré)
178
+ 2. **Fichiers locaux** (sample_data.csv, etc.)
179
+ 3. **Données d'exemple** générées automatiquement
180
+
181
+ ## 🔍 Messages de Debug
182
+ Vous verrez dans la console :
183
+ ```
184
+ 🤗 Tentative de chargement depuis Hugging Face: HackathonCRA/2024
185
+ ✅ Données chargées depuis Hugging Face: HackathonCRA/2024
186
+ # OU
187
+ ⚠️ Erreur lors du chargement depuis Hugging Face: [erreur]
188
+ 🔄 Basculement vers les fichiers locaux...
189
+ ✅ Données chargées depuis: sample_data.csv
190
+ # OU
191
+ ⚠️ Aucun fichier de données trouvé, génération de données d'exemple
192
+ ```
193
+
194
+ ## 🚀 Test Rapide (sans token HF)
195
+ Si vous voulez juste tester l'interface rapidement :
196
+ ```bash
197
+ # L'app fonctionnera avec les données d'exemple générées
198
+ python app.py
199
+ ```
200
+
201
+ L'application sera accessible sur **http://localhost:7860** avec toutes les fonctionnalités ! 🌾✨
app.py ADDED
@@ -0,0 +1,442 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
3
+
4
+ import gradio as gr
5
+ import pandas as pd
6
+ import numpy as np
7
+ import matplotlib.pyplot as plt
8
+ import seaborn as sns
9
+ import plotly.express as px
10
+ import plotly.graph_objects as go
11
+ from plotly.subplots import make_subplots
12
+ import warnings
13
+ from datasets import load_dataset
14
+ warnings.filterwarnings('ignore')
15
+
16
+ # Configuration Hugging Face
17
+ hf_token = os.environ.get("HF_TOKEN")
18
+ dataset_id = "HackathonCRA/2024"
19
+
20
+ # Configuration des graphiques
21
+ plt.style.use('default')
22
+ sns.set_palette("husl")
23
+
24
+ class AgricultureAnalyzer:
25
+ def __init__(self):
26
+ self.df = None
27
+ self.risk_analysis = None
28
+
29
+ def load_data(self, file_path=None):
30
+ """Charge les données agricoles depuis Hugging Face ou fichiers locaux"""
31
+
32
+ # D'abord, essayer de charger depuis Hugging Face
33
+ try:
34
+ print(f"🤗 Tentative de chargement depuis Hugging Face: {dataset_id}")
35
+ dataset = load_dataset(dataset_id, use_auth_token=hf_token)
36
+
37
+ # Le dataset peut avoir plusieurs splits, essayer 'train' en premier
38
+ if 'train' in dataset:
39
+ # Convertir en DataFrame pandas
40
+ self.df = dataset['train'].to_pandas()
41
+ print(f"✅ Données chargées depuis Hugging Face: {dataset_id}")
42
+
43
+ # Si le dataset contient plusieurs fichiers CSV, prendre le premier qui contient les données d'intervention
44
+ if 'file' in self.df.columns:
45
+ # Filtrer pour ne garder que les fichiers d'intervention
46
+ intervention_files = self.df[self.df['file'].str.contains('Interventions', na=False)]
47
+ if not intervention_files.empty:
48
+ self.df = intervention_files
49
+
50
+ return self.analyze_data()
51
+ else:
52
+ # Si pas de split 'train', prendre le premier disponible
53
+ available_splits = list(dataset.keys())
54
+ if available_splits:
55
+ self.df = dataset[available_splits[0]].to_pandas()
56
+ print(f"✅ Données chargées depuis Hugging Face (split: {available_splits[0]})")
57
+ return self.analyze_data()
58
+
59
+ except Exception as e:
60
+ print(f"⚠️ Erreur lors du chargement depuis Hugging Face: {e}")
61
+ print("🔄 Basculement vers les fichiers locaux...")
62
+
63
+ # Si le chargement HF échoue, utiliser l'ancienne méthode
64
+ # Liste des chemins possibles pour les données
65
+ possible_paths = [
66
+ "data/Interventions-(sortie-excel)-Station_Expérimentale_de_Kerguéhennec-2025.csv",
67
+ "data/sample_data.csv",
68
+ "sample_data.csv"
69
+ ]
70
+
71
+ if file_path:
72
+ possible_paths.insert(0, file_path)
73
+
74
+ # Essayer de charger depuis les différents chemins
75
+ for path in possible_paths:
76
+ try:
77
+ self.df = pd.read_csv(path, skiprows=1)
78
+ print(f"✅ Données chargées depuis: {path}")
79
+ break
80
+ except FileNotFoundError:
81
+ continue
82
+ else:
83
+ # Si aucun fichier n'est trouvé, créer des données d'exemple
84
+ print("⚠️ Aucun fichier de données trouvé, génération de données d'exemple")
85
+ self.df = self.create_sample_data()
86
+
87
+ return self.analyze_data()
88
+
89
+ def create_sample_data(self):
90
+ """Crée des données d'exemple pour la démo"""
91
+ np.random.seed(42)
92
+ n_parcels = 45
93
+ n_interventions = 653
94
+
95
+ parcels = {
96
+ 'numparcell': np.random.randint(1, n_parcels+1, n_interventions),
97
+ 'nomparc': [f"Parcelle_{i}" for i in np.random.randint(1, n_parcels+1, n_interventions)],
98
+ 'surfparc': np.random.uniform(0.1, 7.0, n_interventions),
99
+ 'libelleusag': np.random.choice(['blé tendre hiver', 'maïs grain', 'colza hiver', 'haricot vert industrie',
100
+ 'CIPAN autre', 'orge hiver', 'soja', 'avoine printemps'], n_interventions),
101
+ 'familleprod': np.random.choice(['Herbicides', 'Fongicides', 'Insecticides', 'Fertilisants'],
102
+ n_interventions, p=[0.16, 0.25, 0.15, 0.44]),
103
+ 'produit': [f"Produit_{i}" for i in np.random.randint(1, 50, n_interventions)],
104
+ 'quantitetot': np.random.uniform(0.1, 25.0, n_interventions),
105
+ 'libevenem': ['Traitement et protection des cultures'] * n_interventions,
106
+ 'millesime': [2025] * n_interventions,
107
+ 'raisonsoci': ['Station Expérimentale de Kerguéhennec'] * n_interventions
108
+ }
109
+
110
+ return pd.DataFrame(parcels)
111
+
112
+ def analyze_data(self):
113
+ """Analyse des données et calcul des risques"""
114
+ if self.df is None:
115
+ return "Erreur: Aucune donnée chargée"
116
+
117
+ # Analyse générale
118
+ general_stats = {
119
+ 'total_parcelles': self.df['numparcell'].nunique(),
120
+ 'total_interventions': len(self.df),
121
+ 'surface_totale': self.df['surfparc'].sum(),
122
+ 'surface_moyenne': self.df['surfparc'].mean(),
123
+ 'periode': f"{self.df['millesime'].min()} - {self.df['millesime'].max()}"
124
+ }
125
+
126
+ # Analyse des herbicides
127
+ herbicides_df = self.df[self.df['familleprod'] == 'Herbicides'].copy()
128
+ herbicide_stats = {
129
+ 'nb_interventions_herbicides': len(herbicides_df),
130
+ 'pourcentage_herbicides': (len(herbicides_df) / len(self.df)) * 100,
131
+ 'parcelles_traitees': herbicides_df['numparcell'].nunique()
132
+ }
133
+
134
+ # Calcul de l'analyse des risques
135
+ self.calculate_risk_analysis()
136
+
137
+ return general_stats, herbicide_stats
138
+
139
+ def calculate_risk_analysis(self):
140
+ """Calcule l'analyse des risques par parcelle"""
141
+ # Groupement des données par parcelle
142
+ risk_analysis = self.df.groupby(['numparcell', 'nomparc', 'libelleusag', 'surfparc']).agg({
143
+ 'familleprod': lambda x: (x == 'Herbicides').sum(), # Nb traitements herbicides
144
+ 'libevenem': lambda x: len(x.unique()), # Diversité des événements
145
+ 'produit': lambda x: len(x.unique()), # Diversité des produits
146
+ 'quantitetot': 'sum' # Quantité totale
147
+ }).round(2)
148
+
149
+ # Quantités d'herbicides spécifiques
150
+ herbicide_quantities = self.df[self.df['familleprod'] == 'Herbicides'].groupby(
151
+ ['numparcell', 'nomparc', 'libelleusag', 'surfparc'])['quantitetot'].sum().fillna(0)
152
+
153
+ risk_analysis['Quantite_herbicides'] = herbicide_quantities.reindex(risk_analysis.index, fill_value=0)
154
+
155
+ risk_analysis.columns = ['Nb_herbicides', 'Diversite_evenements', 'Diversite_produits',
156
+ 'Quantite_totale', 'Quantite_herbicides']
157
+
158
+ # Calcul de l'IFT approximatif
159
+ risk_analysis['IFT_herbicide_approx'] = (risk_analysis['Quantite_herbicides'] /
160
+ risk_analysis.index.get_level_values('surfparc')).round(2)
161
+
162
+ # Classification du risque
163
+ def classify_risk(row):
164
+ ift = row['IFT_herbicide_approx']
165
+ nb_herb = row['Nb_herbicides']
166
+
167
+ if ift == 0 and nb_herb == 0:
168
+ return 'TRÈS FAIBLE'
169
+ elif ift < 1 and nb_herb <= 1:
170
+ return 'FAIBLE'
171
+ elif ift < 3 and nb_herb <= 3:
172
+ return 'MODÉRÉ'
173
+ elif ift < 5 and nb_herb <= 5:
174
+ return 'ÉLEVÉ'
175
+ else:
176
+ return 'TRÈS ÉLEVÉ'
177
+
178
+ risk_analysis['Risque_adventice'] = risk_analysis.apply(classify_risk, axis=1)
179
+
180
+ # Tri par risque
181
+ risk_order = ['TRÈS FAIBLE', 'FAIBLE', 'MODÉRÉ', 'ÉLEVÉ', 'TRÈS ÉLEVÉ']
182
+ risk_analysis['Risk_Score'] = risk_analysis['Risque_adventice'].map({r: i for i, r in enumerate(risk_order)})
183
+
184
+ self.risk_analysis = risk_analysis.sort_values(['Risk_Score', 'IFT_herbicide_approx'])
185
+
186
+ def get_summary_stats(self):
187
+ """Retourne les statistiques de résumé"""
188
+ if self.df is None:
189
+ return "Aucune donnée disponible"
190
+
191
+ stats_text = f"""
192
+ ## 📊 Statistiques Générales
193
+ - **Nombre total de parcelles**: {self.df['numparcell'].nunique()}
194
+ - **Nombre d'interventions**: {len(self.df):,}
195
+ - **Surface totale**: {self.df['surfparc'].sum():.2f} hectares
196
+ - **Surface moyenne par parcelle**: {self.df['surfparc'].mean():.2f} hectares
197
+ - **Période**: {self.df['millesime'].min()} - {self.df['millesime'].max()}
198
+
199
+ ## 🧪 Analyse Herbicides
200
+ """
201
+
202
+ herbicides_df = self.df[self.df['familleprod'] == 'Herbicides']
203
+ if len(herbicides_df) > 0:
204
+ stats_text += f"""
205
+ - **Interventions herbicides**: {len(herbicides_df)} ({(len(herbicides_df)/len(self.df)*100):.1f}%)
206
+ - **Parcelles traitées**: {herbicides_df['numparcell'].nunique()}
207
+ - **Produits herbicides différents**: {herbicides_df['produit'].nunique()}
208
+ """
209
+
210
+ if self.risk_analysis is not None:
211
+ risk_distribution = self.risk_analysis['Risque_adventice'].value_counts()
212
+ stats_text += f"""
213
+
214
+ ## 🎯 Répartition des Risques Adventices
215
+ """
216
+ for risk_level in ['TRÈS FAIBLE', 'FAIBLE', 'MODÉRÉ', 'ÉLEVÉ', 'TRÈS ÉLEVÉ']:
217
+ if risk_level in risk_distribution:
218
+ count = risk_distribution[risk_level]
219
+ pct = (count / len(self.risk_analysis)) * 100
220
+ stats_text += f"- **{risk_level}**: {count} parcelles ({pct:.1f}%)\n"
221
+
222
+ return stats_text
223
+
224
+ def get_low_risk_recommendations(self):
225
+ """Retourne les recommandations pour les parcelles à faible risque"""
226
+ if self.risk_analysis is None:
227
+ return "Analyse des risques non disponible"
228
+
229
+ low_risk = self.risk_analysis[
230
+ self.risk_analysis['Risque_adventice'].isin(['TRÈS FAIBLE', 'FAIBLE'])
231
+ ].head(10)
232
+
233
+ recommendations = "## 🌾 TOP 10 - Parcelles Recommandées pour Cultures Sensibles (Pois, Haricot)\n\n"
234
+
235
+ for idx, row in low_risk.iterrows():
236
+ parcelle, nom, culture, surface = idx
237
+ recommendations += f"""
238
+ **Parcelle {parcelle}** ({nom})
239
+ - Culture actuelle: {culture}
240
+ - Surface: {surface:.2f} ha
241
+ - Niveau de risque: {row['Risque_adventice']}
242
+ - IFT herbicide: {row['IFT_herbicide_approx']:.2f}
243
+ - Nombre d'herbicides: {row['Nb_herbicides']}
244
+
245
+ ---
246
+ """
247
+
248
+ return recommendations
249
+
250
+ def create_risk_visualization(self):
251
+ """Crée la visualisation des risques"""
252
+ if self.risk_analysis is None:
253
+ return None
254
+
255
+ risk_df = self.risk_analysis.reset_index()
256
+
257
+ fig = px.scatter(risk_df,
258
+ x='surfparc',
259
+ y='IFT_herbicide_approx',
260
+ color='Risque_adventice',
261
+ size='Nb_herbicides',
262
+ hover_data=['nomparc', 'libelleusag'],
263
+ color_discrete_map={
264
+ 'TRÈS FAIBLE': 'green',
265
+ 'FAIBLE': 'lightgreen',
266
+ 'MODÉRÉ': 'orange',
267
+ 'ÉLEVÉ': 'red',
268
+ 'TRÈS ÉLEVÉ': 'darkred'
269
+ },
270
+ title="🎯 Analyse du Risque Adventice par Parcelle",
271
+ labels={
272
+ 'surfparc': 'Surface de la parcelle (ha)',
273
+ 'IFT_herbicide_approx': 'IFT Herbicide (approximatif)',
274
+ 'Risque_adventice': 'Niveau de risque'
275
+ })
276
+
277
+ fig.update_layout(width=800, height=600, title_font_size=16)
278
+ return fig
279
+
280
+ def create_culture_analysis(self):
281
+ """Analyse par type de culture"""
282
+ if self.df is None:
283
+ return None
284
+
285
+ culture_counts = self.df['libelleusag'].value_counts()
286
+
287
+ fig = px.pie(values=culture_counts.values,
288
+ names=culture_counts.index,
289
+ title="🌱 Répartition des Cultures")
290
+
291
+ fig.update_layout(width=700, height=500)
292
+ return fig
293
+
294
+ def create_risk_distribution(self):
295
+ """Distribution des niveaux de risque"""
296
+ if self.risk_analysis is None:
297
+ return None
298
+
299
+ risk_counts = self.risk_analysis['Risque_adventice'].value_counts()
300
+
301
+ fig = px.bar(x=risk_counts.index,
302
+ y=risk_counts.values,
303
+ color=risk_counts.index,
304
+ color_discrete_map={
305
+ 'TRÈS FAIBLE': 'green',
306
+ 'FAIBLE': 'lightgreen',
307
+ 'MODÉRÉ': 'orange',
308
+ 'ÉLEVÉ': 'red',
309
+ 'TRÈS ÉLEVÉ': 'darkred'
310
+ },
311
+ title="📊 Distribution des Niveaux de Risque Adventice",
312
+ labels={'x': 'Niveau de risque', 'y': 'Nombre de parcelles'})
313
+
314
+ fig.update_layout(width=700, height=500, showlegend=False)
315
+ return fig
316
+
317
+ # Initialisation de l'analyseur
318
+ analyzer = AgricultureAnalyzer()
319
+ analyzer.load_data()
320
+
321
+ # Interface Gradio
322
+ def create_interface():
323
+ with gr.Blocks(title="🌾 Analyse Adventices Agricoles CRA", theme=gr.themes.Soft()) as demo:
324
+ gr.Markdown("""
325
+ # 🌾 Analyse des Adventices Agricoles - CRA Bretagne
326
+
327
+ **Objectif**: Anticiper et réduire la pression des adventices dans les parcelles agricoles bretonnes
328
+
329
+ Cette application analyse les données historiques pour identifier les parcelles les plus adaptées
330
+ à la culture de plantes sensibles comme le pois ou le haricot.
331
+ """)
332
+
333
+ with gr.Tabs():
334
+ with gr.TabItem("📊 Vue d'ensemble"):
335
+ gr.Markdown("## Statistiques générales des données agricoles")
336
+
337
+ stats_output = gr.Markdown(analyzer.get_summary_stats())
338
+
339
+ with gr.Row():
340
+ culture_plot = gr.Plot(analyzer.create_culture_analysis())
341
+ risk_dist_plot = gr.Plot(analyzer.create_risk_distribution())
342
+
343
+ with gr.TabItem("🎯 Analyse des Risques"):
344
+ gr.Markdown("## Cartographie des risques adventices par parcelle")
345
+
346
+ risk_plot = gr.Plot(analyzer.create_risk_visualization())
347
+
348
+ gr.Markdown("""
349
+ **Interprétation du graphique**:
350
+ - **Axe X**: Surface de la parcelle (hectares)
351
+ - **Axe Y**: IFT Herbicide approximatif
352
+ - **Couleur**: Niveau de risque adventice
353
+ - **Taille**: Nombre d'herbicides utilisés
354
+
355
+ Les parcelles vertes (risque faible) sont idéales pour les cultures sensibles.
356
+ """)
357
+
358
+ with gr.TabItem("🌾 Recommandations"):
359
+ gr.Markdown(analyzer.get_low_risk_recommendations())
360
+
361
+ gr.Markdown("""
362
+ ## 💡 Conseils pour la gestion des adventices
363
+
364
+ ### Parcelles à Très Faible Risque (Vertes)
365
+ - ✅ **Idéales pour pois et haricot**
366
+ - ✅ Historique d'usage herbicide minimal
367
+ - ✅ Pression adventice faible attendue
368
+
369
+ ### Parcelles à Faible Risque (Vert clair)
370
+ - ⚠️ Surveillance légère recommandée
371
+ - ✅ Conviennent aux cultures sensibles avec précautions
372
+
373
+ ### Parcelles à Risque Modéré/Élevé (Orange/Rouge)
374
+ - ❌ Éviter pour cultures sensibles
375
+ - 🔍 Rotation nécessaire avant implantation
376
+ - 📈 Surveillance renforcée des adventices
377
+
378
+ ### Stratégies alternatives
379
+ - **Rotation longue**: 3-4 ans avant cultures sensibles
380
+ - **Cultures intermédiaires**: CIPAN pour réduire la pression
381
+ - **Techniques mécaniques**: Hersage, binage
382
+ - **Biostimulants**: Renforcement naturel des cultures
383
+ """)
384
+
385
+ with gr.TabItem("ℹ️ À propos"):
386
+ gr.Markdown("""
387
+ ## 🎯 Méthodologie
388
+
389
+ Cette analyse se base sur :
390
+
391
+ ### Calcul de l'IFT (Indice de Fréquence de Traitement)
392
+ - **IFT ≈ Quantité appliquée / Surface de parcelle**
393
+ - Indicateur de l'intensité des traitements herbicides
394
+
395
+ ### Classification des risques
396
+ - **TRÈS FAIBLE**: IFT = 0, aucun herbicide
397
+ - **FAIBLE**: IFT < 1, usage minimal
398
+ - **MODÉRÉ**: IFT < 3, usage modéré
399
+ - **ÉLEVÉ**: IFT < 5, usage important
400
+ - **TRÈS ÉLEVÉ**: IFT ≥ 5, usage intensif
401
+
402
+ ### Données analysées
403
+ - **Source**: Station Expérimentale de Kerguéhennec
404
+ - **Période**: Campagne 2025
405
+ - **Variables**: Interventions, produits, quantités, surfaces
406
+
407
+ ---
408
+
409
+ **Développé pour le Hackathon CRA Bretagne** 🏆
410
+
411
+ *Application d'aide à la décision pour une agriculture durable*
412
+ """)
413
+
414
+ # Bouton de rafraîchissement
415
+ refresh_btn = gr.Button("🔄 Actualiser les données", variant="secondary")
416
+
417
+ def refresh_data():
418
+ analyzer.load_data()
419
+ return (
420
+ analyzer.get_summary_stats(),
421
+ analyzer.create_culture_analysis(),
422
+ analyzer.create_risk_distribution(),
423
+ analyzer.create_risk_visualization(),
424
+ analyzer.get_low_risk_recommendations()
425
+ )
426
+
427
+ refresh_btn.click(
428
+ refresh_data,
429
+ outputs=[stats_output, culture_plot, risk_dist_plot, risk_plot]
430
+ )
431
+
432
+ return demo
433
+
434
+ # Lancement de l'application
435
+ if __name__ == "__main__":
436
+ demo = create_interface()
437
+ # Configuration pour Hugging Face Spaces
438
+ demo.launch(
439
+ server_name="0.0.0.0",
440
+ server_port=7860,
441
+ share=False # Pas besoin de share sur HF Spaces
442
+ )
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio==4.31.0
2
+ pandas>=2.0.0
3
+ numpy>=1.21.0,<3.0.0
4
+ matplotlib>=3.5.0
5
+ seaborn>=0.11.0
6
+ plotly>=5.0.0
7
+ scipy>=1.7.0
8
+ scikit-learn>=1.0.0
9
+ datasets>=2.0.0
10
+ huggingface_hub>=0.16.0
sample_data.csv ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Station Expérimentale de Kerguéhennec - Données d'intervention 2025
2
+ millesime,raisonsoci,siret,pacage,refca,numilot,numparcell,nomparc,surfparc,rang,estpac,libelleusag,datedebut,datefin,libperiode,libregroupe,libevenem,dureeeffect,familleprod,produit,quantitetot,unite,neffqte,peffqte,kqte,teneurn,teneurp,teneurk,keq,volumebo,codeamm,codegnis,materiel,mainoeuvre
3
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,1102,Bourg bas,6.73,1,True,blé tendre hiver,15/03/25,15/03/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,LUMEO,0.20,L,,,,,,,,,,,Pulvérisateur,2.5
4
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,1301,Bois Guillemin,5.97,1,True,blé tendre hiver,20/03/25,20/03/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,PEAK,0.01,L,,,,,,,,,,,Pulvérisateur,2.0
5
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,1101,Bourg Haut,5.55,1,True,maïs grain,25/04/25,25/04/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,GLISTER ULTRA 360,3.50,L,,,,,,,,,,,Pulvérisateur,3.0
6
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,1001,Carancier Ht,5.46,1,True,colza hiver,10/04/25,10/04/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,BISCOTO,1.20,L,,,,,,,,,,,Pulvérisateur,2.5
7
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,48,Etang Bois,3.36,1,True,haricot vert industrie,05/05/25,05/05/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,ISARD,2.40,L,,,,,,,,,,,Pulvérisateur,4.0
8
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,44,La Défriche,3.25,1,True,CIPAN autre,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
9
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,2,Kersuzan Bas,3.05,1,True,CIPAN autre,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
10
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,81,Charbonnerie Entrée,3.01,1,True,CIPAN autre,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
11
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,11,Cléhury,2.97,1,True,orge hiver,12/04/25,12/04/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,FREEWAY 480,0.80,L,,,,,,,,,,,Pulvérisateur,2.0
12
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,5,Etang Moulin,2.85,1,True,CIPAN autre,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
13
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,50,Lann Chebot Le Roch,2.20,1,True,blé tendre hiver,18/03/25,18/03/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,NISSHIN PREMIUM 6 OD,1.50,L,,,,,,,,,,,Pulvérisateur,3.5
14
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,16,Champ ferme W du sol parking,1.95,1,True,maïs grain,28/04/25,28/04/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,ALABAMA,1.20,L,,,,,,,,,,,Pulvérisateur,2.5
15
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,39,Champ ferme transfert,1.85,1,True,blé tendre hiver,22/03/25,22/03/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,CENT-7,0.15,L,,,,,,,,,,,Pulvérisateur,2.0
16
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,1201,Champ Robert,1.75,1,True,blé tendre hiver,25/03/25,25/03/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,CORUM,0.95,L,,,,,,,,,,,Pulvérisateur,2.5
17
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,38,Champ ferme W du sol,1.65,1,True,colza hiver,15/04/25,15/04/25,,Herbicides,Traitement et protection des cultures,1,Herbicides,LUMEO,0.18,L,,,,,,,,,,,Pulvérisateur,2.0
18
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,14,Grand-Champ 1 essai soja 25,0.53,1,True,soja,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
19
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,10,Penderff 7 analytique,1.56,1,True,avoine printemps,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
20
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,33,Penderff Luzerne,2.10,1,True,luzerne,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
21
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,4,Penderff 1,0.37,1,True,feverole printemps,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0
22
+ 2025,Station Expérimentale de Kerguéhennec,12345678901234,1001,CA001,1,6,Lann Chebot chemin,0.11,1,True,CIPAN autre,,,,,Traitement et protection des cultures,0,,,0.00,L,,,,,,,,,,,Pulvérisateur,0.0