Commit 48f356fa76f70ecaa96732fdfcc7cefb8c49ca34

Authored by David Mayerich
1 parent e318123b

bug fixes for FFT in stim::agilent_binary

matlab/loadAgilent.m 0 → 100644
  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,26 +35,28 @@ public:
35 void alloc(){ 35 void alloc(){
36 ptr = (T*) malloc(bytes()); 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 R[0] = x; 39 R[0] = x;
40 R[1] = y; 40 R[1] = y;
41 R[2] = z; 41 R[2] = z;
42 alloc(); 42 alloc();
43 } 43 }
44 44
  45 + /// Create a deep copy of an agileng_binary object
45 void deep_copy(agilent_binary<T>* dst, const agilent_binary<T>* src){ 46 void deep_copy(agilent_binary<T>* dst, const agilent_binary<T>* src){
46 dst->alloc(src->R[0], src->R[1], src->R[2]); //allocate memory 47 dst->alloc(src->R[0], src->R[1], src->R[2]); //allocate memory
47 memcpy(dst->ptr, src->ptr, bytes()); //copy the data 48 memcpy(dst->ptr, src->ptr, bytes()); //copy the data
48 memcpy(dst->Z, src->Z, sizeof(double) * 2); //copy the data z range 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 agilent_binary(){ 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 ptr = NULL; 55 ptr = NULL;
54 } 56 }
55 57
56 /// Constructor with resolution 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 alloc(x, y, z); 60 alloc(x, y, z);
59 } 61 }
60 62
@@ -109,13 +111,11 @@ public: @@ -109,13 +111,11 @@ public:
109 111
110 char zero = 0; 112 char zero = 0;
111 for(size_t i = 0; i < 9; i++) outfile.write(&zero, 1); //write 9 zeros 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 for(size_t i = 0; i < 13; i++) outfile.write(&zero, 1); //write 13 zeros 115 for(size_t i = 0; i < 13; i++) outfile.write(&zero, 1); //write 13 zeros
  116 + outfile.write((char*)&R[0], 2);
114 outfile.write((char*)&R[1], 2); 117 outfile.write((char*)&R[1], 2);
115 - outfile.write((char*)&R[2], 2);  
116 for(size_t i = 0; i < 992; i++) outfile.write(&zero, 1); //write 992 zeros 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 size_t b = bytes(); 120 size_t b = bytes();
121 outfile.write((char*)ptr, b); //write the data to the output file 121 outfile.write((char*)ptr, b); //write the data to the output file
@@ -149,7 +149,7 @@ public: @@ -149,7 +149,7 @@ public:
149 149
150 #ifdef CUDA_FOUND 150 #ifdef CUDA_FOUND
151 /// Perform an FFT and return a binary file with bands in the specified range 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 auto total_start = std::chrono::high_resolution_clock::now(); 153 auto total_start = std::chrono::high_resolution_clock::now();
154 154
155 auto start = std::chrono::high_resolution_clock::now(); 155 auto start = std::chrono::high_resolution_clock::now();
@@ -177,8 +177,8 @@ public: @@ -177,8 +177,8 @@ public:
177 177
178 start = std::chrono::high_resolution_clock::now(); 178 start = std::chrono::high_resolution_clock::now();
179 int N[1]; //create an array with the interferogram size (required for cuFFT input) 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 std::cout<<"cuFFT Error: unable to create 1D plan."<<std::endl; 182 std::cout<<"cuFFT Error: unable to create 1D plan."<<std::endl;
183 exit(1); 183 exit(1);
184 } 184 }
@@ -199,12 +199,13 @@ public: @@ -199,12 +199,13 @@ public:
199 std::complex<T>* cpu_fft = (std::complex<T>*) malloc( R[0] * R[1] * (R[2]/2+1) * sizeof(std::complex<T>) ); 199 std::complex<T>* cpu_fft = (std::complex<T>*) malloc( R[0] * R[1] * (R[2]/2+1) * sizeof(std::complex<T>) );
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 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 double int_length = int_delta * R[2]; //interferogram length in centimeters 204 double int_length = int_delta * R[2]; //interferogram length in centimeters
204 double fft_delta = 1/int_length; //spectrum spacing (in inverse centimeters, wavenumber 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 size_t end_i = start_i + size_i; //last band number 209 size_t end_i = start_i + size_i; //last band number
209 agilent_binary<T> result(R[0], R[1], size_i); 210 agilent_binary<T> result(R[0], R[1], size_i);
210 result.Z[0] = start_i * fft_delta; //set the range for the FFT result 211 result.Z[0] = start_i * fft_delta; //set the range for the FFT result
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include "../envi/bil.h" 7 #include "../envi/bil.h"
8 #include "../math/fd_coefficients.h" 8 #include "../math/fd_coefficients.h"
9 #include <iostream> 9 #include <iostream>
  10 +#include <fstream>
10 //#include "../image/image.h" 11 //#include "../image/image.h"
11 12
12 namespace stim{ 13 namespace stim{
@@ -224,6 +225,37 @@ public: @@ -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 /// Open an existing ENVI file given the filename and a header structure 259 /// Open an existing ENVI file given the filename and a header structure
228 260
229 /// @param filename is the name of the ENVI binary file 261 /// @param filename is the name of the ENVI binary file
@@ -257,7 +289,6 @@ public: @@ -257,7 +289,6 @@ public:
257 //header.load(headername); 289 //header.load(headername);
258 290
259 return open(filename, h); 291 return open(filename, h);
260 -  
261 } 292 }
262 293
263 /// Normalize a hyperspectral ENVI file given a band number and threshold. 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,9 +440,24 @@ struct envi_header
440 } 440 }
441 441
442 /// Convert a wavelength to a band index (or a pair of surrounding band indices) 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 std::vector<size_t> band_index(double w){ 444 std::vector<size_t> band_index(double w){
444 std::vector<size_t> idx; //create an empty array of indices 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 for(size_t b = 0; b < bands; b++){ //for each band in the wavelength vector 462 for(size_t b = 0; b < bands; b++){ //for each band in the wavelength vector
448 if(wavelength[b] == w){ //if an exact match is found 463 if(wavelength[b] == w){ //if an exact match is found
@@ -216,7 +216,7 @@ public: @@ -216,7 +216,7 @@ public:
216 return result; 216 return result;
217 } 217 }
218 218
219 -#ifndef __NVCC__ 219 +//#ifndef __NVCC__
220 /// Outputs the vector as a string 220 /// Outputs the vector as a string
221 std::string str() const{ 221 std::string str() const{
222 std::stringstream ss; 222 std::stringstream ss;
@@ -234,7 +234,7 @@ public: @@ -234,7 +234,7 @@ public:
234 234
235 return ss.str(); 235 return ss.str();
236 } 236 }
237 -#endif 237 +//#endif
238 238
239 size_t size(){ return 3; } 239 size_t size(){ return 3; }
240 240