spectralpython / spectral

Python module for hyperspectral image processing
MIT License
563 stars 138 forks source link

BandResampler won't work without exact match between source and target #153

Closed Satalert closed 1 year ago

Satalert commented 1 year ago

I'm resampling a spectrum from 31800 sample points between 1399-2500nm to fit the EnMAP sensor wavelengths (90 of 224 wavelengths). Fair to say, there are some extremely close samples in the source spectrum that would be an almost exact match to the target sensor, though there are none that are exact matches. Nonetheless, Spectral's BandResampler finds no matches and can not resample the spectrum. I would like to request that the BandResampler chooses the nearest match or matches within a specified threshold to allow for some leeway where exact matches can't be found. From reading the code it seems there's no capacity to do this, but if there is please let me know.

Thankyou.

tboggs commented 1 year ago

I'm not quite following what you are trying to accomplish. Your source wavelengths are in the range 1399-2500 nm. What is the range of the destination/target bands to which you want to resample?

Also, it would be helpful if you could provide the exact command & message/error, as well as the band-related part of your header files.

Satalert commented 1 year ago

Thanks for getting back to me. I've included the relevant data for the original spectrum and the bands/FWHMs for the destination. There is no FWHM data for the original spectrum.

resampling_issue.txt

The code I have used is here:

spec: the original spectrum with 31800 sample points, there are 7 similar spectra and I'm only interested in the last one. em_bands: the EnMAP satellite sensor wavelengths em_fwhms: the EnMAP satellite sensor FWHMs

br = BandResampler(centers1 = spec.asarray()[0,6,:], fwhm1=None, 
                   centers2= em_bands, fwhm2=em_fwhms) 

br(spec.asarray()[0,6,:])

# result: 
array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]) # result of calling br with original 31800 point spectrum

As a follow up, I was able to perform a resampling of the spectrum by using the BandInfo of the original spectrum, will include code below

br2 = BandResampler(spec.bands, centers2= em_bands, fwhm2=em_fwhms)
br2(spec.asarray()[0,6,:])

Result: image

There is a large area of zero values between the two main features of the original spectrum (pale blue) but the resampled spectra (red) have aggregated through that region and made a long slope in the resampled spectra. This is due to the EnMAP bands leaving a long gap between wavelengths 1759.83 and 1939.44, so this is something I can manage.

For me, I have the solution to my issue but I think the behaviour of Spectral's band resampler seems inconsistent between using the BandInfo attribute and the centers/FWHMs for the same spectrum. So I'll leave it with you. All the best!

tboggs commented 1 year ago

Thanks for providing the detailed info. If I'm understanding your code, it looks like this line is incorrect:

br = BandResampler(centers1 = spec.asarray()[0,6,:], fwhm1=None, 
                   centers2= em_bands, fwhm2=em_fwhms) 

The "centers1" parameter of the BandResampler should be an array of center wavelengths associated with the source sensor bands. From your code, it appears you are passing in data values instead (i.e., reflectance or radiance values). I say this because your example uses the same array (spec.asarray()[0,6,:]) as both the "centers1" argument to create the resampler and also as the source spectrum to be resampled (on the following line).

Satalert commented 1 year ago

Ahh! You're right, my fault! I've changed the parameter and BandResampler has worked as expected. Thanks Thomas!

Dan

---- On Mon, 30 Jan 2023 02:47:57 +1100 Thomas Boggs @.***> wrote ---

Thanks for providing the detailed info. If I'm understanding your code, it looks like this line is incorrect:

br = BandResampler(centers1 = spec.asarray()[0,6,:], fwhm1=None, centers2= em_bands, fwhm2=em_fwhms)

The "centers1" parameter of the BandResampler should be an array of center wavelengths associated with the source sensor bands. From your code, it appears you are passing in data values instead (i.e., reflectance or radiance values). I say this because your example uses the same array (spec.asarray()[0,6,:]) as both the "centers1" argument to create the resampler and also as the source spectrum to be resampled (on the following line).

— Reply to this email directly, https://github.com/spectralpython/spectral/issues/153#issuecomment-1407698455, or https://github.com/notifications/unsubscribe-auth/A2EVIYPANE45O75KPMBL7R3WU2GK3ANCNFSM6AAAAAAUJLOTJE. You are receiving this because you authored the thread.

tboggs commented 1 year ago

Glad it worked for you!