sierra-research 1.3.6__py3-none-any.whl → 1.5.0__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 (254) hide show
  1. sierra/__init__.py +3 -3
  2. sierra/core/__init__.py +3 -3
  3. sierra/core/batchroot.py +223 -0
  4. sierra/core/cmdline.py +681 -1057
  5. sierra/core/compare.py +11 -0
  6. sierra/core/config.py +96 -88
  7. sierra/core/engine.py +306 -0
  8. sierra/core/execenv.py +380 -0
  9. sierra/core/expdef.py +11 -0
  10. sierra/core/experiment/__init__.py +1 -0
  11. sierra/core/experiment/bindings.py +150 -101
  12. sierra/core/experiment/definition.py +414 -245
  13. sierra/core/experiment/spec.py +83 -85
  14. sierra/core/exproot.py +44 -0
  15. sierra/core/generators/__init__.py +10 -0
  16. sierra/core/generators/experiment.py +528 -0
  17. sierra/core/generators/generator_factory.py +138 -137
  18. sierra/core/graphs/__init__.py +23 -0
  19. sierra/core/graphs/bcbridge.py +94 -0
  20. sierra/core/graphs/heatmap.py +245 -324
  21. sierra/core/graphs/pathset.py +27 -0
  22. sierra/core/graphs/schema.py +77 -0
  23. sierra/core/graphs/stacked_line.py +341 -0
  24. sierra/core/graphs/summary_line.py +506 -0
  25. sierra/core/logging.py +3 -2
  26. sierra/core/models/__init__.py +3 -1
  27. sierra/core/models/info.py +19 -0
  28. sierra/core/models/interface.py +52 -122
  29. sierra/core/pipeline/__init__.py +2 -5
  30. sierra/core/pipeline/pipeline.py +228 -126
  31. sierra/core/pipeline/stage1/__init__.py +10 -0
  32. sierra/core/pipeline/stage1/pipeline_stage1.py +45 -31
  33. sierra/core/pipeline/stage2/__init__.py +10 -0
  34. sierra/core/pipeline/stage2/pipeline_stage2.py +8 -11
  35. sierra/core/pipeline/stage2/runner.py +401 -0
  36. sierra/core/pipeline/stage3/__init__.py +12 -0
  37. sierra/core/pipeline/stage3/gather.py +321 -0
  38. sierra/core/pipeline/stage3/pipeline_stage3.py +37 -84
  39. sierra/core/pipeline/stage4/__init__.py +12 -2
  40. sierra/core/pipeline/stage4/pipeline_stage4.py +36 -354
  41. sierra/core/pipeline/stage5/__init__.py +12 -0
  42. sierra/core/pipeline/stage5/pipeline_stage5.py +33 -208
  43. sierra/core/pipeline/yaml.py +48 -0
  44. sierra/core/plugin.py +529 -62
  45. sierra/core/proc.py +11 -0
  46. sierra/core/prod.py +11 -0
  47. sierra/core/ros1/__init__.py +5 -1
  48. sierra/core/ros1/callbacks.py +22 -21
  49. sierra/core/ros1/cmdline.py +59 -88
  50. sierra/core/ros1/generators.py +159 -175
  51. sierra/core/ros1/variables/__init__.py +3 -0
  52. sierra/core/ros1/variables/exp_setup.py +122 -116
  53. sierra/core/startup.py +106 -76
  54. sierra/core/stat_kernels.py +4 -5
  55. sierra/core/storage.py +13 -32
  56. sierra/core/trampoline.py +30 -0
  57. sierra/core/types.py +116 -71
  58. sierra/core/utils.py +103 -106
  59. sierra/core/variables/__init__.py +1 -1
  60. sierra/core/variables/base_variable.py +12 -17
  61. sierra/core/variables/batch_criteria.py +387 -481
  62. sierra/core/variables/builtin.py +135 -0
  63. sierra/core/variables/exp_setup.py +19 -39
  64. sierra/core/variables/population_size.py +72 -76
  65. sierra/core/variables/variable_density.py +44 -68
  66. sierra/core/vector.py +1 -1
  67. sierra/main.py +256 -88
  68. sierra/plugins/__init__.py +119 -0
  69. sierra/plugins/compare/__init__.py +14 -0
  70. sierra/plugins/compare/graphs/__init__.py +19 -0
  71. sierra/plugins/compare/graphs/cmdline.py +120 -0
  72. sierra/plugins/compare/graphs/comparator.py +291 -0
  73. sierra/plugins/compare/graphs/inter_controller.py +531 -0
  74. sierra/plugins/compare/graphs/inter_scenario.py +297 -0
  75. sierra/plugins/compare/graphs/namecalc.py +53 -0
  76. sierra/plugins/compare/graphs/outputroot.py +73 -0
  77. sierra/plugins/compare/graphs/plugin.py +147 -0
  78. sierra/plugins/compare/graphs/preprocess.py +172 -0
  79. sierra/plugins/compare/graphs/schema.py +37 -0
  80. sierra/plugins/engine/__init__.py +14 -0
  81. sierra/plugins/engine/argos/__init__.py +18 -0
  82. sierra/plugins/{platform → engine}/argos/cmdline.py +144 -151
  83. sierra/plugins/{platform/argos/variables → engine/argos/generators}/__init__.py +5 -0
  84. sierra/plugins/engine/argos/generators/engine.py +394 -0
  85. sierra/plugins/engine/argos/plugin.py +393 -0
  86. sierra/plugins/{platform/argos/generators → engine/argos/variables}/__init__.py +5 -0
  87. sierra/plugins/engine/argos/variables/arena_shape.py +183 -0
  88. sierra/plugins/engine/argos/variables/cameras.py +240 -0
  89. sierra/plugins/engine/argos/variables/constant_density.py +112 -0
  90. sierra/plugins/engine/argos/variables/exp_setup.py +82 -0
  91. sierra/plugins/{platform → engine}/argos/variables/physics_engines.py +83 -87
  92. sierra/plugins/engine/argos/variables/population_constant_density.py +178 -0
  93. sierra/plugins/engine/argos/variables/population_size.py +115 -0
  94. sierra/plugins/engine/argos/variables/population_variable_density.py +123 -0
  95. sierra/plugins/engine/argos/variables/rendering.py +108 -0
  96. sierra/plugins/engine/ros1gazebo/__init__.py +18 -0
  97. sierra/plugins/engine/ros1gazebo/cmdline.py +175 -0
  98. sierra/plugins/{platform/ros1robot → engine/ros1gazebo}/generators/__init__.py +5 -0
  99. sierra/plugins/engine/ros1gazebo/generators/engine.py +125 -0
  100. sierra/plugins/engine/ros1gazebo/plugin.py +404 -0
  101. sierra/plugins/engine/ros1gazebo/variables/__init__.py +15 -0
  102. sierra/plugins/engine/ros1gazebo/variables/population_size.py +214 -0
  103. sierra/plugins/engine/ros1robot/__init__.py +18 -0
  104. sierra/plugins/engine/ros1robot/cmdline.py +159 -0
  105. sierra/plugins/{platform/ros1gazebo → engine/ros1robot}/generators/__init__.py +4 -0
  106. sierra/plugins/engine/ros1robot/generators/engine.py +95 -0
  107. sierra/plugins/engine/ros1robot/plugin.py +410 -0
  108. sierra/plugins/{hpc/local → engine/ros1robot/variables}/__init__.py +5 -0
  109. sierra/plugins/engine/ros1robot/variables/population_size.py +146 -0
  110. sierra/plugins/execenv/__init__.py +11 -0
  111. sierra/plugins/execenv/hpc/__init__.py +18 -0
  112. sierra/plugins/execenv/hpc/adhoc/__init__.py +18 -0
  113. sierra/plugins/execenv/hpc/adhoc/cmdline.py +30 -0
  114. sierra/plugins/execenv/hpc/adhoc/plugin.py +131 -0
  115. sierra/plugins/execenv/hpc/cmdline.py +137 -0
  116. sierra/plugins/execenv/hpc/local/__init__.py +18 -0
  117. sierra/plugins/execenv/hpc/local/cmdline.py +31 -0
  118. sierra/plugins/execenv/hpc/local/plugin.py +145 -0
  119. sierra/plugins/execenv/hpc/pbs/__init__.py +18 -0
  120. sierra/plugins/execenv/hpc/pbs/cmdline.py +30 -0
  121. sierra/plugins/execenv/hpc/pbs/plugin.py +121 -0
  122. sierra/plugins/execenv/hpc/slurm/__init__.py +18 -0
  123. sierra/plugins/execenv/hpc/slurm/cmdline.py +30 -0
  124. sierra/plugins/execenv/hpc/slurm/plugin.py +133 -0
  125. sierra/plugins/execenv/prefectserver/__init__.py +18 -0
  126. sierra/plugins/execenv/prefectserver/cmdline.py +66 -0
  127. sierra/plugins/execenv/prefectserver/dockerremote/__init__.py +18 -0
  128. sierra/plugins/execenv/prefectserver/dockerremote/cmdline.py +66 -0
  129. sierra/plugins/execenv/prefectserver/dockerremote/plugin.py +132 -0
  130. sierra/plugins/execenv/prefectserver/flow.py +66 -0
  131. sierra/plugins/execenv/prefectserver/local/__init__.py +18 -0
  132. sierra/plugins/execenv/prefectserver/local/cmdline.py +29 -0
  133. sierra/plugins/execenv/prefectserver/local/plugin.py +133 -0
  134. sierra/plugins/{hpc/adhoc → execenv/robot}/__init__.py +1 -0
  135. sierra/plugins/execenv/robot/turtlebot3/__init__.py +18 -0
  136. sierra/plugins/execenv/robot/turtlebot3/plugin.py +204 -0
  137. sierra/plugins/expdef/__init__.py +14 -0
  138. sierra/plugins/expdef/json/__init__.py +14 -0
  139. sierra/plugins/expdef/json/plugin.py +504 -0
  140. sierra/plugins/expdef/xml/__init__.py +14 -0
  141. sierra/plugins/expdef/xml/plugin.py +386 -0
  142. sierra/{core/hpc → plugins/proc}/__init__.py +1 -1
  143. sierra/plugins/proc/collate/__init__.py +15 -0
  144. sierra/plugins/proc/collate/cmdline.py +47 -0
  145. sierra/plugins/proc/collate/plugin.py +271 -0
  146. sierra/plugins/proc/compress/__init__.py +18 -0
  147. sierra/plugins/proc/compress/cmdline.py +47 -0
  148. sierra/plugins/proc/compress/plugin.py +123 -0
  149. sierra/plugins/proc/decompress/__init__.py +18 -0
  150. sierra/plugins/proc/decompress/plugin.py +96 -0
  151. sierra/plugins/proc/imagize/__init__.py +15 -0
  152. sierra/plugins/proc/imagize/cmdline.py +49 -0
  153. sierra/plugins/proc/imagize/plugin.py +270 -0
  154. sierra/plugins/proc/modelrunner/__init__.py +16 -0
  155. sierra/plugins/proc/modelrunner/plugin.py +250 -0
  156. sierra/plugins/proc/statistics/__init__.py +15 -0
  157. sierra/plugins/proc/statistics/cmdline.py +64 -0
  158. sierra/plugins/proc/statistics/plugin.py +390 -0
  159. sierra/plugins/{hpc → prod}/__init__.py +1 -0
  160. sierra/plugins/prod/graphs/__init__.py +18 -0
  161. sierra/plugins/prod/graphs/cmdline.py +269 -0
  162. sierra/plugins/prod/graphs/collate.py +279 -0
  163. sierra/plugins/prod/graphs/inter/__init__.py +13 -0
  164. sierra/plugins/prod/graphs/inter/generate.py +83 -0
  165. sierra/plugins/prod/graphs/inter/heatmap.py +86 -0
  166. sierra/plugins/prod/graphs/inter/line.py +134 -0
  167. sierra/plugins/prod/graphs/intra/__init__.py +15 -0
  168. sierra/plugins/prod/graphs/intra/generate.py +202 -0
  169. sierra/plugins/prod/graphs/intra/heatmap.py +74 -0
  170. sierra/plugins/prod/graphs/intra/line.py +114 -0
  171. sierra/plugins/prod/graphs/plugin.py +103 -0
  172. sierra/plugins/prod/graphs/targets.py +63 -0
  173. sierra/plugins/prod/render/__init__.py +18 -0
  174. sierra/plugins/prod/render/cmdline.py +72 -0
  175. sierra/plugins/prod/render/plugin.py +282 -0
  176. sierra/plugins/storage/__init__.py +5 -0
  177. sierra/plugins/storage/arrow/__init__.py +18 -0
  178. sierra/plugins/storage/arrow/plugin.py +38 -0
  179. sierra/plugins/storage/csv/__init__.py +9 -0
  180. sierra/plugins/storage/csv/plugin.py +12 -5
  181. sierra/version.py +3 -2
  182. sierra_research-1.5.0.dist-info/METADATA +238 -0
  183. sierra_research-1.5.0.dist-info/RECORD +186 -0
  184. {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/WHEEL +1 -2
  185. sierra/core/experiment/xml.py +0 -454
  186. sierra/core/generators/controller_generator_parser.py +0 -34
  187. sierra/core/generators/exp_creator.py +0 -351
  188. sierra/core/generators/exp_generators.py +0 -142
  189. sierra/core/graphs/scatterplot2D.py +0 -109
  190. sierra/core/graphs/stacked_line_graph.py +0 -249
  191. sierra/core/graphs/stacked_surface_graph.py +0 -220
  192. sierra/core/graphs/summary_line_graph.py +0 -369
  193. sierra/core/hpc/cmdline.py +0 -142
  194. sierra/core/models/graphs.py +0 -87
  195. sierra/core/pipeline/stage2/exp_runner.py +0 -286
  196. sierra/core/pipeline/stage3/imagizer.py +0 -149
  197. sierra/core/pipeline/stage3/run_collator.py +0 -317
  198. sierra/core/pipeline/stage3/statistics_calculator.py +0 -478
  199. sierra/core/pipeline/stage4/graph_collator.py +0 -319
  200. sierra/core/pipeline/stage4/inter_exp_graph_generator.py +0 -240
  201. sierra/core/pipeline/stage4/intra_exp_graph_generator.py +0 -317
  202. sierra/core/pipeline/stage4/model_runner.py +0 -168
  203. sierra/core/pipeline/stage4/rendering.py +0 -283
  204. sierra/core/pipeline/stage4/yaml_config_loader.py +0 -103
  205. sierra/core/pipeline/stage5/inter_scenario_comparator.py +0 -328
  206. sierra/core/pipeline/stage5/intra_scenario_comparator.py +0 -989
  207. sierra/core/platform.py +0 -493
  208. sierra/core/plugin_manager.py +0 -369
  209. sierra/core/root_dirpath_generator.py +0 -241
  210. sierra/plugins/hpc/adhoc/plugin.py +0 -125
  211. sierra/plugins/hpc/local/plugin.py +0 -81
  212. sierra/plugins/hpc/pbs/__init__.py +0 -9
  213. sierra/plugins/hpc/pbs/plugin.py +0 -126
  214. sierra/plugins/hpc/slurm/__init__.py +0 -9
  215. sierra/plugins/hpc/slurm/plugin.py +0 -130
  216. sierra/plugins/platform/__init__.py +0 -9
  217. sierra/plugins/platform/argos/__init__.py +0 -9
  218. sierra/plugins/platform/argos/generators/platform_generators.py +0 -383
  219. sierra/plugins/platform/argos/plugin.py +0 -337
  220. sierra/plugins/platform/argos/variables/arena_shape.py +0 -145
  221. sierra/plugins/platform/argos/variables/cameras.py +0 -243
  222. sierra/plugins/platform/argos/variables/constant_density.py +0 -136
  223. sierra/plugins/platform/argos/variables/exp_setup.py +0 -113
  224. sierra/plugins/platform/argos/variables/population_constant_density.py +0 -175
  225. sierra/plugins/platform/argos/variables/population_size.py +0 -102
  226. sierra/plugins/platform/argos/variables/population_variable_density.py +0 -132
  227. sierra/plugins/platform/argos/variables/rendering.py +0 -104
  228. sierra/plugins/platform/ros1gazebo/__init__.py +0 -9
  229. sierra/plugins/platform/ros1gazebo/cmdline.py +0 -213
  230. sierra/plugins/platform/ros1gazebo/generators/platform_generators.py +0 -137
  231. sierra/plugins/platform/ros1gazebo/plugin.py +0 -335
  232. sierra/plugins/platform/ros1gazebo/variables/__init__.py +0 -10
  233. sierra/plugins/platform/ros1gazebo/variables/population_size.py +0 -204
  234. sierra/plugins/platform/ros1robot/__init__.py +0 -9
  235. sierra/plugins/platform/ros1robot/cmdline.py +0 -175
  236. sierra/plugins/platform/ros1robot/generators/platform_generators.py +0 -112
  237. sierra/plugins/platform/ros1robot/plugin.py +0 -373
  238. sierra/plugins/platform/ros1robot/variables/__init__.py +0 -10
  239. sierra/plugins/platform/ros1robot/variables/population_size.py +0 -146
  240. sierra/plugins/robot/__init__.py +0 -9
  241. sierra/plugins/robot/turtlebot3/__init__.py +0 -9
  242. sierra/plugins/robot/turtlebot3/plugin.py +0 -194
  243. sierra_research-1.3.6.data/data/share/man/man1/sierra-cli.1 +0 -2349
  244. sierra_research-1.3.6.data/data/share/man/man7/sierra-examples.7 +0 -488
  245. sierra_research-1.3.6.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
  246. sierra_research-1.3.6.data/data/share/man/man7/sierra-glossary.7 +0 -285
  247. sierra_research-1.3.6.data/data/share/man/man7/sierra-platforms.7 +0 -358
  248. sierra_research-1.3.6.data/data/share/man/man7/sierra-usage.7 +0 -725
  249. sierra_research-1.3.6.data/data/share/man/man7/sierra.7 +0 -78
  250. sierra_research-1.3.6.dist-info/METADATA +0 -500
  251. sierra_research-1.3.6.dist-info/RECORD +0 -133
  252. sierra_research-1.3.6.dist-info/top_level.txt +0 -1
  253. {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
  254. {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,279 @@
1
+ # Copyright 2018 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Collation functionality for stage3 outputs according to configuration."""
5
+
6
+ # Core packages
7
+ import multiprocessing as mp
8
+ import queue
9
+ import typing as tp
10
+ import logging
11
+ import pathlib
12
+ import json
13
+ import re
14
+
15
+ # 3rd party packages
16
+ import pandas as pd
17
+
18
+ # Project packages
19
+ from sierra.core import utils, config, types, storage, batchroot
20
+ import sierra.core.variables.batch_criteria as bc
21
+ from sierra.plugins.prod.graphs import targets
22
+ from sierra.core import plugin as pm
23
+
24
+ _logger = logging.getLogger(__name__)
25
+
26
+
27
+ class GraphCollationInfo:
28
+ """Container for :term:`Collated Output Data` files for a particular graph.
29
+
30
+ This is one of the focal points for the magic of SIERRA: here is where time
31
+ series data is transformed into different dataframe formats so as to make
32
+ generation of different types of graphs seamless when you want to look at
33
+ some data *across* the batch. The for dataframes by graph type is as
34
+ follows:
35
+
36
+ - :func:`~sierra.core.graphs.stacked_line` : Columns are the raw time
37
+ series data. Column names are the names of the experiments.
38
+
39
+ - :func:`~sierra.core.graphs.summary_line`: Columns are a single time
40
+ slice of time series data. Column names are the names of the
41
+ experiments. Indexed by (exp name, summary column).
42
+
43
+ - :func:`~sierra.core.graphs.heatmap`: X,Y columns are the indices in
44
+ the multidimensional array defining the experiment space, parsed out
45
+ from the exp dirnames for the batch. Z values are a single time slice
46
+ of time series data for the specified column in each experiment in the
47
+ batch.
48
+ """
49
+
50
+ def __init__(
51
+ self, df_ext: str, exp_names: tp.List[str], graph_type: str, summary_col: str
52
+ ) -> None:
53
+ self.df_ext = df_ext
54
+
55
+ if graph_type == "summary_line":
56
+ self.df = pd.DataFrame(index=exp_names, columns=[summary_col])
57
+ self.df.index.name = "Experiment ID"
58
+ elif graph_type == "stacked_line":
59
+ self.df = pd.DataFrame(columns=exp_names)
60
+ elif graph_type == "heatmap":
61
+ self.df = pd.DataFrame(columns=["x", "y", "z"])
62
+
63
+ self.graph_type = graph_type
64
+ self.summary_col = summary_col
65
+ self.all_srcs_exist = True
66
+ self.some_srcs_exist = False
67
+
68
+
69
+ class GraphCollator:
70
+ """For a single graph gather needed data from experiments in a batch.
71
+
72
+ Results are put into a single :term:`Collated Output Data` file.
73
+ """
74
+
75
+ def __init__(
76
+ self,
77
+ main_config: types.YAMLDict,
78
+ cmdopts: types.Cmdopts,
79
+ pathset: batchroot.PathSet,
80
+ ) -> None:
81
+ self.main_config = main_config
82
+ self.cmdopts = cmdopts
83
+ self.pathset = pathset
84
+ self.logger = logging.getLogger(__name__)
85
+
86
+ def __call__(self, criteria, target: types.YAMLDict) -> None:
87
+ self.logger.info(
88
+ "Files from univariate experiment in <batch_root>/%s for graph '%s'",
89
+ self.pathset.output_root.relative_to(self.pathset.root),
90
+ target["src_stem"],
91
+ )
92
+ self.logger.trace(json.dumps(target, indent=4)) # type: ignore
93
+
94
+ exp_dirs = utils.exp_range_calc(
95
+ self.cmdopts["exp_range"],
96
+ self.pathset.output_root,
97
+ criteria.gen_exp_names(),
98
+ )
99
+
100
+ # Always do the mean, even if stats are disabled
101
+ stat_config = config.kStats["mean"].exts
102
+
103
+ if self.cmdopts["dist_stats"] in ["conf95", "all"]:
104
+ stat_config.update(config.kStats["conf95"].exts)
105
+
106
+ if self.cmdopts["dist_stats"] in ["bw", "all"]:
107
+ stat_config.update(config.kStats["bw"].exts)
108
+
109
+ stats = [
110
+ GraphCollationInfo(
111
+ df_ext=suffix,
112
+ exp_names=[e.name for e in exp_dirs],
113
+ summary_col="{0}+{1}".format(
114
+ self.cmdopts["controller"], self.cmdopts["scenario"]
115
+ ),
116
+ graph_type=target["type"],
117
+ )
118
+ for suffix in stat_config.values()
119
+ ]
120
+
121
+ for diri in exp_dirs:
122
+ self._collate_exp(target, diri.name, stats)
123
+
124
+ for stat in stats:
125
+ if stat.all_srcs_exist:
126
+ storage.df_write(
127
+ stat.df,
128
+ self.pathset.stat_interexp_root
129
+ / (target["dest_stem"] + stat.df_ext),
130
+ "storage.csv",
131
+ index=stat.graph_type == "summary_line",
132
+ )
133
+
134
+ elif not stat.all_srcs_exist and stat.some_srcs_exist:
135
+ self.logger.warning(
136
+ "Not all experiments in '%s' produced '%s%s'",
137
+ self.pathset.output_root,
138
+ target["src_stem"],
139
+ stat.df_ext,
140
+ )
141
+ else:
142
+ self.logger.warning(
143
+ "No experiments in <batchroot>/%s produced %s%s",
144
+ self.pathset.output_root.relative_to(self.pathset.root),
145
+ target["src_stem"],
146
+ stat.df_ext,
147
+ )
148
+
149
+ def _collate_exp(
150
+ self, target: dict, exp_dir: str, stats: tp.List[GraphCollationInfo]
151
+ ) -> None:
152
+ exp_stat_root = self.pathset.stat_root / exp_dir
153
+
154
+ for stat in stats:
155
+ csv_ipath = pathlib.Path(exp_stat_root, target["src_stem"] + stat.df_ext)
156
+ if not utils.path_exists(csv_ipath):
157
+ stat.all_srcs_exist = False
158
+ continue
159
+
160
+ stat.some_srcs_exist = True
161
+
162
+ data_df = storage.df_read(csv_ipath, "storage.csv")
163
+
164
+ # 2025-07-08 [JRH]: This is the ONE place in all the graph
165
+ # generation code which is a procedural switch on graph type.
166
+ if target["type"] == "summary_line":
167
+ idx = target.get("index", -1)
168
+ assert "col" in target, "'col' key is required"
169
+ assert (
170
+ target["col"] in data_df.columns.values
171
+ ), "{0} not in columns of {1}".format(
172
+ target["col"], target["src_stem"] + stat.df_ext
173
+ )
174
+ datapoint = data_df.loc[data_df.index[idx], target["col"]]
175
+ stat.df.loc[exp_dir, stat.summary_col] = datapoint
176
+ elif target["type"] == "stacked_line":
177
+ assert "cols" in target, "'cols' key is required"
178
+
179
+ assert (
180
+ target["cols"] in data_df.columns.values
181
+ ), "{0} not in columns of {1}".format(
182
+ target["cols"], target["src_stem"] + stat.df_ext
183
+ )
184
+ stat.df[exp_dir] = data_df[target["cols"]]
185
+ elif target["type"] == "heatmap":
186
+ idx = target.get("index", -1)
187
+
188
+ regex = r"c1-exp(\d+)\+c2-exp(\d+)"
189
+ res = re.match(regex, exp_dir)
190
+
191
+ assert (
192
+ res and len(res.groups()) == 2
193
+ ), f"Unexpected directory name '{exp_dir}': does not match regex {regex}"
194
+
195
+ row = pd.DataFrame(
196
+ [
197
+ {
198
+ # group 0 is always the whole matched string
199
+ "x": int(res.group(1)),
200
+ "y": int(res.group(2)),
201
+ "z": data_df.loc[data_df.index[idx], target["col"]],
202
+ }
203
+ ]
204
+ )
205
+
206
+ stat.df = pd.concat([stat.df, row])
207
+
208
+
209
+ def proc_batch_exp(
210
+ main_config: types.YAMLDict,
211
+ cmdopts: types.Cmdopts,
212
+ pathset: batchroot.PathSet,
213
+ criteria: bc.XVarBatchCriteria,
214
+ ) -> None:
215
+ """
216
+ Generate :term:`Collated Output Data` files from :term:`Batch Summary Data` files.
217
+
218
+ """
219
+ utils.dir_create_checked(pathset.stat_interexp_root, exist_ok=True)
220
+
221
+ q = mp.JoinableQueue() # type: mp.JoinableQueue
222
+
223
+ loader = pm.module_load_tiered(project=cmdopts["project"], path="pipeline.yaml")
224
+
225
+ graphs_config = loader.load_config(cmdopts, config.kYAML.graphs)
226
+
227
+ if "inter-exp" not in graphs_config:
228
+ _logger.warning(
229
+ "Cannot collate data: 'inter-exp' key not found in graphs YAML config"
230
+ )
231
+ return
232
+
233
+ controller_config = loader.load_config(cmdopts, config.kYAML.controllers)
234
+
235
+ # For each category of graphs we are generating
236
+ for category in targets.inter_exp_calc(
237
+ graphs_config["inter-exp"], controller_config, cmdopts
238
+ ):
239
+ # For each graph in each category
240
+ for graph in category:
241
+ q.put(graph)
242
+
243
+ parallelism = cmdopts["processing_parallelism"]
244
+
245
+ for _ in range(0, parallelism):
246
+ p = mp.Process(
247
+ target=_thread_worker,
248
+ args=(q, main_config, cmdopts, pathset, criteria),
249
+ )
250
+ p.start()
251
+
252
+ q.join()
253
+
254
+
255
+ def _thread_worker(
256
+ q: mp.Queue,
257
+ main_config: types.YAMLDict,
258
+ cmdopts: types.Cmdopts,
259
+ pathset: batchroot.PathSet,
260
+ criteria,
261
+ ) -> None:
262
+
263
+ collator = GraphCollator(main_config, cmdopts, pathset)
264
+
265
+ while True:
266
+ # Wait for 3 seconds after the queue is empty before bailing
267
+ try:
268
+ graph = q.get(True, 3)
269
+ collator(criteria, graph)
270
+ q.task_done()
271
+ except queue.Empty:
272
+ break
273
+
274
+
275
+ __all__ = [
276
+ "GraphCollator",
277
+ "GraphCollationInfo",
278
+ "proc_batch_exp",
279
+ ]
@@ -0,0 +1,13 @@
1
+ #
2
+ # Copyright 2024 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """Container module for inter-experiment graph generation in stage 4."""
7
+
8
+ # Core packages
9
+
10
+ # 3rd party packages
11
+
12
+ # Project packages
13
+ from . import generate as generate
@@ -0,0 +1,83 @@
1
+ # Copyright 2018 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ #
5
+
6
+ """
7
+ Generate graphs across experiments in a batch.
8
+ """
9
+
10
+ # Core packages
11
+ import logging
12
+
13
+ # 3rd party packages
14
+
15
+ # Project packages
16
+ from sierra.core import types, utils, batchroot, config
17
+ from sierra.plugins.prod.graphs import targets
18
+ from sierra.core import plugin as pm
19
+ from sierra.core.variables import batch_criteria as bc
20
+ from . import line, heatmap
21
+
22
+ _logger = logging.getLogger(__name__)
23
+
24
+
25
+ def proc_batch_exp(
26
+ main_config: types.YAMLDict,
27
+ cmdopts: types.Cmdopts,
28
+ pathset: batchroot.PathSet,
29
+ criteria: bc.XVarBatchCriteria,
30
+ ) -> None:
31
+ """Generate graphs from :term:`Collated Output Data` files.
32
+
33
+ Performs the following steps:
34
+
35
+ #. :func:`~sierra.plugins.prod.graphs.inter.line.generate()` to
36
+ generate linegraphs (univariate batch criteria only).
37
+
38
+ #. :func:`~sierra.plugins.prod.graphs.inter.heatmap.generate()`
39
+ to generate heatmaps (bivariate batch criteria only).
40
+
41
+ Which graphs are generated can be controlled by YAML configuration files
42
+ parsed in stage 4.
43
+
44
+ Arguments:
45
+ main_config: Parsed dictionary of main YAML configuration
46
+
47
+ cmdopts: Dictionary of parsed cmdline attributes.
48
+
49
+ targets: A list of dictionaries, where each dictionary defines an
50
+ inter-experiment graph to generate.
51
+ """
52
+ utils.dir_create_checked(pathset.graph_interexp_root, exist_ok=True)
53
+
54
+ loader = pm.module_load_tiered(project=cmdopts["project"], path="pipeline.yaml")
55
+
56
+ graphs_config = loader.load_config(cmdopts, config.kYAML.graphs)
57
+
58
+ if "inter-exp" not in graphs_config:
59
+ _logger.warning(
60
+ "Cannot generate graphs: 'inter-exp' key not found in YAML config"
61
+ )
62
+ return
63
+
64
+ controller_config = loader.load_config(cmdopts, config.kYAML.controllers)
65
+
66
+ info = criteria.graph_info(cmdopts, batch_output_root=pathset.output_root)
67
+
68
+ if criteria.cardinality() == 1:
69
+ if not cmdopts["project_no_LN"]:
70
+ graph_targets = targets.inter_exp_calc(
71
+ graphs_config["inter-exp"], controller_config, cmdopts
72
+ )
73
+ line.generate(cmdopts, pathset, graph_targets, info)
74
+ else:
75
+ graph_targets = targets.inter_exp_calc(
76
+ graphs_config["inter-exp"], controller_config, cmdopts
77
+ )
78
+ heatmap.generate(cmdopts, pathset, graph_targets, info)
79
+
80
+
81
+ __all__ = [
82
+ "proc_batch_exp",
83
+ ]
@@ -0,0 +1,86 @@
1
+ #
2
+ # Copyright 2024 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """Generate heatmaps *across* multiple :term:`Experiments <Experiment>`."""
7
+
8
+ # Core packages
9
+ import typing as tp
10
+ import logging
11
+
12
+ # 3rd party packages
13
+ import json
14
+ import yaml
15
+ import strictyaml
16
+
17
+ # Project packages
18
+ from sierra.core import types, batchroot, graphs
19
+ from sierra.core.graphs import bcbridge, schema
20
+
21
+ _logger = logging.getLogger(__name__)
22
+
23
+
24
+ def generate(
25
+ cmdopts: types.Cmdopts,
26
+ pathset: batchroot.PathSet,
27
+ targets: tp.List[types.YAMLDict],
28
+ info: bcbridge.GraphInfo,
29
+ ) -> None:
30
+ """
31
+ Generate heatmaps from: term:`Processed Output Data` files.
32
+ """
33
+ large_text = cmdopts["plot_large_text"]
34
+
35
+ _logger.info(
36
+ "Heatmaps from <batch_root>/%s",
37
+ pathset.stat_interexp_root.relative_to(pathset.root),
38
+ )
39
+
40
+ # For each category of heatmaps we are generating
41
+ for category in targets:
42
+
43
+ # For each graph in each category
44
+ for graph in category:
45
+ # Only try to create heatmaps (duh)
46
+ if graph["type"] != "heatmap":
47
+ continue
48
+
49
+ _logger.trace("\n" + json.dumps(graph, indent=4)) # type: ignore
50
+
51
+ try:
52
+ graph = strictyaml.load(yaml.dump(graph), schema.heatmap).data
53
+
54
+ except strictyaml.YAMLError as e:
55
+ _logger.critical("Non-conformant heatmap YAML: %s", e)
56
+ raise
57
+
58
+ graph_pathset = graphs.PathSet(
59
+ input_root=pathset.stat_interexp_root,
60
+ output_root=pathset.graph_interexp_root,
61
+ batchroot=pathset.root,
62
+ model_root=None,
63
+ )
64
+ # 2025-06-05 [JRH]: We always write stage {3,4} output data files as
65
+ # .csv because that is currently SIERRA's 'native' format; this may
66
+ # change in the future.
67
+ graphs.heatmap(
68
+ pathset=graph_pathset,
69
+ input_stem=graph["dest_stem"],
70
+ output_stem=graph["dest_stem"],
71
+ medium="storage.csv",
72
+ title=graph.get("title", None),
73
+ xlabel=graph.get("xlabel", ""),
74
+ ylabel=graph.get("ylabel", ""),
75
+ zlabel=graph.get("zlabel", ""),
76
+ backend=graph.get("backend", cmdopts["graphs_backend"]),
77
+ colnames=(
78
+ graph.get("x", "x"),
79
+ graph.get("y", "y"),
80
+ graph.get("z", "z"),
81
+ ),
82
+ large_text=large_text,
83
+ )
84
+
85
+
86
+ __all__ = ["generate"]
@@ -0,0 +1,134 @@
1
+ #
2
+ # Copyright 2024 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """Inter-experiment linegraph generation in stage 4."""
7
+
8
+ # Core packages
9
+ import typing as tp
10
+ import logging
11
+
12
+ # 3rd party packages
13
+ import json
14
+ import yaml
15
+ import strictyaml
16
+
17
+ # Project packages
18
+ from sierra.core import types, batchroot, graphs
19
+ from sierra.core.graphs import bcbridge, schema
20
+
21
+ _logger = logging.getLogger(__name__)
22
+
23
+
24
+ def generate(
25
+ cmdopts: types.Cmdopts,
26
+ pathset: batchroot.PathSet,
27
+ targets: tp.List[types.YAMLDict],
28
+ info: bcbridge.GraphInfo,
29
+ ) -> None:
30
+ """Generate linegraphs from :term:`Collated Output Data` files.
31
+
32
+ The graphs generated by this module respect the ``--exp-range`` cmdline
33
+ option.
34
+ """
35
+
36
+ _logger.info(
37
+ "Linegraphs from <batchroot>/%s",
38
+ pathset.stat_interexp_root.relative_to(pathset.root),
39
+ )
40
+
41
+ # For each category of linegraphs we are generating
42
+ for category in targets:
43
+
44
+ # For each graph in each category
45
+ for graph in category:
46
+ if graph["type"] not in ["summary_line", "stacked_line"]:
47
+ continue
48
+
49
+ _logger.trace("\n" + json.dumps(graph, indent=4)) # type: ignore
50
+
51
+ if graph["type"] == "summary_line":
52
+ try:
53
+ graph = strictyaml.load(yaml.dump(graph), schema.summary_line).data
54
+ except strictyaml.YAMLError as e:
55
+ _logger.critical("Non-conformant summary_line YAML: %s", e)
56
+ raise
57
+ _gen_summary_linegraph(graph, pathset, cmdopts, info)
58
+ elif graph["type"] == "stacked_line":
59
+ try:
60
+ graph = strictyaml.load(yaml.dump(graph), schema.stacked_line).data
61
+ except strictyaml.YAMLError as e:
62
+ _logger.critical("Non-conformant stacked_line YAML: %s", e)
63
+ raise
64
+ _gen_stacked_linegraph(graph, pathset, cmdopts, info)
65
+
66
+
67
+ def _gen_summary_linegraph(
68
+ graph: types.YAMLDict,
69
+ pathset: batchroot.PathSet,
70
+ cmdopts: types.Cmdopts,
71
+ info: bcbridge.GraphInfo,
72
+ ) -> None:
73
+ legend = "{0}+{1}".format(cmdopts["controller"], cmdopts["scenario"])
74
+
75
+ paths = graphs.PathSet(
76
+ input_root=pathset.stat_interexp_root,
77
+ output_root=pathset.graph_interexp_root,
78
+ batchroot=pathset.root,
79
+ model_root=pathset.model_interexp_root,
80
+ )
81
+
82
+ # 2025-06-05 [JRH]: We always write stage {3,4} output data files as .csv
83
+ # because that is currently SIERRA's 'native' format; this may change in the
84
+ # future.
85
+ graphs.summary_line(
86
+ paths=paths,
87
+ input_stem=graph["dest_stem"],
88
+ output_stem=graph["dest_stem"],
89
+ medium="storage.csv",
90
+ legend=[legend],
91
+ stats=cmdopts["dist_stats"],
92
+ title=graph["title"],
93
+ xlabel=info.xlabel,
94
+ ylabel=graph.get("ylabel", None),
95
+ backend=graph.get("backend", cmdopts["graphs_backend"]),
96
+ xticks=info.xticks,
97
+ xticklabels=info.xticklabels,
98
+ logyscale=graph.get("logy", cmdopts["plot_log_yscale"]),
99
+ large_text=cmdopts["plot_large_text"],
100
+ )
101
+
102
+
103
+ def _gen_stacked_linegraph(
104
+ graph: types.YAMLDict,
105
+ pathset: batchroot.PathSet,
106
+ cmdopts: types.Cmdopts,
107
+ info: bcbridge.GraphInfo,
108
+ ) -> None:
109
+
110
+ paths = graphs.PathSet(
111
+ input_root=pathset.stat_interexp_root,
112
+ output_root=pathset.graph_interexp_root,
113
+ model_root=None,
114
+ batchroot=pathset.root,
115
+ )
116
+
117
+ graphs.stacked_line(
118
+ paths=paths,
119
+ input_stem=graph["dest_stem"],
120
+ output_stem=graph["dest_stem"],
121
+ stats=cmdopts["dist_stats"],
122
+ medium="storage.csv",
123
+ title=graph["title"],
124
+ backend=graph.get("backend", cmdopts["graphs_backend"]),
125
+ xticks=None,
126
+ xlabel=graph.get("xlabel", "Time"),
127
+ ylabel=graph.get("ylabel", None),
128
+ logyscale=graph.get("logy", cmdopts["plot_log_yscale"]),
129
+ large_text=cmdopts["plot_large_text"],
130
+ legend=graph.get("legend", [f"exp{i}" for i in range(0, len(info.exp_names))]),
131
+ )
132
+
133
+
134
+ __all__ = ["generate"]
@@ -0,0 +1,15 @@
1
+ #
2
+ # Copyright 2024 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """Container module for intra-experiment graph generation in stage 4."""
7
+
8
+ # Core packages
9
+
10
+ # 3rd party packages
11
+
12
+ # Project packages
13
+ from . import generate as generate
14
+ from . import line as line
15
+ from . import heatmap as heatmap