Background réaliste CsI(Tl) + hybridation mesuré/synthétique + dashboard continuum

- Remplace le continuum exponentiel par un modèle réaliste CsI(Tl) dans
  l'entraînement (bosse asymétrique ~110 keV + queue Compton)
- Ajoute l'injection de background mesuré (70% mesuré / 30% synthétique)
  via --measured_background et MEASURED_BACKGROUND_PATH
- Ajoute l'endpoint /api/background/continuum et le toggle "Continuum CsI"
  sur le dashboard background
- Exclut le canal 1023 (overflow bin) de l'affichage web (NUM_CHANNELS=1023)
- Corrige le lissage Gaussien du background (normalisation locale aux bords)
- Met à jour README.md, CLAUDE.md, TUTORIEL.md, TOTO.md, vega_ml/README.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-05-19 18:14:00 +02:00
parent 1e0c1a5ea5
commit 75d271c696
17 changed files with 917 additions and 224 deletions

View File

@ -80,29 +80,40 @@ Les spectres synthetiques simulent des acquisitions de 12 a 24 heures (43200-864
- **Pics photoelectriques** : Gaussiennes dont la largeur (FWHM) depend de l'energie. Pour le CsI(Tl) du Radiacode 103, FWHM = 8.4% a 662 keV, avec la relation FWHM(E) = FWHM_662 * sqrt(E/662).
- **Continuum Compton** : Distribution de Klein-Nishina simplifiee sous chaque pic, simulant la diffusion des photons gamma.
- **Bruit Poissonnien** : Chaque canal est echantillonne depuis une loi Poisson(lambda), ce qui reproduit exactement les fluctuations statistiques reelles.
- **Background environnemental** : Continuum exponentiel + pics de K-40 (1460 keV), Pb-214 (295, 352 keV), Bi-214 (609, 1120, 1764 keV), Ac-228 (911 keV), Pb-212 (239 keV), Tl-208 (583, 2614 keV), avec des activites aleatoires realistes.
- **Background environnemental** : Continuum CsI(Tl) realiste (bosse asymetrique a ~110 keV + queue Compton exponentielle) + pics de K-40 (1460 keV), Pb-214 (295, 352 keV), Bi-214 (609, 1120, 1764 keV), Ac-228 (911 keV), Pb-212 (239 keV), Tl-208 (583, 2614 keV), avec des activites aleatoires realistes.
- **Efficacite du detecteur** : Modele phenomenologique tenant compte de l'absorption basse energie et de la penetration haute energie du scintillateur CsI(Tl) de 1 cm3.
**Entrainement hybride (optionnel mais recommande) :**
Si vous avez capture un fichier `background_24h.npy`, le generateur peut l'utiliser pour rendre les spectres synthetiques plus realistes. Le background mesure est melange a 70% avec le modele synthetique (30%), et les pics isotopiques sont ajoutes avec variation aleatoire par-dessus.
```bash
# Avec background mesure (recommande si disponible)
docker compose run --rm train
# Le fichier /data/background_24h.npy est automatiquement utilise
# grace a MEASURED_BACKGROUND_PATH dans docker-compose.yml
```
### Phase 2 : Entrainement du VegaModel (~35 min sur RTX 5060 Ti)
Le modele VegaModel est un CNN-FCNN multi-tache :
```
Entree : spectre 1D (1023 canaux, 20-3000 keV)
├── Bloc CNN 1 : Conv1d(1, 64, 7) BN ReLU MaxPool
├── Bloc CNN 2 : Conv1d(64, 128, 5) BN ReLU MaxPool
├── Bloc CNN 3 : Conv1d(128, 256, 3) BN ReLU MaxPool
├── Tete classification : FC(25651225682) Sigmoid
82 isotopes, probabilite de presence [0, 1]
└── Tete regression : FC(25651225682)
|
|-- Bloc CNN 1 : Conv1d(1, 64, 7) -> BN -> LeakyReLU -> MaxPool
|-- Bloc CNN 2 : Conv1d(64, 128, 5) -> BN -> LeakyReLU -> MaxPool
|-- Bloc CNN 3 : Conv1d(128, 256, 3) -> BN -> LeakyReLU -> MaxPool
|
|-- Tete classification : FC(256->512->256->82) -> Sigmoid
| 82 isotopes, probabilite de presence [0, 1]
|
+-- Tete regression : FC(256->512->256->82)
Activite estimee en Bq pour chaque isotope
```
- **34 493 156 parametres** au total
- **Fonction de perte** : BCE (classification) + MSE ponderee (regression sur isotopes presents uniquement)
- **Fonction de perte** : BCE (classification) + Huber ponderee (regression sur isotopes presents uniquement)
- **Mixed precision (AMP)** : Acceleration sur GPU via float16
- **Early stopping** : Patience de 10 epochs sans amelioration
@ -196,61 +207,55 @@ Le fichier `data/background_24h.npy` est genere avec :
---
## 5. Lancer la detection continue
## 5. Lancer la detection continue + dashboard
```bash
docker compose up detect
docker compose up detect web
```
Le dashboard est accessible sur `http://localhost:8080` avec quatre onglets :
- **Spectre** : Spectre cumule en temps reel, soustraction du background, lignes d'energie des isotopes detectes
- **Background** : Spectre du bruit de fond (live et 24h), modele theorique CsI(Tl), pics detectes
- **CPS** : Evolution du comptage par seconde dans le temps (1h a 30 jours)
- **Historique** : Liste des rapports quotidiens avec isotopes detectes
### Comment ca marche
Toutes les 60 secondes, le moniteur :
```
┌──────────────────────────────────────────────────────────────┐
1. Echantillonnage │
Radiacode.spectrum() → 1024 canaux + duree │
cumulated_counts += counts │
cumulated_live_time += duration.total_seconds() │
│ Radiacode.spectrum_reset() │
│ │
2. A 00h00 chaque jour : Rapport │
Si live_time > 1h : │
rate = cumulated_counts / cumulated_live_time
bg_rate = bg_counts / bg_live_time │
net_rate = clip(rate - bg_rate, 0, None) │
normalized = net_rate / net_rate.max() │
logits, activities = model(normalized) │
probs = sigmoid(logits) │
Pour chaque isotope avec prob > 0.5 : │
rapport[name, prob%, activite_bq] │
Sauvegarder dans logs/report_YYYY-MM-DD.json │
│ Reset cumulateurs │
3. Si detecteur debranche : │
Attendre 60s, retenter la connexion │
│ Les donnees cumulees sont conservees │
└──────────────────────────────────────────────────────────────┘
1. Echantillonnage
Radiacode.spectrum() -> 1024 canaux + duree
cumulated_counts += counts
cumulated_live_time += duration.total_seconds()
Radiacode.spectrum_reset()
2. A 00h00 chaque jour : Rapport
Si live_time > 1h :
rate = cumulated_counts / cumulated_live_time
bg_rate = bg_counts / bg_live_time
net_rate = clip(rate - bg_rate, 0, None)
normalized = net_rate / net_rate.max()
logits, activities = model(normalized)
probs = sigmoid(logits)
Pour chaque isotope avec prob > 0.5 :
rapport[name, prob%, activite_bq]
Sauvegarder dans logs/report_YYYY-MM-DD.json
Reset cumulateurs
3. Si detecteur debranche :
Attendre 60s, retenter la connexion
Les donnees cumulees sont conservees
```
### Pourquoi soustraire le background ?
Le modele est entraite avec du background synthetique, mais le background reel varie selon l'emplacement. La soustraction reelle ameliore la detection :
Le modele est entraite avec du background synthetique realiste (continuum CsI(Tl) + pics environnementaux), mais le background reel varie selon l'emplacement. La soustraction reelle ameliore la detection :
- **Sans soustraction** : Le modele voit K-40 a 1460 keV et peut le signaler comme isotope detecte, meme si c'est juste du background
- **Avec soustraction** : Le pic de K-40 du background est elimine, seul un signal supplementaire est analyse
- **Resultat** : Moins de faux positifs, meilleure sensibilite pour les isotopes faibles
### Debranchement et rebranchement
Le moniteur gere les deconnexions USB proprement :
- Si le Radiacode est debranche, `try_connect()` echoue et retourne `None`
- Le moniteur attend 60 secondes et retente
- Les compteurs cumules ne sont pas reinitialises
- Quand le detecteur est rebranche, l'accumulation reprend
Cela permet de prendre le detecteur avec soi pendant la journee sans perdre les donnees de la nuit.
---
## 6. Interpreter les rapports
@ -393,6 +398,7 @@ L'inference CPU sur Pi 4 prend environ 0.5-1 seconde par spectre, ce qui est suf
| `MAX_DURATION` | `86400` | Duree max des spectres (24h en secondes) |
| `NVIDIA_VISIBLE_DEVICES` | `1` | GPU a utiliser (0 ou 1) |
| `CUDA_VISIBLE_DEVICES` | `1` | GPU visible par CUDA |
| `MEASURED_BACKGROUND_PATH` | `/data/background_24h.npy` | Background mesure pour entrainement hybride |
### Detection (`docker-compose.yml` - service `detect`)
@ -407,6 +413,13 @@ L'inference CPU sur Pi 4 prend environ 0.5-1 seconde par spectre, ce qui est suf
| `REPORT_HOUR` | `0` | Heure du rapport quotidien |
| `MIN_LIVE_TIME` | `3600` | Live time min pour rapport (s) |
### Dashboard (`docker-compose.yml` - service `web`)
| Variable | Defaut | Description |
|----------|--------|-------------|
| `ENERGY_CALIBRATION_OFFSET` | `0.33` | Calibration energetique offset (keV) |
| `ENERGY_CALIBRATION_SLOPE` | `2.97` | Calibration energetique pente (keV/canal) |
### Capture de background
| Variable | Defaut | Description |