HLS Mixture Residual

This describes how to unmix a large number of HLS images from ENVI-formatted reflectance, and simulataneously compute three output images:

  1. Unmixed image, where the bands correspond to subpixel fractions of each endmember;

  2. Modeled image, which represents what the reflectance spectrum of each pixel would have been if the mixture model were perfectly accurate;

  3. Mixture Residual image, which represents the wavelength-specific difference between the observed and modeled reflectance images.


To do this, you already need to have the following things in hand:

  1. A folder of ENVI-formatted reflectance images

  2. A file with the endmembers you would like to use to do the unmixing

    1. This is usually in the form of columns, with spaces separating the columns. The first column should be the center wavelength of each band. The next columns are the endmember spectra.

  3. A file with a list of bands which you would like to keep or exclude

    1. This is a single row of 1s and 0s, separated by commas. 1s indicate you will use the band, 0s indicate you will not.

    2. Here is a typical file for L30 HLS, and here is a typical file for S30 HLS


Once this is ready, execute the following steps:

  1. Download this script: batch_HLS_L30_MixtureResidual.py

  2. Create an extra copy of your endmember file. Open it in a text editor and remove all the header lines.

  3. Change the following variables within the script:

    1. Line 20: directory (should be the path to your files)

    2. Line 28: endmember file (should be the path to the headerless endmember file you created above)

    3. Line 29: badbands file (should be the path to your file indicating which bands to use)

    4. Line 32: unit sum weight (change according to data scaling)

    5. Line 35: rescale (change according to data scaling)

  4. Run the code.

  5. Run the following commands to generate header files for each of the output files, for L30:

for i in *_subScale.hdr; do sed 's/bands = 7/bands = 7/' ${i} > ${i%????}_Modeled.hdr; done

for i in *_subScale.hdr; do sed 's/bands = 7/bands = 7/' ${i} > ${i%????}_MixtureResidual.hdr; done

for i in *_subScale.hdr; do sed 's/bands = 7/bands = 3/' ${i} > ${i%????}_Unmixed.hdr; done

for i in *_Unmixed.hdr; do sed -i.bak 's/Band 1,/Substrate,/g' ${i}; sed -i.bak 's/Band 2,/Vegetation,/g' ${i}; sed -i.bak 's/Band 3,/Dark}/g' ${i}; sed -i.bak 's/Band 4,//g' ${i}; sed -i.bak 's/Band 5,//g' ${i}; sed -i.bak 's/Band 6,//g' ${i}; sed -i.bak 's/Band 7}//g' ${i}; done

  1. Run the following commands to generate header files for each of the output files, for S30:

for i in *_subScale.hdr; do sed 's/bands = 11/bands = 11/' ${i} > ${i%????}_Modeled.hdr; done

for i in *_Modeled.hdr; do sed -i.bak 's/data type = 12/data type = 4/' ${i}; done

for i in *_subScale.hdr; do sed 's/bands = 11/bands = 11/' ${i} > ${i%????}_MixtureResidual.hdr; done

for i in *_MixtureResidual.hdr; do sed -i.bak 's/data type = 12/data type = 4/' ${i}; done

for i in *_subScale.hdr; do sed 's/bands = 11/bands = 3/' ${i} > ${i????}_Unmixed.hdr; done

for i in *_Unmixed.hdr; do sed -i.bak 's/data type = 12/data type = 4/' ${i}; done

for i in *_Unmixed.hdr; do sed -i.bak 's/Band 1,/Substrate,/g' ${i}; sed -i.bak 's/Band 2,/Vegetation,/g' ${i}; sed -i.bak 's/Band 3,/Dark}/g' ${i}; sed -i.bak 's/Band 4,//g' ${i}; sed -i.bak 's/Band 5,//g' ${i}; sed -i.bak 's/Band 6,//g' ${i}; sed -i.bak 's/Band 7,//g' ${i}; sed -i.bak 's/Band 8,//g' ${i}; sed -i.bak 's/Band 9,//g' ${i}; sed -i.bak 's/Band 10,//g' ${i}; sed -i.bak 's/Band 11}//g' ${i}; done

  1. Run the following commands to rename the files so L30 and S30 can mix while being in correct time series order:

    for i in *L30*.hdr; do mv -v ${i} ${i:15:-4}_L30.hdr; done


for i in *S30*.hdr; do mv -v ${i} ${i:15:-4}_S30.hdr; done


for i in *L30*xed; do mv -v ${i} ${i:15}_L30; done


for i in *S30*xed; do mv -v ${i} ${i:15}_S30; done