mirror of
https://github.com/LCPQ/QUESTDB_website.git
synced 2024-08-26 14:11:51 +02:00
513 lines
17 KiB
HTML
513 lines
17 KiB
HTML
---
|
|
title: "Multiple dataset"
|
|
date: 2019-09-27 16:41
|
|
draft: false
|
|
---
|
|
<link rel="stylesheet" type="text/css" href="/css/modal.css" />
|
|
<link rel="stylesheet" type="text/css" href="/css/form.css" />
|
|
<link rel="stylesheet" type="text/css" href="/css/table.css" />
|
|
<link rel="stylesheet" type="text/css" href="/css/color-emoji-font.css" />
|
|
<script src="/js/data.js" type="text/javascript"></script>
|
|
<script src="/js/loadAllData.js" type="text/javascript"></script>
|
|
<script src="/js/getFullDataPath.js" type="text/javascript"></script>
|
|
<script src="/js/getTextFromFile.js" type="text/javascript"></script>
|
|
<script src="/js/trueTypeOf.js" type="text/javascript"></script>
|
|
<script src="/js/uniq.js"></script>
|
|
<script src="/js/processingIndicator.js"></script>
|
|
<script src="/js/noNan.js"></script>
|
|
<script src="/js/websiteFile.js"></script>
|
|
<script src="/js/getSets.js"></script>
|
|
<script src="https://cdn.rawgit.com/larsgw/citation.js/archive/citation.js/citation-0.4.0-9.js"
|
|
type="text/javascript"></script>
|
|
<script src="/js/DOICache.js"></script>
|
|
<script src="/js/nestedCheckbox.js"></script>
|
|
<script src="https://unpkg.com/simple-statistics@7.0.2/dist/simple-statistics.min.js"></script>
|
|
<script>
|
|
window.onload = async () => {
|
|
const LatexInline = ['\\(', '\\)']
|
|
var cbextl = $("#cb_exTypeList")
|
|
var allc = $("#AllowList>li:last-child")
|
|
for (const [name, value] of excitationTypes.All) {
|
|
var description = null
|
|
switch (Number(value)) {
|
|
case Number(excitationTypes.VALENCE):
|
|
description = name.toLowerCase()
|
|
break;
|
|
case Number(excitationTypes.RYDBERG):
|
|
const word = name
|
|
description = word.charAt(0).toUpperCase() + word.substring(1).toLowerCase()
|
|
break;
|
|
case Number(excitationTypes.Single):
|
|
description = name.toLowerCase()
|
|
break;
|
|
case Number(excitationTypes.Double):
|
|
description = name.toLowerCase()
|
|
break;
|
|
case Number(excitationTypes.Singulet):
|
|
description = name.toLowerCase()
|
|
break;
|
|
case Number(excitationTypes.Triplet):
|
|
description = name.toLowerCase()
|
|
break;
|
|
default:
|
|
description = null;
|
|
break;
|
|
}
|
|
$("<li/>").text(LatexInline[0] + value.LaTeX + LatexInline[1] + (description == null ? '' : ": " + description)).insertBefore(allc)
|
|
var cbli = $("<li/>")
|
|
$("<input/>", { type: "checkbox", id: "cb_" + name, name: name, value: Number(value) }).change(nestedCheckbox_change).appendTo(cbli);
|
|
$('<label />', { 'for': 'cb_' + name, text: LatexInline[0] + value.LaTeX + LatexInline[1] + (description == null ? '' : ": " + description) }).appendTo(cbli);
|
|
cbextl.append(cbli);
|
|
}
|
|
await MathJax.typesetPromise();
|
|
delete (cbextl)
|
|
delete (allc)
|
|
window.doiCache = new DOICache()
|
|
$('#form_dat > fieldset > input[type=radio]').on('change', async function (event) {
|
|
processingIndicator.isActive = true
|
|
$("#Geom_th,#GSGeom_th,#ESGeom_th").each(function () {
|
|
$(this).attr("hidden", true)
|
|
})
|
|
var result = $(this).val();
|
|
var proms = [];
|
|
switch (result) {
|
|
case "abs":
|
|
proms = getAbsFilesName().map((f) => AbsDataFile.loadAsync(f));
|
|
$("#Geom_th").attr("hidden", false)
|
|
break;
|
|
case "fluo":
|
|
proms = getFluoFilesName().map((f) => FluoDataFile.loadAsync(f));
|
|
$("#Geom_th").attr("hidden", false)
|
|
break;
|
|
case "zpe":
|
|
proms = getZPEFilesName().map((f) => ZPEDataFile.loadAsync(f));
|
|
$("#GSGeom_th,#ESGeom_th").each(function () {
|
|
$(this).attr("hidden", false)
|
|
})
|
|
break;
|
|
}
|
|
window.dats = await Promise.all(proms)
|
|
processingIndicator.isActive = false
|
|
reloadFileSelector()
|
|
await reloadSelect()
|
|
})
|
|
}
|
|
function reloadFileSelector() {
|
|
$("#customFiles_input").attr("value", "").attr("disabled", false)
|
|
}
|
|
|
|
async function reloadSelect() {
|
|
processingIndicator.isActive = true
|
|
radioval = $('#form_dat > fieldset > input[name=datatype]:checked').val();
|
|
const files = $("#customFiles_input")[0].files
|
|
for (file of [...files]) {
|
|
switch (radioval) {
|
|
case "abs":
|
|
var dat = await AbsDataFile.loadAsync(file)
|
|
window.dats.push(dat)
|
|
break;
|
|
case "fluo":
|
|
dat = await FluoDataFile.loadAsync(file)
|
|
window.dats.push(dat)
|
|
break;
|
|
case "ZPE":
|
|
dat = await ZPEDataFile.loadAsync(file)
|
|
window.dats.push(dat)
|
|
break;
|
|
}
|
|
}
|
|
$('#form_dat > fieldset > div > select,#sel_ref').each(function () {
|
|
$(this).empty()
|
|
})
|
|
$('#form_dat > fieldset > div > select').each(async function () {
|
|
const vals = uniq(window.dats.map((d) => {
|
|
switch ($(this).attr("name")) {
|
|
case "method":
|
|
return d.method.name
|
|
break;
|
|
case "basis":
|
|
return d.method.basis
|
|
default:
|
|
return d[$(this).attr("name")]
|
|
break;
|
|
}
|
|
}))
|
|
var sets = await getSets()
|
|
for (const val of vals) {
|
|
if(val!==null) {
|
|
var op = $("<option/>", {
|
|
value: JSON.stringify(val)
|
|
})
|
|
if ($(this).attr("name") == "DOI") {
|
|
if (sets.has(val.string)) {
|
|
str=sets.get(val.string)
|
|
if(val.IsSupporting){
|
|
str+=" (SI)"
|
|
}
|
|
}
|
|
else{
|
|
str=val.toString()
|
|
}
|
|
$(op).text(str)
|
|
}
|
|
else {
|
|
$(op).text(val.toString())
|
|
}
|
|
op.appendTo(this)
|
|
}
|
|
}
|
|
})
|
|
$('#form_dat > input[type="submit"').prop('disabled', false);
|
|
processingIndicator.isActive = false
|
|
await reloadContent()
|
|
}
|
|
async function reloadStat() {
|
|
processingIndicator.isActive = true
|
|
var stb = $("#stat_table > tbody")
|
|
$("#graph_div").empty()
|
|
$(stb).empty()
|
|
var refstr = $("#sel_ref option:selected").val()
|
|
var sdatdic = new Map()
|
|
for (const d of window.filtData) {
|
|
const key = JSON.stringify([d.code, d.method, d.DOI.string])
|
|
if (!(sdatdic.has(key))) {
|
|
sdatdic.set(key, new Map())
|
|
}
|
|
for (const exc of d.excitations) {
|
|
const key2 = JSON.stringify([d.molecule, exc.initial, exc.final])
|
|
const keydic = sdatdic.get(key)
|
|
if ((!exc.isUnsafe || window.filterParams[0]) && ((exc.type & window.filterParams[1])!==0)) {
|
|
if (!(keydic.has(key2))) {
|
|
keydic.set(key2, [])
|
|
}
|
|
keydic.get(key2).push(exc.value)
|
|
}
|
|
}
|
|
}
|
|
var sdic = new Map()
|
|
for (const [key, sdat] of sdatdic) {
|
|
for (const [key2, exval] of sdat) {
|
|
if (!(sdic.has(key))) {
|
|
sdic.set(key, [])
|
|
}
|
|
sdic.get(key).push(exval - ((sdatdic.has(refstr)) ? sdatdic.get(refstr).get(key2) : NaN))
|
|
}
|
|
}
|
|
sdic.delete(refstr)
|
|
var graphdat = []
|
|
for (const [keystr, vals] of sdic) {
|
|
row = $("<tr/>")
|
|
key = JSON.parse(keystr)
|
|
key.shift()
|
|
Reflect.setPrototypeOf(key[0], method.prototype)
|
|
//Reflect.setPrototypeOf(key[1], DOI.prototype)
|
|
for (const [i,el] of key.entries()) {
|
|
var td = $("<td/>")
|
|
if (i===1) {
|
|
var publi = doiCache.get(el, true)
|
|
const sets = await getSets()
|
|
if (sets.has(el)) {
|
|
var str=sets.get(el)
|
|
$(td).append(str)
|
|
}
|
|
$("<a/>", {
|
|
href: new DOI(el).url,
|
|
target: "_blank"
|
|
}).html(publi.format('citation', {
|
|
format: 'html',
|
|
lang: 'en-US'
|
|
})).appendTo(td)
|
|
}
|
|
else {
|
|
$(td).text(el)
|
|
}
|
|
$(row).append(td)
|
|
}
|
|
const noNanVals = (vals.every((v) => Number.isNaN(v))) ? vals : (vals.filter((v) => !Number.isNaN(v)))
|
|
const avals = noNanVals.map(v => Math.abs(v))
|
|
for (const val of [ss.min(noNanVals), ss.max(noNanVals), ss.mean(noNanVals), ss.mean(avals), ss.median(noNanVals), ss.median(avals), ss.rootMeanSquare(noNanVals), ss.variance(noNanVals), ss.standardDeviation(noNanVals)]) {
|
|
$("<td/>").text(noNanPrecision(val, 3)).appendTo(row)
|
|
}
|
|
$(stb).append(row)
|
|
var box = {
|
|
x: noNanVals,
|
|
amean: ss.mean(avals).toFixed(3),
|
|
name: key[0].toString() + " MAD : " + ss.mean(avals).toPrecision(4),
|
|
type: 'box',
|
|
boxmean: 'sd'
|
|
};
|
|
graphdat.push(box)
|
|
}
|
|
var layout = {
|
|
paper_bgcolor: 'rgba(0,0,0,0)',
|
|
plot_bgcolor: 'rgba(0,0,0,0)',
|
|
gap: 0,
|
|
legend: {
|
|
traceorder: 'reversed',
|
|
},
|
|
xaxis: {
|
|
title: {
|
|
text: 'Energy (eV)',
|
|
}
|
|
},
|
|
bgcolor: '#E2E2E2',
|
|
bordercolor: '#FFFFFF',
|
|
borderwidth: 2,
|
|
// autosize: false,
|
|
width: 850,
|
|
height: 500,
|
|
margin: {
|
|
l: 0,
|
|
r: 10,
|
|
b: 15,
|
|
t: 20,
|
|
pad: 0,
|
|
},
|
|
}
|
|
Plotly.newPlot('graph_div', graphdat, layout);
|
|
processingIndicator.isActive = false
|
|
}
|
|
async function reloadContent() {
|
|
window.filterParams = [$("#cb_unsafe").prop("checked"), Array.from(Array.from($("#cb_exTypeList>li>input[type=checkbox]:checked")).map(el => parseInt(el.value))).reduce((pv, cv) => pv + cv, 0)]
|
|
doiCache.clear()
|
|
processingIndicator.isActive = true
|
|
const LatexInline = ['\\(', '\\)']
|
|
window.filtData = window.dats
|
|
$('#form_dat > fieldset > div > select').each(function () {
|
|
const prop = $(this).attr("name")
|
|
const values = $(this).val()
|
|
window.filtData = window.filtData.filter((d) => {
|
|
if (typeof values == "undefined" || values == null) {
|
|
return false
|
|
}
|
|
var val=null
|
|
switch (prop) {
|
|
case "method":
|
|
val=d.method.name
|
|
break;
|
|
case "basis":
|
|
val=d.method.basis
|
|
break;
|
|
default:
|
|
val=d[prop]
|
|
break;
|
|
}
|
|
return values.includes(JSON.stringify(val))
|
|
delete(val)
|
|
})
|
|
})
|
|
await window.doiCache.addRange(window.filtData.map((d) => d.DOI.string))
|
|
$(sel_ref).empty()
|
|
for (const el of uniq(window.filtData.map(d => [d.code, d.method, d.DOI.string]))) {
|
|
op = $("<option/>", {
|
|
value: JSON.stringify(el)
|
|
}).text(el[1])
|
|
if (el[1].name.includes("TBE")) {
|
|
$(sel_ref).prepend(op)
|
|
}
|
|
else {
|
|
$(sel_ref).append(op)
|
|
}
|
|
}
|
|
$(sel_ref).prop("selectedIndex", 0);
|
|
var data = $("#data")
|
|
$(data).empty();
|
|
if (window.filtData.length > 0) {
|
|
var sets = await getSets()
|
|
for (const doi of doiCache.keys()) {
|
|
paperdata = window.filtData.filter((d) => {
|
|
return d.DOI.string == doi
|
|
})
|
|
var methods = uniq(paperdata.map(d => d.method))
|
|
const sortedMethods = methods.sort((a, b) => {
|
|
if (a.isTBE && !b.isTBE) {
|
|
return -1
|
|
}
|
|
else if (a.isTBE && b.isTBE) {
|
|
if (!a.isCorrected && b.isCorrected) {
|
|
return -1
|
|
}
|
|
else {
|
|
return 1
|
|
}
|
|
}
|
|
else if (!a.isTBE && b.isTBE) {
|
|
return 1
|
|
}
|
|
else {
|
|
return 0
|
|
}
|
|
})
|
|
var div = $('<div/>').appendTo(data)
|
|
$("<h1/>").text(sets.get(doi)).appendTo(div)
|
|
var table = $("<table/>").addClass("datatable").appendTo(div)
|
|
var head = $("<tr/>")
|
|
$("<thead/>").append(head).appendTo(table)
|
|
var tbody = $("<tbody/>").appendTo(table)
|
|
head.append(["Molecule", "Transition"].map(x => $("<th/>").text(x)))
|
|
head.append(sortedMethods.map(x => $("<th/>").text(x.toString())))
|
|
datadic = new Map()
|
|
for (const dat of paperdata) {
|
|
const key1 = dat.molecule;
|
|
if (!datadic.has(key1)) {
|
|
datadic.set(key1, new Map())
|
|
}
|
|
const key3 = JSON.stringify(dat.method)
|
|
for (const ex of dat.excitations) {
|
|
Reflect.setPrototypeOf(ex.type,excitationType.prototype)
|
|
if ((window.filterParams[1] & ex.type)!==0) {
|
|
const key2 = JSON.stringify([ex.initial, ex.final, ex.type])
|
|
if (!datadic.get(key1).has(key2)) {
|
|
datadic.get(key1).set(key2, new Map())
|
|
}
|
|
datadic.get(key1).get(key2).set(key3, [ex.value, ex.isUnsafe])
|
|
}
|
|
}
|
|
}
|
|
for (const [molecule, moldat] of datadic.entries()) {
|
|
var printmol = true;
|
|
for (const [jsonex, exdat] of moldat.entries()) {
|
|
const ex = JSON.parse(jsonex)
|
|
Reflect.setPrototypeOf(ex[0], state.prototype)
|
|
Reflect.setPrototypeOf(ex[1], state.prototype)
|
|
Reflect.setPrototypeOf(ex[2], excitationType.prototype)
|
|
var tr = $("<tr/>")
|
|
var tdmol = $("<td/>")
|
|
if (printmol) {
|
|
$(tdmol).text(molecule)
|
|
printmol = false
|
|
}
|
|
tr.append(tdmol)
|
|
$("<td/>").text(String.raw`${LatexInline[0]}${ex[0].toLaTeX()} \rightarrow ${ex[1].toLaTeX()} (${ex[2].LaTeX}) ${LatexInline[1]}`).appendTo(tr)
|
|
var entries = Array.from(exdat.entries())
|
|
for (const method of sortedMethods) {
|
|
td = $("<td/>")
|
|
kv = entries.find(x => {
|
|
return JSON.stringify(method) == x[0]
|
|
})
|
|
if (kv !== undefined) {
|
|
const [val, unsafe] = kv[1]
|
|
if (unsafe) {
|
|
td.append($("<div/>", { title: "unsafe value", style: "float: left; font-family: color-emoji;" }).text('⚠'))
|
|
}
|
|
if (unsafe && !$("#cb_unsafe").is(':checked')) {
|
|
td.append($("<s/>").append(val))
|
|
}
|
|
else {
|
|
td.append(val)
|
|
}
|
|
}
|
|
tr.append(td)
|
|
}
|
|
tbody.append(tr)
|
|
}
|
|
}
|
|
}
|
|
await MathJax.typesetPromise()
|
|
}
|
|
await reloadStat()
|
|
}
|
|
async function submitdat(){
|
|
window.onbeforeunload = () => {return '';}
|
|
await reloadContent();
|
|
}
|
|
</script>
|
|
{{< getDataFilesName >}}
|
|
<p>
|
|
In this page you can compare multiple dataset and have somme statistics to evaluate method or basis accuracy.
|
|
For this follow this steps
|
|
<ol>
|
|
<li>Select a value type (Absorption, fluorescence or \(\Delta \text{ZPE}\))</li>
|
|
<li>You can add custom files if you want</li>
|
|
<li>Choose each parameters (of course you can select multiples values for each)</li>
|
|
<ul>
|
|
<li>Molecule</li>
|
|
<li>Method</li>
|
|
<li>Publication</li>
|
|
<li>Allow:</li>
|
|
<ul id="AllowList">
|
|
<li>Unsafe</li>
|
|
</ul>
|
|
</ul>
|
|
<li>Select a reference from <strong>already selected data</strong> (by default first is selected -it's the <abbr
|
|
title="Theoretical best estimate">TBE</abbr> if present- is already selected)</li>
|
|
<li>Now you can see the list of selected data and some statistics about these data</li>
|
|
</ol>
|
|
</p>
|
|
<form id="form_dat" action="javascript:submitdat()" method="post">
|
|
<fieldset>
|
|
<legend>Data type</legend>
|
|
<input type="radio" id="abs" value="abs" name="datatype">
|
|
<label for="abs">Absorption</label>
|
|
<input type="radio" id="fluo" value="fluo" name="datatype">
|
|
<label for="fluo">Fluorescence</label>
|
|
<input type="radio" id="zpe" value="zpe" name="datatype">
|
|
<label for="zpe">\(\Delta \text{ZPE}\)</label>
|
|
</fieldset>
|
|
<fieldset>
|
|
<div>
|
|
<label for="customFiles_input">Add custom data file</label>
|
|
<input type="file" multiple onchange="reloadSelect()" id="customFiles_input" disabled=true></input>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset class="table">
|
|
<div>
|
|
<label for="mol_select">Molecule</label>
|
|
<select multiple id="mol_select" name="molecule"></select>
|
|
</div>
|
|
<div>
|
|
<label for="method_select">Method</label>
|
|
<select multiple id="method_select" name="method"></select>
|
|
</div>
|
|
<div>
|
|
<label for="basis_select">Basis</label>
|
|
<select multiple id="basis_select" name="basis"></select>
|
|
</div>
|
|
<div>
|
|
<label for="DOI_select">Publication</label>
|
|
<select multiple id="DOI_select" name="DOI"></select>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset id="excitationFilter">
|
|
<legend>Filters</legend>
|
|
<ul class="nestedCbList" style="padding-left: 0em;">
|
|
<li>
|
|
<input type="checkbox" onchange="nestedCheckbox_change(event)" id="cb_exType_All"></input>
|
|
<label for="cb_exType_All"> All</label>
|
|
</li>
|
|
<ul id="cb_exTypeList" class="nestedCbList">
|
|
</ul>
|
|
<li id="li_cb_unsafe">
|
|
<input type="checkbox" id="cb_unsafe" name="unsafe">
|
|
<label for="cb_unsafe">Unsafe</label>
|
|
</li>
|
|
</fieldset>
|
|
<input type="submit" disabled=true value="Load"></input>
|
|
</form>
|
|
<form id="form_ref">
|
|
<label for="sel_ref">Reference</label>
|
|
<select id="sel_ref" onchange="reloadStat()"></select>
|
|
</form>
|
|
<section id="data">
|
|
</section>
|
|
<section>
|
|
<table id="stat_table" class="datatable">
|
|
<thead>
|
|
<th>Method</th>
|
|
<th>Publication</th>
|
|
<th>Min</th>
|
|
<th>Max</th>
|
|
<th>Mean</th>
|
|
<th>Absolute Mean</th>
|
|
<th>Median</th>
|
|
<th>Absolute Median</th>
|
|
<th>RMS</th>
|
|
<th>Variance</th>
|
|
<th>Standard deviation</th>
|
|
</thead>
|
|
<tbody>
|
|
</tbody>
|
|
<div id="graph_div"></div>
|
|
</table>
|
|
</section>
|
|
{{< waitModal >}} |