Commit 63fc1df8ebee680b2a16a6709d79f05e2dffe90b

Authored by David Mayerich
1 parent 371bf339

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

@@ -35,7 +35,12 @@ protected: @@ -35,7 +35,12 @@ protected:
35 return R[1]; 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 public: 45 public:
41 46
@@ -63,9 +68,10 @@ public: @@ -63,9 +68,10 @@ public:
63 68
64 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 69 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
65 /// @param page <= B is the integer number of the band to be copied. 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 //return binary<T>::read_plane_1(p, page); 72 //return binary<T>::read_plane_1(p, page);
68 73
  74 + if(PROGRESS) progress = 0;
69 unsigned int L = X() * sizeof(T); //caculate the number of bytes in a sample line 75 unsigned int L = X() * sizeof(T); //caculate the number of bytes in a sample line
70 unsigned int jump = X() * (Z() - 1) * sizeof(T); 76 unsigned int jump = X() * (Z() - 1) * sizeof(T);
71 77
@@ -79,6 +85,7 @@ public: @@ -79,6 +85,7 @@ public:
79 { 85 {
80 file.read((char *)(p + i * X()), L); 86 file.read((char *)(p + i * X()), L);
81 file.seekg( jump, std::ios::cur); 87 file.seekg( jump, std::ios::cur);
  88 + if(PROGRESS) progress = (double)(i+1) / Y() * 100;
82 } 89 }
83 90
84 return true; 91 return true;
@@ -88,7 +95,7 @@ public: @@ -88,7 +95,7 @@ public:
88 95
89 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 96 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
90 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied. 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 //if there are no wavelengths in the BSQ file 100 //if there are no wavelengths in the BSQ file
94 if(w.size() == 0) 101 if(w.size() == 0)
@@ -104,7 +111,7 @@ public: @@ -104,7 +111,7 @@ public:
104 111
105 //if wavelength is smaller than the first one in header file 112 //if wavelength is smaller than the first one in header file
106 if ( w[page] > wavelength ){ 113 if ( w[page] > wavelength ){
107 - band_index(p, page); 114 + band_index(p, page, PROGRESS);
108 return true; 115 return true;
109 } 116 }
110 117
@@ -124,7 +131,7 @@ public: @@ -124,7 +131,7 @@ public:
124 p1=(T*)malloc(S); //memory allocation 131 p1=(T*)malloc(S); //memory allocation
125 p2=(T*)malloc(S); 132 p2=(T*)malloc(S);
126 band_index(p1, page - 1); 133 band_index(p1, page - 1);
127 - band_index(p2, page ); 134 + band_index(p2, page, PROGRESS);
128 for(unsigned i=0; i < XY; i++){ 135 for(unsigned i=0; i < XY; i++){
129 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); 136 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
130 p[i] = (p2[i] - p1[i]) * r + p1[i]; 137 p[i] = (p2[i] - p1[i]) * r + p1[i];
@@ -134,7 +141,7 @@ public: @@ -134,7 +141,7 @@ public:
134 } 141 }
135 else //if the wavelength is equal to a wavelength in header file 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 return true; 147 return true;
@@ -195,8 +202,8 @@ public: @@ -195,8 +202,8 @@ public:
195 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. 202 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
196 /// @param x is the x-coordinate (dimension 1) of the spectrum. 203 /// @param x is the x-coordinate (dimension 1) of the spectrum.
197 /// @param y is the y-coordinate (dimension 2) of the spectrum. 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 /// Retrieve a single pixel and stores it in pre-allocated memory. 209 /// Retrieve a single pixel and stores it in pre-allocated memory.
@@ -223,7 +230,7 @@ public: @@ -223,7 +230,7 @@ public:
223 230
224 /// @param outname is the name of the output file used to store the resulting baseline-corrected data. 231 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
225 /// @param wls is the list of baseline points based on band labels. 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 unsigned N = wls.size(); //get the number of baseline points 235 unsigned N = wls.size(); //get the number of baseline points
229 236
@@ -321,7 +328,7 @@ public: @@ -321,7 +328,7 @@ public:
321 }//loop for YZ line end 328 }//loop for YZ line end
322 target.write(reinterpret_cast<const char*>(c), L); //write the corrected data into destination 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 }//loop for Y slice end 332 }//loop for Y slice end
326 333
327 free(a); 334 free(a);
@@ -329,8 +336,6 @@ public: @@ -329,8 +336,6 @@ public:
329 free(c); 336 free(c);
330 target.close(); 337 target.close();
331 338
332 - thread_data = 100;  
333 -  
334 return true; 339 return true;
335 340
336 } 341 }
@@ -340,7 +345,7 @@ public: @@ -340,7 +345,7 @@ public:
340 /// @param outname is the name of the output file used to store the resulting baseline-corrected data. 345 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
341 /// @param w is the label specifying the band that the hyperspectral image will be normalized to. 346 /// @param w is the label specifying the band that the hyperspectral image will be normalized to.
342 /// @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. 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 unsigned int B = Z(); //calculate the number of bands 350 unsigned int B = Z(); //calculate the number of bands
346 unsigned int ZX = Z() * X(); 351 unsigned int ZX = Z() * X();
@@ -374,20 +379,19 @@ public: @@ -374,20 +379,19 @@ public:
374 } 379 }
375 target.write(reinterpret_cast<const char*>(c), L); //write normalized data into destination 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 free(b); 385 free(b);
381 free(c); 386 free(c);
382 target.close(); 387 target.close();
383 - thread_data = 100;  
384 return true; 388 return true;
385 } 389 }
386 390
387 /// Convert the current BIL file to a BSQ file with the specified file name. 391 /// Convert the current BIL file to a BSQ file with the specified file name.
388 392
389 /// @param outname is the name of the output BSQ file to be saved to disk. 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 unsigned int S = X() * Y() * sizeof(T); //calculate the number of bytes in a band 396 unsigned int S = X() * Y() * sizeof(T); //calculate the number of bytes in a band
393 397
@@ -402,11 +406,9 @@ public: @@ -402,11 +406,9 @@ public:
402 band_index(p, i); 406 band_index(p, i);
403 target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file 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 free(p); 412 free(p);
411 target.close(); 413 target.close();
412 return true; 414 return true;
@@ -415,7 +417,7 @@ public: @@ -415,7 +417,7 @@ public:
415 /// Convert the current BIL file to a BIP file with the specified file name. 417 /// Convert the current BIL file to a BIP file with the specified file name.
416 418
417 /// @param outname is the name of the output BIP file to be saved to disk. 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 unsigned int S = X() * Z() * sizeof(T); //calculate the number of bytes in a ZX slice 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,15 +438,12 @@ public:
436 for ( unsigned j = 0; j < X(); j++) 438 for ( unsigned j = 0; j < X(); j++)
437 q[k + j * Z()] = p[ks + j]; 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 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file 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 free(p); 447 free(p);
449 free(q); 448 free(q);
450 target.close(); 449 target.close();
@@ -879,14 +878,14 @@ public: @@ -879,14 +878,14 @@ public:
879 target.write((char*)spec, B * sizeof(T)); //write that spectrum to disk. Size is L2. 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 target.close(); 884 target.close();
886 free(slice); 885 free(slice);
887 free(spec); 886 free(spec);
888 887
889 - thread_data = 100; 888 + progress = 100;
890 return true; 889 return true;
891 } 890 }
892 891
@@ -923,7 +922,7 @@ public: @@ -923,7 +922,7 @@ public:
923 922
924 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum 923 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
925 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 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 unsigned long long XZ = X() * Z(); 926 unsigned long long XZ = X() * Z();
928 unsigned long long XY = X() * Y(); 927 unsigned long long XY = X() * Y();
929 T* temp = (T*)malloc(sizeof(T) * XZ); 928 T* temp = (T*)malloc(sizeof(T) * XZ);
@@ -947,6 +946,7 @@ public: @@ -947,6 +946,7 @@ public:
947 } 946 }
948 } 947 }
949 } 948 }
  949 + if(PROGRESS) progress = (double)(k+1) / Y() * 100;
