valyte 0.1.7__tar.gz

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.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ include valyte/Logo.png
valyte-0.1.7/PKG-INFO ADDED
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.2
2
+ Name: valyte
3
+ Version: 0.1.7
4
+ Summary: A comprehensive CLI tool for VASP pre-processing (Supercells, K-points) and post-processing (DOS, Band Structure plotting)
5
+ Home-page: https://github.com/nikyadav002/Valyte-Project
6
+ Author: Nikhil
7
+ Author-email: nikhil@example.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: numpy
14
+ Requires-Dist: matplotlib
15
+ Requires-Dist: pymatgen
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: classifier
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: requires-dist
23
+ Dynamic: requires-python
24
+ Dynamic: summary
25
+
26
+ <p align="center">
27
+ <img src="valyte/Logo.png" alt="Valyte Logo" width="100%"/>
28
+ </p>
29
+
30
+ # Valyte
31
+
32
+ **Valyte** is a comprehensive CLI tool for VASP workflows, providing both pre-processing and post-processing capabilities with a focus on clean, publication-quality outputs and modern aesthetics.
33
+
34
+ ## Features
35
+
36
+ ### Pre-processing
37
+ - **Supercell Creation**: Generate supercells from POSCAR files.
38
+ - **Interactive K-Point Generation**: Create KPOINTS files with automatic grid calculation based on K-spacing.
39
+ - **Band KPOINTS Generation**: Automatic high-symmetry path detection for band structure calculations.
40
+
41
+ ### Post-processing
42
+ - **DOS Plotting**:
43
+ - Smart Plotting: Automatically handles total DOS and Projected DOS (PDOS).
44
+ - Orbital-Resolved: Plots individual orbitals (s, p, d, f) by default.
45
+ - Adaptive Legend: Intelligently hides the legend if PDOS contributions are low.
46
+ - Gradient Fill: Aesthetically pleasing gradient fills for DOS peaks.
47
+ - **Band Structure Plotting**:
48
+ - VBM alignment to 0 eV.
49
+ - Color-coded bands (Purple for VB, Teal for CB).
50
+ - High-symmetry path labels from KPOINTS.
51
+ - **Publication Quality**: Clean aesthetics, custom fonts (Arial, Helvetica, Times New Roman), high DPI output.
52
+
53
+ ## Installation
54
+
55
+ Install Valyte directly from PyPI:
56
+
57
+ ```bash
58
+ pip install valyte
59
+ ```
60
+
61
+ Or install from source:
62
+
63
+ ```bash
64
+ git clone https://github.com/nikyadav002/Valyte-Project
65
+ cd Valyte-Project
66
+ pip install -e .
67
+ ```
68
+
69
+ ## Examples
70
+
71
+ <p align="center">
72
+ <img src="valyte/valyte_dos.png" alt="DOS Plot Example" width="47%"/>
73
+ <img src="valyte/valyte_band.png" alt="Band Structure Example" width="38%"/>
74
+ </p>
75
+
76
+ ## Updating Valyte
77
+
78
+ To update to the latest version:
79
+
80
+ ```bash
81
+ pip install --upgrade valyte
82
+ ```
83
+
84
+ ## Usage
85
+
86
+ The main command is `valyte`.
87
+
88
+ <details>
89
+ <summary><strong>Click to view detailed usage instructions</strong></summary>
90
+
91
+ <br>
92
+
93
+ ### 🧊 Create Supercell
94
+
95
+ Generate a supercell from a POSCAR file:
96
+
97
+ ```bash
98
+ valyte supercell nx ny nz [options]
99
+ ```
100
+
101
+ **Example:**
102
+ ```bash
103
+ # Create a 2×2×2 supercell
104
+ valyte supercell 2 2 2
105
+
106
+ # Specify input and output files
107
+ valyte supercell 3 3 1 -i POSCAR_primitive -o POSCAR_3x3x1
108
+ ```
109
+
110
+ **Options:**
111
+ - `-i`, `--input`: Input POSCAR file (default: `POSCAR`).
112
+ - `-o`, `--output`: Output filename (default: `POSCAR_supercell`).
113
+
114
+ ---
115
+
116
+ ### 📉 Band Structure
117
+
118
+ #### 1. Generate KPOINTS
119
+
120
+ Automatically generate a KPOINTS file with high-symmetry paths for band structure calculations.
121
+
122
+ ```bash
123
+ valyte band kpt-gen [options]
124
+ ```
125
+
126
+ **Options:**
127
+ - `-i`, `--input`: Input POSCAR file (default: `POSCAR`).
128
+ - `-n`, `--npoints`: Points per segment (default: `40`).
129
+ - `-o`, `--output`: Output filename (default: `KPOINTS`).
130
+
131
+ **Example:**
132
+ ```bash
133
+ valyte band kpt-gen -n 60 -i POSCAR_relaxed -o KPOINTS_band
134
+ ```
135
+
136
+ ### 🕸️ Generate K-Points (Interactive)
137
+
138
+ Generate a `KPOINTS` file for SCF calculations interactively.
139
+
140
+ ```bash
141
+ valyte kpt
142
+ ```
143
+
144
+ This command will prompt you for:
145
+ 1. **K-Mesh Scheme**: Monkhorst-Pack or Gamma.
146
+ 2. **K-Spacing**: Value in $2\pi/\AA$ (e.g., 0.04).
147
+
148
+ It automatically calculates the optimal grid based on your `POSCAR` structure.
149
+
150
+ #### 2. Plot Band Structure
151
+
152
+ Plot the electronic band structure from `vasprun.xml`.
153
+
154
+ ```bash
155
+ valyte band [options]
156
+ ```
157
+
158
+ **Options:**
159
+ - `--vasprun`: Path to `vasprun.xml` (default: current directory).
160
+ - `--kpoints`: Path to `KPOINTS` file for path labels (default: looks for `KPOINTS` in same dir).
161
+ - `--ylim`: Energy range, e.g., `--ylim -4 4`.
162
+ - `-o, --output`: Output filename (default: `valyte_band.png`).
163
+
164
+ **Example:**
165
+ ```bash
166
+ valyte band --ylim -3 3 -o my_bands.png
167
+ ```
168
+
169
+ ---
170
+
171
+ ### 📊 Plot DOS
172
+
173
+ ```bash
174
+ valyte dos [path/to/vasprun.xml] [options]
175
+ ```
176
+
177
+ You can provide the path as a positional argument, use the `--vasprun` flag, or omit it to use the current directory.
178
+
179
+ **Examples:**
180
+ ```bash
181
+ # Plot all orbitals for all elements (Default)
182
+ valyte dos
183
+
184
+ # Plot specific elements (Total PDOS)
185
+ valyte dos -e Fe O
186
+
187
+ # Plot specific orbitals
188
+ valyte dos -e "Fe(d)" "O(p)"
189
+
190
+ # Plot mixed (Fe Total and Fe d-orbital)
191
+ valyte dos -e Fe "Fe(d)"
192
+ ```
193
+
194
+ **Options:**
195
+ - `-e`, `--elements`: Specific elements or orbitals to plot.
196
+ - Example: `-e Fe O` (Plots Total PDOS for Fe and O).
197
+ - Example: `-e Fe(d) O(p)` (Plots Fe d-orbital and O p-orbital).
198
+ - Example: `-e Fe Fe(d)` (Plots Fe Total and Fe d-orbital).
199
+ - `--xlim`: Energy range (default: `-6 6`).
200
+ - `--ylim`: DOS range (e.g., `--ylim 0 10`).
201
+ - `--scale`: Scaling factor for Y-axis (e.g., `--scale 3` divides DOS by 3).
202
+ - `--fermi`: Draw a dashed line at the Fermi level (E=0). Default is OFF.
203
+ - `--pdos`: Plot only Projected DOS (hide Total DOS).
204
+ - `--legend-cutoff`: Threshold for legend visibility (default: `0.10` = 10%).
205
+ - `-o`, `--output`: Output filename (default: `valyte_dos.png`).
206
+ - `--font`: Font family (default: `Arial`).
207
+
208
+ **Example:**
209
+
210
+ ```bash
211
+ valyte dos ./vasp_data --xlim -5 5 -o my_dos.png
212
+ ```
213
+
214
+ </details>
valyte-0.1.7/README.md ADDED
@@ -0,0 +1,189 @@
1
+ <p align="center">
2
+ <img src="valyte/Logo.png" alt="Valyte Logo" width="100%"/>
3
+ </p>
4
+
5
+ # Valyte
6
+
7
+ **Valyte** is a comprehensive CLI tool for VASP workflows, providing both pre-processing and post-processing capabilities with a focus on clean, publication-quality outputs and modern aesthetics.
8
+
9
+ ## Features
10
+
11
+ ### Pre-processing
12
+ - **Supercell Creation**: Generate supercells from POSCAR files.
13
+ - **Interactive K-Point Generation**: Create KPOINTS files with automatic grid calculation based on K-spacing.
14
+ - **Band KPOINTS Generation**: Automatic high-symmetry path detection for band structure calculations.
15
+
16
+ ### Post-processing
17
+ - **DOS Plotting**:
18
+ - Smart Plotting: Automatically handles total DOS and Projected DOS (PDOS).
19
+ - Orbital-Resolved: Plots individual orbitals (s, p, d, f) by default.
20
+ - Adaptive Legend: Intelligently hides the legend if PDOS contributions are low.
21
+ - Gradient Fill: Aesthetically pleasing gradient fills for DOS peaks.
22
+ - **Band Structure Plotting**:
23
+ - VBM alignment to 0 eV.
24
+ - Color-coded bands (Purple for VB, Teal for CB).
25
+ - High-symmetry path labels from KPOINTS.
26
+ - **Publication Quality**: Clean aesthetics, custom fonts (Arial, Helvetica, Times New Roman), high DPI output.
27
+
28
+ ## Installation
29
+
30
+ Install Valyte directly from PyPI:
31
+
32
+ ```bash
33
+ pip install valyte
34
+ ```
35
+
36
+ Or install from source:
37
+
38
+ ```bash
39
+ git clone https://github.com/nikyadav002/Valyte-Project
40
+ cd Valyte-Project
41
+ pip install -e .
42
+ ```
43
+
44
+ ## Examples
45
+
46
+ <p align="center">
47
+ <img src="valyte/valyte_dos.png" alt="DOS Plot Example" width="47%"/>
48
+ <img src="valyte/valyte_band.png" alt="Band Structure Example" width="38%"/>
49
+ </p>
50
+
51
+ ## Updating Valyte
52
+
53
+ To update to the latest version:
54
+
55
+ ```bash
56
+ pip install --upgrade valyte
57
+ ```
58
+
59
+ ## Usage
60
+
61
+ The main command is `valyte`.
62
+
63
+ <details>
64
+ <summary><strong>Click to view detailed usage instructions</strong></summary>
65
+
66
+ <br>
67
+
68
+ ### 🧊 Create Supercell
69
+
70
+ Generate a supercell from a POSCAR file:
71
+
72
+ ```bash
73
+ valyte supercell nx ny nz [options]
74
+ ```
75
+
76
+ **Example:**
77
+ ```bash
78
+ # Create a 2×2×2 supercell
79
+ valyte supercell 2 2 2
80
+
81
+ # Specify input and output files
82
+ valyte supercell 3 3 1 -i POSCAR_primitive -o POSCAR_3x3x1
83
+ ```
84
+
85
+ **Options:**
86
+ - `-i`, `--input`: Input POSCAR file (default: `POSCAR`).
87
+ - `-o`, `--output`: Output filename (default: `POSCAR_supercell`).
88
+
89
+ ---
90
+
91
+ ### 📉 Band Structure
92
+
93
+ #### 1. Generate KPOINTS
94
+
95
+ Automatically generate a KPOINTS file with high-symmetry paths for band structure calculations.
96
+
97
+ ```bash
98
+ valyte band kpt-gen [options]
99
+ ```
100
+
101
+ **Options:**
102
+ - `-i`, `--input`: Input POSCAR file (default: `POSCAR`).
103
+ - `-n`, `--npoints`: Points per segment (default: `40`).
104
+ - `-o`, `--output`: Output filename (default: `KPOINTS`).
105
+
106
+ **Example:**
107
+ ```bash
108
+ valyte band kpt-gen -n 60 -i POSCAR_relaxed -o KPOINTS_band
109
+ ```
110
+
111
+ ### 🕸️ Generate K-Points (Interactive)
112
+
113
+ Generate a `KPOINTS` file for SCF calculations interactively.
114
+
115
+ ```bash
116
+ valyte kpt
117
+ ```
118
+
119
+ This command will prompt you for:
120
+ 1. **K-Mesh Scheme**: Monkhorst-Pack or Gamma.
121
+ 2. **K-Spacing**: Value in $2\pi/\AA$ (e.g., 0.04).
122
+
123
+ It automatically calculates the optimal grid based on your `POSCAR` structure.
124
+
125
+ #### 2. Plot Band Structure
126
+
127
+ Plot the electronic band structure from `vasprun.xml`.
128
+
129
+ ```bash
130
+ valyte band [options]
131
+ ```
132
+
133
+ **Options:**
134
+ - `--vasprun`: Path to `vasprun.xml` (default: current directory).
135
+ - `--kpoints`: Path to `KPOINTS` file for path labels (default: looks for `KPOINTS` in same dir).
136
+ - `--ylim`: Energy range, e.g., `--ylim -4 4`.
137
+ - `-o, --output`: Output filename (default: `valyte_band.png`).
138
+
139
+ **Example:**
140
+ ```bash
141
+ valyte band --ylim -3 3 -o my_bands.png
142
+ ```
143
+
144
+ ---
145
+
146
+ ### 📊 Plot DOS
147
+
148
+ ```bash
149
+ valyte dos [path/to/vasprun.xml] [options]
150
+ ```
151
+
152
+ You can provide the path as a positional argument, use the `--vasprun` flag, or omit it to use the current directory.
153
+
154
+ **Examples:**
155
+ ```bash
156
+ # Plot all orbitals for all elements (Default)
157
+ valyte dos
158
+
159
+ # Plot specific elements (Total PDOS)
160
+ valyte dos -e Fe O
161
+
162
+ # Plot specific orbitals
163
+ valyte dos -e "Fe(d)" "O(p)"
164
+
165
+ # Plot mixed (Fe Total and Fe d-orbital)
166
+ valyte dos -e Fe "Fe(d)"
167
+ ```
168
+
169
+ **Options:**
170
+ - `-e`, `--elements`: Specific elements or orbitals to plot.
171
+ - Example: `-e Fe O` (Plots Total PDOS for Fe and O).
172
+ - Example: `-e Fe(d) O(p)` (Plots Fe d-orbital and O p-orbital).
173
+ - Example: `-e Fe Fe(d)` (Plots Fe Total and Fe d-orbital).
174
+ - `--xlim`: Energy range (default: `-6 6`).
175
+ - `--ylim`: DOS range (e.g., `--ylim 0 10`).
176
+ - `--scale`: Scaling factor for Y-axis (e.g., `--scale 3` divides DOS by 3).
177
+ - `--fermi`: Draw a dashed line at the Fermi level (E=0). Default is OFF.
178
+ - `--pdos`: Plot only Projected DOS (hide Total DOS).
179
+ - `--legend-cutoff`: Threshold for legend visibility (default: `0.10` = 10%).
180
+ - `-o`, `--output`: Output filename (default: `valyte_dos.png`).
181
+ - `--font`: Font family (default: `Arial`).
182
+
183
+ **Example:**
184
+
185
+ ```bash
186
+ valyte dos ./vasp_data --xlim -5 5 -o my_dos.png
187
+ ```
188
+
189
+ </details>
valyte-0.1.7/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
valyte-0.1.7/setup.py ADDED
@@ -0,0 +1,33 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="valyte",
5
+ version="0.1.7",
6
+ packages=find_packages(),
7
+ install_requires=[
8
+ "numpy",
9
+ "matplotlib",
10
+ "pymatgen",
11
+ ],
12
+ include_package_data=True,
13
+ package_data={
14
+ "valyte": ["*.png"],
15
+ },
16
+ entry_points={
17
+ "console_scripts": [
18
+ "valyte=valyte.cli:main",
19
+ ],
20
+ },
21
+ author="Nikhil",
22
+ author_email="nikhil@example.com",
23
+ description="A comprehensive CLI tool for VASP pre-processing (Supercells, K-points) and post-processing (DOS, Band Structure plotting)",
24
+ long_description=open("README.md").read(),
25
+ long_description_content_type="text/markdown",
26
+ url="https://github.com/nikyadav002/Valyte-Project",
27
+ classifiers=[
28
+ "Programming Language :: Python :: 3",
29
+ "License :: OSI Approved :: MIT License",
30
+ "Operating System :: OS Independent",
31
+ ],
32
+ python_requires=">=3.6",
33
+ )
Binary file
File without changes
@@ -0,0 +1,56 @@
1
+ """
2
+ Band structure KPOINTS generation module for Valyte.
3
+ """
4
+
5
+ import os
6
+ from pymatgen.core import Structure
7
+ from pymatgen.symmetry.bandstructure import HighSymmKpath
8
+
9
+
10
+ def generate_band_kpoints(poscar_path="POSCAR", npoints=40, output="KPOINTS"):
11
+ """
12
+ Generates KPOINTS file in line-mode for band structure calculations.
13
+ Uses SeeK-path method for high-symmetry path determination.
14
+
15
+ Args:
16
+ poscar_path (str): Path to input POSCAR file.
17
+ npoints (int): Number of points per segment (default: 40).
18
+ output (str): Output filename for KPOINTS.
19
+ """
20
+
21
+ if not os.path.exists(poscar_path):
22
+ raise FileNotFoundError(f"{poscar_path} not found")
23
+
24
+ # Read structure
25
+ structure = Structure.from_file(poscar_path)
26
+
27
+ # Get high-symmetry path using SeeK-path method
28
+ kpath = HighSymmKpath(structure, path_type="setyawan_curtarolo")
29
+
30
+ # Get the path
31
+ path = kpath.kpath["path"]
32
+ kpoints = kpath.kpath["kpoints"]
33
+
34
+ # Write KPOINTS file
35
+ with open(output, 'w') as f:
36
+ f.write("k-points for band structure\n")
37
+ f.write(f"{npoints}\n")
38
+ f.write("Line-mode\n")
39
+ f.write("Reciprocal\n")
40
+
41
+ # Write each segment
42
+ for segment in path:
43
+ for i in range(len(segment) - 1):
44
+ start = segment[i]
45
+ end = segment[i + 1]
46
+
47
+ start_coords = kpoints[start]
48
+ end_coords = kpoints[end]
49
+
50
+ f.write(f" {start_coords[0]:.6f} {start_coords[1]:.6f} {start_coords[2]:.6f} ! {start}\n")
51
+ f.write(f" {end_coords[0]:.6f} {end_coords[1]:.6f} {end_coords[2]:.6f} ! {end}\n")
52
+ f.write("\n")
53
+
54
+ # Print success message
55
+ path_str = ' → '.join([' - '.join(seg) for seg in path])
56
+ print(f"✅ KPOINTS generated: {output} ({path_str}, {npoints} pts/seg)")
@@ -0,0 +1,127 @@
1
+ import os
2
+ import numpy as np
3
+ import matplotlib as mpl
4
+ mpl.use("agg")
5
+ mpl.rcParams["axes.unicode_minus"] = False
6
+ import matplotlib.pyplot as plt
7
+ from pymatgen.io.vasp import Vasprun, BSVasprun
8
+ from pymatgen.electronic_structure.plotter import BSPlotter
9
+
10
+ def plot_band_structure(vasprun_path, kpoints_path=None, output="valyte_band.png",
11
+ ylim=None, figsize=(4, 4), dpi=400, font="Arial"):
12
+ """
13
+ Plots the electronic band structure from vasprun.xml.
14
+
15
+ Args:
16
+ vasprun_path (str): Path to vasprun.xml file.
17
+ kpoints_path (str, optional): Path to KPOINTS file (for labels).
18
+ output (str): Output filename.
19
+ ylim (tuple, optional): Energy range (min, max).
20
+ figsize (tuple): Figure size in inches.
21
+ dpi (int): Resolution of the output image.
22
+ font (str): Font family.
23
+ """
24
+
25
+ # --- Font configuration ---
26
+ font_map = {
27
+ "arial": "Arial",
28
+ "helvetica": "Helvetica",
29
+ "times": "Times New Roman",
30
+ "times new roman": "Times New Roman",
31
+ }
32
+ font = font_map.get(font.lower(), "Arial")
33
+ mpl.rcParams["font.family"] = font
34
+ mpl.rcParams["axes.linewidth"] = 1.4
35
+ mpl.rcParams["font.weight"] = "bold"
36
+ mpl.rcParams["font.size"] = 14
37
+ mpl.rcParams["xtick.major.width"] = 1.2
38
+ mpl.rcParams["ytick.major.width"] = 1.2
39
+
40
+ # print(f"🔍 Reading {vasprun_path} ...") # Silent mode
41
+
42
+ try:
43
+ # Load VASP output
44
+ # BSVasprun is optimized for band structures
45
+ vr = BSVasprun(vasprun_path, parse_projected_eigen=False)
46
+ bs = vr.get_band_structure(kpoints_filename=kpoints_path, line_mode=True)
47
+ except Exception as e:
48
+ raise ValueError(f"Failed to load band structure: {e}")
49
+
50
+ # Use BSPlotter to get the data in a plot-friendly format
51
+ bs_plotter = BSPlotter(bs)
52
+ data = bs_plotter.bs_plot_data(zero_to_efermi=True)
53
+
54
+ # Extract data
55
+ distances = data['distances'] # List of lists (one per segment)
56
+ energies = data['energy'] # Can be list of dicts OR dict of lists depending on pymatgen version/structure
57
+ ticks = data['ticks'] # Dict with 'distance' and 'label'
58
+
59
+ # Setup plot
60
+ fig, ax = plt.subplots(figsize=figsize)
61
+
62
+ # Colors
63
+ color_vb = "#8e44ad" # Purple
64
+ color_cb = "#2a9d8f" # Teal
65
+
66
+ # Plot bands
67
+ # Iterate over segments
68
+ for i in range(len(distances)):
69
+ d = distances[i]
70
+
71
+ # Handle different energy data structures
72
+ if isinstance(energies, dict):
73
+ # Structure: {'1': [seg1, seg2, ...], '-1': ...}
74
+ # Iterate over spins
75
+ for spin in energies:
76
+ # energies[spin] is a list of segments
77
+ # energies[spin][i] is the list of bands for segment i
78
+ for band in energies[spin][i]:
79
+ # Determine color based on energy relative to VBM (0 eV)
80
+ if np.mean(band) <= 0:
81
+ c = color_vb
82
+ else:
83
+ c = color_cb
84
+ ax.plot(d, band, color=c, lw=1.5, alpha=1.0)
85
+ else:
86
+ # Structure: [{'1': bands, ...}, {'1': bands, ...}] (List of dicts)
87
+ # Iterate over spin channels in this segment
88
+ for spin in energies[i]:
89
+ # energies[i][spin] is a list of arrays (one per band)
90
+ for band in energies[i][spin]:
91
+ if np.mean(band) <= 0:
92
+ c = color_vb
93
+ else:
94
+ c = color_cb
95
+ ax.plot(d, band, color=c, lw=1.5, alpha=1.0)
96
+
97
+ # Setup X-axis (K-path)
98
+ ax.set_xticks(ticks['distance'])
99
+ # Clean up labels (remove formatting like $ if needed, but pymatgen usually does a good job)
100
+ clean_labels = [l.replace("$\\mid$", "|") for l in ticks['label']]
101
+ ax.set_xticklabels(clean_labels, fontsize=14, fontweight="bold")
102
+
103
+ # Draw vertical lines at high-symmetry points
104
+ for d in ticks['distance']:
105
+ ax.axvline(d, color="k", lw=0.8, ls="-", alpha=0.3)
106
+
107
+ # Draw VBM line (E=0)
108
+ ax.axhline(0, color="k", lw=0.8, ls="--", alpha=0.5)
109
+
110
+ # Setup Y-axis
111
+ ax.set_ylabel("Energy (eV)", fontsize=16, fontweight="bold", labelpad=8)
112
+ if ylim:
113
+ ax.set_ylim(ylim)
114
+ # Set y-ticks with 1 eV spacing
115
+ yticks = np.arange(np.ceil(ylim[0]), np.floor(ylim[1]) + 1, 1)
116
+ ax.set_yticks(yticks)
117
+ else:
118
+ # Default zoom around gap
119
+ ax.set_ylim(-4, 4)
120
+ ax.set_yticks(np.arange(-4, 5, 1))
121
+
122
+ ax.set_xlim(distances[0][0], distances[-1][-1])
123
+
124
+ plt.tight_layout()
125
+ plt.savefig(output, dpi=dpi)
126
+ plt.close(fig)
127
+ # print(f"✅ Band structure saved to {output}") # Silent mode