@mat3ra/wode 2025.10.1-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 (252) hide show
  1. package/.babelrc +17 -0
  2. package/LICENSE.md +15 -0
  3. package/README.md +164 -0
  4. package/assets/subworkflows/deepmd/deepmd.yml +31 -0
  5. package/assets/subworkflows/deepmd/espresso_cp_md.yml +16 -0
  6. package/assets/subworkflows/espresso/average_electrostatic_potential_find_minima.yml +27 -0
  7. package/assets/subworkflows/espresso/average_electrostatic_potential_via_band_structure.yml +67 -0
  8. package/assets/subworkflows/espresso/band_gap.yml +21 -0
  9. package/assets/subworkflows/espresso/band_gap_hse_dos.yml +30 -0
  10. package/assets/subworkflows/espresso/band_structure.yml +26 -0
  11. package/assets/subworkflows/espresso/band_structure_dos.yml +34 -0
  12. package/assets/subworkflows/espresso/band_structure_hse.yml +30 -0
  13. package/assets/subworkflows/espresso/band_structure_magn.yml +31 -0
  14. package/assets/subworkflows/espresso/band_structure_soc.yml +30 -0
  15. package/assets/subworkflows/espresso/dielectric_tensor.yml +35 -0
  16. package/assets/subworkflows/espresso/dos.yml +24 -0
  17. package/assets/subworkflows/espresso/electronic_density_mesh.yml +19 -0
  18. package/assets/subworkflows/espresso/esm.yml +14 -0
  19. package/assets/subworkflows/espresso/esm_relax.yml +14 -0
  20. package/assets/subworkflows/espresso/espresso_extract_kpoints.yml +16 -0
  21. package/assets/subworkflows/espresso/espresso_xml_get_qpt_irr.yml +12 -0
  22. package/assets/subworkflows/espresso/fixed_cell_relaxation.yml +16 -0
  23. package/assets/subworkflows/espresso/gw_band_structure_band_gap_full_frequency.yml +22 -0
  24. package/assets/subworkflows/espresso/gw_band_structure_band_gap_plasmon_pole.yml +22 -0
  25. package/assets/subworkflows/espresso/hubbard_u_hp.yml +21 -0
  26. package/assets/subworkflows/espresso/kpoint_convergence.yml +86 -0
  27. package/assets/subworkflows/espresso/neb.yml +16 -0
  28. package/assets/subworkflows/espresso/ph_init_qpoints.yml +14 -0
  29. package/assets/subworkflows/espresso/ph_single_irr_qpt.yml +14 -0
  30. package/assets/subworkflows/espresso/phonon_dispersions.yml +29 -0
  31. package/assets/subworkflows/espresso/phonon_dos.yml +29 -0
  32. package/assets/subworkflows/espresso/phonon_dos_dispersion.yml +34 -0
  33. package/assets/subworkflows/espresso/phonon_reduce.yml +29 -0
  34. package/assets/subworkflows/espresso/post_processor.yml +14 -0
  35. package/assets/subworkflows/espresso/pre_processor.yml +14 -0
  36. package/assets/subworkflows/espresso/pw_scf.yml +16 -0
  37. package/assets/subworkflows/espresso/recalculate_bands.yml +19 -0
  38. package/assets/subworkflows/espresso/surface_energy.yml +16 -0
  39. package/assets/subworkflows/espresso/total_energy.yml +16 -0
  40. package/assets/subworkflows/espresso/valence_band_offset_calc_from_previous_esp_vbm.yml +35 -0
  41. package/assets/subworkflows/espresso/variable_cell_relaxation.yml +18 -0
  42. package/assets/subworkflows/espresso/zero_point_energy.yml +19 -0
  43. package/assets/subworkflows/jupyterLab/jupyter_notebook.yml +17 -0
  44. package/assets/subworkflows/nwchem/total_energy.yml +16 -0
  45. package/assets/subworkflows/python/ml/classification_tail.yml +56 -0
  46. package/assets/subworkflows/python/ml/clustering_tail.yml +62 -0
  47. package/assets/subworkflows/python/ml/regression_tail.yml +56 -0
  48. package/assets/subworkflows/python/ml/train_head.yml +61 -0
  49. package/assets/subworkflows/python/python_script.yml +14 -0
  50. package/assets/subworkflows/shell/batch_espresso_pwscf.yml +14 -0
  51. package/assets/subworkflows/shell/hello_world.yml +14 -0
  52. package/assets/subworkflows/vasp/band_gap.yml +21 -0
  53. package/assets/subworkflows/vasp/band_structure.yml +21 -0
  54. package/assets/subworkflows/vasp/band_structure_dos.yml +23 -0
  55. package/assets/subworkflows/vasp/dos.yml +18 -0
  56. package/assets/subworkflows/vasp/fixed_cell_relaxation.yml +16 -0
  57. package/assets/subworkflows/vasp/initial_final_total_energies.yml +25 -0
  58. package/assets/subworkflows/vasp/kpoint_convergence.yml +89 -0
  59. package/assets/subworkflows/vasp/neb_subworkflow.yml +16 -0
  60. package/assets/subworkflows/vasp/prepare_images.yml +16 -0
  61. package/assets/subworkflows/vasp/recalculate_bands.yml +16 -0
  62. package/assets/subworkflows/vasp/surface_energy.yml +18 -0
  63. package/assets/subworkflows/vasp/total_energy.yml +16 -0
  64. package/assets/subworkflows/vasp/variable_cell_relaxation.yml +18 -0
  65. package/assets/subworkflows/vasp/zero_point_energy.yml +16 -0
  66. package/assets/workflows/deepmd/deepmd_md.yml +6 -0
  67. package/assets/workflows/espresso/band_gap.yml +4 -0
  68. package/assets/workflows/espresso/band_gap_dos_hse.yml +4 -0
  69. package/assets/workflows/espresso/band_structure.yml +4 -0
  70. package/assets/workflows/espresso/band_structure_dos.yml +4 -0
  71. package/assets/workflows/espresso/band_structure_hse.yml +14 -0
  72. package/assets/workflows/espresso/band_structure_magn.yml +7 -0
  73. package/assets/workflows/espresso/band_structure_soc.yml +7 -0
  74. package/assets/workflows/espresso/dielectric_tensor.yml +4 -0
  75. package/assets/workflows/espresso/dos.yml +4 -0
  76. package/assets/workflows/espresso/electronic_density_mesh.yml +4 -0
  77. package/assets/workflows/espresso/esm.yml +4 -0
  78. package/assets/workflows/espresso/esm_relax.yml +4 -0
  79. package/assets/workflows/espresso/fixed_cell_relaxation.yml +4 -0
  80. package/assets/workflows/espresso/gw_band_structure_band_gap_full_frequency.yml +4 -0
  81. package/assets/workflows/espresso/gw_band_structure_band_gap_plasmon_pole.yml +4 -0
  82. package/assets/workflows/espresso/hubbard_u_hp.yml +7 -0
  83. package/assets/workflows/espresso/kpoint_convergence.yml +4 -0
  84. package/assets/workflows/espresso/neb.yml +4 -0
  85. package/assets/workflows/espresso/phonon_dispersions.yml +4 -0
  86. package/assets/workflows/espresso/phonon_dos.yml +4 -0
  87. package/assets/workflows/espresso/phonon_dos_dispersion.yml +4 -0
  88. package/assets/workflows/espresso/phonon_map.yml +28 -0
  89. package/assets/workflows/espresso/recalculate_bands.yml +4 -0
  90. package/assets/workflows/espresso/surface_energy.yml +4 -0
  91. package/assets/workflows/espresso/total_energy.yml +4 -0
  92. package/assets/workflows/espresso/valence_band_offset.yml +171 -0
  93. package/assets/workflows/espresso/variable_cell_relaxation.yml +4 -0
  94. package/assets/workflows/espresso/zero_point_energy.yml +4 -0
  95. package/assets/workflows/jupyterLab/jupyter_notebook.yml +4 -0
  96. package/assets/workflows/nwchem/total_energy.yml +4 -0
  97. package/assets/workflows/python/ml/classification_workflow.yml +9 -0
  98. package/assets/workflows/python/ml/clustering_workflow.yml +9 -0
  99. package/assets/workflows/python/ml/regression_workflow.yml +9 -0
  100. package/assets/workflows/python/python_script.yml +4 -0
  101. package/assets/workflows/shell/batch_espresso_pwscf.yml +4 -0
  102. package/assets/workflows/shell/hello_world.yml +4 -0
  103. package/assets/workflows/vasp/band_gap.yml +4 -0
  104. package/assets/workflows/vasp/band_structure.yml +4 -0
  105. package/assets/workflows/vasp/band_structure_dos.yml +4 -0
  106. package/assets/workflows/vasp/dos.yml +4 -0
  107. package/assets/workflows/vasp/fixed_cell_relaxation.yml +4 -0
  108. package/assets/workflows/vasp/kpoint_convergence.yml +4 -0
  109. package/assets/workflows/vasp/neb.yml +8 -0
  110. package/assets/workflows/vasp/recalculate_bands.yml +4 -0
  111. package/assets/workflows/vasp/surface_energy.yml +4 -0
  112. package/assets/workflows/vasp/total_energy.yml +4 -0
  113. package/assets/workflows/vasp/variable_cell_relaxation.yml +4 -0
  114. package/assets/workflows/vasp/zero_point_energy.yml +4 -0
  115. package/build_workflows.js +65 -0
  116. package/dist/context/context.js +49 -0
  117. package/dist/context/mixins/ApplicationContextMixin.js +19 -0
  118. package/dist/context/mixins/JobContextMixin.js +39 -0
  119. package/dist/context/mixins/MaterialContextMixin.js +40 -0
  120. package/dist/context/mixins/MaterialsContextMixin.js +19 -0
  121. package/dist/context/mixins/MaterialsSetContextMixin.js +25 -0
  122. package/dist/context/mixins/MethodDataContextMixin.js +48 -0
  123. package/dist/context/mixins/WorkflowContextMixin.js +28 -0
  124. package/dist/context/providers/BoundaryConditionsFormDataProvider.js +86 -0
  125. package/dist/context/providers/CollinearMagnetizationContextProvider.js +113 -0
  126. package/dist/context/providers/HubbardContextProviderLegacy.js +81 -0
  127. package/dist/context/providers/HubbardJContextProvider.js +74 -0
  128. package/dist/context/providers/HubbardUContextProvider.js +77 -0
  129. package/dist/context/providers/HubbardVContextProvider.js +104 -0
  130. package/dist/context/providers/IonDynamicsContextProvider.js +62 -0
  131. package/dist/context/providers/MLSettingsContextProvider.js +52 -0
  132. package/dist/context/providers/MLTrainTestSplitContextProvider.js +48 -0
  133. package/dist/context/providers/NEBFormDataProvider.js +38 -0
  134. package/dist/context/providers/NonCollinearMagnetizationContextProvider.js +253 -0
  135. package/dist/context/providers/PlanewaveCutoffsContextProvider.js +67 -0
  136. package/dist/context/providers/PointsGridFormDataProvider.js +272 -0
  137. package/dist/context/providers/PointsPathFormDataProvider.js +155 -0
  138. package/dist/context/providers/by_application/ExecutableContextProvider.js +17 -0
  139. package/dist/context/providers/by_application/espresso/QENEBContextProvider.js +60 -0
  140. package/dist/context/providers/by_application/espresso/QEPWXContextProvider.js +149 -0
  141. package/dist/context/providers/by_application/nwchem/NWChemTotalEnergyContextProvider.js +84 -0
  142. package/dist/context/providers/by_application/vasp/VASPContextProvider.js +64 -0
  143. package/dist/context/providers/by_application/vasp/VASPNEBContextProvider.js +56 -0
  144. package/dist/context/providers/settings.js +37 -0
  145. package/dist/context/providers.js +199 -0
  146. package/dist/enums.js +65 -0
  147. package/dist/index.js +64 -0
  148. package/dist/patch.js +19 -0
  149. package/dist/subworkflows/convergence/factory.js +35 -0
  150. package/dist/subworkflows/convergence/non_uniform_kgrid.js +31 -0
  151. package/dist/subworkflows/convergence/parameter.js +70 -0
  152. package/dist/subworkflows/convergence/uniform_kgrid.js +26 -0
  153. package/dist/subworkflows/convergence.js +189 -0
  154. package/dist/subworkflows/create.js +285 -0
  155. package/dist/subworkflows/dynamic/espresso/getQpointIrrep.js +34 -0
  156. package/dist/subworkflows/dynamic/index.js +19 -0
  157. package/dist/subworkflows/dynamic/surfaceEnergy.js +67 -0
  158. package/dist/subworkflows/index.js +19 -0
  159. package/dist/subworkflows/subworkflow.js +279 -0
  160. package/dist/units/assertion.js +37 -0
  161. package/dist/units/assignment.js +42 -0
  162. package/dist/units/base.js +91 -0
  163. package/dist/units/builders/AssertionUnitConfigBuilder.js +34 -0
  164. package/dist/units/builders/AssignmentUnitConfigBuilder.js +41 -0
  165. package/dist/units/builders/ExecutionUnitConfigBuilder.js +67 -0
  166. package/dist/units/builders/IOUnitConfigBuilder.js +54 -0
  167. package/dist/units/builders/UnitConfigBuilder.js +79 -0
  168. package/dist/units/builders/index.js +18 -0
  169. package/dist/units/condition.js +52 -0
  170. package/dist/units/execution.js +222 -0
  171. package/dist/units/factory.js +53 -0
  172. package/dist/units/index.js +82 -0
  173. package/dist/units/io.js +148 -0
  174. package/dist/units/map.js +38 -0
  175. package/dist/units/processing.js +41 -0
  176. package/dist/units/reduce.js +24 -0
  177. package/dist/units/subworkflow.js +23 -0
  178. package/dist/utils.js +92 -0
  179. package/dist/workflows/create.js +312 -0
  180. package/dist/workflows/default.js +41 -0
  181. package/dist/workflows/index.js +108 -0
  182. package/dist/workflows/relaxation.js +37 -0
  183. package/dist/workflows/workflow.js +303 -0
  184. package/package.json +94 -0
  185. package/src/context/context.js +47 -0
  186. package/src/context/mixins/ApplicationContextMixin.js +19 -0
  187. package/src/context/mixins/JobContextMixin.js +36 -0
  188. package/src/context/mixins/MaterialContextMixin.js +41 -0
  189. package/src/context/mixins/MaterialsContextMixin.js +18 -0
  190. package/src/context/mixins/MaterialsSetContextMixin.js +24 -0
  191. package/src/context/mixins/MethodDataContextMixin.js +48 -0
  192. package/src/context/mixins/WorkflowContextMixin.js +25 -0
  193. package/src/context/providers/BoundaryConditionsFormDataProvider.js +80 -0
  194. package/src/context/providers/CollinearMagnetizationContextProvider.js +117 -0
  195. package/src/context/providers/HubbardContextProviderLegacy.js +75 -0
  196. package/src/context/providers/HubbardJContextProvider.js +73 -0
  197. package/src/context/providers/HubbardUContextProvider.js +100 -0
  198. package/src/context/providers/HubbardVContextProvider.js +111 -0
  199. package/src/context/providers/IonDynamicsContextProvider.js +56 -0
  200. package/src/context/providers/MLSettingsContextProvider.js +48 -0
  201. package/src/context/providers/MLTrainTestSplitContextProvider.js +45 -0
  202. package/src/context/providers/NEBFormDataProvider.js +32 -0
  203. package/src/context/providers/NonCollinearMagnetizationContextProvider.js +269 -0
  204. package/src/context/providers/PlanewaveCutoffsContextProvider.js +68 -0
  205. package/src/context/providers/PointsGridFormDataProvider.js +285 -0
  206. package/src/context/providers/PointsPathFormDataProvider.js +165 -0
  207. package/src/context/providers/by_application/ExecutableContextProvider.js +10 -0
  208. package/src/context/providers/by_application/espresso/QENEBContextProvider.js +56 -0
  209. package/src/context/providers/by_application/espresso/QEPWXContextProvider.js +166 -0
  210. package/src/context/providers/by_application/nwchem/NWChemTotalEnergyContextProvider.js +86 -0
  211. package/src/context/providers/by_application/vasp/VASPContextProvider.js +56 -0
  212. package/src/context/providers/by_application/vasp/VASPNEBContextProvider.js +46 -0
  213. package/src/context/providers/settings.js +38 -0
  214. package/src/context/providers.js +140 -0
  215. package/src/enums.js +65 -0
  216. package/src/index.js +17 -0
  217. package/src/patch.js +12 -0
  218. package/src/subworkflows/convergence/factory.js +14 -0
  219. package/src/subworkflows/convergence/non_uniform_kgrid.js +28 -0
  220. package/src/subworkflows/convergence/parameter.js +58 -0
  221. package/src/subworkflows/convergence/uniform_kgrid.js +22 -0
  222. package/src/subworkflows/convergence.js +196 -0
  223. package/src/subworkflows/create.js +201 -0
  224. package/src/subworkflows/dynamic/espresso/getQpointIrrep.js +35 -0
  225. package/src/subworkflows/dynamic/index.js +8 -0
  226. package/src/subworkflows/dynamic/surfaceEnergy.js +124 -0
  227. package/src/subworkflows/index.js +2 -0
  228. package/src/subworkflows/subworkflow.js +329 -0
  229. package/src/units/assertion.js +29 -0
  230. package/src/units/assignment.js +34 -0
  231. package/src/units/base.js +97 -0
  232. package/src/units/builders/AssertionUnitConfigBuilder.js +28 -0
  233. package/src/units/builders/AssignmentUnitConfigBuilder.js +36 -0
  234. package/src/units/builders/ExecutionUnitConfigBuilder.js +59 -0
  235. package/src/units/builders/IOUnitConfigBuilder.js +53 -0
  236. package/src/units/builders/UnitConfigBuilder.js +86 -0
  237. package/src/units/builders/index.js +15 -0
  238. package/src/units/condition.js +47 -0
  239. package/src/units/execution.js +263 -0
  240. package/src/units/factory.js +53 -0
  241. package/src/units/index.js +25 -0
  242. package/src/units/io.js +163 -0
  243. package/src/units/map.js +33 -0
  244. package/src/units/processing.js +39 -0
  245. package/src/units/reduce.js +17 -0
  246. package/src/units/subworkflow.js +15 -0
  247. package/src/utils.js +73 -0
  248. package/src/workflows/create.js +222 -0
  249. package/src/workflows/default.js +39 -0
  250. package/src/workflows/index.js +99 -0
  251. package/src/workflows/relaxation.js +41 -0
  252. package/src/workflows/workflow.js +351 -0
