Commit 63fc1df8ebee680b2a16a6709d79f05e2dffe90b

Authored by David Mayerich
1 parent 371bf339

added an inverse PCA transform to the stim::envi classes

stim/envi/bil.h
... ... @@ -35,7 +35,12 @@ protected:
35 35 return R[1];
36 36 }
37 37  
38   - using binary<T>::thread_data;
  38 + using binary<T>::progress;
  39 +
  40 + /// Call the binary nnz() function for the BIL orientation
  41 + unsigned long long nnz(unsigned char* mask){
  42 + return binary<T>::nnz(mask, X()*Y());
  43 + }
39 44  
40 45 public:
41 46  
... ... @@ -63,9 +68,10 @@ public:
63 68  
64 69 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
65 70 /// @param page <= B is the integer number of the band to be copied.
66   - bool band_index( T * p, unsigned int page){
  71 + bool band_index( T * p, unsigned int page, bool PROGRESS = false){
67 72 //return binary<T>::read_plane_1(p, page);
68 73  
  74 + if(PROGRESS) progress = 0;
69 75 unsigned int L = X() * sizeof(T); //caculate the number of bytes in a sample line
70 76 unsigned int jump = X() * (Z() - 1) * sizeof(T);
71 77  
... ... @@ -79,6 +85,7 @@ public:
79 85 {
80 86 file.read((char *)(p + i * X()), L);
81 87 file.seekg( jump, std::ios::cur);
  88 + if(PROGRESS) progress = (double)(i+1) / Y() * 100;
82 89 }
83 90  
84 91 return true;
... ... @@ -88,7 +95,7 @@ public:
88 95  
89 96 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
90 97 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied.
91   - bool band( T * p, double wavelength){
  98 + bool band( T * p, double wavelength, bool PROGRESS = false){
92 99  
93 100 //if there are no wavelengths in the BSQ file
94 101 if(w.size() == 0)
... ... @@ -104,7 +111,7 @@ public:
104 111  
105 112 //if wavelength is smaller than the first one in header file
106 113 if ( w[page] > wavelength ){
107   - band_index(p, page);
  114 + band_index(p, page, PROGRESS);
108 115 return true;
109 116 }
110 117  
... ... @@ -124,7 +131,7 @@ public:
124 131 p1=(T*)malloc(S); //memory allocation
125 132 p2=(T*)malloc(S);
126 133 band_index(p1, page - 1);
127   - band_index(p2, page );
  134 + band_index(p2, page, PROGRESS);
128 135 for(unsigned i=0; i < XY; i++){
129 136 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
130 137 p[i] = (p2[i] - p1[i]) * r + p1[i];
... ... @@ -134,7 +141,7 @@ public:
134 141 }
135 142 else //if the wavelength is equal to a wavelength in header file
136 143 {
137   - band_index(p, page);
  144 + band_index(p, page, PROGRESS);
138 145 }
139 146  
140 147 return true;
... ... @@ -195,8 +202,8 @@ public:
195 202 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
196 203 /// @param x is the x-coordinate (dimension 1) of the spectrum.
197 204 /// @param y is the y-coordinate (dimension 2) of the spectrum.
198   - bool spectrum(T * p, unsigned x, unsigned y){
199   - return binary<T>::read_line_02(p, x, y);
  205 + bool spectrum(T * p, unsigned x, unsigned y, bool PROGRESS = false){
  206 + return binary<T>::read_line_1(p, x, y, PROGRESS);
200 207 }
201 208  
202 209 /// Retrieve a single pixel and stores it in pre-allocated memory.
... ... @@ -223,7 +230,7 @@ public:
223 230  
224 231 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
225 232 /// @param wls is the list of baseline points based on band labels.
226   - bool baseline(std::string outname, std::vector<double> wls){
  233 + bool baseline(std::string outname, std::vector<double> wls, bool PROGRESS = false){
227 234  
228 235 unsigned N = wls.size(); //get the number of baseline points
229 236  
... ... @@ -321,7 +328,7 @@ public:
321 328 }//loop for YZ line end
322 329 target.write(reinterpret_cast<const char*>(c), L); //write the corrected data into destination
323 330  
324   - thread_data = (double)k / Y() * 100;
  331 + if(PROGRESS) progress = (double)(k+1) / Y() * 100;
325 332 }//loop for Y slice end
326 333  
327 334 free(a);
... ... @@ -329,8 +336,6 @@ public:
329 336 free(c);
330 337 target.close();
331 338  
332   - thread_data = 100;
333   -
334 339 return true;
335 340  
336 341 }
... ... @@ -340,7 +345,7 @@ public:
340 345 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
341 346 /// @param w is the label specifying the band that the hyperspectral image will be normalized to.
342 347 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers.
343   - bool normalize(std::string outname, double w, double t = 0.0)
  348 + bool normalize(std::string outname, double w, double t = 0.0, bool PROGRESS = false)
344 349 {
345 350 unsigned int B = Z(); //calculate the number of bands
346 351 unsigned int ZX = Z() * X();
... ... @@ -374,20 +379,19 @@ public:
374 379 }
375 380 target.write(reinterpret_cast<const char*>(c), L); //write normalized data into destination
376 381  
377   - thread_data = (double)j / Y() * 100;
  382 + if(PROGRESS) progress = (double)(j+1) / Y() * 100;
378 383 }
379 384  
380 385 free(b);
381 386 free(c);
382 387 target.close();
383   - thread_data = 100;
384 388 return true;
385 389 }
386 390  
387 391 /// Convert the current BIL file to a BSQ file with the specified file name.
388 392  
389 393 /// @param outname is the name of the output BSQ file to be saved to disk.
390   - bool bsq(std::string outname)
  394 + bool bsq(std::string outname, bool PROGRESS = false)
391 395 {
392 396 unsigned int S = X() * Y() * sizeof(T); //calculate the number of bytes in a band
393 397  
... ... @@ -402,11 +406,9 @@ public:
402 406 band_index(p, i);
403 407 target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file
404 408  
405   - thread_data = (double)i / Z() * 100; //store the progress for the current operation
  409 + if(PROGRESS) progress = (double)(i+1) / Z() * 100; //store the progress for the current operation
406 410 }
407 411  
408   - thread_data = 100; //set the current progress to 100%
409   -
410 412 free(p);
411 413 target.close();
412 414 return true;
... ... @@ -415,7 +417,7 @@ public:
415 417 /// Convert the current BIL file to a BIP file with the specified file name.
416 418  
417 419 /// @param outname is the name of the output BIP file to be saved to disk.
418   - bool bip(std::string outname)
  420 + bool bip(std::string outname, bool PROGRESS = false)
419 421 {
420 422 unsigned int S = X() * Z() * sizeof(T); //calculate the number of bytes in a ZX slice
421 423  
... ... @@ -436,15 +438,12 @@ public:
436 438 for ( unsigned j = 0; j < X(); j++)
437 439 q[k + j * Z()] = p[ks + j];
438 440  
439   - thread_data = (double)(i * Z() + k) / (Z() * Y()) * 100; //store the progress for the current operation
  441 + if(PROGRESS) progress = (double)((i+1) * Z() + k+1) / (Z() * Y()) * 100; //store the progress for the current operation
440 442 }
441 443  
442 444 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file
443 445 }
444 446  
445   - thread_data = 100;
446   -
447   -
448 447 free(p);
449 448 free(q);
450 449 target.close();
... ... @@ -879,14 +878,14 @@ public:
879 878 target.write((char*)spec, B * sizeof(T)); //write that spectrum to disk. Size is L2.
880 879 }
881 880  
882   - thread_data = (double) (y * X() + x) / (Y() * X()) * 100;
  881 + progress = (double) (y * X() + x) / (Y() * X()) * 100;
883 882 }
884 883 }
885 884 target.close();
886 885 free(slice);
887 886 free(spec);
888 887  
889   - thread_data = 100;
  888 + progress = 100;
890 889 return true;
891 890 }
892 891  
... ... @@ -923,7 +922,7 @@ public:
923 922  
924 923 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
925 924 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
926   - bool avg_band(double* p, unsigned char* mask = NULL){
  925 + bool avg_band(double* p, unsigned char* mask = NULL, bool PROGRESS = false){
927 926 unsigned long long XZ = X() * Z();
928 927 unsigned long long XY = X() * Y();
929 928 T* temp = (T*)malloc(sizeof(T) * XZ);
... ... @@ -947,6 +946,7 @@ public:
947 946 }
948 947 }
949 948 }
  949 + if(PROGRESS) progress = (double)(k+1) / Y() * 100;
950 950 }
951 951 free(temp);
952 952 return true;
... ... @@ -957,8 +957,8 @@ public:
957 957 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
958 958 /// @param avg is a pointer to memory of size B that stores the average spectrum
959 959 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
960   - bool co_matrix(double* co, double* avg, unsigned char *mask){
961   - thread_data = 0;
  960 + bool co_matrix(double* co, double* avg, unsigned char *mask, bool PROGRESS = false){
  961 + progress = 0;
962 962 //memory allocation
963 963 unsigned long long xy = X() * Y();
964 964 unsigned long long B = Z();
... ... @@ -986,7 +986,7 @@ public:
986 986 }
987 987 }
988 988 }
989   - thread_data = (double)j / xy * 100;
  989 + if(PROGRESS) progress = (double)(j+1) / xy * 100;
990 990 }
991 991 //because correlation matrix is symmetric
992 992 for (unsigned long long i = 0; i < B; i++){
... ... @@ -996,9 +996,6 @@ public:
996 996 }
997 997  
998 998 free(temp);
999   -
1000   - thread_data = 100; //processing complete
1001   -
1002 999 return true;
1003 1000 }
1004 1001  
... ... @@ -1015,7 +1012,8 @@ public:
1015 1012 unsigned long long x1,
1016 1013 unsigned long long y1,
1017 1014 unsigned long long b0,
1018   - unsigned long long b1){
  1015 + unsigned long long b1,
  1016 + bool PROGRESS = false){
1019 1017  
1020 1018 //calculate the new image parameters
1021 1019 unsigned long long samples = x1 - x0;
... ... @@ -1048,7 +1046,7 @@ public:
1048 1046 file.read((char *)(temp + z * samples), sizeof(T) * samples);
1049 1047 file.seekg(jumpb, std::ios::cur); //go to the next band
1050 1048  
1051   - thread_data = (double)(x * Z() + z) / (lines * Z()) * 100;
  1049 + if(PROGRESS) progress = (double)(x * Z() + z+1) / (lines * Z()) * 100;
1052 1050 }
1053 1051  
1054 1052 //write slice data into target file
... ... @@ -1061,8 +1059,6 @@ public:
1061 1059 //free the temporary frame
1062 1060 free(temp);
1063 1061  
1064   - thread_data = 100;
1065   -
1066 1062 return true;
1067 1063 }
1068 1064  
... ...
stim/envi/binary.h
... ... @@ -24,11 +24,11 @@ protected:
24 24 std::fstream file; //file stream used for reading and writing
25 25 std::string name; //file name
26 26  
27   - unsigned long long int R[D]; //resolution
  27 + unsigned long long R[D]; //resolution
28 28 unsigned int header; //header size (in bytes)
29 29 unsigned char* mask; //pointer to a character array: 0 = background, 1 = foreground (or valid data)
30 30  
31   - unsigned int thread_data; //unsigned integer used to pass data to threads during processing
  31 + double progress; //stores the progress on the current operation (accessible using a thread)
32 32  
33 33  
34 34 /// Private initialization function used to set default parameters in the data structure.
... ... @@ -37,7 +37,24 @@ protected:
37 37 header = 0; //initialize the header size to zero
38 38 mask = NULL;
39 39  
40   - thread_data = 0;
  40 + progress = 0;
  41 + }
  42 +
  43 + //calculate the number of non-zero pixels in a mask
  44 + unsigned long long nnz(unsigned char* mask, unsigned long long N){
  45 +
  46 + unsigned long long n = 0; //initialize the counter to 0 (zero)
  47 + if(mask == NULL) return N; //if the mask is NULL, assume all pixels are masked
  48 +
  49 + for(unsigned long long i = 0; i < N; i++){ //for each pixel
  50 + if(mask[i] != 0) n++; //increment the counter for every non-zero pixel in the mask
  51 + }
  52 + return n; //return the number of nonzero pixels
  53 + }
  54 +
  55 + /// Calculate the number of nonzero pixels in a mask over X-Y
  56 + unsigned long long nnz(unsigned char* mask){
  57 + return nnz(mask, R[0] * R[1]);
41 58 }
42 59  
43 60 /// Private helper function that returns the size of the file on disk using system functions.
... ... @@ -105,12 +122,12 @@ protected:
105 122  
106 123 public:
107 124  
108   - unsigned int get_thread_data(){
109   - return thread_data;
  125 + unsigned int get_progress(){
  126 + return progress;
110 127 }
111 128  
112   - void reset_thread_data(){
113   - thread_data = 0;
  129 + void reset_progress(){
  130 + progress = 0;
114 131 }
115 132  
116 133 /// Open a binary file for streaming.
... ... @@ -178,7 +195,9 @@ public:
178 195  
179 196 /// @param p is a pointer to pre-allocated memory equal to the page size
180 197 /// @param page is the index of the page
181   - bool read_page( T * p, unsigned int page){
  198 + bool read_page( T * p, unsigned int page, bool PROGRESS = false){
  199 +
  200 + if(PROGRESS) progress = 0;
182 201  
183 202 if (page >= R[2]){ //make sure the bank number is right
184 203 std::cout<<"ERROR: page out of range"<<std::endl;
... ... @@ -187,7 +206,7 @@ public:
187 206  
188 207 file.seekg(R[1] * R[0] * page * sizeof(T) + header, std::ios::beg); //write into memory from the binary file
189 208 file.read((char *)p, R[0] * R[1] * sizeof(T));
190   -
  209 + if(PROGRESS) progress = 100;
191 210 return true;
192 211 }
193 212  
... ... @@ -198,9 +217,11 @@ public:
198 217 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
199 218 /// @param x is the x coordinate
200 219 /// @param y is the y coordinate
201   - bool read_line_01( T * p, unsigned int x, unsigned int y){
  220 + bool read_line_2( T * p, unsigned int x, unsigned int y, bool PROGRESS = false){
202 221 unsigned int i;
203 222  
  223 + if(PROGRESS) progress = 0;
  224 +
204 225 if ( x >= R[0] || y >= R[1]){ //make sure the sample and line number is right
205 226 std::cout<<"ERROR: sample or line out of range"<<std::endl;
206 227 return false;
... ... @@ -211,7 +232,9 @@ public:
211 232 {
212 233 file.read((char *)(p + i), sizeof(T));
213 234 file.seekg((R[1] * R[0] - 1) * sizeof(T), std::ios::cur); //go to the next band
  235 + if(PROGRESS) progress = (double)i / (double)R[2] * 100;
214 236 }
  237 + if(PROGRESS) progress = 100;
215 238  
216 239 return true;
217 240 }
... ... @@ -221,7 +244,7 @@ public:
221 244 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
222 245 /// @param x is the y coordinate
223 246 /// @param y is the z coordinate
224   - bool read_line_12(T * p, unsigned int y, unsigned int z){
  247 + bool read_line_0(T * p, unsigned int y, unsigned int z, bool PROGRESS = false){
225 248 //test to make sure the specified value is within range
226 249 if( y >= R[1] || z >= R[2] ){
227 250 std::cout<<"ERROR: sample or line out of range"<<std::endl;
... ... @@ -230,7 +253,7 @@ public:
230 253  
231 254 file.seekg((z * R[0] * R[1] + y * R[0]) * sizeof(T), std::ios::beg); //seek to the start of the line
232 255 file.read((char *)p, sizeof(T) * R[0]); //read the line
233   -
  256 + if(PROGRESS) progress = 100;
234 257 return true;
235 258 }
236 259  
... ... @@ -239,7 +262,8 @@ public:
239 262 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
240 263 /// @param x is the y coordinate
241 264 /// @param z is the z coordinate
242   - bool read_line_02(T * p, unsigned int x, unsigned int z){
  265 + bool read_line_1(T * p, unsigned int x, unsigned int z, bool PROGRESS = false){
  266 + if(PROGRESS) progress = 0;
243 267 //test to make sure the specified value is within range
244 268 if( x >= R[0] || z >= R[2] ){
245 269 std::cout<<"ERROR: sample or line out of range"<<std::endl;
... ... @@ -250,8 +274,9 @@ public:
250 274 for (unsigned int i = 0; i < R[1]; i++){ //for each pixel in the line
251 275 file.read((char *)(p + i), sizeof(T)); //read the pixel
252 276 file.seekg((R[0] - 1) * sizeof(T), std::ios::cur); //seek to the next pixel in the line
  277 + if(PROGRESS) progress = (double)i / (double)R[1] * 100;
253 278 }
254   -
  279 + if(PROGRESS) progress = 100;
255 280 return true;
256 281 }
257 282  
... ... @@ -259,8 +284,8 @@ public:
259 284  
260 285 /// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T)
261 286 /// @param n is the 0-axis coordinate used to retrieve the plane
262   - bool read_plane_0(T* p, unsigned int n){
263   -
  287 + bool read_plane_0(T* p, unsigned int n, bool PROGRESS = false){
  288 + if(PROGRESS) progress = 0;
264 289 if (n >= R[0]){ //make sure the number is within the possible range
265 290 std::cout<<"ERROR read_plane_0: page out of range"<<std::endl;
266 291 return false;
... ... @@ -274,10 +299,10 @@ public:
274 299 for(unsigned int i = 0; i<N; i++){
275 300 file.read((char*)(p+i), sizeof(T));
276 301 file.seekg(jump, std::ios::cur);
277   - thread_data = (double)i / N * 100;
  302 + if(PROGRESS) progress = (double)i / N * 100;
278 303 }
279 304  
280   - thread_data = 100;
  305 + if(PROGRESS) progress = 100;
281 306 return true;
282 307  
283 308  
... ... @@ -287,8 +312,8 @@ public:
287 312  
288 313 /// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T)
289 314 /// @param n is the 1-axis coordinate used to retrieve the plane
290   - bool read_plane_1(T* p, unsigned int n){
291   -
  315 + bool read_plane_1(T* p, unsigned int n, bool PROGRESS = false){
  316 + if(PROGRESS) progress = 0;
292 317 unsigned int L = R[0] * sizeof(T); //caculate the number of bytes in a sample line
293 318 unsigned int jump = R[0] * (R[1] - 1) * sizeof(T);
294 319  
... ... @@ -299,13 +324,13 @@ public:
299 324  
300 325 file.seekg(R[0] * n * sizeof(T), std::ios::beg);
301 326 for (unsigned i = 0; i < R[2]; i++){
302   - thread_data = (double)i / R[2] * 100;
  327 + if(PROGRESS) progress = (double)i / R[2] * 100;
303 328 file.read((char *)(p + i * R[0]), L);
304 329 file.seekg( jump, std::ios::cur);
305 330 std::cout<<i<<" ";
306 331 }
307 332  
308   - thread_data = 100;
  333 + if(PROGRESS) progress = 100;
309 334 return true;
310 335 }
311 336  
... ... @@ -313,8 +338,8 @@ public:
313 338  
314 339 /// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T)
315 340 /// @param n is the 2-axis coordinate used to retrieve the plane
316   - bool read_plane_2(T* p, unsigned int n){
317   - return read_page(p, n);
  341 + bool read_plane_2(T* p, unsigned int n, bool PROGRESS = false){
  342 + return read_page(p, n, PROGRESS);
318 343 }
319 344  
320 345 /// Reads a single pixel, treating the entire data set as a linear array
... ...
stim/envi/bip.h
... ... @@ -41,14 +41,77 @@ protected:
41 41 return R[0];
42 42 }
43 43  
44   - using binary<T>::thread_data;
  44 + using binary<T>::progress;
  45 +
  46 + /// Call the binary nnz() function for the BIP orientation
  47 + unsigned long long nnz(unsigned char* mask){
  48 + return binary<T>::nnz(mask, X()*Y());
  49 + }
  50 +
  51 + /// Linear interpolation of a spectral value given the bounding spectral samples
  52 + T lerp(double w, T low_v, double low_w, T high_v, double high_w){
  53 + if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds
  54 + double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor
  55 + return (1.0 - alpha) * low_v + alpha * high_v; //interpolate
  56 + }
  57 +
  58 + /// Gets the two band indices surrounding a given wavelength
  59 + void band_bounds(double wavelength, unsigned long long& low, unsigned long long& high){
  60 + unsigned long long B = Z();
  61 + for(high = 0; high < B; high++){
  62 + if(w[high] > wavelength) break;
  63 + }
  64 + low = 0;
  65 + if(high > 0)
  66 + low = high-1;
  67 + }
  68 +
  69 + /// Get the list of band numbers that bound a list of wavelengths
  70 + void band_bounds(std::vector<double> wavelengths,
  71 + std::vector<unsigned long long>& low_bands,
  72 + std::vector<unsigned long long>& high_bands){
  73 +
  74 + unsigned long long W = w.size(); //get the number of wavelengths in the list
  75 + low_bands.resize(W); //pre-allocate space for the band lists
  76 + high_bands.resize(W);
  77 +
  78 + for(unsigned long long wl = 0; wl < W; wl++){ //for each wavelength
  79 + band_bounds(wavelengths[wl], low_bands[wl], high_bands[wl]); //find the low and high bands
  80 + }
  81 + }
  82 +
  83 + /// Returns the interpolated in the given spectrum based on the given wavelength
  84 +
  85 + /// @param s is the spectrum in main memory of length Z()
  86 + /// @param wavelength is the wavelength value to interpolate out
  87 + T interp_spectrum(T* s, double wavelength){
  88 + unsigned long long low, high; //indices for the bands surrounding wavelength
  89 + band_bounds(wavelength, low, high); //get the surrounding band indices
  90 +
  91 + if(high == w.size()) return s[w.size()-1]; //if the high band is above the wavelength range, return the highest wavelength value
  92 +
  93 + return lerp(wavelength, s[low], w[low], s[high], w[high]);
  94 + }
  95 +
  96 + /// Returns the interpolated value corresponding to the given list of wavelengths
  97 + std::vector<T> interp_spectrum(T* s, std::vector<double> wavelengths){
  98 +
  99 + unsigned long long N = wavelengths.size(); //get the number of wavelength measurements
  100 +
  101 + std::vector<T> v; //allocate space for the resulting values
  102 + v.resize(wavelengths.size());
  103 + for(unsigned long long n = 0; n < N; n++){ //for each measurement
  104 + v[n] = interp_spectrum(s, wavelengths[n]); //interpolate the measurement
  105 + }
  106 + return v;
  107 + }
45 108  
46 109 public:
47 110  
48 111 using binary<T>::open;
49 112 using binary<T>::file;
50 113 using binary<T>::R;
51   - using binary<T>::read_line_12;
  114 + using binary<T>::read_line_0;
52 115  
53 116 /// Open a data file for reading using the class interface.
54 117  
... ... @@ -73,19 +136,19 @@ public:
73 136  
74 137 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
75 138 /// @param page <= B is the integer number of the band to be copied.
76   - bool band_index( T * p, unsigned int page){
77   - return binary<T>::read_plane_0(p, page);
  139 + bool band_index( T * p, unsigned int page, bool PROGRESS = false){
  140 + return binary<T>::read_plane_0(p, page, PROGRESS);
78 141 }
79 142  
80 143 /// Retrieve a single band (by numerical label) and stores it in pre-allocated memory.
81 144  
82 145 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
83 146 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied.
84   - bool band( T * p, double wavelength){
  147 + bool band( T * p, double wavelength, bool PROGRESS = false){
85 148  
86 149 //if there are no wavelengths in the BSQ file
87 150 if(w.size() == 0)
88   - return band_index(p, (unsigned int)wavelength);
  151 + return band_index(p, (unsigned int)wavelength, PROGRESS);
89 152  
90 153 unsigned int XY = X() * Y(); //calculate the number of pixels in a band
91 154  
... ... @@ -96,7 +159,7 @@ public:
96 159  
97 160 //if wavelength is smaller than the first one in header file
98 161 if ( w[page] > wavelength ){
99   - band_index(p, page);
  162 + band_index(p, page, PROGRESS);
100 163 return true;
101 164 }
102 165  
... ... @@ -105,7 +168,7 @@ public:
105 168 page++;
106 169 //if wavelength is larger than the last wavelength in header file
107 170 if (page == Z()) {
108   - band_index(p, Z()-1);
  171 + band_index(p, Z()-1, PROGRESS);
109 172 return true;
110 173 }
111 174 }
... ... @@ -116,7 +179,7 @@ public:
116 179 p1=(T*)malloc( XY * sizeof(T)); //memory allocation
117 180 p2=(T*)malloc( XY * sizeof(T));
118 181 band_index(p1, page - 1);
119   - band_index(p2, page );
  182 + band_index(p2, page, PROGRESS);
120 183 for(unsigned i=0; i < XY; i++){
121 184 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
122 185 p[i] = (p2[i] - p1[i]) * r + p1[i];
... ... @@ -126,7 +189,7 @@ public:
126 189 }
127 190 else //if the wavelength is equal to a wavelength in header file
128 191 {
129   - band_index(p, page);
  192 + band_index(p, page, PROGRESS);
130 193 }
131 194  
132 195 return true;
... ... @@ -137,8 +200,8 @@ public:
137 200 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
138 201 /// @param x is the x-coordinate (dimension 1) of the spectrum.
139 202 /// @param y is the y-coordinate (dimension 2) of the spectrum.
140   - bool spectrum(T * p, unsigned x, unsigned y){
141   - return read_line_12(p, x, y); //read a line in the binary YZ plane (dimension order for BIP is ZXY)
  203 + bool spectrum(T * p, unsigned x, unsigned y, bool PROGRESS = false){
  204 + return read_line_0(p, x, y, PROGRESS); //read a line in the binary YZ plane (dimension order for BIP is ZXY)
142 205 }
143 206  
144 207 /// Retrieves a band of x values from a given xz plane.
... ... @@ -235,8 +298,8 @@ public:
235 298 /// @param n is an integer index to the pixel using linear array indexing.
236 299 bool pixel(T * p, unsigned n){
237 300  
238   - unsigned bandnum = X() * Y(); //calculate numbers in one band
239   - if ( n >= bandnum){ //make sure the pixel number is right
  301 + unsigned N = X() * Y(); //calculate numbers in one band
  302 + if ( n >= N){ //make sure the pixel number is right
240 303 std::cout<<"ERROR: sample or line out of range"<<std::endl;
241 304 return false;
242 305 }
... ... @@ -255,113 +318,57 @@ public:
255 318  
256 319 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
257 320 /// @param wls is the list of baseline points based on band labels.
258   - bool baseline(std::string outname, std::vector<double> wls){
259   -
260   - unsigned N = wls.size(); //get the number of baseline points
  321 + bool baseline(std::string outname, std::vector<double> base_pts, bool PROGRESS = false){
261 322  
262 323 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
263 324 std::string headername = outname + ".hdr"; //the header file name
264 325  
265   - //simplify image resolution
266   - unsigned int ZX = Z() * X(); //calculate the number of points in a Y slice
267   - unsigned int L = ZX * sizeof(T); //calculate the number of bytes of a Y slice
268   - unsigned int B = Z();
269   -
270   - T* c; //pointer to the current Y slice
271   - c = (T*)malloc(L); //memory allocation
272   -
273   - T* a; //pointer to the two YZ lines surrounding the current YZ line
274   - T* b;
275   -
276   - a = (T*)malloc(X() * sizeof(T));
277   - b = (T*)malloc(X() * sizeof(T));
278   -
279   -
280   - double ai, bi; //stores the two baseline points wavelength surrounding the current band
281   - double ci; //stores the current band's wavelength
282   - unsigned control;
283   -
284   - if (a == NULL || b == NULL || c == NULL){
285   - std::cout<<"ERROR: error allocating memory";
286   - exit(1);
287   - }
288   - // loop start correct every y slice
289   -
290   - for (unsigned k =0; k < Y(); k++)
291   - {
292   - //get the current y slice
293   - read_plane_y(c, k);
294   -
295   - //initialize lownum, highnum, low, high
296   - control=0;
297   - ai = w[0];
298   - //if no baseline point is specified at band 0,
299   - //set the baseline point at band 0 to 0
300   - if(wls[0] != w[0]){
301   - bi = wls[control];
302   - memset(a, (char)0, X() * sizeof(T) );
303   - }
304   - //else get the low band
305   - else{
306   - control++;
307   - read_x_from_xz(a, c, ai);
308   - bi = wls[control];
309   - }
310   - //get the high band
311   - read_x_from_xz(b, c, bi);
312   -
313   - //correct every YZ line
314   -
315   - for(unsigned cii = 0; cii < B; cii++){
316   - //update baseline points, if necessary
317   - if( w[cii] >= bi && cii != B - 1) {
318   - //if the high band is now on the last BL point?
319   - if (control != N-1) {
320   -
321   - control++; //increment the index
322   -
323   - std::swap(a, b); //swap the baseline band pointers
324   -
325   - ai = bi;
326   - bi = wls[control];
327   - read_x_from_xz(b, c, bi);
328   -
329   - }
330   - //if the last BL point on the last band of the file?
331   - else if ( wls[control] < w[B - 1]) {
332   -
333   - std::swap(a, b); //swap the baseline band pointers
334   -
335   - memset(b, (char)0, X() * sizeof(T) ); //clear the high band
336   -
337   - ai = bi;
338   - bi = w[B - 1];
339   - }
  326 + unsigned long long N = X() * Y(); //calculate the total number of pixels to be processed
  327 + unsigned long long B = Z(); //get the number of bands
  328 + T* s = (T*)malloc(sizeof(T) * B); //allocate memory to store a pixel
  329 + T* sbc = (T*)malloc(sizeof(T) * B); //allocate memory to store the baseline corrected spectrum
  330 +
  331 + std::vector<T> base_vals; //allocate space for the values at each baseline point
  332 + double aw, bw; //surrounding baseline point wavelengths
  333 + T av, bv; //surrounding baseline point values
  334 + double alpha;
  335 + unsigned long long ai, bi; //surrounding baseline point band indices
  336 + for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image
  337 + pixel(s, n); //retrieve the spectrum s
  338 + base_vals = interp_spectrum(s, base_pts); //get the values at each baseline point
  339 +
  340 + ai = bi = 0;
  341 + aw = w[0]; //initialize the current baseline points (assume the spectrum starts at 0)
  342 + av = s[0];
  343 + bw = base_pts[0];
  344 + for(unsigned long long b = 0; b < B; b++){ //for each band in the spectrum
  345 + while(bi < base_pts.size() && base_pts[bi] < w[b]) //while the current wavelength is higher than the second baseline point
  346 + bi++; //move to the next baseline point
  347 + if(bi < base_pts.size()){
  348 + bw = base_pts[bi]; //set the wavelength for the upper bound baseline point
  349 + bv = base_vals[bi]; //set the value for the upper bound baseline point
340 350 }
341   -
342   - ci = w[cii];
343   -
344   - //perform the baseline correction
345   - for(unsigned i=0; i < X(); i++)
346   - {
347   - double r = (double) (ci - ai) / (double) (bi - ai);
348   - c[i * B + cii] =(T) ( c[i * B + cii] - (b[i] - a[i]) * r - a[i] );
  351 + if(bi == base_pts.size()){ //if we have passed the last baseline point
  352 + bw = w[B-1]; //set the outer bound to the last spectral band
  353 + bv = s[B-1];
349 354 }
350   -
351   - }//loop for YZ line end
352   - target.write(reinterpret_cast<const char*>(c), L); //write the corrected data into destination
353   -
354   - thread_data = (double)k / Y() * 100;
355   - }//loop for Y slice end
  355 + if(bi != 0){
  356 + ai = bi - 1; //set the lower bound baseline point index
  357 + aw = base_pts[ai]; //set the wavelength for the lower bound baseline point
  358 + av = base_vals[ai]; //set the value for the lower bound baseline point
  359 + }
  360 + sbc[b] = s[b] - lerp(w[b], av, aw, bv, bw); //perform the baseline correction and save the new value
  361 + }
356 362  
  363 + if(PROGRESS) progress = (double)(n+1) / N * 100; //set the current progress
357 364  
  365 + target.write((char*)sbc, sizeof(T) * B); //write the corrected data into destination
  366 + } //end for each pixel
358 367  
359   - free(a);
360   - free(b);
361   - free(c);
  368 + free(s);
  369 + free(sbc);
362 370 target.close();
363   -
364   - thread_data = 100;
  371 +
365 372 return true;
366 373  
367 374 }
... ... @@ -371,80 +378,41 @@ public:
371 378 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
372 379 /// @param w is the label specifying the band that the hyperspectral image will be normalized to.
373 380 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers.
374   - bool normalize(std::string outname, double w, double t = 0.0)
  381 + bool normalize(std::string outname, double w, double t = 0.0, bool PROGRESS = false)
375 382 {
376   - unsigned int B = Z(); //calculate the number of bands
377   - unsigned int ZX = Z() * X();
378   - unsigned int XY = X() * Y(); //calculate the number of pixels in a band
379   - unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band
380   - unsigned int L = ZX * sizeof(T);
381   -
382 383 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
383   - std::string headername = outname + ".hdr"; //the header file name
384   -
385   - T * c; //pointer to the current ZX slice
386   - T * b; //pointer to the standard band
387   -
388   - b = (T*)malloc( S ); //memory allocation
389   - c = (T*)malloc( L );
390   -
391   - band(b, w); //get the certain band into memory
392   -
393   - for(unsigned j = 0; j < Y(); j++)
394   - {
395   - read_plane_y(c, j);
396   - unsigned jX = j * X(); //to avoid calculating it many times
397   - for(unsigned i = 0; i < X(); i++)
398   - {
399   - unsigned iB = i * B;
400   - for(unsigned m = 0; m < B; m++)
401   - {
402   - if( b[i+jX] < t )
403   - c[m + iB] = (T)0.0;
404   - else
405   - c[m + iB] = c[m + iB] / b[i + jX]; //perform normalization
406   - }
  384 + std::string headername = outname + ".hdr"; //the header file name
  385 +
  386 + unsigned long long N = X() * Y(); //calculate the total number of pixels to be processed
  387 + unsigned long long B = Z(); //get the number of bands
  388 + T* s = (T*)malloc(sizeof(T) * B); //allocate memory to store a pixel
  389 + T nv; //stores the value of the normalized band
  390 + for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image
  391 + pixel(s, n); //retrieve the spectrum s
  392 + nv = interp_spectrum(s, w); //find the value of the normalization band
  393 + if(abs(nv) <= t) //if the normalization band is below threshold
  394 + memset(s, 0, sizeof(T) * B); //set the output to zero
  395 + else{
  396 + for(unsigned long long b = 0; b < B; b++){ //for each band in the spectrum
  397 + s[b] /= nv; //divide by the normalization value
  398 + }
407 399 }
408   - target.write(reinterpret_cast<const char*>(c), L); //write normalized data into destination
409   -
410   - thread_data = (double) j / Y() * 100;
411   - }
  400 +
  401 + if(PROGRESS) progress = (double)(n+1) / N * 100; //set the current progress
412 402  
  403 + target.write((char*)s, sizeof(T) * B); //write the corrected data into destination
  404 + } //end for each pixel
413 405  
414   - free(b);
415   - free(c);
  406 + free(s);
416 407 target.close();
417   - thread_data = 100;
418 408 return true;
419 409 }
420 410  
421   - /// Convert the current BIP file to a BSQ file with the specified file name.
422   -
423   - /// @param outname is the name of the output BSQ file to be saved to disk.
424   - bool bsq(std::string outname)
425   - {
426   - std::string temp = outname + "_temp";
427   - std::string headtemp = temp + ".hdr";
428   - //first creat a temporary bil file and convert bip file to bil file
429   - bil(temp);
430   -
431   - stim::bil<T> n;
432   - if(n.open(temp, X(), Y(), Z(), offset, w)==false){ //open infile
433   - std::cout<<"ERROR: unable to open input file"<<std::endl;
434   - exit(1);
435   - }
436   - //then convert bil file to bsq file
437   - n.bsq(outname);
438   - n.close();
439   - remove(temp.c_str());
440   - remove(headtemp.c_str());
441   - return true;
442   - }
443 411  
444 412 /// Convert the current BIP file to a BIL file with the specified file name.
445 413  
446 414 /// @param outname is the name of the output BIL file to be saved to disk.
447   - bool bil(std::string outname)
  415 + bool bil(std::string outname, bool PROGRESS = false)
448 416 {
449 417 unsigned int S = X() * Z() * sizeof(T); //calculate the number of bytes in a ZX slice
450 418  
... ... @@ -465,13 +433,11 @@ public:
465 433 for ( unsigned j = 0; j < X(); j++)
466 434 q[ks + j] = p[k + j * Z()];
467 435  
468   - thread_data = (double)(i * Z() + k) / (Y() * Z()) * 100;
  436 + if(PROGRESS) progress = (double)(i * Z() + k+1) / (Y() * Z()) * 100;
469 437 }
470 438 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file
471 439 }
472 440  
473   - thread_data = 100;
474   -
475 441 free(p);
476 442 free(q);
477 443 target.close();
... ... @@ -909,7 +875,7 @@ public:
909 875 //write this pixel out
910 876 target.write((char *)spectrum, B * sizeof(T));
911 877  
912   - thread_data = (double) x / XY * 100;
  878 + progress = (double) x / XY * 100;
913 879 }
914 880  
915 881 }
... ... @@ -918,7 +884,7 @@ public:
918 884 target.close();
919 885 free(spectrum);
920 886  
921   - thread_data = 100;
  887 + progress = 100;
922 888  
923 889 return true;
924 890 }
... ... @@ -962,7 +928,7 @@ public:
962 928 target.write((char *)spectrum, B * sizeof(T));
963 929 }
964 930  
965   - thread_data = (double)x / XY * 100;
  931 + progress = (double)x / XY * 100;
966 932  
967 933 }
968 934  
... ... @@ -970,7 +936,7 @@ public:
970 936 target.close();
971 937 free(spectrum);
972 938  
973   - thread_data = 100;
  939 + progress = 100;
974 940  
975 941 return true;
976 942  
... ... @@ -981,7 +947,7 @@ public:
981 947  
982 948 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
983 949 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
984   - bool avg_band(double* p, unsigned char* mask = NULL){
  950 + bool avg_band(double* p, unsigned char* mask = NULL, bool PROGRESS = false){
985 951 unsigned long long XY = X() * Y();
986 952 T* temp = (T*)malloc(sizeof(T) * Z());
987 953 //Iinitialize
... ... @@ -989,12 +955,8 @@ public:
989 955 p[j] = 0;
990 956 }
991 957 //calculate vaild number in a band
992   - unsigned count = 0;
993   - for (unsigned j = 0; j < XY; j++){
994   - if (mask == NULL || mask[j] != 0){
995   - count++;
996   - }
997   - }
  958 + unsigned count = nnz(mask);
  959 +
998 960 //calculate average number of a band
999 961 for (unsigned i = 0; i < XY; i++){
1000 962 if (mask == NULL || mask[i] != 0){
... ... @@ -1003,22 +965,21 @@ public:
1003 965 p[j] += (double)temp[j] / (double)count;
1004 966 }
1005 967 }
1006   - thread_data = (double)i / XY * 100;
  968 + if(PROGRESS) progress = (double)(i+1) / XY * 100;
1007 969 }
1008 970  
1009 971 free(temp);
1010   - thread_data = 100;
1011 972 return true;
1012 973 }
1013 974 #ifdef CUDA_FOUND
1014 975 /// Calculate the covariance matrix for masked pixels using cuBLAS
1015   - bool cu_co_matrix(double* co, double* avg, unsigned char *mask){
  976 + bool co_matrix_cublas(double* co, double* avg, unsigned char *mask, bool PROGRESS = false){
1016 977  
1017 978 cudaError_t cudaStat;
1018 979 cublasStatus_t stat;
1019 980 cublasHandle_t handle;
1020 981  
1021   - thread_data = 0; //initialize the progress to zero (0)
  982 + progress = 0; //initialize the progress to zero (0)
1022 983 unsigned long long XY = X() * Y(); //calculate the number of elements in a band image
1023 984 unsigned long long B = Z(); //calculate the number of spectral elements
1024 985  
... ... @@ -1047,7 +1008,7 @@ public:
1047 1008 stat = cublasDaxpy(handle, B, &axpy_alpha, avg_dev, 1, s_dev, 1); //subtract the average spectrum
1048 1009 stat = cublasDsyr(handle, CUBLAS_FILL_MODE_UPPER, B, &ger_alpha, s_dev, 1, A_dev, B); //calculate the covariance matrix (symmetric outer product)
1049 1010 }
1050   - thread_data = (double)xy / XY * 100; //record the current progress
  1011 + if(PROGRESS) progress = (double)(xy+1) / XY * 100; //record the current progress
1051 1012  
1052 1013 }
1053 1014  
... ... @@ -1063,7 +1024,6 @@ public:
1063 1024 }
1064 1025 }
1065 1026  
1066   - thread_data = 100; //processing complete
1067 1027 return true;
1068 1028 }
1069 1029 #endif
... ... @@ -1073,23 +1033,19 @@ public:
1073 1033 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
1074 1034 /// @param avg is a pointer to memory of size B that stores the average spectrum
1075 1035 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
1076   - bool co_matrix(double* co, double* avg, unsigned char *mask){
  1036 + bool co_matrix(double* co, double* avg, unsigned char *mask, bool PROGRESS = false){
1077 1037  
1078 1038 #ifdef CUDA_FOUND
1079   - return cu_co_matrix(co, avg, mask); //if CUDA is available, use cuBLAS to calculate the covariance matrix
  1039 + return co_matrix_cublas(co, avg, mask, PROGRESS); //if CUDA is available, use cuBLAS to calculate the covariance matrix
1080 1040 #endif
1081   - thread_data = 0;
  1041 + progress = 0;
1082 1042 //memory allocation
1083 1043 unsigned long long XY = X() * Y();
1084 1044 unsigned long long B = Z();
1085 1045 T* temp = (T*)malloc(sizeof(T) * B);
1086 1046 //count vaild pixels in a band
1087   - unsigned long long count = 0;
1088   - for (unsigned long long j = 0; j < XY; j++){
1089   - if (mask == NULL || mask[j] != 0){
1090   - count++;
1091   - }
1092   - }
  1047 + unsigned long long count = nnz(mask);
  1048 +
1093 1049 //initialize covariance matrix
1094 1050 memset(co, 0, B * B * sizeof(double));
1095 1051  
... ... @@ -1110,7 +1066,7 @@ public:
1110 1066 co_half[idx++] += temp_precise[b0] * temp_precise[b1];
1111 1067 }
1112 1068 }
1113   - thread_data = (double)xy / XY * 100;
  1069 + if(PROGRESS) progress = (double)(xy+1) / XY * 100;
1114 1070 }
1115 1071 idx = 0;
1116 1072 for (unsigned long long i = 0; i < B; i++){ //copy the precision matrix to both halves of the output matrix
... ... @@ -1119,12 +1075,78 @@ public:
1119 1075 }
1120 1076 }
1121 1077  
1122   - thread_data = 100; //processing complete
1123 1078 free(temp);
1124 1079 free(temp_precise);
1125 1080 return true;
1126 1081 }
1127 1082  
  1083 + bool project(std::string outfile, double* center, double* basis, unsigned long long M, bool PROGRESS = false){
  1084 +
  1085 + std::ofstream target(outfile.c_str(), std::ios::binary); //open the target binary file
  1086 + std::string headername = outfile + ".hdr"; //the header file name
  1087 +
  1088 + //memory allocation
  1089 + unsigned long long XY = X() * Y();
  1090 + unsigned long long B = Z();
  1091 +
  1092 + T* s = (T*)malloc(sizeof(T) * B); //allocate space for the spectrum
  1093 + T* rs = (T*)malloc(sizeof(T) * M); //allocate space for the projected spectrum
  1094 + double* bv; //pointer to the current projection vector
  1095 + for(unsigned long long xy = 0; xy < XY; xy++){ //for each spectrum in the image
  1096 + pixel(s, xy); //load the spectrum
  1097 + memset(rs, 0, sizeof(T) * M); //initialize the rotated spectrum to zero (0)
  1098 + for(unsigned long long m = 0; m < M; m++){ //for each basis vector
  1099 + bv = &basis[m * B]; //assign 'bv' to the beginning of the basis vector
  1100 + for(unsigned long long b = 0; b < B; b++){ //for each band
  1101 + rs[m] += (s[b] - center[b]) * bv[b]; //center the spectrum and perform the projection
  1102 + }
  1103 + }
  1104 +
  1105 + target.write(reinterpret_cast<const char*>(rs), sizeof(T) * M); //write the projected vector
  1106 + if(PROGRESS) progress = (double)(xy+1) / XY * 100;
  1107 + }
  1108 +
  1109 + free(s); //free temporary storage arrays
  1110 + free(rs);
  1111 + target.close(); //close the output file
  1112 +
  1113 + return true;
  1114 + }
  1115 +
  1116 + bool inverse(std::string outfile, double* center, double* basis, unsigned long long B, unsigned long long C = 0, bool PROGRESS = false){
  1117 +
  1118 + std::ofstream target(outfile.c_str(), std::ios::binary); //open the target binary file
  1119 + std::string headername = outfile + ".hdr"; //the header file name
  1120 +
  1121 + //memory allocation
  1122 + unsigned long long XY = X() * Y();
  1123 + if(C == 0) C = Z(); //if no coefficient number is given, assume all are used
  1124 + C = std::min<unsigned long long>(C, Z()); //set the number of coefficients (the user can specify fewer)
  1125 +
  1126 + T* coeff = (T*)malloc(sizeof(T) * Z()); //allocate space for the coefficients
  1127 + T* s = (T*)malloc(sizeof(T) * B); //allocate space for the spectrum
  1128 + double* bv; //pointer to the current projection vector
  1129 + for(unsigned long long xy = 0; xy < XY; xy++){ //for each pixel in the image (expressed as a set of coefficients)
  1130 + pixel(coeff, xy); //load the coefficients
  1131 + memset(s, 0, sizeof(T) * B); //initialize the spectrum to zero (0)
  1132 + for(unsigned long long c = 0; c < C; c++){ //for each basis vector coefficient
  1133 + bv = &basis[c * B]; //assign 'bv' to the beginning of the basis vector
  1134 + for(unsigned long long b = 0; b < B; b++){ //for each component of the basis vector
  1135 + s[b] += coeff[c] * bv[b] + center[b]; //calculate the contribution of each element of the basis vector in the final spectrum
  1136 + }
  1137 + }
  1138 +
  1139 + target.write(reinterpret_cast<const char*>(s), sizeof(T) * B); //write the projected vector
  1140 + if(PROGRESS) progress = (double)(xy+1) / XY * 100;
  1141 + }
  1142 +
  1143 + free(coeff); //free temporary storage arrays
  1144 + free(s);
  1145 + target.close(); //close the output file
  1146 +
  1147 + return true;
  1148 + }
  1149 +
1128 1150  
1129 1151 /// Crop a region of the image and save it to a new file.
1130 1152  
... ... @@ -1138,7 +1160,8 @@ public:
1138 1160 unsigned long long x1,
1139 1161 unsigned long long y1,
1140 1162 unsigned long long b0,
1141   - unsigned long long b1){
  1163 + unsigned long long b1,
  1164 + bool PROGRESS = false){
1142 1165  
1143 1166 //calculate the new number of samples, lines, and bands
1144 1167 unsigned long long samples = x1 - x0;
... ... @@ -1180,14 +1203,13 @@ public:
1180 1203  
1181 1204 file.seekg(jump_sample, std::ios::cur);
1182 1205  
1183   - thread_data = (double)(y * samples + x) / (lines * samples) * 100;
  1206 + if(PROGRESS) progress = (double)((y+1) * samples + x + 1) / (lines * samples) * 100;
1184 1207 }
1185 1208  
1186 1209 file.seekg(jump_line, std::ios::cur);
1187 1210 }
1188 1211 free(temp);
1189 1212  
1190   - thread_data = 100;
1191 1213 return true;
1192 1214 }
1193 1215  
... ...
stim/envi/bsq.h
... ... @@ -42,13 +42,14 @@ protected:
42 42 return R[2];
43 43 }
44 44  
45   - using binary<T>::thread_data;
  45 + using binary<T>::nnz;
  46 + using binary<T>::progress;
46 47  
47 48 public:
48 49  
49 50 using binary<T>::open;
50 51 using binary<T>::file;
51   - using binary<T>::read_line_01;
  52 + using binary<T>::read_line_2;
52 53 using binary<T>::read_plane_2;
53 54 //using binary<T>::getSlice;
54 55  
... ... @@ -76,15 +77,15 @@ public:
76 77 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
77 78 /// @param page <= B is the integer number of the band to be copied.
78 79 bool band_index( T * p, unsigned int page){
79   - return read_plane_2(p, page);
  80 + return read_plane_2(p, page); //call the binary read_plane function (don't let it update the progress)
80 81 }
81 82  
82 83 /// Retrieve a single band (by numerical label) and stores it in pre-allocated memory.
83 84  
84 85 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
85 86 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied.
86   - bool band( T * p, double wavelength){
87   -
  87 + bool band( T * p, double wavelength, bool PROGRESS = false){
  88 + if(PROGRESS) progress = 0;
88 89 //if there are no wavelengths in the BSQ file
89 90 if(w.size() == 0)
90 91 return band_index(p, (unsigned int)wavelength);
... ... @@ -132,7 +133,7 @@ public:
132 133 else{
133 134 band_index(p, page); //return the band
134 135 }
135   -
  136 + if(PROGRESS) progress = 100;
136 137 return true;
137 138 }
138 139  
... ... @@ -141,8 +142,8 @@ public:
141 142 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
142 143 /// @param x is the x-coordinate (dimension 1) of the spectrum.
143 144 /// @param y is the y-coordinate (dimension 2) of the spectrum.
144   - bool spectrum(T * p, unsigned x, unsigned y){
145   - return read_line_01(p, x, y);
  145 + bool spectrum(T * p, unsigned x, unsigned y, bool PROGRESS = false){
  146 + return read_line_2(p, x, y, PROGRESS);
146 147 }
147 148  
148 149 /// Retrieve a single pixel and stores it in pre-allocated memory.
... ... @@ -171,8 +172,9 @@ public:
171 172  
172 173 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
173 174 /// @param wls is the list of baseline points based on band labels.
174   - bool baseline(std::string outname, std::vector<double> wls )
  175 + bool baseline(std::string outname, std::vector<double> wls, bool PROGRESS = false )
175 176 {
  177 + if(PROGRESS) progress = 0;
176 178 unsigned N = wls.size(); //get the number of baseline points
177 179  
178 180 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
... ... @@ -261,7 +263,7 @@ public:
261 263  
262 264 target.write(reinterpret_cast<const char*>(c), S); //write the corrected data into destination
263 265  
264   - thread_data = (double)cii / B * 100;
  266 + if(PROGRESS)progress = (double)(cii+1) / B * 100;
265 267  
266 268 }
267 269  
... ... @@ -272,7 +274,6 @@ public:
272 274 free(c);
273 275 target.close();
274 276  
275   - thread_data = 100;
276 277 return true;
277 278 }
278 279  
... ... @@ -281,7 +282,7 @@ public:
281 282 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
282 283 /// @param w is the label specifying the band that the hyperspectral image will be normalized to.
283 284 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers.
284   - bool normalize(std::string outname, double w, double t = 0.0)
  285 + bool normalize(std::string outname, double w, double t = 0.0, bool PROGRESS = false)
285 286 {
286 287 unsigned int B = Z(); //calculate the number of bands
287 288 unsigned int XY = X() * Y(); //calculate the number of pixels in a band
... ... @@ -310,7 +311,7 @@ public:
310 311 }
311 312 target.write(reinterpret_cast<const char*>(c), S); //write normalized data into destination
312 313  
313   - thread_data = (double)j / B * 100;
  314 + if(PROGRESS) progress = (double)(j+1) / B * 100;
314 315 }
315 316  
316 317  
... ... @@ -320,14 +321,13 @@ public:
320 321 free(b);
321 322 free(c);
322 323 target.close();
323   - thread_data = 100; //make sure that the progress bar is full
324 324 return true;
325 325 }
326 326  
327 327 /// Convert the current BSQ file to a BIP file with the specified file name.
328 328  
329 329 /// @param outname is the name of the output BIP file to be saved to disk.
330   - bool bip(std::string outname)
  330 + /*bool bip(std::string outname)
331 331 {
332 332 std::string temp = outname + "_temp";
333 333 std::string headtemp = temp + ".hdr";
... ... @@ -340,17 +340,18 @@ public:
340 340 exit(1);
341 341 }
342 342 //then convert bil file to bip file
  343 + progress = 0;
343 344 n.bip(outname);
344 345 n.close();
345 346 remove(temp.c_str());
346 347 remove(headtemp.c_str());
347 348 return true;
348   - }
  349 + }*/
349 350  
350 351 /// Convert the current BSQ file to a BIL file with the specified file name.
351 352  
352 353 /// @param outname is the name of the output BIL file to be saved to disk.
353   - bool bil(std::string outname)
  354 + bool bil(std::string outname, bool PROGRESS = false)
354 355 {
355 356 //simplify image resolution
356 357 unsigned int L = X() * Z() * sizeof(T); //calculate the number of bytes of a ZX slice
... ... @@ -370,17 +371,11 @@ public:
370 371 {
371 372 file.read((char *)(xz_slice + z * X()), sizeof(T) * X()); //read a line
372 373 file.seekg(jump, std::ios::cur); //seek to the next band
373   -
374   -
375   - thread_data = (double)(y * Z() + z) / (Z() * Y()) * 100; //update the progress counter
  374 + if(PROGRESS) progress = (double)(y * Z() + z + 1) / (Z() * Y()) * 100; //update the progress counter
376 375 }
377 376 target.write(reinterpret_cast<const char*>(xz_slice), xz_bytes); //write the generated XZ slice to the target file
378 377 }
379 378  
380   -
381   -
382   - thread_data = 100;
383   -
384 379 free(xz_slice);
385 380 target.close();
386 381  
... ... @@ -869,13 +864,13 @@ public:
869 864 continue;
870 865 }
871 866  
872   - thread_data = (double)(i * XY + j) / (XY * Z()) * 100;
  867 + progress = (double)(i * XY + j) / (XY * Z()) * 100;
873 868 }
874 869 }
875 870 target.close();
876 871 free(temp);
877 872  
878   - thread_data = 100;
  873 + progress = 100;
879 874  
880 875 return true;
881 876 }
... ... @@ -923,7 +918,7 @@ public:
923 918 i++;
924 919 }
925 920 //std::cout<<xi<<"/"<<XY<<", "<<b<<"/"<<B<<std::endl;
926   - thread_data = (double)(b * XY + xi) / (B * XY) * 100;
  921 + progress = (double)(b * XY + xi) / (B * XY) * 100;
927 922 }
928 923 //std::cout<<b*XY<<"/"<<B*XY<<" "<<B<<"-"<<XY<<std::endl;
929 924 //write the band image to disk
... ... @@ -931,7 +926,7 @@ public:
931 926 }
932 927  
933 928 //std::cout<<"unsifted"<<std::endl;
934   - thread_data = 100;
  929 + progress = 100;
935 930  
936 931 return true;
937 932 }
... ... @@ -963,7 +958,7 @@ public:
963 958  
964 959 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
965 960 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
966   - bool avg_band(double* p, unsigned char* mask = NULL){
  961 + bool avg_band(double* p, unsigned char* mask = NULL, bool PROGRESS = false){
967 962 unsigned long long XY = X() * Y();
968 963 unsigned long long count = 0; //count will store the number of masked pixels
969 964 T* temp = (T*)malloc(sizeof(T) * XY);
... ... @@ -983,6 +978,7 @@ public:
983 978 p[i] += (double)temp[j] / (double)count;
984 979 }
985 980 }
  981 + if(PROGRESS) progress = (double)(i+1) / Z() * 100;
986 982 }
987 983 free(temp);
988 984 return true;
... ... @@ -993,8 +989,8 @@ public:
993 989 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
994 990 /// @param avg is a pointer to memory of size B that stores the average spectrum
995 991 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
996   - bool co_matrix(double* co, double* avg, unsigned char *mask){
997   - thread_data = 0; //initialize thread data for timers and progress bars
  992 + /*bool co_matrix(double* co, double* avg, unsigned char *mask){
  993 + progress = 0; //initialize thread data for timers and progress bars
998 994 //memory allocation
999 995 unsigned long long xy = X() * Y();
1000 996 unsigned long long B = Z();
... ... @@ -1024,15 +1020,15 @@ public:
1024 1020 co[i*B + j] = numerator;
1025 1021 co[j*B + i] = numerator; //because correlated matrix is a symmetric matrix
1026 1022 }
1027   - thread_data = (double)i / B * 100;
  1023 + progress = (double)i / B * 100;
1028 1024 }
1029 1025 free(bandi);
1030 1026 free(bandj);
1031 1027  
1032   - thread_data = 100; //processing complete
  1028 + progress = 100; //processing complete
1033 1029  
1034 1030 return true;
1035   - }
  1031 + }*/
1036 1032  
1037 1033  
1038 1034 /// Crop a region of the image and save it to a new file.
... ... @@ -1047,7 +1043,8 @@ public:
1047 1043 unsigned long long x1,
1048 1044 unsigned long long y1,
1049 1045 unsigned long long b0,
1050   - unsigned long long b1){
  1046 + unsigned long long b1,
  1047 + bool PROGRESS = false){
1051 1048  
1052 1049 //calculate the new number of samples, lines, and bands
1053 1050 unsigned long long samples = x1 - x0;
... ... @@ -1080,15 +1077,13 @@ public:
1080 1077 file.read((char *)(temp + y * samples), sizeof(T) * samples);
1081 1078 file.seekg(jumpl, std::ios::cur); //go to the next band
1082 1079  
1083   - thread_data = (double)(z * lines + y) / (Z() * lines) * 100;
  1080 + if(PROGRESS) progress = (double)((z+1) * lines + y + 1) / ((b1 - b0) * lines) * 100;
1084 1081 }
1085 1082 out.write(reinterpret_cast<const char*>(temp), L); //write slice data into target file
1086 1083 file.seekg(jumpb, std::ios::cur);
1087 1084 }
1088 1085 free(temp);
1089 1086  
1090   - thread_data = 100;
1091   -
1092 1087 return true;
1093 1088 }
1094 1089  
... ...
stim/envi/envi.h
... ... @@ -37,27 +37,27 @@ public:
37 37  
38 38 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
39 39 if(header.data_type ==envi_header::float32)
40   - ((bsq<float>*)file)->reset_thread_data();
  40 + ((bsq<float>*)file)->reset_progress();
