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 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  
... ...