@@ -0,0 +1,263 @@
1
+ import { Template } from "@exabyte-io/ade.js";
2
+ import ApplicationRegistry from "@exabyte-io/ade.js/dist/js/ApplicationRegistry";
3
+ import { Utils } from "@mat3ra/utils";
4
+ import _ from "underscore";
5
+
6
+ import { BaseUnit } from "./base";
7
+
8
+ export class ExecutionUnit extends BaseUnit {
9
+ // keys to be omitted during toJSON
10
+ static omitKeys = [
11
+ "job",
12
+ "workflow",
13
+ "material",
14
+ "materials",
15
+ "model",
16
+ "methodData",
17
+ "hasRelaxation",
18
+ ];
19
+
20
+ /**
21
+ * @override this method to provide entities from other sources
22
+ */
23
+ _initApplication(config) {
24
+ this._application = ApplicationRegistry.createApplication(config.application);
25
+ this._executable = ApplicationRegistry.getExecutableByConfig(
26
+ this._application.name,
27
+ config.executable,
28
+ );
29
+ this._flavor = ApplicationRegistry.getFlavorByConfig(this._executable, config.flavor);
30
+ this._templates = this._flavor ? this._flavor.inputAsTemplates : [];
31
+ }
32
+
33
+ /**
34
+ * @override this method to provide default executable from other source
35
+ */
36
+ _getDefaultExecutable() {
37
+ return ApplicationRegistry.getExecutableByName(this.application.name);
38
+ }
39
+
40
+ /**
41
+ * @override this method to provide default flavor from other source
42
+ */
43
+ _getDefaultFlavor() {
44
+ return ApplicationRegistry.getFlavorByName(this.executable.name);
45
+ }
46
+
47
+ /**
48
+ * @override this method to provide custom templates
49
+ */
50
+ _getTemplatesFromInput() {
51
+ return this.getInput().map((i) => new Template(i));
52
+ }
53
+
54
+ /**
55
+ * @override this method to provide custom input from other sources
56
+ */
57
+ _getInput() {
58
+ return (
59
+ this.input ||
60
+ ApplicationRegistry.getInputAsRenderedTemplates(
61
+ this.flavor,
62
+ this.getCombinedContext(),
63
+ ) ||
64
+ []
65
+ );
66
+ }
67
+
68
+ /**
69
+ * @override this method to provide custom input as templates
70
+ */
71
+ _getInputAsTemplates() {
72
+ return ApplicationRegistry.getInputAsTemplates(this.flavor);
73
+ }
74
+
75
+ _initRuntimeItems(keys, config) {
76
+ this._initApplication(config);
77
+ super._initRuntimeItems(keys);
78
+ }
79
+
80
+ /*
81
+ * @summary expects an array with elements containing field [{content: "..."}]
82
+ */
83
+ get hashFromArrayInputContent() {
84
+ const objectForHashing = this._getInput().map((i) => {
85
+ return Utils.str.removeEmptyLinesFromString(
86
+ Utils.str.removeCommentsFromSourceCode(i.content),
87
+ );
88
+ });
89
+ return Utils.hash.calculateHashFromObject(objectForHashing);
90
+ }
91
+
92
+ get name() {
93
+ return this.prop("name", this.flavor.name);
94
+ }
95
+
96
+ get application() {
97
+ return this._application;
98
+ }
99
+
100
+ get executable() {
101
+ return this._executable;
102
+ }
103
+
104
+ get flavor() {
105
+ return this._flavor;
106
+ }
107
+
108
+ get templates() {
109
+ return this._templates;
110
+ }
111
+
112
+ setApplication(application, omitSettingExecutable = false) {
113
+ this._application = application;
114
+ this.setProp("application", application.toJSON());
115
+ if (!omitSettingExecutable) {
116
+ this.setExecutable(this._getDefaultExecutable());
117
+ }
118
+ }
119
+
120
+ setExecutable(executable) {
121
+ this._executable = executable;
122
+ this.setProp("executable", executable.toJSON());
123
+ this.setFlavor(this._getDefaultFlavor());
124
+ }
125
+
126
+ setFlavor(flavor) {
127
+ this._flavor = flavor;
128
+ this.setRuntimeItemsToDefaultValues();
129
+ this.setProp("flavor", flavor.toJSON());
130
+ this.setTemplates(this._getInputAsTemplates());
131
+ }
132
+
133
+ setTemplates(templates) {
134
+ this._templates = templates;
135
+ this.render(this.context, true);
136
+ }
137
+
138
+ setInput(input) {
139
+ this.setProp("input", input);
140
+ }
141
+
142
+ get defaultResults() {
143
+ return this.flavor.results;
144
+ }
145
+
146
+ get defaultMonitors() {
147
+ return this.flavor.monitors;
148
+ }
149
+
150
+ get defaultPostProcessors() {
151
+ return this.flavor.postProcessors;
152
+ }
153
+
154
+ get allowedResults() {
155
+ return this.executable.results;
156
+ }
157
+
158
+ get allowedMonitors() {
159
+ return this.executable.monitors;
160
+ }
161
+
162
+ get allowedPostProcessors() {
163
+ return this.executable.postProcessors;
164
+ }
165
+
166
+ get allContextProviders() {
167
+ const list = [];
168
+ // pass context below to keep UI changes
169
+ this.templates.forEach((i) =>
170
+ list.push(...i.getContextProvidersAsClassInstances(this.getCombinedContext())),
171
+ );
172
+ return list;
173
+ }
174
+
175
+ get contextProviders() {
176
+ return this.allContextProviders.filter((p) => p.isUnitContextProvider);
177
+ }
178
+
179
+ get input() {
180
+ return this.prop("input");
181
+ }
182
+
183
+ get renderingContext() {
184
+ return this._renderingContext || {};
185
+ }
186
+
187
+ set renderingContext(ctx) {
188
+ this._renderingContext = ctx;
189
+ }
190
+
191
+ // context to persist in toJSON
192
+ get storedContext() {
193
+ return _.omit(this.context, ...this.constructor.omitKeys);
194
+ }
195
+
196
+ // context to show to users with some extra keys omitted
197
+ get visibleRenderingContext() {
198
+ return _.omit(this.renderingContext, ...this.constructor.omitKeys);
199
+ }
200
+
201
+ static getSubworkflowContext(context) {
202
+ const { subworkflowContext } = context;
203
+ return subworkflowContext ? { subworkflowContext } : {};
204
+ }
205
+
206
+ /** Update rendering context and persistent context
207
+ * Note: this function is sometimes being called without passing a context!
208
+ * @param context
209
+ * @param fromTemplates
210
+ */
211
+ render(context, fromTemplates = false) {
212
+ const newInput = [];
213
+ const newPersistentContext = {};
214
+ const newRenderingContext = {};
215
+ const renderingContext = { ...this.context, ...context };
216
+ this.updateContext(renderingContext); // update in-memory context to properly render templates from input below
217
+ (fromTemplates ? this.templates : this._getTemplatesFromInput()).forEach((t) => {
218
+ newInput.push(t.getRenderedJSON(renderingContext));
219
+ Object.assign(
220
+ newRenderingContext,
221
+ t.getDataFromProvidersForRenderingContext(renderingContext),
222
+ ExecutionUnit.getSubworkflowContext(renderingContext),
223
+ );
224
+ Object.assign(
225
+ newPersistentContext,
226
+ t.getDataFromProvidersForPersistentContext(renderingContext),
227
+ ExecutionUnit.getSubworkflowContext(renderingContext),
228
+ );
229
+ });
230
+ this.setInput(newInput);
231
+ this.renderingContext = newRenderingContext;
232
+ this.updatePersistentContext(newPersistentContext);
233
+ }
234
+
235
+ /**
236
+ * @summary Calculates hash on unit-specific fields.
237
+ * The meaningful fields of processing unit are operation, flavor and input at the moment.
238
+ */
239
+ getHashObject() {
240
+ return {
241
+ ...super.getHashObject(),
242
+ application: Utils.specific.removeTimestampableKeysFromConfig(
243
+ this.application.toJSON(),
244
+ ),
245
+ executable: Utils.specific.removeTimestampableKeysFromConfig(this.executable.toJSON()),
246
+ flavor: Utils.specific.removeTimestampableKeysFromConfig(this.flavor.toJSON()),
247
+ input: this.hashFromArrayInputContent,
248
+ };
249
+ }
250
+
251
+ toJSON() {
252
+ return this.clean({
253
+ ...super.toJSON(),
254
+ executable: this.executable.toJSON(),
255
+ flavor: this.flavor.toJSON(),
256
+ input: this._getInput(),
257
+ // keys below are not propagated to the parent class on initialization of a new unit unless explicitly given
258
+ name: this.name,
259
+ // TODO: figure out the problem with storing context below
260
+ // context: this.storedContext,
261
+ });
262
+ }
263
+ }
@@ -0,0 +1,53 @@
1
+ import { UNIT_TYPES } from "../enums";
2
+ import { AssertionUnit } from "./assertion";
3
+ import { AssignmentUnit } from "./assignment";
4
+ import { BaseUnit } from "./base";
5
+ import { ConditionUnit } from "./condition";
6
+ import { ExecutionUnit } from "./execution";
7
+ import { IOUnit } from "./io";
8
+ import { MapUnit } from "./map";
9
+ import { ProcessingUnit } from "./processing";
10
+ import { SubworkflowUnit } from "./subworkflow";
11
+
12
+ export class UnitFactory {
13
+ static AssertionUnit = AssertionUnit;
14
+
15
+ static AssignmentUnit = AssignmentUnit;
16
+
17
+ static BaseUnit = BaseUnit;
18
+
19
+ static ConditionUnit = ConditionUnit;
20
+
21
+ static ExecutionUnit = ExecutionUnit;
22
+
23
+ static IOUnit = IOUnit;
24
+
25
+ static MapUnit = MapUnit;
26
+
27
+ static ProcessingUnit = ProcessingUnit;
28
+
29
+ static SubworkflowUnit = SubworkflowUnit;
30
+
31
+ static create(config) {
32
+ switch (config.type) {
33
+ case UNIT_TYPES.execution:
34
+ return new this.ExecutionUnit(config);
35
+ case UNIT_TYPES.assignment:
36
+ return new this.AssignmentUnit(config);
37
+ case UNIT_TYPES.condition:
38
+ return new this.ConditionUnit(config);
39
+ case UNIT_TYPES.io:
40
+ return new this.IOUnit(config);
41
+ case UNIT_TYPES.processing:
42
+ return new this.ProcessingUnit(config);
43
+ case UNIT_TYPES.map:
44
+ return new this.MapUnit(config);
45
+ case UNIT_TYPES.subworkflow:
46
+ return new this.SubworkflowUnit(config);
47
+ case UNIT_TYPES.assertion:
48
+ return new this.AssertionUnit(config);
49
+ default:
50
+ return new this.BaseUnit(config);
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,25 @@
1
+ import { AssertionUnit } from "./assertion";
2
+ import { AssignmentUnit } from "./assignment";
3
+ import { BaseUnit } from "./base";
4
+ import { ConditionUnit } from "./condition";
5
+ import { ExecutionUnit } from "./execution";
6
+ import { UnitFactory } from "./factory";
7
+ import { IOUnit } from "./io";
8
+ import { MapUnit } from "./map";
9
+ import { ProcessingUnit } from "./processing";
10
+ import { ReduceUnit } from "./reduce";
11
+ import { SubworkflowUnit } from "./subworkflow";
12
+
13
+ export {
14
+ BaseUnit,
15
+ AssertionUnit,
16
+ AssignmentUnit,
17
+ ConditionUnit,
18
+ ExecutionUnit,
19
+ IOUnit,
20
+ MapUnit,
21
+ ProcessingUnit,
22
+ ReduceUnit,
23
+ SubworkflowUnit,
24
+ UnitFactory,
25
+ };
@@ -0,0 +1,163 @@
1
+ import lodash from "lodash";
2
+
3
+ import { IO_ID_COLUMN, UNIT_TYPES } from "../enums";
4
+ import { BaseUnit } from "./base";
5
+
6
+ export class IOUnit extends BaseUnit {
7
+ /**
8
+ * IO Unit Builder for Object Storage sources.
9
+ *
10
+ * @param {Object} config - config object with other parameters:
11
+ * @param {String} config.name - the name of the unit this builder is creating
12
+ * @param {String} config.subtype - "input", "output", or "dataframe"
13
+ * @param {Object} config.input - input containing information on the file to download
14
+ * @param {Boolean} config.enableRender - Whether to use Jinja templating at runtime
15
+ */
16
+ constructor(config) {
17
+ super({ ...IOUnit.getIOConfig(), ...config });
18
+ this.initialize(config);
19
+ }
20
+
21
+ static getIOConfig() {
22
+ return {
23
+ name: UNIT_TYPES.io,
24
+ type: UNIT_TYPES.io,
25
+ subtype: "input",
26
+ };
27
+ }
28
+
29
+ initialize(config) {
30
+ this._materials = [];
31
+ this._defaultTargets = ["band_gaps:direct", "band_gaps:indirect"];
32
+ this._features = lodash.get(config, "input.0.endpoint_options.data.features", []);
33
+ this._targets = lodash.get(
34
+ config,
35
+ "input.0.endpoint_options.data.targets",
36
+ this._defaultTargets,
37
+ );
38
+ this._ids = lodash.get(config, "input.0.endpoint_options.data.ids", []);
39
+ this._jobId = null;
40
+ }
41
+
42
+ get materials() {
43
+ return this._materials || [];
44
+ }
45
+
46
+ get defaultTargets() {
47
+ return this._defaultTargets;
48
+ }
49
+
50
+ get features() {
51
+ return this._features;
52
+ }
53
+
54
+ get featuresWithoutId() {
55
+ return this.features.filter((x) => x !== IO_ID_COLUMN);
56
+ }
57
+
58
+ get availableFeatures() {
59
+ const { materials } = this;
60
+ return lodash.uniq(
61
+ lodash
62
+ .flatten(materials.map((x) => lodash.keys(x.propertiesDict())))
63
+ .concat(this.features),
64
+ );
65
+ }
66
+
67
+ get availableFeaturesWithoutId() {
68
+ return this.availableFeatures.filter((feature) => feature !== IO_ID_COLUMN);
69
+ }
70
+
71
+ get targets() {
72
+ return this._targets;
73
+ }
74
+
75
+ /**
76
+ * @summary Checks whether selected features contain only IO_ID_COLUMN ('exabyteId').
77
+ * Used to identify that no features are selected yet (features set always contains ID_COLUMN)
78
+ */
79
+ get onlyIdFeatureSelected() {
80
+ return lodash.isEmpty(lodash.without(this.features, IO_ID_COLUMN));
81
+ }
82
+
83
+ /**
84
+ * @summary Returns object with targets as key and arrays of appropriate values.
85
+ * E.g. {'band_gap:indirect': [0.1, 0.3], 'pressure': [100, undefined]}
86
+ */
87
+ get valuesByTarget() {
88
+ const values = this.dataGridValues;
89
+ const result = {};
90
+ this.targets.forEach((target) => {
91
+ result[target] = values.map((v) => v[target]);
92
+ });
93
+ return result;
94
+ }
95
+
96
+ get dataFrameConfig() {
97
+ return {
98
+ subtype: "dataFrame",
99
+ source: "api",
100
+ input: [
101
+ {
102
+ endpoint: "dataframe",
103
+ endpoint_options: {
104
+ method: "POST",
105
+ data: {
106
+ targets: this._targets,
107
+ features: this._features,
108
+ ids: this._ids,
109
+ jobId: this._jobId,
110
+ },
111
+ headers: {},
112
+ params: {},
113
+ },
114
+ },
115
+ ],
116
+ };
117
+ }
118
+
119
+ get isDataFrame() {
120
+ return this.prop("subtype") === "dataFrame";
121
+ }
122
+
123
+ setMaterials(materials) {
124
+ this._materials = materials;
125
+ this._ids = materials.map((m) => m.exabyteId);
126
+ }
127
+
128
+ addFeature(feature) {
129
+ // only add if not already present
130
+ if (this._features.indexOf(feature) === -1) this._features.push(feature);
131
+ }
132
+
133
+ removeFeature(feature) {
134
+ if (this.featuresWithoutId.length === 1) {
135
+ throw new Error("At least one feature is required");
136
+ }
137
+ this._features = this._features.filter((x) => feature !== x && x !== IO_ID_COLUMN);
138
+ }
139
+
140
+ addTarget(target) {
141
+ if (this._targets.indexOf(target) === -1) this._targets.push(target);
142
+ }
143
+
144
+ removeTarget(target) {
145
+ if (this._targets.length === 1) {
146
+ throw new Error("At least one target is required");
147
+ }
148
+ this._targets = this._targets.filter((x) => target !== x);
149
+ }
150
+
151
+ hasFeature(feature) {
152
+ return this._features.indexOf(feature) > -1;
153
+ }
154
+
155
+ hasTarget(target) {
156
+ return this._targets.indexOf(target) > -1;
157
+ }
158
+
159
+ toJSON() {
160
+ const config = this.isDataFrame ? this.dataFrameConfig : {};
161
+ return this.clean({ ...super.toJSON(), ...config });
162
+ }
163
+ }
@@ -0,0 +1,33 @@
1
+ import { UNIT_TYPES } from "../enums";
2
+ import { BaseUnit } from "./base";
3
+
4
+ export const defaultMapConfig = {
5
+ name: UNIT_TYPES.map,
6
+ type: UNIT_TYPES.map,
7
+ workflowId: "",
8
+ input: {
9
+ target: "MAP_DATA",
10
+ scope: "global",
11
+ name: "",
12
+ values: [],
13
+ useValues: false,
14
+ },
15
+ };
16
+
17
+ export class MapUnit extends BaseUnit {
18
+ constructor(config) {
19
+ super({ ...defaultMapConfig, ...config });
20
+ }
21
+
22
+ get input() {
23
+ return this.prop("input");
24
+ }
25
+
26
+ get workflowId() {
27
+ return this.prop("workflowId");
28
+ }
29
+
30
+ setWorkflowId(id) {
31
+ this.setProp("workflowId", id);
32
+ }
33
+ }
@@ -0,0 +1,39 @@
1
+ import { UNIT_TYPES } from "../enums";
2
+ import { BaseUnit } from "./base";
3
+
4
+ export class ProcessingUnit extends BaseUnit {
5
+ constructor(config) {
6
+ super({ ...ProcessingUnit.getProcessingConfig(), ...config });
7
+ }
8
+
9
+ static getProcessingConfig() {
10
+ return {
11
+ name: UNIT_TYPES.processing,
12
+ type: UNIT_TYPES.processing,
13
+ };
14
+ }
15
+
16
+ setOperation(op) {
17
+ this.setProp("operation", op);
18
+ }
19
+
20
+ setOperationType(type) {
21
+ this.setProp("operationType", type);
22
+ }
23
+
24
+ setInput(input) {
25
+ this.setProp("input", input);
26
+ }
27
+
28
+ get operation() {
29
+ return this.prop("operation");
30
+ }
31
+
32
+ get operationType() {
33
+ return this.prop("operationType");
34
+ }
35
+
36
+ get input() {
37
+ return this.prop("input");
38
+ }
39
+ }
@@ -0,0 +1,17 @@
1
+ import { UNIT_TYPES } from "../enums";
2
+ import { BaseUnit } from "./base";
3
+
4
+ export class ReduceUnit extends BaseUnit {
5
+ constructor(unitName, mapUnit, input) {
6
+ super({ ...ReduceUnit.getReduceConfig(unitName, mapUnit, input) });
7
+ }
8
+
9
+ static getReduceConfig(unitName, mapUnit, input) {
10
+ return {
11
+ type: UNIT_TYPES.reduce,
12
+ name: unitName,
13
+ mapFlowchartId: mapUnit,
14
+ input,
15
+ };
16
+ }
17
+ }
@@ -0,0 +1,15 @@
1
+ import { UNIT_TYPES } from "../enums";
2
+ import { BaseUnit } from "./base";
3
+
4
+ export class SubworkflowUnit extends BaseUnit {
5
+ constructor(config) {
6
+ super({ ...SubworkflowUnit.getSubworkflowConfig(), ...config });
7
+ }
8
+
9
+ static getSubworkflowConfig() {
10
+ return {
11
+ name: "New Subworkflow",
12
+ type: UNIT_TYPES.subworkflow,
13
+ };
14
+ }
15
+ }
package/src/utils.js ADDED
@@ -0,0 +1,73 @@
1
+ import lodash from "lodash";
2
+
3
+ /**
4
+ * @summary set the head of an array of units
5
+ * @param units
6
+ * @returns {Unit[]}
7
+ */
8
+ export function setUnitsHead(units) {
9
+ if (units.length > 0) {
10
+ units[0].head = true;
11
+ lodash.tail(units).map((x) => (x.head = false));
12
+ }
13
+ return units;
14
+ }
15
+
16
+ // TODO: fix setNextLinks on unit removal and convergence logic.
17
+ /**
18
+ * @summary Re-establishes the linked `next => flowchartId` logic in an array of units
19
+ * @params units {Unit[]}
20
+ * @returns units {Unit[]}
21
+ */
22
+ export function setNextLinks(units) {
23
+ const flowchartIds = units.map((u) => u.flowchartId);
24
+ for (let i = 0; i < units.length - 1; i++) {
25
+ if (!units[i].next) {
26
+ // newly added units don't have next set yet => set it
27
+ units[i].next = units[i + 1].flowchartId;
28
+ if (i > 0) units[i - 1].next = units[i].flowchartId;
29
+ } else if (!flowchartIds.includes(units[i].next)) {
30
+ // newly removed units may create broken next links => fix it
31
+ units[i].next = units[i + 1].flowchartId;
32
+ }
33
+ }
34
+ return units;
35
+ }
36
+
37
+ /**
38
+ * @summary Apply configuration data to an object
39
+ * @param obj {*} object / class containing methods or attributes to be set
40
+ * @param config { functions: {}, attributes: {} } functions to call and attributes to set
41
+ * @param callBuild {boolean} if true; call build between applying functions and attributes
42
+ * @returns {*} updated object
43
+ */
44
+ export function applyConfig({ obj, config = {}, callBuild = false }) {
45
+ const { functions = {}, attributes = {} } = config;
46
+ // eslint-disable-next-line no-restricted-syntax
47
+ for (const [func, args] of Object.entries(functions)) {
48
+ // eslint-disable-next-line no-nested-ternary
49
+ if (obj[func]) {
50
+ if (args) obj[func](args);
51
+ else obj[func]();
52
+ }
53
+ }
54
+ const modified = callBuild ? obj.build() : obj;
55
+ // eslint-disable-next-line no-restricted-syntax
56
+ for (const [key, values] of Object.entries(attributes)) {
57
+ modified[key] = values;
58
+ }
59
+ return modified;
60
+ }
61
+
62
+ /**
63
+ * @summary Safely extract unit object from subworkflow data
64
+ * @param subworkflowData {Object} subworkflow data
65
+ * @param index {number} index of subworkflow unit
66
+ * @param type {string} type of subworkflow unit
67
+ * @returns {Object|null} subworkflow unit object (not a unit class instance!)
68
+ */
69
+ export function findUnit({ subworkflowData, index, type }) {
70
+ const unit = subworkflowData.units[index];
71
+ if (unit.type !== type) throw new Error("findUnit() error: unit type does not match!");
72
+ return unit;
73
+ }