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
@@ -1,10 +1,10 @@
1
1
  # Copyright 2018 John Harwell, All rights reserved.
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- """Factory for combining controller+scenario XML modification generators.
4
+ """Factory for combining controller+scenario expdef modification generators.
5
5
 
6
6
  By combining them together, the result can be easily used to apply modifications
7
- to the template XML file to scaffold the batch experiment.
7
+ to the template expdef file to scaffold the batch experiment.
8
8
 
9
9
  """
10
10
  # Core packages
@@ -17,213 +17,214 @@ import pathlib
17
17
  import yaml
18
18
 
19
19
  # Project packages
20
- from sierra.core.experiment import spec, xml, definition
21
- import sierra.core.plugin_manager as pm
20
+ from sierra.core.experiment import definition
21
+ from sierra.core.experiment import spec as expspec
22
+ import sierra.core.plugin as pm
22
23
  from sierra.core import types, config, utils
23
24
 
24
25
 
25
- class ControllerGenerator():
26
- """Generate XML changes for a selected ``--controller``.
26
+ class ControllerGenerator:
27
+ """Generate expdef changes for a selected ``--controller``.
27
28
 
28
29
  If the specified controller is not found in ``controllers.yaml`` for the
29
- loaded :term:`Project`, an assert will be triggered.
30
+ loaded :term:`Project`, a warning will be issued.
30
31
  """
31
32
 
32
- def __init__(self,
33
- controller: str,
34
- config_root: pathlib.Path,
35
- cmdopts: types.Cmdopts,
36
- exp_spec: spec.ExperimentSpec) -> None:
33
+ def __init__(
34
+ self,
35
+ controller: str,
36
+ config_root: pathlib.Path,
37
+ cmdopts: types.Cmdopts,
38
+ spec: expspec.ExperimentSpec,
39
+ ) -> None:
37
40
  controllers_yaml = config_root / config.kYAML.controllers
38
- with utils.utf8open(controllers_yaml) as f:
39
- self.controller_config = yaml.load(f, yaml.FullLoader)
41
+ self.logger = logging.getLogger(__name__)
42
+ self.name = controller
43
+
44
+ try:
45
+ with utils.utf8open(controllers_yaml) as f:
46
+ self.controller_config = yaml.load(f, yaml.FullLoader)
47
+ except FileNotFoundError:
48
+ self.logger.warning("%s does not exist!", controllers_yaml)
49
+ self.controller_config = {}
40
50
 
41
51
  main_yaml = config_root / config.kYAML.main
42
52
  with utils.utf8open(main_yaml) as f:
43
53
  self.main_config = yaml.load(f, yaml.FullLoader)
44
54
 
45
- self.category, self.name = controller.split('.')
55
+ # Only check this if controllers.yaml exists. If it doesn't, then user's
56
+ # can use whatever they want as the controller name (i.e., doesn't need
57
+ # to conform to the below schema).
58
+ if self.controller_config is not None:
59
+ n_components = len(controller.split("."))
60
+ if n_components != 2:
61
+ raise RuntimeError(
62
+ (
63
+ "Expected 2 controller components, got "
64
+ f"{n_components}. Arguments to --controller "
65
+ "must be of the form CATEGORY.TYPE (i.e., 2 "
66
+ "components separated by a '.')."
67
+ )
68
+ )
69
+
70
+ self.category, self.name = controller.split(".")
46
71
  self.cmdopts = cmdopts
47
72
  self.logger = logging.getLogger(__name__)
48
- self.spec = exp_spec
73
+ self.spec = spec
49
74
 
50
- def generate(self, exp_def: definition.XMLExpDef) -> definition.XMLExpDef:
51
- """Generate all modifications to the experiment definition from the controller.
75
+ def generate(self, exp_def: definition.BaseExpDef) -> definition.BaseExpDef:
76
+ """Generate all modifications to the expdef from the controller.
52
77
 
