valyte 0.1.9__py3-none-any.whl → 0.1.11__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.
- valyte/band.py +135 -177
- valyte/band_plot.py +25 -66
- valyte/cli.py +66 -81
- valyte/dos_plot.py +137 -306
- valyte/ipr.py +186 -0
- valyte/kpoints.py +26 -54
- valyte/potcar.py +29 -54
- valyte/supercell.py +5 -22
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/METADATA +60 -1
- valyte-0.1.11.dist-info/RECORD +19 -0
- valyte-0.1.9.dist-info/RECORD +0 -18
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/WHEEL +0 -0
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/entry_points.txt +0 -0
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/top_level.txt +0 -0
valyte/cli.py
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Valyte CLI Tool
|
|
4
|
-
===============
|
|
5
|
-
|
|
6
|
-
A post-processing tool for VASP outputs, designed to create publication-quality
|
|
7
|
-
plots with a modern aesthetic. Supports DOS and band structure plotting.
|
|
8
|
-
|
|
9
|
-
Features:
|
|
10
|
-
- DOS plotting with gradient fills
|
|
11
|
-
- Band structure plotting
|
|
12
|
-
- Smart legend positioning
|
|
13
|
-
- Custom font support
|
|
14
|
-
"""
|
|
2
|
+
"""Valyte CLI entry point."""
|
|
15
3
|
|
|
16
4
|
import os
|
|
17
5
|
import sys
|
|
@@ -28,59 +16,51 @@ from valyte.band_plot import plot_band_structure
|
|
|
28
16
|
from valyte.dos_plot import load_dos, plot_dos
|
|
29
17
|
from valyte.kpoints import generate_kpoints_interactive
|
|
30
18
|
from valyte.potcar import generate_potcar
|
|
19
|
+
from valyte.ipr import run_ipr_interactive
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _normalize_element(symbol: str) -> str:
|
|
23
|
+
if not symbol:
|
|
24
|
+
return symbol
|
|
25
|
+
return symbol[0].upper() + symbol[1:].lower()
|
|
26
|
+
|
|
31
27
|
|
|
32
28
|
def parse_element_selection(inputs):
|
|
33
|
-
"""
|
|
34
|
-
Parses user input for elements and orbitals.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
inputs (list): List of strings, e.g., ["Ag", "Bi(s)", "O(p)"]
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
tuple: (elements_to_load, plotting_config)
|
|
41
|
-
elements_to_load (list): Elements to extract from VASP data.
|
|
42
|
-
plotting_config (list): List of (Element, Orbital) tuples.
|
|
43
|
-
"""
|
|
29
|
+
"""Parse element/orbital selections like "Fe", "Fe(d)", "O(p)"."""
|
|
44
30
|
if not inputs:
|
|
45
31
|
return None, None
|
|
46
32
|
|
|
47
|
-
elements_to_load =
|
|
33
|
+
elements_to_load = []
|
|
34
|
+
elements_seen = set()
|
|
48
35
|
plotting_config = []
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
|
|
37
|
+
pattern = re.compile(r"^([A-Za-z]+)(?:\(([spdf])\))?$", re.IGNORECASE)
|
|
38
|
+
|
|
53
39
|
for item in inputs:
|
|
54
|
-
match = pattern.match(item)
|
|
55
|
-
if match:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
plotting_config.append((el, orb))
|
|
62
|
-
else:
|
|
63
|
-
plotting_config.append((el, 'total'))
|
|
64
|
-
else:
|
|
65
|
-
print(f"⚠️ Warning: Could not parse '{item}'. Ignoring.")
|
|
66
|
-
|
|
40
|
+
match = pattern.match(item.strip())
|
|
41
|
+
if not match:
|
|
42
|
+
print(f"Warning: could not parse '{item}'. Ignoring.")
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
el = _normalize_element(match.group(1))
|
|
46
|
+
orb = match.group(2).lower() if match.group(2) else None
|
|
67
47
|
|
|
68
|
-
|
|
48
|
+
if el not in elements_seen:
|
|
49
|
+
elements_to_load.append(el)
|
|
50
|
+
elements_seen.add(el)
|
|
51
|
+
|
|
52
|
+
plotting_config.append((el, orb or "total"))
|
|
53
|
+
|
|
54
|
+
return elements_to_load, plotting_config
|
|
69
55
|
|
|
70
56
|
|
|
71
|
-
# ===============================================================
|
|
72
|
-
# Main CLI
|
|
73
|
-
# ===============================================================
|
|
74
57
|
def main():
|
|
75
|
-
"""
|
|
76
|
-
Main entry point for the CLI.
|
|
77
|
-
"""
|
|
78
58
|
parser = argparse.ArgumentParser(description="Valyte: VASP Post-Processing Tool")
|
|
79
59
|
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
80
60
|
|
|
81
|
-
#
|
|
61
|
+
# DOS
|
|
82
62
|
dos_parser = subparsers.add_parser("dos", help="Plot Density of States (DOS)")
|
|
83
|
-
dos_parser.add_argument("filepath", nargs="?", help="Path to vasprun.xml or directory containing it
|
|
63
|
+
dos_parser.add_argument("filepath", nargs="?", help="Path to vasprun.xml or directory containing it")
|
|
84
64
|
dos_parser.add_argument("--vasprun", help="Explicit path to vasprun.xml (alternative to positional argument)")
|
|
85
65
|
dos_parser.add_argument("-e", "--elements", nargs="+", help="Elements/Orbitals to plot (e.g., 'Fe O' or 'Fe(d) O(p)')")
|
|
86
66
|
dos_parser.add_argument("-o", "--output", default="valyte_dos.png", help="Output filename")
|
|
@@ -92,7 +72,7 @@ def main():
|
|
|
92
72
|
dos_parser.add_argument("--legend-cutoff", type=float, default=0.10, help="Threshold for legend visibility (0.0-1.0)")
|
|
93
73
|
dos_parser.add_argument("--font", default="Arial", help="Font family")
|
|
94
74
|
|
|
95
|
-
#
|
|
75
|
+
# Supercell
|
|
96
76
|
supercell_parser = subparsers.add_parser("supercell", help="Create a supercell")
|
|
97
77
|
supercell_parser.add_argument("nx", type=int, help="Supercell size x")
|
|
98
78
|
supercell_parser.add_argument("ny", type=int, help="Supercell size y")
|
|
@@ -100,50 +80,51 @@ def main():
|
|
|
100
80
|
supercell_parser.add_argument("-i", "--input", default="POSCAR", help="Input POSCAR file")
|
|
101
81
|
supercell_parser.add_argument("-o", "--output", default="POSCAR_supercell", help="Output filename")
|
|
102
82
|
|
|
103
|
-
#
|
|
83
|
+
# Band
|
|
104
84
|
band_parser = subparsers.add_parser("band", help="Band structure utilities")
|
|
105
85
|
band_subparsers = band_parser.add_subparsers(dest="band_command", help="Band commands")
|
|
106
86
|
|
|
107
|
-
# Band
|
|
108
|
-
# Note: argparse doesn't easily support default subcommands, so we handle this in logic
|
|
87
|
+
# Band plotting (default)
|
|
109
88
|
band_parser.add_argument("--vasprun", default=".", help="Path to vasprun.xml or directory")
|
|
110
89
|
band_parser.add_argument("--kpoints", help="Path to KPOINTS file (for labels)")
|
|
111
90
|
band_parser.add_argument("-o", "--output", default="valyte_band.png", help="Output filename")
|
|
112
91
|
band_parser.add_argument("--ylim", nargs=2, type=float, help="Energy range (min max)")
|
|
113
92
|
band_parser.add_argument("--font", default="Arial", help="Font family")
|
|
114
93
|
|
|
115
|
-
# Band KPOINTS
|
|
94
|
+
# Band KPOINTS generation
|
|
116
95
|
kpt_gen_parser = band_subparsers.add_parser("kpt-gen", help="Generate KPOINTS for band structure")
|
|
117
96
|
kpt_gen_parser.add_argument("-i", "--input", default="POSCAR", help="Input POSCAR file")
|
|
118
97
|
kpt_gen_parser.add_argument("-n", "--npoints", type=int, default=40, help="Points per segment")
|
|
119
98
|
kpt_gen_parser.add_argument("-o", "--output", default="KPOINTS", help="Output filename")
|
|
120
99
|
kpt_gen_parser.add_argument("--symprec", type=float, default=0.01, help="Symmetry precision (default: 0.01)")
|
|
121
|
-
|
|
122
100
|
kpt_gen_parser.add_argument("--mode", default="bradcrack", help="Standardization mode (default: bradcrack)")
|
|
123
101
|
|
|
124
|
-
#
|
|
102
|
+
# KPOINTS (interactive)
|
|
125
103
|
subparsers.add_parser("kpt", help="Interactive K-Point Generation (SCF)")
|
|
126
104
|
|
|
127
|
-
#
|
|
105
|
+
# POTCAR
|
|
128
106
|
potcar_parser = subparsers.add_parser("potcar", help="Generate POTCAR")
|
|
129
107
|
potcar_parser.add_argument("-i", "--input", default="POSCAR", help="Input POSCAR file")
|
|
130
108
|
potcar_parser.add_argument("-o", "--output", default="POTCAR", help="Output filename")
|
|
131
109
|
potcar_parser.add_argument("--functional", default="PBE", help="Functional (default: PBE)")
|
|
132
110
|
|
|
111
|
+
# IPR
|
|
112
|
+
subparsers.add_parser("ipr", help="Compute IPR from PROCAR")
|
|
113
|
+
|
|
133
114
|
args = parser.parse_args()
|
|
134
115
|
|
|
135
116
|
if args.command == "dos":
|
|
136
|
-
# Resolve filepath: positional > flag > current dir
|
|
137
117
|
target_path = args.filepath if args.filepath else args.vasprun
|
|
138
118
|
if not target_path:
|
|
139
119
|
target_path = "."
|
|
140
|
-
|
|
120
|
+
|
|
141
121
|
elements, plotting_config = parse_element_selection(args.elements)
|
|
142
|
-
|
|
122
|
+
|
|
143
123
|
try:
|
|
144
124
|
dos_data, pdos_data = load_dos(target_path, elements)
|
|
145
125
|
plot_dos(
|
|
146
|
-
dos_data,
|
|
126
|
+
dos_data,
|
|
127
|
+
pdos_data,
|
|
147
128
|
out=args.output,
|
|
148
129
|
xlim=tuple(args.xlim),
|
|
149
130
|
ylim=tuple(args.ylim) if args.ylim else None,
|
|
@@ -152,11 +133,10 @@ def main():
|
|
|
152
133
|
show_total=not args.pdos,
|
|
153
134
|
plotting_config=plotting_config,
|
|
154
135
|
legend_cutoff=args.legend_cutoff,
|
|
155
|
-
scale_factor=args.scale
|
|
136
|
+
scale_factor=args.scale,
|
|
156
137
|
)
|
|
157
|
-
# print(f"✅ DOS plot saved to {args.output}") # Silent mode
|
|
158
138
|
except Exception as e:
|
|
159
|
-
print(f"
|
|
139
|
+
print(f"Error: {e}")
|
|
160
140
|
sys.exit(1)
|
|
161
141
|
|
|
162
142
|
elif args.command == "supercell":
|
|
@@ -166,17 +146,17 @@ def main():
|
|
|
166
146
|
nx=args.nx,
|
|
167
147
|
ny=args.ny,
|
|
168
148
|
nz=args.nz,
|
|
169
|
-
output=args.output
|
|
149
|
+
output=args.output,
|
|
170
150
|
)
|
|
171
151
|
except Exception as e:
|
|
172
|
-
print(f"
|
|
152
|
+
print(f"Error: {e}")
|
|
173
153
|
sys.exit(1)
|
|
174
|
-
|
|
154
|
+
|
|
175
155
|
elif args.command == "kpt":
|
|
176
156
|
try:
|
|
177
157
|
generate_kpoints_interactive()
|
|
178
158
|
except Exception as e:
|
|
179
|
-
print(f"
|
|
159
|
+
print(f"Error: {e}")
|
|
180
160
|
sys.exit(1)
|
|
181
161
|
|
|
182
162
|
elif args.command == "potcar":
|
|
@@ -184,10 +164,17 @@ def main():
|
|
|
184
164
|
generate_potcar(
|
|
185
165
|
poscar_path=args.input,
|
|
186
166
|
functional=args.functional,
|
|
187
|
-
output=args.output
|
|
167
|
+
output=args.output,
|
|
188
168
|
)
|
|
189
169
|
except Exception as e:
|
|
190
|
-
print(f"
|
|
170
|
+
print(f"Error: {e}")
|
|
171
|
+
sys.exit(1)
|
|
172
|
+
|
|
173
|
+
elif args.command == "ipr":
|
|
174
|
+
try:
|
|
175
|
+
run_ipr_interactive()
|
|
176
|
+
except Exception as e:
|
|
177
|
+
print(f"Error: {e}")
|
|
191
178
|
sys.exit(1)
|
|
192
179
|
|
|
193
180
|
elif args.command == "band":
|
|
@@ -198,23 +185,19 @@ def main():
|
|
|
198
185
|
npoints=args.npoints,
|
|
199
186
|
output=args.output,
|
|
200
187
|
symprec=args.symprec,
|
|
201
|
-
mode=args.mode
|
|
188
|
+
mode=args.mode,
|
|
202
189
|
)
|
|
203
190
|
except Exception as e:
|
|
204
|
-
print(f"
|
|
191
|
+
print(f"Error: {e}")
|
|
205
192
|
sys.exit(1)
|
|
206
193
|
elif args.band_command == "plot" or args.band_command is None:
|
|
207
|
-
# Default behavior for 'valyte band' is plotting
|
|
208
194
|
try:
|
|
209
|
-
|
|
210
|
-
target_path = args.vasprun or args.filepath or "."
|
|
195
|
+
target_path = args.vasprun or "."
|
|
211
196
|
if os.path.isdir(target_path):
|
|
212
197
|
target_path = os.path.join(target_path, "vasprun.xml")
|
|
213
|
-
|
|
214
|
-
# Determine KPOINTS path
|
|
198
|
+
|
|
215
199
|
kpoints_path = args.kpoints
|
|
216
200
|
if not kpoints_path:
|
|
217
|
-
# Try to find KPOINTS in the same directory as vasprun.xml
|
|
218
201
|
base_dir = os.path.dirname(target_path)
|
|
219
202
|
potential_kpoints = os.path.join(base_dir, "KPOINTS")
|
|
220
203
|
if os.path.exists(potential_kpoints):
|
|
@@ -225,10 +208,11 @@ def main():
|
|
|
225
208
|
kpoints_path=kpoints_path,
|
|
226
209
|
output=args.output,
|
|
227
210
|
ylim=tuple(args.ylim) if args.ylim else None,
|
|
228
|
-
font=args.font
|
|
211
|
+
font=args.font,
|
|
229
212
|
)
|
|
230
213
|
except Exception:
|
|
231
214
|
import traceback
|
|
215
|
+
|
|
232
216
|
traceback.print_exc()
|
|
233
217
|
sys.exit(1)
|
|
234
218
|
else:
|
|
@@ -236,5 +220,6 @@ def main():
|
|
|
236
220
|
else:
|
|
237
221
|
parser.print_help()
|
|
238
222
|
|
|
223
|
+
|
|
239
224
|
if __name__ == "__main__":
|
|
240
225
|
main()
|