@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
@@ -0,0 +1,102 @@
1
+ import { CategorizedModel, SlugifiedEntryOrSlug } from "@mat3ra/esse/dist/js/types";
2
+
3
+ import * as tree from "./tree";
4
+ import type { ModelConfig, SimplifiedCategorizedModel } from "./types";
5
+
6
+ export function safelyGetSlug(slugObj: SlugifiedEntryOrSlug): string {
7
+ return typeof slugObj === "string" ? slugObj : slugObj.slug;
8
+ }
9
+
10
+ export class ModelConversionHandler {
11
+ static convertToSimple(categorizedModel: CategorizedModel | undefined): ModelConfig {
12
+ if (!categorizedModel) return this.convertUnknownToSimple();
13
+ switch (categorizedModel.categories.tier3) {
14
+ case "dft":
15
+ return this.convertDftToSimple(categorizedModel);
16
+ case "ml":
17
+ return this.convertMlToSimple();
18
+ default:
19
+ return this.convertUnknownToSimple();
20
+ }
21
+ }
22
+
23
+ static convertDftToSimple(categorizedModel: CategorizedModel): ModelConfig {
24
+ if (!categorizedModel.categories?.subtype) return this.convertUnknownToSimple();
25
+ const subtypeCategory = categorizedModel.categories.subtype as SlugifiedEntryOrSlug;
26
+ const subtype = safelyGetSlug(subtypeCategory);
27
+ const functionalParam = (categorizedModel.parameters as any)?.functional;
28
+ const functionalSlug = functionalParam
29
+ ? safelyGetSlug(functionalParam as SlugifiedEntryOrSlug)
30
+ : "";
31
+ return {
32
+ type: "dft",
33
+ subtype,
34
+ functional: tree.treeSlugToNamedObject(functionalSlug),
35
+ };
36
+ }
37
+
38
+ static convertMlToSimple(): ModelConfig {
39
+ return {
40
+ type: "ml",
41
+ subtype: "re",
42
+ };
43
+ }
44
+
45
+ static convertUnknownToSimple(): ModelConfig {
46
+ return {
47
+ type: "unknown",
48
+ subtype: "unknown",
49
+ };
50
+ }
51
+
52
+ static convertToCategorized(
53
+ simpleModel: ModelConfig | undefined,
54
+ allModels: CategorizedModel[] = [],
55
+ ): SimplifiedCategorizedModel | undefined {
56
+ switch (simpleModel?.type) {
57
+ case "dft":
58
+ return this.convertDftToCategorized(simpleModel, allModels);
59
+ case "ml":
60
+ return this.convertMlToCategorized(simpleModel);
61
+ case "unknown":
62
+ return undefined;
63
+ default:
64
+ return undefined;
65
+ }
66
+ }
67
+
68
+ static convertDftToCategorized(
69
+ simpleModel: ModelConfig,
70
+ allModels: CategorizedModel[] = [],
71
+ ): SimplifiedCategorizedModel | undefined {
72
+ const { subtype, functional: functionalStringOrObject } = simpleModel;
73
+ const defaultFunctionals: Record<string, string> = {
74
+ lda: "pz",
75
+ gga: "pbe",
76
+ hybrid: "b3lyp",
77
+ };
78
+ let functional: string | undefined;
79
+ if (!functionalStringOrObject) {
80
+ functional = defaultFunctionals[subtype as string];
81
+ } else {
82
+ functional = safelyGetSlug(functionalStringOrObject as SlugifiedEntryOrSlug);
83
+ }
84
+ const path = `/pb/qm/dft/ksdft/${subtype}?functional=${functional}`;
85
+ return allModels.find((categorized) => categorized.path === path);
86
+ }
87
+
88
+ static convertMlToCategorized(simpleModel: ModelConfig): SimplifiedCategorizedModel {
89
+ const subtype = safelyGetSlug(simpleModel.subtype as SlugifiedEntryOrSlug);
90
+ return {
91
+ name: "Regression",
92
+ path: "/st/det/ml/re/none",
93
+ categories: {
94
+ tier1: "st",
95
+ tier2: "det",
96
+ tier3: "ml",
97
+ type: subtype,
98
+ },
99
+ parameters: {},
100
+ };
101
+ }
102
+ }
@@ -0,0 +1,110 @@
1
+ import { safeMakeArray } from "@mat3ra/code/dist/js/utils";
2
+ import { SlugifiedEntry, SlugifiedEntryOrSlug } from "@mat3ra/esse/dist/js/types";
3
+ import _ from "underscore";
4
+
5
+ import { MethodFactory } from "../methods/factory";
6
+ import { Model } from "../model";
7
+ import { treeSlugToNamedObject } from "../tree";
8
+ import type { ModelConfig } from "../types";
9
+
10
+ export class DFTModel extends Model {
11
+ constructor(config: ModelConfig & { MethodFactory?: typeof MethodFactory }) {
12
+ super(config);
13
+ this._MethodFactory = config.MethodFactory || MethodFactory;
14
+ }
15
+
16
+ get groupSlug(): string {
17
+ const functionalSlug = this.functional.slug;
18
+ const refinersSlug = this.refiners.map((o) => o.slug).join("+");
19
+ const modifiersSlug = this.modifiers.map((o) => o.slug).join("+");
20
+ const slugs = [
21
+ this._application?.shortName,
22
+ this.type,
23
+ this.subtype,
24
+ functionalSlug,
25
+ refinersSlug,
26
+ modifiersSlug,
27
+ ].filter(Boolean);
28
+ return slugs.join(":");
29
+ }
30
+
31
+ get defaultFunctional(): SlugifiedEntry {
32
+ const [slug] = this.treeBranchForSubType.functionals || [];
33
+ return treeSlugToNamedObject(slug);
34
+ }
35
+
36
+ get defaultRefiners(): SlugifiedEntry[] {
37
+ return [];
38
+ }
39
+
40
+ get defaultModifiers(): SlugifiedEntry[] {
41
+ return [];
42
+ }
43
+
44
+ get functional(): SlugifiedEntry {
45
+ return this.prop<SlugifiedEntry>("functional", this.defaultFunctional);
46
+ }
47
+
48
+ get refiners(): SlugifiedEntry[] {
49
+ return this.prop<SlugifiedEntry[]>("refiners", this.defaultRefiners);
50
+ }
51
+
52
+ get modifiers(): SlugifiedEntry[] {
53
+ return this.prop<SlugifiedEntry[]>("modifiers", this.defaultModifiers);
54
+ }
55
+
56
+ setSubtype(subtype: SlugifiedEntryOrSlug): void {
57
+ this.setProp("subtype", subtype);
58
+ this.setFunctional(this.defaultFunctional);
59
+ }
60
+
61
+ setFunctional(functional: SlugifiedEntryOrSlug): void {
62
+ this.setProp("functional", this._stringToSlugifiedObject(functional));
63
+ this.setMethod(this._MethodFactory.create(this.defaultMethodConfig));
64
+ }
65
+
66
+ private _setArrayProp(
67
+ name: "refiners" | "modifiers",
68
+ data: SlugifiedEntryOrSlug | SlugifiedEntryOrSlug[],
69
+ ): void {
70
+ const normalized = safeMakeArray(data).map((item) => this._stringToSlugifiedObject(item));
71
+ this.setProp(name, normalized);
72
+ (this as unknown as Record<string, SlugifiedEntry[]>)[`_${name}`] = normalized;
73
+ }
74
+
75
+ setRefiners(refiners: SlugifiedEntryOrSlug | SlugifiedEntryOrSlug[]): void {
76
+ this._setArrayProp("refiners", refiners);
77
+ }
78
+
79
+ setModifiers(modifiers: SlugifiedEntryOrSlug | SlugifiedEntryOrSlug[]): void {
80
+ this._setArrayProp("modifiers", modifiers);
81
+ }
82
+
83
+ toJSON(): Record<string, unknown> {
84
+ const pickSlugFromObject = (item: SlugifiedEntry) => _.pick(item, "slug");
85
+ return {
86
+ ...super.toJSON(),
87
+ functional: pickSlugFromObject(this.functional),
88
+ refiners: this.refiners,
89
+ modifiers: this.modifiers,
90
+ };
91
+ }
92
+
93
+ get allFunctionals(): SlugifiedEntry[] {
94
+ return (this.treeBranchForSubType.functionals || []).map((slug) =>
95
+ treeSlugToNamedObject(slug),
96
+ );
97
+ }
98
+
99
+ get allRefiners(): SlugifiedEntry[] {
100
+ return (this.treeBranchForSubType.refiners || []).map((slug) =>
101
+ treeSlugToNamedObject(slug),
102
+ );
103
+ }
104
+
105
+ get allModifiers(): SlugifiedEntry[] {
106
+ return (this.treeBranchForSubType.modifiers || []).map((slug) =>
107
+ treeSlugToNamedObject(slug),
108
+ );
109
+ }
110
+ }
@@ -1,5 +1,6 @@
1
1
  import { Model } from "../model";