41 41 else if(header.data_type == envi_header::float64)
42   - ((bsq<double>*)file)->reset_thread_data();
  42 + ((bsq<double>*)file)->reset_progress();
43 43 else
44 44 std::cout<<"ERROR: unidentified data type"<<std::endl;
45 45 }
46 46  
47 47 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
48 48 if(header.data_type ==envi_header::float32)
49   - ((bil<float>*)file)->reset_thread_data();
  49 + ((bil<float>*)file)->reset_progress();
50 50 else if(header.data_type == envi_header::float64)
51   - ((bil<double>*)file)->reset_thread_data();
  51 + ((bil<double>*)file)->reset_progress();
52 52 else
53 53 std::cout<<"ERROR: unidentified data type"<<std::endl;
54 54 }
55 55  
56 56 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
57 57 if(header.data_type ==envi_header::float32)
58   - ((bip<float>*)file)->reset_thread_data();
  58 + ((bip<float>*)file)->reset_progress();
59 59 else if(header.data_type == envi_header::float64)
60   - ((bip<double>*)file)->reset_thread_data();
  60 + ((bip<double>*)file)->reset_progress();
61 61 else
62 62 std::cout<<"ERROR: unidentified data type"<<std::endl;
63 63 }
... ... @@ -73,27 +73,27 @@ public:
73 73  
74 74 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
75 75 if(header.data_type ==envi_header::float32)
76   - return ((bsq<float>*)file)->get_thread_data();
  76 + return ((bsq<float>*)file)->get_progress();
77 77 else if(header.data_type == envi_header::float64)
78   - return ((bsq<double>*)file)->get_thread_data();
  78 + return ((bsq<double>*)file)->get_progress();
79 79 else
80 80 std::cout<<"ERROR: unidentified data type"<<std::endl;
81 81 }
82 82  
83 83 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
84 84 if(header.data_type ==envi_header::float32)
85   - return ((bil<float>*)file)->get_thread_data();
  85 + return ((bil<float>*)file)->get_progress();
86 86 else if(header.data_type == envi_header::float64)
87   - return ((bil<double>*)file)->get_thread_data();
  87 + return ((bil<double>*)file)->get_progress();
88 88 else
89 89 std::cout<<"ERROR: unidentified data type"<<std::endl;
90 90 }
91 91  
92 92 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
93 93 if(header.data_type ==envi_header::float32)
94   - return ((bip<float>*)file)->get_thread_data();
  94 + return ((bip<float>*)file)->get_progress();
95 95 else if(header.data_type == envi_header::float64)
96   - return ((bip<double>*)file)->get_thread_data();
  96 + return ((bip<double>*)file)->get_progress();
97 97 else
98 98 std::cout<<"ERROR: unidentified data type"<<std::endl;
99 99 }
... ... @@ -213,31 +213,31 @@ public:
213 213 /// @param outfile is the name of the normalized file to be output
214 214 /// @param band is the band label to be output
215 215 /// @param threshold is a threshold value specified such that normalization will only be done to values in the band > threshold (preventing division by small numbers)
216   - bool normalize(std::string outfile, double band, double threshold = 0.0){
  216 + bool normalize(std::string outfile, double band, double threshold = 0.0, bool PROGRESS = false){
217 217  
218 218 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
219 219 if(header.data_type ==envi_header::float32)
220   - return ((bsq<float>*)file)->normalize(outfile, band, threshold);
  220 + return ((bsq<float>*)file)->normalize(outfile, band, threshold, PROGRESS);
221 221 else if(header.data_type == envi_header::float64)
222   - return ((bsq<double>*)file)->normalize(outfile,band, threshold);
  222 + return ((bsq<double>*)file)->normalize(outfile,band, threshold, PROGRESS);
223 223 else
224 224 std::cout<<"ERROR: unidentified data type"<<std::endl;
225 225 }
226 226  
227 227 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
228 228 if(header.data_type ==envi_header::float32)
229   - return ((bil<float>*)file)->normalize(outfile, band);
  229 + return ((bil<float>*)file)->normalize(outfile, band, threshold, PROGRESS);
230 230 else if(header.data_type == envi_header::float64)
231   - return ((bil<double>*)file)->normalize(outfile,band);
  231 + return ((bil<double>*)file)->normalize(outfile,band, threshold, PROGRESS);
232 232 else
233 233 std::cout<<"ERROR: unidentified data type"<<std::endl;
234 234 }
235 235  
236 236 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
237 237 if(header.data_type ==envi_header::float32)
238   - return ((bip<float>*)file)->normalize(outfile, band);
  238 + return ((bip<float>*)file)->normalize(outfile, band, threshold, PROGRESS);
239 239 else if(header.data_type == envi_header::float64)
240   - return ((bip<double>*)file)->normalize(outfile,band);
  240 + return ((bip<double>*)file)->normalize(outfile,band, threshold, PROGRESS);
