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,343 @@
|
|
|
1
|
+
"""
|
|
2
|
+
xmolout–fort.7 combined workflow for ReaxKit.
|
|
3
|
+
|
|
4
|
+
This workflow provides visualization and analysis tasks that require both
|
|
5
|
+
atomic coordinates from `xmolout` and per-atom properties from `fort.7`
|
|
6
|
+
(e.g. partial charges, bond-order–derived quantities).
|
|
7
|
+
|
|
8
|
+
It supports:
|
|
9
|
+
- 3D scatter visualization of arbitrary fort.7 scalar properties mapped onto
|
|
10
|
+
atomic positions across selected frames.
|
|
11
|
+
- 2D projected heatmaps (xy/xz/yz) of atomic properties or atom counts,
|
|
12
|
+
with flexible spatial binning and aggregation.
|
|
13
|
+
|
|
14
|
+
The workflow is designed for spatially resolved analysis of ReaxFF outputs,
|
|
15
|
+
enabling intuitive inspection of per-atom quantities in real space and
|
|
16
|
+
across time.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
import argparse
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Optional, Sequence, Tuple, Union
|
|
24
|
+
|
|
25
|
+
import numpy as np
|
|
26
|
+
|
|
27
|
+
# Handlers / analyzers
|
|
28
|
+
from reaxkit.io.handlers.xmolout_handler import XmoloutHandler
|
|
29
|
+
from reaxkit.io.handlers.fort7_handler import Fort7Handler
|
|
30
|
+
from reaxkit.analysis.per_file import fort7_analyzer as f7
|
|
31
|
+
|
|
32
|
+
# Utils (NEW: replace local parsers with these)
|
|
33
|
+
from reaxkit.utils.frame_utils import parse_frames, parse_atoms, resolve_indices
|
|
34
|
+
|
|
35
|
+
# Aliases (NEW: accept canonical or alias names like 'charge', 'q', etc.)
|
|
36
|
+
from reaxkit.utils.alias import resolve_alias_from_columns
|
|
37
|
+
|
|
38
|
+
# Plotting
|
|
39
|
+
from reaxkit.utils.media.plotter import scatter3d_points, heatmap2d_from_3d
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# ------------------------- internals -------------------------
|
|
43
|
+
|
|
44
|
+
def _indices_from_spec(xh: XmoloutHandler, frames_spec: Optional[Union[slice, Sequence[int]]]) -> list[int]:
|
|
45
|
+
"""Turn a frames spec (slice or list) into concrete frame indices for xh."""
|
|
46
|
+
return resolve_indices(xh, frames=frames_spec, iterations=None, step=None)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _select_atoms(n_atoms: int, atoms: Optional[Sequence[int]]) -> np.ndarray:
|
|
50
|
+
"""Return a boolean mask over 0..n_atoms-1 for the selected atom indices."""
|
|
51
|
+
if not atoms:
|
|
52
|
+
return np.ones(n_atoms, dtype=bool)
|
|
53
|
+
mask = np.zeros(n_atoms, dtype=bool)
|
|
54
|
+
for a in atoms:
|
|
55
|
+
if 0 <= int(a) < n_atoms:
|
|
56
|
+
mask[int(a)] = True
|
|
57
|
+
return mask
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# ========================= 3D SCATTER (per-frame) =========================
|
|
61
|
+
|
|
62
|
+
def _plot_fort7_property_3d(
|
|
63
|
+
*,
|
|
64
|
+
xmolout_handler: XmoloutHandler,
|
|
65
|
+
fort7_handler: Fort7Handler,
|
|
66
|
+
property_name: str,
|
|
67
|
+
frames_spec: Optional[Union[slice, Sequence[int]]] = None,
|
|
68
|
+
atoms_list: Optional[Sequence[int]] = None,
|
|
69
|
+
save_dir: Optional[Union[str, Path]] = None,
|
|
70
|
+
vmin: Optional[float] = None,
|
|
71
|
+
vmax: Optional[float] = None,
|
|
72
|
+
size: float = 8.0,
|
|
73
|
+
alpha: float = 0.9,
|
|
74
|
+
cmap: str = "coolwarm",
|
|
75
|
+
elev: float = 22.0,
|
|
76
|
+
azim: float = 38.0,
|
|
77
|
+
) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Plot any scalar property (e.g., partial_charge/charge/q) from fort.7 in 3D across frames.
|
|
80
|
+
"""
|
|
81
|
+
# Pull all per-atom data we need from fort7 (tidy: frame_idx, iter, atom_idx, <props...>)
|
|
82
|
+
df_all = f7.get_features_atom(fort7_handler, columns=".*", frames=frames_spec, regex=True)
|
|
83
|
+
|
|
84
|
+
# Resolve the requested property via alias map against the columns we actually have
|
|
85
|
+
col = resolve_alias_from_columns(df_all.columns, property_name)
|
|
86
|
+
if col is None:
|
|
87
|
+
raise ValueError(
|
|
88
|
+
f"Column '{property_name}' not found (with alias resolution). "
|
|
89
|
+
f"Available columns include: {list(df_all.columns)[:12]} ..."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Auto color limits if not provided
|
|
93
|
+
if vmin is None:
|
|
94
|
+
vmin = float(np.nanmin(df_all[col].to_numpy(dtype=float)))
|
|
95
|
+
if vmax is None:
|
|
96
|
+
vmax = float(np.nanmax(df_all[col].to_numpy(dtype=float)))
|
|
97
|
+
|
|
98
|
+
# Prep output
|
|
99
|
+
save_dir = Path(save_dir) if save_dir else None
|
|
100
|
+
if save_dir:
|
|
101
|
+
save_dir.mkdir(parents=True, exist_ok=True)
|
|
102
|
+
|
|
103
|
+
# Concrete frame indices to iterate
|
|
104
|
+
idx_list = _indices_from_spec(xmolout_handler, frames_spec)
|
|
105
|
+
|
|
106
|
+
for fi in idx_list:
|
|
107
|
+
# xmolout: geometry + types
|
|
108
|
+
fr = xmolout_handler.frame(int(fi))
|
|
109
|
+
coords = fr["coords"] # (N,3)
|
|
110
|
+
n_atoms = coords.shape[0]
|
|
111
|
+
keep_atoms = _select_atoms(n_atoms, atoms_list)
|
|
112
|
+
|
|
113
|
+
# fort7 values aligned by atom_idx
|
|
114
|
+
sub = df_all[df_all["frame_idx"] == fi][["atom_idx", col]].copy()
|
|
115
|
+
vals = np.full(n_atoms, np.nan, dtype=float)
|
|
116
|
+
if not sub.empty:
|
|
117
|
+
idx = sub["atom_idx"].to_numpy(int, copy=False) # 0-based
|
|
118
|
+
good = (idx >= 0) & (idx < n_atoms)
|
|
119
|
+
vals[idx[good]] = sub[col].to_numpy(float, copy=False)[good]
|
|
120
|
+
|
|
121
|
+
# filter & drop NaNs
|
|
122
|
+
use = keep_atoms & np.isfinite(vals)
|
|
123
|
+
if not np.any(use):
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
title = f"{col}_3D_frame_{fi}"
|
|
127
|
+
scatter3d_points(
|
|
128
|
+
coords[use],
|
|
129
|
+
vals[use],
|
|
130
|
+
title=title,
|
|
131
|
+
s=size,
|
|
132
|
+
alpha=alpha,
|
|
133
|
+
cmap=cmap,
|
|
134
|
+
vmin=vmin,
|
|
135
|
+
vmax=vmax,
|
|
136
|
+
elev=elev,
|
|
137
|
+
azim=azim,
|
|
138
|
+
save=(save_dir / f"{title}.png" if save_dir else None),
|
|
139
|
+
show_message = False
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _plot_property_task(args: argparse.Namespace) -> int:
|
|
144
|
+
xh = XmoloutHandler(args.xmolout)
|
|
145
|
+
fh = Fort7Handler(args.fort7)
|
|
146
|
+
|
|
147
|
+
frames_spec = parse_frames(args.frames) # NEW
|
|
148
|
+
atoms_list = parse_atoms(args.atoms) # NEW
|
|
149
|
+
|
|
150
|
+
_plot_fort7_property_3d(
|
|
151
|
+
xmolout_handler=xh,
|
|
152
|
+
fort7_handler=fh,
|
|
153
|
+
property_name=args.property,
|
|
154
|
+
frames_spec=frames_spec,
|
|
155
|
+
atoms_list=atoms_list,
|
|
156
|
+
save_dir=args.save,
|
|
157
|
+
vmin=args.vmin,
|
|
158
|
+
vmax=args.vmax,
|
|
159
|
+
size=args.size,
|
|
160
|
+
alpha=args.alpha,
|
|
161
|
+
cmap=args.cmap,
|
|
162
|
+
elev=args.elev,
|
|
163
|
+
azim=args.azim,
|
|
164
|
+
)
|
|
165
|
+
if args.save:
|
|
166
|
+
print(f"[Done] All plots saved in {args.save}")
|
|
167
|
+
|
|
168
|
+
return 0
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# ==================== 2D HEATMAP (projection + aggregation) ====================
|
|
172
|
+
|
|
173
|
+
def _parse_bins(bins: str) -> Union[int, Tuple[int, int]]:
|
|
174
|
+
if "," in bins:
|
|
175
|
+
nx, ny = [int(x) for x in bins.split(",")]
|
|
176
|
+
return (nx, ny)
|
|
177
|
+
return int(bins)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _heatmap2d_task(args: argparse.Namespace) -> int:
|
|
181
|
+
"""
|
|
182
|
+
Project 3D coords to 2D (xy/xz/yz), bin into a grid, and aggregate values.
|
|
183
|
+
If --property is provided, aggregate that fort7 scalar; else aggregate point count.
|
|
184
|
+
One PNG per frame is saved if --save is provided; otherwise plots are shown.
|
|
185
|
+
"""
|
|
186
|
+
xh = XmoloutHandler(args.xmolout)
|
|
187
|
+
frames_spec = parse_frames(args.frames) # NEW
|
|
188
|
+
idx_list = _indices_from_spec(xh, frames_spec)
|
|
189
|
+
|
|
190
|
+
# Optional scalar from fort7
|
|
191
|
+
use_scalar = args.property is not None
|
|
192
|
+
if use_scalar:
|
|
193
|
+
fh = Fort7Handler(args.fort7)
|
|
194
|
+
df = f7.get_features_atom(fh, columns=".*", frames=frames_spec, regex=True)
|
|
195
|
+
col = resolve_alias_from_columns(df.columns, args.property)
|
|
196
|
+
if col is None:
|
|
197
|
+
raise ValueError(
|
|
198
|
+
f"Column '{args.property}' not found (with alias resolution). "
|
|
199
|
+
f"Available columns include: {list(df.columns)[:12]} ..."
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
bins: Union[int, Tuple[int, int]] = _parse_bins(args.bins)
|
|
203
|
+
|
|
204
|
+
# Output
|
|
205
|
+
save_dir = Path(args.save) if args.save else None
|
|
206
|
+
if save_dir:
|
|
207
|
+
save_dir.mkdir(parents=True, exist_ok=True)
|
|
208
|
+
|
|
209
|
+
for fi in idx_list:
|
|
210
|
+
fr = xh.frame(int(fi))
|
|
211
|
+
coords = fr["coords"]
|
|
212
|
+
|
|
213
|
+
if use_scalar:
|
|
214
|
+
sub = df[df["frame_idx"] == fi][["atom_idx", col]]
|
|
215
|
+
values = np.full(coords.shape[0], np.nan, float)
|
|
216
|
+
if not sub.empty:
|
|
217
|
+
idx = sub["atom_idx"].to_numpy(int, copy=False)
|
|
218
|
+
ok = (idx >= 0) & (idx < coords.shape[0])
|
|
219
|
+
values[idx[ok]] = sub[col].to_numpy(float, copy=False)[ok]
|
|
220
|
+
m = np.isfinite(values)
|
|
221
|
+
c_plot, v_plot = coords[m], values[m]
|
|
222
|
+
agg = args.agg
|
|
223
|
+
label = col
|
|
224
|
+
else:
|
|
225
|
+
c_plot = coords
|
|
226
|
+
v_plot = np.ones(coords.shape[0], float)
|
|
227
|
+
agg = "count"
|
|
228
|
+
label = "count"
|
|
229
|
+
|
|
230
|
+
title = f"{label}_{args.plane}_frame_{fi}"
|
|
231
|
+
out_path = (save_dir / f"{title}.png") if save_dir else None
|
|
232
|
+
|
|
233
|
+
heatmap2d_from_3d(
|
|
234
|
+
c_plot,
|
|
235
|
+
v_plot,
|
|
236
|
+
plane=args.plane,
|
|
237
|
+
bins=bins,
|
|
238
|
+
agg=agg,
|
|
239
|
+
vmin=args.vmin,
|
|
240
|
+
vmax=args.vmax,
|
|
241
|
+
cmap=args.cmap,
|
|
242
|
+
title=title,
|
|
243
|
+
save=out_path,
|
|
244
|
+
show_message = False,
|
|
245
|
+
)
|
|
246
|
+
if args.save:
|
|
247
|
+
print(f"[Done] All plots saved in {args.save}")
|
|
248
|
+
|
|
249
|
+
return 0
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# ==================== CLI registration ====================
|
|
253
|
+
def _add_common_xmolout_io_args(
|
|
254
|
+
p: argparse.ArgumentParser,
|
|
255
|
+
*,
|
|
256
|
+
include_plot: bool = False,
|
|
257
|
+
) -> None:
|
|
258
|
+
p.add_argument("--xmolout", default="xmolout", help="Path to xmolout file.")
|
|
259
|
+
p.add_argument("--fort7", default="fort.7", help="Path to fort.7 file.")
|
|
260
|
+
if include_plot:
|
|
261
|
+
p.add_argument("--plot", action="store_true", help="Show plot interactively.")
|
|
262
|
+
|
|
263
|
+
p.add_argument("--export", default=None, help="Path to export CSV data.")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def register_tasks(subparsers: argparse._SubParsersAction) -> None:
|
|
267
|
+
"""
|
|
268
|
+
Register coordination-related CLI subcommands.
|
|
269
|
+
|
|
270
|
+
This function defines the task-level interface for the
|
|
271
|
+
`reaxkit file` workflow and attaches its tasks (i.e., subcommands).
|
|
272
|
+
|
|
273
|
+
Each task may share common input arguments and defines task-specific options as needed.
|
|
274
|
+
"""
|
|
275
|
+
# 3D scatter
|
|
276
|
+
p = subparsers.add_parser(
|
|
277
|
+
"plot3d",
|
|
278
|
+
help="3D scatter plot of any fort7 property (aliases allowed: charge/q → partial_charge).",
|
|
279
|
+
description=(
|
|
280
|
+
"Examples:\n"
|
|
281
|
+
" reaxkit xmolfort7 plot3d --property charge --frames 0:20:10 \n"
|
|
282
|
+
),
|
|
283
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
284
|
+
)
|
|
285
|
+
_add_common_xmolout_io_args(p, include_plot=True)
|
|
286
|
+
p.add_argument("--property", required=True,
|
|
287
|
+
help="Column name or alias (e.g., partial_charge, charge, q).")
|
|
288
|
+
p.add_argument("--frames", default=None,
|
|
289
|
+
help='Frames: "0,10,20" or "0:100:5".')
|
|
290
|
+
p.add_argument("--atoms", default=None,
|
|
291
|
+
help='Atom indices: "0,1,2" (0-based).')
|
|
292
|
+
p.add_argument("--vmin", type=float, default=None,
|
|
293
|
+
help="Color scale min (auto if not set).")
|
|
294
|
+
p.add_argument("--vmax", type=float, default=None,
|
|
295
|
+
help="Color scale max (auto if not set).")
|
|
296
|
+
p.add_argument("--size", type=float, default=8.0, help="Marker size.")
|
|
297
|
+
p.add_argument("--alpha", type=float, default=0.9, help="Marker transparency.")
|
|
298
|
+
p.add_argument("--cmap", default="coolwarm", help="Matplotlib colormap.")
|
|
299
|
+
p.add_argument("--elev", type=float, default=22.0, help="3D view elevation.")
|
|
300
|
+
p.add_argument("--azim", type=float, default=38.0, help="3D view azimuth.")
|
|
301
|
+
p.add_argument("--save", default="reaxkit_outputs/xmol_fort7/3D_scatter/", help="Path to save plot image.")
|
|
302
|
+
p.set_defaults(_run=_plot_property_task)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
# 2D heatmap
|
|
309
|
+
q = subparsers.add_parser(
|
|
310
|
+
"heatmap2d",
|
|
311
|
+
help="Project 3D atoms to 2D grid (xy/xz/yz) and aggregate values per cell.",
|
|
312
|
+
description=(
|
|
313
|
+
"Examples:\n"
|
|
314
|
+
" reaxkit xmolfort7 heatmap2d --property partial_charge --plane xz "
|
|
315
|
+
"--bins 10 --agg mean --frames 0:300:100\n"
|
|
316
|
+
),
|
|
317
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
318
|
+
)
|
|
319
|
+
_add_common_xmolout_io_args(q, include_plot=True)
|
|
320
|
+
q.add_argument("--frames", default=None,
|
|
321
|
+
help='Frames: "0,10,20" or "0:100:5".')
|
|
322
|
+
|
|
323
|
+
# Projection/grid
|
|
324
|
+
q.add_argument("--plane", default="xy", choices=["xy", "xz", "yz"],
|
|
325
|
+
help="Projection plane.")
|
|
326
|
+
q.add_argument("--bins", default="40",
|
|
327
|
+
help='Grid bins: "N" or "Nx,Ny" (e.g., "10,25").')
|
|
328
|
+
q.add_argument("--agg", default="mean",
|
|
329
|
+
help="Aggregation: mean|max|min|sum|count.")
|
|
330
|
+
|
|
331
|
+
# Optional scalar from fort7
|
|
332
|
+
q.add_argument("--property", default=None,
|
|
333
|
+
help="fort7 column or alias to aggregate (e.g., partial_charge|charge|q).")
|
|
334
|
+
|
|
335
|
+
# Viz
|
|
336
|
+
q.add_argument("--vmin", type=float, default=None,
|
|
337
|
+
help="Color scale min (auto if not set).")
|
|
338
|
+
q.add_argument("--vmax", type=float, default=None,
|
|
339
|
+
help="Color scale max (auto if not set).")
|
|
340
|
+
q.add_argument("--cmap", default="viridis", help="Matplotlib colormap.")
|
|
341
|
+
q.add_argument("--save", default="reaxkit_outputs/xmol_fort7/2D_heatmap/", help="Path to save plot image.")
|
|
342
|
+
q.set_defaults(_run=_heatmap2d_task)
|
|
343
|
+
|
|
File without changes
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Interactive help and discovery workflow for ReaxKit.
|
|
3
|
+
|
|
4
|
+
This workflow provides a search-based help system that maps conceptual,
|
|
5
|
+
human-language queries (e.g. "electric field", "restraint", "bond order")
|
|
6
|
+
to relevant ReaxFF input and output files.
|
|
7
|
+
|
|
8
|
+
It operates as a kind-level command (`reaxkit help`) rather than a task-based
|
|
9
|
+
workflow, and therefore does not define subcommands. Instead, it queries
|
|
10
|
+
curated help indices and ranks matches based on relevance.
|
|
11
|
+
|
|
12
|
+
Optional flags allow users to inspect why a file matched, view example
|
|
13
|
+
ReaxKit commands, and explore core, optional, and derived variables
|
|
14
|
+
associated with each file.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
from reaxkit.help.help_index_loader import search_help_indices, _format_hits
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def build_parser(p: argparse.ArgumentParser) -> None:
|
|
24
|
+
"""
|
|
25
|
+
Define CLI arguments for the kind-level command: `reaxkit help`.
|
|
26
|
+
|
|
27
|
+
This is used by documentation generation to render a stable list of flags
|
|
28
|
+
and defaults, and can also be reused by the CLI entry-point when building
|
|
29
|
+
the parser for `help`.
|
|
30
|
+
"""
|
|
31
|
+
p.add_argument(
|
|
32
|
+
"query",
|
|
33
|
+
nargs="?",
|
|
34
|
+
default=None,
|
|
35
|
+
help="Search query (use quotes for multi-word queries).",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
p.add_argument(
|
|
39
|
+
"--top",
|
|
40
|
+
type=int,
|
|
41
|
+
default=8,
|
|
42
|
+
help="Maximum number of matches to display.",
|
|
43
|
+
)
|
|
44
|
+
p.add_argument(
|
|
45
|
+
"--min-score",
|
|
46
|
+
type=float,
|
|
47
|
+
default=35.0,
|
|
48
|
+
help="Minimum score threshold; lower-scoring matches are hidden.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Output detail toggles
|
|
52
|
+
p.add_argument("--why", action="store_true", help="Show why each file matched the query.")
|
|
53
|
+
p.add_argument("--file_templates", action="store_true", help="Show one example ReaxKit command per match.")
|
|
54
|
+
p.add_argument("--tags", action="store_true", help="Show tags for each match.")
|
|
55
|
+
p.add_argument("--core-vars", dest="core_vars", action="store_true", help="Show core variables for each match.")
|
|
56
|
+
p.add_argument("--optional-vars", dest="optional_vars", action="store_true", help="Show optional variables.")
|
|
57
|
+
p.add_argument("--derived-vars", dest="derived_vars", action="store_true", help="Show derived variables.")
|
|
58
|
+
p.add_argument("--notes", action="store_true", help="Show notes for each match.")
|
|
59
|
+
|
|
60
|
+
# Convenience flag
|
|
61
|
+
p.add_argument(
|
|
62
|
+
"--all-info",
|
|
63
|
+
dest="all_info",
|
|
64
|
+
action="store_true",
|
|
65
|
+
help="Show why/file_templates/tags/core/optional/derived/notes all at once.",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def run_main(args: argparse.Namespace) -> None:
|
|
70
|
+
"""
|
|
71
|
+
Run the `reaxkit help` command.
|
|
72
|
+
|
|
73
|
+
Behavior:
|
|
74
|
+
-----------
|
|
75
|
+
- If no query is provided, prints a short usage message and exits.
|
|
76
|
+
- If a query is provided, searches curated help indices and prints ranked matches.
|
|
77
|
+
- Use `--top` and `--min-score` to control result count and filtering.
|
|
78
|
+
- Use detail flags (`--why`, `--file_templates`, `--tags`, `--core-vars`, `--optional-vars`,
|
|
79
|
+
`--derived-vars`, `--notes`) to expand what is shown per match.
|
|
80
|
+
- `--all-info` enables all detail flags together.
|
|
81
|
+
|
|
82
|
+
Examples
|
|
83
|
+
-----------
|
|
84
|
+
reaxkit help 'restraint'
|
|
85
|
+
reaxkit help 'electric field'
|
|
86
|
+
"""
|
|
87
|
+
# Allow: `reaxkit help` (no query)
|
|
88
|
+
if getattr(args, "query", None) is None:
|
|
89
|
+
print("ReaxKit help\n")
|
|
90
|
+
print('Usage:\n reaxkit help "restraint"\n reaxkit help bond\n reaxkit help "electric field"\n')
|
|
91
|
+
print("Tip: put multi-word queries in quotes.")
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
hits = search_help_indices(
|
|
95
|
+
args.query,
|
|
96
|
+
top_k=getattr(args, "top", 8),
|
|
97
|
+
min_score=getattr(args, "min_score", 35.0),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if not hits:
|
|
101
|
+
print(f"❌ No matches for: {args.query!r}")
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
all_info = getattr(args, "all_info", False)
|
|
105
|
+
|
|
106
|
+
show_why = all_info or getattr(args, "why", False)
|
|
107
|
+
show_examples = all_info or getattr(args, "file_templates", False)
|
|
108
|
+
show_tags = all_info or getattr(args, "tags", False)
|
|
109
|
+
show_core_vars = all_info or getattr(args, "core_vars", False)
|
|
110
|
+
show_optional_vars = all_info or getattr(args, "optional_vars", False)
|
|
111
|
+
show_derived_vars = all_info or getattr(args, "derived_vars", False)
|
|
112
|
+
show_notes = all_info or getattr(args, "notes", False)
|
|
113
|
+
|
|
114
|
+
print(
|
|
115
|
+
_format_hits(
|
|
116
|
+
hits,
|
|
117
|
+
show_why=show_why,
|
|
118
|
+
show_examples=show_examples,
|
|
119
|
+
show_tags=show_tags,
|
|
120
|
+
show_core_vars=show_core_vars,
|
|
121
|
+
show_optional_vars=show_optional_vars,
|
|
122
|
+
show_derived_vars=show_derived_vars,
|
|
123
|
+
show_notes=show_notes,
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def register_tasks(subparsers: argparse._SubParsersAction) -> None:
|
|
129
|
+
"""
|
|
130
|
+
Intentionally empty.
|
|
131
|
+
|
|
132
|
+
`help` is a kind-level command (invoked as `reaxkit help "<query>"`), so it does
|
|
133
|
+
not define subcommands via `register_tasks`. The CLI entry-point should call
|
|
134
|
+
`build_parser(...)` and route execution to `run_main(...)`.
|
|
135
|
+
"""
|
|
136
|
+
return
|