| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- import pandas as pd
- import numpy as np
- import matplotlib.pyplot as plt
- # -----------------------------------------------------
- # 1) Read and prepare data
- # -----------------------------------------------------
- file_path = "./uv_responsivity_and_spectral_effectiveness_data.csv"
- df = pd.read_csv(file_path)
- w = df["Wavelength (nm)"].values
- uvc = df["UVC"].values
- uvb = df["UVB"].values
- uva = df["UVA"].values
- eff_std = df["Relative Spectral Effectiveness"].values
- eff_prot = df["Relative Spectral Effectiveness (eyes protected)"].values
- # -----------------------------------------------------
- # 2) Peak finding (with UVA “double-peak” averaging)
- # -----------------------------------------------------
- peak_uvc_idx = np.nanargmax(uvc)
- peak_uvb_idx = np.nanargmax(uvb)
- uva_ones = w[uva == 1.0]
- if len(uva_ones) >= 2:
- avg_uva_wl = (uva_ones[0] + uva_ones[1]) / 2
- peak_uva_idx = np.abs(w - avg_uva_wl).argmin()
- else:
- peak_uva_idx = np.nanargmax(uva)
- peak_uvc_wl = w[peak_uvc_idx]
- peak_uvb_wl = w[peak_uvb_idx]
- peak_uva_wl = w[peak_uva_idx]
- peak_uvc_eff_std = eff_std[peak_uvc_idx]
- peak_uvc_eff_prot = eff_prot[peak_uvc_idx]
- peak_uvb_eff_std = eff_std[peak_uvb_idx]
- peak_uvb_eff_prot = eff_prot[peak_uvb_idx]
- peak_uva_eff_std = eff_std[peak_uva_idx]
- peak_uva_eff_prot = eff_prot[peak_uva_idx]
- # -----------------------------------------------------
- # 3) Plotting
- # -----------------------------------------------------
- colors = {
- "UVC": "#4d4d4d", # darker grey
- "UVB": "#8a2be2", # violet/purple
- "UVA": "#0b66f2", # pleasing blue
- }
- fig, ax1 = plt.subplots(figsize=(10, 6))
- # 3.1) Sensor responsivity curves
- ax1.plot(w, uvc, color=colors["UVC"], linewidth=2, label="UVC Responsivity")
- ax1.plot(w, uvb, color=colors["UVB"], linewidth=2, label="UVB Responsivity")
- ax1.plot(w, uva, color=colors["UVA"], linewidth=2, label="UVA Responsivity")
- # 3.2) Peaks: vertical lines + marker + annotate SpecEff std/prot
- y_annot = 1.05
- for wl, color, eff_s, eff_p, lbl in [
- (peak_uvc_wl, colors["UVC"], peak_uvc_eff_std, peak_uvc_eff_prot, "UVC Peak"),
- (peak_uvb_wl, colors["UVB"], peak_uvb_eff_std, peak_uvb_eff_prot, "UVB Peak"),
- (peak_uva_wl, colors["UVA"], peak_uva_eff_std, peak_uva_eff_prot, "UVA Peak"),
- ]:
- ax1.axvline(x=wl, color=color, linestyle="dotted", linewidth=2, label=lbl)
- ax1.scatter(wl, 1.0, color=color, zorder=5)
- ax1.text(
- wl + 2,
- y_annot,
- f"{eff_s:.4g} / {eff_p:.4g}",
- color=color,
- fontsize=10,
- ha="left",
- va="bottom",
- )
- # 3.3) Primary axis styling & legend (resp + peaks) top-right
- ax1.set_xlabel("Wavelength (nm)")
- ax1.set_ylabel("Normalized Sensor Responsivity")
- ax1.set_ylim(0, 1.1)
- leg1 = ax1.legend(loc="upper right", bbox_to_anchor=(1, 0.8))
- ax1.add_artist(leg1)
- # 3.4) Spectral-effectiveness curves on log scale & second legend
- ax2 = ax1.twinx()
- ax2.plot(
- w,
- eff_std,
- color="grey",
- linestyle="--",
- linewidth=2,
- alpha=0.6,
- label="SpecEff (standard)",
- )
- ax2.plot(
- w,
- eff_prot,
- color="grey",
- linestyle="-.",
- linewidth=2,
- alpha=0.6,
- label="SpecEff (eyes protected)",
- )
- ax2.set_ylabel("Relative Spectral Effectiveness (Log)")
- ax2.set_yscale("log")
- leg2 = ax2.legend(loc="upper right")
- ax2.add_artist(leg2)
- # 3.5) Final touches
- ax1.set_title("UV Responsivity and Spectral Effectiveness")
- plt.tight_layout()
- plt.show()
|