950 } 950 }
951 free(temp); 951 free(temp);
952 return true; 952 return true;
@@ -957,8 +957,8 @@ public: @@ -957,8 +957,8 @@ public:
957 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix 957 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
958 /// @param avg is a pointer to memory of size B that stores the average spectrum 958 /// @param avg is a pointer to memory of size B that stores the average spectrum
959 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 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 //memory allocation 962 //memory allocation
963 unsigned long long xy = X() * Y(); 963 unsigned long long xy = X() * Y();
964 unsigned long long B = Z(); 964 unsigned long long B = Z();
@@ -986,7 +986,7 @@ public: @@ -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 //because correlation matrix is symmetric 991 //because correlation matrix is symmetric
992 for (unsigned long long i = 0; i < B; i++){ 992 for (unsigned long long i = 0; i < B; i++){
@@ -996,9 +996,6 @@ public: @@ -996,9 +996,6 @@ public:
996 } 996 }
997 997
998 free(temp); 998 free(temp);
999 -  
1000 - thread_data = 100; //processing complete  
1001 -  
1002 return true; 999 return true;
1003 } 1000 }
1004 1001
@@ -1015,7 +1012,8 @@ public: @@ -1015,7 +1012,8 @@ public:
1015 unsigned long long x1, 1012 unsigned long long x1,
1016 unsigned long long y1, 1013 unsigned long long y1,
1017 unsigned long long b0, 1014 unsigned long long b0,
1018 - unsigned long long b1){ 1015 + unsigned long long b1,
  1016 + bool PROGRESS = false){
1019 1017
1020 //calculate the new image parameters 1018 //calculate the new image parameters
1021 unsigned long long samples = x1 - x0; 1019 unsigned long long samples = x1 - x0;
@@ -1048,7 +1046,7 @@ public: @@ -1048,7 +1046,7 @@ public:
1048 file.read((char *)(temp + z * samples), sizeof(T) * samples); 1046 file.read((char *)(temp + z * samples), sizeof(T) * samples);
1049 file.seekg(jumpb, std::ios::cur); //go to the next band 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 //write slice data into target file 1052 //write slice data into target file
@@ -1061,8 +1059,6 @@ public: @@ -1061,8 +1059,6 @@ public:
1061 //free the temporary frame 1059 //free the temporary frame
1062 free(temp); 1060 free(temp);
1063 1061
1064 - thread_data = 100;  
1065 -  
1066 return true; 1062 return true;
1067 } 1063 }
1068 1064
stim/envi/binary.h
@@ -24,11 +24,11 @@ protected: @@ -24,11 +24,11 @@ protected:
24 std::fstream file; //file stream used for reading and writing 24 std::fstream file; //file stream used for reading and writing
25 std::string name; //file name 25 std::string name; //file name
26 26
27 - unsigned long long int R[D]; //resolution 27 + unsigned long long R[D]; //resolution
28 unsigned int header; //header size (in bytes) 28 unsigned int header; //header size (in bytes)
29 unsigned char* mask; //pointer to a character array: 0 = background, 1 = foreground (or valid data) 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 /// Private initialization function used to set default parameters in the data structure. 34 /// Private initialization function used to set default parameters in the data structure.
@@ -37,7 +37,24 @@ protected: @@ -37,7 +37,24 @@ protected:
37 header = 0; //initialize the header size to zero 37 header = 0; //initialize the header size to zero
38 mask = NULL; 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 /// Private helper function that returns the size of the file on disk using system functions. 60 /// Private helper function that returns the size of the file on disk using system functions.
@@ -105,12 +122,12 @@ protected: @@ -105,12 +122,12 @@ protected:
105 122
106 public: 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 /// Open a binary file for streaming. 133 /// Open a binary file for streaming.
@@ -178,7 +195,9 @@ public: @@ -178,7 +195,9 @@ public:
178 195
179 /// @param p is a pointer to pre-allocated memory equal to the page size 196 /// @param p is a pointer to pre-allocated memory equal to the page size
180 /// @param page is the index of the page 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 if (page >= R[2]){ //make sure the bank number is right 202 if (page >= R[2]){ //make sure the bank number is right
184 std::cout<<"ERROR: page out of range"<<std::endl; 203 std::cout<<"ERROR: page out of range"<<std::endl;
@@ -187,7 +206,7 @@ public: @@ -187,7 +206,7 @@ public:
187 206
188 file.seekg(R[1] * R[0] * page * sizeof(T) + header, std::ios::beg); //write into memory from the binary file 207 file.seekg(R[1] * R[0] * page * sizeof(T) + header, std::ios::beg); //write into memory from the binary file
189 file.read((char *)p, R[0] * R[1] * sizeof(T)); 208 file.read((char *)p, R[0] * R[1] * sizeof(T));
190 - 209 + if(PROGRESS) progress = 100;
191 return true; 210 return true;
192 } 211 }
193 212
@@ -198,9 +217,11 @@ public: @@ -198,9 +217,11 @@ public:
198 /// @param p is a pointer to pre-allocated memory equal to the line size R[2] 217 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
199 /// @param x is the x coordinate 218 /// @param x is the x coordinate
200 /// @param y is the y coordinate 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 unsigned int i; 221 unsigned int i;
203 222
  223 + if(PROGRESS) progress = 0;
  224 +
