# This file was extracted from the HV SDK Docusaurus examples. # It is intended as a downloadable, runnable companion to the documentation. # Set HSI_EXAMPLE_BASE_DIR and related env vars to use your own data. # Source page: /hsi/hv_sdk/examples/basics#smoothing-spectra # region: setup import os from pathlib import Path import matplotlib.pyplot as plt import numpy as np import qtec_hv_sdk as hs from qtec_hv_sdk.preprocessing import make_reference from qtec_hv_sdk.preprocessing import reflectance_calibration from qtec_hv_sdk.preprocessing import savgol_filter BASE_DIR = Path(os.environ.get("HSI_EXAMPLE_BASE_DIR", "/path/to/HSI_data/nuts")) if not BASE_DIR.exists(): raise SystemExit( "Run: 'export HSI_EXAMPLE_BASE_DIR=/path/to/HSI_data/' to setup the " "folder containing the example datacubes." ) CUBE = os.environ.get("HSI_EXAMPLE_CUBE", "mix1.pam") DARK_REF = os.environ.get("HSI_EXAMPLE_DARK_REF", "dark_ref.pam") WHITE_REF = os.environ.get("HSI_EXAMPLE_WHITE_REF", "white_ref.pam") WAVELENGTH_MIN_NM = 430.0 WAVELENGTH_MAX_NM = 1700.0 def make_references(): dark = hs.open(str(BASE_DIR / DARK_REF)) white = hs.open(str(BASE_DIR / WHITE_REF)) return make_reference(dark), make_reference(white) def add_camera_wavelengths(img): # Example PAM cubes may not include wavelengths; attach them so downstream # wavelength-based code can use img.meta.spectral.wavelengths. if img.meta.spectral.wavelengths is not None: return img meta = img.meta meta.spectral = hs.SpectralMeta( wavelengths=hs.WavelengthMeta( np.linspace(WAVELENGTH_MIN_NM, WAVELENGTH_MAX_NM, img.meta.shape.bands), hs.WavelengthUnit.Nanometer, ) ) return img.with_meta(meta) def open_reflectance_cube(cube_name=CUBE): dark_ref, white_ref = make_references() img = add_camera_wavelengths(hs.open(str(BASE_DIR / cube_name))) return reflectance_calibration(img, white_ref, dark_ref, clip=True) def wavelengths_for_image(img): wavelengths = img.meta.spectral.wavelengths if wavelengths is None: raise ValueError("This image does not contain wavelength metadata.") if wavelengths.unit != hs.WavelengthUnit.Nanometer: raise ValueError(f"Expected wavelengths in nm, got {wavelengths.unit}.") return np.array(wavelengths.band_data) # end region # region: example reflectance = open_reflectance_cube() # Savitzky-Golay filter only supports BIP and BIL reflectance = reflectance.to_interleave(hs.bip) smoothed_reflectance = savgol_filter(reflectance, window_length=21, polyorder=3) x = 450 y = 320 spectrum = reflectance[y, x, :].to_numpy_with_interleave(hs.bip)[0, 0, :] smoothed_spectrum = smoothed_reflectance[y, x, :].to_numpy_with_interleave(hs.bip)[0, 0, :] wavelengths = wavelengths_for_image(reflectance) plt.plot(wavelengths, spectrum, alpha=0.5, label="raw") plt.plot(wavelengths, smoothed_spectrum, label="smoothed") plt.xlabel("Wavelength [nm]") plt.ylabel("Reflectance") plt.legend() plt.grid(True, alpha=0.3) plt.show() # end region