Commit 48f356fa76f70ecaa96732fdfcc7cefb8c49ca34
1 parent
e318123b
bug fixes for FFT in stim::agilent_binary
Showing
5 changed files
with
81 additions
and
17 deletions
Show diff stats
1 | +function S = loadAgilent(filename) | |
2 | + | |
3 | +fid = fopen(filename); %open the file for reading | |
4 | +fseek(fid, 9, 'bof'); %skip past the first 9 bytes of the header | |
5 | + | |
6 | +bands = fread(fid, 1, 'int16'); %read the number of bands in the file | |
7 | +fseek(fid, 13, 'cof'); %skip the next 13 bytes in the header | |
8 | + | |
9 | +samples = fread(fid, 1, 'int16'); %read the number of samples (X) | |
10 | +lines = fread(fid, 1, 'int16'); %read the number of lines (Y) | |
11 | + | |
12 | +fseek(fid, 1020, 'bof'); %skip past the entire header | |
13 | +S = fread(fid, [samples lines*bands], 'float32'); %read all the data | |
14 | +S = reshape(S, [samples, lines, bands]); | |
15 | +fclose(fid); %close the file | |
16 | + | |
17 | + | ... | ... |
stim/envi/agilent_binary.h
... | ... | @@ -35,26 +35,28 @@ public: |
35 | 35 | void alloc(){ |
36 | 36 | ptr = (T*) malloc(bytes()); |
37 | 37 | } |
38 | - void alloc(short x, short y, short z){ | |
38 | + void alloc(size_t x, size_t y, size_t z){ | |
39 | 39 | R[0] = x; |
40 | 40 | R[1] = y; |
41 | 41 | R[2] = z; |
42 | 42 | alloc(); |
43 | 43 | } |
44 | 44 | |
45 | + /// Create a deep copy of an agileng_binary object | |
45 | 46 | void deep_copy(agilent_binary<T>* dst, const agilent_binary<T>* src){ |
46 | 47 | dst->alloc(src->R[0], src->R[1], src->R[2]); //allocate memory |
47 | 48 | memcpy(dst->ptr, src->ptr, bytes()); //copy the data |
48 | 49 | memcpy(dst->Z, src->Z, sizeof(double) * 2); //copy the data z range |
49 | 50 | } |
50 | 51 | |
52 | + /// Default constructor, sets the resolution to zero and the data pointer to NULL | |
51 | 53 | agilent_binary(){ |
52 | - memset(R, 0, sizeof(short) * 3); //set the resolution to zero | |
54 | + memset(R, 0, sizeof(size_t) * 3); //set the resolution to zero | |
53 | 55 | ptr = NULL; |
54 | 56 | } |
55 | 57 | |
56 | 58 | /// Constructor with resolution |
57 | - agilent_binary(short x, short y, short z){ | |
59 | + agilent_binary(size_t x, size_t y, size_t z){ | |
58 | 60 | alloc(x, y, z); |
59 | 61 | } |
60 | 62 | |
... | ... | @@ -109,13 +111,11 @@ public: |
109 | 111 | |
110 | 112 | char zero = 0; |
111 | 113 | for(size_t i = 0; i < 9; i++) outfile.write(&zero, 1); //write 9 zeros |
112 | - outfile.write((char*)&R[0], 2); | |
114 | + outfile.write((char*)&R[2], 2); | |
113 | 115 | for(size_t i = 0; i < 13; i++) outfile.write(&zero, 1); //write 13 zeros |
116 | + outfile.write((char*)&R[0], 2); | |
114 | 117 | outfile.write((char*)&R[1], 2); |
115 | - outfile.write((char*)&R[2], 2); | |
116 | 118 | for(size_t i = 0; i < 992; i++) outfile.write(&zero, 1); //write 992 zeros |
117 | - //char zerovec[1020]; | |
118 | - //outfile.write((char*)zerovec, 1020); | |
119 | 119 | |
120 | 120 | size_t b = bytes(); |
121 | 121 | outfile.write((char*)ptr, b); //write the data to the output file |
... | ... | @@ -149,7 +149,7 @@ public: |
149 | 149 | |
150 | 150 | #ifdef CUDA_FOUND |
151 | 151 | /// Perform an FFT and return a binary file with bands in the specified range |
152 | - agilent_binary<T> fft(float band_min, float band_max){ | |
152 | + agilent_binary<T> fft(double band_min, double band_max, double ELWN = 15798, int UDR = 2){ | |
153 | 153 | auto total_start = std::chrono::high_resolution_clock::now(); |
154 | 154 | |
155 | 155 | auto start = std::chrono::high_resolution_clock::now(); |
... | ... | @@ -177,8 +177,8 @@ public: |
177 | 177 | |
178 | 178 | start = std::chrono::high_resolution_clock::now(); |
179 | 179 | int N[1]; //create an array with the interferogram size (required for cuFFT input) |
180 | - N[0] = R[2]; //set the only array value to the interferogram size | |
181 | - if(cufftPlanMany(&plan, 1, N, NULL, 1, R[2], NULL, 1, R[2], CUFFT_R2C, batch) != CUFFT_SUCCESS){ | |
180 | + N[0] = (int)R[2]; //set the only array value to the interferogram size | |
181 | + if(cufftPlanMany(&plan, 1, N, NULL, 1, (int)R[2], NULL, 1, (int)R[2], CUFFT_R2C, (int)batch) != CUFFT_SUCCESS){ | |
182 | 182 | std::cout<<"cuFFT Error: unable to create 1D plan."<<std::endl; |
183 | 183 | exit(1); |
184 | 184 | } |
... | ... | @@ -199,12 +199,13 @@ public: |
199 | 199 | std::complex<T>* cpu_fft = (std::complex<T>*) malloc( R[0] * R[1] * (R[2]/2+1) * sizeof(std::complex<T>) ); |
200 | 200 | HANDLE_ERROR(cudaMemcpy(cpu_fft, gpu_fft, R[0] * R[1] * (R[2]/2+1) * sizeof(cufftComplex), cudaMemcpyDeviceToHost)); //copy data from the host to the device |
201 | 201 | |
202 | - double int_delta = 0.00012656; //interferogram sample spacing in centimeters | |
202 | + //double int_delta = 0.00012656; //interferogram sample spacing in centimeters | |
203 | + double int_delta = (1.0 / ELWN) * ((double)UDR / 2.0); //calculate the interferogram spacing | |
203 | 204 | double int_length = int_delta * R[2]; //interferogram length in centimeters |
204 | 205 | double fft_delta = 1/int_length; //spectrum spacing (in inverse centimeters, wavenumber |
205 | 206 | |
206 | - size_t start_i = std::ceil(band_min / fft_delta); //calculate the first band to store | |
207 | - size_t size_i = std::floor(band_max / fft_delta) - start_i; //calculate the number of bands to store | |
207 | + size_t start_i = (size_t)std::ceil(band_min / fft_delta); //calculate the first band to store | |
208 | + size_t size_i = (size_t)std::floor(band_max / fft_delta) - start_i; //calculate the number of bands to store | |
208 | 209 | size_t end_i = start_i + size_i; //last band number |
209 | 210 | agilent_binary<T> result(R[0], R[1], size_i); |
210 | 211 | result.Z[0] = start_i * fft_delta; //set the range for the FFT result | ... | ... |
stim/envi/envi.h
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | #include "../envi/bil.h" |
8 | 8 | #include "../math/fd_coefficients.h" |
9 | 9 | #include <iostream> |
10 | +#include <fstream> | |
10 | 11 | //#include "../image/image.h" |
11 | 12 | |
12 | 13 | namespace stim{ |
... | ... | @@ -224,6 +225,37 @@ public: |
224 | 225 | |
225 | 226 | } |
226 | 227 | |
228 | + /// Open an Agilent binary file as an ENVI stream | |
229 | + bool open_agilent(std::string filename){ | |
230 | + fname = filename; //store the file name | |
231 | + | |
232 | + //Open the file temporarily to get the header information | |
233 | + FILE* f = fopen(filename.c_str(), "r"); //open the binary file for reading | |
234 | + if(f == NULL) return false; //return false if no file is opened | |
235 | + | |
236 | + fseek(f, 9, SEEK_SET); //seek to the number of bands | |
237 | + short b; //allocate space for the number of bands | |
238 | + fread(&b, sizeof(short), 1, f); //read the number of bands | |
239 | + fseek(f, 13, SEEK_CUR); //skip the the x and y dimensions | |
240 | + short x, y; | |
241 | + fread(&x, sizeof(short), 1, f); //read the image x and y size | |
242 | + fread(&y, sizeof(short), 1, f); | |
243 | + fclose(f); //close the file | |
244 | + | |
245 | + //store the information from the Agilent header in the ENVI header | |
246 | + header.bands = b; | |
247 | + header.samples = x; | |
248 | + header.lines = y; | |
249 | + header.data_type = envi_header::float32; //all values are 32-bit floats | |
250 | + header.header_offset = 1020; //number of bytes in an Agilent binary header | |
251 | + header.interleave = envi_header::BSQ; //all Agilent binary files are BSQ | |
252 | + | |
253 | + allocate(); //allocate the streaming file object | |
254 | + open(); //open the file for streaming | |
255 | + | |
256 | + return true; | |
257 | + } | |
258 | + | |
227 | 259 | /// Open an existing ENVI file given the filename and a header structure |
228 | 260 | |
229 | 261 | /// @param filename is the name of the ENVI binary file |
... | ... | @@ -257,7 +289,6 @@ public: |
257 | 289 | //header.load(headername); |
258 | 290 | |
259 | 291 | return open(filename, h); |
260 | - | |
261 | 292 | } |
262 | 293 | |
263 | 294 | /// Normalize a hyperspectral ENVI file given a band number and threshold. | ... | ... |
stim/envi/envi_header.h
... | ... | @@ -440,9 +440,24 @@ struct envi_header |
440 | 440 | } |
441 | 441 | |
442 | 442 | /// Convert a wavelength to a band index (or a pair of surrounding band indices) |
443 | + /// if the file doesn't specify wavelengths, w is assumed to be a band index | |
443 | 444 | std::vector<size_t> band_index(double w){ |
444 | 445 | std::vector<size_t> idx; //create an empty array of indices |
445 | - if(w < wavelength[0] || w > wavelength[bands-1]) return idx; //if the wavelength range is outside of the file, return an empty array | |
446 | + if(wavelength.size() == 0){ //if a wavelength vector doesn't exist, assume the passed value is a band | |
447 | + if(w < 0 || w > bands-1) return idx; //if the band is outside the given band range, return an empty vector | |
448 | + size_t low, high; //allocate space for the floor and ceiling | |
449 | + low = std::floor(w); //calculate the floor | |
450 | + high = std::ceil(w); //calculate the ceiling | |
451 | + if(low == high) //if the floor and ceiling are the same | |
452 | + idx.push_back(low); //return a vector with one element (the given w matches a band exactly) | |
453 | + else{ | |
454 | + idx.resize(2); //otherwise return the floor and ceiling | |
455 | + idx[0] = low; | |
456 | + idx[1] = high; | |
457 | + } | |
458 | + return idx; | |
459 | + } | |
460 | + else if(w < wavelength[0] || w > wavelength[bands-1]) return idx; //if the wavelength range is outside of the file, return an empty array | |
446 | 461 | |
447 | 462 | for(size_t b = 0; b < bands; b++){ //for each band in the wavelength vector |
448 | 463 | if(wavelength[b] == w){ //if an exact match is found | ... | ... |
stim/math/vec3.h
... | ... | @@ -216,7 +216,7 @@ public: |
216 | 216 | return result; |
217 | 217 | } |
218 | 218 | |
219 | -#ifndef __NVCC__ | |
219 | +//#ifndef __NVCC__ | |
220 | 220 | /// Outputs the vector as a string |
221 | 221 | std::string str() const{ |
222 | 222 | std::stringstream ss; |
... | ... | @@ -234,7 +234,7 @@ public: |
234 | 234 | |
235 | 235 | return ss.str(); |
236 | 236 | } |
237 | -#endif | |
237 | +//#endif | |
238 | 238 | |
239 | 239 | size_t size(){ return 3; } |
240 | 240 | ... | ... |