204 if ( x >= R[0] || y >= R[1]){ //make sure the sample and line number is right 225 if ( x >= R[0] || y >= R[1]){ //make sure the sample and line number is right
205 std::cout<<"ERROR: sample or line out of range"<<std::endl; 226 std::cout<<"ERROR: sample or line out of range"<<std::endl;
206 return false; 227 return false;
@@ -211,7 +232,9 @@ public: @@ -211,7 +232,9 @@ public:
211 { 232 {
212 file.read((char *)(p + i), sizeof(T)); 233 file.read((char *)(p + i), sizeof(T));
213 file.seekg((R[1] * R[0] - 1) * sizeof(T), std::ios::cur); //go to the next band 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 return true; 239 return true;
217 } 240 }
@@ -221,7 +244,7 @@ public: @@ -221,7 +244,7 @@ public:
221 /// @param p is a pointer to pre-allocated memory equal to the line size R[2] 244 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
222 /// @param x is the y coordinate 245 /// @param x is the y coordinate
223 /// @param y is the z coordinate 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 //test to make sure the specified value is within range 248 //test to make sure the specified value is within range
226 if( y >= R[1] || z >= R[2] ){ 249 if( y >= R[1] || z >= R[2] ){
227 std::cout<<"ERROR: sample or line out of range"<<std::endl; 250 std::cout<<"ERROR: sample or line out of range"<<std::endl;
@@ -230,7 +253,7 @@ public: @@ -230,7 +253,7 @@ public:
230 253
231 file.seekg((z * R[0] * R[1] + y * R[0]) * sizeof(T), std::ios::beg); //seek to the start of the line 254 file.seekg((z * R[0] * R[1] + y * R[0]) * sizeof(T), std::ios::beg); //seek to the start of the line
232 file.read((char *)p, sizeof(T) * R[0]); //read the line 255 file.read((char *)p, sizeof(T) * R[0]); //read the line
233 - 256 + if(PROGRESS) progress = 100;
234 return true; 257 return true;
235 } 258 }
236 259
@@ -239,7 +262,8 @@ public: @@ -239,7 +262,8 @@ public:
239 /// @param p is a pointer to pre-allocated memory equal to the line size R[2] 262 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
240 /// @param x is the y coordinate 263 /// @param x is the y coordinate
241 /// @param z is the z coordinate 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 //test to make sure the specified value is within range 267 //test to make sure the specified value is within range
244 if( x >= R[0] || z >= R[2] ){ 268 if( x >= R[0] || z >= R[2] ){
245 std::cout<<"ERROR: sample or line out of range"<<std::endl; 269 std::cout<<"ERROR: sample or line out of range"<<std::endl;
@@ -250,8 +274,9 @@ public: @@ -250,8 +274,9 @@ public:
250 for (unsigned int i = 0; i < R[1]; i++){ //for each pixel in the line 274 for (unsigned int i = 0; i < R[1]; i++){ //for each pixel in the line
251 file.read((char *)(p + i), sizeof(T)); //read the pixel 275 file.read((char *)(p + i), sizeof(T)); //read the pixel
252 file.seekg((R[0] - 1) * sizeof(T), std::ios::cur); //seek to the next pixel in the line 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 return true; 280 return true;
256 } 281 }
257 282
@@ -259,8 +284,8 @@ public: @@ -259,8 +284,8 @@ public:
259 284
260 /// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T) 285 /// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T)
261 /// @param n is the 0-axis coordinate used to retrieve the plane 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 if (n >= R[0]){ //make sure the number is within the possible range 289 if (n >= R[0]){ //make sure the number is within the possible range
265 std::cout<<"ERROR read_plane_0: page out of range"<<std::endl; 290 std::cout<<"ERROR read_plane_0: page out of range"<<std::endl;
266 return false; 291 return false;
@@ -274,10 +299,10 @@ public: @@ -274,10 +299,10 @@ public:
274 for(unsigned int i = 0; i<N; i++){ 299 for(unsigned int i = 0; i<N; i++){
275 file.read((char*)(p+i), sizeof(T)); 300 file.read((char*)(p+i), sizeof(T));
276 file.seekg(jump, std::ios::cur); 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 return true; 306 return true;
282 307
283 308
@@ -287,8 +312,8 @@ public: @@ -287,8 +312,8 @@ public:
287 312
288 /// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T) 313 /// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T)
289 /// @param n is the 1-axis coordinate used to retrieve the plane 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 unsigned int L = R[0] * sizeof(T); //caculate the number of bytes in a sample line 317 unsigned int L = R[0] * sizeof(T); //caculate the number of bytes in a sample line
293 unsigned int jump = R[0] * (R[1] - 1) * sizeof(T); 318 unsigned int jump = R[0] * (R[1] - 1) * sizeof(T);
294 319
@@ -299,13 +324,13 @@ public: @@ -299,13 +324,13 @@ public:
299 324
300 file.seekg(R[0] * n * sizeof(T), std::ios::beg); 325 file.seekg(R[0] * n * sizeof(T), std::ios::beg);
301 for (unsigned i = 0; i < R[2]; i++){ 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 file.read((char *)(p + i * R[0]), L); 328 file.read((char *)(p + i * R[0]), L);
304 file.seekg( jump, std::ios::cur); 329 file.seekg( jump, std::ios::cur);
305 std::cout<<i<<" "; 330 std::cout<<i<<" ";
306 } 331 }
307 332
308 - thread_data = 100; 333 + if(PROGRESS) progress = 100;
309 return true; 334 return true;
310 } 335 }
311 336
@@ -313,8 +338,8 @@ public: @@ -313,8 +338,8 @@ public:
313 338
314 /// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T) 339 /// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T)
315 /// @param n is the 2-axis coordinate used to retrieve the plane 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 /// Reads a single pixel, treating the entire data set as a linear array 345 /// Reads a single pixel, treating the entire data set as a linear array
@@ -41,14 +41,77 @@ protected: @@ -41,14 +41,77 @@ protected:
41 return R[0]; 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 public: 109 public:
47 110
48 using binary<T>::open; 111 using binary<T>::open;
49 using binary<T>::file; 112 using binary<T>::file;
50 using binary<T>::R; 113 using binary<T>::R;
51 - using binary<T>::read_line_12; 114 + using binary<T>::read_line_0;
52 115
53 /// Open a data file for reading using the class interface. 116 /// Open a data file for reading using the class interface.
54 117
@@ -73,19 +136,19 @@ public: @@ -73,19 +136,19 @@ public:
73 136
74 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 137 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
75 /// @param page <= B is the integer number of the band to be copied. 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 /// Retrieve a single band (by numerical label) and stores it in pre-allocated memory. 143 /// Retrieve a single band (by numerical label) and stores it in pre-allocated memory.
81 144
82 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 145 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
83 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied. 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 //if there are no wavelengths in the BSQ file 149 //if there are no wavelengths in the BSQ file
87 if(w.size() == 0) 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 unsigned int XY = X() * Y(); //calculate the number of pixels in a band 153 unsigned int XY = X() * Y(); //calculate the number of pixels in a band
91 154
@@ -96,7 +159,7 @@ public: @@ -96,7 +159,7 @@ public:
96 159
97 //if wavelength is smaller than the first one in header file 160 //if wavelength is smaller than the first one in header file
98 if ( w[page] > wavelength ){ 161 if ( w[page] > wavelength ){
99 - band_index(p, page); 162 + band_index(p, page, PROGRESS);
100 return true; 163 return true;
101 } 164 }
102 165
@@ -105,7 +168,7 @@ public: @@ -105,7 +168,7 @@ public:
105 page++; 168 page++;
106 //if wavelength is larger than the last wavelength in header file 169 //if wavelength is larger than the last wavelength in header file
107 if (page == Z()) { 170 if (page == Z()) {
108 - band_index(p, Z()-1); 171 + band_index(p, Z()-1, PROGRESS);
109 return true; 172 return true;
110 } 173 }
111 } 174 }
@@ -116,7 +179,7 @@ public: @@ -116,7 +179,7 @@ public:
116 p1=(T*)malloc( XY * sizeof(T)); //memory allocation 179 p1=(T*)malloc( XY * sizeof(T)); //memory allocation
117 p2=(T*)malloc( XY * sizeof(T)); 180 p2=(T*)malloc( XY * sizeof(T));
118 band_index(p1, page - 1); 181 band_index(p1, page - 1);
119 - band_index(p2, page ); 182 + band_index(p2, page, PROGRESS);
120 for(unsigned i=0; i < XY; i++){ 183 for(unsigned i=0; i < XY; i++){
121 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); 184 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
122 p[i] = (p2[i] - p1[i]) * r + p1[i]; 185 p[i] = (p2[i] - p1[i]) * r + p1[i];
@@ -126,7 +189,7 @@ public: @@ -126,7 +189,7 @@ public:
126 } 189 }
127 else //if the wavelength is equal to a wavelength in header file 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 return true; 195 return true;
@@ -137,8 +200,8 @@ public: @@ -137,8 +200,8 @@ public:
137 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. 200 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
138 /// @param x is the x-coordinate (dimension 1) of the spectrum. 201 /// @param x is the x-coordinate (dimension 1) of the spectrum.
139 /// @param y is the y-coordinate (dimension 2) of the spectrum. 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 /// Retrieves a band of x values from a given xz plane. 207 /// Retrieves a band of x values from a given xz plane.
@@ -235,8 +298,8 @@ public: @@ -235,8 +298,8 @@ public:
235 /// @param n is an integer index to the pixel using linear array indexing. 298 /// @param n is an integer index to the pixel using linear array indexing.
236 bool pixel(T * p, unsigned n){ 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 std::cout<<"ERROR: sample or line out of range"<<std::endl; 303 std::cout<<"ERROR: sample or line out of range"<<std::endl;
241 return false; 304 return false;
242 } 305 }
@@ -255,113 +318,57 @@ public: @@ -255,113 +318,57 @@ public:
255 318
256 /// @param outname is the name of the output file used to store the resulting baseline-corrected data. 319 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
257 /// @param wls is the list of baseline points based on band labels. 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 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 323 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
263 std::string headername = outname + ".hdr"; //the header file name 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 target.close(); 370 target.close();
363 -  
364 - thread_data = 100; 371 +
365 return true; 372 return true;
366 373
367 } 374 }
@@ -371,80 +378,41 @@ public: @@ -371,80 +378,41 @@ public:
371 /// @param outname is the name of the output file used to store the resulting baseline-corrected data. 378 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
372 /// @param w is the label specifying the band that the hyperspectral image will be normalized to. 379 /// @param w is the label specifying the band that the hyperspectral image will be normalized to.
373 /// @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. 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 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 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 target.close(); 407 target.close();
417 - thread_data = 100;  
418 return true; 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 /// Convert the current BIP file to a BIL file with the specified file name. 412 /// Convert the current BIP file to a BIL file with the specified file name.
445 413
446 /// @param outname is the name of the output BIL file to be saved to disk. 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 unsigned int S = X() * Z() * sizeof(T); //calculate the number of bytes in a ZX slice 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,13 +433,11 @@ public:
465 for ( unsigned j = 0; j < X(); j++) 433 for ( unsigned j = 0; j < X(); j++)
466 q[ks + j] = p[k + j * Z()]; 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 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file 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 free(p); 441 free(p);
476 free(q); 442 free(q);
477 target.close(); 443 target.close();
@@ -909,7 +875,7 @@ public: @@ -909,7 +875,7 @@ public:
909 //write this pixel out 875 //write this pixel out
910 target.write((char *)spectrum, B * sizeof(T)); 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,7 +884,7 @@ public:
918 target.close(); 884 target.close();
919 free(spectrum); 885 free(spectrum);
920 886
921 - thread_data = 100; 887 + progress = 100;
922 888
923 return true; 889 return true;
924 } 890 }
@@ -962,7 +928,7 @@ public: @@ -962,7 +928,7 @@ public:
962 target.write((char *)spectrum, B * sizeof(T)); 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,7 +936,7 @@ public:
970 target.close(); 936 target.close();
971 free(spectrum); 937 free(spectrum);
972 938
973 - thread_data = 100; 939 + progress = 100;
974 940
975 return true; 941 return true;
976 942
@@ -981,7 +947,7 @@ public: @@ -981,7 +947,7 @@ public:
981 947
982 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum 948 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
983 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 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 unsigned long long XY = X() * Y(); 951 unsigned long long XY = X() * Y();
986 T* temp = (T*)malloc(sizeof(T) * Z()); 952 T* temp = (T*)malloc(sizeof(T) * Z());
987 //Iinitialize 953 //Iinitialize
@@ -989,12 +955,8 @@ public: @@ -989,12 +955,8 @@ public:
989 p[j] = 0; 955 p[j] = 0;
990 } 956 }
991 //calculate vaild number in a band 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 //calculate average number of a band 960 //calculate average number of a band
999 for (unsigned i = 0; i < XY; i++){ 961 for (unsigned i = 0; i < XY; i++){
1000 if (mask == NULL || mask[i] != 0){ 962 if (mask == NULL || mask[i] != 0){
@@ -1003,22 +965,21 @@ public: @@ -1003,22 +965,21 @@ public:
1003 p[j] += (double)temp[j] / (double)count; 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 free(temp); 971 free(temp);
1010 - thread_data = 100;  
1011 return true; 972 return true;
1012 } 973 }
1013 #ifdef CUDA_FOUND 974 #ifdef CUDA_FOUND
1014 /// Calculate the covariance matrix for masked pixels using cuBLAS 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 cudaError_t cudaStat; 978 cudaError_t cudaStat;
1018 cublasStatus_t stat; 979 cublasStatus_t stat;
1019 cublasHandle_t handle; 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 unsigned long long XY = X() * Y(); //calculate the number of elements in a band image 983 unsigned long long XY = X() * Y(); //calculate the number of elements in a band image
1023 unsigned long long B = Z(); //calculate the number of spectral elements 984 unsigned long long B = Z(); //calculate the number of spectral elements
1024 985
@@ -1047,7 +1008,7 @@ public: @@ -1047,7 +1008,7 @@ public:
1047 stat = cublasDaxpy(handle, B, &axpy_alpha, avg_dev, 1, s_dev, 1); //subtract the average spectrum 1008 stat = cublasDaxpy(handle, B, &axpy_alpha, avg_dev, 1, s_dev, 1); //subtract the average spectrum
1048 stat = cublasDsyr(handle, CUBLAS_FILL_MODE_UPPER, B, &ger_alpha, s_dev, 1, A_dev, B); //calculate the covariance matrix (symmetric outer product) 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,7 +1024,6 @@ public:
1063 } 1024 }
1064 } 1025 }
1065 1026
1066 - thread_data = 100; //processing complete  
1067 return true; 1027 return true;
1068 } 1028 }
1069 #endif 1029 #endif
@@ -1073,23 +1033,19 @@ public: @@ -1073,23 +1033,19 @@ public:
1073 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix 1033 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
1074 /// @param avg is a pointer to memory of size B that stores the average spectrum 1034 /// @param avg is a pointer to memory of size B that stores the average spectrum
1075 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 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 #ifdef CUDA_FOUND 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 #endif 1040 #endif
1081 - thread_data = 0; 1041 + progress = 0;
1082 //memory allocation 1042 //memory allocation
1083 unsigned long long XY = X() * Y(); 1043 unsigned long long XY = X() * Y();
1084 unsigned long long B = Z(); 1044 unsigned long long B = Z();
1085 T* temp = (T*)malloc(sizeof(T) * B); 1045 T* temp = (T*)malloc(sizeof(T) * B);
1086 //count vaild pixels in a band 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 //initialize covariance matrix 1049 //initialize covariance matrix
1094 memset(co, 0, B * B * sizeof(double)); 1050 memset(co, 0, B * B * sizeof(double));
1095 1051
@@ -1110,7 +1066,7 @@ public: @@ -1110,7 +1066,7 @@ public:
1110 co_half[idx++] += temp_precise[b0] * temp_precise[b1]; 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 idx = 0; 1071 idx = 0;
1116 for (unsigned long long i = 0; i < B; i++){ //copy the precision matrix to both halves of the output matrix 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,12 +1075,78 @@ public:
1119 } 1075 }
1120 } 1076 }
1121 1077
1122 - thread_data = 100; //processing complete  
1123 free(temp); 1078 free(temp);
1124 free(temp_precise); 1079 free(temp_precise);
1125 return true; 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 /// Crop a region of the image and save it to a new file. 1151 /// Crop a region of the image and save it to a new file.
1130 1152
@@ -1138,7 +1160,8 @@ public: @@ -1138,7 +1160,8 @@ public:
1138 unsigned long long x1, 1160 unsigned long long x1,
1139 unsigned long long y1, 1161 unsigned long long y1,
1140 unsigned long long b0, 1162 unsigned long long b0,
1141 - unsigned long long b1){ 1163 + unsigned long long b1,
  1164 + bool PROGRESS = false){
1142 1165
1143 //calculate the new number of samples, lines, and bands 1166 //calculate the new number of samples, lines, and bands
1144 unsigned long long samples = x1 - x0; 1167 unsigned long long samples = x1 - x0;
@@ -1180,14 +1203,13 @@ public: @@ -1180,14 +1203,13 @@ public:
1180 1203
1181 file.seekg(jump_sample, std::ios::cur); 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 file.seekg(jump_line, std::ios::cur); 1209 file.seekg(jump_line, std::ios::cur);
1187 } 1210 }
1188 free(temp); 1211 free(temp);
1189 1212
1190 - thread_data = 100;  
1191 return true; 1213 return true;
1192 } 1214 }
1193 1215
@@ -42,13 +42,14 @@ protected: @@ -42,13 +42,14 @@ protected:
42 return R[2]; 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 public: 48 public:
48 49
49 using binary<T>::open; 50 using binary<T>::open;
50 using binary<T>::file; 51 using binary<T>::file;
51 - using binary<T>::read_line_01; 52 + using binary<T>::read_line_2;
52 using binary<T>::read_plane_2; 53 using binary<T>::read_plane_2;
53 //using binary<T>::getSlice; 54 //using binary<T>::getSlice;
54 55
@@ -76,15 +77,15 @@ public: @@ -76,15 +77,15 @@ public:
76 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 77 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
77 /// @param page <= B is the integer number of the band to be copied. 78 /// @param page <= B is the integer number of the band to be copied.
78 bool band_index( T * p, unsigned int page){ 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 /// Retrieve a single band (by numerical label) and stores it in pre-allocated memory. 83 /// Retrieve a single band (by numerical label) and stores it in pre-allocated memory.
83 84
84 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 85 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
85 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied. 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 //if there are no wavelengths in the BSQ file 89 //if there are no wavelengths in the BSQ file
89 if(w.size() == 0) 90 if(w.size() == 0)
90 return band_index(p, (unsigned int)wavelength); 91 return band_index(p, (unsigned int)wavelength);
@@ -132,7 +133,7 @@ public: @@ -132,7 +133,7 @@ public:
132 else{ 133 else{
133 band_index(p, page); //return the band 134 band_index(p, page); //return the band
134 } 135 }
135 - 136 + if(PROGRESS) progress = 100;
136 return true; 137 return true;
137 } 138 }
138 139
@@ -141,8 +142,8 @@ public: @@ -141,8 +142,8 @@ public:
141 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. 142 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
142 /// @param x is the x-coordinate (dimension 1) of the spectrum. 143 /// @param x is the x-coordinate (dimension 1) of the spectrum.
143 /// @param y is the y-coordinate (dimension 2) of the spectrum. 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 /// Retrieve a single pixel and stores it in pre-allocated memory. 149 /// Retrieve a single pixel and stores it in pre-allocated memory.
@@ -171,8 +172,9 @@ public: @@ -171,8 +172,9 @@ public:
171 172
172 /// @param outname is the name of the output file used to store the resulting baseline-corrected data. 173 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
173 /// @param wls is the list of baseline points based on band labels. 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 unsigned N = wls.size(); //get the number of baseline points 178 unsigned N = wls.size(); //get the number of baseline points
177 179
178 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 180 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
@@ -261,7 +263,7 @@ public: @@ -261,7 +263,7 @@ public:
261 263
262 target.write(reinterpret_cast<const char*>(c), S); //write the corrected data into destination 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,7 +274,6 @@ public:
272 free(c); 274 free(c);
273 target.close(); 275 target.close();
274 276
275 - thread_data = 100;  
276 return true; 277 return true;
277 } 278 }
278 279
@@ -281,7 +282,7 @@ public: @@ -281,7 +282,7 @@ public:
281 /// @param outname is the name of the output file used to store the resulting baseline-corrected data. 282 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
282 /// @param w is the label specifying the band that the hyperspectral image will be normalized to. 283 /// @param w is the label specifying the band that the hyperspectral image will be normalized to.
283 /// @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 /// @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 unsigned int B = Z(); //calculate the number of bands 287 unsigned int B = Z(); //calculate the number of bands
287 unsigned int XY = X() * Y(); //calculate the number of pixels in a band 288 unsigned int XY = X() * Y(); //calculate the number of pixels in a band
@@ -310,7 +311,7 @@ public: @@ -310,7 +311,7 @@ public:
310 } 311 }
311 target.write(reinterpret_cast<const char*>(c), S); //write normalized data into destination 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,14 +321,13 @@ public:
320 free(b); 321 free(b);
321 free(c); 322 free(c);
322 target.close(); 323 target.close();
323 - thread_data = 100; //make sure that the progress bar is full  
324 return true; 324 return true;
325 } 325 }
326 326
327 /// Convert the current BSQ file to a BIP file with the specified file name. 327 /// Convert the current BSQ file to a BIP file with the specified file name.
328 328
329 /// @param outname is the name of the output BIP file to be saved to disk. 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 std::string temp = outname + "_temp"; 332 std::string temp = outname + "_temp";
333 std::string headtemp = temp + ".hdr"; 333 std::string headtemp = temp + ".hdr";
@@ -340,17 +340,18 @@ public: @@ -340,17 +340,18 @@ public:
340 exit(1); 340 exit(1);
341 } 341 }
342 //then convert bil file to bip file 342 //then convert bil file to bip file
  343 + progress = 0;
