mirror of
https://github.com/vale981/neutrino_oscillations
synced 2025-03-05 09:41:39 -05:00
reduce ui boilerplate and add initial state control
This commit is contained in:
parent
6a2b35466b
commit
542c810820
2 changed files with 282 additions and 125 deletions
59
index.html
59
index.html
|
@ -19,67 +19,28 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<div class="row">
|
||||||
|
<h1>Controls</h1>
|
||||||
|
<form id="controls">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="neutrinos" class="card fluid">
|
<div id="neutrinos" class="card fluid">
|
||||||
<canvas id="neutrinorender"></canvas>
|
<canvas id="neutrinorender"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="card fluid" id="settings">
|
<div class="card" id="pmns">
|
||||||
<h3>Current Settings</h3>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-6" id="pmns">
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3" id="sliders_1">
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3" id="sliders_2">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<form id="controls">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<fieldset>
|
|
||||||
<legend>Mixing Angles in \(^\circ\)</legend>
|
|
||||||
<label for="t12">\(\theta_{12}\)</label>
|
|
||||||
<input type="range" step=".1" min="0" max="90" id="t12" />
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<label for="t13">\(\theta_{13}\)</label>
|
|
||||||
<input type="range" step=".1" max="90" id="t13" />
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<label for="t23">\(\theta_{23}\)</label>
|
|
||||||
<input type="range" step=".1" min="0" max="90" id="t23" />
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>Squared Mass Differences \([10^{-4}\text{eV}^{2}]\)</legend>
|
|
||||||
<label for="ms13">\(\Delta m_{13}^2\)</label>
|
|
||||||
<input type="range" step=".1" min="0" max="30" id="ms13" />
|
|
||||||
<br>
|
|
||||||
<label for="ms23">\(\Delta m_{23}^2\)</label>
|
|
||||||
<input type="range" step=".1" min="0" max="30" id="ms23" />
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<fieldset>
|
|
||||||
<legend>Observatory Settings</legend>
|
|
||||||
<label for="L_max">\(L_{\text{max}}\) [km]</label>
|
|
||||||
<input type="range" min="0" max="1000" id="L_max" />
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<label for="energy">\(E\) [MeV]</label>
|
|
||||||
<input type="range" step=".1" min="0" max="1000" id="energy" />
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="lib/chart.min.js"></script>
|
<script src="lib/chart.min.js"></script>
|
||||||
<script src="lib/math.min.js"></script>
|
<script src="lib/math.min.js"></script>
|
||||||
|
|
340
index.js
340
index.js
|
@ -34,6 +34,7 @@ const render = new Chart(ctx, {
|
||||||
|
|
||||||
const controls = document.forms.controls;
|
const controls = document.forms.controls;
|
||||||
const settings = document.getElementById('settings');
|
const settings = document.getElementById('settings');
|
||||||
|
const pmnsElement = document.getElementById("pmns");
|
||||||
|
|
||||||
// Mixing Angle Experimental Values, degrees
|
// Mixing Angle Experimental Values, degrees
|
||||||
const t12 = 33.44;
|
const t12 = 33.44;
|
||||||
|
@ -52,13 +53,168 @@ const defaultNeutrinoData =
|
||||||
t13,
|
t13,
|
||||||
ms13,
|
ms13,
|
||||||
ms23,
|
ms23,
|
||||||
L_range: [0, 100],
|
L_max: 100,
|
||||||
|
is_e: 1,
|
||||||
|
is_m: 0,
|
||||||
|
is_t: 0,
|
||||||
E: 6 // MeV
|
E: 6 // MeV
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const control_categories = {
|
||||||
|
angles: {
|
||||||
|
title: 'Mixing Angles',
|
||||||
|
},
|
||||||
|
|
||||||
|
masses: {
|
||||||
|
title: 'Squared Mass Differences',
|
||||||
|
},
|
||||||
|
|
||||||
|
state: {
|
||||||
|
title: 'Initial State',
|
||||||
|
},
|
||||||
|
|
||||||
|
observatory: {
|
||||||
|
title: 'Observatory Settings',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const neutrino_controls = {
|
||||||
|
t12: {
|
||||||
|
title: '\\(\\theta_{12}\\)',
|
||||||
|
unit: '\\(^\\circ\\)',
|
||||||
|
default_value: t12,
|
||||||
|
category: 'angles',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 90,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
t13: {
|
||||||
|
title: '\\(\\theta_{13}\\)',
|
||||||
|
unit: '\\(^\\circ\\)',
|
||||||
|
default_value: t13,
|
||||||
|
category: 'angles',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 90,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
t23: {
|
||||||
|
title: '\\(\\theta_{23}\\)',
|
||||||
|
unit: '\\(^\\circ\\)',
|
||||||
|
default_value: t23,
|
||||||
|
category: 'angles',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 90,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ms13: {
|
||||||
|
title: '\\(\\Delta m_{13}^2\\)',
|
||||||
|
unit: '\\(\\cdot 10^{-4}\\text{eV}^2\\)',
|
||||||
|
default_value: ms13,
|
||||||
|
category: 'masses',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 50,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ms23: {
|
||||||
|
title: '\\(\\Delta m_{23}^2\\)',
|
||||||
|
unit: '\\(\\cdot 10^{-4}\\text{eV}^2\\)',
|
||||||
|
default_value: ms23,
|
||||||
|
category: 'masses',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 50,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
L_max: {
|
||||||
|
title: '\\(L_\\text{max}\\)',
|
||||||
|
unit: ' \\(\\text{km}\\)',
|
||||||
|
default_value: defaultNeutrinoData.L_max,
|
||||||
|
category: 'observatory',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 1000,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
E: {
|
||||||
|
title: '\\(E\\)',
|
||||||
|
unit: ' \\(\\text{MeV}\\)',
|
||||||
|
default_value: defaultNeutrinoData.E,
|
||||||
|
category: 'observatory',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: .1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
is_e: {
|
||||||
|
title: '\\(e\\)',
|
||||||
|
unit: '',
|
||||||
|
default_value: defaultNeutrinoData.is_e,
|
||||||
|
category: 'state',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
step: .01,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
is_m: {
|
||||||
|
title: '\\(\\mu\\)',
|
||||||
|
unit: '',
|
||||||
|
default_value: defaultNeutrinoData.is_m,
|
||||||
|
category: 'state',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
step: .01,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
is_t: {
|
||||||
|
title: '\\(\\tau\\)',
|
||||||
|
unit: '',
|
||||||
|
default_value: defaultNeutrinoData.is_t,
|
||||||
|
category: 'state',
|
||||||
|
control: {
|
||||||
|
type: 'slider',
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
step: .01,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Util //
|
// Util //
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function deg_to_rad(x) {
|
function deg_to_rad(x) {
|
||||||
return (x / 180) * math.pi
|
return (x / 180) * math.pi
|
||||||
}
|
}
|
||||||
|
@ -115,13 +271,20 @@ function state_to_probabilies(state) {
|
||||||
return state.map(value => math.multiply(value.conjugate(), value).re);
|
return state.map(value => math.multiply(value.conjugate(), value).re);
|
||||||
}
|
}
|
||||||
|
|
||||||
function plot_propagation(state, neutrino_data) {
|
function plot_propagation(neutrino_data) {
|
||||||
const {t12, t23, t13, ms13, ms23, L_range, E} = neutrino_data;
|
const {t12, t23, t13, ms13, ms23, L_max, E, is_e, is_m, is_t} = neutrino_data;
|
||||||
|
|
||||||
|
const norm = math.sqrt(is_e * is_e + is_m * is_m + is_t * is_t);
|
||||||
|
let state = math.matrix([
|
||||||
|
[is_e / norm],
|
||||||
|
[is_m / norm],
|
||||||
|
[is_t / norm]
|
||||||
|
]);
|
||||||
|
|
||||||
pmns_matrix = pmns(t12, t23, t13);
|
pmns_matrix = pmns(t12, t23, t13);
|
||||||
|
|
||||||
dL = ((L_range[1] - L_range[0]) / 1000);
|
dL = ((L_max) / 1000);
|
||||||
lengths = math.range(L_range[0], L_range[1], dL);
|
lengths = math.range(0, L_max, dL);
|
||||||
|
|
||||||
common_options = {
|
common_options = {
|
||||||
pointRadius: 0,
|
pointRadius: 0,
|
||||||
|
@ -167,30 +330,9 @@ function plot_propagation(state, neutrino_data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function initForm() {
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
controls.elements.t13.value = t13;
|
// UI Stuff //
|
||||||
controls.elements.t12.value = t12;
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
controls.elements.t23.value = t23;
|
|
||||||
|
|
||||||
controls.elements.L_max.value = defaultNeutrinoData.L_range[1];
|
|
||||||
controls.elements.energy.value = defaultNeutrinoData.E;
|
|
||||||
|
|
||||||
controls.elements.ms13.value = ms13;
|
|
||||||
controls.elements.ms23.value = ms23;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNeutrinoData() {
|
|
||||||
return {
|
|
||||||
...defaultNeutrinoData,
|
|
||||||
t13: controls.elements.t13.value,
|
|
||||||
t12: controls.elements.t12.value,
|
|
||||||
t23: controls.elements.t23.value,
|
|
||||||
ms13: controls.elements.ms13.value,
|
|
||||||
ms23: controls.elements.ms23.value,
|
|
||||||
E: controls.elements.energy.value,
|
|
||||||
L_range: [0, controls.elements.L_max.value],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderPmnsMatrix(pmns_matrix) {
|
function renderPmnsMatrix(pmns_matrix) {
|
||||||
let result = "$$U=\\begin{pmatrix}\n";
|
let result = "$$U=\\begin{pmatrix}\n";
|
||||||
|
@ -205,52 +347,106 @@ function renderPmnsMatrix(pmns_matrix) {
|
||||||
|
|
||||||
result += "\\end{pmatrix}$$";
|
result += "\\end{pmatrix}$$";
|
||||||
|
|
||||||
return result;
|
|
||||||
|
pmnsElement.textContent = result;
|
||||||
|
renderMathInElement(pmnsElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayCurrentSettings() {
|
|
||||||
const {t12, t23, t13, ms13, ms23, L_range, E} = getNeutrinoData();
|
|
||||||
pmns_matrix = pmns(t12, t23, t13);
|
|
||||||
|
|
||||||
// render pmns
|
|
||||||
settings.querySelector("#pmns").textContent = renderPmnsMatrix(pmns_matrix);
|
|
||||||
|
|
||||||
settings.querySelector("#sliders_1").innerHTML = `
|
|
||||||
\\(\\theta_{12} = ${t12}^\\circ\\)
|
|
||||||
<br>
|
|
||||||
\\(\\theta_{13} = ${t13}^\\circ\\)
|
|
||||||
<br>
|
|
||||||
\\(\\theta_{23} = ${t23}^\\circ\\)
|
|
||||||
`;
|
|
||||||
settings.querySelector("#sliders_2").innerHTML = `
|
|
||||||
\\(\\Delta m_{13}^2 = ${ms13}\\cdot 10^{-4}\\text{GeV}\\)
|
|
||||||
<br>
|
|
||||||
\\(\\Delta m_{23}^2 = ${ms23}\\cdot 10^{-4}\\text{GeV}\\)
|
|
||||||
<br>
|
|
||||||
\\(L_\\text{max} = ${L_range[1]}\\text{km}\\)
|
|
||||||
<br>
|
|
||||||
\\(E = ${E}\\text{MeV}\\)
|
|
||||||
`;
|
|
||||||
|
|
||||||
renderMathInElement(settings);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", (event) => {
|
document.addEventListener("DOMContentLoaded", (event) => {
|
||||||
initForm();
|
renderControls();
|
||||||
displayCurrentSettings();
|
|
||||||
plot_propagation(math.matrix([
|
const {t12, t23, t13} = getNeutrinoData();
|
||||||
[1],
|
renderPmnsMatrix(pmns(t12, t23, t13));
|
||||||
[0],
|
|
||||||
[0]
|
plot_propagation(defaultNeutrinoData);
|
||||||
]), defaultNeutrinoData);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
controls.addEventListener('input', () => {
|
function makeControlElement(id, element) {
|
||||||
displayCurrentSettings();
|
const {min, max, step} = element.control;
|
||||||
plot_propagation(math.matrix([
|
|
||||||
[1],
|
const input_div = document.createElement("div");
|
||||||
[0],
|
const label = document.createElement("label");
|
||||||
[0]
|
const input = document.createElement("input");
|
||||||
]), getNeutrinoData());
|
|
||||||
});
|
|
||||||
|
label.innerHTML = `${element.title} = <span id="val_${id}">${element.default_value}</span>${element.unit}`;
|
||||||
|
label.htmlFor = id
|
||||||
|
|
||||||
|
input.type = "range";
|
||||||
|
input.step = step;
|
||||||
|
input.min = min;
|
||||||
|
input.max = max;
|
||||||
|
input.id = id;
|
||||||
|
input.value = element.default_value;
|
||||||
|
input.label = label;
|
||||||
|
|
||||||
|
input_div.className = "input-group vertical";
|
||||||
|
input_div.appendChild(label);
|
||||||
|
input_div.appendChild(input);
|
||||||
|
|
||||||
|
return input_div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderControls() {
|
||||||
|
for (let category in control_categories) {
|
||||||
|
const category_element = document.createElement("fieldset");
|
||||||
|
category_element.id = category;
|
||||||
|
|
||||||
|
const legend = document.createElement("legend");
|
||||||
|
legend.textContent = control_categories[category].title;
|
||||||
|
|
||||||
|
category_element.appendChild(legend);
|
||||||
|
controls.appendChild(category_element);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let id in neutrino_controls) {
|
||||||
|
const element = neutrino_controls[id];
|
||||||
|
const group = controls.querySelector("#" + element.category);
|
||||||
|
const control = makeControlElement(id, element);
|
||||||
|
|
||||||
|
group.appendChild(control);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMathInElement(controls);
|
||||||
|
controls.addEventListener('input', handleInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNeutrinoData() {
|
||||||
|
const data = {};
|
||||||
|
|
||||||
|
for (let element in neutrino_controls) {
|
||||||
|
data[element] = parseFloat(controls.elements[element].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {...defaultNeutrinoData, ...data};
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateControlLabel(control) {
|
||||||
|
control.label.childNodes.item(3).textContent = control.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleInput(event) {
|
||||||
|
const control = event.target;
|
||||||
|
normalizeSliders()
|
||||||
|
|
||||||
|
const neutrino_data = getNeutrinoData();
|
||||||
|
const {t12, t23, t13} = neutrino_data;
|
||||||
|
|
||||||
|
renderPmnsMatrix(pmns(t12, t23, t13));
|
||||||
|
|
||||||
|
updateControlLabel(control);
|
||||||
|
|
||||||
|
plot_propagation(neutrino_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSliders() {
|
||||||
|
const {is_e, is_m, is_t} = getNeutrinoData();
|
||||||
|
const norm = math.sqrt(is_e * is_e + is_m * is_m + is_t * is_t);
|
||||||
|
|
||||||
|
for (let name of ['is_e', 'is_t', 'is_m']) {
|
||||||
|
const control = controls[name];
|
||||||
|
control.value = control.value / norm
|
||||||
|
updateControlLabel(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue