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
sierra/core/compare.py ADDED
@@ -0,0 +1,11 @@
1
+ # Copyright 2021 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Trampoline bindings for the various ``--compare`` plugins that come with SIERRA."""
5
+
6
+ # Core packages
7
+
8
+ # 3rd party packages
9
+
10
+ # Project packages
11
+ from sierra.core.trampoline import cmdline_parser # noqa: F401
sierra/core/config.py CHANGED
@@ -9,164 +9,172 @@ Contains all SIERRA hard-coded configuration in one place.
9
9
  import logging
10
10
  import typing as tp
11
11
  import packaging
12
+ import holoviews as hv
12
13
 
13
14
  # 3rd party packages
14
15
 
15
16
  # Project packages
16
17
  from sierra.core import types
17
18
 
19
+
18
20
  ################################################################################
19
- # Matplotlib Configuration
21
+ # Holoviews Configuration
20
22
  ################################################################################
23
+ def bokeh_init():
24
+ # Only needed when hv backend is bokeh
25
+ logging.getLogger("selenium").setLevel(logging.WARNING)
26
+ logging.getLogger("urllib3").setLevel(logging.WARNING)
21
27
 
22
28
 
23
29
  def mpl_init():
24
30
  # Turn off MPL messages when the log level is set to DEBUG or
25
31
  # higher. Otherwise you get HUNDREDS. Must be before import to suppress
26
32
  # messages which occur during import.
27
- logging.getLogger('matplotlib').setLevel(logging.WARNING)
28
- logging.getLogger('PIL').setLevel(logging.WARNING)
33
+ #
34
+ # Only needed when the hv backend is mpl
35
+ logging.getLogger("matplotlib").setLevel(logging.WARNING)
36
+ logging.getLogger("PIL").setLevel(logging.WARNING)
29
37
 
30
38
  import matplotlib as mpl
31
39
 
32
- mpl.rcParams['lines.linewidth'] = 3
33
- mpl.rcParams['lines.markersize'] = 10
34
- mpl.rcParams['figure.max_open_warning'] = 10000
35
- mpl.rcParams['axes.formatter.limits'] = (-4, 4)
40
+ mpl.rcParams["lines.linewidth"] = 3
41
+ mpl.rcParams["lines.markersize"] = 10
42
+ mpl.rcParams["figure.max_open_warning"] = 1000
43
+ mpl.rcParams["axes.formatter.limits"] = (-4, 4)
36
44
 
37
45
  # Use latex to render all math, so that it matches how the math renders in
38
46
  # papers.
39
- mpl.rcParams['text.usetex'] = True
47
+ mpl.rcParams["text.usetex"] = True
40
48
 
41
49
  # Set MPL backend (headless for non-interactive use). Must be BEFORE
42
50
  # importing pyplot reduce import loading time.
43
- mpl.use('agg')
51
+ mpl.use("Agg")
44
52
 
45
53
  import matplotlib.pyplot as plt
46
54
 
47
55
  # Set MPL style
48
- plt.style.use('seaborn-v0_8-colorblind')
56
+ plt.style.use("seaborn-v0_8-colorblind")
49
57
 
50
58
 
51
- # Actually initialize matplotlib
59
+ # Actually initialize holoviews
60
+ bokeh_init()
52
61
  mpl_init()
53
62
 
63
+ hv.core.cache_size = 10
64
+ hv.config.cache_size = 0
65
+ hv.config.warning_level = 0
54
66
  ################################################################################
55
67
  # General Configuration
56
68
  ################################################################################
57
69
 
58
70
 
59
- kImageExt = '.png'
71
+ kStaticImageType = "png"
72
+ kInteractiveImageType = "html"
60
73
 
61
- kRenderFormat = '.mp4'
74
+ kRenderFormat = ".mp4"
62
75
 
63
- kPickleExt = '.pkl'
64
- kPickleLeaf = 'exp_def' + kPickleExt
76
+ kPickleExt = ".pkl"
77
+ kPickleLeaf = "exp_def" + kPickleExt
65
78
  kRandomSeedsLeaf = "seeds" + kPickleExt
66
79
 