343 n.bip(outname); 344 n.bip(outname);
344 n.close(); 345 n.close();
345 remove(temp.c_str()); 346 remove(temp.c_str());
346 remove(headtemp.c_str()); 347 remove(headtemp.c_str());
347 return true; 348 return true;
348 - } 349 + }*/
349 350
350 /// Convert the current BSQ file to a BIL file with the specified file name. 351 /// Convert the current BSQ file to a BIL file with the specified file name.
351 352
352 /// @param outname is the name of the output BIL file to be saved to disk. 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 //simplify image resolution 356 //simplify image resolution
356 unsigned int L = X() * Z() * sizeof(T); //calculate the number of bytes of a ZX slice 357 unsigned int L = X() * Z() * sizeof(T); //calculate the number of bytes of a ZX slice
@@ -370,17 +371,11 @@ public: @@ -370,17 +371,11 @@ public:
370 { 371 {
371 file.read((char *)(xz_slice + z * X()), sizeof(T) * X()); //read a line 372 file.read((char *)(xz_slice + z * X()), sizeof(T) * X()); //read a line
372 file.seekg(jump, std::ios::cur); //seek to the next band 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 target.write(reinterpret_cast<const char*>(xz_slice), xz_bytes); //write the generated XZ slice to the target file 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 free(xz_slice); 379 free(xz_slice);
385 target.close(); 380 target.close();
386 381
@@ -869,13 +864,13 @@ public: @@ -869,13 +864,13 @@ public:
869 continue; 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 target.close(); 870 target.close();
876 free(temp); 871 free(temp);
877 872
878 - thread_data = 100; 873 + progress = 100;
879 874
880 return true; 875 return true;
881 } 876 }
@@ -923,7 +918,7 @@ public: @@ -923,7 +918,7 @@ public:
923 i++; 918 i++;
924 } 919 }
925 //std::cout<<xi<<"/"<<XY<<", "<<b<<"/"<<B<<std::endl; 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 //std::cout<<b*XY<<"/"<<B*XY<<" "<<B<<"-"<<XY<<std::endl; 923 //std::cout<<b*XY<<"/"<<B*XY<<" "<<B<<"-"<<XY<<std::endl;
929 //write the band image to disk 924 //write the band image to disk
@@ -931,7 +926,7 @@ public: @@ -931,7 +926,7 @@ public:
931 } 926 }
932 927
933 //std::cout<<"unsifted"<<std::endl; 928 //std::cout<<"unsifted"<<std::endl;
934 - thread_data = 100; 929 + progress = 100;
935 930
936 return true; 931 return true;
937 } 932 }
@@ -963,7 +958,7 @@ public: @@ -963,7 +958,7 @@ public:
963 958
964 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum 959 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
965 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 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 unsigned long long XY = X() * Y(); 962 unsigned long long XY = X() * Y();
968 unsigned long long count = 0; //count will store the number of masked pixels 963 unsigned long long count = 0; //count will store the number of masked pixels
969 T* temp = (T*)malloc(sizeof(T) * XY); 964 T* temp = (T*)malloc(sizeof(T) * XY);
@@ -983,6 +978,7 @@ public: @@ -983,6 +978,7 @@ public:
983 p[i] += (double)temp[j] / (double)count; 978 p[i] += (double)temp[j] / (double)count;
984 } 979 }
985 } 980 }
  981 + if(PROGRESS) progress = (double)(i+1) / Z() * 100;