53
- Does not save.
78
+ Returns a new, modified expdef. Does not save to filesystem.
54
79
 
55
80
  """
56
81
  self._generate_controller_support(exp_def)
57
82
  self._generate_controller(exp_def)
58
83
  return exp_def
59
84
 
60
- def _pp_for_tag_add(self,
61
- add: xml.TagAdd,
62
- robot_id: tp.Optional[int] = None) -> xml.TagAdd:
63
- module = pm.pipeline.get_plugin_module(self.cmdopts['platform'])
85
+ def _pp_for_element_add(
86
+ self, add: definition.ElementAdd, robot_id: tp.Optional[int] = None
87
+ ) -> definition.ElementAdd:
88
+ module = pm.pipeline.get_plugin_module(self.cmdopts["engine"])
64
89
 
65
- if '__UUID__' in add.path:
90
+ if "__UUID__" in add.path:
66
91
  prefix = module.robot_prefix_extract(self.main_config, self.cmdopts)
67
- add.path = add.path.replace('__UUID__', f"{prefix}{robot_id}")
92
+ add.path = add.path.replace("__UUID__", f"{prefix}{robot_id}")
68
93
 
69
94
  return add
70
95
 
71
- def _do_tag_add(self,
72
- exp_def: definition.XMLExpDef,
73
- add: xml.TagAdd) -> None:
96
+ def _do_element_add(
97
+ self, exp_def: definition.BaseExpDef, add: definition.ElementAdd
98
+ ) -> None:
74
99
 
75
100
  # If the user is applying tags for each robot, then they might be added
76
101
  # multiple tags with the same name, but different attributes, so we
77
102
  # allow that explicitly here. Otherwise, we force all tag adds to be
78
103
  # unique.
79
- if '__UUID__' in add.path:
80
- # We can't use platform.population_size_from_def() here because we
104
+ if "__UUID__" in add.path:
105
+ # We can't use engine.population_size_from_def() here because we
81
106
  # haven't added any tags to the experiment definition yet, and if
82
- # the platform relies on added tags to calculate population sizes,
107
+ # the engine relies on added tags to calculate population sizes,
83
108
  # then this won't work.
84
109
  controllers = config.kYAML.controllers
85
- assert hasattr(self.spec.criteria, 'n_robots'),\
86
- (f"When using __UUID__ and tag_add in {controllers}, the batch "
87
- "criteria must implement bc.IQueryableBatchCriteria")
88
- n_robots = self.spec.criteria.n_robots(self.spec.exp_num)
110
+ assert hasattr(self.spec.criteria, "n_agents"), (
111
+ f"When using __UUID__ and element_add in {controllers}, the batch "
112
+ "criteria must implement bc.IQueryableBatchCriteria"
113
+ )
114
+ n_agents = self.spec.criteria.n_agents(self.spec.exp_num)
89
115
 
90
- assert n_robots > 0,\
91
- "Batch criteria {self.spec.criteria} returned 0 robots?"
116
+ assert (
117
+ n_agents > 0
118
+ ), "Batch criteria {self.spec.criteria} returned 0 agents?"
92
119
 
93
- for robot_id in range(0, n_robots):
120
+ for robot_id in range(0, n_agents):
94
121
  to_pp = copy.deepcopy(add)
95
- pp_add = self._pp_for_tag_add(to_pp, robot_id)
96
- exp_def.tag_add(pp_add.path,
97
- pp_add.tag,
98
- pp_add.attr,
99
- True)
122
+ pp_add = self._pp_for_element_add(to_pp, robot_id)
123
+ exp_def.element_add(pp_add.path, pp_add.tag, pp_add.attr, True)
100
124
  else:
101
125
  to_pp = copy.deepcopy(add)
102
- pp_add = self._pp_for_tag_add(to_pp)
103
- exp_def.tag_add(pp_add.path,
104
- pp_add.tag,
105
- pp_add.attr,
106
- False)
107
-
108
- def _generate_controller_support(self,
109
- exp_def: definition.XMLExpDef) -> None:
126
+ pp_add = self._pp_for_element_add(to_pp)
127
+ exp_def.element_add(pp_add.path, pp_add.tag, pp_add.attr, False)
128
+
129
+ def _generate_controller_support(self, exp_def: definition.BaseExpDef) -> None:
110
130
  # Setup controller support code (if any)
111
- xml_mods = self.controller_config.get(self.category, {}).get('xml', {})
131
+ xml_mods = self.controller_config.get(self.category, {}).get("xml", {})
112
132
 
113
- chgs = xml_mods.get('attr_change', {})
133
+ chgs = xml_mods.get("attr_change", {})
114
134
  for t in chgs:
115
135
  exp_def.attr_change(t[0], t[1], t[2])
116
136
 
117
- chgs = xml_mods. get('tag_change', {})
137
+ chgs = xml_mods.get("element_change", {})
118
138
  for t in chgs:
119
- exp_def.tag_change(t[0], t[1], t[2])
139
+ exp_def.element_change(t[0], t[1], t[2])
120
140
 
121
- adds = xml_mods.get('tag_add', {})
141
+ adds = xml_mods.get("element_add", {})
122
142
  for t in adds:
123
- self._do_tag_add(exp_def, xml.TagAdd(t[0],
124
- t[1],
125
- eval(t[2]),
126
- False))
143
+ self._do_element_add(
144
+ exp_def, definition.ElementAdd(t[0], t[1], eval(t[2]), False)
145
+ )
127
146
 
128
- def _generate_controller(self, exp_def: definition.XMLExpDef) -> None:
147
+ def _generate_controller(self, exp_def: definition.BaseExpDef) -> None:
129
148
  if self.category not in self.controller_config:
130
- self.logger.fatal("Controller category '%s' not found in YAML configuration",
131
- self.category)
132
- raise RuntimeError
133
-
134
- if not any(self.name in config['name'] for config in self.controller_config[self.category]['controllers']):
135
- self.logger.fatal("Controller name '%s' not found in YAML configuration",
136
- self.name)
137
- raise RuntimeError
138
-
139
- self.logger.debug("Applying changes from %s (all experiments)",
140
- config.kYAML.controllers)
141
-
142
- for controller in self.controller_config[self.category]['controllers']:
143
- if controller['name'] != self.name:
149
+ self.logger.warning(
150
+ "Controller category '%s' not found in YAML configuration",
151
+ self.category,
152
+ )
153
+ return
154
+
155
+ if not any(
156
+ self.name in config["name"]
157
+ for config in self.controller_config[self.category]["controllers"]
158
+ ):
159
+ self.logger.warning(
160
+ "Controller name '%s' not found in YAML configuration", self.name
161
+ )
162
+ return
163
+
164
+ self.logger.debug(
165
+ "Applying changes from %s (all experiments)", config.kYAML.controllers
166
+ )
167
+
168
+ for controller in self.controller_config[self.category]["controllers"]:
169
+ if controller["name"] != self.name:
144
170
  continue
145
171
 
146
- chgs = controller.get('xml', {}).get('attr_change', {})
172
+ chgs = controller.get("xml", {}).get("attr_change", {})
147
173
  for t in chgs:
148
174
  exp_def.attr_change(t[0], t[1], t[2])
149
175
 
150
- chgs = controller.get('xml', {}).get('tag_change', {})
176
+ chgs = controller.get("xml", {}).get("element_change", {})
151
177
  for t in chgs:
152
- exp_def.tag_change(t[0], t[1], t[2])
178
+ exp_def.element_change(t[0], t[1], t[2])
153
179
 
154
- adds = controller.get('xml', {}).get('tag_add', {})
180
+ adds = controller.get("xml", {}).get("element_add", {})
155
181
  for t in adds:
156
- self._do_tag_add(exp_def, xml.TagAdd(t[0],
157
- t[1],
158
- eval(t[2]),
159
- False))
182
+ self._do_element_add(
183
+ exp_def, definition.ElementAdd(t[0], t[1], eval(t[2]), False)
184
+ )
160
185
 
161
186
 
162
- def joint_generator_create(controller, scenario):
163
- """
164
- Combine controller and scenario XML modification generators together.
165
- """
166
- joint_name = '+'.join([controller.__class__.__name__,
167
- scenario.__class__.__name__])
187
+ class ScenarioGenerator:
188
+ """Generate expdef changes for a selected ``--scenario``."""
168
189
 
169
- def __init__(self) -> None:
190
+ def __init__(
191
+ self, spec: expspec.ExperimentSpec, controller: str, scenario: str, **kwargs
192
+ ):
193
+ self.logger = logging.getLogger(__name__)
194
+ self.spec = spec
170
195
  self.controller = controller
171
- self.scenario = scenario
172
- self.joint_name = joint_name
196
+ self.name = scenario
197
+ self.kwargs = kwargs
173
198
 
174
- def generate(self):
175
- exp_def = self.scenario.generate()
176
- return self.controller.generate(exp_def)
199
+ cmdopts = kwargs["cmdopts"]
200
+ module = pm.module_load_tiered(
201
+ project=cmdopts["project"], path="generators.scenario"
202
+ )
203
+ self.generator = getattr(module, module.to_generator_name(spec.scenario_name))
177
204
 
178
- return type(joint_name,
179
- (object,), {"__init__": __init__, "generate":
180
- generate})()
205
+ def generate(self):
206
+ return self.generator(spec=self.spec, controller=self.controller, **self.kwargs)
181
207
 
182
208
 
183
- def scenario_generator_create(exp_spec: spec.ExperimentSpec,
184
- controller,
185
- **kwargs):
209
+ class JointGenerator:
186
210
  """
