@mat3ra/mode 2025.11.3-0 → 2025.11.5-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/package.json +32 -17
  2. package/src/js/default_methods.ts +36 -0
  3. package/src/js/default_models.ts +11 -0
  4. package/src/js/generated/MethodSchemaMixin.ts +26 -0
  5. package/src/js/generated/ModelSchemaMixin.ts +23 -0
  6. package/src/{index.js → js/index.ts} +1 -1
  7. package/src/js/method.ts +67 -0
  8. package/src/js/methodConversionHandler.ts +142 -0
  9. package/src/{methods/factory.js → js/methods/factory.ts} +3 -1
  10. package/src/js/methods/pseudopotential.ts +86 -0
  11. package/src/js/model.ts +168 -0
  12. package/src/js/modelConversionHandler.ts +102 -0
  13. package/src/js/models/dft.ts +110 -0
  14. package/src/{models/factory.js → js/models/factory.ts} +9 -4
  15. package/src/{tree.js → js/tree.ts} +26 -20
  16. package/src/js/types/index.ts +37 -0
  17. package/tsconfig.json +3 -0
  18. package/.babelrc +0 -17
  19. package/dist/data/method_list.js +0 -1132
  20. package/dist/data/model_list.js +0 -786
  21. package/dist/data/model_method_map.js +0 -82
  22. package/dist/default_methods.js +0 -39
  23. package/dist/default_models.js +0 -14
  24. package/dist/index.js +0 -69
  25. package/dist/method.js +0 -84
  26. package/dist/methodConversionHandler.js +0 -128
  27. package/dist/methods/factory.js +0 -24
  28. package/dist/methods/pseudopotential.js +0 -100
  29. package/dist/model.js +0 -123
  30. package/dist/modelConversionHandler.js +0 -102
  31. package/dist/models/dft.js +0 -102
  32. package/dist/models/factory.js +0 -36
  33. package/dist/tree.js +0 -147
  34. package/src/data/method_list.js +0 -2
  35. package/src/data/model_list.js +0 -2
  36. package/src/data/model_method_map.js +0 -2
  37. package/src/default_methods.js +0 -38
  38. package/src/default_models.js +0 -9
  39. package/src/method.js +0 -77
  40. package/src/methodConversionHandler.js +0 -125
  41. package/src/methods/pseudopotential.js +0 -99
  42. package/src/model.js +0 -127
  43. package/src/modelConversionHandler.js +0 -91
  44. package/src/models/dft.js +0 -115
