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,506 @@
1
+ # Copyright 2018 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ #
5
+ """
6
+ Linegraph for summarizing the results of a :term:`Batch Experiment`.
7
+
8
+ Graphs one datapoint per :term:`Experiment`.
9
+ """
10
+
11
+ # Core packages
12
+ import typing as tp
13
+ import logging
14
+ import pathlib
15
+
16
+ # 3rd party packages
17
+ import pandas as pd
18
+ import holoviews as hv
19
+ import matplotlib.pyplot as plt
20
+ import bokeh
21
+
22
+ # Project packages
23
+ from sierra.core import config, utils, storage, models
24
+ from . import pathset
25
+
26
+ _logger = logging.getLogger(__name__)
27
+
28
+
29
+ def generate(
30
+ paths: pathset.PathSet,
31
+ input_stem: str,
32
+ output_stem: str,
33
+ medium: str,
34
+ title: str,
35
+ xlabel: str,
36
+ ylabel: str,
37
+ backend: str,
38
+ legend: tp.List[str],
39
+ xticks: tp.List[float],
40
+ xticklabels: tp.Optional[tp.List[str]] = None,
41
+ large_text: bool = False,
42
+ logyscale: bool = False,
43
+ stats: str = "none",
44
+ ) -> bool:
45
+ """Generate a linegraph from a :term:`Batch Summary Data` file.
46
+
47
+ Possibly shows the 95% confidence interval or box and whisker plots,
48
+ according to configuration.
49
+
50
+ Attributes:
51
+ paths: Set of run-time tree paths for the batch experiment.
52
+
53
+ input_stem: Stem of the :term:`Batch Summary Data` file to generate a
54
+ graph from.
55
+
56
+ output_fpath: The absolute path to the output image file to save
57
+ generated graph to.
58
+
59
+ title: Graph title.
60
+
61
+ xlabel: X-label for graph.
62
+
63
+ ylabel: Y-label for graph.
64
+
65
+ backend: The holoviews backend to use.
66
+
67
+ xticks: The xticks for the graph.
68
+
69
+ xticklabels: The xtick labels for the graph (can be different than the
70
+ xticks; e.g., if the xticxs are 1-10 for categorical data,
71
+ then then labels would be the categories).
72
+
73
+ large_text: Should the labels, ticks, and titles be large, or regular
74
+ size?
75
+
76
+ legend: Legend for graph.
77
+
78
+ logyscale: Should the Y axis be in the log2 domain ?
79
+
80
+ stats: The type of statistics to include on the graph (from
81
+ ``--dist-stats``).
82
+
83
+ model_root: The absolute path to the ``models/`` directory for the batch
84
+ experiment.
85
+
86
+ """
87
+ hv.extension(backend)
88
+ if backend == "matplotlib":
89
+ ofile_ext = config.kStaticImageType
90
+ elif backend == "bokeh":
91
+ ofile_ext = config.kInteractiveImageType
92
+
93
+ input_fpath = paths.input_root / (input_stem + config.kStats["mean"].exts["mean"])
94
+ output_fpath = paths.output_root / ("SM-{0}.{1}".format(output_stem, ofile_ext))
95
+
96
+ if not utils.path_exists(input_fpath):
97
+ _logger.debug(
98
+ "Not generating <batchroot>/%s: <batchroot>/%s does not exist",
99
+ output_fpath.relative_to(paths.batchroot),
100
+ input_fpath.relative_to(paths.batchroot),
101
+ )
102
+ return False
103
+
104
+ if large_text:
105
+ text_size = config.kGraphs["text_size_large"]
106
+ else:
107
+ text_size = config.kGraphs["text_size_small"]
108
+
109
+ df = storage.df_read(input_fpath, medium, index_col="Experiment ID")
110
+ # Column 0 is the 'Experiment ID' index, which we don't want included as
111
+ # a vdim
112
+ cols = df.columns.tolist()
113
+ df["xticks"] = xticks
114
+
115
+ dataset = hv.Dataset(data=df.reset_index(), kdims=["xticks"], vdims=cols)
116
+ assert len(df.index) == len(
117
+ xticks
118
+ ), "Length mismatch between xticks,# data points: {0} vs {1}".format(
119
+ len(xticks), len(df.index)
120
+ )
121
+
122
+ model_info = _read_model_info(paths.model_root, input_stem, medium, xticks)
123
+
124
+ # Add statistics according to configuration
125
+ stat_dfs = _read_stats(stats, medium, paths.input_root, input_stem)
126
+ plot = _plot_stats(dataset, stats, stat_dfs, backend)
127
+
128
+ # Add legend
129
+ plot.opts(legend_position="bottom")
130
+
131
+ # Plot lines after stats so they show on top
132
+ plot *= _plot_lines(dataset, model_info, legend, backend)
133
+
134
+ # Add X,Y labels
135
+ plot.opts(ylabel=ylabel, xlabel=xlabel)
136
+
137
+ # Configure ticks (must be last so not overwritten by what you get from
138
+ # plotting the lines)
139
+ plot = _plot_ticks(plot, logyscale, xticks, xticklabels)
140
+
141
+ # Set fontsizes
142
+ plot.opts(
143
+ fontsize={
144
+ "title": text_size["title"],
145
+ "labels": text_size["xyz_label"],
146
+ "ticks": text_size["tick_label"],
147
+ "legend": text_size["legend_label"],
148
+ },
149
+ )
150
+
151
+ # Add title
152
+ plot.opts(title=title)
153
+
154
+ if backend == "matplotlib":
155
+ hv.save(
156
+ plot.opts(fig_inches=config.kGraphs["base_size"]),
157
+ output_fpath,
158
+ fig=config.kStaticImageType,
159
+ dpi=config.kGraphs["dpi"],
160
+ )
161
+ plt.close("all")
162
+ elif backend == "bokeh":
163
+ fig = hv.render(plot)
164
+ fig.width = int(config.kGraphs["dpi"] * config.kGraphs["base_size"])
165
+ fig.height = int(config.kGraphs["dpi"] * config.kGraphs["base_size"])
166
+ html = bokeh.embed.file_html(fig, resources=bokeh.resources.INLINE)
167
+ with open(output_fpath, "w") as f:
168
+ f.write(html)
169
+
170
+ _logger.debug(
171
+ "Graph written to <batchroot>/%s", output_fpath.relative_to(paths.batchroot)
172
+ )
173
+
174
+ return True
175
+
176
+
177
+ def _plot_lines(
178
+ dataset: hv.Dataset,
179
+ model_info: models.ModelInfo,
180
+ legend: tp.List[str],
181
+ backend: str,
182
+ ) -> hv.NdOverlay:
183
+ # Plot the curve(s)
184
+ plot = hv.Overlay(
185
+ [
186
+ hv.Curve(
187
+ dataset,
188
+ kdims=dataset.kdims[0],
189
+ vdims=vdim,
190
+ label=legend[dataset.vdims.index(vdim)],
191
+ )
192
+ for vdim in dataset.vdims
193
+ ]
194
+ )
195
+
196
+ # Plot the points for each curve
197
+ plot *= hv.Overlay(
198
+ [hv.Points((dataset[dataset.kdims[0]], dataset[v])) for v in dataset.vdims]
199
+ )
200
+
201
+ if model_info.dataset:
202
+ if backend == "matplotlib":
203
+ opts = {
204
+ "linestyle": "--",
205
+ }
206
+ elif backend == "bokeh":
207
+ opts = {"line_dash": [6, 3]}
208
+
209
+ # TODO: This currently only works for a single model being put onto a
210
+ # summary line graph.
211
+ plot *= hv.Overlay(
212
+ [
213
+ hv.Curve(
214
+ model_info.dataset,
215
+ model_info.dataset.kdims[0],
216
+ vdim.name,
217
+ label=model_info.legend[model_info.dataset.vdims.index(vdim)],
218
+ ).opts(**opts)
219
+ for vdim in model_info.dataset.vdims
220
+ ]
221
+ )
222
+
223
+ # Plot the points for each curve
224
+ plot *= hv.Overlay(
225
+ [
226
+ hv.Points(
227
+ (
228
+ model_info.dataset[model_info.dataset.kdims[0]],
229
+ model_info.dataset[v],
230
+ )
231
+ )
232
+ for v in model_info.dataset.vdims
233
+ if len(model_info.dataset[v]) <= 50
234
+ ]
235
+ )
236
+ return plot
237
+
238
+
239
+ def _plot_stats(
240
+ dataset: hv.Dataset,
241
+ setting: str,
242
+ stat_dfs: tp.Dict[str, pd.DataFrame],
243
+ backend: str,
244
+ ) -> hv.NdOverlay:
245
+ """
246
+ Plot statistics for all lines on the graph.
247
+ """
248
+ plot = _plot_conf95_stats(dataset, setting, stat_dfs)
249
+ plot *= _plot_bw_stats(dataset, setting, stat_dfs, backend)
250
+
251
+ return plot
252
+
253
+
254
+ def _plot_conf95_stats(
255
+ dataset: hv.Dataset, setting: str, stat_dfs: tp.Dict[str, pd.DataFrame]
256
+ ) -> hv.NdOverlay:
257
+ if setting not in ["conf95", "all"]:
258
+ return hv.Overlay()
259
+
260
+ if not all(k in stat_dfs.keys() for k in config.kStats["conf95"].exts):
261
+ _logger.warning(
262
+ (
263
+ "Cannot plot 95%% confidence intervals: "
264
+ "missing some statistics: %s vs %s"
265
+ ),
266
+ stat_dfs.keys(),
267
+ config.kStats["conf95"].exts,
268
+ )
269
+ return hv.Overlay()
270
+
271
+ # Stddevs have to be added to dataset to be able to plot via overlays,
272
+ # afaict.
273
+ stddevs = pd.DataFrame()
274
+
275
+ for c in dataset.vdims:
276
+ stddevs[f"{c}_stddev_l"] = dataset[c] - 2 * stat_dfs["stddev"][c.name].abs()
277
+ stddevs[f"{c}_stddev_u"] = dataset[c] + 2 * stat_dfs["stddev"][c.name].abs()
278
+ stddevs.index = dataset.data.index
279
+ dataset.data = pd.concat([dataset.dframe(), stddevs], axis=1)
280
+
281
+ return hv.Overlay(
282
+ [
283
+ hv.Area(
284
+ dataset, vdims=[f"{vdim.name}_stddev_l", f"{vdim.name}_stddev_u"]
285
+ ).opts(
286
+ alpha=0.5,
287
+ )
288
+ for vdim in dataset.vdims
289
+ ]
290
+ )
291
+
292
+
293
+ def _plot_bw_stats(
294
+ dataset: hv.Dataset,
295
+ setting: str,
296
+ stat_dfs: tp.Dict[str, pd.DataFrame],
297
+ backend: str,
298
+ ) -> hv.NdOverlay:
299
+ if setting not in ["bw", "all"]:
300
+ return hv.Overlay()
301
+
302
+ if not all(k in stat_dfs.keys() for k in config.kStats["bw"].exts):
303
+ _logger.warning(
304
+ ("Cannot plot box-and-whisker plots: missing some statistics: %s vs %s"),
305
+ stat_dfs.keys(),
306
+ config.kStats["bw"].exts,
307
+ )
308
+ return hv.Overlay()
309
+
310
+ elements = []
311
+
312
+ if backend == "matplotlib":
313
+ opts = {"linewidth": 2}
314
+ elif backend == "bokeh":
315
+ opts = {"line_width": 2}
316
+
317
+ # For each value dimension (set of datapoints from a batch experiment)
318
+ for i in range(0, len(dataset.vdims)):
319
+
320
+ # For each datapoint captured from an experiment in the batch
321
+ for j in range(0, len(dataset.data.values)):
322
+ col = dataset.vdims[i].name
323
+
324
+ # Read stats from file
325
+ q1 = stat_dfs["q1"][col].iloc[j]
326
+ median = stat_dfs["median"][col].iloc[j]
327
+ q3 = stat_dfs["q3"][col].iloc[j]
328
+ whishi = stat_dfs["whislo"][col].iloc[j]
329
+ whislo = stat_dfs["whishi"][col].iloc[j]
330
+
331
+ # Box (Rectangle from q1 to q3).
332
+ # Args: x center, y center, x width, y height
333
+ box = hv.Box(dataset.data["xticks"][j], median, (0.2, (q3 - q1))).opts(
334
+ **opts
335
+ )
336
+
337
+ # Median line
338
+ median_line = hv.Segments(
339
+ (
340
+ dataset.data["xticks"][j] - 0.2,
341
+ median,
342
+ dataset.data["xticks"][j] + 0.2,
343
+ median,
344
+ )
345
+ ).opts(color="darkred", **opts)
346
+
347
+ # Whisker lines (vertical lines from box to min/max)
348
+ lower_whisker = hv.Segments(
349
+ (dataset.data["xticks"][j], q1, dataset.data["xticks"][j], whislo)
350
+ ).opts(color="black", **opts)
351
+ upper_whisker = hv.Segments(
352
+ (dataset.data["xticks"][j], q3, dataset.data["xticks"][j], whishi)
353
+ ).opts(color="black", **opts)
354
+
355
+ # Whisker caps (horizontal lines at min/max)
356
+ lower_cap = hv.Segments(
357
+ (
358
+ dataset.data["xticks"][j] - 0.1,
359
+ whislo,
360
+ dataset.data["xticks"][j] + 0.1,
361
+ whislo,
362
+ )
363
+ ).opts(color="black", **opts)
364
+ upper_cap = hv.Segments(
365
+ (
366
+ dataset.data["xticks"][j] - 0.1,
367
+ whishi,
368
+ dataset.data["xticks"][j] + 0.1,
369
+ whishi,
370
+ )
371
+ ).opts(color="black", **opts)
372
+ # Combine all elements
373
+ elements.append(
374
+ box
375
+ * median_line
376
+ * lower_whisker
377
+ * upper_whisker
378
+ * lower_cap
379
+ * upper_cap
380
+ )
381
+
382
+ return hv.Overlay(elements)
383
+
384
+
385
+ def _plot_ticks(
386
+ plot: hv.NdOverlay,
387
+ logyscale: bool,
388
+ xticks: tp.List[float],
389
+ xticklabels: tp.List[str],
390
+ ) -> hv.NdOverlay:
391
+ if logyscale:
392
+ plot.opts(logy=True)
393
+
394
+ # For ordered, qualitative data
395
+
396
+ if xticklabels is not None:
397
+ plot.opts(
398
+ xticks=list((i, j) for i, j in zip(xticks, xticklabels)), xrotation=90
399
+ )
400
+
401
+ return plot
402
+
403
+
404
+ def _read_stats(
405
+ setting: str, medium: str, stats_root: pathlib.Path, input_stem: str
406
+ ) -> tp.Dict[str, tp.List[pd.DataFrame]]:
407
+ dfs = {}
408
+
409
+ dfs.update(_read_conf95_stats(setting, medium, stats_root, input_stem))
410
+ dfs.update(_read_bw_stats(setting, medium, stats_root, input_stem))
411
+
412
+ return dfs
413
+
414
+
415
+ def _read_conf95_stats(
416
+ setting: str,
417
+ medium: str,
418
+ stats_root: pathlib.Path,
419
+ input_stem: str,
420
+ ) -> tp.Dict[str, tp.List[pd.DataFrame]]:
421
+ dfs = {}
422
+
423
+ exts = config.kStats["conf95"].exts
424
+ if setting in ["conf95", "all"]:
425
+ for k in exts:
426
+ ipath = stats_root / (input_stem + exts[k])
427
+
428
+ if utils.path_exists(ipath):
429
+ dfs[k] = storage.df_read(ipath, medium, index_col="Experiment ID")
430
+ else:
431
+ _logger.warning("%s file not found for '%s'", exts[k], input_stem)
432
+
433
+ return dfs
434
+
435
+
436
+ def _read_bw_stats(
437
+ setting: str,
438
+ medium: str,
439
+ stats_root: pathlib.Path,
440
+ input_stem: str,
441
+ ) -> tp.Dict[str, tp.List[pd.DataFrame]]:
442
+ dfs = {}
443
+
444
+ exts = config.kStats["bw"].exts
445
+
446
+ if setting in ["bw", "all"]:
447
+ for k in exts:
448
+ ipath = stats_root / (input_stem + exts[k])
449
+
450
+ if utils.path_exists(ipath):
451
+ dfs[k] = storage.df_read(ipath, medium, index_col="Experiment ID")
452
+ else:
453
+ _logger.warning("%s file not found for '%s'", exts[k], input_stem)
454
+
455
+ return dfs
456
+
457
+
458
+ # 2024/09/13 [JRH]: The union is for compatability with type checkers in
459
+ # python {3.8,3.11}.
460
+ def _read_model_info(
461
+ model_root: tp.Optional[pathlib.Path],
462
+ input_stem: str,
463
+ medium: str,
464
+ xticks: tp.List[float],
465
+ ) -> models.ModelInfo:
466
+
467
+ if model_root is None:
468
+ return models.ModelInfo()
469
+
470
+ _logger.trace("Model root='%s'", model_root) # type: ignore
471
+
472
+ exts = config.kModelsExt
473
+ modelf = model_root / (input_stem + exts["model"])
474
+ legendf = model_root / (input_stem + exts["legend"])
475
+
476
+ if not utils.path_exists(modelf):
477
+ _logger.trace(
478
+ "No model file=<batch_model_root>/%s found",
479
+ modelf.relative_to(model_root),
480
+ ) # type: ignore
481
+ return models.ModelInfo()
482
+
483
+ info = models.ModelInfo()
484
+
485
+ df = storage.df_read(modelf, medium, index_col="Experiment ID")
486
+
487
+ # Column 0 is the 'Experiment ID' index, which we don't want included as
488
+ # a vdim
489
+ cols = df.columns.tolist()
490
+ df["xticks"] = xticks
491
+
492
+ info.dataset = hv.Dataset(data=df.reset_index(), kdims=["xticks"], vdims=cols)
493
+
494
+ with utils.utf8open(legendf, "r") as f:
495
+ info.legend = f.read().splitlines()
496
+
497
+ _logger.trace(
498
+ "Loaded model='%s',legend='%s'", # type: ignore
499
+ modelf.relative_to(model_root),
500
+ legendf.relative_to(model_root),
501
+ )
502
+
503
+ return info
504
+
505
+
506
+ __all__ = ["generate"]
sierra/core/logging.py CHANGED
@@ -21,11 +21,12 @@ from haggis import logs
21
21
  # Project packages
