viewof sigma = Inputs.range([0.3, 2.0], {
value: 1.0,
step: 0.05,
label: "trial σ"
})
viewof noise = Inputs.range([0.01, 0.15], {
value: 0.05,
step: 0.01,
label: "noise δy"
})
viewof regenerate = Inputs.button("Generate new pseudo-data")
viewof overlays = {
const control = Inputs.checkbox(
["show best fit", "show true σ"],
{label: "show", value: ["show best fit"]}
);
control.classList.add("fit-overlays-inline");
return control;
}
showFit = overlays.includes("show best fit")
showTruth = overlays.includes("show true σ")
// Gaussian random number
function randn() {
const u = 1 - Math.random();
const v = Math.random();
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
}
// Fixed x values
x = Array.from({length: 21}, (_, i) => -2.5 + 0.25 * i)
// True sigma (hidden by default)
sigmaTrue = {
regenerate;
return 0.5 + Math.random();
}
gauss = (x, s) => Math.exp(-(x * x) / (2 * s * s))
data = {
regenerate;
return x.map((xi) => ({
x: xi,
y: gauss(xi, sigmaTrue) + noise * randn(),
err: noise
}));
}
chi2of = (s) => data.reduce(
(sum, d) => sum + ((d.y - gauss(d.x, s)) / d.err) ** 2,
0
)
chi2 = chi2of(sigma)
sigmaGrid = Array.from({length: 341}, (_, i) => 0.30 + 0.005 * i)
chi2Grid = sigmaGrid.map((s) => ({sigma: s, chi2: chi2of(s)}))
best = chi2Grid.reduce((a, b) => (a.chi2 < b.chi2 ? a : b))
sigmaFit = best.sigma
chi2min = best.chi2
ndf = Math.max(data.length - 1, 1)
dchi2 = chi2 - chi2min
trialCurve = x.map((xi) => ({x: xi, y: gauss(xi, sigma)}))
fitCurve = x.map((xi) => ({x: xi, y: gauss(xi, sigmaFit)}))
trueCurve = x.map((xi) => ({x: xi, y: gauss(xi, sigmaTrue)}))
mutable history = []
historyReset = {
regenerate;
mutable history = [];
return null;
}
historyUpdate = {
const h = history;
const last = h.length > 0 ? h[h.length - 1] : null;
const point = {sigma, chi2};
if (!last || Math.abs(last.sigma - point.sigma) > 1e-9) {
mutable history = [...h, point];
}
return null;
}
mainPlot = Plot.plot({
width: 700,
height: 380,
x: {label: "x"},
y: {label: "y", domain: [-0.2, 1.2]},
grid: true,
marks: [
Plot.ruleX(data, {
x: "x",
y1: (d) => d.y - d.err,
y2: (d) => d.y + d.err,
stroke: "white",
strokeWidth: 1.5
}),
Plot.dot(data, {x: "x", y: "y", r: 3.5, fill: "white", stroke: "white"}),
Plot.line(trialCurve, {x: "x", y: "y", stroke: "#ff6b6b", strokeWidth: 2}),
...(showTruth ? [
Plot.line(trueCurve, {
x: "x",
y: "y",
stroke: "#8ec5ff",
strokeWidth: 2,
strokeOpacity: 0.85
})
] : []),
...(showFit ? [
Plot.line(fitCurve, {
x: "x",
y: "y",
stroke: "#7CFC00",
strokeWidth: 2,
strokeDasharray: "6,4"
})
] : [])
]
})
profilePlot = Plot.plot({
width: 320,
height: 230,
x: {label: "σ", domain: [0.3, 2.0]},
y: {label: "χ²"},
grid: true,
marks: [
Plot.line(chi2Grid, {
x: "sigma",
y: "chi2",
stroke: "#8ec5ff",
strokeOpacity: 0.75
}),
...(history.length > 1 ? [
Plot.line(history, {
x: "sigma",
y: "chi2",
stroke: "gray",
strokeOpacity: 0.45
})
] : []),
Plot.dot(history.slice(0, -1), {
x: "sigma",
y: "chi2",
fill: "gray",
r: 2.8
}),
Plot.dot([{sigma, chi2}], {
x: "sigma",
y: "chi2",
fill: "#ff6b6b",
r: 5
}),
...(showFit ? [
Plot.dot([{sigma: sigmaFit, chi2: chi2min}], {
x: "sigma",
y: "chi2",
fill: "#7CFC00",
r: 5
}),
Plot.ruleY([chi2min], {
stroke: "#7CFC00",
strokeDasharray: "4,4"
})
] : [])
]
})
fitStyle = html`
<style>
.fit-widget .fit-overlays-inline {
display: flex;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
}
.fit-widget .fit-overlays-inline label {
display: inline-flex;
align-items: center;
gap: 0.35rem;
margin: 0;
}
.fit-widget .fit-layout {
display: grid;
grid-template-columns: minmax(520px, 1fr) 320px;
gap: 1rem;
align-items: start;
}
.fit-widget .fit-side figure {
margin: 0;
}
@media (max-width: 980px) {
.fit-widget .fit-layout {
grid-template-columns: 1fr;
}
}
</style>
`
html`
<div>
${fitStyle}
<div class="fit-layout">
<div class="fit-main">
${mainPlot}
</div>
<div class="fit-side">
${profilePlot}
</div>
</div>
<div style="margin-top:0.8em; font-size:0.9em; line-height:1.6;">
<div>
<span style="color:#ff6b6b;"><b>Your choice:</b></span>
σ = ${sigma.toFixed(2)},
χ² = ${chi2.toFixed(2)},
χ²/ndf = ${(chi2 / ndf).toFixed(2)}
</div>
${showFit ? `
<div>
<span style="color:#7CFC00;"><b>Best fit:</b></span>
σ_fit = ${sigmaFit.toFixed(3)},
χ²_min = ${chi2min.toFixed(2)},
Δχ² = ${dchi2.toFixed(2)}
</div>` : ``}
${showTruth ? `
<div>
<span style="color:#8ec5ff;"><b>Truth:</b></span>
σ_true = ${sigmaTrue.toFixed(3)}
</div>` : ``}
</div>
</div>
`