Dash web: crosshair, zoom/pan X, scale log/lin, continuum extraction, background resume

- Tooltip entier (intersect:false) + ligne verticale crosshair sur tous les graphes
- Zoom molette/pinch sur l'axe X, pan souris, limites clamped 30-3000 keV
- Toggle échelle log/linéaire onglet Background
- Extraction continuum détecteur (isotope peaks subtracted + Gaussian smoothing)
- Reprise snapshot précédent au démarrage capture_background.py
- Suppression refs "Théorique" et "Bruit capteur" de l'interface
- Plugin chartjs-plugin-zoom + hammerjs via CDN
- Fix Chart constructor spread operator

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-05-19 23:26:28 +02:00
parent 0f2417bf88
commit c764a5c264
15 changed files with 975 additions and 221 deletions

View File

@ -324,13 +324,16 @@ def generate_realistic_continuum(
Generate realistic CsI(Tl) background continuum shape.
Calibrated against real Radiacode 103 background measurements.
Produces the characteristic asymmetric hump at ~110 keV and
Compton-like tail that simple exponentials miss.
Produces the characteristic asymmetric hump at ~110 keV with
housing absorption at low energy, Compton plateau, and proper
high-energy falloff.
Shape components:
- Asymmetric hump centered at ~110 keV (sigma_left=55, sigma_right=50 keV)
- Compton continuum: 0.45*exp(-E/240) + 0.04*exp(-E/700)
- Noise floor at 0.8% of peak
- Asymmetric hump at ~110 keV (sigma_left=48, sigma_right=80 keV)
- Housing absorption below ~40 keV: 1 - exp(-E/30)
- Compton plateau around 200-260 keV from Pb-214/Bi-214 scatter
- Compton tail: 0.38*exp(-E/170) + 0.06*exp(-E/500)
- Noise floor at 0.3% of peak
Args:
energy_bins: Array of energy bin centers (keV)
@ -342,24 +345,31 @@ def generate_realistic_continuum(
"""
E = energy_bins
# Asymmetric hump at ~110 keV (low-energy scatter peak in CsI(Tl))
# Asymmetric hump at ~110 keV
# Left side sharper (sigma=48), right side broader with Compton shoulder (sigma=80)
hump_center = 110.0
sigma_left = 55.0 # Broader on the low-energy side
sigma_right = 50.0 # Narrower on the high-energy side
hump = np.where(
E <= hump_center,
np.exp(-0.5 * ((E - hump_center) / sigma_left) ** 2),
np.exp(-0.5 * ((E - hump_center) / sigma_right) ** 2),
np.exp(-0.5 * ((E - hump_center) / 48.0) ** 2),
np.exp(-0.5 * ((E - hump_center) / 80.0) ** 2),
)
# Housing absorption at very low energy (< ~40 keV)
absorption = 1.0 - np.exp(-E / 30.0)
# Compton continuum tail
tail = 0.45 * np.exp(-E / 240.0) + 0.04 * np.exp(-E / 700.0)
tail = 0.38 * np.exp(-E / 170.0) + 0.06 * np.exp(-E / 500.0)
# Noise floor (low-level baseline)
noise_floor = 0.008
# Compton plateau around 200-260 keV (Pb-214/Bi-214 scatter)
compton_edge = np.maximum(0, 1.0 - ((E - 180.0) / 150.0) ** 2)
compton_edge[E > 330] = 0
compton_plateau = 0.12 * compton_edge
# Combine shape components
continuum = hump + tail + noise_floor
# Noise floor
noise_floor = 0.003
# Combine continuum with absorption
continuum = (hump + tail + compton_plateau) * absorption + noise_floor
# Normalize to target total counts
if continuum.sum() > 0 and total_counts > 0: