hpcflow 0.1.9__py3-none-any.whl → 0.2.0a271__py3-none-any.whl

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 (275) hide show
  1. hpcflow/__init__.py +2 -11
  2. hpcflow/__pyinstaller/__init__.py +5 -0
  3. hpcflow/__pyinstaller/hook-hpcflow.py +40 -0
  4. hpcflow/_version.py +1 -1
  5. hpcflow/app.py +43 -0
  6. hpcflow/cli.py +2 -462
  7. hpcflow/data/demo_data_manifest/__init__.py +3 -0
  8. hpcflow/data/demo_data_manifest/demo_data_manifest.json +6 -0
  9. hpcflow/data/jinja_templates/test/test_template.txt +8 -0
  10. hpcflow/data/programs/hello_world/README.md +1 -0
  11. hpcflow/data/programs/hello_world/hello_world.c +87 -0
  12. hpcflow/data/programs/hello_world/linux/hello_world +0 -0
  13. hpcflow/data/programs/hello_world/macos/hello_world +0 -0
  14. hpcflow/data/programs/hello_world/win/hello_world.exe +0 -0
  15. hpcflow/data/scripts/__init__.py +1 -0
  16. hpcflow/data/scripts/bad_script.py +2 -0
  17. hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +8 -0
  18. hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +8 -0
  19. hpcflow/data/scripts/demo_task_1_parse_p3.py +7 -0
  20. hpcflow/data/scripts/do_nothing.py +2 -0
  21. hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
  22. hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
  23. hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
  24. hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
  25. hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
  26. hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
  27. hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
  28. hpcflow/data/scripts/generate_t1_file_01.py +7 -0
  29. hpcflow/data/scripts/import_future_script.py +7 -0
  30. hpcflow/data/scripts/input_file_generator_basic.py +3 -0
  31. hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
  32. hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
  33. hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
  34. hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +6 -0
  35. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
  36. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
  37. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
  38. hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
  39. hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +15 -0
  40. hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
  41. hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +8 -0
  42. hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
  43. hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
  44. hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +6 -0
  45. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +12 -0
  46. hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
  47. hpcflow/data/scripts/main_script_test_hdf5_in_obj_group.py +12 -0
  48. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +11 -0
  49. hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +14 -0
  50. hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +17 -0
  51. hpcflow/data/scripts/main_script_test_json_in_json_out.py +14 -0
  52. hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +16 -0
  53. hpcflow/data/scripts/main_script_test_json_in_obj.py +12 -0
  54. hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
  55. hpcflow/data/scripts/main_script_test_json_out_obj.py +10 -0
  56. hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +16 -0
  57. hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
  58. hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
  59. hpcflow/data/scripts/output_file_parser_basic.py +3 -0
  60. hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
  61. hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
  62. hpcflow/data/scripts/parse_t1_file_01.py +4 -0
  63. hpcflow/data/scripts/script_exit_test.py +5 -0
  64. hpcflow/data/template_components/__init__.py +1 -0
  65. hpcflow/data/template_components/command_files.yaml +26 -0
  66. hpcflow/data/template_components/environments.yaml +13 -0
  67. hpcflow/data/template_components/parameters.yaml +14 -0
  68. hpcflow/data/template_components/task_schemas.yaml +139 -0
  69. hpcflow/data/workflows/workflow_1.yaml +5 -0
  70. hpcflow/examples.ipynb +1037 -0
  71. hpcflow/sdk/__init__.py +149 -0
  72. hpcflow/sdk/app.py +4266 -0
  73. hpcflow/sdk/cli.py +1479 -0
  74. hpcflow/sdk/cli_common.py +385 -0
  75. hpcflow/sdk/config/__init__.py +5 -0
  76. hpcflow/sdk/config/callbacks.py +246 -0
  77. hpcflow/sdk/config/cli.py +388 -0
  78. hpcflow/sdk/config/config.py +1410 -0
  79. hpcflow/sdk/config/config_file.py +501 -0
  80. hpcflow/sdk/config/errors.py +272 -0
  81. hpcflow/sdk/config/types.py +150 -0
  82. hpcflow/sdk/core/__init__.py +38 -0
  83. hpcflow/sdk/core/actions.py +3857 -0
  84. hpcflow/sdk/core/app_aware.py +25 -0
  85. hpcflow/sdk/core/cache.py +224 -0
  86. hpcflow/sdk/core/command_files.py +814 -0
  87. hpcflow/sdk/core/commands.py +424 -0
  88. hpcflow/sdk/core/element.py +2071 -0
  89. hpcflow/sdk/core/enums.py +221 -0
  90. hpcflow/sdk/core/environment.py +256 -0
  91. hpcflow/sdk/core/errors.py +1043 -0
  92. hpcflow/sdk/core/execute.py +207 -0
  93. hpcflow/sdk/core/json_like.py +809 -0
  94. hpcflow/sdk/core/loop.py +1320 -0
  95. hpcflow/sdk/core/loop_cache.py +282 -0
  96. hpcflow/sdk/core/object_list.py +933 -0
  97. hpcflow/sdk/core/parameters.py +3371 -0
  98. hpcflow/sdk/core/rule.py +196 -0
  99. hpcflow/sdk/core/run_dir_files.py +57 -0
  100. hpcflow/sdk/core/skip_reason.py +7 -0
  101. hpcflow/sdk/core/task.py +3792 -0
  102. hpcflow/sdk/core/task_schema.py +993 -0
  103. hpcflow/sdk/core/test_utils.py +538 -0
  104. hpcflow/sdk/core/types.py +447 -0
  105. hpcflow/sdk/core/utils.py +1207 -0
  106. hpcflow/sdk/core/validation.py +87 -0
  107. hpcflow/sdk/core/values.py +477 -0
  108. hpcflow/sdk/core/workflow.py +4820 -0
  109. hpcflow/sdk/core/zarr_io.py +206 -0
  110. hpcflow/sdk/data/__init__.py +13 -0
  111. hpcflow/sdk/data/config_file_schema.yaml +34 -0
  112. hpcflow/sdk/data/config_schema.yaml +260 -0
  113. hpcflow/sdk/data/environments_spec_schema.yaml +21 -0
  114. hpcflow/sdk/data/files_spec_schema.yaml +5 -0
  115. hpcflow/sdk/data/parameters_spec_schema.yaml +7 -0
  116. hpcflow/sdk/data/task_schema_spec_schema.yaml +3 -0
  117. hpcflow/sdk/data/workflow_spec_schema.yaml +22 -0
  118. hpcflow/sdk/demo/__init__.py +3 -0
  119. hpcflow/sdk/demo/cli.py +242 -0
  120. hpcflow/sdk/helper/__init__.py +3 -0
  121. hpcflow/sdk/helper/cli.py +137 -0
  122. hpcflow/sdk/helper/helper.py +300 -0
  123. hpcflow/sdk/helper/watcher.py +192 -0
  124. hpcflow/sdk/log.py +288 -0
  125. hpcflow/sdk/persistence/__init__.py +18 -0
  126. hpcflow/sdk/persistence/base.py +2817 -0
  127. hpcflow/sdk/persistence/defaults.py +6 -0
  128. hpcflow/sdk/persistence/discovery.py +39 -0
  129. hpcflow/sdk/persistence/json.py +954 -0
  130. hpcflow/sdk/persistence/pending.py +948 -0
  131. hpcflow/sdk/persistence/store_resource.py +203 -0
  132. hpcflow/sdk/persistence/types.py +309 -0
  133. hpcflow/sdk/persistence/utils.py +73 -0
  134. hpcflow/sdk/persistence/zarr.py +2388 -0
  135. hpcflow/sdk/runtime.py +320 -0
  136. hpcflow/sdk/submission/__init__.py +3 -0
  137. hpcflow/sdk/submission/enums.py +70 -0
  138. hpcflow/sdk/submission/jobscript.py +2379 -0
  139. hpcflow/sdk/submission/schedulers/__init__.py +281 -0
  140. hpcflow/sdk/submission/schedulers/direct.py +233 -0
  141. hpcflow/sdk/submission/schedulers/sge.py +376 -0
  142. hpcflow/sdk/submission/schedulers/slurm.py +598 -0
  143. hpcflow/sdk/submission/schedulers/utils.py +25 -0
  144. hpcflow/sdk/submission/shells/__init__.py +52 -0
  145. hpcflow/sdk/submission/shells/base.py +229 -0
  146. hpcflow/sdk/submission/shells/bash.py +504 -0
  147. hpcflow/sdk/submission/shells/os_version.py +115 -0
  148. hpcflow/sdk/submission/shells/powershell.py +352 -0
  149. hpcflow/sdk/submission/submission.py +1402 -0
  150. hpcflow/sdk/submission/types.py +140 -0
  151. hpcflow/sdk/typing.py +194 -0
  152. hpcflow/sdk/utils/arrays.py +69 -0
  153. hpcflow/sdk/utils/deferred_file.py +55 -0
  154. hpcflow/sdk/utils/hashing.py +16 -0
  155. hpcflow/sdk/utils/patches.py +31 -0
  156. hpcflow/sdk/utils/strings.py +69 -0
  157. hpcflow/tests/api/test_api.py +32 -0
  158. hpcflow/tests/conftest.py +123 -0
  159. hpcflow/tests/data/__init__.py +0 -0
  160. hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
  161. hpcflow/tests/data/benchmark_script_runner.yaml +26 -0
  162. hpcflow/tests/data/multi_path_sequences.yaml +29 -0
  163. hpcflow/tests/data/workflow_1.json +10 -0
  164. hpcflow/tests/data/workflow_1.yaml +5 -0
  165. hpcflow/tests/data/workflow_1_slurm.yaml +8 -0
  166. hpcflow/tests/data/workflow_1_wsl.yaml +8 -0
  167. hpcflow/tests/data/workflow_test_run_abort.yaml +42 -0
  168. hpcflow/tests/jinja_templates/test_jinja_templates.py +161 -0
  169. hpcflow/tests/programs/test_programs.py +180 -0
  170. hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +12 -0
  171. hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
  172. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +14 -0
  173. hpcflow/tests/scripts/test_input_file_generators.py +282 -0
  174. hpcflow/tests/scripts/test_main_scripts.py +1361 -0
  175. hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
  176. hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
  177. hpcflow/tests/shells/wsl/test_wsl_submission.py +14 -0
  178. hpcflow/tests/unit/test_action.py +1066 -0
  179. hpcflow/tests/unit/test_action_rule.py +24 -0
  180. hpcflow/tests/unit/test_app.py +132 -0
  181. hpcflow/tests/unit/test_cache.py +46 -0
  182. hpcflow/tests/unit/test_cli.py +172 -0
  183. hpcflow/tests/unit/test_command.py +377 -0
  184. hpcflow/tests/unit/test_config.py +195 -0
  185. hpcflow/tests/unit/test_config_file.py +162 -0
  186. hpcflow/tests/unit/test_element.py +666 -0
  187. hpcflow/tests/unit/test_element_iteration.py +88 -0
  188. hpcflow/tests/unit/test_element_set.py +158 -0
  189. hpcflow/tests/unit/test_group.py +115 -0
  190. hpcflow/tests/unit/test_input_source.py +1479 -0
  191. hpcflow/tests/unit/test_input_value.py +398 -0
  192. hpcflow/tests/unit/test_jobscript_unit.py +757 -0
  193. hpcflow/tests/unit/test_json_like.py +1247 -0
  194. hpcflow/tests/unit/test_loop.py +2674 -0
  195. hpcflow/tests/unit/test_meta_task.py +325 -0
  196. hpcflow/tests/unit/test_multi_path_sequences.py +259 -0
  197. hpcflow/tests/unit/test_object_list.py +116 -0
  198. hpcflow/tests/unit/test_parameter.py +243 -0
  199. hpcflow/tests/unit/test_persistence.py +664 -0
  200. hpcflow/tests/unit/test_resources.py +243 -0
  201. hpcflow/tests/unit/test_run.py +286 -0
  202. hpcflow/tests/unit/test_run_directories.py +29 -0
  203. hpcflow/tests/unit/test_runtime.py +9 -0
  204. hpcflow/tests/unit/test_schema_input.py +372 -0
  205. hpcflow/tests/unit/test_shell.py +129 -0
  206. hpcflow/tests/unit/test_slurm.py +39 -0
  207. hpcflow/tests/unit/test_submission.py +502 -0
  208. hpcflow/tests/unit/test_task.py +2560 -0
  209. hpcflow/tests/unit/test_task_schema.py +182 -0
  210. hpcflow/tests/unit/test_utils.py +616 -0
  211. hpcflow/tests/unit/test_value_sequence.py +549 -0
  212. hpcflow/tests/unit/test_values.py +91 -0
  213. hpcflow/tests/unit/test_workflow.py +827 -0
  214. hpcflow/tests/unit/test_workflow_template.py +186 -0
  215. hpcflow/tests/unit/utils/test_arrays.py +40 -0
  216. hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
  217. hpcflow/tests/unit/utils/test_hashing.py +65 -0
  218. hpcflow/tests/unit/utils/test_patches.py +5 -0
  219. hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
  220. hpcflow/tests/unit/utils/test_strings.py +97 -0
  221. hpcflow/tests/workflows/__init__.py +0 -0
  222. hpcflow/tests/workflows/test_directory_structure.py +31 -0
  223. hpcflow/tests/workflows/test_jobscript.py +355 -0
  224. hpcflow/tests/workflows/test_run_status.py +198 -0
  225. hpcflow/tests/workflows/test_skip_downstream.py +696 -0
  226. hpcflow/tests/workflows/test_submission.py +140 -0
  227. hpcflow/tests/workflows/test_workflows.py +564 -0
  228. hpcflow/tests/workflows/test_zip.py +18 -0
  229. hpcflow/viz_demo.ipynb +6794 -0
  230. hpcflow-0.2.0a271.dist-info/LICENSE +375 -0
  231. hpcflow-0.2.0a271.dist-info/METADATA +65 -0
  232. hpcflow-0.2.0a271.dist-info/RECORD +237 -0
  233. {hpcflow-0.1.9.dist-info → hpcflow-0.2.0a271.dist-info}/WHEEL +4 -5
  234. hpcflow-0.2.0a271.dist-info/entry_points.txt +6 -0
  235. hpcflow/api.py +0 -458
  236. hpcflow/archive/archive.py +0 -308
  237. hpcflow/archive/cloud/cloud.py +0 -47
  238. hpcflow/archive/cloud/errors.py +0 -9
  239. hpcflow/archive/cloud/providers/dropbox.py +0 -432
  240. hpcflow/archive/errors.py +0 -5
  241. hpcflow/base_db.py +0 -4
  242. hpcflow/config.py +0 -232
  243. hpcflow/copytree.py +0 -66
  244. hpcflow/data/examples/_config.yml +0 -14
  245. hpcflow/data/examples/damask/demo/1.run.yml +0 -4
  246. hpcflow/data/examples/damask/demo/2.process.yml +0 -29
  247. hpcflow/data/examples/damask/demo/geom.geom +0 -2052
  248. hpcflow/data/examples/damask/demo/load.load +0 -1
  249. hpcflow/data/examples/damask/demo/material.config +0 -185
  250. hpcflow/data/examples/damask/inputs/geom.geom +0 -2052
  251. hpcflow/data/examples/damask/inputs/load.load +0 -1
  252. hpcflow/data/examples/damask/inputs/material.config +0 -185
  253. hpcflow/data/examples/damask/profiles/_variable_lookup.yml +0 -21
  254. hpcflow/data/examples/damask/profiles/damask.yml +0 -4
  255. hpcflow/data/examples/damask/profiles/damask_process.yml +0 -8
  256. hpcflow/data/examples/damask/profiles/damask_run.yml +0 -5
  257. hpcflow/data/examples/damask/profiles/default.yml +0 -6
  258. hpcflow/data/examples/thinking.yml +0 -177
  259. hpcflow/errors.py +0 -2
  260. hpcflow/init_db.py +0 -37
  261. hpcflow/models.py +0 -2549
  262. hpcflow/nesting.py +0 -9
  263. hpcflow/profiles.py +0 -455
  264. hpcflow/project.py +0 -81
  265. hpcflow/scheduler.py +0 -323
  266. hpcflow/utils.py +0 -103
  267. hpcflow/validation.py +0 -167
  268. hpcflow/variables.py +0 -544
  269. hpcflow-0.1.9.dist-info/METADATA +0 -168
  270. hpcflow-0.1.9.dist-info/RECORD +0 -45
  271. hpcflow-0.1.9.dist-info/entry_points.txt +0 -8
  272. hpcflow-0.1.9.dist-info/top_level.txt +0 -1
  273. /hpcflow/{archive → data/jinja_templates}/__init__.py +0 -0
  274. /hpcflow/{archive/cloud → data/programs}/__init__.py +0 -0
  275. /hpcflow/{archive/cloud/providers → data/workflows}/__init__.py +0 -0
@@ -0,0 +1,25 @@
1
+ """
2
+ Utility base class for making classes aware of the overall application context.
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from typing import ClassVar
10
+ from ..app import BaseApp
11
+
12
+
13
+ class AppAware:
14
+ """
15
+ A base class that marks its subclasses as aware of the application.
16
+
17
+ Attributes
18
+ ----------
19
+ _app: BaseApp
20
+ A class attribute that holds the application instance.
21
+ """
22
+
23
+ __slots__: ClassVar[tuple[str, ...]] = ()
24
+ _app: ClassVar[BaseApp]
25
+ _app_attr: ClassVar[str] = "_app"
@@ -0,0 +1,224 @@
1
+ """
2
+ Dependency resolution cache.
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from collections import defaultdict
7
+ from dataclasses import dataclass
8
+ from itertools import chain
9
+ from typing import TYPE_CHECKING
10
+
11
+ from hpcflow.sdk.log import TimeIt
12
+
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Sequence
15
+ from typing_extensions import Self
16
+ from .element import Element, ElementIteration
17
+ from .actions import ElementActionRun
18
+ from .workflow import Workflow
19
+ from ..persistence.base import StoreEAR, StoreElement, StoreElementIter
20
+
21
+
22
+ @dataclass
23
+ class ObjectCache:
24
+ """Class to bulk-retrieve and store elements, iterations, runs and their various
25
+ dependencies."""
26
+
27
+ #: The elements of the workflow that this cache was built from.
28
+ elements: list[Element] | None = None
29
+ #: The iterations of the workflow that this cache was built from.
30
+ iterations: list[ElementIteration] | None = None
31
+ #: The runs of the workflow that this cache was built from.
32
+ runs: list[ElementActionRun] | None = None
33
+
34
+ #: What EARs (by ID) a given EAR depends on.
35
+ run_dependencies: dict[int, set[int]] | None = None
36
+ #: What EARs (by ID) are depending on a given EAR.
37
+ run_dependents: dict[int, set[int]] | None = None
38
+ #: What EARs (by ID) a given iteration depends on.
39
+ iter_run_dependencies: dict[int, set[int]] | None = None
40
+ #: What iterations (by ID) a given iteration depends on.
41
+ iter_iter_dependencies: dict[int, set[int]] | None = None
42
+ #: What iterations (by ID) a given element depends on.
43
+ elem_iter_dependencies: dict[int, set[int]] | None = None
44
+ #: What elements (by ID) a given element depends on.
45
+ elem_elem_dependencies: dict[int, set[int]] | None = None
46
+ #: What elements (by ID) are depending on a given element.
47
+ elem_elem_dependents: dict[int, set[int]] | None = None
48
+ #: Transitive closure of :py:attr:`elem_elem_dependents`.
49
+ elem_elem_dependents_rec: dict[int, set[int]] | None = None
50
+
51
+ @classmethod
52
+ @TimeIt.decorator
53
+ def build(
54
+ cls,
55
+ workflow: Workflow,
56
+ dependencies: bool = False,
57
+ elements: bool = False,
58
+ iterations: bool = False,
59
+ runs: bool = False,
60
+ ):
61
+ """
62
+ Build a cache instance.
63
+
64
+ Parameters
65
+ ----------
66
+ workflow: ~hpcflow.app.Workflow
67
+ The workflow to build the cache from.
68
+ dependencies
69
+ If True, calculate dependencies.
70
+ elements
71
+ If True, include elements in the cache.
72
+ iterations
73
+ If True, include iterations in the cache.
74
+ runs
75
+ If True, include runs in the cache.
76
+
77
+ """
78
+ kwargs = {}
79
+ if dependencies:
80
+ kwargs.update(cls._get_dependencies(workflow))
81
+
82
+ if elements:
83
+ kwargs["elements"] = workflow.get_all_elements()
84
+
85
+ if iterations:
86
+ kwargs["iterations"] = workflow.get_all_element_iterations()
87
+
88
+ if runs:
89
+ kwargs["runs"] = workflow.get_all_EARs()
90
+
91
+ return cls(**kwargs)
92
+
93
+ @classmethod
94
+ @TimeIt.decorator
95
+ def _get_dependencies(cls, workflow: Workflow):
96
+ def _get_recursive_deps(elem_id: int, seen_ids: list[int] | None = None):
97
+ if seen_ids is None:
98
+ seen_ids = [elem_id]
99
+ elif elem_id in seen_ids:
100
+ # stop recursion
101
+ return set()
102
+ else:
103
+ seen_ids.append(elem_id)
104
+ return set(elem_elem_dependents[elem_id]).union(
105
+ [
106
+ j
107
+ for i in elem_elem_dependents[elem_id]
108
+ for j in _get_recursive_deps(i, seen_ids)
109
+ if j != elem_id
110
+ ]
111
+ )
112
+
113
+ num_iters = workflow.num_element_iterations
114
+ num_elems = workflow.num_elements
115
+ num_runs = workflow.num_EARs
116
+
117
+ all_store_runs: Sequence[StoreEAR] = workflow._store.get_EARs(range(num_runs))
118
+ all_store_iters: Sequence[StoreElementIter] = (
119
+ workflow._store.get_element_iterations(range(num_iters))
120
+ )
121
+ all_store_elements: Sequence[StoreElement] = workflow._store.get_elements(
122
+ range(num_elems)
123
+ )
124
+ all_param_sources = workflow.get_all_parameter_sources()
125
+ all_data_idx = (
126
+ {
127
+ k: v if isinstance(v, list) else [v]
128
+ for k, v in store_ear.data_idx.items()
129
+ if not k.startswith("repeats.")
130
+ }
131
+ for store_ear in all_store_runs
132
+ )
133
+
134
+ # run dependencies and dependents
135
+ run_dependencies: dict[int, set[int]] = {}
136
+ run_dependents: defaultdict[int, set[int]] = defaultdict(set)
137
+ for idx, dict_i in enumerate(all_data_idx):
138
+ run_i_sources = set(
139
+ run_k
140
+ for dat_idx_k in chain.from_iterable(dict_i.values())
141
+ if (run_k := all_param_sources[dat_idx_k].get("EAR_ID")) is not None
142
+ and run_k != idx
143
+ )
144
+ run_dependencies[idx] = run_i_sources
145
+ for m in run_i_sources:
146
+ run_dependents[m].add(idx)
147
+
148
+ # add missing and downgrade to dict:
149
+ for run_idx in range(num_runs):
150
+ run_dependents[run_idx]
151
+ run_dependents.default_factory = None
152
+
153
+ # iteration dependencies
154
+ all_iter_run_IDs = {
155
+ iter_.id_: tuple(chain.from_iterable((iter_.EAR_IDs or {}).values()))
156
+ for iter_ in all_store_iters
157
+ }
158
+ # for each iteration, which runs does it depend on?
159
+ iter_run_dependencies = {
160
+ k: set(j for idx in v for j in run_dependencies[idx])
161
+ for k, v in all_iter_run_IDs.items()
162
+ }
163
+
164
+ # for each run, which iteration does it belong to?
165
+ all_run_iter_IDs = {
166
+ run_ID: iter_ID
167
+ for iter_ID, run_IDs in all_iter_run_IDs.items()
168
+ for run_ID in run_IDs
169
+ }
170
+
171
+ # for each iteration, which iterations does it depend on?
172
+ iter_iter_dependencies = {
173
+ k: set(all_run_iter_IDs[i] for i in v)
174
+ for k, v in iter_run_dependencies.items()
175
+ }
176
+
177
+ all_elem_iter_IDs = {el.id_: el.iteration_IDs for el in all_store_elements}
178
+
179
+ elem_iter_dependencies = {
180
+ elem_ID: set(j for i in iter_IDs for j in iter_iter_dependencies[i])
181
+ for elem_ID, iter_IDs in all_elem_iter_IDs.items()
182
+ }
183
+
184
+ # for each iteration, which element does it belong to?
185
+ all_iter_elem_IDs = {
186
+ iter_ID: elem_ID
187
+ for elem_ID, iter_IDs in all_elem_iter_IDs.items()
188
+ for iter_ID in iter_IDs
189
+ }
190
+
191
+ # element dependencies
192
+ elem_elem_dependencies = {
193
+ k: set(all_iter_elem_IDs[i] for i in dep_set)
194
+ for k, dep_set in elem_iter_dependencies.items()
195
+ }
196
+
197
+ # for each element, which elements depend on it (directly)?
198
+ elem_elem_dependents: defaultdict[int, set[int]] = defaultdict(set)
199
+ for k, dep_set in elem_elem_dependencies.items():
200
+ for i in dep_set:
201
+ elem_elem_dependents[i].add(k)
202
+
203
+ # for each element, which elements depend on it (recursively)?
204
+ elem_elem_dependents_rec: defaultdict[int, set[int]] = defaultdict(set)
205
+ for i in list(elem_elem_dependents):
206
+ elem_elem_dependents_rec[i] = _get_recursive_deps(i)
207
+
208
+ # add missing keys and downgrade to dict:
209
+ for elem_idx in range(num_elems):
210
+ elem_elem_dependents[elem_idx]
211
+ elem_elem_dependents_rec[elem_idx]
212
+ elem_elem_dependents.default_factory = None
213
+ elem_elem_dependents_rec.default_factory = None
214
+
215
+ return dict(
216
+ run_dependencies=run_dependencies,
217
+ run_dependents=run_dependents,
218
+ iter_run_dependencies=iter_run_dependencies,
219
+ iter_iter_dependencies=iter_iter_dependencies,
220
+ elem_iter_dependencies=elem_iter_dependencies,
221
+ elem_elem_dependencies=elem_elem_dependencies,
222
+ elem_elem_dependents=elem_elem_dependents,
223
+ elem_elem_dependents_rec=elem_elem_dependents_rec,
224
+ )