241 241 else
242 242 std::cout<<"ERROR: unidentified data type"<<std::endl;
243 243 }
... ... @@ -253,13 +253,13 @@ public:
253 253  
254 254 /// @param outfile is the file name for the baseline corrected output
255 255 /// @param w is a list of band labels to serve as baseline points (zero values)
256   - bool baseline(std::string outfile, std::vector<double> w){
  256 + bool baseline(std::string outfile, std::vector<double> w, bool PROGRESS){
257 257  
258 258 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
259 259 if(header.data_type ==envi_header::float32)
260   - return ((bsq<float>*)file)->baseline(outfile, w);
  260 + return ((bsq<float>*)file)->baseline(outfile, w, PROGRESS);
261 261 else if(header.data_type == envi_header::float64)
262   - return ((bsq<double>*)file)->baseline(outfile,w);
  262 + return ((bsq<double>*)file)->baseline(outfile,w, PROGRESS);
263 263 else{
264 264 std::cout<<"ERROR: unidentified data type"<<std::endl;
265 265 exit(1);
... ... @@ -268,9 +268,9 @@ public:
268 268  
269 269 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
270 270 if(header.data_type ==envi_header::float32)
271   - return ((bil<float>*)file)->baseline(outfile, w);
  271 + return ((bil<float>*)file)->baseline(outfile, w, PROGRESS);
272 272 else if(header.data_type == envi_header::float64)
273   - return ((bil<double>*)file)->baseline(outfile, w);
  273 + return ((bil<double>*)file)->baseline(outfile, w, PROGRESS);
274 274 else{
275 275 std::cout<<"ERROR: unidentified data type"<<std::endl;
276 276 exit(1);
... ... @@ -279,9 +279,9 @@ public:
279 279  
280 280 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
281 281 if(header.data_type ==envi_header::float32)
282   - return ((bip<float>*)file)->baseline(outfile, w);
  282 + return ((bip<float>*)file)->baseline(outfile, w, PROGRESS);
283 283 else if(header.data_type == envi_header::float64)
284   - return ((bip<double>*)file)->baseline(outfile, w);
  284 + return ((bip<double>*)file)->baseline(outfile, w, PROGRESS);
285 285 else{
286 286 std::cout<<"ERROR: unidentified data type"<<std::endl;
287 287 exit(1);
... ... @@ -294,11 +294,65 @@ public:
294 294 }
295 295 }
296 296  
  297 + void project(std::string outfile, double* center, double* basis, unsigned long long M, bool PROGRESS = false){
  298 + if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
  299 + std::cout<<"ERROR: BSQ projection not supported"<<std::endl;
  300 + exit(1);
  301 + }
  302 +
  303 + else if(header.interleave == envi_header::BIL){ //if the infile is bil file
  304 + std::cout<<"ERROR: BIL projection not supported"<<std::endl;
  305 + exit(1);
  306 + }
  307 +
  308 + else if(header.interleave == envi_header::BIP){ //if the infile is bip file
  309 + if(header.data_type ==envi_header::float32)
  310 + ((bip<float>*)file)->project(outfile, center, basis, M, PROGRESS);
  311 + else if(header.data_type == envi_header::float64)
  312 + ((bip<double>*)file)->project(outfile, center, basis, M, PROGRESS);
  313 + else{
  314 + std::cout<<"ERROR: unidentified data type"<<std::endl;
  315 + exit(1);
  316 + }
  317 + }
  318 +
  319 + stim::envi_header out_hdr = header;
  320 + out_hdr.bands = M; //set the number of bands in the output header
  321 + out_hdr.save(outfile + ".hdr"); //save the output header
  322 + }
  323 +
  324 + void inverse(std::string outfile, double* center, double* basis, unsigned long long B, unsigned long long C = 0, bool PROGRESS = false){
  325 + if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
  326 + std::cout<<"ERROR: BSQ projection not supported"<<std::endl;
  327 + exit(1);
  328 + }
  329 +
  330 + else if(header.interleave == envi_header::BIL){ //if the infile is bil file
  331 + std::cout<<"ERROR: BIL projection not supported"<<std::endl;
  332 + exit(1);
  333 + }
  334 +
  335 + else if(header.interleave == envi_header::BIP){ //if the infile is bip file
  336 + if(header.data_type ==envi_header::float32)
  337 + ((bip<float>*)file)->inverse(outfile, center, basis, B, C, PROGRESS);
  338 + else if(header.data_type == envi_header::float64)
  339 + ((bip<double>*)file)->inverse(outfile, center, basis, B, C, PROGRESS);
  340 + else{
  341 + std::cout<<"ERROR: unidentified data type"<<std::endl;
  342 + exit(1);
  343 + }
  344 + }
  345 +
  346 + stim::envi_header out_hdr = header;
  347 + out_hdr.bands = B; //set the number of bands in the output header
  348 + out_hdr.save(outfile + ".hdr"); //save the output header
  349 + }
  350 +
297 351 /// Converts ENVI files between interleave types (BSQ, BIL, and BIP)
298 352  
299 353 /// @param outfile is the file name for the converted output
300 354 /// @param interleave is the interleave format for the destination file
301   - bool convert(std::string outfile, stim::envi_header::interleaveType interleave){
  355 + bool convert(std::string outfile, stim::envi_header::interleaveType interleave, bool PROGRESS = false){
302 356  
303 357 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
304 358  
... ... @@ -308,9 +362,12 @@ public:
308 362 exit(1);
309 363 }
310 364 else if(interleave == envi_header::BIL) //if the target file is bil file
311   - return ((bsq<float>*)file)->bil(outfile);
312   - else if(interleave == envi_header::BIP) //if the target file is bip file
313   - return ((bsq<float>*)file)->bip(outfile);
  365 + return ((bsq<float>*)file)->bil(outfile, PROGRESS);
  366 + else if(interleave == envi_header::BIP){ //if the target file is bip file
  367 + std::cout<<"ERROR: conversion from BSQ to BIP isn't practical; use BSQ->BIL->BIP instead"<<std::endl;
  368 + //return ((bsq<float>*)file)->bip(outfile, PROGRESS);
  369 + exit(1);
  370 + }
314 371 }
315 372  
316 373 else if(header.data_type == envi_header::float64){ //if the data type is float
... ... @@ -319,9 +376,12 @@ public:
319 376 exit(1);
320 377 }
321 378 else if(interleave == envi_header::BIL)
322   - return ((bsq<double>*)file)->bil(outfile);
323   - else if(interleave == envi_header::BIP)
324   - return ((bsq<double>*)file)->bip(outfile);
  379 + return ((bsq<double>*)file)->bil(outfile, PROGRESS);
  380 + else if(interleave == envi_header::BIP){ //if the target file is bip file
  381 + std::cout<<"ERROR: conversion from BSQ to BIP isn't practical; use BSQ->BIL->BIP instead"<<std::endl;
  382 + //return ((bsq<float>*)file)->bip(outfile, PROGRESS);
  383 + exit(1);
  384 + }
325 385 }
326 386  
327 387 else{
... ... @@ -338,9 +398,9 @@ public:
338 398 exit(1);
339 399 }
340 400 else if(interleave == envi_header::BSQ) //if the target file is bsq file
341   - return ((bil<float>*)file)->bsq(outfile);
  401 + return ((bil<float>*)file)->bsq(outfile, PROGRESS);
342 402 else if(interleave == envi_header::BIP) //if the target file is bip file
343   - return ((bil<float>*)file)->bip(outfile);
  403 + return ((bil<float>*)file)->bip(outfile, PROGRESS);
344 404 }
345 405  
346 406 else if(header.data_type == envi_header::float64){ //if the data type is float
... ... @@ -349,9 +409,9 @@ public:
349 409 exit(1);
350 410 }
351 411 else if(interleave == envi_header::BSQ)
352   - return ((bil<double>*)file)->bsq(outfile);
  412 + return ((bil<double>*)file)->bsq(outfile, PROGRESS);
353 413 else if(interleave == envi_header::BIP)
354   - return ((bil<double>*)file)->bip(outfile);
  414 + return ((bil<double>*)file)->bip(outfile, PROGRESS);
355 415 }
356 416  
357 417 else{
... ... @@ -368,9 +428,12 @@ public:
368 428 exit(1);
369 429 }
370 430 else if(interleave == envi_header::BIL) //if the target file is bil file
371   - return ((bip<float>*)file)->bil(outfile);
372   - else if(interleave == envi_header::BSQ) //if the target file is bsq file
373   - return ((bip<float>*)file)->bsq(outfile);
  431 + return ((bip<float>*)file)->bil(outfile, PROGRESS);
  432 + else if(interleave == envi_header::BSQ){ //if the target file is bip file
  433 + std::cout<<"ERROR: conversion from BIP to BSQ isn't practical; use BIP->BIL->BSQ instead"<<std::endl;
  434 + //return ((bsq<float>*)file)->bip(outfile, PROGRESS);
  435 + exit(1);
  436 + }
374 437 }
375 438  
376 439 else if(header.data_type == envi_header::float64){ //if the data type is float
... ... @@ -379,9 +442,12 @@ public:
379 442 exit(1);
380 443 }
381 444 else if(interleave == envi_header::BIL) //if the target file is bil file
382   - return ((bip<double>*)file)->bil(outfile);
383   - else if(interleave == envi_header::BSQ) //if the target file is bsq file
384   - return ((bip<double>*)file)->bsq(outfile);
  445 + return ((bip<double>*)file)->bil(outfile, PROGRESS);
  446 + else if(interleave == envi_header::BSQ){ //if the target file is bip file
  447 + std::cout<<"ERROR: conversion from BIP to BSQ isn't practical; use BIP->BIL->BSQ instead"<<std::endl;
  448 + //return ((bsq<float>*)file)->bip(outfile, PROGRESS);
  449 + exit(1);
  450 + }
385 451 }
386 452  
387 453 else{
... ... @@ -872,13 +938,13 @@ public:
872 938  
873 939 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
874 940 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied.
875   - bool band(void* ptr, double wavelength){
  941 + bool band(void* ptr, double wavelength, bool PROGRESS = false){
876 942  
877 943 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
878 944 if(header.data_type ==envi_header::float32)
879   - return ((bsq<float>*)file)->band((float*)ptr, wavelength);
  945 + return ((bsq<float>*)file)->band((float*)ptr, wavelength, PROGRESS);
880 946 else if (header.data_type == envi_header::float64)
881   - return ((bsq<double>*)file)->band((double*)ptr, wavelength);
  947 + return ((bsq<double>*)file)->band((double*)ptr, wavelength, PROGRESS);
882 948 else{
883 949 std::cout << "ERROR: unidentified data type" << std::endl;
884 950 exit(1);
... ... @@ -886,9 +952,9 @@ public:
886 952 }
887 953 else if (header.interleave == envi_header::BIL){
888 954 if (header.data_type == envi_header::float32)
889   - return ((bil<float>*)file)->band((float*)ptr, wavelength);
  955 + return ((bil<float>*)file)->band((float*)ptr, wavelength, PROGRESS);
890 956 else if (header.data_type == envi_header::float64)
891