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