change the html + javascript still do the job

This commit is contained in:
Ryan@fsunuc 2023-07-30 15:14:19 -04:00
parent 7f359212fb
commit 5521960088
9 changed files with 772 additions and 239 deletions

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "imgui"]
path = imgui
url = https://github.com/ocornut/imgui.git
[submodule "implot"]
path = implot
url = https://github.com/epezent/implot.git

View File

@ -3,7 +3,10 @@
{ {
"name": "Linux", "name": "Linux",
"includePath": [ "includePath": [
"${workspaceFolder}/**" "${workspaceFolder}/**",
"/opt/root/**",
"${workspaceFolder}/imgui/**",
"${workspaceFolder}/implot/**"
], ],
"defines": [], "defines": [],
"compilerPath": "/usr/bin/gcc", "compilerPath": "/usr/bin/gcc",

View File

@ -1,20 +0,0 @@
CXX = em++
OUTPUT = spsGUI.js
IMGUI_DIR = imgui
SOURCES = spsGUI.cpp
SOURCES += implot/implot.cpp implot/implot_items.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_widgets.cpp $(IMGUI_DIR)/imgui_tables.cpp
LIBS = -lGL
WEBGL_VER = -s USE_WEBGL2=1 -s USE_GLFW=3 -s FULL_ES3=1
USE_WASM = -s WASM=1
all: $(SOURCES) $(OUTPUT)
$(OUTPUT): $(SOURCES)
$(CXX) $(SOURCES) -std=c++11 -o $(OUTPUT) $(LIBS) $(WEBGL_VER) -O2 $(USE_WASM) -Iimplot -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
clean:
rm -f $(OUTPUT)

115
get_nuclear_data.py Normal file
View File

@ -0,0 +1,115 @@
#!/usr/bin/env /usr/bin/python3
################################################
import pandas as pd
# the API webpage
# https://www-nds.iaea.org/relnsd/vcharthtml/api_v0_guide.html#examples
# the service URL
livechart = "https://nds.iaea.org/relnsd/v0/data?"
import urllib.request
def lc_read_csv(url):
req = urllib.request.Request(url)
req.add_header('User-Agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0')
return pd.read_csv(urllib.request.urlopen(req))
mp = 938.27208816 #MeV/c^2
mn = 939.56542052
#===================================================
import cgi, cgitb
form = cgi.FieldStorage()
AZ = form.getvalue('isotopes_name')
maxEx = form.getvalue('maxEx')
if maxEx == "can be omitted" :
maxEx = -1
if AZ == "p" :
AZ = "1H"
if AZ == "d" :
AZ = "2H"
if AZ == "t" :
AZ = "3H"
if AZ == "a" :
AZ = "4He"
query = livechart + "fields=ground_states&nuclides=" + AZ
temp = lc_read_csv(query)
print( "Content-type:text/html\r\n\r\n")
print("<html>")
print("<style> body { font-family: courier, courier new, serif; color: #F7CF3C; } </style>")
print("<body>")
print("<br>========================= " + AZ )
try :
Z = temp['z'][0]
N = temp['n'][0]
mass = Z*mp + N*mn - (Z+N)*temp['binding']/1000
halfLife = temp['half_life_sec'][0]
print("<br> A : %3d, Z : %3d, N : %3d" % (Z+N, Z, N))
print("<br> Jpi : %3s" % (temp['jp'][0]))
#if halfLife != " " :
print("<br> half-live : %s sec" % (halfLife))
print("<br> Mass : %.4f MeV" % (mass))
print("<br> Binding : %.4f MeV/A" % (temp['binding']/1000))
print("<br> Binding : %.4f MeV" % (temp['binding']/1000*(Z+N)))
#print(" magnetic dipole : " + temp['magnetic_dipole'][0] + " mu.N")
#print("electric quadruple : " + temp['electric_quadrupole'][0] + " barn")
#if halfLife > 0 :
# print('------------ decay mode:')
# for i in range(1, 4) :
# print("%5s %s %%" % (temp["decay_%d" % i][0], temp["decay_%d_%%" % i][0]))
# print('--------------------------')
except :
print("<br>No such Isotopes.")
# import os, subprocess
# os.chdir(r"files")
# result=subprocess.run(['../Cleopatra/IsotopeShort', AZ], stdout=subprocess.PIPE).stdout.decode('utf-8')
# p1 = result.find('Sn:')
# print("<br>" + result[p1:p1+16])
# p1 = result.find('Sp')
# print("<br>" + result[p1:p1+16])
# p1 = result.find('Sa')
# print("<br>" + result[p1:p1+16])
print("<br>=============================")
if float(maxEx) > 0 :
print("<br>")
query = livechart + "fields=levels&nuclides=" + AZ
tempEx = lc_read_csv(query);
ex = tempEx['energy']
jp = tempEx['jp']
l = ex.last_valid_index()
try :
print("<table>")
for i in range(0, l+1):
if float(ex[i]) < float(maxEx)*1000:
print("<tr><td style=\"text-align:right\" width=80> %9.3f </td><td style=\"text-align:right\" width=100> %s </td></tr>" % (ex[i], jp[i].replace(' ', ',')))
else:
break
print("</table>")
except:
print("<br> cannot find Ex data")
print("</body>")
print("</html>")

1
imgui

@ -1 +0,0 @@
Subproject commit 79d6f4e211f245de24ab7c3a58f33261bd7931bf

1
implot

@ -1 +0,0 @@
Subproject commit cc5e1daa5c7f2335a9460ae79c829011dc5cef2d

View File

@ -1,53 +1,160 @@
<!doctype html> <!DOCTYPE html>
<html lang="en-us"> <html>
<head> <head>
<meta charset="utf-8"> <title>SPS Simulation</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="description" content="SPS simulation">
<title>WebGui Demo</title> <!-- <link rel="icon" type="image/x-icon" href="logos/SOLARIS_favicon.png"> -->
<style> <script src="https://cdn.plot.ly/plotly-2.16.1.min.js"></script>
body { <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, user-scalable=0"/>
font-family: arial; </head>
margin: 0;
padding: none;
}
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: none; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten { border: 0px none; background-color: black; }
</style>
</head>
<body>
<div class="emscripten_border"> <style>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas> body{
</div> font-family: Arial, Helvetica, sans-serif;
background : #CEB888;
}
input[type="range"] {
width: 400px;
}
input::-webkit-slider-runnable-track {
-webkit-appearance: none;
position: relative;
background-color: #782F40;
width: 100%;
height: 20px;
border-radius: 10px;
overflow: hidden;
}
input::-webkit-slider-thumb {
position: relative;
-webkit-appearance: none;
box-shadow: -340px 0 0 320px #782F40, inset 0 0 0 40px #782F40, 340px 0 0 320px #FFFFFF, inset 0 0 0 40px #782F40;
}
</style>
<script type='text/javascript'> <body>
var Module = {
preRun: [], <h1>Split-Pole Spectrograph Simulation</h1>
postRun: [],
print: (function() {})(), <b>For a given reaction and excited states,</b>
printErr: function(text) {}, <ul>
canvas: (function() { <li> calculate the KE vs Lab angle, then </li>
var canvas = document.getElementById('canvas'); <li> find the KE for each state at SPS angle, then </li>
// As a default initial behavior, pop up an alert when webgl context is lost. To make your <li> calculate the rho, then </li>
// application robust, you may want to override this behavior before shipping! <li> plot</li>
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2 <li>Could add energy loss in future.</li>
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false); </ul>
return canvas;
})(), <table id="ReactionTable">
setStatus: function(text) {}, <tr>
totalDependencies: 0, <td style="text-align: right;"><b>Beam</b></td>
monitorRunDependencies: function(left) {} <td><Input type="text" style="text-align: center; width:90px" value="d" id="beam" enterkeyhint="done"/></td>
}; <tr>
window.addEventListener('resize', js_resizeCanvas, false); <td style="text-align: right;"><b>Target</b></td>
function js_resizeCanvas() { <td><Input type="text" style="text-align: center; width:90px" value="12C" id="target" enterkeyhint="done"/></td>
document.getElementById('canvas').width = window.innerWidth; </tr>
document.getElementById('canvas').height = window.innerHeight; <tr>
} <td style="text-align: right;"><b>Recoil</b></td>
<td><Input type="text" style="text-align: center; width:90px" value="p" id="recoil" enterkeyhint="done"/></td>
</tr>
<tr>
<td style="text-align: right;"><b>Residual</b></td>
<td id='residual' style="text-align: center;">13C</td>
</tr>
<tr>
<td style="text-align: right;"><b>Sp</b></td>
<td id="residualSp" style="text-align: right;"></td>
</tr>
<tr>
<td style="text-align: right;"><b>Sn</b></td>
<td id="residualSn" style="text-align: right;"></td>
</tr>
<tr>
<td style="text-align: right;"><b>Sa</b></td>
<td id="residualSa" style="text-align: right;"></td>
</tr>
<tr>
<td style="text-align: right;"><b>Q-value</b></td>
<td id='Q-value' style="text-align: right;"></td>
</tr>
<tr>
<td></td>
<td><button type="button" onclick="addReaction(this)">Add Reaction</button></td>
</tr>
<tr>
<td></td>
<td><button type="button" onclick="removeRactiion(this)">Rm. Reaction</button></td>
</tr>
</table>
<p id="msg" style="color: red;"> Will add more reactions later </p>
<p></p>
<table>
<tr>
<td style="text-align:right"> <b>Energy :</b></td>
<td><Input type="text" style="width:60px" value="8" id="KEA" enterkeyhint="done"/></td>
<td>MeV/u</td>
<td colspan="6"><Input type="range" min="0" max="20" step="0.05" value="8" id="KEARange"/> </td>
</tr>
<tr>
<td style="text-align:right"> <b>SPS Angle :</b></td>
<td><Input type="text" style="width:60px" value="20" id="angle" enterkeyhint="done"/></td>
<td>degree</td>
<td colspan="6"><Input type="range" min="0" max="90" step="1" value="20" id='angleRange'/> </td>
</tr>
<tr>
<td style="text-align:right"> <b>SPS B-field :</b></td>
<td><Input type="text" style="width:60px" value="0.9" id="BField" enterkeyhint="done"/></td>
<td>T</td>
<td colspan="6"><Input type="range" min="0" max="1" step="0.001" value="0.9" id='BRange'/> </td>
</tr>
</table>
<p></p>
<br>
<input type="checkbox" id="pos" onclick="checkParity()" checked/>Positive parity</td>
<input type="checkbox" id="neg" onclick="checkParity()" checked/>Negative parity</td>
<input type="checkbox" id="unk" onclick="checkParity()" checked/>Unknown parity</td>
<br>
<button type="button" onclick="addStates()">Add known states</button>
Max Ex: <input type="text" id="maxEx" size="5" value="10"/>MeV
<p id='waiting'></p>
<table id="ExTable">
<tr>
<td><b> E<sub>x</sub> [MeV] </b></td>
</tr>
</tr>
<td><input type="text" name="Ex" size="5" value="0"/></td>
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td>
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td>
</tr>
</table>
<p></p>
<button type="button" onclick="PlotAll(this)" style="width: 300px; height: 50px;"> Calculate SPS Kinematics </button>
<p></p>
<table>
<tr>
<td>
<div id="Plot_Kinematics" class="plotStyle" style="width: 400px; height: 400px;"></div>
</td>
<td>
<div id="Plot_SPS" class="plotStyle" style="width: 800px; height: 400px;"></div>
</td>
</tr>
</table>
</body>
<script src="spsSim.js"></script>
</script>
<script async type="text/javascript" src="spsGUI.js"></script>
</body>
</html> </html>

View File

@ -1,161 +0,0 @@
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#define GLFW_INCLUDE_ES3
#include <GLES3/gl3.h>
#include <GLFW/glfw3.h>
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_glfw.h"
#ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS
#define IMPLOT_DISABLE_OBSOLETE_FUNCTIONS
#endif
#include "implot.h"
#include <iostream>
#include <cstring>
#include <vector>
GLFWwindow* g_window;
ImVec4 clear_color = ImVec4(0xCE/255., 0xB8/255., 0x88/255., 1.00f);
int g_width;
int g_height;
// Function used by c++ to get the size of the html canvas
EM_JS(int, canvas_get_width, (), {
return Module.canvas.width;
});
// Function used by c++ to get the size of the html canvas
EM_JS(int, canvas_get_height, (), {
return Module.canvas.height;
});
// Function called by javascript
EM_JS(void, resizeCanvas, (), {
js_resizeCanvas();
});
void on_size_changed(){
glfwSetWindowSize(g_window, g_width, g_height);
ImGui::SetCurrentContext(ImGui::GetCurrentContext());
}
void loop(){
int width = canvas_get_width();
int height = canvas_get_height();
if (width != g_width || height != g_height){
g_width = width;
g_height = height;
on_size_changed();
}
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Debug Window
{
ImGui::SetNextWindowSize(ImVec2(400, 100), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(1000, 100), ImGuiCond_FirstUseEver);
ImGui::Begin("Debug");
ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
ImGui::ColorEdit3("bg color", (float*)&clear_color); // Edit 3 floats representing a color
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
ImGui::Render();
int display_w, display_h;
glfwMakeContextCurrent(g_window);
glfwGetFramebufferSize(g_window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwMakeContextCurrent(g_window);
}
//^ #########################################################
int init_gl(){
if( !glfwInit() ){
fprintf( stderr, "Failed to initialize GLFW\n" );
return 1;
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL
// Open a window and create its OpenGL context
int canvasWidth = g_width;
int canvasHeight = g_height;
g_window = glfwCreateWindow(canvasWidth, canvasHeight, "Woods-Saxon Calculation Demo", NULL, NULL);
if( g_window == NULL ){
fprintf( stderr, "Failed to open GLFW window.\n" );
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(g_window); // Initialize GLEW
return 0;
}
int init_imgui(){
// Setup Dear ImGui binding
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui_ImplGlfw_InitForOpenGL(g_window, true);
ImGui_ImplOpenGL3_Init();
ImPlot::CreateContext();
// Setup style
//ImGui::StyleColorsDark();
ImGui::StyleColorsLight();
ImGuiIO& io = ImGui::GetIO();
resizeCanvas();
return 0;
}
int init(){
init_gl();
init_imgui();
return 0;
}
void quit(){
glfwTerminate();
}
extern "C" int main(int argc, char** argv){
g_width = canvas_get_width();
g_height = canvas_get_height();
if (init() != 0) return 1;
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(loop, 0, 1);
#endif
quit();
return 0;
}

497
spsSim.js Normal file
View File

@ -0,0 +1,497 @@
var beam = [];
var target = [];
var recoil = [];
var residual = [];
var ExB; //excitation energy of residual
var reactionName;
var angle;
var BField;
var parity;
function checkParity(){
parity = 0;
if( document.getElementById('pos').checked == true ) parity += 1;
if( document.getElementById('neg').checked == true ) parity += 2;
if( document.getElementById('unk').checked == true ) parity += 4;
//console.log(parity);
}
function addStates(){
let AZ = residual[3];
let maxEx = document.getElementById('maxEx').value;
checkParity();
let str = 'get_nuclear_data.py?isotopes_name=' + AZ + '&maxEx='+maxEx;
let table = document.getElementById("ExTable");
const client = new XMLHttpRequest();
client.addEventListener('loadstart',
function(e){
document.getElementById('waiting').innerHTML = "wait....retrieving data from IAEA..";
}
);
client.addEventListener('error',
function(e){
document.getElementById('waiting').innerHTML = "Error.";
}
);
client.addEventListener('loadend',
function(e){
let result = client.responseText.split(/\r?\n/);
//clear table
let nRow = table.rows.length;
for( let j = nRow; j > 2; j--){
table.deleteRow(j - 2);
}
document.getElementById('waiting').innerHTML = "";
let count = 0;
for( let i = 0; i < result.length; i++){
if( i < 17 ) continue;
if( result[i] == "</table>" ) break;
let kaka = result[i].split(' ').filter(n => n);
let ex = parseFloat(kaka[3])/1000.;
let jpi = kaka[7]?.replace('(', '')?.replace(')', '');
//console.log(ex + ", " + jpi);
//check parity
if( (((parity >> 2) & 1) != 1) && kaka[7].slice(-1) == ")" ) continue;
if( (((parity >> 2) & 1) != 1) && jpi == "," ) continue;
if( (((parity) & 1) != 1) && jpi.slice(-1) == "+" ) continue;
if( (((parity >> 1) & 1) != 1) && jpi.slice(-1) == "-" ) continue;
count ++;
nRow = table.rows.length;
let row = table.insertRow(nRow-1);
row.innerHTML = '<td><input type="text" name="Ex" size="5" value="' + ex.toFixed(3) + '"/></td> \
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td> \
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td> \
<td>'+ kaka[7] +'</td>';
}
if( count == 0 ){
document.getElementById('waiting').innerHTML = "no states found.";
nRow = table.rows.length;
let row = table.insertRow(nRow-1);
row.innerHTML = '<td><input type="text" name="Ex" size="5" value="0"/></td> \
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td> \
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td>';
}
}
);
client.open('GET', str);
client.send();
}
function addRow(ele) {
let iRow = ele.closest('tr').sectionRowIndex;
let table = document.getElementById("ExTable");
let row = table.insertRow(iRow+1);
row.innerHTML = '<td><input type="text" name="Ex" size="5" /></td> \
<td><button type="button" onclick="addRow(this)">Insert Ex</button></td> \
<td><button type="button" onclick="deleteRow(this)">Remove Ex</button></td>';
}
function deleteRow(ele){
let table = document.getElementById("ExTable");
let nRow = table.rows.length;
let iRow = ele.closest('tr').sectionRowIndex;
if ( nRow > 2){
table.deleteRow(iRow);
}
}
function GetMassData(Name, id){
let str = 'https://fsunuc.physics.fsu.edu/SOLARIS/massProxy.py?AZ=' + Name;
let client = new XMLHttpRequest();
client.onreadystatechange = function() {
let mass = client.responseText.split(",");
if( id == 0 ){ //Beam
beam[0] = parseInt(mass[0]); // A
beam[1] = parseInt(mass[1]); // Z
beam[2] = parseFloat(mass[2]); // mass
beam[3] = Name; // Sym
}
if( id == 1 ){ // target
target[0] = parseInt(mass[0]);
target[1] = parseInt(mass[1]);
target[2] = parseFloat(mass[2]);
target[3] = Name;
target[4] = parseFloat(mass[4]); //Sp
target[5] = parseFloat(mass[5]); //Sn
target[6] = parseFloat(mass[6]); //Sa
}
if( id == 2 ){ // Recoil
recoil[0] = parseInt(mass[0]);
recoil[1] = parseInt(mass[1]);
recoil[2] = parseFloat(mass[2]);
recoil[3] = Name;
}
}
client.open('GET', str, false);
client.send();
}
function GetMassFromAZ(A,Z){
let str = 'https://fsunuc.physics.fsu.edu/SOLARIS/massProxy.py?A=' + A + '&Z=' + Z;
let client = new XMLHttpRequest();
client.onreadystatechange = function() {
let mass = client.responseText.split(",");
residual[2] = parseFloat(mass[2]);
residual[3] = mass[3]?.trim();
residual[4] = parseFloat(mass[4]); //Sp
residual[5] = parseFloat(mass[5]); //Sn
residual[6] = parseFloat(mass[6]); //Sa
}
client.open('GET', str, false);
client.send();
}
function UpdateReaction(){
residual[0] = beam[0] + target[0] - recoil[0];
residual[1] = beam[1] + target[1] - recoil[1];
GetMassFromAZ( residual[0], residual[1]);
var Qvalue = beam[2] + target[2] - recoil[2] - residual[2];
document.getElementById('residual').innerHTML = residual[3];
document.getElementById('residualSp').innerHTML = residual[4].toFixed(3);
document.getElementById('residualSn').innerHTML = residual[5].toFixed(3);
document.getElementById('residualSa').innerHTML = residual[6].toFixed(3);
document.getElementById('Q-value').innerHTML = Qvalue.toFixed(3);
CalTransferConstant();
}
var Etot; // CM frame total energy
var k; //Lab frame momentum of beam
var beta, gamma; // Lorentz boost
var p; // CM frame exist channel momentum
function CalTransferConstant(){
let ma = beam[2];
let mA = target[2];
let KE = parseFloat(document.getElementById('KEA').value) * beam[0];
k = Math.sqrt( Math.pow(ma + KE, 2 ) -ma * ma);
beta = k / (ma + KE + mA);
gamma = 1 / Math.sqrt(1 - beta * beta);
Etot = Math.sqrt(Math.pow(ma + KE + mA,2) - k * k);
reactionName = target[3] + "(" + beam[3] + "," + recoil[3] + ")" + residual[3] + " @ " + KE/beam[0] + " MeV/u";
// console.log("Etot : " + Etot);
// console.log("k : " + k);
// console.log("beta : " + beta);
// console.log("gamma : " + gamma);
// console.log(reactionName);
}
function CalCMMomentum(ExB){
let mb = recoil[2];
let mB = residual[2];
ExB = parseFloat(ExB);
p = Math.sqrt( (Etot*Etot - Math.pow(mb + mB + ExB, 2)) * (Etot*Etot - Math.pow(mb - mB - ExB,2)) ) / 2 / Etot;
// console.log("p : " + p);
}
var ExList = [];
var EnergyLab = [];
var data = [];
function PlotKinematic(){
// plot recoil Lab energy vs Lab angle;
Plotly.purge("Plot_Kinematics");
ExList = Array.from(document.getElementsByName("Ex"));
// for( let i = 0; i < ExList.length; i++){ console.log(ExList[i].value);}
let mb = recoil[2];
//console.log("Plot--------------");
data = [];
for( let i = 0; i < ExList.length; i++){
let yList = []; // lab energy;
let xList = []; // lab angle in degree;
let ExB = parseFloat(ExList[i].value).toFixed(3);
CalCMMomentum(ExB);
// console.log("ExB : " + ExB + ", p : " + p);
for( let thetaCM = 0; thetaCM <= 120; thetaCM ++){
let thetaRad = thetaCM * Math.PI/ 180.;
let EE = gamma * Math.sqrt(mb*mb + p*p) + gamma * beta * p * Math.cos(thetaRad);
let pz = gamma * beta * Math.sqrt(mb*mb + p*p) + gamma * p * Math.cos(thetaRad);
let pxy = p * Math.sin(thetaRad);
let thetaLab = Math.atan2(pxy, pz) * 180. / Math.PI;
xList.push(thetaLab);
yList.push((EE-mb));
}
let newData = {
x : xList,
y : yList,
mode : "lines",
type: "scatter",
name : ("Ex=" + ExB)
}
data.push(newData);
};
let layout = {
xaxis: {range: [0, 90], title: { text : "Angle Lab [degree]", standoff : 1}, mirror : "allticks", linewidth : "1"},
yaxis: {range: [0, 20], title: "Kinematic Energy [MeV]" , mirror : "allticks", linewidth : "1"},
title: reactionName,
dragmode : "pan",
margin: { l: 40, r: 40, b : 60, t : 40},
legend: {yanchor:"bottom", xanchor:"left", x:"0.01",y:"0.01" }
};
Plotly.newPlot( "Plot_Kinematics", data, layout, {responsive: false});
ChangeSPSAnglePlotKinematics();
}
function SearchForRecoilEnergy(){
EnergyLab = [];
angle = parseFloat(document.getElementById("angle").value);
for( let i = 0; i < data.length; i++){
let low = 0, high = 180;
let elow, ehigh;
for(let j = 0; j < data[i].x.length; j++ ){
let thetaLab = data[i].x[j];
let energy = data[i].y[j];
if( angle >= thetaLab && thetaLab > low) {low = thetaLab; elow = energy; }
if( high > thetaLab && thetaLab >= angle) {high = thetaLab; ehigh = energy;}
}
EnergyLab.push((ehigh - elow )/ (high - low) * (angle - low) + elow);
// console.log("angle low : " + low + ", " + elow);
// console.log("angle low : " + high + ", " + ehigh);
// console.log("E : " + EnergyLab);
}
}
function ChangeSPSAnglePlotKinematics(){
angle = parseFloat(document.getElementById("angle").value);
let shapeArray = [
{
type: 'rect',
xref: 'x',
yref: 'paper',
x0 : angle - 0.5,
x1 : angle + 0.5,
y0 : 0,
y1 : 1,
fillcolor : '#782F40',
opacity : 0.5,
line : { width : 0}
}
];
var update = {
'shapes' : shapeArray
}
Plotly.relayout("Plot_Kinematics", update);
SearchForRecoilEnergy();
}
//################################### SPS functions
function recoilRho(KE){
let mass = parseFloat(recoil[2]);
let charge = parseFloat(recoil[1]);
let momt = Math.sqrt( 2*mass*KE + KE*KE );
let field = parseFloat(document.getElementById('BField').value);
return momt/ 299.792458 / charge / field * 100; // unit??
}
function PlotSPS(){
Plotly.purge("Plot_SPS");
let spsData = [];
for(let i = 0; i < EnergyLab.length; i++){
let rho = recoilRho(EnergyLab[i]);
let newData = {
x : [rho, rho],
y : [0, 1],
mode : "lines",
type: "scatter",
name : ("Ex=" + parseFloat(ExList[i].value).toFixed(3))
}
spsData.push(newData);
//console.log(rho);
}
let layout = {
xaxis: {range: [65, 82], title: { text : "rho [cm]", standoff : 1}, mirror : "allticks", linewidth : "1"},
yaxis: {range: [0, 1], title: "state" , mirror : "allticks", linewidth : "1"},
title: reactionName,
dragmode : "pan",
margin: { l: 40, r: 40, b : 60, t : 40},
legend: {yanchor:"top", xanchor:"left", x:"0.01",y:"0.99" }
};
Plotly.newPlot( "Plot_SPS", spsData, layout, {responsive: false});
}
function PlotAll(){
PlotKinematic();
PlotSPS();
}
//######################################## Add reaction
var reactionCount = 1;
function addReaction(){
document.getElementById('msg').innerHTML = "not working yet";
var table = document.getElementById('ReactionTable');
var rowCount = table.rows.length;
if(reactionCount >= 3 ){
document.getElementById('msg').innerHTML = "maximum # of reaction reached.";
return;
}
for (var i = 0; i < rowCount; i++) {
var row = table.rows[i];
var cell = row.insertCell(-1); // -1 means insert at the end
if( i == 0 ) cell.innerHTML = '<Input type="text" style="text-align: center; width:90px" value="d" id="beam1" enterkeyhint="done"/>';
if( i == 1 ) cell.innerHTML = '<Input type="text" style="text-align: center; width:90px" value="12C" id="target1" enterkeyhint="done"/>';
if( i == 2 ) cell.innerHTML = '<Input type="text" style="text-align: center; width:90px" value="p" id="recoil1" enterkeyhint="done"/>';
if( i == 3 ) {
cell.innerHTML = '13C';
cell.style.textAlign = 'center';
}
if( i == 4 ) cell.innerHTML = '4.946';
if( i == 5 ) cell.innerHTML = '17.533';
if( i == 6 ) cell.innerHTML = '10.648';
if( i == 7 ) cell.innerHTML = '2.722';
if( i >= 4) {
cell.style.textAlign = 'right';
}
}
reactionCount ++;
}
function removeRactiion(ele){
document.getElementById('msg').innerHTML = "not working yet";
}
//######################################### when load
GetMassData( document.getElementById('beam').value, 0);
GetMassData( document.getElementById('target').value, 1);
GetMassData( document.getElementById('recoil').value, 2);
UpdateReaction();
PlotAll();
//########################################## UI control
document.getElementById('beam').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
GetMassData( document.getElementById('beam').value, 0);
UpdateReaction();
PlotAll();
}
}, false
);
document.getElementById('target').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
GetMassData( document.getElementById('target').value, 1);
UpdateReaction();
PlotAll();
}
}, false
);
document.getElementById('recoil').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
GetMassData( document.getElementById('recoil').value, 2);
UpdateReaction();
PlotAll();
}
}, false
);
document.getElementById('KEA').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
document.getElementById('KEARange').value = this.value;
CalTransferConstant();
PlotAll();
}
}, false
);
document.getElementById('KEARange').oninput = function(){
document.getElementById('KEA').value = this.value;
CalTransferConstant();
PlotAll();
};
document.getElementById('angle').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
document.getElementById('angleRange').value = this.value;
angle = this.value;
PlotSPS();
}
}, false
);
document.getElementById('angleRange').oninput = function(){
document.getElementById('angle').value = this.value;
angle = this.value;
ChangeSPSAnglePlotKinematics();
PlotSPS();
};
document.getElementById('BField').addEventListener('keypress',
function(e){
if(e.keyCode == 13){
document.getElementById('BRange').value = this.value;
BField - this.value;
ChangeSPSAnglePlotKinematics();
PlotSPS();
}
}, false
);
document.getElementById('BRange').oninput = function(){
document.getElementById('BField').value = this.value;
BField - this.value;
PlotSPS();
};