22
22
 
23
23
 
24
- def initialize(log_level: str):
24
+ def initialize(log_level: str) -> None:
25
+ """Initialize logging in SIERRA."""
25
26
  logs.add_logging_level(level_name='TRACE',
26
27
  level_num=logging.DEBUG - 5,
27
28
  method_name=None,
28
- if_exists=logs.RAISE)
29
+ if_exists=None)
29
30
  # Needed for static analysis (mypy and/or pylint)
30
31
  setattr(logging, '_HAS_DYNAMIC_ATTRIBUTES', True)
31
32
 
@@ -1,9 +1,11 @@
1
1
  # Copyright 2021 John Harwell, All rights reserved.
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
+ """Container module for things related to models."""
5
+
4
6
  # Core packages
5
7
 
6
8
  # 3rd party packages
7
9
 
8
10
  # Project packages
9
- from . import interface
11
+ from .info import ModelInfo as ModelInfo
@@ -0,0 +1,19 @@
1
+ # Copyright 2021 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Abstract info about models."""
5
+
6
+ # Core packages
7
+ import dataclasses
8
+ import typing as tp
9
+
10
+ # 3rd party packages
11
+ import holoviews as hv
12
+
13
+ # Project packages
14
+
15
+
16
+ @dataclasses.dataclass
17
+ class ModelInfo:
18
+ dataset: hv.Dataset = None
19
+ legend: tp.List[str] = dataclasses.field(default_factory=lambda: [])