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