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,249 +0,0 @@
1
- # Copyright 2018 John Harwell, All rights reserved.
2
- #
3
- # SPDX-License-Identifier: MIT
4
- #
5
-
6
- # Core packages
7
- import typing as tp
8
- import copy
9
- import logging
10
- import pathlib
11
-
12
- # 3rd party packages
13
- import pandas as pd
14
- import matplotlib.pyplot as plt
15
-
16
- # Project packages
17
- from sierra.core import config, utils, storage
18
-
19
-
20
- class StackedLineGraph:
21
- """Generates a line graph from a set of columns in a CSV file.
22
-
23
- If the necessary data file does not exist, the graph is not generated.
24
-
25
- If the .stddev file that goes with the .mean does not exist, then no error
26
- bars are plotted.
27
-
28
- If the .model file that goes with the .mean does not exist, then no model
29
- predictions are plotted.
30
-
31
- Ideally, model predictions/stddev calculations would be in derived classes,
32
- but I can't figure out a good way to easily pull that stuff out of here.
33
-
34
- """
35
-
36
- def __init__(self,
37
- stats_root: pathlib.Path,
38
- input_stem: str,
39
- output_fpath: pathlib.Path,
40
- title: str,
41
- xlabel: tp.Optional[str] = None,
42
- ylabel: tp.Optional[str] = None,
43
- large_text: bool = False,
44
- legend: tp.Optional[tp.List[str]] = None,
45
- cols: tp.Optional[tp.List[str]] = None,
46
- linestyles: tp.Optional[tp.List[str]] = None,
47
- dashstyles: tp.Optional[tp.List[str]] = None,
48
- logyscale: bool = False,
49
- stddev_fpath: tp.Optional[pathlib.Path] = None,
50
- stats: str = 'none',
51
- model_root: tp.Optional[pathlib.Path] = None) -> None:
52
-
53
- # Required arguments
54
- self.stats_root = stats_root
55
- self.input_stem = input_stem
56
- self.output_fpath = output_fpath
57
- self.title = title
58
-
59
- # Optional arguments
60
- if large_text:
61
- self.text_size = config.kGraphTextSizeLarge
62
- else:
63
- self.text_size = config.kGraphTextSizeSmall
64
-
65
- self.xlabel = xlabel
66
- self.ylabel = ylabel
67
- self.legend = legend
68
- self.cols = cols
69
- self.logyscale = logyscale
70
- self.linestyles = linestyles
71
- self.dashstyles = dashstyles
72
- self.stats = stats
73
- self.model_root = model_root
74
- self.stddev_fpath = stddev_fpath
75
- self.logger = logging.getLogger(__name__)
76
-
77
- def generate(self) -> None:
78
- ext = config.kStats['mean'].exts['mean']
79
- input_fpath = self.stats_root / (self.input_stem + ext)
80
- if not utils.path_exists(input_fpath):
81
- self.logger.debug("Not generating %s: %s does not exist",
82
- self.output_fpath,
83
- input_fpath)
84
- return
85
-
86
- data_df = storage.DataFrameReader('storage.csv')(input_fpath)
87
-
88
- model = self._read_models()
89
- stat_dfs = self._read_stats()
90
-
91
- # Plot specified columns from dataframe.
92
- if self.cols is None:
93
- ncols = max(1, int(len(data_df.columns) / 2.0))
94
- ax = self._plot_selected_cols(
95
- data_df, stat_dfs, data_df.columns, model)
96
- else:
97
- ncols = max(1, int(len(self.cols) / 2.0))
98
- ax = self._plot_selected_cols(data_df, stat_dfs, self.cols, model)
99
-
100
- self._plot_ticks(ax)
101
-
102
- self._plot_legend(ax, model[1], ncols)
103
-
104
- # Add title
105
- ax.set_title(self.title, fontsize=self.text_size['title'])
106
-
107
- # Add X,Y labels
108
- if self.xlabel is not None:
109
- ax.set_xlabel(self.xlabel, fontsize=self.text_size['xyz_label'])
110
-
111
- if self.ylabel is not None:
112
- ax.set_ylabel(self.ylabel, fontsize=self.text_size['xyz_label'])
113
-
114
- # Output figure
115
- fig = ax.get_figure()
116
- fig.set_size_inches(config.kGraphBaseSize,
117
- config.kGraphBaseSize)
118
- fig.savefig(self.output_fpath,
119
- bbox_inches='tight',
120
- dpi=config.kGraphDPI)
121
- # Prevent memory accumulation (fig.clf() does not close everything)
122
- plt.close(fig)
123
-
124
- def _plot_ticks(self, ax) -> None:
125
- if self.logyscale:
126
- plt.yscale('symlog')
127
-
128
- ax.tick_params(labelsize=self.text_size['tick_label'])
129
-
130
- def _plot_selected_cols(self,
131
- data_df: pd.DataFrame,
132
- stat_dfs: tp.Dict[str, pd.DataFrame],
133
- cols: tp.List[str],
134
- model: tp.Tuple[pd.DataFrame, tp.List[str]]):
135
- """
136
- Plot the selected columns in a dataframe.
137
-
138
- This may include:
139
-
140
- - Errorbars
141
- - Models
142
- - Custom line styles
143
- - Custom dash styles
144
- """
145
- # Always plot the data
146
- if self.linestyles is None and self.dashstyles is None:
147
- ax = data_df[cols].plot()
148
- elif self.dashstyles is None and self.linestyles is not None:
149
- for c, s in zip(cols, self.linestyles):
150
- ax = data_df[c].plot(linestyle=s)
151
- elif self.dashstyles is not None and self.linestyles is not None:
152
- for c, s, d in zip(cols, self.linestyles, self.dashstyles):
153
- ax = data_df[c].plot(linestyle=s, dashes=d)
154
-
155
- # Plot models if they have been computed
156
- if model[0] is not None:
157
- model[0][model[0].columns].plot(ax=ax)
158
-
159
- # Plot stddev if it has been computed
160
- if 'stddev' in stat_dfs.keys():
161
- for c in cols:
162
- self._plot_col_errorbars(data_df, stat_dfs['stddev'], c)
163
- return ax
164
-
165
- def _plot_col_errorbars(self,
166
- data_df: pd.DataFrame,
167
- stddev_df: pd.DataFrame,
168
- col: str) -> None:
169
- """
170
- Plot the errorbars for a specific column in a dataframe.
171
- """
172
- plt.fill_between(data_df.index,
173
- data_df[col] - 2 * stddev_df[col].abs(),
174
- data_df[col] + 2 * stddev_df[col].abs(),
175
- alpha=0.50)
176
-
177
- def _plot_legend(self, ax, model_legend: tp.List[str], ncols: int) -> None:
178
- # Should always use one column: If a small number of lines are plotted,
179
- # then 1 vs. > 1 column makes no difference. If a large number of lines
180
- # are plotted, this will make the figures more portrait than landscape,
181
- # which is more amenable to inclusion in academic papers.
182
-
183
- # If the legend is not specified, then we assume this is not a graph
184
- # that will contain any models and/or no legend is desired.
185
- legend = self.legend
186
-
187
- if self.legend is not None:
188
- legend = copy.deepcopy(self.legend)
189
- if model_legend:
190
- legend.extend(model_legend)
191
-
192
- lines, _ = ax.get_legend_handles_labels()
193
- ax.legend(lines,
194
- legend,
195
- loc='lower center',
196
- bbox_to_anchor=(0.5, -0.5),
197
- ncol=1,
198
- fontsize=self.text_size['legend_label'])
199
- else:
200
- ax.legend().remove()
201
- # ax.legend(loc='lower center',
202
- # bbox_to_anchor=(0.5, -0.5),
203
- # ncol=1,
204
- # fontsize=self.text_size['legend_label'])
205
-
206
- def _read_stats(self) -> tp.Dict[str, pd.DataFrame]:
207
- dfs = {}
208
-
209
- reader = storage.DataFrameReader('storage.csv')
210
- if self.stats in ['conf95', 'all']:
211
- exts = config.kStats['conf95'].exts
212
-
213
- for k in exts:
214
- ipath = self.stats_root / (self.input_stem + exts[k])
215
-
216
- if utils.path_exists(ipath):
217
- dfs[k] = reader(ipath)
218
- else:
219
- self.logger.warning("%sfile not found for '%s'",
220
- exts[k],
221
- self.input_stem)
222
-
223
- return dfs
224
-
225
- def _read_models(self) -> tp.Tuple[pd.DataFrame, tp.List[str]]:
226
- if self.model_root is not None:
227
- model_fpath = self.model_root / \
228
- (self.input_stem + config.kModelsExt['model'])
229
- legend_fpath = self.model_root / \
230
- (self.input_stem + config.kModelsExt['legend'])
231
-
232
- if utils.path_exists(model_fpath):
233
- model = storage.DataFrameReader('storage.csv')(model_fpath)
234
- if utils.path_exists(legend_fpath):
235
- with utils.utf8open(legend_fpath, 'r') as f:
236
- model_legend = f.read().splitlines()
237
- else:
238
- self.logger.warning("No legend file for model '%s' found",
239
- model_fpath)
240
- model_legend = ['Model Prediction']
241
-
242
- return (model, model_legend)
243
-
244
- return (None, [])
245
-
246
-
247
- __api__ = [
248
- 'StackedLineGraph'
249
- ]
@@ -1,220 +0,0 @@
1
- # Copyright 2018 John Harwell, All rights reserved.
2
- #
3
- # SPDX-License-Identifier: MIT
4
- #
5
-
6
- # Core packages
7
- import typing as tp
8
- import logging
9
- import pathlib
10
-
11
- # 3rd party packages
12
- import numpy as np
13
- import matplotlib as mpl
14
- import matplotlib.pyplot as plt
15
- from mpl_toolkits.mplot3d import Axes3D
16
-
17
- # Project packages
18
- from sierra.core import config, storage, types
19
-
20
-
21
- class StackedSurfaceGraph:
22
- """Generates a plot of a set of 3D surface graphs from a set of CSVs.
23
-
24
- ``.mean`` files must be named as``<input_stem_fpath>_X.mean``, where `X` is
25
- non-negative integer. Input CSV files must be 2D grids of the same
26
- cardinality.
27
-
28
- This graph does not plot standard deviation.
29
-
30
- If no ``.mean`` files matching the pattern are found, the graph is not
31
- generated.
32
-
33
- """
34
- kMaxSurfaces = 4
35
-
36
- def __init__(self,
37
- ipaths: types.PathList,
38
- output_fpath: pathlib.Path,
39
- title: str,
40
- legend: tp.List[str],
41
- xlabel: str,
42
- ylabel: str,
43
- zlabel: str,
44
- xtick_labels: tp.List[str],
45
- ytick_labels: tp.List[str],
46
- comp_type: str,
47
- large_text: bool = False) -> None:
48
-
49
- self.ipaths = ipaths
50
- self.output_fpath = output_fpath
51
- self.title = title
52
- self.legend = legend
53
- self.xlabel = xlabel
54
- self.ylabel = ylabel
55
- self.zlabel = zlabel
56
- self.xtick_labels = xtick_labels
57
- self.ytick_labels = ytick_labels
58
- self.comp_type = comp_type
59
-
60
- if large_text:
61
- self.text_size = config.kGraphTextSizeLarge
62
- else:
63
- self.text_size = config.kGraphTextSizeSmall
64
-
65
- self.logger = logging.getLogger(__name__)
66
-
67
- def generate(self) -> None:
68
- reader = storage.DataFrameReader('storage.csv')
69
- dfs = [reader(f) for f in self.ipaths]
70
-
71
- if not dfs or len(dfs) > StackedSurfaceGraph.kMaxSurfaces:
72
- self.logger.debug(("Not generating stacked surface graph: wrong # "
73
- "files (must be > 0, <= %s)"),
74
- StackedSurfaceGraph.kMaxSurfaces)
75
- return
76
-
77
- assert len(dfs) <= StackedSurfaceGraph.kMaxSurfaces,\
78
- f"Too many surfaces to plot: {len(dfs)} > {StackedSurfaceGraph.kMaxSurfaces}"
79
-
80
- # Scaffold graph
81
- plt.figure(figsize=(config.kGraphBaseSize, config.kGraphBaseSize))
82
- ax = plt.axes(projection='3d')
83
- x = np.arange(len(dfs[0].columns))
84
- y = dfs[0].index
85
- X, Y = np.meshgrid(x, y)
86
-
87
- # Use non-quantitative colormaps in order to get really nice looking
88
- # surfaces that change color with Z value. From
89
- # https://stackoverflow.com/questions/55501860/how-to-put-multiple-colormap-patches-in-a-matplotlib-legend
90
- colors = [plt.cm.Greens, plt.cm.Reds, plt.cm.Purples, plt.cm.Oranges]
91
- legend_cmap_handles = [mpl.patches.Rectangle(
92
- (0, 0), 1, 1) for _ in colors]
93
- legend_handler_map = dict(zip(legend_cmap_handles,
94
- [HandlerColormap(c, num_stripes=8) for c in colors]))
95
-
96
- # Plot surfaces
97
- self._plot_surfaces(X, Y, ax, colors, dfs)
98
-
99
- # Add title
100
- ax.set_title(self.title, fontsize=24)
101
-
102
- # Add X,Y,Z labels
103
- self._plot_labels(ax)
104
-
105
- # Add X,Y ticks
106
- self._plot_ticks(ax, x, y)
107
-
108
- # Add legend
109
- self._plot_legend(ax, legend_cmap_handles, legend_handler_map)
110
-
111
- # Output figures
112
- fig = ax.get_figure()
113
- fig.set_size_inches(10, 10)
114
- self._save_figs(fig, ax)
115
-
116
- def _plot_surfaces(self, X, Y, ax, colors, dfs):
117
- ax.plot_surface(X, Y, dfs[0], cmap=colors[0])
118
-
119
- # We do the calculations between dataframes in here rather than in the
120
- # comparator, because we can be comparing more than 2.
121
- for i in range(1, len(dfs)):
122
- if self.comp_type == 'SUraw':
123
- plot_df = dfs[i]
124
- elif self.comp_type == 'SUscale':
125
- plot_df = dfs[i] / dfs[0]
126
- elif self.comp_type == 'SUdiff':
127
- plot_df = dfs[i] - dfs[0]
128
- ax.plot_surface(X, Y, plot_df, cmap=colors[i], alpha=0.5)
129
-
130
- def _plot_ticks(self, ax, xvals, yvals):
131
- """Plot ticks and tick labels.
132
-
133
- If the labels are numerical and the numbers are too large, force
134
- scientific notation (the ``rcParam`` way of doing this does not seem to
135
- work...)
136
-
137
- """
138
- ax.tick_params(labelsize=self.text_size['tick_label'])
139
- ax.set_xticks(xvals)
140
- ax.set_xticklabels(self.xtick_labels, rotation='vertical')
141
-
142
- ax.set_yticks(yvals)
143
- ax.set_yticklabels(self.ytick_labels, rotation='vertical')
144
-
145
- def _plot_legend(self, ax, cmap_handles, handler_map):
146
- # Legend should have ~3 entries per column, in order to maximize real
147
- # estate on tightly constrained papers.
148
- ax.legend(handles=cmap_handles,
149
- handler_map=handler_map,
150
- labels=self.legend,
151
- loc=9,
152
- bbox_to_anchor=(0.5, -0.1),
153
- ncol=len(self.legend),
154
- fontsize=self.text_size['legend_label'])
155
-
156
- def _plot_labels(self, ax):
157
- max_xlen = max([len(str(l)) for l in self.xtick_labels])
158
- max_ylen = max([len(str(l)) for l in self.ytick_labels])
159
- ax.set_xlabel('\n' * max_xlen + self.xlabel,
160
- fontsize=self.text_size['xyz_label'])
161
- ax.set_ylabel('\n' * max_ylen + self.ylabel,
162
- fontsize=self.text_size['xyz_label'])
163
- ax.set_zlabel('\n' + self.zlabel, fontsize=self.text_size['xyz_label'])
164
-
165
- def _save_figs(self, fig, ax):
166
- """Save multiple rotated copies of the same figure.
167
-
168
- Necessary for automation of 3D figure generation, because you can't
169
- really know a priori what views are going to give the best results. MPL
170
- doesn't have a true 3D plot generator yet.
171
-
172
- """
173
- for angle in range(0, 360, 30):
174
- ax.view_init(elev=None, azim=angle)
175
- # The path we are passed may contain dots from the controller same,
176
- # so we extract the leaf of that for manipulation to add the angle
177
- # of the view right before the file extension.
178
- path = self.output_fpath.parent
179
- leaf = self.output_fpath.name
180
- components = leaf.split('.')
181
- fname = ''.join(leaf[0:-2]) + '_' + \
182
- str(angle) + '.' + components[-1]
183
- fig.savefig(path / fname,
184
- bbox_inches='tight',
185
- dpi=config.kGraphDPI,
186
- pad_inches=0)
187
- # Prevent memory accumulation (fig.clf() does not close everything)
188
- plt.close(fig)
189
-
190
-
191
- class HandlerColormap(mpl.legend_handler.HandlerBase):
192
- def __init__(self, cmap, num_stripes=8, **kw) -> None:
193
- super().__init__(**kw)
194
- self.cmap = cmap
195
- self.num_stripes = num_stripes
196
-
197
- def create_artists(self,
198
- legend,
199
- orig_handle,
200
- xdescent,
201
- ydescent,
202
- width,
203
- height,
204
- fontsize,
205
- trans):
206
- stripes = []
207
- for i in range(self.num_stripes):
208
- s = mpl.patches.Rectangle([xdescent + i * width / self.num_stripes, ydescent],
209
- width / self.num_stripes,
210
- height,
211
- fc=self.cmap(
212
- (2 * i + 1) / (2 * self.num_stripes)),
213
- transform=trans)
214
- stripes.append(s)
215
- return stripes
216
-
217
-
218
- __api__ = [
219
- 'StackedSurfaceGraph'
220
- ]