package/src/method.js DELETED
@@ -1,77 +0,0 @@
1
- import { InMemoryEntity } from "@mat3ra/code/dist/js/entity";
2
- import { deepClone } from "@mat3ra/code/dist/js/utils";
3
- import lodash from "lodash";
4
-
5
- import { PseudopotentialMethodConfig } from "./default_methods";
6
-
7
- export class Method extends InMemoryEntity {
8
- constructor(config) {
9
- const data = config.data || {};
10
- super({ ...config, data });
11
- }
12
-
13
- cloneWithoutData() {
14
- const clone = this.clone();
15
- clone.setData({});
16
- return clone;
17
- }
18
-
19
- get type() {
20
- return this.prop("type");
21
- }
22
-
23
- get subtype() {
24
- return this.prop("subtype");
25
- }
26
-
27
- setSubtype(subtype) {
28
- // TODO: add proper handling of method data subscriptions on type/subtype change
29
- this.setProp("subtype", subtype);
30
- }
31
-
32
- static get defaultConfig() {
33
- return PseudopotentialMethodConfig;
34
- }
35
-
36
- get precision() {
37
- return this.prop("precision");
38
- }
39
-
40
- get data() {
41
- return this.prop("data");
42
- }
43
-
44
- get searchText() {
45
- return this.prop("data.searchText", "");
46
- }
47
-
48
- // used to narrow down the list of methodData items available for selection
49
- // utilizing "data" field as a "blackbox" container for searchText
50
- setSearchText(searchText) {
51
- this.setData({ ...this.prop("data"), searchText });
52
- }
53
-
54
- setData(data = {}) {
55
- this.setProp("data", data);
56
- }
57
-
58
- get omitInHashCalculation() {
59
- const data = this.prop("data");
60
- return !data.searchText && lodash.isEmpty(lodash.omit(data, "searchText"));
61
- }
62
-
63
- // data without client-only fields
64
- cleanData(fieldsToExclude = []) {
65
- const filteredData = { ...this.prop("data") };
66
- fieldsToExclude.forEach((f) => {
67
- delete filteredData[f];
68
- });
69
- return filteredData;
70
- }
71
-
72
- // override in child class if needed
73
- toJSONWithCleanData(fieldsToExclude = []) {
74
- const json = { ...this._json, data: this.cleanData(fieldsToExclude) };
75
- return deepClone(json);
76
- }
77
- }
@@ -1,125 +0,0 @@
1
- import { LocalOrbitalMethodConfig, UnknownMethodConfig } from "./default_methods";
2
-
3
- export function safelyGetSlug(slugObj) {
4
- return typeof slugObj === "string" ? slugObj : slugObj.slug;
5
- }
6
-
7
- /**
8
- * The method interface converts between the legacy method data structure (type, subtype)
9
- * and the categorized method data structure (units with tier1, tier2, ...).
10
- */
11
- export class MethodConversionHandler {
12
- static convertToSimple(cm) {
13
- if (!cm) return this.convertUnknownToSimple();
14
- const pspUnits = cm.units.filter((u) => u.categories.type === "psp");
15
- const aoUnit = cm.units.find((u) => u.categories.type === "ao");
16
- const reUnit = cm.units.find((u) => u.name && u.name.includes("regression"));
17
- if (pspUnits.length) return this.convertPspUnitsToSimple(pspUnits);
18
- if (aoUnit) return this.convertAoUnitToSimple();
19
- if (reUnit) return this.convertRegressionUnitToSimple(reUnit);
20
- return this.convertRegressionUnitToSimple(reUnit);
21
- }
22
-
23
- static convertUnknownToSimple() {
24
- return UnknownMethodConfig;
25
- }
26
-
27
- static convertPspUnitsToSimple(cm) {
28
- const [firstPspUnit, ...otherUnits] = cm;
29
- if (!firstPspUnit || !firstPspUnit.categories?.subtype)
30
- return this.convertUnknownToSimple();
31
- const subtype = otherUnits?.length ? "any" : firstPspUnit.categories.subtype;
32
- return {
33
- type: "pseudopotential",
34
- subtype,
35
- };
36
- }
37
-
38
- static convertAoUnitToSimple() {
39
- return LocalOrbitalMethodConfig;
40
- }
41
-
42
- static convertRegressionUnitToSimple(cm) {
43
- const type = cm.categories.type || "linear";
44
- const subtype = cm.categories.subtype || "least_squares";
45
- return {
46
- type: safelyGetSlug(type),
47
- subtype: safelyGetSlug(subtype),
48
- data: cm.data,
49
- precision: cm.precision,
50
- };
51
- }
52
-
53
- static convertToCategorized(sm, allMethods = []) {
54
- switch (sm?.type) {
55
- case "pseudopotential":
56
- return this.convertPspToCategorized(sm, allMethods);
57
- case "localorbital":
58
- return this.convertAoToCategorized(sm);
59
- case "linear":
60
- return this.convertRegressionToCategorized(sm);
61
- case "kernel_ridge":
62
- return this.convertRegressionToCategorized(sm);
63
- default:
64
- return undefined;
65
- }
66
- }
67
-
68
- static convertPspToCategorized(sm, allMethods = []) {
69
- const subtype = safelyGetSlug(sm.subtype);
70
- // the "any" subtype is equivalent to the method representing all planewave-pseudopotential
71
- // methods. All other subtypes are equivalent to using a specific PW-PSP method.
72
- const path =
73
- subtype === "any"
74
- ? "/qm/wf/none/psp/us::/qm/wf/none/psp/nc::/qm/wf/none/psp/nc-fr::/qm/wf/none/psp/paw::/qm/wf/none/pw/none"
75
- : `/qm/wf/none/smearing/gaussian::/linalg/diag/none/davidson/none::/qm/wf/none/psp/${subtype}::/qm/wf/none/pw/none`;
76
-
77
- return allMethods.find((catMethod) => {
78
- return catMethod.path === path;
79
- });
80
- }
81
-
82
- static convertAoToCategorized(sm) {
83
- const subtype = safelyGetSlug(sm.subtype);
84
- return {
85
- units: [
86
- {
87
- parameters: { basisSlug: "6-31G" },
88
- categories: { tier1: "qm", tier2: "wf", type: "ao", subtype },
89
- tags: ["atomic orbital"],
90
- name: "Wave function: LCAO - Pople basis set (6-31G)",
91
- path: "/qm/wf/none/ao/pople?basisSlug=6-31G",
92
- },
93
- ],
94
- name: "Wave function: LCAO - Pople basis set (6-31G)",
95
- path: "/qm/wf/none/ao/pople?basisSlug=6-31G",
96
- };
97
- }
98
-
99
- static convertRegressionToCategorized(sm) {
100
- const type = safelyGetSlug(sm.type);
101
- const subtype = safelyGetSlug(sm.subtype);
102
- const { precision, data } = sm;
103
- const path = `/none/none/none/${type}/${subtype}`;
104
- const nameMap = {
105
- kernel_ridge: "Kernel ridge",
106
- linear: "Linear",
107
- least_squares: "least squares",
108
- ridge: "ridge",
109
- };
110
- const name = `${nameMap[type]} ${nameMap[subtype]} regression`;
111
- return {
112
- units: [
113
- {
114
- categories: { type, subtype },
115
- name,
116
- path,
117
- precision,
118
- data,
119
- },
120
- ],
121
- name,
122
- path,
123
- };
124
- }
125
- }
@@ -1,99 +0,0 @@
1
- import { safeMakeArray } from "@mat3ra/code/dist/js/utils";
2
- import _ from "underscore";
3
-
4
- import { Method } from "../method";
5
-
6
- export class PseudopotentialMethod extends Method {
7
- constructor(config) {
8
- super(config);
9
- this.PseudopotentialCls = null;
10
- }
11
-
12
- // "Unique" or "selected" pseudopotentials - one per element
13
- get pseudo() {
14
- return this.prop("data.pseudo", []);
15
- }
16
-
17
- // "All" or "non-unique" pseudopotentials available for a choice
18
- get allPseudo() {
19
- return this.prop("data.allPseudo", []);
20
- }
21
-
22
- get pseudopotentials() {
23
- return this.pseudo.map((x) => new this.PseudopotentialCls(x));
24
- }
25
-
26
- get allPseudopotentials() {
27
- return this.allPseudo.map((x) => new this.PseudopotentialCls(x));
28
- }
29
-
30
- static extractExchangeCorrelationFromSubworkflow(subworkflow) {
31
- const { model } = subworkflow;
32
- const approximation = model.subtype;
33
- const functional = model.functional ? model.functional.slug || model.functional : "";
34
- return {
35
- approximation,
36
- functional,
37
- };
38
- }
39
-
40
- hasPseudopotentialFor(element) {
41
- return Boolean(this.pseudopotentials.find((x) => x.element === element));
42
- }
43
-
44
- /**
45
- * @summary Sets one pseudopotential per element. Subsequent applications will override previous.
46
- * @param pseudo {Pseudopotential}
47
- */
48
- setPseudopotentialPerElement(pseudo) {
49
- if (!pseudo) {
50
- this.setPseudopotentials([]);
51
- return;
52
- }
53
- const arr = this.pseudopotentials.filter((x) => x.element !== pseudo.element);
54
- arr.push(pseudo);
55
- this.setPseudopotentials(arr);
56
- }
57
-
58
- // add new pseudopotentials to the list of all pseudopotentials
59
- addToAllPseudos(pseudos) {
60
- // eslint-disable-next-line no-param-reassign
61
- pseudos = safeMakeArray(pseudos);
62
- const allPseudos = this.allPseudopotentials;
63
- allPseudos.push(...pseudos);
64
- this.setAllPseudopotentials(allPseudos);
65
- }
66
-
67
- /**
68
- * @param pseudopotentials {Pseudopotential[]}
69
- */
70
- setPseudopotentials(pseudopotentials) {
71
- // sort by alphabetical order to ensure elements order consistency in VASP POSCAR/POTCAR
72
- this.setData({
73
- ...this.data,
74
- pseudo: _.sortBy(pseudopotentials, "element").map((x) => x.toJSON()),
75
- });
76
- }
77
-
78
- /**
79
- * @param pseudopotentials {Pseudopotential[]}
80
- */
81
- setAllPseudopotentials(pseudopotentials) {
82
- // sort by alphabetical order to ensure elements order consistency in VASP POSCAR/POTCAR
83
- this.setData({
84
- ...this.data,
85
- allPseudo: _.sortBy(pseudopotentials, "element").map((x) => x.toJSON()),
86
- });
87
- }
88
-
89
- // override default `toJSONWithCleanData` method to avoid saving `allPseudo` inside the workflow
90
- // TODO: revise after implementing Pseudopotential Sets
91
- toJSONWithCleanData(exclude = []) {
92
- return super.toJSONWithCleanData(
93
- exclude.concat([
94
- "allPseudo",
95
- // 'pseudo' - not cleaning the field to save it in `Job.workflow`
96
- ]),
97
- );
98
- }
99
- }
package/src/model.js DELETED
@@ -1,127 +0,0 @@
1
- import { InMemoryEntity } from "@mat3ra/code/dist/js/entity";
2
- import lodash from "lodash";
3
-
4
- import { DFTModelConfig } from "./default_models";
5
- import { Method } from "./method";
6
- import { MethodFactory } from "./methods/factory";
7
- import { getTreeByApplicationNameAndVersion, MODEL_TREE, treeSlugToNamedObject } from "./tree";
8
-
9
- export class Model extends InMemoryEntity {
10
- constructor({ application, ...config }) {
11
- super(config);
12
- this._application = application;
13
- this._MethodFactory = MethodFactory;
14
- }
15
-
16
- get type() {
17
- return this.prop("type", this.defaultType);
18
- }
19
-
20
- get subtype() {
21
- return this.prop("subtype", this.defaultSubtype);
22
- }
23
-
24
- setSubtype(subtype) {
25
- this.setProp("subtype", subtype);
26
- this.setMethod(this._MethodFactory.create(this.defaultMethodConfig));
27
- }
28
-
29
- get allowedTypes() {
30
- return Object.keys(this.tree).map((modelSlug) => treeSlugToNamedObject(modelSlug));
31
- }
32
-
33
- get allowedSubtypes() {
34
- return Object.keys(this.treeBranchForType).map((slug) => treeSlugToNamedObject(slug));
35
- }
36
-
37
- get defaultType() {
38
- return this.allowedTypes[0]?.slug;
39
- }
40
-
41
- get defaultSubtype() {
42
- return this.allowedSubtypes[0]?.slug;
43
- }
44
-
45
- get tree() {
46
- return (this._application && this.treeByApplicationNameAndVersion) || MODEL_TREE;
47
- }
48
-
49
- get treeBranchForType() {
50
- return this.tree[this.type] || {};
51
- }
52
-
53
- get treeBranchForSubType() {
54
- return this.treeBranchForType[this.subtype] || {};
55
- }
56
-
57
- get treeByApplicationNameAndVersion() {
58
- const [name, version] = [this._application.name, this._application.version];
59
- return getTreeByApplicationNameAndVersion({ name, version });
60
- }
61
-
62
- get groupSlug() {
63
- return `${this._application.shortName}:${this.type}:${this.subtype}`;
64
- }
65
-
66
- get method() {
67
- if (!this._method) {
68
- const method = this.prop("method") || this.defaultMethodConfig;
69
- this._method = this._MethodFactory.create(method);
70
- }
71
- return this._method;
72
- }
73
-
74
- setMethod(method) {
75
- this._method = method;
76
- }
77
-
78
- // Consider moving the below to `Method`
79
- get methodsFromTree() {
80
- return this.treeBranchForSubType.methods || {};
81
- }
82
-
83
- get methodTypes() {
84
- return Object.keys(this.methodsFromTree).map((m) => treeSlugToNamedObject(m));
85
- }
86
-
87
- get methodSubtypes() {
88
- return this.methodsFromTree[this.method.type].map((m) => treeSlugToNamedObject(m)) || [];
89
- }
90
-
91
- get defaultMethodConfig() {
92
- const type = Object.keys(this.methodsFromTree)[0];
93
- const subtype = (this.methodsFromTree[type] || [])[0];
94
- return { type, subtype };
95
- }
96
-
97
- static get defaultConfig() {
98
- return {
99
- ...DFTModelConfig,
100
- method: Method.defaultConfig,
101
- };
102
- }
103
-
104
- static get allTypes() {
105
- return Object.keys(this.tree).map((modelSlug) => treeSlugToNamedObject(modelSlug));
106
- }
107
-
108
- toJSON() {
109
- return {
110
- ...super.toJSON(),
111
- type: this.type,
112
- subtype: this.subtype,
113
- // TODO: use schema-based cleaning instead
114
- method: this.method.toJSONWithCleanData(),
115
- };
116
- }
117
-
118
- // to be used with extra properties
119
- // eslint-disable-next-line class-methods-use-this
120
- _stringToSlugifiedObject(slug) {
121
- return lodash.isString(slug) ? { slug } : slug;
122
- }
123
-
124
- get isUnknown() {
125
- return this.type === "unknown";
126
- }
127
- }
@@ -1,91 +0,0 @@
1
- import * as tree from "./tree";
2
-
3
- export function safelyGetSlug(slugObj) {
4
- return typeof slugObj === "string" ? slugObj : slugObj.slug;
5
- }
6
-
7
- /**
8
- * The model interface converts between the legacy model data structure (type, subtype, functional)
9
- * and the categorized model data structure (tier1, tier2, ...).
10
- */
11
- export class ModelConversionHandler {
12
- static convertToSimple(cm) {
13
- if (!cm) return this.convertUnknownToSimple();
14
-
15
- // eslint-disable-next-line default-case
16
- switch (cm.categories.tier3) {
17
- case "dft":
18
- return this.convertDftToSimple(cm);
19
- case "ml":
20
- return this.convertMlToSimple();
21
- default:
22
- return this.convertUnknownToSimple();
23
- }
24
- }
25
-
26
- static convertDftToSimple(cm) {
27
- if (!cm.categories?.subtype) return this.convertUnknownToSimple();
28
- const { subtype } = cm.categories;
29
- const functional = cm.parameters?.functional;
30
- return {
31
- type: "dft",
32
- subtype,
33
- functional: tree.treeSlugToNamedObject(functional),
34
- };
35
- }
36
-
37
- static convertMlToSimple() {
38
- return {
39
- type: "ml",
40
- subtype: "re",
41
- };
42
- }
43
-
44
- static convertUnknownToSimple() {
45
- return {
46
- type: "unknown",
47
- subtype: "unknown",
48
- };
49
- }
50
-
51
- static convertToCategorized(sm, allModels = []) {
52
- switch (sm?.type) {
53
- case "dft":
54
- return this.convertDftToCategorized(sm, allModels);
55
- case "ml":
56
- return this.convertMlToCategorized(sm);
57
- case "unknown":
58
- return undefined;
59
- default:
60
- return undefined;
61
- }
62
- }
63
-
64
- static convertDftToCategorized(sm, allModels = []) {
65
- const { subtype, functional: functionalStringOrObject } = sm;
66
- const defaultFunctionals = { lda: "pz", gga: "pbe", hybrid: "b3lyp" };
67
- let functional;
68
- if (!functionalStringOrObject) {
69
- functional = defaultFunctionals[subtype];
70
- } else {
71
- functional = safelyGetSlug(functionalStringOrObject);
72
- }
73
- const path = `/pb/qm/dft/ksdft/${subtype}?functional=${functional}`;
74
- return allModels.find((cm) => cm.path === path);
75
- }
76
-
77
- static convertMlToCategorized(sm) {
78
- const subtype = safelyGetSlug(sm.subtype);
79
- return {
80
- name: "Regression",
81
- path: "/st/det/ml/re/none",
82
- categories: {
83
- tier1: "st",
84
- tier2: "det",
85
- tier3: "ml",
86
- type: subtype,
87
- },
88
- parameters: {},
89
- };
90
- }
91
- }
package/src/models/dft.js DELETED
@@ -1,115 +0,0 @@
1
- import _ from "underscore";
2
-
3
- import { MethodFactory } from "../methods/factory";
4
- import { Model } from "../model";
5
- import { treeSlugToNamedObject } from "../tree";
6
-
7
- export class DFTModel extends Model {
8
- constructor(config) {
9
- super(config);
10
- this._MethodFactory = config.MethodFactory || MethodFactory;
11
- }
12
-
13
- /**
14
- * @summary Build slug string based on model information
15
- * @returns {string}
16
- */
17
- get groupSlug() {
18
- return [
19
- this._application.shortName,
20
- this.type,
21
- this.subtype,
22
- this.functional.slug,
23
- this.refiners.map((o) => o.slug).join("+"),
24
- this.modifiers.map((o) => o.slug).join("+"),
25
- ]
26
- .join(":")
27
- .replace("::", ":")
28
- .replace(/:$/, "");
29
- }
30
-
31
- get defaultFunctional() {
32
- return treeSlugToNamedObject(this.treeBranchForSubType.functionals[0]);
33
- }
34
-
35
- // eslint-disable-next-line class-methods-use-this
36
- get defaultRefiners() {
37
- return [];
38
- }
39
-
40
- // eslint-disable-next-line class-methods-use-this
41
- get defaultModifiers() {
42
- return [];
43
- }
44
-
45
- get functional() {
46
- return this.prop("functional", this.defaultFunctional);
47
- }
48
-
49
- get refiners() {
50
- return this.prop("refiners", this.defaultRefiners);
51
- }
52
-
53
- get modifiers() {
54
- return this.prop("modifiers", this.defaultModifiers);
55
- }
56
-
57
- setSubtype(subtype) {
58
- this.setProp("subtype", subtype);
59
- this.setFunctional(this.defaultFunctional);
60
- }
61
-
62
- setFunctional(functional) {
63
- this.setProp("functional", this._stringToSlugifiedObject(functional));
64
- this.setMethod(this._MethodFactory.create(this.defaultMethodConfig));
65
- }
66
-
67
- _setArrayProp(name, data) {
68
- // eslint-disable-next-line no-param-reassign, no-undef
69
- data = safeMakeArray(data).map((r) => this._stringToSlugifiedObject(r));
70
- this.setProp(name, data);
71
- this[`_${name}`] = data;
72
- }
73
-
74
- setRefiners(refiners) {
75
- this._setArrayProp("refiners", refiners);
76
- }
77
-
78
- setModifiers(modifiers) {
79
- this._setArrayProp("modifiers", modifiers);
80
- }
81
-
82
- toJSON() {
83
- const pickSlugFromObject = (o) => _.pick(o, "slug");
84
- return {
85
- ...super.toJSON(),
86
- functional: pickSlugFromObject(this.functional), // only store slug for `functional`
87
- refiners: this.refiners,
88
- modifiers: this.modifiers,
89
- };
90
- }
91
-
92
- /**
93
- * Get all functionals in the form of {name: ..., slug: ...} for further use in UI
94
- * @returns {Object.<string, string>[]} - List of functional objects
95
- */
96
- get allFunctionals() {
97
- return this.treeBranchForSubType.functionals.map((x) => treeSlugToNamedObject(x));
98
- }
99
-
100
- /**
101
- * Get all refiners in the form of {name: ..., slug: ...} for further use in UI
102
- * @returns {Object.<string, string>[]} - List of refiner objects
103
- */
104
- get allRefiners() {
105
- return this.treeBranchForSubType.refiners.map((x) => treeSlugToNamedObject(x));
106
- }
107
-
108
- /**
109
- * Get all modifiers in the form of {name: ..., slug: ...} for further use in UI
110
- * @returns {Object.<string, string>[]} - List of modifier objects
111
- */
112
- get allModifiers() {
113
- return this.treeBranchForSubType.modifiers.map((x) => treeSlugToNamedObject(x));
114
- }
115
- }