mirror of
https://github.com/vale981/neutrino_oscillations
synced 2025-03-04 17:21: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
67
index.html
67
index.html
|
@ -20,67 +20,28 @@
|
|||
|
||||
<div class="container">
|
||||
<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="col-sm-2">
|
||||
<div class="row">
|
||||
<div class="col-sm-6" id="pmns">
|
||||
<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 class="col-sm-3" id="sliders_1">
|
||||
</div>
|
||||
<div class="col-sm-3" id="sliders_2">
|
||||
</div>
|
||||
<div class="row">
|
||||
<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>
|
||||
<script src="index.js"></script>
|
||||
|
|
340
index.js
340
index.js
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue