10
0
mirror of https://github.com/LCPQ/QUESTDB_website.git synced 2024-12-27 06:43:47 +01:00
QUESTDB_website/static/js/data.js

416 lines
12 KiB
JavaScript
Raw Normal View History

class excitationTypes {
static get VALENCE() { return new excitationType(1<< 1, new description("VALENCE")) }
static get RYDBERG() { return new excitationType(1 << 2, new description("RYDBERG")) }
static get PiPis() { return new excitationType(1 << 3, new description(String.raw`\pi \rightarrow \pi^\star`,true)) }
static get nPis() { return new excitationType(1 << 4, new description(String.raw`n \rightarrow \pi^\star`,true)) }
static get Single() { return new excitationType(1 << 5, new description("Single")) }
static get Double() { return new excitationType(1 << 6, new description("Double")) }
static get Singlet() { return new excitationType(1 << 7, new description("Singlet")) }
static get Triplet() { return new excitationType(1 << 8, new description("Triplet")) }
// Max bit shifts is 31 because int are int32 So 1 << 31 are -2147483648
static get Others() { return new excitationType(1 << 31, new description("Others"))}
static get All() { return EnumUltils.getAll(this,excitationType)}
static GetFlags(value){return EnumUltils.GetFlags(value,this,excitationType)}
}
class EnumUltils{
static getAll(enumClass,valueType) {
2020-01-06 14:35:29 +01:00
var lst = []
for (const prop of Object.getOwnPropertyNames(enumClass)) {
2020-01-06 14:35:29 +01:00
if (prop != "All") {
const value = enumClass[prop]
if (trueTypeOf(value) == valueType.name) {
2020-01-06 14:35:29 +01:00
lst.push([prop, value])
}
2020-01-06 14:35:29 +01:00
}
}
return lst
}
static GetFlags(value,enumClass,valueType) {
return this.getAll(enumClass,valueType).filter((x) => { value & x[1] })
}
}
class description {
constructor(string,isLaTeX=false) {
this.string = string
this.isLaTeX=isLaTeX
}
}
class DescribedValueBase {
constructor(value, description) {
2020-01-06 14:35:29 +01:00
this.Value = value;
this.description = description
}
2020-01-06 14:35:29 +01:00
valueOf() {
return this.Value;
}
2019-12-01 18:14:45 +01:00
}
class excitationType extends DescribedValueBase{
}
class VertExcitationKind extends DescribedValueBase{
}
2019-08-28 11:59:18 +02:00
class code {
constructor(name, version) {
this.name = name;
this.version = version;
2019-09-03 15:36:32 +02:00
};
toString() {
var str = this.name;
2019-09-03 15:36:32 +02:00
if (this.version) {
str = str + ' (' + this.version + ')';
2019-09-03 15:36:32 +02:00
}
return str;
2019-08-28 11:59:18 +02:00
}
2019-09-19 15:05:07 +02:00
static fromString(str) {
var vals = str.split(",")
if (vals.length >= 2) {
return new code(vals[0], vals[1]);
2019-09-19 15:05:07 +02:00
} else {
return new code(vals[0], null);
2019-09-19 15:05:07 +02:00
}
}
2019-08-28 11:59:18 +02:00
}
2019-09-17 17:19:00 +02:00
class method {
2020-01-06 14:35:29 +01:00
constructor(name, basis = null) {
this.name = name;
this.basis = basis;
2019-09-03 15:36:32 +02:00
}
2019-09-19 15:05:07 +02:00
static fromString(str) {
var vals = str.split(",")
2019-11-24 19:40:57 +01:00
if (vals.length == 2) {
return new method(vals[0], vals[1]);
}
else {
return new method(vals[0], null)
2019-09-26 09:32:03 +02:00
}
2019-09-19 15:05:07 +02:00
}
toString(separator="/") {
var str = this.name;
2019-09-28 14:38:14 +02:00
if (this.basis) {
str = str + separator + this.basis;
2019-09-03 15:36:32 +02:00
}
return str;
2019-08-22 10:34:07 +02:00
}
2020-01-06 14:35:29 +01:00
get isTBE() {
2020-01-03 17:12:43 +01:00
return /^TBE/.test(this.name)
}
2020-01-14 18:03:17 +01:00
get isCorrectedTBE() {
return this.name="TBE"
2020-01-03 17:12:43 +01:00
}
2019-08-22 10:34:07 +02:00
}
class state {
constructor(number, multiplicity, symetry) {
this.number = number;
this.multiplicity = multiplicity;
this.symetry = symetry;
2019-09-03 15:36:32 +02:00
};
toString() {
var str = this.number + ' ^' + this.multiplicity + this.symetry;
2019-09-03 15:36:32 +02:00
return str;
};
toLaTeX() {
2019-11-12 15:27:53 +01:00
var tex = String.raw`${this.number}\:^{${this.multiplicity}}\mathrm{${this.symetry}}`;
2019-09-03 15:36:32 +02:00
return tex;
};
2019-08-22 10:34:07 +02:00
}
2019-11-02 15:10:57 +01:00
class DOI {
2020-01-08 11:02:15 +01:00
constructor(doistring,IsSupporting=false) {
this.string = doistring
2020-01-08 11:02:15 +01:00
this.IsSupporting = IsSupporting
2019-09-03 15:36:32 +02:00
};
2020-01-08 11:02:15 +01:00
static fromString(str){
const vals=str.split(",")
2020-01-08 15:48:35 +01:00
if (vals.length==1) {
2020-01-08 11:02:15 +01:00
return new DOI(vals[0].toString())
}
else{
2020-01-08 15:48:35 +01:00
return new DOI(vals[0].toString(),(true ? vals[1]=== true.toString() : false))
2020-01-08 11:02:15 +01:00
}
}
toString() {
2020-01-08 11:02:15 +01:00
var str=this.string;
if (this.IsSupporting) {
str+=" "+"(SI)"
}
return str
2019-09-03 15:36:32 +02:00
};
2019-08-28 11:59:18 +02:00
get url() {
2020-01-06 14:35:29 +01:00
return new URL(this.string, 'https://doi.org').toString()
2019-12-10 15:15:46 +01:00
}
2019-08-28 11:59:18 +02:00
}
2019-09-26 09:32:03 +02:00
class excitationBase {
2020-01-06 14:35:29 +01:00
constructor(initial, final, type = '', T1 = null) {
this.initial = initial;
this.final = final
this.type = new excitationType(0, new description(type,true))
2020-01-03 17:12:43 +01:00
if (type !== "") {
2019-12-10 13:55:32 +01:00
const tys = type.split(";")
const arrow = String.raw`\rightarrow`
for (const ty of tys) {
if (ty.includes(arrow)) {
const [initialt, finalt] = ty.split(arrow, 2)
2020-01-06 14:35:29 +01:00
const initialts = initialt.split(",").map(x => x.trim())
const finalts = finalt.split(",").map(x => x.trim())
2020-01-08 16:30:55 +01:00
if (initialts.length == 2 && finalts.length == 2) {
2020-01-06 14:35:29 +01:00
this.type.Value = this.type | excitationTypes.Double
2019-12-03 11:32:14 +01:00
}
2020-01-14 14:20:43 +01:00
else if (initialts.length == 1 && finalts.length == 1) {
2020-01-06 14:35:29 +01:00
this.type.Value = this.type | excitationTypes.Single
2019-12-03 11:32:14 +01:00
}
if (initialts.includes("n") && finalts.includes(String.raw`\pi^\star`)) {
2020-01-06 14:35:29 +01:00
this.type.Value = this.type | excitationTypes.nPis
2020-01-07 09:28:41 +01:00
} else if (initialts.includes(String.raw`\pi`) && finalts.includes(String.raw`\pi^\star`)) {
2020-01-06 14:35:29 +01:00
this.type.Value = this.type | excitationTypes.PiPis
2019-12-01 18:14:45 +01:00
}
2020-01-06 14:35:29 +01:00
} else if (ty.includes(String.raw`\mathrm{R}`)) {
this.type.Value = this.type | excitationTypes.RYDBERG
} else if (ty.includes(String.raw`\mathrm{V}`)) {
this.type.Value = this.type | excitationTypes.VALENCE
2019-12-01 18:14:45 +01:00
}
}
}
switch (final.multiplicity) {
case 1:
2020-01-13 14:48:26 +01:00
this.type.Value=this.type|excitationTypes.Singlet
break;
case 3:
this.type.Value=this.type|excitationTypes.Triplet
break;
}
2020-01-07 09:37:32 +01:00
if (this.type.Value==0) {
this.type.Value=excitationTypes.Others.Value;
2020-01-06 21:03:06 +01:00
}
2019-12-01 18:14:45 +01:00
this.T1 = T1
2019-09-26 09:32:03 +02:00
}
}
class excitationValue extends excitationBase {
2020-01-06 14:35:29 +01:00
constructor(initial, final, type, value, oscilatorForces = null, T1 = null, isUnsafe = false) {
2019-12-10 13:55:32 +01:00
super(initial, final, type, T1)
this.value = value
2019-11-25 14:49:40 +01:00
this.oscilatorForces = oscilatorForces
2019-12-17 09:59:57 +01:00
this.isUnsafe = isUnsafe
2019-11-20 20:15:53 +01:00
}
}
class excitation extends excitationBase {
constructor(initial, final, Eabs, Efluo, EZPE) {
super(initial, final)
this.Eabs = Eabs
this.Efluo = Efluo
this.EZPE = EZPE
2019-09-19 15:05:07 +02:00
}
2019-09-19 18:54:23 +02:00
get Eadia() {
return (this.Eabs + this.Efluo) / 2
}
2019-09-19 15:05:07 +02:00
get Ezz() {
return this.Eadia - this.EZPE
2019-08-28 11:59:18 +02:00
}
2019-09-03 15:36:32 +02:00
toString() {
return this.start + ', ' + this.end + ', ' + noNanPrecision(this.Eabs, 3);
2019-09-03 15:36:32 +02:00
}
2019-08-28 11:59:18 +02:00
}
2019-09-26 09:32:03 +02:00
class dataFileBase {
constructor() {
this.molecule = ''
this.comment = ""
this.code = null
this.method = null
this.excitations = []
this.DOI = null
2020-01-06 14:35:29 +01:00
this.sourceFile = null
2019-08-28 11:59:18 +02:00
}
static _GetMetaRexEx() {
//metadata RegExp (start with #; maybe somme spaces; : ; maybe somme space; datas)
return /^#\s*([A-Za-z_]+)\s*:\s*(.*)$/;
}
2020-01-15 13:10:21 +01:00
CopyExcitationsTypeFrom(data) {
for (const ex of this.excitations) {
const ex2=data.excitations.find((e)=>{
return (JSON.stringify(e.initial)===JSON.stringify(ex.initial)) && (JSON.stringify(e.final)===JSON.stringify(ex.final))
})
if(ex2!==undefined){
ex.type=ex2.type
}
}
}
static async loadAsync(file,kind=undefined) {
2019-10-02 19:20:37 +02:00
switch (trueTypeOf(file)) {
case String.name:
2020-01-06 14:35:29 +01:00
file = getFullDataPath(file)
var str = await getTextFromFileUrlAsync(file)
2019-10-02 19:20:37 +02:00
break;
case File.name:
2020-01-06 14:35:29 +01:00
var str = await getTextFromUploadedFileAsync(file)
2019-10-02 19:20:37 +02:00
break
}
var dat = this.loadString(str,kind);
2020-01-06 14:35:29 +01:00
dat.sourceFile = new websiteFile(file)
2019-09-30 10:53:13 +02:00
return dat
2019-09-26 09:32:03 +02:00
}
_OnReadMetaPair(key, value) {
switch (key) {
2019-09-26 09:32:03 +02:00
case "molecule":
this.molecule = value
2019-09-26 09:32:03 +02:00
break;
case "comment":
this.comment = value
2019-09-26 09:32:03 +02:00
break;
case "code":
this.code = code.fromString(value)
2019-09-26 09:32:03 +02:00
break;
case "method":
this.method = method.fromString(value)
break;
2019-09-26 09:32:03 +02:00
case "doi":
this.DOI = DOI.fromString(value);
2019-09-26 09:32:03 +02:00
break;
default:
}
2019-08-28 11:59:18 +02:00
}
_OnReadRow(line) {
var vals = line.match(/\([^\)]+\)|\S+/g)
var start = new state(parseInt(vals[0], 10), parseInt(vals[1], 10), vals[2]);
var end = new state(parseInt(vals[3], 10), parseInt(vals[4],10), vals[5]);
var hasType = vals.length >= 7 && isNaN(vals[6])
var type = ((vals.length >= 7 && hasType) ? vals[6] : null)
if (type) {
const m = type.match(/^\(([^\)]*)\)$/)
if (m) {
type = m[1]
2019-08-28 11:59:18 +02:00
}
}
2020-02-04 09:14:57 +01:00
var val = ((vals.length >= 7 + hasType) ? new stringNumber(vals[6 + hasType]) : NaN)
var oscilatorForces = ((vals.length >= 8 + hasType) ? new stringNumber(vals[7 + hasType]) : NaN)
var T1 = ((vals.length >= 9 + hasType) ? new stringNumber(vals[8 + hasType]) : NaN)
var isUnsafe = ((vals.length >= 10 + hasType) ? vals[9 + hasType] === true.toString() : false)
var ex = new excitationValue(start, end, type, val, oscilatorForces, T1, isUnsafe);
if (this.VertExcitationKind) {
ex.VertExcitationKind=this.VertExcitationKind
}
return ex;
};
_OnReadMeta(line) {
// get key value
var match = line.match(dataFileBase._GetMetaRexEx())
// normalize key to lower
var key = match[1].toLowerCase()
//if data has value
if (match.length == 3 && match[2]) {
var val = match[2]
this._OnReadMetaPair(key,val)
}
}
static loadString(text,kind=null) {
// for each line with metadata
var ismetaArea = true;
var dat = new VertDataFile()
for (var line of text.split("\n")) {
2019-08-28 11:59:18 +02:00
//if it's not empty line
line = line.trim();
if (line) {
2019-08-28 11:59:18 +02:00
//if # may be metadata or comment
if (line.charAt(0) == "#") {
2019-08-28 11:59:18 +02:00
//if it's metadata
if (ismetaArea && dataFileBase._GetMetaRexEx().test(line)) {
dat._OnReadMeta(line);
}
2019-08-28 11:59:18 +02:00
} else { //else its row
ismetaArea = false;
dat.excitations.push(dat._OnReadRow(line,kind));
2019-08-28 11:59:18 +02:00
}
}
}
2019-08-28 11:59:18 +02:00
return dat
}
2019-08-22 10:34:07 +02:00
}
class VertExcitationKinds{
static get Absorbtion() {return new VertExcitationKind(1, new description("Absorption"))}
static get Fluorescence() {return new VertExcitationKind(1<<1, new description("Fluorescence"))}
static get All() { return EnumUltils.getAll(this,VertExcitationKind)}
static GetFlags(value){return EnumUltils.GetFlags(value,this,VertExcitationKind)}
}
class VertDataFile extends dataFileBase {
constructor(VertExcitationKind) {
2019-09-26 09:32:03 +02:00
super()
this.VertExcitationKind=VertExcitationKind
this.geometry = null
2019-09-26 09:32:03 +02:00
}
_OnReadMetaPair(key, value) {
if (key == "geom") {
this.geometry = method.fromString(value)
2019-09-26 09:32:03 +02:00
}
else {
super._OnReadMetaPair(key, value)
2019-09-26 09:32:03 +02:00
}
}
_OnReadRow(line,kind) {
var ex=super._OnReadRow(line)
ex.VertExcitationKind=kind
return ex
2019-09-26 09:32:03 +02:00
}
}
class CombinedData {
constructor() {
this.Abs = null
this.Fluo = null
this.ZPE = null
2019-09-26 09:32:03 +02:00
}
get excitations() {
var exs = []
var dic = new Map()
if (this.Abs != null) {
for (const el of this.Abs.excitations) {
var key = JSON.stringify([el.initial, el.final])
if (!dic.has(key)) {
dic.set(key, {})
2019-09-26 09:32:03 +02:00
}
dic.get(key)["abs"] = el.value
}
if (this.Fluo != null) {
for (const el of this.Fluo.excitations) {
var key = JSON.stringify([el.initial, el.final])
if (!dic.has(key)) {
dic.set(key, {})
}
dic.get(key)["fluo"] = el.value
2019-09-26 09:32:03 +02:00
}
}
if (this.ZPE != null) {
for (const el of this.ZPE.excitations) {
var key = JSON.stringify([el.initial, el.final])
if (!dic.has(key)) {
dic.set(key, {})
}
dic.get(key)["ZPE"] = el.value
}
}
dic.forEach((value, key) => {
var eabs = NaN
var efluo = NaN
var eZPE = NaN
var mykey = JSON.parse(key)
for (var el of mykey) {
Reflect.setPrototypeOf(el, state.prototype)
}
if ("abs" in value) {
eabs = value["abs"]
}
if ("fluo" in value) {
efluo = value["fluo"]
}
if ("ZPE" in value) {
eZPE = value["ZPE"]
2019-09-26 09:32:03 +02:00
}
exs.push(new excitation(mykey[0], mykey[1], eabs, efluo, eZPE))
2019-09-26 09:32:03 +02:00
})
return exs
2019-09-26 09:32:03 +02:00
}
}
2019-09-26 09:32:03 +02:00
}