-
-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathplot_spectra.py
More file actions
123 lines (105 loc) · 3.62 KB
/
Copy pathplot_spectra.py
File metadata and controls
123 lines (105 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
"""
Plot spectra from Ocean Optics-style TXT files and save PNGs beside them.
Assumptions:
- Each file contains a header and a line with '>>>>>Begin Spectral Data<<<<<'
- After that marker, each data line has two columns: wavelength intensity
- Columns are whitespace- or tab-separated
"""
import sys
import re
from pathlib import Path
import matplotlib.pyplot as plt
MARKER = "Begin Spectral Data"
def parse_spectrum(path: Path):
"""
Returns (wavelengths, intensities, meta_title)
meta_title is a short string (e.g., Date or Spectrometer) for plot title.
"""
# Be forgiving with encoding
try_encodings = ("utf-8", "utf-8-sig", "latin-1")
text = None
for enc in try_encodings:
try:
text = path.read_text(encoding=enc, errors="ignore")
break
except Exception:
continue
if text is None:
raise RuntimeError(f"Could not read {path} with common encodings.")
lines = text.splitlines()
# Grab something nice for the title if present
date_line = next((ln for ln in lines if ln.strip().startswith("Date:")), None)
spect_line = next((ln for ln in lines if ln.strip().startswith("Spectrometer:")), None)
meta_title = None
if date_line and spect_line:
meta_title = (
f"{spect_line.replace('Spectrometer:', '').strip()} - "
f"{date_line.replace('Date:', '').strip()}"
)
elif date_line:
meta_title = date_line.replace("Date:", "").strip()
elif spect_line:
meta_title = spect_line.replace("Spectrometer:", "").strip()
# Find start of data
start_idx = None
for i, ln in enumerate(lines):
if MARKER in ln:
start_idx = i + 1
break
if start_idx is None:
raise ValueError(f"No data marker '{MARKER}' found in {path.name}")
wl = []
iv = []
num_re = re.compile(r"^[\s\t]*([+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\s+([+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)")
for ln in lines[start_idx:]:
ln = ln.strip()
if not ln:
continue
m = num_re.match(ln)
if not m:
# Stop if we hit non-data after starting
# (or just skip this line)
continue
try:
w = float(m.group(1))
y = float(m.group(2))
except Exception:
continue
wl.append(w)
iv.append(y)
if not wl:
raise ValueError(f"No numeric data parsed from {path.name}")
return wl, iv, meta_title
def plot_and_save(wl, iv, out_path: Path, title: str):
plt.figure(figsize=(9, 5))
plt.plot(wl, iv, linewidth=1.2)
plt.xlabel("Wavelength (nm)")
plt.ylabel("Intensity (a.u.)")
plt.title(title)
plt.grid(True, linestyle=":", linewidth=0.6)
plt.tight_layout()
plt.savefig(out_path, dpi=150)
plt.close()
def main():
"""Parse TXT spectra in current directory and save chart PNGs."""
here = Path.cwd()
txt_files = sorted(here.glob("*.txt"))
if not txt_files:
print("No .txt files found in the current directory.", file=sys.stderr)
sys.exit(1)
ok, fail = 0, 0
for f in txt_files:
try:
wl, iv, meta = parse_spectrum(f)
title = f.name if not meta else f"{f.name} | {meta}"
out_png = f.with_suffix(".png")
plot_and_save(wl, iv, out_png, title)
print(f"[ok] Saved: {out_png.name}")
ok += 1
except Exception as e:
print(f"[skip] Skipped {f.name}: {e}", file=sys.stderr)
fail += 1
print(f"\nDone. {ok} plotted, {fail} failed.")
if __name__ == "__main__":
main()