986 } 982 }
987 free(temp); 983 free(temp);
988 return true; 984 return true;
@@ -993,8 +989,8 @@ public: @@ -993,8 +989,8 @@ public:
993 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix 989 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
994 /// @param avg is a pointer to memory of size B that stores the average spectrum 990 /// @param avg is a pointer to memory of size B that stores the average spectrum
995 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 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 //memory allocation 994 //memory allocation
999 unsigned long long xy = X() * Y(); 995 unsigned long long xy = X() * Y();
1000 unsigned long long B = Z(); 996 unsigned long long B = Z();
@@ -1024,15 +1020,15 @@ public: @@ -1024,15 +1020,15 @@ public:
1024 co[i*B + j] = numerator; 1020 co[i*B + j] = numerator;
1025 co[j*B + i] = numerator; //because correlated matrix is a symmetric matrix 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 free(bandi); 1025 free(bandi);
1030 free(bandj); 1026 free(bandj);
1031 1027
1032 - thread_data = 100; //processing complete 1028 + progress = 100; //processing complete
1033 1029
1034 return true; 1030 return true;
1035 - } 1031 + }*/
1036 1032
1037 1033
1038 /// Crop a region of the image and save it to a new file. 1034 /// Crop a region of the image and save it to a new file.
@@ -1047,7 +1043,8 @@ public: @@ -1047,7 +1043,8 @@ public:
1047 unsigned long long x1, 1043 unsigned long long x1,
1048 unsigned long long y1, 1044 unsigned long long y1,
1049 unsigned long long b0, 1045 unsigned long long b0,
1050 - unsigned long long b1){ 1046 + unsigned long long b1,
  1047 + bool PROGRESS = false){
1051 1048
1052 //calculate the new number of samples, lines, and bands 1049 //calculate the new number of samples, lines, and bands
1053 unsigned long long samples = x1 - x0; 1050 unsigned long long samples = x1 - x0;
@@ -1080,15 +1077,13 @@ public: @@ -1080,15 +1077,13 @@ public:
1080 file.read((char *)(temp + y * samples), sizeof(T) * samples); 1077 file.read((char *)(temp + y * samples), sizeof(T) * samples);
1081 file.seekg(jumpl, std::ios::cur); //go to the next band 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 out.write(reinterpret_cast<const char*>(temp), L); //write slice data into target file 1082 out.write(reinterpret_cast<const char*>(temp), L); //write slice data into target file
1086 file.seekg(jumpb, std::ios::cur); 1083 file.seekg(jumpb, std::ios::cur);
1087 } 1084 }
1088 free(temp); 1085 free(temp);
1089 1086
1090 - thread_data = 100;  
1091 -  
1092 return true; 1087 return true;
1093 } 1088 }
1094 1089
@@ -37,27 +37,27 @@ public: @@ -37,27 +37,27 @@ public:
37 37
38 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 38 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
39 if(header.data_type ==envi_header::float32) 39 if(header.data_type ==envi_header::float32)
40 - ((bsq<float>*)file)->reset_thread_data(); 40 + ((bsq<float>*)file)->reset_progress();
41 else if(header.data_type == envi_header::float64) 41 else if(header.data_type == envi_header::float64)
42 - ((bsq<double>*)file)->reset_thread_data(); 42 + ((bsq<double>*)file)->reset_progress();
43 else 43 else
44 std::cout<<"ERROR: unidentified data type"<<std::endl; 44 std::cout<<"ERROR: unidentified data type"<<std::endl;
45 } 45 }
46 46
47 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 47 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
48 if(header.data_type ==envi_header::float32) 48 if(header.data_type ==envi_header::float32)
49 - ((bil<float>*)file)->reset_thread_data(); 49 + ((bil<float>*)file)->reset_progress();
50 else if(header.data_type == envi_header::float64) 50 else if(header.data_type == envi_header::float64)
51 - ((bil<double>*)file)->reset_thread_data(); 51 + ((bil<double>*)file)->reset_progress();
52 else 52 else
53 std::cout<<"ERROR: unidentified data type"<<std::endl; 53 std::cout<<"ERROR: unidentified data type"<<std::endl;
54 } 54 }
55 55
56 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 56 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
57 if(header.data_type ==envi_header::float32) 57 if(header.data_type ==envi_header::float32)
58 - ((bip<float>*)file)->reset_thread_data(); 58 + ((bip<float>*)file)->reset_progress();
59 else if(header.data_type == envi_header::float64) 59 else if(header.data_type == envi_header::float64)
60 - ((bip<double>*)file)->reset_thread_data(); 60 + ((bip<double>*)file)->reset_progress();
61 else 61 else
62 std::cout<<"ERROR: unidentified data type"<<std::endl; 62 std::cout<<"ERROR: unidentified data type"<<std::endl;
63 } 63 }
@@ -73,27 +73,27 @@ public: @@ -73,27 +73,27 @@ public:
73 73
74 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 74 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
75 if(header.data_type ==envi_header::float32) 75 if(header.data_type ==envi_header::float32)
76 - return ((bsq<float>*)file)->get_thread_data(); 76 + return ((bsq<float>*)file)->get_progress();
77 else if(header.data_type == envi_header::float64) 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 else 79 else
80 std::cout<<"ERROR: unidentified data type"<<std::endl; 80 std::cout<<"ERROR: unidentified data type"<<std::endl;
81 } 81 }
82 82
83 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 83 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
84 if(header.data_type ==envi_header::float32) 84 if(header.data_type ==envi_header::float32)
85 - return ((bil<float>*)file)->get_thread_data(); 85 + return ((bil<float>*)file)->get_progress();
86 else if(header.data_type == envi_header::float64) 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 else 88 else
89 std::cout<<"ERROR: unidentified data type"<<std::endl; 89 std::cout<<"ERROR: unidentified data type"<<std::endl;
90 } 90 }
91 91
92 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 92 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
93 if(header.data_type ==envi_header::float32) 93 if(header.data_type ==envi_header::float32)
94 - return ((bip<float>*)file)->get_thread_data(); 94 + return ((bip<float>*)file)->get_progress();
95 else if(header.data_type == envi_header::float64) 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 else 97 else
98 std::cout<<"ERROR: unidentified data type"<<std::endl; 98 std::cout<<"ERROR: unidentified data type"<<std::endl;
99 } 99 }
@@ -213,31 +213,31 @@ public: @@ -213,31 +213,31 @@ public:
213 /// @param outfile is the name of the normalized file to be output 213 /// @param outfile is the name of the normalized file to be output
214 /// @param band is the band label to be output 214 /// @param band is the band label to be output
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) 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 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 218 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
219 if(header.data_type ==envi_header::float32) 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 else if(header.data_type == envi_header::float64) 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 else 223 else
224 std::cout<<"ERROR: unidentified data type"<<std::endl; 224 std::cout<<"ERROR: unidentified data type"<<std::endl;
225 } 225 }
226 226
227 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 227 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
228 if(header.data_type ==envi_header::float32) 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 else if(header.data_type == envi_header::float64) 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 else 232 else
233 std::cout<<"ERROR: unidentified data type"<<std::endl; 233 std::cout<<"ERROR: unidentified data type"<<std::endl;
234 } 234 }
235 235
236 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 236 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
237 if(header.data_type ==envi_header::float32) 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 else if(header.data_type == envi_header::float64) 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 else 241 else
242 std::cout<<"ERROR: unidentified data type"<<std::endl; 242 std::cout<<"ERROR: unidentified data type"<<std::endl;
243 } 243 }
@@ -253,13 +253,13 @@ public: @@ -253,13 +253,13 @@ public:
253 253
254 /// @param outfile is the file name for the baseline corrected output 254 /// @param outfile is the file name for the baseline corrected output
255 /// @param w is a list of band labels to serve as baseline points (zero values) 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 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 258 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
259 if(header.data_type ==envi_header::float32) 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 else if(header.data_type == envi_header::float64) 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 else{ 263 else{
264 std::cout<<"ERROR: unidentified data type"<<std::endl; 264 std::cout<<"ERROR: unidentified data type"<<std::endl;
265 exit(1); 265 exit(1);
@@ -268,9 +268,9 @@ public: @@ -268,9 +268,9 @@ public:
268 268
269 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 269 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
270 if(header.data_type ==envi_header::float32) 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 else if(header.data_type == envi_header::float64) 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 else{ 274 else{
275 std::cout<<"ERROR: unidentified data type"<<std::endl; 275 std::cout<<"ERROR: unidentified data type"<<std::endl;
276 exit(1); 276 exit(1);
@@ -279,9 +279,9 @@ public: @@ -279,9 +279,9 @@ public:
279 279
280 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 280 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
281 if(header.data_type ==envi_header::float32) 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 else if(header.data_type == envi_header::float64) 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 else{ 285 else{
286 std::cout<<"ERROR: unidentified data type"<<std::endl; 286 std::cout<<"ERROR: unidentified data type"<<std::endl;
287 exit(1); 287 exit(1);
@@ -294,11 +294,65 @@ public: @@ -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 /// Converts ENVI files between interleave types (BSQ, BIL, and BIP) 351 /// Converts ENVI files between interleave types (BSQ, BIL, and BIP)
298 352
299 /// @param outfile is the file name for the converted output 353 /// @param outfile is the file name for the converted output
300 /// @param interleave is the interleave format for the destination file 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 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 357 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
304 358
@@ -308,9 +362,12 @@ public: @@ -308,9 +362,12 @@ public:
308 exit(1); 362 exit(1);
309 } 363 }
310 else if(interleave == envi_header::BIL) //if the target file is bil file 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 else if(header.data_type == envi_header::float64){ //if the data type is float 373 else if(header.data_type == envi_header::float64){ //if the data type is float
@@ -319,9 +376,12 @@ public: @@ -319,9 +376,12 @@ public:
319 exit(1); 376 exit(1);
320 } 377 }
321 else if(interleave == envi_header::BIL) 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 else{ 387 else{
@@ -338,9 +398,9 @@ public: @@ -338,9 +398,9 @@ public:
338 exit(1); 398 exit(1);
339 } 399 }
340 else if(interleave == envi_header::BSQ) //if the target file is bsq file 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 else if(interleave == envi_header::BIP) //if the target file is bip file 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 else if(header.data_type == envi_header::float64){ //if the data type is float 406 else if(header.data_type == envi_header::float64){ //if the data type is float
@@ -349,9 +409,9 @@ public: @@ -349,9 +409,9 @@ public:
349 exit(1); 409 exit(1);
350 } 410 }
351 else if(interleave == envi_header::BSQ) 411 else if(interleave == envi_header::BSQ)
352 - return ((bil<double>*)file)->bsq(outfile); 412 + return ((bil<double>*)file)->bsq(outfile, PROGRESS);
353 else if(interleave == envi_header::BIP) 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 else{ 417 else{
@@ -368,9 +428,12 @@ public: @@ -368,9 +428,12 @@ public:
368 exit(1); 428 exit(1);
369 } 429 }
370 else if(interleave == envi_header::BIL) //if the target file is bil file 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 else if(header.data_type == envi_header::float64){ //if the data type is float 439 else if(header.data_type == envi_header::float64){ //if the data type is float
@@ -379,9 +442,12 @@ public: @@ -379,9 +442,12 @@ public:
379 exit(1); 442 exit(1);
380 } 443 }
381 else if(interleave == envi_header::BIL) //if the target file is bil file 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 else{ 453 else{
@@ -872,13 +938,13 @@ public: @@ -872,13 +938,13 @@ public:
872 938
873 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 939 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
874 /// @param wavelength is a floating point value (usually a wavelength in spectral data) used as a label for the band to be copied. 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 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 943 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
878 if(header.data_type ==envi_header::float32) 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 else if (header.data_type == envi_header::float64) 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 else{ 948 else{
883 std::cout << "ERROR: unidentified data type" << std::endl; 949 std::cout << "ERROR: unidentified data type" << std::endl;
884 exit(1); 950 exit(1);
@@ -886,9 +952,9 @@ public: @@ -886,9 +952,9 @@ public:
886 } 952 }
887 else if (header.interleave == envi_header::BIL){ 953 else if (header.interleave == envi_header::BIL){
888 if (header.data_type == envi_header::float32) 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 else if (header.data_type == envi_header::float64) 956 else if (header.data_type == envi_header::float64)
891 - return ((bil<double>*)file)->band((double*)ptr, wavelength); 957 + return ((bil<double>*)file)->band((double*)ptr, wavelength, PROGRESS);
892 else{ 958 else{
893 std::cout << "ERROR: unidentified data type" << std::endl; 959 std::cout << "ERROR: unidentified data type" << std::endl;
894 exit(1); 960 exit(1);
@@ -896,9 +962,9 @@ public: @@ -896,9 +962,9 @@ public:
896 } 962 }
897 else if (header.interleave == envi_header::BIP){ 963 else if (header.interleave == envi_header::BIP){
898 if (header.data_type == envi_header::float32) 964 if (header.data_type == envi_header::float32)
899 - return ((bip<float>*)file)->band((float*)ptr, wavelength); 965 + return ((bip<float>*)file)->band((float*)ptr, wavelength, PROGRESS);
900 else if (header.data_type == envi_header::float64) 966 else if (header.data_type == envi_header::float64)
901 - return ((bip<double>*)file)->band((double*)ptr, wavelength); 967 + return ((bip<double>*)file)->band((double*)ptr, wavelength, PROGRESS);
902 else{ 968 else{
903 std::cout << "ERROR: unidentified data type" << std::endl; 969 std::cout << "ERROR: unidentified data type" << std::endl;
904 exit(1); 970 exit(1);
@@ -912,13 +978,13 @@ public: @@ -912,13 +978,13 @@ public:
912 /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) 978 /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T)
913 /// @param x is the x-coordinate of the spectrum 979 /// @param x is the x-coordinate of the spectrum
914 /// @param y is the y-coordinate of the spectrum 980 /// @param y is the y-coordinate of the spectrum
915 - bool spectrum(void* ptr, unsigned int x, unsigned int y){ 981 + bool spectrum(void* ptr, unsigned int x, unsigned int y, bool PROGRESS = false){
916 982
917 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 983 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
918 if(header.data_type ==envi_header::float32) 984 if(header.data_type ==envi_header::float32)
919 - return ((bsq<float>*)file)->spectrum((float*)ptr, x, y); 985 + return ((bsq<float>*)file)->spectrum((float*)ptr, x, y, PROGRESS);
920 else if (header.data_type == envi_header::float64) 986 else if (header.data_type == envi_header::float64)
921 - return ((bsq<double>*)file)->spectrum((double*)ptr, x, y); 987 + return ((bsq<double>*)file)->spectrum((double*)ptr, x, y, PROGRESS);
922 else{ 988 else{
923 std::cout << "ERROR: unidentified data type" << std::endl; 989 std::cout << "ERROR: unidentified data type" << std::endl;
924 exit(1); 990 exit(1);
@@ -926,9 +992,9 @@ public: @@ -926,9 +992,9 @@ public:
926 } 992 }
927 else if (header.interleave == envi_header::BIL){ 993 else if (header.interleave == envi_header::BIL){
928 if (header.data_type == envi_header::float32) 994 if (header.data_type == envi_header::float32)
929 - return ((bil<float>*)file)->spectrum((float*)ptr, x, y); 995 + return ((bil<float>*)file)->spectrum((float*)ptr, x, y, PROGRESS);
930 else if (header.data_type == envi_header::float64) 996 else if (header.data_type == envi_header::float64)
931 - return ((bil<double>*)file)->spectrum((double*)ptr, x, y); 997 + return ((bil<double>*)file)->spectrum((double*)ptr, x, y, PROGRESS);
932 else{ 998 else{
933 std::cout << "ERROR: unidentified data type" << std::endl; 999 std::cout << "ERROR: unidentified data type" << std::endl;
934 exit(1); 1000 exit(1);
@@ -936,9 +1002,9 @@ public: @@ -936,9 +1002,9 @@ public:
936 } 1002 }
937 else if (header.interleave == envi_header::BIP){ 1003 else if (header.interleave == envi_header::BIP){
938 if (header.data_type == envi_header::float32) 1004 if (header.data_type == envi_header::float32)
939 - return ((bip<float>*)file)->spectrum((float*)ptr, x, y); 1005 + return ((bip<float>*)file)->spectrum((float*)ptr, x, y, PROGRESS);
940 else if (header.data_type == envi_header::float64) 1006 else if (header.data_type == envi_header::float64)
941 - return ((bip<double>*)file)->spectrum((double*)ptr, x, y); 1007 + return ((bip<double>*)file)->spectrum((double*)ptr, x, y, PROGRESS);
942 else{ 1008 else{
943 std::cout << "ERROR: unidentified data type" << std::endl; 1009 std::cout << "ERROR: unidentified data type" << std::endl;
944 exit(1); 1010 exit(1);
@@ -989,12 +1055,12 @@ public: @@ -989,12 +1055,12 @@ public:
989 1055
990 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum 1056 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
991 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 1057 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
992 - bool avg_band(double * p, unsigned char* mask){ 1058 + bool avg_band(double * p, unsigned char* mask, bool PROGRESS = false){
993 if (header.interleave == envi_header::BSQ){ 1059 if (header.interleave == envi_header::BSQ){
994 if (header.data_type == envi_header::float32) 1060 if (header.data_type == envi_header::float32)
995 - return ((bsq<float>*)file)->avg_band(p, mask); 1061 + return ((bsq<float>*)file)->avg_band(p, mask, PROGRESS);
996 else if (header.data_type == envi_header::float64) 1062 else if (header.data_type == envi_header::float64)
997 - return ((bsq<double>*)file)->avg_band(p, mask); 1063 + return ((bsq<double>*)file)->avg_band(p, mask, PROGRESS);
998 else{ 1064 else{
999 std::cout << "ERROR: unidentified data type" << std::endl; 1065 std::cout << "ERROR: unidentified data type" << std::endl;
1000 exit(1); 1066 exit(1);
@@ -1002,9 +1068,9 @@ public: @@ -1002,9 +1068,9 @@ public:
1002 } 1068 }
1003 else if (header.interleave == envi_header::BIL){ 1069 else if (header.interleave == envi_header::BIL){
1004 if (header.data_type == envi_header::float32) 1070 if (header.data_type == envi_header::float32)
1005 - return ((bil<float>*)file)->avg_band(p, mask); 1071 + return ((bil<float>*)file)->avg_band(p, mask, PROGRESS);
1006 else if (header.data_type == envi_header::float64) 1072 else if (header.data_type == envi_header::float64)
1007 - return ((bil<double>*)file)->avg_band(p, mask); 1073 + return ((bil<double>*)file)->avg_band(p, mask, PROGRESS);
1008 else{ 1074 else{
1009 std::cout << "ERROR: unidentified data type" << std::endl; 1075 std::cout << "ERROR: unidentified data type" << std::endl;
1010 exit(1); 1076 exit(1);
@@ -1012,9 +1078,9 @@ public: @@ -1012,9 +1078,9 @@ public:
1012 } 1078 }
1013 else if (header.interleave == envi_header::BIP){ 1079 else if (header.interleave == envi_header::BIP){
1014 if (header.data_type == envi_header::float32) 1080 if (header.data_type == envi_header::float32)
1015 - return ((bip<float>*)file)->avg_band(p, mask); 1081 + return ((bip<float>*)file)->avg_band(p, mask, PROGRESS);
1016 else if (header.data_type == envi_header::float64) 1082 else if (header.data_type == envi_header::float64)
1017 - return ((bip<double>*)file)->avg_band(p, mask); 1083 + return ((bip<double>*)file)->avg_band(p, mask, PROGRESS);
1018 else{ 1084 else{
1019 std::cout << "ERROR: unidentified data type" << std::endl; 1085 std::cout << "ERROR: unidentified data type" << std::endl;
1020 exit(1); 1086 exit(1);
@@ -1028,22 +1094,24 @@ public: @@ -1028,22 +1094,24 @@ public:
1028 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix 1094 /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix
1029 /// @param avg is a pointer to memory of size B that stores the average spectrum 1095 /// @param avg is a pointer to memory of size B that stores the average spectrum
1030 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 1096 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
1031 - bool co_matrix(double* co, double* avg, unsigned char* mask){ 1097 + bool co_matrix(double* co, double* avg, unsigned char* mask, bool PROGRESS = false){
1032 if (header.interleave == envi_header::BSQ){ 1098 if (header.interleave == envi_header::BSQ){
1033 - if (header.data_type == envi_header::float32)  
1034 - return ((bsq<float>*)file)->co_matrix(co, avg, mask); 1099 + std::cout<<"ERROR: calculating the covariance matrix for a BSQ file is impractical; convert to BIL or BIP first"<<std::endl;
  1100 + exit(1);
  1101 + /*if (header.data_type == envi_header::float32)
  1102 + return ((bsq<float>*)file)->co_matrix(co, avg, mask, PROGRESS);
1035 else if (header.data_type == envi_header::float64) 1103 else if (header.data_type == envi_header::float64)
1036 - return ((bsq<double>*)file)->co_matrix(co, avg, mask); 1104 + return ((bsq<double>*)file)->co_matrix(co, avg, mask, PROGRESS);
1037 else{ 1105 else{
1038 std::cout << "ERROR: unidentified data type" << std::endl; 1106 std::cout << "ERROR: unidentified data type" << std::endl;
1039 exit(1); 1107 exit(1);
1040 - } 1108 + }*/
1041 } 1109 }
1042 else if (header.interleave == envi_header::BIL){ 1110 else if (header.interleave == envi_header::BIL){
1043 if (header.data_type == envi_header::float32) 1111 if (header.data_type == envi_header::float32)
1044 - return ((bil<float>*)file)->co_matrix(co, avg, mask); 1112 + return ((bil<float>*)file)->co_matrix(co, avg, mask, PROGRESS);
1045 else if (header.data_type == envi_header::float64) 1113 else if (header.data_type == envi_header::float64)
1046 - return ((bil<double>*)file)->co_matrix(co, avg, mask); 1114 + return ((bil<double>*)file)->co_matrix(co, avg, mask, PROGRESS);
1047 else{ 1115 else{
1048 std::cout << "ERROR: unidentified data type" << std::endl; 1116 std::cout << "ERROR: unidentified data type" << std::endl;
1049 exit(1); 1117 exit(1);
@@ -1051,9 +1119,9 @@ public: @@ -1051,9 +1119,9 @@ public:
1051 } 1119 }
1052 else if (header.interleave == envi_header::BIP){ 1120 else if (header.interleave == envi_header::BIP){
1053 if (header.data_type == envi_header::float32) 1121 if (header.data_type == envi_header::float32)
1054 - return ((bip<float>*)file)->co_matrix(co, avg, mask); 1122 + return ((bip<float>*)file)->co_matrix(co, avg, mask, PROGRESS);
1055 else if (header.data_type == envi_header::float64) 1123 else if (header.data_type == envi_header::float64)
1056 - return ((bip<double>*)file)->co_matrix(co, avg, mask); 1124 + return ((bip<double>*)file)->co_matrix(co, avg, mask, PROGRESS);
1057 else{ 1125 else{
1058 std::cout << "ERROR: unidentified data type" << std::endl; 1126 std::cout << "ERROR: unidentified data type" << std::endl;
1059 exit(1); 1127 exit(1);
@@ -1070,7 +1138,7 @@ public: @@ -1070,7 +1138,7 @@ public:
1070 /// @param y0 is the lower-left y pixel coordinate to be included in the cropped image 1138 /// @param y0 is the lower-left y pixel coordinate to be included in the cropped image
1071 /// @param x1 is the upper-right x pixel coordinate to be included in the cropped image 1139 /// @param x1 is the upper-right x pixel coordinate to be included in the cropped image
1072 /// @param y1 is the upper-right y pixel coordinate to be included in the cropped image 1140 /// @param y1 is the upper-right y pixel coordinate to be included in the cropped image
1073 - bool crop(std::string outfile,unsigned x0, unsigned y0, unsigned x1, unsigned y1, unsigned b0, unsigned b1){ 1141 + bool crop(std::string outfile,unsigned x0, unsigned y0, unsigned x1, unsigned y1, unsigned b0, unsigned b1, bool PROGRESS = false){
1074 1142
1075 //save the header for the cropped file 1143 //save the header for the cropped file
1076 stim::envi_header new_header = header; 1144 stim::envi_header new_header = header;
@@ -1084,9 +1152,9 @@ public: @@ -1084,9 +1152,9 @@ public:
1084 1152
1085 if (header.interleave == envi_header::BSQ){ 1153 if (header.interleave == envi_header::BSQ){
1086 if (header.data_type == envi_header::float32) 1154 if (header.data_type == envi_header::float32)
1087 - return ((bsq<float>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1); 1155 + return ((bsq<float>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS);
1088 else if (header.data_type == envi_header::float64) 1156 else if (header.data_type == envi_header::float64)
1089 - return ((bsq<double>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1); 1157 + return ((bsq<double>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS);
1090 else{ 1158 else{
1091 std::cout << "ERROR: unidentified data type" << std::endl; 1159 std::cout << "ERROR: unidentified data type" << std::endl;
1092 exit(1); 1160 exit(1);
@@ -1094,9 +1162,9 @@ public: @@ -1094,9 +1162,9 @@ public:
1094 } 1162 }
1095 else if (header.interleave == envi_header::BIL){ 1163 else if (header.interleave == envi_header::BIL){
1096 if (header.data_type == envi_header::float32) 1164 if (header.data_type == envi_header::float32)
1097 - return ((bil<float>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1); 1165 + return ((bil<float>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS);
1098 else if (header.data_type == envi_header::float64) 1166 else if (header.data_type == envi_header::float64)
1099 - return ((bil<double>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1); 1167 + return ((bil<double>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS);
1100 else{ 1168 else{
1101 std::cout << "ERROR: unidentified data type" << std::endl; 1169 std::cout << "ERROR: unidentified data type" << std::endl;
1102 exit(1); 1170 exit(1);
@@ -1104,9 +1172,9 @@ public: @@ -1104,9 +1172,9 @@ public:
1104 } 1172 }
1105 else if (header.interleave == envi_header::BIP){ 1173 else if (header.interleave == envi_header::BIP){
1106 if (header.data_type == envi_header::float32) 1174 if (header.data_type == envi_header::float32)
1107 - return ((bip<float>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1); 1175 + return ((bip<float>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS);
1108 else if (header.data_type == envi_header::float64) 1176 else if (header.data_type == envi_header::float64)
1109 - return ((bip<double>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1); 1177 + return ((bip<double>*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS);
1110 else{ 1178 else{
1111 std::cout << "ERROR: unidentified data type" << std::endl; 1179 std::cout << "ERROR: unidentified data type" << std::endl;
1112 exit(1); 1180 exit(1);