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){