Explication etape par etape du pipeline complet : - Durees et raisons (24h background, 12-24h spectres synthetiques) - Bruit Poissonnien et rapport signal/bruit - Physique des spectres synthetiques (Compton, FWHM, efficacite) - Architecture VegaModel et resultats d'entrainement - Interpretation des rapports et isotopes de reference - Guide de transfer vers Raspberry Pi 4 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Radiacode 103 — Identification automatique d'isotopes
Pipeline Docker complet pour la capture, l'analyse et l'identification automatique d'isotopes radioactifs avec un spectrometre gamma Radiacode 103.
Architecture
Radiacode 103 (USB)
│
▼
┌─────────────────────────────────────────────────────────┐
│ Conteneur detect (Python 3.11 + PyTorch CPU) │
│ │
│ capture_background.py ──> background_24h.npy (24h) │
│ radiacode_monitor.py ──> rapport JSON quotidien │
│ │ │
│ ├── Echantillonnage chaque 60s │
│ ├── Soustraction du background │
│ ├── Inference VegaModel (34.5M params, 82 iso) │
│ └── Rapport quotidien a 00h00 │
│ │
│ Modele: vega_best.pt (entraite sur RTX 5060 Ti) │
└─────────────────────────────────────────────────────────┘
Demarrage rapide
# 1. Builder les images
docker compose build
# 2. Lancer l'entrainement (GPU, ~45 min)
docker compose run --rm train
# 3. Capturer le bruit de fond (24h, sans source radioactive)
docker compose run --rm -d --name radiacode-bg detect python capture_background.py
# 4. Lancer la detection continue
docker compose up detect
Configuration
Variables d'environnement (dans docker-compose.yml) :
| Variable | Defaut | Description |
|---|---|---|
MODEL_PATH |
/models/vega_best.pt |
Chemin du modele PyTorch |
ISOTOPE_INDEX_PATH |
/models/vega_isotope_index.txt |
Index des 82 isotopes |
BACKGROUND_PATH |
/data/background_24h.npy |
Fichier background de reference |
THRESHOLD |
0.5 |
Seuil de probabilite pour la detection |
SAMPLE_INTERVAL |
60 |
Intervalle d'echantillonnage (secondes) |
REPORT_HOUR |
0 |
Heure du rapport quotidien |
MIN_LIVE_TIME |
3600 |
Live time minimum pour un rapport (secondes) |
VEGA_DEVICE |
cpu |
Device PyTorch (cpu ou cuda) |
Bruit Poissonnien et modele
Physique du bruit
La detection gamma est un processus de comptage intrinsequement stochastique. Chaque canal du spectre suit une loi de Poisson : si un canal accumule en moyenne N comptages, l'ecart-type est sqrt(N). Le rapport signal/bruit s'ameliore donc en sqrt(N) :
- 6.5 CPS de background sur 1024 canaux -> ~0.006 CPS/canal
- Apres 1h : ~22 comptages/canal, ecart-type ~4.7, SNR ~5
- Apres 24h : ~560 comptages/canal, ecart-type ~24, SNR ~23
- Apres 1 semaine : ~3900 comptages/canal, ecart-type ~62, SNR ~63
C'est pourquoi la capture de background dure 24h : en dessous, les pics du background (K-40 a 1460 keV, Bi-214 a 609 keV, Pb-214 a 352 keV) sont noyes dans le bruit Poissonnien.
Modele VegaModel
Le VegaModel est un CNN-FCNN multi-tache inspire de l'architecture Vega d'Open-RadiaCode-Android :
- Entree : spectre 1D de 1023 canaux (20-3000 keV), normalise par max
- Sortie : deux tetes
- Classification : 82 neurones avec sigmoid (presence/absence de chaque isotope)
- Regression : 82 neurones (activite estimee en Bq, normalisee a max_activity_bq=1000)
- Architecture :
- 3 blocs CNN (64, 128, 256 canaux) avec BatchNorm + ReLU + MaxPool
- 2 couches FC (512, 256) avec Dropout(0.3)
- 34 493 156 parametres au total
- Fonction de perte : VegaLoss = classification_weight * BCE + regression_weight * MSE (ponderee pour ne penaliser l'activite que sur les isotopes presents)
- Entrainement : 50 000 spectres synthetiques, 100 epochs, AMP (mixed precision), early stopping (patience=10)
- Background dans les donnees synthetiques : K-40, radon (Pb-214, Bi-214), thorium (Ac-228, Pb-212, Tl-208) simules avec des activites aleatoires realistes
Spectres synthetiques
Les donnees d'entrainement simulent la physique complete :
- Pics photoelectriques : Gaussiennes avec FWHM dependant de l'energie (8.4% a 662 keV pour le CsI(Tl))
- Continuum Compton : distribution de Klein-Nishina simplifiee sous chaque pic
- Bruit Poissonnien : echantillonnage Poisson(N) pour chaque canal, simulant les fluctuations de comptage reelles
- Background environnemental : continuum exponentiel + pics de K-40, radon, thorium avec activites aleatoires
- Efficacite du detecteur : modele phenomenologique qui decroit avec l'energie (absorption basse energie + penetration haute energie)
- Durees de 12-24h : suffisamment longues pour que le rapport signal/bruit soit comparable aux mesures reelles
Soustraction du background a l'inference
Le modele est entraine avec du background synthetique inclus, mais a l'inference on soustrait le vrai background mesure :
rate = cumulated_counts / cumulated_live_time # spectre brut en CPS
bg_rate = bg_counts / bg_live_time # background de reference en CPS
net_rate = np.clip(rate - bg_rate, 0, None) # spectre net (background soustrait)
normalized = net_rate / net_rate.max() # normalisation pour le modele
Cette approche hybride est optimale :
- Le modele apprend a ignorer les pics du background (K-40, radon, thorium) pendant l'entrainement
- La soustraction reelle elimine les variations locales du background (emplacement, altitude, materiaux)
- Resultat : meilleure sensibilite et moins de faux positifs
Le conteneur train execute deux phases :
- Generation des spectres synthetiques : 50 000 spectres 1D (20k mono-isotope, 15k bi-isotope, 10k multi-isotope, 5k background seul) avec des durees de 12-24h
- Entrainement VegaModel : CNN-FCNN multi-tache, 82 isotopes, 34.5M parametres
Resultats de l'entrainement sur RTX 5060 Ti :
- Val accuracy : 99.89%
- AUC macro : 0.995
- Best val loss : 0.0051
- Duree : ~45 min (100 epochs, 25s/epoch)
Detection
Le moniteur radiacode_monitor.py :
- Echantillonne le spectre toutes les 60 secondes
- Cumule les comptages et le live time
- Soustrait le background de reference (si disponible)
- Execute l'inference VegaModel sur le spectre net
- Genere un rapport JSON quotidien a
REPORT_HOUR
Le rapport contient :
- Live time et comptages totaux
- CPS moyen
- Isotopes detectes avec probabilite et activite estimee (Bq)
Capture du bruit de fond
Avant la detection, capturer le background pendant 24h sans source radioactive a proximite :
docker compose run --rm -d --name radiacode-bg \
-e TARGET_DURATION=86400 -e SAMPLE_INTERVAL=60 \
detect python capture_background.py
Suivre la progression :
docker logs -f radiacode-bg
cat data/background_snapshot.json
Structure du projet
radiacode_103/
├── docker-compose.yml # Orchestration des conteneurs
├── TOTO.md # Suivi des taches
├── README.md
├── train/
│ ├── Dockerfile # PyTorch 2.7.0 + CUDA 12.8 (Blackwell)
│ ├── requirements.txt
│ ├── entrypoint.sh # Generation + entrainement
│ └── vega_ml/ # Code VegaModel (copie d'Open-RadiaCode-Android)
│ ├── synthetic_spectra/ # Generateur de spectres synthetiques
│ ├── training/vega/ # Modele, dataset, trainer
│ └── inference/
├── detect/
│ ├── Dockerfile # Python 3.11-slim + radiacode + torch CPU
│ ├── requirements.txt
│ ├── radiacode_monitor.py # Moniteur principal
│ └── capture_background.py # Capture du bruit de fond 24h
├── data/
│ ├── synthetic/spectra/ # 50 000 spectres synthetiques (~4.2 Go)
│ └── background_snapshot.json
├── models/
│ ├── vega_best.pt # Meilleur modele (395 Mo)
│ ├── vega_final.pt # Modele final
│ ├── vega_history.json # Metriques d'entrainement
│ └── vega_isotope_index.txt # 82 isotopes
└── logs/ # Rapports quotidiens JSON
Materiel
| Composant | Modele |
|---|---|
| Spectrometre | Radiacode 103 (CsI(Tl), 1024 canaux, FWHM 8.4% @662 keV) |
| GPU entrainement | NVIDIA RTX 5060 Ti 16 Go (Blackwell, sm_120) |
| GPU secondaire | NVIDIA RTX 4060 Ti 16 Go (Ada Lovelace) |
| Production (futur) | Raspberry Pi 4 8 Go |
82 isotopes detectables
Ac-227, Ac-228, Ag-110m, Am-241, Au-198, Ba-133, Ba-137m, Be-7, Bi-210, Bi-211, Bi-212, Bi-214, C-14, Cd-109, Ce-139, Ce-144, Co-57, Co-58, Co-60, Cr-51, Cs-134, Cs-137, Eu-152, Eu-154, F-18, Fe-59, Ga-67, Hf-181, Hg-203, I-123, I-129, I-131, In-111, Ir-192, K-40, Lu-177, Mn-54, Na-22, Pa-231, Pa-234m, Pb-210, Pb-211, Pb-212, Pb-214, Po-210, Po-212, Po-214, Po-216, Po-218, Pr-144, Ra-223, Ra-224, Ra-226, Ra-228, Rh-106, Rn-220, Rn-222, Ru-106, Sb-125, Sc-46, Se-75, Sm-153, Sn-113, Sr-85, Sr-90, Ta-182, Tc-99m, Th-228, Th-230, Th-231, Th-232, Th-234, Tl-201, Tl-207, Tl-208, U-234, U-235, U-238, Xe-133, Y-88, Y-90, Zn-65
Passage en production (Raspberry Pi 4)
- Copier
models/vega_best.ptetmodels/vega_isotope_index.txtsur le Pi 4 - Capturer le background sur le Pi 4 (emplacement final)
- Le meme
detect/Dockerfilefonctionne sur ARM64 - Adapter
docker-compose.yml: retirerdeploy.resources.reservations.devices VEGA_DEVICE=cpu(inference CPU sur Pi 4, ~1s par spectre)