reaxkit 1.0.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.
- reaxkit/__init__.py +0 -0
- reaxkit/analysis/__init__.py +0 -0
- reaxkit/analysis/composed/RDF_analyzer.py +560 -0
- reaxkit/analysis/composed/__init__.py +0 -0
- reaxkit/analysis/composed/connectivity_analyzer.py +706 -0
- reaxkit/analysis/composed/coordination_analyzer.py +144 -0
- reaxkit/analysis/composed/electrostatics_analyzer.py +687 -0
- reaxkit/analysis/per_file/__init__.py +0 -0
- reaxkit/analysis/per_file/control_analyzer.py +165 -0
- reaxkit/analysis/per_file/eregime_analyzer.py +108 -0
- reaxkit/analysis/per_file/ffield_analyzer.py +305 -0
- reaxkit/analysis/per_file/fort13_analyzer.py +79 -0
- reaxkit/analysis/per_file/fort57_analyzer.py +106 -0
- reaxkit/analysis/per_file/fort73_analyzer.py +61 -0
- reaxkit/analysis/per_file/fort74_analyzer.py +65 -0
- reaxkit/analysis/per_file/fort76_analyzer.py +191 -0
- reaxkit/analysis/per_file/fort78_analyzer.py +154 -0
- reaxkit/analysis/per_file/fort79_analyzer.py +83 -0
- reaxkit/analysis/per_file/fort7_analyzer.py +393 -0
- reaxkit/analysis/per_file/fort99_analyzer.py +411 -0
- reaxkit/analysis/per_file/molfra_analyzer.py +359 -0
- reaxkit/analysis/per_file/params_analyzer.py +258 -0
- reaxkit/analysis/per_file/summary_analyzer.py +84 -0
- reaxkit/analysis/per_file/trainset_analyzer.py +84 -0
- reaxkit/analysis/per_file/vels_analyzer.py +95 -0
- reaxkit/analysis/per_file/xmolout_analyzer.py +528 -0
- reaxkit/cli.py +181 -0
- reaxkit/count_loc.py +276 -0
- reaxkit/data/alias.yaml +89 -0
- reaxkit/data/constants.yaml +27 -0
- reaxkit/data/reaxff_input_files_contents.yaml +186 -0
- reaxkit/data/reaxff_output_files_contents.yaml +301 -0
- reaxkit/data/units.yaml +38 -0
- reaxkit/help/__init__.py +0 -0
- reaxkit/help/help_index_loader.py +531 -0
- reaxkit/help/introspection_utils.py +131 -0
- reaxkit/io/__init__.py +0 -0
- reaxkit/io/base_handler.py +165 -0
- reaxkit/io/generators/__init__.py +0 -0
- reaxkit/io/generators/control_generator.py +123 -0
- reaxkit/io/generators/eregime_generator.py +341 -0
- reaxkit/io/generators/geo_generator.py +967 -0
- reaxkit/io/generators/trainset_generator.py +1758 -0
- reaxkit/io/generators/tregime_generator.py +113 -0
- reaxkit/io/generators/vregime_generator.py +164 -0
- reaxkit/io/generators/xmolout_generator.py +304 -0
- reaxkit/io/handlers/__init__.py +0 -0
- reaxkit/io/handlers/control_handler.py +209 -0
- reaxkit/io/handlers/eregime_handler.py +122 -0
- reaxkit/io/handlers/ffield_handler.py +812 -0
- reaxkit/io/handlers/fort13_handler.py +123 -0
- reaxkit/io/handlers/fort57_handler.py +143 -0
- reaxkit/io/handlers/fort73_handler.py +145 -0
- reaxkit/io/handlers/fort74_handler.py +155 -0
- reaxkit/io/handlers/fort76_handler.py +195 -0
- reaxkit/io/handlers/fort78_handler.py +142 -0
- reaxkit/io/handlers/fort79_handler.py +227 -0
- reaxkit/io/handlers/fort7_handler.py +264 -0
- reaxkit/io/handlers/fort99_handler.py +128 -0
- reaxkit/io/handlers/geo_handler.py +224 -0
- reaxkit/io/handlers/molfra_handler.py +184 -0
- reaxkit/io/handlers/params_handler.py +137 -0
- reaxkit/io/handlers/summary_handler.py +135 -0
- reaxkit/io/handlers/trainset_handler.py +658 -0
- reaxkit/io/handlers/vels_handler.py +293 -0
- reaxkit/io/handlers/xmolout_handler.py +174 -0
- reaxkit/utils/__init__.py +0 -0
- reaxkit/utils/alias.py +219 -0
- reaxkit/utils/cache.py +77 -0
- reaxkit/utils/constants.py +75 -0
- reaxkit/utils/equation_of_states.py +96 -0
- reaxkit/utils/exceptions.py +27 -0
- reaxkit/utils/frame_utils.py +175 -0
- reaxkit/utils/log.py +43 -0
- reaxkit/utils/media/__init__.py +0 -0
- reaxkit/utils/media/convert.py +90 -0
- reaxkit/utils/media/make_video.py +91 -0
- reaxkit/utils/media/plotter.py +812 -0
- reaxkit/utils/numerical/__init__.py +0 -0
- reaxkit/utils/numerical/extrema_finder.py +96 -0
- reaxkit/utils/numerical/moving_average.py +103 -0
- reaxkit/utils/numerical/numerical_calcs.py +75 -0
- reaxkit/utils/numerical/signal_ops.py +135 -0
- reaxkit/utils/path.py +55 -0
- reaxkit/utils/units.py +104 -0
- reaxkit/webui/__init__.py +0 -0
- reaxkit/webui/app.py +0 -0
- reaxkit/webui/components.py +0 -0
- reaxkit/webui/layouts.py +0 -0
- reaxkit/webui/utils.py +0 -0
- reaxkit/workflows/__init__.py +0 -0
- reaxkit/workflows/composed/__init__.py +0 -0
- reaxkit/workflows/composed/coordination_workflow.py +393 -0
- reaxkit/workflows/composed/electrostatics_workflow.py +587 -0
- reaxkit/workflows/composed/xmolout_fort7_workflow.py +343 -0
- reaxkit/workflows/meta/__init__.py +0 -0
- reaxkit/workflows/meta/help_workflow.py +136 -0
- reaxkit/workflows/meta/introspection_workflow.py +235 -0
- reaxkit/workflows/meta/make_video_workflow.py +61 -0
- reaxkit/workflows/meta/plotter_workflow.py +601 -0
- reaxkit/workflows/per_file/__init__.py +0 -0
- reaxkit/workflows/per_file/control_workflow.py +110 -0
- reaxkit/workflows/per_file/eregime_workflow.py +267 -0
- reaxkit/workflows/per_file/ffield_workflow.py +390 -0
- reaxkit/workflows/per_file/fort13_workflow.py +86 -0
- reaxkit/workflows/per_file/fort57_workflow.py +137 -0
- reaxkit/workflows/per_file/fort73_workflow.py +151 -0
- reaxkit/workflows/per_file/fort74_workflow.py +88 -0
- reaxkit/workflows/per_file/fort76_workflow.py +188 -0
- reaxkit/workflows/per_file/fort78_workflow.py +135 -0
- reaxkit/workflows/per_file/fort79_workflow.py +314 -0
- reaxkit/workflows/per_file/fort7_workflow.py +592 -0
- reaxkit/workflows/per_file/fort83_workflow.py +60 -0
- reaxkit/workflows/per_file/fort99_workflow.py +223 -0
- reaxkit/workflows/per_file/geo_workflow.py +554 -0
- reaxkit/workflows/per_file/molfra_workflow.py +577 -0
- reaxkit/workflows/per_file/params_workflow.py +135 -0
- reaxkit/workflows/per_file/summary_workflow.py +161 -0
- reaxkit/workflows/per_file/trainset_workflow.py +356 -0
- reaxkit/workflows/per_file/tregime_workflow.py +79 -0
- reaxkit/workflows/per_file/vels_workflow.py +309 -0
- reaxkit/workflows/per_file/vregime_workflow.py +75 -0
- reaxkit/workflows/per_file/xmolout_workflow.py +678 -0
- reaxkit-1.0.0.dist-info/METADATA +128 -0
- reaxkit-1.0.0.dist-info/RECORD +130 -0
- reaxkit-1.0.0.dist-info/WHEEL +5 -0
- reaxkit-1.0.0.dist-info/entry_points.txt +2 -0
- reaxkit-1.0.0.dist-info/licenses/AUTHORS.md +20 -0
- reaxkit-1.0.0.dist-info/licenses/LICENSE +21 -0
- reaxkit-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""
|
|
2
|
+
fort.79 sensitivity-analysis workflow for ReaxKit.
|
|
3
|
+
|
|
4
|
+
This workflow provides tools for analyzing parameter sensitivities from
|
|
5
|
+
ReaxFF `fort.79` files, which report how force-field parameters influence
|
|
6
|
+
training or objective-function errors.
|
|
7
|
+
|
|
8
|
+
It supports:
|
|
9
|
+
- Identifying the most sensitive (or least sensitive) force-field parameter
|
|
10
|
+
based on minimum and maximum sensitivity metrics.
|
|
11
|
+
- Visualizing sensitivity evolution across epoch sets for a selected parameter.
|
|
12
|
+
- Generating tornado plots that summarize parameter influence ranges
|
|
13
|
+
(min, median, and max effects) across the force field.
|
|
14
|
+
- Exporting processed sensitivity tables and subsets to CSV for downstream
|
|
15
|
+
analysis or reporting.
|
|
16
|
+
|
|
17
|
+
The workflow is intended for diagnosing force-field training behavior,
|
|
18
|
+
prioritizing parameters for refinement, and interpreting sensitivity-driven
|
|
19
|
+
optimization results.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
import argparse
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from reaxkit.io.handlers.fort79_handler import Fort79Handler
|
|
26
|
+
from reaxkit.analysis.per_file.fort79_analyzer import get_fort79_data_with_diff_sensitivities
|
|
27
|
+
from reaxkit.utils.media.plotter import single_plot, tornado_plot
|
|
28
|
+
from reaxkit.utils.path import resolve_output_path
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _fort79_most_sensitive_param_task(args: argparse.Namespace) -> int:
|
|
32
|
+
"""
|
|
33
|
+
Compute and visualize the parameter with the minimum sensitivity in a fort.79 file.
|
|
34
|
+
|
|
35
|
+
This task:
|
|
36
|
+
- Parses the fort.79 output using `Fort79Handler`
|
|
37
|
+
- Identifies the parameter with the lowest `min_sensitivity`
|
|
38
|
+
- Plots its sensitivity values across epoch-sets (optional: --plot / --save)
|
|
39
|
+
- Exports the full sensitivity table and the minimum-identifier subset (optional: --export)
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
int
|
|
44
|
+
Exit status code (0 on success).
|
|
45
|
+
"""
|
|
46
|
+
handler = Fort79Handler(args.file)
|
|
47
|
+
df_sens = get_fort79_data_with_diff_sensitivities(handler)
|
|
48
|
+
|
|
49
|
+
idx_min = df_sens["min_sensitivity"].idxmin()
|
|
50
|
+
min_identifier = df_sens.loc[idx_min, "identider"]
|
|
51
|
+
min_value = df_sens.loc[idx_min, "min_sensitivity"]
|
|
52
|
+
print(f"[Done] Minimum sensitivity value: {min_value:.6f}")
|
|
53
|
+
print(f"📘 Corresponding identifier: {min_identifier}")
|
|
54
|
+
|
|
55
|
+
df_sens = df_sens.copy()
|
|
56
|
+
df_sens["epoch-set"] = df_sens.index + 1
|
|
57
|
+
|
|
58
|
+
# Columns actually used in plotting
|
|
59
|
+
ratio_cols = ["sensitivity1/3", "sensitivity2/3", "sensitivity4/3"]
|
|
60
|
+
subset_min = df_sens[df_sens["identider"] == min_identifier].copy()
|
|
61
|
+
long_all = (
|
|
62
|
+
subset_min[["epoch-set"] + ratio_cols]
|
|
63
|
+
.melt(
|
|
64
|
+
id_vars=["epoch-set"],
|
|
65
|
+
value_vars=ratio_cols,
|
|
66
|
+
var_name="sensitivity_name",
|
|
67
|
+
value_name="sensitivity",
|
|
68
|
+
)
|
|
69
|
+
.dropna(subset=["sensitivity"])
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
series = [{
|
|
73
|
+
"x": long_all["epoch-set"].to_numpy(),
|
|
74
|
+
"y": long_all["sensitivity"].to_numpy(),
|
|
75
|
+
"label": "sensitivities per epoch",
|
|
76
|
+
"marker": "o",
|
|
77
|
+
"linewidth": 0,
|
|
78
|
+
"markersize": 20,
|
|
79
|
+
"alpha": 1,
|
|
80
|
+
}]
|
|
81
|
+
|
|
82
|
+
title_for_save = "Ratios_per_EpochSet"
|
|
83
|
+
workflow_name = args.kind
|
|
84
|
+
|
|
85
|
+
# ---- SAVE / PLOT ----
|
|
86
|
+
if args.save:
|
|
87
|
+
out_save = Path(resolve_output_path(args.save, workflow_name))
|
|
88
|
+
out_save.parent.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
|
|
90
|
+
if out_save.suffix:
|
|
91
|
+
title_for_save = out_save.stem
|
|
92
|
+
|
|
93
|
+
single_plot(
|
|
94
|
+
series=series,
|
|
95
|
+
plot_type="scatter",
|
|
96
|
+
title=title_for_save,
|
|
97
|
+
xlabel="Epoch Set",
|
|
98
|
+
ylabel="sensitivity (Error Response)",
|
|
99
|
+
save=str(out_save),
|
|
100
|
+
legend=True,
|
|
101
|
+
)
|
|
102
|
+
elif args.plot:
|
|
103
|
+
single_plot(
|
|
104
|
+
series=series,
|
|
105
|
+
plot_type="scatter",
|
|
106
|
+
title=title_for_save,
|
|
107
|
+
xlabel="Epoch Set",
|
|
108
|
+
ylabel="sensitivity (Error Response)",
|
|
109
|
+
save=None,
|
|
110
|
+
legend=True,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# ---- EXPORT ----
|
|
114
|
+
if args.export:
|
|
115
|
+
export_base = Path(resolve_output_path(args.export, workflow_name))
|
|
116
|
+
export_base.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
+
|
|
118
|
+
base_no_suffix = export_base.with_suffix("")
|
|
119
|
+
out_min = base_no_suffix.with_name(base_no_suffix.name + "_min").with_suffix(".csv")
|
|
120
|
+
out_all = base_no_suffix.with_name(base_no_suffix.name + "_all").with_suffix(".csv")
|
|
121
|
+
|
|
122
|
+
# Use the *real* column names that exist in df_sens
|
|
123
|
+
# Start with epoch-set and identider, then the sensitivity columns,
|
|
124
|
+
# then any min/max columns that actually exist.
|
|
125
|
+
export_cols = ["epoch-set", "identider"]
|
|
126
|
+
export_cols += [c for c in ratio_cols if c in df_sens.columns]
|
|
127
|
+
export_cols += [c for c in ["min_sensitivity", "max_sensitivity"] if c in df_sens.columns]
|
|
128
|
+
|
|
129
|
+
# Min-identifier subset
|
|
130
|
+
subset_min = df_sens[df_sens["identider"] == min_identifier].copy()
|
|
131
|
+
subset_min[export_cols].to_csv(out_min, index=False)
|
|
132
|
+
|
|
133
|
+
# All identifiers
|
|
134
|
+
to_all = df_sens.copy()
|
|
135
|
+
to_all[export_cols].to_csv(out_all, index=False)
|
|
136
|
+
|
|
137
|
+
print(f"[Done] Exported min-identifier data to {out_min}")
|
|
138
|
+
print(f"[Done] Exported all-identifier data to {out_all}")
|
|
139
|
+
|
|
140
|
+
if not args.plot and not args.save and not args.export:
|
|
141
|
+
print("ℹ️ No action selected. Use one or more of --plot, --save, --export.")
|
|
142
|
+
return 0
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _fort79_tornado_task(args: argparse.Namespace) -> int:
|
|
146
|
+
"""
|
|
147
|
+
Generate a tornado sensitivity plot from a fort.79 file.
|
|
148
|
+
|
|
149
|
+
This task:
|
|
150
|
+
- Parses sensitivity values from `fort.79`
|
|
151
|
+
- Builds a tornado-style bar plot showing positive and negative effects
|
|
152
|
+
- Allows saving or displaying the plot (via --plot / --save)
|
|
153
|
+
- Supports exporting the processed tornado table (via --export)
|
|
154
|
+
|
|
155
|
+
Returns
|
|
156
|
+
-------
|
|
157
|
+
int
|
|
158
|
+
Exit status code (0 on success).
|
|
159
|
+
"""
|
|
160
|
+
handler = Fort79Handler(args.file)
|
|
161
|
+
sensitivities = get_fort79_data_with_diff_sensitivities(handler) # has: identider, min_sensitivity, max_sensitivity, ...
|
|
162
|
+
|
|
163
|
+
# Aggregate per identifier: min & max from their respective columns
|
|
164
|
+
grouped = (
|
|
165
|
+
sensitivities.groupby("identider", dropna=True)
|
|
166
|
+
.agg(min_eff=("min_sensitivity", "min"),
|
|
167
|
+
max_eff=("max_sensitivity", "max"))
|
|
168
|
+
.reset_index()
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Median across ALL min & max values together (union) per parameter
|
|
172
|
+
eff_union = (
|
|
173
|
+
sensitivities.melt(
|
|
174
|
+
id_vars=["identider"],
|
|
175
|
+
value_vars=["min_sensitivity", "max_sensitivity"],
|
|
176
|
+
var_name="kind",
|
|
177
|
+
value_name="eff"
|
|
178
|
+
)
|
|
179
|
+
.dropna(subset=["eff"])
|
|
180
|
+
)
|
|
181
|
+
median_series = eff_union.groupby("identider", dropna=True)["eff"].median()
|
|
182
|
+
grouped["median_eff"] = grouped["identider"].map(median_series)
|
|
183
|
+
|
|
184
|
+
# Sort by span just like before
|
|
185
|
+
grouped["span"] = grouped["max_eff"] - grouped["min_eff"]
|
|
186
|
+
grouped = grouped.sort_values("span", ascending=False)
|
|
187
|
+
|
|
188
|
+
if grouped.empty:
|
|
189
|
+
print("No data to plot (empty after grouping).")
|
|
190
|
+
return 0
|
|
191
|
+
|
|
192
|
+
# Apply top-N before exporting/plotting
|
|
193
|
+
grouped_top = grouped.head(args.top) if (args.top and args.top > 0) else grouped.copy()
|
|
194
|
+
|
|
195
|
+
workflow_name = args.kind
|
|
196
|
+
# Export (now includes median)
|
|
197
|
+
if args.export:
|
|
198
|
+
print('here!')
|
|
199
|
+
out = resolve_output_path(args.export, workflow_name)
|
|
200
|
+
export_cols = ["identider", "min_eff", "median_eff", "max_eff", "span"]
|
|
201
|
+
grouped_top[export_cols].to_csv(out, index=False)
|
|
202
|
+
print(f"[Done] Exported tornado data to {out}")
|
|
203
|
+
|
|
204
|
+
# Save figure if requested
|
|
205
|
+
if args.save:
|
|
206
|
+
out = resolve_output_path(args.save, workflow_name)
|
|
207
|
+
tornado_plot(
|
|
208
|
+
labels=grouped_top["identider"].tolist(),
|
|
209
|
+
min_vals=grouped_top["min_eff"].tolist(),
|
|
210
|
+
max_vals=grouped_top["max_eff"].tolist(),
|
|
211
|
+
median_vals=grouped_top["median_eff"].tolist(), # NEW
|
|
212
|
+
title="Parameter Sensitivity Tornado Plot",
|
|
213
|
+
xlabel="sensitivity (Error Response)",
|
|
214
|
+
ylabel="Parameter",
|
|
215
|
+
save=out,
|
|
216
|
+
top=0,
|
|
217
|
+
vline=1.0 if args.vline else None,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Interactive plot if requested
|
|
221
|
+
if args.plot:
|
|
222
|
+
tornado_plot(
|
|
223
|
+
labels=grouped_top["identider"].tolist(),
|
|
224
|
+
min_vals=grouped_top["min_eff"].tolist(),
|
|
225
|
+
max_vals=grouped_top["max_eff"].tolist(),
|
|
226
|
+
median_vals=grouped_top["median_eff"].tolist(), # NEW
|
|
227
|
+
title="Parameter Sensitivity Tornado Plot",
|
|
228
|
+
xlabel="sensitivity (Error Response)",
|
|
229
|
+
ylabel="Parameter",
|
|
230
|
+
save=None,
|
|
231
|
+
top=0,
|
|
232
|
+
vline=1.0 if args.vline else None,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if not args.plot and not args.save and not args.export:
|
|
236
|
+
print("ℹ️ No action selected. Use one or more of --plot, --save, --export.")
|
|
237
|
+
|
|
238
|
+
return 0
|
|
239
|
+
|
|
240
|
+
# --------------------------
|
|
241
|
+
# CLI REGISTRATION
|
|
242
|
+
# --------------------------
|
|
243
|
+
def _add_common_fort79_io_args(
|
|
244
|
+
p: argparse.ArgumentParser,
|
|
245
|
+
*,
|
|
246
|
+
include_plot: bool = True,
|
|
247
|
+
) -> None:
|
|
248
|
+
"""
|
|
249
|
+
Common I/O flags for fort.79-based tasks.
|
|
250
|
+
"""
|
|
251
|
+
p.add_argument("--file", default="fort.79", help="Path to fort.79 file.")
|
|
252
|
+
|
|
253
|
+
if include_plot:
|
|
254
|
+
p.add_argument("--plot", action="store_true", help="Show plot interactively.")
|
|
255
|
+
|
|
256
|
+
p.add_argument(
|
|
257
|
+
"--save",
|
|
258
|
+
default=None,
|
|
259
|
+
help="Path or directory to save the plot image (resolved via resolve_output_path).",
|
|
260
|
+
)
|
|
261
|
+
p.add_argument(
|
|
262
|
+
"--export",
|
|
263
|
+
default=None,
|
|
264
|
+
help="Export processed data to CSV (path or directory, resolved via resolve_output_path).",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
def register_tasks(subparsers: argparse._SubParsersAction) -> None:
|
|
268
|
+
|
|
269
|
+
# ------------------------------------------------------
|
|
270
|
+
# most-sensitive
|
|
271
|
+
# ------------------------------------------------------
|
|
272
|
+
most_sensitive = subparsers.add_parser(
|
|
273
|
+
"most-sensitive",
|
|
274
|
+
help="Identify the parameter with the minimum sensitivity and optionally plot or export results.",
|
|
275
|
+
description=(
|
|
276
|
+
"Examples:\n"
|
|
277
|
+
" reaxkit fort79 most-sensitive --plot\n"
|
|
278
|
+
" reaxkit fort79 most-sensitive --export result.csv\n"
|
|
279
|
+
),
|
|
280
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
_add_common_fort79_io_args(most_sensitive)
|
|
284
|
+
most_sensitive.set_defaults(_run=_fort79_most_sensitive_param_task)
|
|
285
|
+
|
|
286
|
+
# ------------------------------------------------------
|
|
287
|
+
# tornado
|
|
288
|
+
# ------------------------------------------------------
|
|
289
|
+
p_tornado = subparsers.add_parser(
|
|
290
|
+
"tornado",
|
|
291
|
+
help="Create a tornado plot of sensitivities from fort.79 and optionally save or export the data.",
|
|
292
|
+
description=(
|
|
293
|
+
"Examples:\n"
|
|
294
|
+
" reaxkit fort79 tornado --top 6 --save tornado.png --export tornado.csv\n"
|
|
295
|
+
),
|
|
296
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
_add_common_fort79_io_args(p_tornado)
|
|
300
|
+
|
|
301
|
+
p_tornado.add_argument(
|
|
302
|
+
"--top",
|
|
303
|
+
type=int,
|
|
304
|
+
default=0,
|
|
305
|
+
help="Only show/export top-N widest spans (0 = show all).",
|
|
306
|
+
)
|
|
307
|
+
p_tornado.add_argument(
|
|
308
|
+
"--vline",
|
|
309
|
+
type=float,
|
|
310
|
+
default=1.0,
|
|
311
|
+
help="Draw a vertical reference line at x = this value.",
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
p_tornado.set_defaults(_run=_fort79_tornado_task)
|