2
2
  import { getDefaultModelTypeForApplication } from "../tree";
3
+ import type { ModelConfig } from "../types";
3
4
  import { DFTModel } from "./dft";
4
5
 
5
6
  export class ModelFactory {
@@ -7,7 +8,7 @@ export class ModelFactory {
7
8
 
8
9
  static Model = Model;
9
10
 
10
- static create(config) {
11
+ static create(config: ModelConfig): Model {
11
12
  switch (config.type) {
12
13
  case "dft":
13
14
  return new this.DFTModel(config);
@@ -16,13 +17,17 @@ export class ModelFactory {
16
17
  }
17
18
  }
18
19
 
19
- static createFromApplication(config) {
20
+ static createFromApplication(config: ModelConfig): Model {
20
21
  const { application } = config;
21
- const type = application && getDefaultModelTypeForApplication(application);
22
- if (!type)
22
+ if (!application) {
23
+ throw new Error("ModelFactory.createFromApplication: application is required");
24
+ }
25
+ const type = getDefaultModelTypeForApplication(application);
26
+ if (!type) {
23
27
  throw new Error(
24
28
  `ModelFactory.createFromApplication: cannot determine model type: ${type}`,
25
29
  );
30
+ }
26
31
  return this.create({ ...config, type });
27
32
  }
28
33
  }
@@ -1,23 +1,26 @@
1
1
  import { deepClone } from "@mat3ra/code/dist/js/utils";
2
+ import { ApplicationSchemaBase, SlugifiedEntry } from "@mat3ra/esse/dist/js/types";
2
3
  import lodash from "lodash";
3
4
  import _ from "underscore";
4
5
 
6
+ import type { ModelTree } from "./types";
7
+
5
8
  // TODO: migrate to use manifest instead
6
9
 
7
10
  export const METHODS = {
8
11
  pseudopotential: "pseudopotential",
9
12
  localorbital: "localorbital",
10
13
  unknown: "unknown",
11
- };
14
+ } as const;
12
15
 
13
- const methods = {
16
+ const methods: Record<string, string[]> = {
14
17
  [METHODS.pseudopotential]: ["paw", "nc", "nc-fr", "us"],
15
18
  // TODO: Add additional basis set options, once user choice of specific (i.e 3-21G vs cc-pVDZ) is implemented.
16
19
  [METHODS.localorbital]: ["pople"],
17
20
  [METHODS.unknown]: ["unknown"],
18
21
  };
19
22
 
20
- export const getPseudopotentialTypesFromTree = () => methods[METHODS.pseudopotential];
23
+ export const getPseudopotentialTypesFromTree = (): string[] => methods[METHODS.pseudopotential];
21
24
 
22
25
  // DFT-specific
23
26
 
@@ -47,16 +50,16 @@ const DFTModelTree = {
47
50
  },
48
51
  };
49
52
 
50
- export const getDFTFunctionalsFromTree = () => Object.keys(DFTModelTree);
53
+ export const getDFTFunctionalsFromTree = (): string[] => Object.keys(DFTModelTree);
51
54
 
52
- export const getDFTFunctionalsByApproximation = (approximation) => {
53
- const branch = DFTModelTree[approximation];
55
+ export const getDFTFunctionalsByApproximation = (approximation: string): string[] | undefined => {
56
+ const branch = DFTModelTree[approximation as keyof typeof DFTModelTree];
54
57
  return branch && branch.functionals;
55
58
  };
56
59
 
57
60
  // GENERAL
58
61
 
59
- export const MODEL_TREE = {
62
+ export const MODEL_TREE: ModelTree = {
60
63
  dft: DFTModelTree,
61
64
  ml: {
62
65
  re: {
@@ -75,7 +78,7 @@ export const MODEL_TREE = {
75
78
  },
76
79
  };
77
80
 
78
- export const MODEL_NAMES = {
81
+ export const MODEL_NAMES: Record<string, string> = {
79
82
  dft: "density functional theory",
80
83
  lda: "local density approximation",
81
84
  gga: "generalized gradient approximation",
@@ -84,7 +87,7 @@ export const MODEL_NAMES = {
84
87
  re: "regression",
85
88
  };
86
89
 
87
- export const treeSlugToNamedObject = (modelSlug) => {
90
+ export const treeSlugToNamedObject = (modelSlug: string): SlugifiedEntry => {
88
91
  return {
89
92
  slug: modelSlug,
90
93
  name: lodash.get(MODEL_NAMES, modelSlug, modelSlug),
@@ -96,11 +99,13 @@ export const treeSlugToNamedObject = (modelSlug) => {
96
99
  // demonstrate how tree can be modified
97
100
  // VASP_MODELS_TREE.gga.functionals = _.omit(VASP_MODELS_TREE.gga.functionals);
98
101
 
99
- const VASP_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft"));
100
- const ESPRESSO_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft"));
101
- const NWCHEM_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft"));
102
+ type DftOnlyTree = { dft: typeof DFTModelTree };
103
+
104
+ const VASP_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft")) as DftOnlyTree;
105
+ const ESPRESSO_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft")) as DftOnlyTree;
106
+ const NWCHEM_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft")) as DftOnlyTree;
102
107
 
103
- ["gga", "lda"].forEach((approximation) => {
108
+ (["gga", "lda"] as const).forEach((approximation) => {
104
109
  // pick "paw" for vasp
105
110
  VASP_MODELS_TREE.dft[approximation].methods.pseudopotential = VASP_MODELS_TREE.dft[
106
111
  approximation
@@ -111,10 +116,13 @@ const NWCHEM_MODELS_TREE = deepClone(_.pick(MODEL_TREE, "dft"));
111
116
  ESPRESSO_MODELS_TREE.dft[approximation].methods.pseudopotential.reverse();
112
117
  });
113
118
 
114
- const UNKNOWN_MODELS_TREE = _.pick(MODEL_TREE, "unknown");
119
+ const UNKNOWN_MODELS_TREE = _.pick(MODEL_TREE, "unknown") as ModelTree;
115
120
  // const ML_MODELS_TREE = _.pick(MODEL_TREE, "ml");
116
121
 
117
- const MODELS_TREE_CONFIGS_BY_APPLICATION_NAME_VERSION = [
122
+ const MODELS_TREE_CONFIGS_BY_APPLICATION_NAME_VERSION: Array<{
123
+ name: string;
124
+ tree: ModelTree;
125
+ }> = [
118
126
  {
119
127
  name: "vasp",
120
128
  tree: VASP_MODELS_TREE,
@@ -147,16 +155,14 @@ const MODELS_TREE_CONFIGS_BY_APPLICATION_NAME_VERSION = [
147
155
 
148
156
  export const getTreeByApplicationNameAndVersion = ({
149
157
  name,
150
- // eslint-disable-next-line no-unused-vars
151
- version,
152
- }) => {
158
+ }: Pick<ApplicationSchemaBase, "name" | "version">): ModelTree => {
153
159
  // TODO: add logic to filter by version when necessary
154
160
  const cfgs = MODELS_TREE_CONFIGS_BY_APPLICATION_NAME_VERSION.filter(
155
161
  (cfg) => cfg.name === name,
156
- ).map((x) => x.tree);
162
+ ).map((cfg) => cfg.tree);
157
163
  return Object.assign({}, ...cfgs);
158
164
  };
159
165
 
160
- export const getDefaultModelTypeForApplication = (application) => {
166
+ export const getDefaultModelTypeForApplication = (application: ApplicationSchemaBase): string => {
161
167
  return Object.keys(getTreeByApplicationNameAndVersion(application))[0];
162
168
  };
@@ -0,0 +1,37 @@
1
+ import type {
2
+ ApplicationSchemaBase,
3
+ BaseModel,
4
+ CategorizedMethod,
5
+ CategorizedModel,
6
+ CategorizedUnitMethod,
7
+ } from "@mat3ra/esse/dist/js/types";
8
+
9
+ export type ModelConfig = Pick<BaseModel, "type" | "subtype"> &
10
+ Partial<Omit<BaseModel, "type" | "subtype">> & {
11
+ application?: ApplicationSchemaBase;
12
+ };
13
+
14
+ export type SimplifiedCategorizedModel = Pick<
15
+ CategorizedModel,
16
+ "name" | "path" | "categories" | "parameters"
17
+ >;
18
+
19
+ export type SimplifiedCategorizedMethod = Pick<CategorizedMethod, "name" | "path"> & {
20
+ units: CategorizedUnitMethod[];
21
+ };
22
+
23
+ export interface PseudopotentialLike {
24
+ element?: string;
25
+ toJSON(): Record<string, unknown>;
26
+ }
27
+
28
+ export type PseudopotentialCtor = new (config: Record<string, unknown>) => PseudopotentialLike;
29
+
30
+ export interface MethodTreeBranch {
31
+ methods: Record<string, string[]>;
32
+ functionals?: string[];
33
+ refiners?: string[];
34
+ modifiers?: string[];
35
+ }
36
+
37
+ export type ModelTree = Record<string, Record<string, MethodTreeBranch>>;
package/tsconfig.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "@mat3ra/tsconfig/tsconfig-js-py-dev.json"
3
+ }
package/.babelrc DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "presets": [
3
- [
4
- "@babel/preset-env",
5
- {
6
- "targets": {
7
- "node": "current"
8
- }
9
- }
10
- ],
11
- "@babel/preset-react",
12
- ],
13
- "plugins": [
14
- "@babel/plugin-proposal-class-properties"
15
- ]
16
- }
17
-