187
- Create a scenario generator using the plugin search path.
211
+ Combine controller and scenario expdef modification generators together.
188
212
  """
189
213
 
190
- def __init__(self, **kwargs) -> None:
191
- cmdopts = kwargs['cmdopts']
192
- self.logger = logging.getLogger(__name__)
193
- module = pm.module_load_tiered(project=cmdopts['project'],
194
- path='generators.scenario_generators')
195
- generator_name = module.gen_generator_name(exp_spec.scenario_name)
196
- self.scenario_generator = getattr(module, generator_name)(controller=controller,
197
- exp_spec=exp_spec,
198
- **kwargs)
214
+ def __init__(
215
+ self, controller: ControllerGenerator, scenario: ScenarioGenerator
216
+ ) -> None:
217
+ self.name = "+".join([controller.name, scenario.name])
218
+ self.controller = controller
219
+ self.scenario = scenario
199
220
 
200
221
  def generate(self):
201
- return self.scenario_generator.generate()
202
-
203
- return type(exp_spec.scenario_name,
204
- (object,), {"__init__": __init__,
205
- "generate": generate
206
- })(**kwargs)
207
-
208
-
209
- def controller_generator_create(controller: str,
210
- config_root: pathlib.Path,
211
- cmdopts: types.Cmdopts,
212
- exp_spec: spec.ExperimentSpec):
213
- """
214
- Create a controller generator from the cmdline specification.
215
- """
216
-
217
- return type(controller,
218
- (ControllerGenerator,), {})(controller,
219
- config_root,
220
- cmdopts,
221
- exp_spec)
222
+ exp_def = self.scenario.generate()
223
+ return self.controller.generate(exp_def)
222
224
 
223
225
 
224
- __api__ = [
225
- 'ControllerGenerator',
226
- 'joint_generator_create',
227
- 'scenario_generator_create',
228
- 'controller_generator_create',
226
+ __all__ = [
227
+ "ControllerGenerator",
228
+ "ScenarioGenerator",
229
+ "JointGenerator",
229
230
  ]
@@ -0,0 +1,23 @@
1
+ # Copyright 2021 John Harwell, All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Container module for things related to graphs."""
5
+
6
+ # Core packages
7
+
8
+ # 3rd party packages
9
+
10
+ # Project packages
11
+ from .stacked_line import generate as stacked_line
12
+ from .summary_line import generate as summary_line
13
+ from .heatmap import generate as heatmap
14
+ from .heatmap import generate2 as dual_heatmap
15
+ from .pathset import PathSet
16
+
17
+ __all__ = [
18
+ "stacked_line",
19
+ "summary_line",
20
+ "heatmap",
21
+ "dual_heatmap",
22
+ "PathSet",
23
+ ]
@@ -0,0 +1,94 @@
1
+ #
2
+ # Copyright 2025 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """
7
+ Bridge/glue interfaces/bindings for :term:`Batch Criteria` which can be graphed.
8
+ """
9
+
10
+ # Core packages
11
+ import pathlib
12
+ import typing as tp
13
+
14
+ # 3rd party packages
15
+ import implements
16
+
17
+ # Project packages
18
+ from sierra.core import types
19
+
20
+
21
+ class GraphInfo:
22
+ """
23
+ Container of info for generating graphs from batch criteria.
24
+
25
+ Attributes:
26
+ cmdopts: Dictionary of parsed command line options. Most batch
27
+ criteria will not need this to compute things, BUT it is
28
+ available.
29
+
30
+ batch_output_root: Root directory for all experimental output in the
31
+ batch. Needed in calculating graphs for batch
32
+ criteria when ``--exp-range`` is used.
33
+
34
+ exp_names: The names of experiment directories to instantiate on the
35
+ filesystem.
36
+
37
+ xticklabels: Labels for the xticks.
38
+
39
+ xticks: The x-axis ticks.
40
+
41
+ yticklabels: Labels for the yticks.
42
+
43
+ yticks: The y-axis ticks.
44
+
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ cmdopts: types.Cmdopts,
50
+ batch_output_root: tp.Optional[pathlib.Path] = None,
51
+ exp_names: tp.Optional[tp.List[str]] = None,
52
+ ) -> None:
53
+ self.cmdopts = cmdopts
54
+ self.batch_output_root = batch_output_root
55
+ self.exp_names = exp_names
56
+
57
+ self.xticklabels = [] # type: tp.List[str]
58
+ self.xticks = [] # type: tp.List[float]
59
+ self.xlabel = ""
60
+
61
+ self.yticklabels = [] # type: tp.List[str]
62
+ self.yticks = [] # type: tp.List[float]
63
+ self.ylabel = ""
64
+
65
+
66
+ class IGraphable(implements.Interface):
67
+ """
68
+ Interface for batch criteria for usage with :ref:`plugins/prod/graphs`.
69
+ """
70
+
71
+ def graph_info(
72
+ self,
73
+ cmdopts: types.Cmdopts,
74
+ batch_output_root: tp.Optional[pathlib.Path] = None,
75
+ exp_names: tp.Optional[tp.List[str]] = None,
76
+ ) -> GraphInfo:
77
+ """
78
+ Generate graph info for generating graphs from :term:`Batch Criteria`.
79
+
80
+ Arguments:
81
+
82
+ exp_names: Needed as an optional for bivariate batch
83
+ criteria. When calculating say yticks using criteria2, if
84
+ criteria2 uses ``populations()`` in the process,
85
+ the criteria's OWN ``gen_exp_names()`` will be used, which
86
+ will result in bad directory name calculations. This can
87
+ be overcome by passing the list of exp names to use at
88
+ THIS level, which should override the value otherwise
89
+ present in :class:`GraphInfo`.
90
+ """
91
+ raise NotImplementedError
92
+
93
+
94
+ __all__ = ["GraphInfo", "IGraphable"]