visualize_data.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import pandas as pd
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. # -----------------------------------------------------
  5. # 1) Read and prepare data
  6. # -----------------------------------------------------
  7. file_path = "./uv_responsivity_and_spectral_effectiveness_data.csv"
  8. df = pd.read_csv(file_path)
  9. w = df["Wavelength (nm)"].values
  10. uvc = df["UVC"].values
  11. uvb = df["UVB"].values
  12. uva = df["UVA"].values
  13. eff_std = df["Relative Spectral Effectiveness"].values
  14. eff_prot = df["Relative Spectral Effectiveness (eyes protected)"].values
  15. # -----------------------------------------------------
  16. # 2) Peak finding (with UVA “double-peak” averaging)
  17. # -----------------------------------------------------
  18. peak_uvc_idx = np.nanargmax(uvc)
  19. peak_uvb_idx = np.nanargmax(uvb)
  20. uva_ones = w[uva == 1.0]
  21. if len(uva_ones) >= 2:
  22. avg_uva_wl = (uva_ones[0] + uva_ones[1]) / 2
  23. peak_uva_idx = np.abs(w - avg_uva_wl).argmin()
  24. else:
  25. peak_uva_idx = np.nanargmax(uva)
  26. peak_uvc_wl = w[peak_uvc_idx]
  27. peak_uvb_wl = w[peak_uvb_idx]
  28. peak_uva_wl = w[peak_uva_idx]
  29. peak_uvc_eff_std = eff_std[peak_uvc_idx]
  30. peak_uvc_eff_prot = eff_prot[peak_uvc_idx]
  31. peak_uvb_eff_std = eff_std[peak_uvb_idx]
  32. peak_uvb_eff_prot = eff_prot[peak_uvb_idx]
  33. peak_uva_eff_std = eff_std[peak_uva_idx]
  34. peak_uva_eff_prot = eff_prot[peak_uva_idx]
  35. # -----------------------------------------------------
  36. # 3) Plotting
  37. # -----------------------------------------------------
  38. colors = {
  39. "UVC": "#4d4d4d", # darker grey
  40. "UVB": "#8a2be2", # violet/purple
  41. "UVA": "#0b66f2", # pleasing blue
  42. }
  43. fig, ax1 = plt.subplots(figsize=(10, 6))
  44. # 3.1) Sensor responsivity curves
  45. ax1.plot(w, uvc, color=colors["UVC"], linewidth=2, label="UVC Responsivity")
  46. ax1.plot(w, uvb, color=colors["UVB"], linewidth=2, label="UVB Responsivity")
  47. ax1.plot(w, uva, color=colors["UVA"], linewidth=2, label="UVA Responsivity")
  48. # 3.2) Peaks: vertical lines + marker + annotate SpecEff std/prot
  49. y_annot = 1.05
  50. for wl, color, eff_s, eff_p, lbl in [
  51. (peak_uvc_wl, colors["UVC"], peak_uvc_eff_std, peak_uvc_eff_prot, "UVC Peak"),
  52. (peak_uvb_wl, colors["UVB"], peak_uvb_eff_std, peak_uvb_eff_prot, "UVB Peak"),
  53. (peak_uva_wl, colors["UVA"], peak_uva_eff_std, peak_uva_eff_prot, "UVA Peak"),
  54. ]:
  55. ax1.axvline(x=wl, color=color, linestyle="dotted", linewidth=2, label=lbl)
  56. ax1.scatter(wl, 1.0, color=color, zorder=5)
  57. ax1.text(
  58. wl + 2,
  59. y_annot,
  60. f"{eff_s:.4g} / {eff_p:.4g}",
  61. color=color,
  62. fontsize=10,
  63. ha="left",
  64. va="bottom",
  65. )
  66. # 3.3) Primary axis styling & legend (resp + peaks) top-right
  67. ax1.set_xlabel("Wavelength (nm)")
  68. ax1.set_ylabel("Normalized Sensor Responsivity")
  69. ax1.set_ylim(0, 1.1)
  70. leg1 = ax1.legend(loc="upper right", bbox_to_anchor=(1, 0.8))
  71. ax1.add_artist(leg1)
  72. # 3.4) Spectral-effectiveness curves on log scale & second legend
  73. ax2 = ax1.twinx()
  74. ax2.plot(
  75. w,
  76. eff_std,
  77. color="grey",
  78. linestyle="--",
  79. linewidth=2,
  80. alpha=0.6,
  81. label="SpecEff (standard)",
  82. )
  83. ax2.plot(
  84. w,
  85. eff_prot,
  86. color="grey",
  87. linestyle="-.",
  88. linewidth=2,
  89. alpha=0.6,
  90. label="SpecEff (eyes protected)",
  91. )
  92. ax2.set_ylabel("Relative Spectral Effectiveness (Log)")
  93. ax2.set_yscale("log")
  94. leg2 = ax2.legend(loc="upper right")
  95. ax2.add_artist(leg2)
  96. # 3.5) Final touches
  97. ax1.set_title("UV Responsivity and Spectral Effectiveness")
  98. plt.tight_layout()
  99. plt.show()