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