133 lines
4.3 KiB
Python
133 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
HyTools: Hyperspectral image processing library
|
|
Copyright (C) 2021 University of Wisconsin
|
|
|
|
Authors: Adam Chlus, Zhiwei Ye, Philip Townsend.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, version 3 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
Spectral resampling functions.
|
|
|
|
"""
|
|
import numpy as np
|
|
from scipy.interpolate import interp1d
|
|
|
|
|
|
def gaussian(x,mu,fwhm):
|
|
"""
|
|
Args:
|
|
x (numpy.ndarray): Values along which to generate gaussian..
|
|
mu (float): Mean of the gaussian function..
|
|
fwhm (float): Full width half maximum..
|
|
|
|
Returns:
|
|
numpy.ndarray: Gaussian along input range.
|
|
|
|
"""
|
|
|
|
c = fwhm/(2* np.sqrt(2*np.log(2)))
|
|
return np.exp(-1*((x-mu)**2/(2*c**2)))
|
|
|
|
def calc_resample_coeffs(in_wave,in_fwhm,out_wave,out_fwhm, spacing = 1):
|
|
"""Given a set of source and destination wavelengths and FWHMs this
|
|
function caculates the relative contribution or each input wavelength
|
|
to the output wavelength. It assumes that both input and output
|
|
response functions follow a gaussian distribution.
|
|
|
|
All inputs shoud be provide in nanometers.
|
|
|
|
|
|
Args:
|
|
in_wave (list): Input wavelength centers.
|
|
in_fwhm (list): Input full width half maxes.
|
|
out_wave (list): Output wavelength centers.
|
|
out_fwhm (list): Output full width half maxes.
|
|
spacing (int, optional): Resolution at which to model the
|
|
spectral response functions. Defaults to 1.
|
|
|
|
Returns:
|
|
numpy.ndarray: Transform coeffiecients.
|
|
|
|
"""
|
|
|
|
out_matrix = []
|
|
min_spectrum = min(out_wave.min(),in_wave.min())//100 *100 - 100
|
|
max_spectrum = 100 + max(out_wave.max(),in_wave.max())//100 *100
|
|
one_nm = np.arange(min_spectrum,max_spectrum,spacing)
|
|
|
|
for wave,fwhm, in zip(out_wave,out_fwhm):
|
|
a = gaussian(one_nm,wave,fwhm)
|
|
out_matrix.append(np.divide(a,np.sum(a)))
|
|
out_matrix = np.array(out_matrix)
|
|
|
|
# For each source wavelength generate the gaussion response
|
|
in_matrix = []
|
|
for wave,fwhm in zip(in_wave,in_fwhm):
|
|
in_matrix.append(gaussian(one_nm ,wave,fwhm))
|
|
in_matrix = np.array(in_matrix)
|
|
|
|
# Calculate the relative contribution of each source response function
|
|
ratio = in_matrix/in_matrix.sum(axis=0)
|
|
ratio[np.isnan(ratio)] = 0
|
|
ratio2 = np.einsum('ab,cb->acb',ratio,out_matrix)
|
|
|
|
# Calculate the relative contribution of each input wavelength
|
|
# to each destination wavelength
|
|
coeffs = np.trapz(ratio2)
|
|
|
|
return coeffs
|
|
|
|
|
|
def apply_resampler(hy_obj,data):
|
|
''' Apply SCSS correction to a slice of the data
|
|
|
|
Args:
|
|
hy_obj (TYPE): DESCRIPTION.
|
|
band (TYPE): DESCRIPTION.
|
|
index (TYPE): DESCRIPTION.
|
|
|
|
Returns:
|
|
band (TYPE): DESCRIPTION.
|
|
|
|
'''
|
|
|
|
interp_types = ['linear', 'nearest', 'nearest-up',
|
|
'zero', 'slinear', 'quadratic',
|
|
'cubic']
|
|
|
|
#Convert to float
|
|
data = data.astype(np.float32)
|
|
|
|
if hy_obj.resampler['type'] == 'gaussian':
|
|
|
|
# Load resampling coeffs to memory if needed
|
|
if 'resample_coeffs' not in hy_obj.ancillary.keys():
|
|
in_wave = hy_obj.wavelengths[~hy_obj.bad_bands]
|
|
in_fwhm =hy_obj.fwhm[~hy_obj.bad_bands]
|
|
resample_coeffs = calc_resample_coeffs(in_wave,in_fwhm,
|
|
hy_obj.resampler['out_waves'],
|
|
hy_obj.resampler['out_fwhm'])
|
|
hy_obj.ancillary['resample_coeffs'] = resample_coeffs
|
|
|
|
data = np.dot(data, hy_obj.ancillary['resample_coeffs'] )
|
|
|
|
|
|
elif hy_obj.resampler['type'] in interp_types:
|
|
interp_func = interp1d(hy_obj.wavelengths[~hy_obj.bad_bands], data,
|
|
kind=hy_obj.resampler['type'],
|
|
axis=2, fill_value="extrapolate")
|
|
data = interp_func(hy_obj.resampler['out_waves'])
|
|
|
|
return data
|