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.
Files changed (130) hide show
  1. reaxkit/__init__.py +0 -0
  2. reaxkit/analysis/__init__.py +0 -0
  3. reaxkit/analysis/composed/RDF_analyzer.py +560 -0
  4. reaxkit/analysis/composed/__init__.py +0 -0
  5. reaxkit/analysis/composed/connectivity_analyzer.py +706 -0
  6. reaxkit/analysis/composed/coordination_analyzer.py +144 -0
  7. reaxkit/analysis/composed/electrostatics_analyzer.py +687 -0
  8. reaxkit/analysis/per_file/__init__.py +0 -0
  9. reaxkit/analysis/per_file/control_analyzer.py +165 -0
  10. reaxkit/analysis/per_file/eregime_analyzer.py +108 -0
  11. reaxkit/analysis/per_file/ffield_analyzer.py +305 -0
  12. reaxkit/analysis/per_file/fort13_analyzer.py +79 -0
  13. reaxkit/analysis/per_file/fort57_analyzer.py +106 -0
  14. reaxkit/analysis/per_file/fort73_analyzer.py +61 -0
  15. reaxkit/analysis/per_file/fort74_analyzer.py +65 -0
  16. reaxkit/analysis/per_file/fort76_analyzer.py +191 -0
  17. reaxkit/analysis/per_file/fort78_analyzer.py +154 -0
  18. reaxkit/analysis/per_file/fort79_analyzer.py +83 -0
  19. reaxkit/analysis/per_file/fort7_analyzer.py +393 -0
  20. reaxkit/analysis/per_file/fort99_analyzer.py +411 -0
  21. reaxkit/analysis/per_file/molfra_analyzer.py +359 -0
  22. reaxkit/analysis/per_file/params_analyzer.py +258 -0
  23. reaxkit/analysis/per_file/summary_analyzer.py +84 -0
  24. reaxkit/analysis/per_file/trainset_analyzer.py +84 -0
  25. reaxkit/analysis/per_file/vels_analyzer.py +95 -0
  26. reaxkit/analysis/per_file/xmolout_analyzer.py +528 -0
  27. reaxkit/cli.py +181 -0
  28. reaxkit/count_loc.py +276 -0
  29. reaxkit/data/alias.yaml +89 -0
  30. reaxkit/data/constants.yaml +27 -0
  31. reaxkit/data/reaxff_input_files_contents.yaml +186 -0
  32. reaxkit/data/reaxff_output_files_contents.yaml +301 -0
  33. reaxkit/data/units.yaml +38 -0
  34. reaxkit/help/__init__.py +0 -0
  35. reaxkit/help/help_index_loader.py +531 -0
  36. reaxkit/help/introspection_utils.py +131 -0
  37. reaxkit/io/__init__.py +0 -0
  38. reaxkit/io/base_handler.py +165 -0
  39. reaxkit/io/generators/__init__.py +0 -0
  40. reaxkit/io/generators/control_generator.py +123 -0
  41. reaxkit/io/generators/eregime_generator.py +341 -0
  42. reaxkit/io/generators/geo_generator.py +967 -0
  43. reaxkit/io/generators/trainset_generator.py +1758 -0
  44. reaxkit/io/generators/tregime_generator.py +113 -0
  45. reaxkit/io/generators/vregime_generator.py +164 -0
  46. reaxkit/io/generators/xmolout_generator.py +304 -0
  47. reaxkit/io/handlers/__init__.py +0 -0
  48. reaxkit/io/handlers/control_handler.py +209 -0
  49. reaxkit/io/handlers/eregime_handler.py +122 -0
  50. reaxkit/io/handlers/ffield_handler.py +812 -0
  51. reaxkit/io/handlers/fort13_handler.py +123 -0
  52. reaxkit/io/handlers/fort57_handler.py +143 -0
  53. reaxkit/io/handlers/fort73_handler.py +145 -0
  54. reaxkit/io/handlers/fort74_handler.py +155 -0
  55. reaxkit/io/handlers/fort76_handler.py +195 -0
  56. reaxkit/io/handlers/fort78_handler.py +142 -0
  57. reaxkit/io/handlers/fort79_handler.py +227 -0
  58. reaxkit/io/handlers/fort7_handler.py +264 -0
  59. reaxkit/io/handlers/fort99_handler.py +128 -0
  60. reaxkit/io/handlers/geo_handler.py +224 -0
  61. reaxkit/io/handlers/molfra_handler.py +184 -0
  62. reaxkit/io/handlers/params_handler.py +137 -0
  63. reaxkit/io/handlers/summary_handler.py +135 -0
  64. reaxkit/io/handlers/trainset_handler.py +658 -0
  65. reaxkit/io/handlers/vels_handler.py +293 -0
  66. reaxkit/io/handlers/xmolout_handler.py +174 -0
  67. reaxkit/utils/__init__.py +0 -0
  68. reaxkit/utils/alias.py +219 -0
  69. reaxkit/utils/cache.py +77 -0
  70. reaxkit/utils/constants.py +75 -0
  71. reaxkit/utils/equation_of_states.py +96 -0
  72. reaxkit/utils/exceptions.py +27 -0
  73. reaxkit/utils/frame_utils.py +175 -0
  74. reaxkit/utils/log.py +43 -0
  75. reaxkit/utils/media/__init__.py +0 -0
  76. reaxkit/utils/media/convert.py +90 -0
  77. reaxkit/utils/media/make_video.py +91 -0
  78. reaxkit/utils/media/plotter.py +812 -0
  79. reaxkit/utils/numerical/__init__.py +0 -0
  80. reaxkit/utils/numerical/extrema_finder.py +96 -0
  81. reaxkit/utils/numerical/moving_average.py +103 -0
  82. reaxkit/utils/numerical/numerical_calcs.py +75 -0
  83. reaxkit/utils/numerical/signal_ops.py +135 -0
  84. reaxkit/utils/path.py +55 -0
  85. reaxkit/utils/units.py +104 -0
  86. reaxkit/webui/__init__.py +0 -0
  87. reaxkit/webui/app.py +0 -0
  88. reaxkit/webui/components.py +0 -0
  89. reaxkit/webui/layouts.py +0 -0
  90. reaxkit/webui/utils.py +0 -0
  91. reaxkit/workflows/__init__.py +0 -0
  92. reaxkit/workflows/composed/__init__.py +0 -0
  93. reaxkit/workflows/composed/coordination_workflow.py +393 -0
  94. reaxkit/workflows/composed/electrostatics_workflow.py +587 -0
  95. reaxkit/workflows/composed/xmolout_fort7_workflow.py +343 -0
  96. reaxkit/workflows/meta/__init__.py +0 -0
  97. reaxkit/workflows/meta/help_workflow.py +136 -0
  98. reaxkit/workflows/meta/introspection_workflow.py +235 -0
  99. reaxkit/workflows/meta/make_video_workflow.py +61 -0
  100. reaxkit/workflows/meta/plotter_workflow.py +601 -0
  101. reaxkit/workflows/per_file/__init__.py +0 -0
  102. reaxkit/workflows/per_file/control_workflow.py +110 -0
  103. reaxkit/workflows/per_file/eregime_workflow.py +267 -0
  104. reaxkit/workflows/per_file/ffield_workflow.py +390 -0
  105. reaxkit/workflows/per_file/fort13_workflow.py +86 -0
  106. reaxkit/workflows/per_file/fort57_workflow.py +137 -0
  107. reaxkit/workflows/per_file/fort73_workflow.py +151 -0
  108. reaxkit/workflows/per_file/fort74_workflow.py +88 -0
  109. reaxkit/workflows/per_file/fort76_workflow.py +188 -0
  110. reaxkit/workflows/per_file/fort78_workflow.py +135 -0
  111. reaxkit/workflows/per_file/fort79_workflow.py +314 -0
  112. reaxkit/workflows/per_file/fort7_workflow.py +592 -0
  113. reaxkit/workflows/per_file/fort83_workflow.py +60 -0
  114. reaxkit/workflows/per_file/fort99_workflow.py +223 -0
  115. reaxkit/workflows/per_file/geo_workflow.py +554 -0
  116. reaxkit/workflows/per_file/molfra_workflow.py +577 -0
  117. reaxkit/workflows/per_file/params_workflow.py +135 -0
  118. reaxkit/workflows/per_file/summary_workflow.py +161 -0
  119. reaxkit/workflows/per_file/trainset_workflow.py +356 -0
  120. reaxkit/workflows/per_file/tregime_workflow.py +79 -0
  121. reaxkit/workflows/per_file/vels_workflow.py +309 -0
  122. reaxkit/workflows/per_file/vregime_workflow.py +75 -0
  123. reaxkit/workflows/per_file/xmolout_workflow.py +678 -0
  124. reaxkit-1.0.0.dist-info/METADATA +128 -0
  125. reaxkit-1.0.0.dist-info/RECORD +130 -0
  126. reaxkit-1.0.0.dist-info/WHEEL +5 -0
  127. reaxkit-1.0.0.dist-info/entry_points.txt +2 -0
  128. reaxkit-1.0.0.dist-info/licenses/AUTHORS.md +20 -0
  129. reaxkit-1.0.0.dist-info/licenses/LICENSE +21 -0
  130. 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)