import numpy as np
import pandas as pd
from pysptools.abundance_maps import NNLS, FCLS, UCLS
from libpyhat.Unmixing.MLM import LMM, GBM
[docs]
def unmix(
spectra,
endmembers,
unmix_method,
params=None,
normalize=False,
mask=None,
em_names=None,
):
"""
Parameters
----------
spectra : libpyhat spectra object
This contains spectral information and corresponding
wavelength values
endmembers :
Endmember spectra to use for unmixing
unmix_method : string
The name of the unmixing method. See supported_methods
variable for the list of possibilities.
params : Only relevant to the *non* pysptools methods; contains
parameter values for methods
normalize : boolean
Only relevant to the pysptools methods; determines
whether to normalize before analysis
mask : array
Contains entry for each wvl column to indicate whether
to mask
em_names : list of strings
Contains names of the end members
Returns
-------
results : unmixing method results (varies)
Includes results from the unmixing algorithm
"""
supported_methods = ["NNLS", "FCLS", "UCLS", "LMM", "GBM"]
# set a default value for whether the method is a pysptools method
is_pysp = False
try:
if unmix_method.upper() in supported_methods:
if unmix_method == "NNLS":
method = NNLS()
is_pysp = True
if unmix_method == "FCLS":
method = FCLS()
is_pysp = True
if unmix_method == "UCLS":
method = UCLS()
is_pysp = True
if unmix_method == "LMM":
method = LMM(**params)
if unmix_method == "GBM":
method = GBM(**params)
else:
print(
f"{unmix_method} is not a supported method. Supported "
f"methods are {supported_methods}"
)
return 1
except KeyError:
print(f"Unable to instantiate class from {unmix_method}.")
return 1
# If the user doesn't provide names for the end members, generate
# generic ones
if em_names is None:
em_names = ["EM" + str(i + 1) for i in range(endmembers.shape[0])]
# If the algorithm the user chose is from pysptools
if is_pysp:
# If there is more than one spectrum, set up a data cube
if len(spectra.shape) == 2:
spectra = np.expand_dims(spectra, 0) # pysptools expects a cube
# Produce results and a column list, which will be combined and
# returned to the user
results = method.map(
np.array(spectra), np.array(endmembers), normalize=normalize, mask=mask
)
cols = [
(unmix_method + " Normalize:" + str(normalize) + " Mask:" + str(mask), i)
for i in em_names
]
else: # If the algorithm is *not* from pysptools
# Same here
results = method.unmix(spectra, endmembers)
cols = [(unmix_method + str(params), i) for i in em_names]
# Combine results into a dataframe and return them to the user
results = pd.DataFrame(np.squeeze(results), columns=pd.MultiIndex.from_tuples(cols))
return results