reduce ui boilerplate and add initial state control

This commit is contained in:
Valentin Boettcher 2021-02-21 14:55:06 +01:00
parent 6a2b35466b
commit 542c810820
2 changed files with 282 additions and 125 deletions

View file

@ -19,67 +19,28 @@
</header>
<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 id="neutrinos" class="card fluid">
<canvas id="neutrinorender"></canvas>
</div>
</div>
<div class="row">
<div class="card fluid" id="settings">
<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 class="card" id="pmns">
</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 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/math.min.js"></script>

340
index.js
View file

@ -34,6 +34,7 @@ const render = new Chart(ctx, {
const controls = document.forms.controls;
const settings = document.getElementById('settings');
const pmnsElement = document.getElementById("pmns");
// Mixing Angle Experimental Values, degrees
const t12 = 33.44;
@ -52,13 +53,168 @@ const defaultNeutrinoData =
t13,
ms13,
ms23,
L_range: [0, 100],
L_max: 100,
is_e: 1,
is_m: 0,
is_t: 0,
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 //
///////////////////////////////////////////////////////////////////////////////
function deg_to_rad(x) {
return (x / 180) * math.pi
}
@ -115,13 +271,20 @@ function state_to_probabilies(state) {
return state.map(value => math.multiply(value.conjugate(), value).re);
}
function plot_propagation(state, neutrino_data) {
const {t12, t23, t13, ms13, ms23, L_range, E} = neutrino_data;
function plot_propagation(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);
dL = ((L_range[1] - L_range[0]) / 1000);
lengths = math.range(L_range[0], L_range[1], dL);
dL = ((L_max) / 1000);
lengths = math.range(0, L_max, dL);
common_options = {
pointRadius: 0,
@ -167,30 +330,9 @@ function plot_propagation(state, neutrino_data) {
});
}
function initForm() {
controls.elements.t13.value = t13;
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],
};
}
///////////////////////////////////////////////////////////////////////////////
// UI Stuff //
///////////////////////////////////////////////////////////////////////////////
function renderPmnsMatrix(pmns_matrix) {
let result = "$$U=\\begin{pmatrix}\n";
@ -205,52 +347,106 @@ function renderPmnsMatrix(pmns_matrix) {
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) => {
initForm();
displayCurrentSettings();
plot_propagation(math.matrix([
[1],
[0],
[0]
]), defaultNeutrinoData);
renderControls();
const {t12, t23, t13} = getNeutrinoData();
renderPmnsMatrix(pmns(t12, t23, t13));
plot_propagation(defaultNeutrinoData);
});
controls.addEventListener('input', () => {
displayCurrentSettings();
plot_propagation(math.matrix([
[1],
[0],
[0]
]), getNeutrinoData());
});
function makeControlElement(id, element) {
const {min, max, step} = element.control;
const input_div = document.createElement("div");
const label = document.createElement("label");
const input = document.createElement("input");
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);
}
}