Fix: reset zoom restores full energy range (0.33-3035.67 keV)

Use {x,y} data format so Chart.js linear scale uses energy values
instead of channel indices. After reset, force scale min/max to the
full energy range.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-05-20 01:25:33 +02:00
parent 6c78c13622
commit edaceae8a3
2 changed files with 37 additions and 26 deletions

View File

@ -87,7 +87,7 @@
<script src="/static/js/chart_pan.js?v=3"></script> <script src="/static/js/chart_pan.js?v=3"></script>
<script src="/static/js/spectrum.js?v=9"></script> <script src="/static/js/spectrum.js?v=9"></script>
<script src="/static/js/history.js?v=2"></script> <script src="/static/js/history.js?v=2"></script>
<script src="/static/js/background.js?v=17"></script> <script src="/static/js/background.js?v=30"></script>
<script src="/static/js/cps.js?v=7"></script> <script src="/static/js/cps.js?v=7"></script>
<script src="/static/js/app.js?v=3"></script> <script src="/static/js/app.js?v=3"></script>
</body> </body>

View File

@ -2,6 +2,22 @@ let bgChart = null;
let bgReferenceData = null; let bgReferenceData = null;
let bgContinuumData = null; let bgContinuumData = null;
// Reset zoom button — fully restores the energy range
document.getElementById('reset-zoom-bg')?.addEventListener('click', () => {
if (bgChart) {
bgChart.resetZoom();
// After resetZoom, force the scale to full energy range
const firstPt = bgChart.data.datasets[0]?.data?.[0];
const lastPt = bgChart.data.datasets[0]?.data?.[bgChart.data.datasets[0].data.length - 1];
const fullMin = firstPt?.x ?? 0;
const fullMax = lastPt?.x ?? 3036;
bgChart.options.scales.x.min = fullMin;
bgChart.options.scales.x.max = fullMax;
bgChart.update();
document.getElementById('reset-zoom-bg').style.display = 'none';
}
});
async function loadBgReference() { async function loadBgReference() {
try { try {
const resp = await fetch(`${API_BASE}/api/background/reference`); const resp = await fetch(`${API_BASE}/api/background/reference`);
@ -94,9 +110,12 @@ function updateBackgroundChart(spec) {
const showSmooth = document.getElementById('show-bg-smooth')?.checked; const showSmooth = document.getElementById('show-bg-smooth')?.checked;
const showContinuum = document.getElementById('show-bg-continuum')?.checked && bgContinuumData; const showContinuum = document.getElementById('show-bg-continuum')?.checked && bgContinuumData;
const energy = spec.energy_kev;
const toData = (arr) => arr.map((v, i) => ({ x: energy[i], y: v }));
const datasets = [{ const datasets = [{
label: 'Background (live)', label: 'Background (live)',
data: spec.counts, data: toData(spec.counts),
borderColor: '#ff9800', borderColor: '#ff9800',
backgroundColor: 'rgba(255, 152, 0, 0.1)', backgroundColor: 'rgba(255, 152, 0, 0.1)',
borderWidth: 1, borderWidth: 1,
@ -108,7 +127,7 @@ function updateBackgroundChart(spec) {
const smoothed = smoothGaussian(spec.counts, 8); const smoothed = smoothGaussian(spec.counts, 8);
datasets.push({ datasets.push({
label: 'Lissé', label: 'Lissé',
data: smoothed, data: toData(smoothed),
borderColor: 'rgba(233, 30, 99, 0.9)', borderColor: 'rgba(233, 30, 99, 0.9)',
backgroundColor: 'rgba(233, 30, 99, 0.05)', backgroundColor: 'rgba(233, 30, 99, 0.05)',
borderWidth: 2, borderWidth: 2,
@ -120,7 +139,7 @@ function updateBackgroundChart(spec) {
if (showContinuum) { if (showContinuum) {
datasets.push({ datasets.push({
label: 'Continuum', label: 'Continuum',
data: bgContinuumData.counts, data: toData(bgContinuumData.counts),
borderColor: 'rgba(156, 39, 176, 0.8)', borderColor: 'rgba(156, 39, 176, 0.8)',
backgroundColor: 'rgba(156, 39, 176, 0.05)', backgroundColor: 'rgba(156, 39, 176, 0.05)',
borderWidth: 2, borderWidth: 2,
@ -134,9 +153,10 @@ function updateBackgroundChart(spec) {
const scale = spec.live_time_s > 0 && bgReferenceData.live_time_s > 0 const scale = spec.live_time_s > 0 && bgReferenceData.live_time_s > 0
? spec.live_time_s / bgReferenceData.live_time_s ? spec.live_time_s / bgReferenceData.live_time_s
: 1; : 1;
const refEnergy = bgReferenceData.energy_kev || energy;
datasets.push({ datasets.push({
label: `Référence 24h (×${scale.toFixed(1)})`, label: `Référence 24h (×${scale.toFixed(1)})`,
data: bgReferenceData.counts.map(c => c * scale), data: bgReferenceData.counts.map((c, i) => ({ x: refEnergy[i] ?? energy[i], y: c * scale })),
borderColor: 'rgba(79, 195, 247, 0.8)', borderColor: 'rgba(79, 195, 247, 0.8)',
backgroundColor: 'rgba(79, 195, 247, 0.08)', backgroundColor: 'rgba(79, 195, 247, 0.08)',
borderWidth: 1, borderWidth: 1,
@ -147,14 +167,15 @@ function updateBackgroundChart(spec) {
} }
const chartData = { const chartData = {
labels: spec.energy_kev,
datasets: datasets, datasets: datasets,
}; };
const existingMin = bgChart?.scales.x?.min; // Preserve pan range (user zoomed), but reset to full range when data refreshes
const existingMax = bgChart?.scales.x?.max; const panRange = bgChart?._panRange;
const xMin = existingMin ?? spec.energy_kev[0]; const firstX = datasets[0].data[0]?.x;
const xMax = existingMax ?? spec.energy_kev[spec.energy_kev.length - 1]; const lastX = datasets[0].data[datasets[0].data.length - 1]?.x;
const xMin = panRange ? panRange[0] : (firstX ?? 0);
const xMax = panRange ? panRange[1] : (lastX ?? 3036);
const options = { const options = {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
@ -165,10 +186,9 @@ function updateBackgroundChart(spec) {
enabled: true, enabled: true,
mode: 'index', mode: 'index',
intersect: false, intersect: false,
filter: (item) => item.raw != null,
callbacks: { callbacks: {
title: (items) => `${spec.energy_kev[items[0].dataIndex]} keV`, title: (items) => `${items[0].parsed.x.toFixed(1)} keV`,
label: (item) => `${item.dataset.label}: ${item.raw.toFixed(1)} counts` label: (item) => `${item.dataset.label}: ${item.parsed.y.toFixed(1)} counts`
} }
}, },
zoom: { zoom: {
@ -208,7 +228,9 @@ function updateBackgroundChart(spec) {
bgChart.update(); bgChart.update();
} else { } else {
bgChart = new Chart(ctx, { type: 'line', data: chartData, ...options }); bgChart = new Chart(ctx, { type: 'line', data: chartData, ...options });
enablePan(bgChart, 'reset-zoom-bg', spec.energy_kev[0], spec.energy_kev[spec.energy_kev.length - 1]); const firstX = datasets[0].data[0]?.x ?? 0;
const lastX = datasets[0].data[datasets[0].data.length - 1]?.x ?? 3036;
enablePan(bgChart, 'reset-zoom-bg', firstX, lastX);
} }
} }
@ -244,15 +266,4 @@ document.getElementById('show-bg-continuum')?.addEventListener('change', () => {
} }
}); });
document.getElementById('show-bg-smooth')?.addEventListener('change', () => refreshBackground()); document.getElementById('show-bg-smooth')?.addEventListener('change', () => refreshBackground());
document.getElementById('bg-scale-log')?.addEventListener('change', () => refreshBackground()); document.getElementById('bg-scale-log')?.addEventListener('change', () => refreshBackground());
// Reset zoom button
document.getElementById('reset-zoom-bg')?.addEventListener('click', () => {
if (bgChart) {
bgChart.resetZoom();
document.getElementById('reset-zoom-bg').style.display = 'none';
}
});
// Show/hide reset button based on zoom state — wrapped via options plugin
const _origBgOptions = options => options;