67
- kGraphDPI = 100
68
-
69
- kGraphBaseSize = 10.0 # inches
70
-
71
- kGraphTextSizeSmall: types.IntDict = {
72
- 'title': 24,
73
- 'xyz_label': 18,
74
- 'tick_label': 12,
75
- 'legend_label': 18
80
+ kGraphs = {
81
+ "dpi": 100,
82
+ "base_size": 10.0, # inches,
83
+ "text_size_small": {
84
+ "title": 24,
85
+ "xyz_label": 18,
86
+ "tick_label": 12,
87
+ "legend_label": 18,
88
+ },
89
+ "text_size_large": {
90
+ "title": 36,
91
+ "xyz_label": 24,
92
+ "tick_label": 24,
93
+ "legend_label": 32,
94
+ },
76
95
  }
77
96
 
78
- kGraphTextSizeLarge: types.IntDict = {
79
- 'title': 36,
80
- 'xyz_label': 24,
81
- 'tick_label': 24,
82
- 'legend_label': 32
83
- }
84
97
 
85
98
  # These are the file extensions that files read/written by a given storage
86
99
  # plugin should have. Once processed by SIERRA they are written out as CSV files
87
100
  # with new extensions contextualizing them.
88
- kStorageExt: types.StrDict = {
89
- 'csv': '.csv'
90
- }
101
+ kStorageExt: types.StrDict = {"csv": ".csv", "arrow": ".arrow"}
91
102
 
92
103
  kStats: tp.Dict[str, types.StatisticsSpec] = {
93
104
  # The default for averaging
94
- 'mean': types.StatisticsSpec({'mean': '.mean'}),
95
-
105
+ "mean": types.StatisticsSpec({"mean": ".mean"}),
96
106
  # For calculating 95% confidence intervals
97
- 'conf95': types.StatisticsSpec({'stddev': '.stddev'}),
98
-
107
+ "conf95": types.StatisticsSpec({"stddev": ".stddev"}),
99
108
  # For calculating box and whisker plots
100
- 'bw': types.StatisticsSpec({'median': '.median',
101
- 'q1': '.q1',
102
- 'q3': '.q3',
103
- 'whislo': '.whislo',
104
- 'whishi': '.whishi',
105
- 'cilo': '.cilo',
106
- 'cihi': '.cihi'
107
- })
109
+ "bw": types.StatisticsSpec(
110
+ {
111
+ "median": ".median",
112
+ "q1": ".q1",
113
+ "q3": ".q3",
114
+ "whislo": ".whislo",
115
+ "whishi": ".whishi",
116
+ "cilo": ".cilo",
117
+ "cihi": ".cihi",
118
+ }
119
+ ),
108
120
  }
109
121
 
110
- kModelsExt: types.StrDict = {
111
- 'model': '.model',
112
- 'legend': '.legend'
113
- }
122
+ kModelsExt: types.StrDict = {"model": ".model", "legend": ".legend"}
114
123
 
115
124
  kRendering = {
116
- 'argos': {
117
- 'frames_leaf': 'frames',
125
+ "argos": {
126
+ "frames_leaf": "frames",
118
127
  }
119
128
  }
120
129
  kARGoS: tp.Dict[str, tp.Any] = {
121
- 'physics_iter_per_tick': 10,
122
- 'min_version': packaging.version.parse('3.0.0-beta53'),
123
- 'launch_cmd': 'argos3',
124
- 'launch_file_ext': '.argos',
125
- 'n_secs_per_run': 5000, # seconds
126
- 'n_ticks_per_sec': 5,
127
-
130
+ "physics_iter_per_tick": 10,
131
+ "min_version": packaging.version.parse("3.0.0-beta53"),
132
+ "launch_cmd": "argos3",
133
+ "launch_file_ext": ".argos",
134
+ "n_secs_per_run": 5000, # seconds
135
+ "n_ticks_per_sec": 5,
128
136
  # These are the cell sizes for use with the spatial_hash method for the
129
137
  # dynamics2D engine. Since that method should only be used with lots of
130
138
  # robots (per the docs), we set a cell a little larger than the robot.
131
- 'spatial_hash2D': {
132
- 'foot-bot': 0.5,
133
- 'e-puck': 0.5,
134
- }
139
+ "spatial_hash2D": {
140
+ "foot-bot": 0.5,
141
+ "e-puck": 0.5,
142
+ },
135
143
  }
136
144
 
137
145
 
138
146
  kROS: types.SimpleDict = {
139
- 'launch_cmd': 'roslaunch',
140
- 'launch_file_ext': '.launch',
141
- 'param_file_ext': '.params',
142
- 'n_ticks_per_sec': 5,
143
- 'n_secs_per_run': 1000, # seconds
144
- 'port_base': 11235,
145
- 'inter_run_pause': 60 # seconds
147
+ "launch_cmd": "roslaunch",
148
+ "launch_file_ext": ".launch",
149
+ "param_file_ext": ".params",
150
+ "n_ticks_per_sec": 5,
151
+ "n_secs_per_run": 1000, # seconds
152
+ "port_base": 11235,
153
+ "inter_run_pause": 60, # seconds
146
154
  }
147
155
 
148
- kYAML = types.YAMLConfigFileSpec(main='main.yaml',
149
- controllers='controllers.yaml',
150
- models='models.yaml',
151
- stage5='stage5.yaml')
156
+ # 2025-06-23 [JRH]: These are empirically determined minimum values which
157
+ # generally result in all data being processed in stage {3,4}. Change with
158
+ # extreme caution.
152
159
 
153
- kGazebo = {
154
- 'launch_cmd': 'gazebo',
155
- 'min_version': '11.0.0',
156
- 'physics_iter_per_tick': 1000,
160
+ kGatherWorkerRetries = 3
161
+ kProcessWorkerRetries = 3
157
162
 
158
- }
163
+ kYAML = types.YAMLConfigFileSpec(
164
+ main="main.yaml",
165
+ graphs="graphs.yaml",
166
+ collate="collate.yaml",
167
+ controllers="controllers.yaml",
168
+ scenarios="scenarios.yaml",
169
+ models="models.yaml",
170
+ )
159
171
 
160
- kGNUParallel: types.StrDict = {
161
- 'cmdfile_stem': 'commands',
162
- 'cmdfile_ext': '.txt'
172
+ kGazebo = {
173
+ "launch_cmd": "gazebo",
174
+ "min_version": "11.0.0",
175
+ "physics_iter_per_tick": 1000,
163
176
  }
164
177
 
165
- kExperimentalRunData = {
166
- # Default # datapoints in each .csv of one-dimensional data.
167
- 'n_datapoints_1D': 50
168
- }
178
+ kGNUParallel: types.StrDict = {"cmdfile_stem": "commands", "cmdfile_ext": ".txt"}
169
179
 
170
- kPlatform = {
171
- 'ping_timeout': 10 # seconds
172
- }
180
+ kEngine = {"ping_timeout": 10} # seconds
sierra/core/engine.py ADDED
@@ -0,0 +1,306 @@
1
+ # Copyright 2021 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Terminal interface for pltaform plugins.
5
+
6
+ Classes for generating the commands to run :term:`experiments <Batch
7
+ Experiment>` on multiple :term:`engines <Engine>` using multiple execution
8
+ methods.
9
+
10
+ """
11
+
12
+ # Core packages
13
+ import typing as tp
14
+ import argparse
15
+ import socket
16
+ import logging
17
+ import pathlib
18
+
19
+ # 3rd party packages
20
+ import implements
21
+ import netifaces
22
+
23
+ # Project packages
24
+ import sierra.core.plugin as pm
25
+ from sierra.core import types
26
+ from sierra.core.experiment import bindings
27
+ import sierra.core.variables.batch_criteria as bc
28
+ from sierra.core.trampoline import cmdline_parser # noqa: F401
29
+
30
+ _logger = logging.getLogger(__name__)
31
+
32
+
33
+ def cmdline_postparse_configure(
34
+ engine: str, execenv: str, args: argparse.Namespace
35
+ ) -> argparse.Namespace:
36
+ """Dispatcher for configuring the cmdopts dictionary.
37
+
38
+ Dispatches configuring to the selected ``--engine`` and ``--execenv``.
39
+ Called before the pipeline starts to add modify existing cmdline arguments
40
+ after initial parsing. ``engine`` and ``execenv`` are needed as
41
+ arguments as they are not present in ``args``; they are "bootstrap" cmdline
42
+ args needed to be parsed first to build the parser for the set of cmdline
43
+ arguments accepted.
44
+ """
45
+ # Configure for selected engine
46
+ module = pm.pipeline.get_plugin_module(engine)
47
+
48
+ if hasattr(module, "cmdline_postparse_configure"):
49
+ args = module.cmdline_postparse_configure(execenv, args)
50
+ else:
51
+ _logger.debug(
52
+ (
53
+ "Skipping configuring cmdline from --engine='%s': "
54
+ "does not define cmdline_postparse_configure()"
55
+ ),
56
+ engine,
57
+ )
58
+
59
+ return args
60
+
61
+
62
+ def execenv_check(cmdopts: types.Cmdopts) -> None:
63
+ """Dispatcher for verifying execution environments in stage 2.
64
+
65
+ This is required because what is needed to create experiments in stage 1 for
66
+ a engine is not necessarily the same as what is needed (in terms of
67
+ envvars, daemons, etc.) when running them.
68
+
69
+ """
70
+ module = pm.pipeline.get_plugin_module(cmdopts["engine"])
71
+ if hasattr(module, "execenv_check"):
72
+ module.execenv_check(cmdopts)
73
+ else:
74
+ _logger.debug(
75
+ (
76
+ "Skipping execution environment check for "
77
+ "--engine=%s: does not define execenv_check()"
78
+ ),
79
+ cmdopts["engine"],
80
+ )
81
+
82
+
83
+ @implements.implements(bindings.IExpRunShellCmdsGenerator)
84
+ class ExpRunShellCmdsGenerator:
85
+ """Dispatcher for shell cmd generation for an :term:`Experimental Run`.
86
+
87
+ Dispatches generation to the selected engine.
88
+ Called during stage 1 to add shell commands which should be run immediately
89
+ before and after the shell command to actually execute a single
90
+ :term:`Experimental Run` to the commands file to be fed to whatever the tool
91
+ a given execution environment environment uses to run cmds (e.g., GNU
92
+ parallel).
93
+
94
+ """
95
+
96
+ def __init__(
97
+ self,
98
+ cmdopts: types.Cmdopts,
99
+ criteria: bc.XVarBatchCriteria,
100
+ n_agents: int,
101
+ exp_num: int,
102
+ ) -> None:
103
+ self.cmdopts = cmdopts
104
+ self.criteria = criteria
105
+ module = pm.pipeline.get_plugin_module(self.cmdopts["engine"])
106
+
107
+ if hasattr(module, "ExpRunShellCmdsGenerator"):
108
+ self.engine = module.ExpRunShellCmdsGenerator(
109
+ self.cmdopts, self.criteria, n_agents, exp_num
110
+ )
111
+ else:
112
+ self.engine = None
113
+
114
+ def pre_run_cmds(
115
+ self, host: str, input_fpath: pathlib.Path, run_num: int
116
+ ) -> tp.List[types.ShellCmdSpec]:
117
+ cmds = []
118
+ if self.engine:
119
+ cmds.extend(self.engine.pre_run_cmds(host, input_fpath, run_num))
120
+
121
+ return cmds
122
+
123
+ def exec_run_cmds(
124
+ self, host: str, input_fpath: pathlib.Path, run_num: int
125
+ ) -> tp.List[types.ShellCmdSpec]:
126
+ cmds = []
127
+
128
+ if self.engine:
129
+ cmds.extend(self.engine.exec_run_cmds(host, input_fpath, run_num))
130
+
131
+ return cmds
132
+
133
+ def post_run_cmds(
134
+ self, host: str, run_output_root: pathlib.Path
135
+ ) -> tp.List[types.ShellCmdSpec]:
136
+ cmds = []
137
+
138
+ if self.engine:
139
+ cmds.extend(self.engine.post_run_cmds(host, run_output_root))
140
+
141
+ return cmds
142
+
143
+
144
+ @implements.implements(bindings.IExpShellCmdsGenerator)
145
+ class ExpShellCmdsGenerator:
146
+ """Dispatcher for shell cmd generation for an :term:`Experiment`.
147
+
148
+ Dispatches generation to the selected engine. Called during stage 2 to
149
+ run shell commands immediately before running a given :term:`Experiment`, to
150
+ run shell commands to actually run the experiment, and to run shell commands
151
+ immediately after the experiment finishes.
152
+ """
153
+
154
+ def __init__(self, cmdopts: types.Cmdopts, exp_num: int) -> None:
155
+ self.cmdopts = cmdopts
156
+
157
+ module = pm.pipeline.get_plugin_module(self.cmdopts["engine"])
158
+ if hasattr(module, "ExpShellCmdsGenerator"):
159
+ self.engine = module.ExpShellCmdsGenerator(self.cmdopts, exp_num)
160
+ else:
161
+ _logger.debug(
162
+ (
163
+ "Skipping generating experiment shell commands "
164
+ "for --engine=%s: does not define ExpShellCmdsGenerator"
165
+ ),
166
+ self.cmdopts["engine"],
167
+ )
168
+
169
+ self.engine = None
170
+
171
+ def pre_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
172
+ cmds = []
173
+
174
+ if self.engine:
175
+ cmds.extend(self.engine.pre_exp_cmds())
176
+
177
+ return cmds
178
+
179
+ def exec_exp_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
180
+ cmds = []
181
+
182
+ if self.engine:
183
+ cmds.extend(self.engine.exec_exp_cmds(exec_opts))
184
+
185
+ return cmds
186
+
187
+ def post_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
188
+ cmds = []
189
+
190
+ if self.engine:
191
+ cmds.extend(self.engine.post_exp_cmds())
192
+
193
+ return cmds
194
+
195
+
196
+ @implements.implements(bindings.IBatchShellCmdsGenerator)
197
+ class BatchShellCmdsGenerator:
198
+ """Dispatcher for shell cmd generation for a :term:`Batch Experiment`.
199
+
200
+ Dispatches generation to the selected engine. Called during stage 2 to run
201
+ shell commands immediately before running a given :term:`Batch Experiment`,
202
+ to run shell commands to actually run the experiment, and to run shell
203
+ commands immediately after the whole experiment finishes.
204
+ """
205
+
206
+ def __init__(self, cmdopts: types.Cmdopts) -> None:
207
+ self.cmdopts = cmdopts
208
+
209
+ module = pm.pipeline.get_plugin_module(self.cmdopts["engine"])
210
+ if hasattr(module, "BatchShellCmdsGenerator"):
211
+ self.engine = module.BatchShellCmdsGenerator(self.cmdopts)
212
+ else:
213
+ _logger.debug(
214
+ (
215
+ "Skipping generating batch experiment shell commands "
216
+ "for --engine=%s: does not define BatchShellCmdsGenerator"
217
+ ),
218
+ self.cmdopts["engine"],
219
+ )
220
+
221
+ self.engine = None
222
+
223
+ def pre_batch_cmds(self) -> tp.List[types.ShellCmdSpec]:
224
+ cmds = []
225
+
226
+ if self.engine:
227
+ cmds.extend(self.engine.pre_batch_cmds())
228
+
229
+ return cmds
230
+
231
+ def exec_batch_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
232
+ cmds = []
233
+
234
+ if self.engine:
235
+ cmds.extend(self.engine.exec_batch_cmds(exec_opts))
236
+
237
+ return cmds
238
+
239
+ def post_batch_cmds(self) -> tp.List[types.ShellCmdSpec]:
240
+ cmds = []
241
+
242
+ if self.engine:
243
+ cmds.extend(self.engine.post_batch_cmds())
244
+
245
+ return cmds
246
+
247
+
248
+ class ExpConfigurer:
249
+ """Perform engine-specific configuration for an :term:`Experimental Run`.
250
+
251
+ For things can do programmatically (i.e., without needing a shell). This
252
+ usually is things like creating directories, etc. Called at the end of
253
+ stage 1 during for each experimental run.
254
+
255
+ """
256
+
257
+ def __init__(self, cmdopts: types.Cmdopts) -> None:
258
+ self.cmdopts = cmdopts
259
+ module = pm.pipeline.get_plugin_module(cmdopts["engine"])
260
+ self.engine = module.ExpConfigurer(self.cmdopts)
261
+
262
+ def for_exp_run(
263
+ self, exp_input_root: pathlib.Path, run_output_root: pathlib.Path
264
+ ) -> None:
265
+ self.engine.for_exp_run(exp_input_root, run_output_root)
266
+
267
+ def for_exp(self, exp_input_root: pathlib.Path) -> None:
268
+ self.engine.for_exp(exp_input_root)
269
+
270
+ def parallelism_paradigm(self) -> str:
271
+ return self.engine.parallelism_paradigm()
272
+
273
+
274
+ def get_local_ip():
275
+ """
276
+ Get the local IP address of the SIERRA host machine.
277
+ """
278
+ active = []
279
+ for iface in netifaces.interfaces():
280
+ # Active=has a normal IP address (that's what AF_INET means)
281
+ if socket.AF_INET in netifaces.ifaddresses(iface):
282
+ active.append(iface)
283
+
284
+ active = list(filter("lo".__ne__, active))
285
+
286
+ if len(active) > 1:
287
+ logging.critical(
288
+ (
289
+ "SIERRA host machine has > 1 non-loopback IP addresses"
290
+ "/network interfaces--SIERRA may select the wrong "
291
+ "one: %s"
292
+ ),
293
+ active,
294
+ )
295
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
296
+ s.connect(("8.8.8.8", 80))
297
+ return s.getsockname()[0]
298
+
299
+
300
+ __all__ = [
301
+ "cmdline_postparse_configure",
302
+ "ExpRunShellCmdsGenerator",
303
+ "ExpShellCmdsGenerator",
304
+ "ExpRunShellCmdsGenerator",
305
+ "ExpShellCmdsGenerator",
306
+ ]