Commit 180d7f3ae17a1a239a774f2106a3d79e7392d15f
1 parent
0ef519a4
added binary file framework
Showing
7 changed files
with
550 additions
and
394 deletions
Show diff stats
1 | +#ifndef RTS_BIL_H | ||
2 | +#define RTS_BIL_H | ||
3 | + | ||
4 | +#include "../envi/envi.h" | ||
5 | + | ||
6 | +namespace rts{ | ||
7 | + | ||
8 | +//This class specifies a BIL binary file that can be streamed to and from storage media | ||
9 | +template< typename T > | ||
10 | +class bil{ | ||
11 | + | ||
12 | +protected: | ||
13 | + | ||
14 | + rts::envi header; | ||
15 | + | ||
16 | + | ||
17 | +public: | ||
18 | + | ||
19 | + bil(){ | ||
20 | + init(); | ||
21 | + } | ||
22 | + | ||
23 | +}; | ||
24 | + | ||
25 | +} | ||
26 | + | ||
27 | +#endif |
1 | +#ifndef RTS_BINARY_H | ||
2 | +#define RTS_BINARY_H | ||
3 | + | ||
4 | +#include "../envi/envi.h" | ||
5 | + | ||
6 | +#include <fstream> | ||
7 | +#include <sys/stat.h> | ||
8 | + | ||
9 | +namespace rts{ | ||
10 | + | ||
11 | +//This class contains a bunch of functions useful for multidimensional binary file access | ||
12 | +template< typename T, unsigned int D = 3 > | ||
13 | +class binary{ | ||
14 | + | ||
15 | +protected: | ||
16 | + | ||
17 | + std::fstream file; //file stream used for reading and writing | ||
18 | + std::string name; //file name | ||
19 | + | ||
20 | + unsigned int R[D]; //resolution | ||
21 | + unsigned int header; //header size (in bytes) | ||
22 | + | ||
23 | + | ||
24 | + //basic initialization | ||
25 | + void init(){ | ||
26 | + memset(R, 0, sizeof(unsigned int) * D); //initialize the resolution to zero | ||
27 | + header = 0; //initialize the header size to zero | ||
28 | + } | ||
29 | + | ||
30 | + //returns the file size | ||
31 | + unsigned int get_file_size(){ | ||
32 | + | ||
33 | + struct stat results; | ||
34 | + if(stat(name.c_str(), &results) == 0) | ||
35 | + return results.st_size; | ||
36 | + else return 0; | ||
37 | + } | ||
38 | + | ||
39 | + bool test_file_size(){ | ||
40 | + unsigned int sum = header; //initialize the sum (in bytes) to the header size | ||
41 | + for(unsigned int i = 0; i<D; i++) //iterate over each dimension, summing the byte size | ||
42 | + sum += R[i] * sizeof(T); | ||
43 | + if(sum == get_file_size()) return true; //if the byte size matches the file size, we're golden | ||
44 | + else return false; //otherwise return an error | ||
45 | + | ||
46 | + } | ||
47 | + | ||
48 | + bool open_file(std::string filename){ | ||
49 | + //open the file as binary for reading and writing | ||
50 | + file.open(filename.c_str(), std::ios::in | std::ios::out | std::ios::binary); | ||
51 | + | ||
52 | + //if the file is successful | ||
53 | + if(file){ | ||
54 | + name = filename; //set the name | ||
55 | + if(test_file_size()) //test the file size | ||
56 | + return true; | ||
57 | + } | ||
58 | + | ||
59 | + return false; | ||
60 | + } | ||
61 | + | ||
62 | +public: | ||
63 | + | ||
64 | + bool open(std::string filename, vec<unsigned int, D> r, unsigned int h = 0){ | ||
65 | + if(!open_file(filename)) return false; | ||
66 | + | ||
67 | + for(unsigned int i = 0; i < D; i++) | ||
68 | + R[i] = r[i]; | ||
69 | + | ||
70 | + header = h; | ||
71 | + | ||
72 | + return test_file_size(); | ||
73 | + } | ||
74 | + | ||
75 | + bool open(std::string filename, unsigned int X, unsigned int h = 0){ | ||
76 | + return open(filename, vec<unsigned int, 1>(X), h); | ||
77 | + } | ||
78 | + | ||
79 | + bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int h = 0){ | ||
80 | + return open(filename, vec<unsigned int, 2>(X, Y), h); | ||
81 | + | ||
82 | + | ||
83 | + } | ||
84 | + | ||
85 | + bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int Z, unsigned int h = 0){ | ||
86 | + return open(filename, vec<unsigned int, 3>(X, Y, Z), h); | ||
87 | + } | ||
88 | + | ||
89 | +}; | ||
90 | + | ||
91 | +} | ||
92 | + | ||
93 | +#endif |
envi/envi.h
1 | -#ifndef RTS_ENVI_H | ||
2 | -#define RTS_ENVI_H | 1 | +#ifndef ENVI_HEADER_H |
2 | +#define ENVI_HEADER_H | ||
3 | 3 | ||
4 | #include <string> | 4 | #include <string> |
5 | -#include <iostream> | 5 | +#include <iostream> |
6 | #include <fstream> | 6 | #include <fstream> |
7 | -#include <sstream> | ||
8 | - | ||
9 | -#include "rts/envi/envi_header.h" | ||
10 | - | ||
11 | -/* This is a class for reading and writing ENVI binary files. This class will be updated as needed. | ||
12 | - | ||
13 | -What this class CAN currently do: | ||
14 | - *) Write band images to a BSQ file. | ||
15 | - *) Append band images to a BSQ file. | ||
16 | - *) Interpolate and query bands in a float32 BSQ file | ||
17 | -*/ | ||
18 | -class EnviFile | 7 | +#include <sstream> |
8 | +#include <vector> | ||
9 | +#include <stdlib.h> | ||
10 | + | ||
11 | +//information from an ENVI header file | ||
12 | +//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html | ||
13 | + | ||
14 | +namespace rts{ | ||
15 | + | ||
16 | +struct envi | ||
19 | { | 17 | { |
20 | - EnviHeader header; | ||
21 | - FILE* data; | ||
22 | - std::string mode; | 18 | + enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64}; |
19 | + enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z | ||
20 | + enum endianType {endianLittle, endianBig}; | ||
23 | 21 | ||
24 | - //a locked file has alread had data written..certain things can't be changed | ||
25 | - // accessor functions deal with these issues | ||
26 | - bool locked; | 22 | + std::string name; |
27 | 23 | ||
28 | - void init() | ||
29 | - { | ||
30 | - locked = false; | ||
31 | - data = NULL; | 24 | + std::string description; |
25 | + | ||
26 | + unsigned int samples; //x-axis | ||
27 | + unsigned int lines; //y-axis | ||
28 | + unsigned int bands; //spectral axis | ||
29 | + unsigned int header_offset; //header offset for binary file (in bytes) | ||
30 | + std::string file_type; //should be "ENVI Standard" | ||
31 | + | ||
32 | + envi::dataType data_type; //data representation; common value is 4 (32-bit float) | ||
33 | + | ||
34 | + | ||
35 | + envi::interleaveType interleave; | ||
36 | + | ||
37 | + std::string sensor_type; //not really used | ||
38 | + | ||
39 | + envi::endianType byte_order; //little = least significant bit first (most systems) | ||
40 | + | ||
41 | + double x_start, y_start; //coordinates of the upper-left corner of the image | ||
42 | + std::string wavelength_units; //stored wavelength units | ||
43 | + std::string z_plot_titles[2]; | ||
44 | + | ||
45 | + double pixel_size[2]; //pixel size along X and Y | ||
46 | + | ||
47 | + std::vector<std::string> band_names; //name for each band in the image | ||
48 | + std::vector<double> wavelength; //wavelength for each band | ||
49 | + | ||
50 | + envi(){ | ||
51 | + name = ""; | ||
52 | + | ||
53 | + //specify default values for a new or empty ENVI file | ||
54 | + samples = 0; | ||
55 | + lines = 0; | ||
56 | + bands = 0; | ||
57 | + header_offset = 0; | ||
58 | + data_type = float32; | ||
59 | + interleave = BSQ; | ||
60 | + byte_order = endianLittle; | ||
61 | + x_start = y_start = 0; | ||
62 | + pixel_size[0] = pixel_size[1] = 1; | ||
63 | + | ||
64 | + //strings | ||
65 | + file_type = "ENVI Standard"; | ||
66 | + sensor_type = "Unknown"; | ||
67 | + wavelength_units = "Unknown"; | ||
68 | + z_plot_titles[0] = z_plot_titles[1] = "Unknown"; | ||
32 | } | 69 | } |
33 | 70 | ||
34 | - void readonly() | ||
35 | - { | ||
36 | - if(mode == "r") | 71 | + std::string trim(std::string line){ |
72 | + //trims whitespace from the beginning and end of line | ||
73 | + unsigned int start_i, end_i; | ||
74 | + for(start_i=0; start_i < line.length(); start_i++) | ||
75 | + if(line[start_i] != 32) | ||
76 | + { | ||
77 | + break; | ||
78 | + } | ||
79 | + | ||
80 | + for(end_i = line.length()-1; end_i >= start_i; end_i--) | ||
81 | + if(line[end_i] != ' ') | ||
82 | + { | ||
83 | + break; | ||
84 | + } | ||
85 | + | ||
86 | + return line.substr(start_i, end_i - start_i+1); | ||
87 | + } | ||
88 | + | ||
89 | + | ||
90 | + std::string get_token(std::string line){ | ||
91 | + //returns a variable name; in this case we look for the '=' sign | ||
92 | + size_t i = line.find_first_of('='); | ||
93 | + | ||
94 | + std::string result; | ||
95 | + if(i != std::string::npos) | ||
96 | + result = trim(line.substr(0, i-1)); | ||
97 | + | ||
98 | + return result; | ||
99 | + } | ||
100 | + | ||
101 | + std::string get_data_str(std::string line){ | ||
102 | + size_t i = line.find_first_of('='); | ||
103 | + | ||
104 | + std::string result; | ||
105 | + if(i != std::string::npos) | ||
106 | + result = trim(line.substr(i+1)); | ||
107 | + else | ||
37 | { | 108 | { |
38 | - std::cout<<"ENVI Error: changes cannot be made to a read-only file."<<std::endl; | 109 | + std::cout<<"ENVI Header error - data not found for token: "<<get_token(line)<<std::endl; |
39 | exit(1); | 110 | exit(1); |
40 | } | 111 | } |
112 | + return result; | ||
41 | } | 113 | } |
42 | 114 | ||
43 | - //this function determines if the current software is capable of the requested change | ||
44 | - bool caps(EnviHeader new_header) | 115 | + std::string get_brace_str(std::string token, std::string line, std::ifstream &file) |
45 | { | 116 | { |
46 | - readonly(); //if the file is read-only, throw an exception | 117 | + //this function assembles all of the characters between curly braces |
118 | + //this is how strings are defined within an ENVI file | ||
47 | 119 | ||
48 | - //we currently only support BSQ | ||
49 | - if(new_header.interleave == Envi::BIP || new_header.interleave == Envi::BIL) | 120 | + std::string result; |
121 | + | ||
122 | + //first, find the starting brace | ||
123 | + size_t i; | ||
124 | + do | ||
125 | + { | ||
126 | + i = line.find_first_of('{'); | ||
127 | + if(i != std::string::npos) | ||
128 | + break; | ||
129 | + }while(file); | ||
130 | + | ||
131 | + //if i is still npos, we have reached the end of the file without a brace...something is wrong | ||
132 | + if(i == std::string::npos) | ||
50 | { | 133 | { |
51 | - std::cout<<"This software only supports BSQ."; | ||
52 | - return false; | 134 | + std::cout<<"ENVI Header error - string token declared without being defined: "<<token<<std::endl; |
135 | + exit(1); | ||
53 | } | 136 | } |
137 | + line = line.substr(i+1); | ||
54 | 138 | ||
55 | - //if the number of bands has changed | ||
56 | - if(header.bands != new_header.bands) | 139 | + //copy character data into the result string until we find a closing brace |
140 | + while(file) | ||
57 | { | 141 | { |
58 | - //the new header must be a BSQ file | ||
59 | - if(new_header.interleave != Envi::BSQ) | 142 | + i = line.find_first_of('}'); |
143 | + | ||
144 | + | ||
145 | + if(i != std::string::npos) | ||
60 | { | 146 | { |
61 | - std::cout<<"ENVI Error: can only add bands to a BSQ file."<<std::endl; | ||
62 | - return false; | 147 | + result += line.substr(0, i); |
148 | + break; | ||
63 | } | 149 | } |
150 | + else | ||
151 | + result += line; | ||
152 | + | ||
153 | + getline(file, line); | ||
64 | } | 154 | } |
65 | 155 | ||
66 | - //disallow anything that can't be done when the file is locked | ||
67 | - if(locked) | 156 | + if(i == std::string::npos) |
68 | { | 157 | { |
69 | - if(header.lines != new_header.lines) | ||
70 | - { | ||
71 | - std::cout<<"ENVI Error: cannot change the number of lines from "<<header.lines<<" to "<<new_header.lines<<" in a locked BSQ file."<<std::endl; | ||
72 | - return false; | ||
73 | - } | ||
74 | - if(header.samples != new_header.samples) | ||
75 | - { | ||
76 | - std::cout<<"ENVI Error: cannot change the number of samples in a locked BSQ file."<<std::endl; | ||
77 | - return false; | ||
78 | - } | ||
79 | - if(header.data_type != new_header.data_type) | ||
80 | - { | ||
81 | - std::cout<<"ENVI Error: cannot change the data type of a locked file."<<std::endl; | ||
82 | - return false; | ||
83 | - } | ||
84 | - if(header.byte_order != new_header.byte_order) | ||
85 | - { | ||
86 | - std::cout<<"ENVI Error: cannot change the byte order of a locked file."<<std::endl; | ||
87 | - return false; | ||
88 | - } | ||
89 | - } | ||
90 | - | ||
91 | - return true; | 158 | + std::cout<<"ENVI Header error - string token declared without a terminating '}': "<<token<<std::endl; |
159 | + exit(1); | ||
160 | + } | ||
92 | 161 | ||
162 | + return trim(result); | ||
93 | } | 163 | } |
94 | 164 | ||
95 | - EnviHeader load_header(std::string header_file) | 165 | + std::vector<std::string> get_string_seq(std::string token, std::string sequence) |
96 | { | 166 | { |
97 | - EnviHeader new_header; | ||
98 | - new_header.load(header_file); | ||
99 | - return new_header; | 167 | + //this function returns a sequence of comma-delimited strings |
168 | + std::vector<std::string> result; | ||
169 | + | ||
170 | + std::string entry; | ||
171 | + size_t i; | ||
172 | + do | ||
173 | + { | ||
174 | + i = sequence.find_first_of(','); | ||
175 | + entry = sequence.substr(0, i); | ||
176 | + sequence = sequence.substr(i+1); | ||
177 | + result.push_back(trim(entry)); | ||
178 | + }while(i != std::string::npos); | ||
179 | + | ||
180 | + return result; | ||
100 | } | 181 | } |
101 | 182 | ||
102 | - void set_header(EnviHeader new_header) | 183 | + std::vector<double> get_double_seq(std::string token, std::string sequence) |
103 | { | 184 | { |
104 | - if(caps(new_header)) | ||
105 | - header = new_header; | ||
106 | - else | ||
107 | - exit(1); | ||
108 | - } | ||
109 | - | ||
110 | - bool test_exist(std::string filename) | ||
111 | - { | ||
112 | - //tests for the existance of the specified binary file | ||
113 | - FILE* f; | ||
114 | - long sz = 0; | ||
115 | - f = fopen(filename.c_str(), "rb"); | ||
116 | - if(f == NULL) | ||
117 | - { | ||
118 | - //std::cout<<"ENVI Error: error testing file existance."<<std::endl; | ||
119 | - //exit(1); | ||
120 | - return false; | ||
121 | - } | ||
122 | - | ||
123 | - fseek(f, 0, SEEK_END); | ||
124 | - sz = ftell(f); | ||
125 | - fclose(f); | ||
126 | - | ||
127 | - if(sz>0) | ||
128 | - return true; | ||
129 | - else | ||
130 | - return false; | ||
131 | - | ||
132 | - } | ||
133 | - | ||
134 | - void get_surrounding_bands(double wavelength, unsigned int &low, unsigned int &high) | ||
135 | - { | ||
136 | - int i; | ||
137 | - int nBands = header.wavelength.size(); | ||
138 | - low = high = 0; | ||
139 | - //std::cout<<"Wavelength to search: "<<wavelength<<" Number of Bands: "<<nBands<<std::endl; | ||
140 | - for(i=0; i<nBands; i++) | ||
141 | - { | ||
142 | - if(header.wavelength[i] < wavelength) | ||
143 | - { | ||
144 | - if(header.wavelength[low] > wavelength) | ||
145 | - low = i; | ||
146 | - if(header.wavelength[i] > header.wavelength[low]) | ||
147 | - low = i; | ||
148 | - } | ||
149 | - | ||
150 | - if(header.wavelength[i] > wavelength) | ||
151 | - { | ||
152 | - if(header.wavelength[high] < wavelength) | ||
153 | - high = i; | ||
154 | - if(header.wavelength[i] < header.wavelength[high]) | ||
155 | - high = i; | ||
156 | - } | ||
157 | - //std::cout<<"Low: "<<low<<" High: "<<high<<std::endl; | ||
158 | - } | ||
159 | - //exit(1); | ||
160 | - } | ||
161 | - | ||
162 | - void interpolate_band(void* result, void* A, void* B, double a) | ||
163 | - { | ||
164 | - //interpolate between two bands independent of data type | ||
165 | - // CURRENTLY ONLY HANDLES FLOAT | ||
166 | - int X = header.samples; | ||
167 | - int Y = header.lines; | ||
168 | - int N = X * Y; | ||
169 | - | ||
170 | - if(header.data_type != Envi::float32) | ||
171 | - { | ||
172 | - std::cout<<"ENVI Error: this software only handles interpolation of 32-bit floats."<<std::endl; | ||
173 | - exit(1); | ||
174 | - } | ||
175 | - | ||
176 | - float v0, v1; | ||
177 | - for(int n=0; n<N; n++) | ||
178 | - { | ||
179 | - v0 = ((float*)A)[n]; | ||
180 | - v1 = ((float*)B)[n]; | ||
181 | - float r = v0 * a + v1 * (1.0 - a); | ||
182 | - //((float*)result)[n] = ((float*)A)[n] * a + ((float*)B)[n] * (1.0 - a); | ||
183 | - ((float*)result)[n] = r; | ||
184 | - } | ||
185 | - | ||
186 | - } | ||
187 | - | ||
188 | -public: | ||
189 | - | ||
190 | - EnviFile() | ||
191 | - { | ||
192 | - mode = "w"; | ||
193 | - init(); | 185 | + //this function returns a sequence of comma-delimited strings |
186 | + std::vector<double> result; | ||
187 | + std::string entry; | ||
188 | + size_t i; | ||
189 | + do | ||
190 | + { | ||
191 | + i = sequence.find_first_of(','); | ||
192 | + entry = sequence.substr(0, i); | ||
193 | + sequence = sequence.substr(i+1); | ||
194 | + result.push_back(atof(entry.c_str())); | ||
195 | + //std::cout<<entry<<" "; | ||
196 | + }while(i != std::string::npos); | ||
197 | + | ||
198 | + return result; | ||
194 | } | 199 | } |
195 | 200 | ||
196 | - EnviFile(std::string filename, std::string file_mode = "r") | 201 | + bool load(std::string filename) |
197 | { | 202 | { |
198 | - init(); | ||
199 | - open(filename, filename + ".hdr", file_mode); | ||
200 | - } | 203 | + //open the header file |
204 | + std::ifstream file(filename.c_str()); | ||
201 | 205 | ||
202 | - void open(std::string file_name, std::string header_name, std::string file_mode = "r") | ||
203 | - { | ||
204 | - | ||
205 | - //load the header file | ||
206 | - // if the file doesn't exist, that is okay unless it is read-only | ||
207 | - | ||
208 | - //if the file is being written, create a new header | ||
209 | - if(file_mode == "w") | ||
210 | - header.name = header_name; | ||
211 | - else if(!header.load(header_name)) | ||
212 | - { | ||
213 | - if(file_mode == "r") | ||
214 | - { | ||
215 | - std::cout<<"ENVI Error: header file not found: "<<header_name<<std::endl; | ||
216 | - exit(1); | ||
217 | - } | ||
218 | - //otherwise use the default header and save the name | ||
219 | - header.name = header_name; | ||
220 | - } | ||
221 | - | ||
222 | - mode = file_mode; | ||
223 | - | ||
224 | - //lock the file if it is read-only | ||
225 | - if(mode == "r") | ||
226 | - locked = true; | ||
227 | - else if(mode == "a" || mode == "r+" || mode == "a+") | ||
228 | - { | ||
229 | - //if the file can be edited, lock it if data has already been written | ||
230 | - if(test_exist(file_name)) | ||
231 | - locked = true; | 206 | + if(!file) |
207 | + { | ||
208 | + return false; | ||
232 | } | 209 | } |
233 | - | ||
234 | - | ||
235 | - //open the data file | ||
236 | - std::string tmpmode = mode+"b"; | ||
237 | - //std::cout<<"Mode: "<<tmpmode<<std::endl; | ||
238 | - data = fopen(file_name.c_str(), tmpmode.c_str()); | ||
239 | - if(data == NULL) | 210 | + |
211 | + //the first line should just be "ENVI" | ||
212 | + std::string line; | ||
213 | + file>>line; | ||
214 | + if(line != "ENVI") | ||
240 | { | 215 | { |
241 | - std::cout<<"ENVI Error: unable to open binary file: "<<file_name<<std::endl; | 216 | + std::cout<<"ENVI Header Error: The header doesn't appear to be an ENVI file. The first line should be 'ENVI'."<<std::endl; |
242 | exit(1); | 217 | exit(1); |
243 | } | 218 | } |
244 | 219 | ||
220 | + //for each line in the file, get the token | ||
221 | + std::string token; | ||
245 | 222 | ||
246 | - } | 223 | + //get a line |
224 | + getline(file, line); | ||
225 | + while(file) | ||
226 | + { | ||
247 | 227 | ||
248 | - void setDescription(std::string desc) | ||
249 | - { | ||
250 | - readonly(); //if the file is read-only, throw an exception | ||
251 | - header.description = desc; | ||
252 | - } | ||
253 | 228 | ||
254 | - void setZPlotTitles(std::string spectrum, std::string value) | ||
255 | - { | ||
256 | - readonly(); //if the file is read-only, throw an exception | ||
257 | - header.z_plot_titles[0] = spectrum; | ||
258 | - header.z_plot_titles[1] = value; | ||
259 | - } | ||
260 | 229 | ||
261 | - void setPixelSize(double sx, double sy) | ||
262 | - { | ||
263 | - readonly(); //if the file is read-only, throw an exception | ||
264 | - header.pixel_size[0] = sx; | ||
265 | - header.pixel_size[1] = sy; | ||
266 | - } | 230 | + //get the token |
231 | + token = get_token(line); | ||
267 | 232 | ||
268 | - void setWavelengthUnits(std::string units) | ||
269 | - { | ||
270 | - readonly(); //if the file is read-only, throw an exception | ||
271 | - header.wavelength_units = units; | ||
272 | - } | 233 | + if(token == "description") |
234 | + description = get_brace_str(token, line, file); | ||
235 | + else if(token == "band names") | ||
236 | + { | ||
237 | + std::string string_sequence = get_brace_str(token, line, file); | ||
238 | + band_names = get_string_seq(token, string_sequence); | ||
239 | + } | ||
240 | + else if(token == "wavelength") | ||
241 | + { | ||
242 | + std::string string_sequence = get_brace_str(token, line, file); | ||
243 | + wavelength = get_double_seq(token, string_sequence); | ||
244 | + } | ||
245 | + else if(token == "pixel size") | ||
246 | + { | ||
247 | + std::string string_sequence = get_brace_str(token, line, file); | ||
248 | + std::vector<double> pxsize = get_double_seq(token, string_sequence); | ||
249 | + pixel_size[0] = pxsize[0]; | ||
250 | + pixel_size[1] = pxsize[1]; | ||
251 | + } | ||
252 | + else if(token == "z plot titles") | ||
253 | + { | ||
254 | + std::string string_sequence = get_brace_str(token, line, file); | ||
255 | + std::vector<std::string> titles = get_string_seq(token, string_sequence); | ||
256 | + z_plot_titles[0] = titles[0]; | ||
257 | + z_plot_titles[1] = titles[1]; | ||
258 | + } | ||
273 | 259 | ||
274 | - void setCoordinates(double x, double y) | ||
275 | - { | ||
276 | - readonly(); //if the file is read-only, throw an exception | ||
277 | - header.x_start = x; | ||
278 | - header.y_start = y; | 260 | + else if(token == "samples") |
261 | + samples = atoi(get_data_str(line).c_str()); | ||
262 | + else if(token == "lines") | ||
263 | + lines = atoi(get_data_str(line).c_str()); | ||
264 | + else if(token == "bands") | ||
265 | + bands = atoi(get_data_str(line).c_str()); | ||
266 | + else if(token == "header offset") | ||
267 | + header_offset = atoi(get_data_str(line).c_str()); | ||
268 | + else if(token == "file type") | ||
269 | + file_type = get_data_str(line); | ||
270 | + else if(token == "data type") | ||
271 | + data_type = (dataType)atoi(get_data_str(line).c_str()); | ||
272 | + else if(token == "interleave") | ||
273 | + { | ||
274 | + std::string interleave_str = get_data_str(line); | ||
275 | + if(interleave_str == "bip") | ||
276 | + interleave = BIP; | ||
277 | + else if(interleave_str == "bil") | ||
278 | + interleave = BIL; | ||
279 | + else if(interleave_str == "bsq") | ||
280 | + interleave = BSQ; | ||
281 | + } | ||
282 | + else if(token == "sensor type") | ||
283 | + sensor_type = get_data_str(line); | ||
284 | + else if(token == "byte order") | ||
285 | + byte_order = (endianType)atoi(get_data_str(line).c_str()); | ||
286 | + else if(token == "x start") | ||
287 | + x_start = atof(get_data_str(line).c_str()); | ||
288 | + else if(token == "y start") | ||
289 | + y_start = atof(get_data_str(line).c_str()); | ||
290 | + else if(token == "wavelength units") | ||
291 | + wavelength_units = get_data_str(line); | ||
292 | + | ||
293 | + //get the next line | ||
294 | + getline(file, line); | ||
295 | + } | ||
296 | + | ||
297 | + //make sure the number of bands matches the number of wavelengths | ||
298 | + unsigned int wavelengths = wavelength.size(); | ||
299 | + if(bands != wavelengths) | ||
300 | + { | ||
301 | + std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "<<bands<<", Wavelengths = "<<wavelength.size()<<std::endl; | ||
302 | + exit(1); | ||
303 | + } | ||
304 | + | ||
305 | + //close the file | ||
306 | + file.close(); | ||
307 | + | ||
308 | + //set the file name | ||
309 | + name = filename; | ||
310 | + | ||
311 | + return true; | ||
279 | } | 312 | } |
280 | 313 | ||
281 | - //FUNCTIONS THAT MAY BE DISALLOWED IN A LOCKED FILE | ||
282 | - void setSamples(unsigned int samples) | 314 | + void save(std::string filename) |
283 | { | 315 | { |
284 | - EnviHeader newHeader = header; | ||
285 | - newHeader.samples = samples; | ||
286 | - set_header(newHeader); | 316 | + //open a file |
317 | + std::ofstream outfile(filename.c_str()); | ||
318 | + | ||
319 | + //write the ENVI type identifier | ||
320 | + outfile<<"ENVI"<<std::endl; | ||
321 | + | ||
322 | + //output all of the data | ||
323 | + outfile<<"description = {"<<std::endl; | ||
324 | + outfile<<" "<<description<<"}"<<std::endl; | ||
325 | + | ||
326 | + outfile<<"samples = "<<samples<<std::endl; | ||
327 | + outfile<<"lines = "<<lines<<std::endl; | ||
328 | + outfile<<"bands = "<<bands<<std::endl; | ||
329 | + outfile<<"header offset = "<<header_offset<<std::endl; | ||
330 | + outfile<<"file type = "<<file_type<<std::endl; | ||
331 | + outfile<<"data type = "<<data_type<<std::endl; | ||
332 | + outfile<<"interleave = "; | ||
333 | + if(interleave == BIP) | ||
334 | + outfile<<"bip"; | ||
335 | + if(interleave == BIL) | ||
336 | + outfile<<"bil"; | ||
337 | + if(interleave == BSQ) | ||
338 | + outfile<<"bsq"; | ||
339 | + outfile<<std::endl; | ||
340 | + outfile<<"sensor type = "<<sensor_type<<std::endl; | ||
341 | + outfile<<"byte order = "<<byte_order<<std::endl; | ||
342 | + outfile<<"x start = "<<x_start<<std::endl; | ||
343 | + outfile<<"y start = "<<y_start<<std::endl; | ||
344 | + outfile<<"wavelength units = "<<wavelength_units<<std::endl; | ||
345 | + outfile<<"z plot titles = {"; | ||
346 | + outfile<<z_plot_titles[0]<<", "<<z_plot_titles[1]<<"}"<<std::endl; | ||
347 | + outfile<<"pixel size = {"<<pixel_size[0]<<", "<<pixel_size[1]<<", units=Meters}"<<std::endl; | ||
348 | + if(band_names.size() > 0) | ||
349 | + { | ||
350 | + outfile<<"band names = {"<<std::endl; | ||
351 | + for(unsigned int i=0; i<band_names.size(); i++) | ||
352 | + { | ||
353 | + outfile<<band_names[i]; | ||
354 | + if(i < band_names.size() - 1) | ||
355 | + outfile<<", "; | ||
356 | + } | ||
357 | + outfile<<"}"<<std::endl; | ||
358 | + } | ||
359 | + outfile<<"wavelength = {"<<std::endl; | ||
360 | + for(unsigned int i=0; i<wavelength.size()-1; i++) | ||
361 | + outfile<<wavelength[i]<<", "; | ||
362 | + outfile<<wavelength.back()<<"}"<<std::endl; | ||
363 | + | ||
364 | + outfile.close(); | ||
287 | } | 365 | } |
288 | 366 | ||
289 | - void setLines(unsigned int lines) | ||
290 | - { | ||
291 | - EnviHeader newHeader = header; | ||
292 | - newHeader.lines = lines; | ||
293 | - set_header(newHeader); | ||
294 | - } | ||
295 | - | ||
296 | - unsigned int lines() {return header.lines;} | ||
297 | - unsigned int samples() {return header.samples;} | ||
298 | - unsigned int bands() {return header.bands;} | ||
299 | - double wavelength(unsigned int b) {return header.wavelength[b];} | ||
300 | - | ||
301 | - void setBands(unsigned int bands) | 367 | + void save() |
302 | { | 368 | { |
303 | - EnviHeader newHeader = header; | ||
304 | - newHeader.bands = bands; | ||
305 | - set_header(newHeader); | ||
306 | - } | ||
307 | - | ||
308 | - unsigned int getElementSize() | ||
309 | - { | ||
310 | - //return the size of each element in bytes | ||
311 | - return header.valsize(); | ||
312 | - } | ||
313 | - unsigned int getBandSize() | ||
314 | - { | ||
315 | - //returns the size of a band in bytes | ||
316 | - return header.valsize() * header.lines * header.samples; | ||
317 | - } | ||
318 | - | ||
319 | - Envi::dataType getDataType() | ||
320 | - { | ||
321 | - return header.data_type; | ||
322 | - } | ||
323 | - | ||
324 | - //DATA MANIPULATION | ||
325 | - void addBand(void* band, unsigned int samples, unsigned int lines, double wavelength, std::string band_name ="") | ||
326 | - { | ||
327 | - //add a band to the file | ||
328 | - | ||
329 | - EnviHeader newHeader = header; | ||
330 | - newHeader.bands++; | ||
331 | - newHeader.samples = samples; | ||
332 | - newHeader.lines = lines; | ||
333 | - newHeader.wavelength.push_back(wavelength); | ||
334 | - if(band_name != "") | ||
335 | - newHeader.band_names.push_back(band_name); | ||
336 | - set_header(newHeader); | ||
337 | - | ||
338 | - //copy the data to the file | ||
339 | - fwrite(band, header.valsize(), samples * lines, data); | ||
340 | - | ||
341 | - //since data was written, the file must be locked | ||
342 | - locked = true; | ||
343 | - } | ||
344 | - | ||
345 | - //DATA RETRIEVAL | ||
346 | - void getBand(void* ptr, unsigned int n) | ||
347 | - { | ||
348 | - //reads the n'th band and writes it to the given pointer | ||
349 | - // memory has been assumed to be allocated | ||
350 | - | ||
351 | - if(n > header.wavelength.size()) | ||
352 | - { | ||
353 | - std::cout<<"ENVI Error: Invalid band number."<<std::endl; | ||
354 | - return; | ||
355 | - } | ||
356 | - | ||
357 | - | ||
358 | - if(header.interleave == Envi::BSQ) | ||
359 | - { | ||
360 | - | ||
361 | - //compute the position of the desired band (relative to the beginning of the file) | ||
362 | - int bandpos = header.header_offset + getBandSize() * n; | ||
363 | - | ||
364 | - //seek to that position | ||
365 | - int seek_result = fseek(data, bandpos, SEEK_SET); | ||
366 | - if(seek_result) | ||
367 | - { | ||
368 | - std::cout<<"ENVI Error: Error seeking through data file."<<std::endl; | ||
369 | - return; | ||
370 | - } | ||
371 | - | ||
372 | - //read the band data from the file | ||
373 | - size_t n_read = fread(ptr, getElementSize(), header.samples * header.lines, data); | ||
374 | - if(n_read != header.samples * header.lines) | ||
375 | - { | ||
376 | - std::cout<<"ENVI Error -- Error reading band data: "<<n_read<<"/"<<samples() * lines()<<" pixels read"<<std::endl; | ||
377 | - exit(1); | ||
378 | - } | ||
379 | - | ||
380 | - return; | ||
381 | - } | ||
382 | - else | ||
383 | - { | ||
384 | - std::cout<<"ENVI Error: Only BSQ operations are currently supported."<<std::endl; | ||
385 | - return; | ||
386 | - } | ||
387 | - } | ||
388 | - | ||
389 | - void getWavelength(void* band, double wavelength) | ||
390 | - { | ||
391 | - //this function retrieves a band via interpolation of wavelength values | ||
392 | - | ||
393 | - //get the low and high band numbers | ||
394 | - unsigned int low, high; | ||
395 | - get_surrounding_bands(wavelength, low, high); | ||
396 | - //std::cout<<"High: "<<high<<" Low: "<<low<<std::endl; | ||
397 | - | ||
398 | - //calculate the position between the two bands | ||
399 | - double a; | ||
400 | - if(low == high) | ||
401 | - a = 1.0; | ||
402 | - else | ||
403 | - a = (wavelength - header.wavelength[low]) / (header.wavelength[high] - header.wavelength[low]); | ||
404 | - | ||
405 | - //read both bands | ||
406 | - void* A; | ||
407 | - A = malloc( getBandSize() ); | ||
408 | - getBand(A, low); | ||
409 | - | ||
410 | - void* B; | ||
411 | - B = malloc( getBandSize() ); | ||
412 | - getBand(B, high); | ||
413 | - | ||
414 | - //interpolate between the bands | ||
415 | - interpolate_band(band, A, B, a); | ||
416 | - | ||
417 | - //free the surrounding bands | ||
418 | - free(A); | ||
419 | - free(B); | ||
420 | - } | ||
421 | - | ||
422 | - //close file | ||
423 | - void close() | ||
424 | - { | ||
425 | - //std::cout<<"ENVI File Mode: "<<mode<<std::endl; | ||
426 | - | ||
427 | - //close the data stream | ||
428 | - fclose(data); | ||
429 | - | ||
430 | - //close the header | ||
431 | - if(mode != "r") | ||
432 | - header.save(); | 369 | + //std::cout<<"ENVI Header Name: "<<name<<std::endl; |
370 | + save(name); | ||
433 | } | 371 | } |
434 | 372 | ||
435 | -}; //end EnviFile | ||
436 | - | 373 | + //returns the size of a single value (in bytes) |
374 | + unsigned int valsize() | ||
375 | + { | ||
376 | + switch(data_type) | ||
377 | + { | ||
378 | + case int8: //1 = 8-bit byte | ||
379 | + return 1; | ||
380 | + case int16: //16-bit signed integer | ||
381 | + case uint16: //16-bit unsigned integer | ||
382 | + return 2; | ||
383 | + case int32: //32-bit signed long integer | ||
384 | + case float32: //32-bit floating point | ||
385 | + case uint32: //32-bit unsigned long integer | ||
386 | + return 4; | ||
387 | + case float64: //64-bit double-precision floating point | ||
388 | + case complex32: //32-bit complex value | ||
389 | + case int64: //64-bit signed long integer | ||
390 | + case uint64: //64-bit unsigned long integer | ||
391 | + return 8; | ||
392 | + case complex64: //64-bit complex value | ||
393 | + return 16; | ||
394 | + default: | ||
395 | + return 0; | ||
396 | + } | ||
437 | 397 | ||
438 | -#endif | 398 | + } |
399 | +}; //end EnviHeader | ||
400 | +} | ||
401 | +#endif |
math/complexfield.cuh
@@ -55,7 +55,7 @@ public: | @@ -55,7 +55,7 @@ public: | ||
55 | int index; //result of the max operation | 55 | int index; //result of the max operation |
56 | rts::complex<T> result; | 56 | rts::complex<T> result; |
57 | 57 | ||
58 | - if(sizeof(T) == 4) | 58 | + if(sizeof(T) == 8) |
59 | stat = cublasIcamax(handle, L, (const cuComplex*)X[n], 1, &index); | 59 | stat = cublasIcamax(handle, L, (const cuComplex*)X[n], 1, &index); |
60 | else | 60 | else |
61 | stat = cublasIzamax(handle, L, (const cuDoubleComplex*)X[n], 1, &index); | 61 | stat = cublasIzamax(handle, L, (const cuDoubleComplex*)X[n], 1, &index); |
@@ -114,7 +114,7 @@ public: | @@ -114,7 +114,7 @@ public: | ||
114 | 114 | ||
115 | void toImage(std::string filename, attribute type = magnitude, unsigned int n=0){ | 115 | void toImage(std::string filename, attribute type = magnitude, unsigned int n=0){ |
116 | 116 | ||
117 | - realfield<T, 1, true> rf(R[0], R[1]); | 117 | + field<T, 1> rf(R[0], R[1]); |
118 | 118 | ||
119 | //get cuda parameters | 119 | //get cuda parameters |
120 | dim3 blocks, grids; | 120 | dim3 blocks, grids; |
@@ -122,7 +122,7 @@ public: | @@ -122,7 +122,7 @@ public: | ||
122 | 122 | ||
123 | if(type == magnitude){ | 123 | if(type == magnitude){ |
124 | gpu_complexfield_mag <<<grids, blocks>>> (rf.ptr(), X[n], R[0], R[1]); | 124 | gpu_complexfield_mag <<<grids, blocks>>> (rf.ptr(), X[n], R[0], R[1]); |
125 | - rf.toImages(filename, 0); | 125 | + rf.toImage(filename, n, true); |
126 | } | 126 | } |
127 | 127 | ||
128 | } | 128 | } |
@@ -134,4 +134,4 @@ public: | @@ -134,4 +134,4 @@ public: | ||
134 | } //end namespace rts | 134 | } //end namespace rts |
135 | 135 | ||
136 | 136 | ||
137 | -#endif | ||
138 | \ No newline at end of file | 137 | \ No newline at end of file |
138 | +#endif |
math/field.cuh
@@ -5,10 +5,14 @@ | @@ -5,10 +5,14 @@ | ||
5 | #include <string> | 5 | #include <string> |
6 | #include <sstream> | 6 | #include <sstream> |
7 | 7 | ||
8 | +#include "cublas_v2.h" | ||
9 | +#include <cuda_runtime.h> | ||
10 | + | ||
8 | #include "../math/rect.h" | 11 | #include "../math/rect.h" |
9 | #include "../cuda/threads.h" | 12 | #include "../cuda/threads.h" |
10 | #include "../cuda/error.h" | 13 | #include "../cuda/error.h" |
11 | #include "../cuda/devices.h" | 14 | #include "../cuda/devices.h" |
15 | +#include "../visualization/colormap.h" | ||
12 | 16 | ||
13 | 17 | ||
14 | namespace rts{ | 18 | namespace rts{ |
@@ -86,6 +90,41 @@ protected: | @@ -86,6 +90,41 @@ protected: | ||
86 | grids = dim3((R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK); | 90 | grids = dim3((R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK); |
87 | } | 91 | } |
88 | 92 | ||
93 | + //find the maximum value of component n | ||
94 | + T find_max(unsigned int n){ | ||
95 | + cublasStatus_t stat; | ||
96 | + cublasHandle_t handle; | ||
97 | + | ||
98 | + //create a CUBLAS handle | ||
99 | + stat = cublasCreate(&handle); | ||
100 | + if(stat != CUBLAS_STATUS_SUCCESS){ | ||
101 | + std::cout<<"CUBLAS Error: initialization failed"<<std::endl; | ||
102 | + exit(1); | ||
103 | + } | ||
104 | + | ||
105 | + int L = R[0] * R[1]; //compute the number of discrete points in a slice | ||
106 | + int index; //result of the max operation | ||
107 | + T result; | ||
108 | + | ||
109 | + if(sizeof(T) == 4) | ||
110 | + stat = cublasIsamax(handle, L, (const float*)X[n], 1, &index); | ||
111 | + else | ||
112 | + stat = cublasIdamax(handle, L, (const double*)X[n], 1, &index); | ||
113 | + | ||
114 | + index -= 1; //adjust for 1-based indexing | ||
115 | + | ||
116 | + //if there was a GPU error, terminate | ||
117 | + if(stat != CUBLAS_STATUS_SUCCESS){ | ||
118 | + std::cout<<"CUBLAS Error: failure finding maximum value."<<std::endl; | ||
119 | + exit(1); | ||
120 | + } | ||
121 | + | ||
122 | + //retrieve the maximum value for this slice and store it in the maxVal array | ||
123 | + std::cout<<X[n]<<std::endl; | ||
124 | + HANDLE_ERROR(cudaMemcpy(&result, X[n] + index, sizeof(T), cudaMemcpyDeviceToHost)); | ||
125 | + return result; | ||
126 | + } | ||
127 | + | ||
89 | public: | 128 | public: |
90 | 129 | ||
91 | //returns a list of file names given an input string with wild cards | 130 | //returns a list of file names given an input string with wild cards |
@@ -286,10 +325,20 @@ public: | @@ -286,10 +325,20 @@ public: | ||
286 | rts::gpu_field_crop <<<dimGrid, dimBlock>>> (result.X[n], X[n], R[0], R[1], width, height); | 325 | rts::gpu_field_crop <<<dimGrid, dimBlock>>> (result.X[n], X[n], R[0], R[1], width, height); |
287 | 326 | ||
288 | return result; | 327 | return result; |
328 | + } | ||
329 | + | ||
330 | + //save an image representing component n | ||
331 | + void toImage(std::string filename, unsigned int n = 0, | ||
332 | + bool positive = false, rts::colormapType cmap = rts::cmBrewer){ | ||
333 | + T max_val = find_max(n); //find the maximum value | ||
289 | 334 | ||
335 | + if(positive) //if the field is positive, use the range [0 max_val] | ||
336 | + rts::gpu2image<T>(X[n], filename, R[0], R[1], 0, max_val, cmap); | ||
337 | + else | ||
338 | + rts::gpu2image<T>(X[n], filename, R[0], R[1], -max_val, max_val, cmap); | ||
290 | } | 339 | } |
291 | 340 | ||
292 | }; | 341 | }; |
293 | 342 | ||
294 | } //end namespace rts | 343 | } //end namespace rts |
295 | -#endif | ||
296 | \ No newline at end of file | 344 | \ No newline at end of file |
345 | +#endif |
math/function.h
@@ -2,7 +2,6 @@ | @@ -2,7 +2,6 @@ | ||
2 | #define RTS_FUNCTION_H | 2 | #define RTS_FUNCTION_H |
3 | 3 | ||
4 | #include <string> | 4 | #include <string> |
5 | -#include <cmath> | ||
6 | 5 | ||
7 | namespace rts{ | 6 | namespace rts{ |
8 | 7 | ||
@@ -59,7 +58,7 @@ protected: | @@ -59,7 +58,7 @@ protected: | ||
59 | 58 | ||
60 | public: | 59 | public: |
61 | function(){ | 60 | function(){ |
62 | - range[0] = range[1] = NAN; | 61 | + range[0] = range[1] = 0; |
63 | bounding[0] = bounding[1] = 0; | 62 | bounding[0] = bounding[1] = 0; |
64 | } | 63 | } |
65 | 64 | ||
@@ -182,7 +181,8 @@ public: | @@ -182,7 +181,8 @@ public: | ||
182 | function<Tx, Ty> & operator= (const Ty & rhs){ | 181 | function<Tx, Ty> & operator= (const Ty & rhs){ |
183 | X.clear(); | 182 | X.clear(); |
184 | Y.clear(); | 183 | Y.clear(); |
185 | - if(rhs != 0) //if the RHS is zero, just clear, otherwise add one value of RHS | 184 | + bounding[0] = bounding[1] = rhs; //set the boundary values to rhs |
185 | + if(rhs != 0) //if the RHS is zero, just clear, otherwise add one value of RHS | ||
186 | insert(0, rhs); | 186 | insert(0, rhs); |
187 | 187 | ||
188 | return *this; | 188 | return *this; |
optics/mirst-1d.cuh
1 | #include "../optics/material.h" | 1 | #include "../optics/material.h" |
2 | #include "../math/complexfield.cuh" | 2 | #include "../math/complexfield.cuh" |
3 | #include "../math/constants.h" | 3 | #include "../math/constants.h" |
4 | +#include "../envi/bil.h" | ||
4 | 5 | ||
5 | #include "cufft.h" | 6 | #include "cufft.h" |
6 | 7 | ||
@@ -163,6 +164,8 @@ private: | @@ -163,6 +164,8 @@ private: | ||
163 | 164 | ||
164 | T NA[2]; //numerical aperature (central obscuration and outer diameter) | 165 | T NA[2]; //numerical aperature (central obscuration and outer diameter) |
165 | 166 | ||
167 | + function<T, T> source_profile; //profile (spectrum) of the source (expressed in inverse centimeters) | ||
168 | + | ||
166 | complexfield<T, 1> scratch; //scratch GPU memory used to build samples, transforms, etc. | 169 | complexfield<T, 1> scratch; //scratch GPU memory used to build samples, transforms, etc. |
167 | 170 | ||
168 | void fft(int direction = CUFFT_FORWARD){ | 171 | void fft(int direction = CUFFT_FORWARD){ |
@@ -251,7 +254,7 @@ private: | @@ -251,7 +254,7 @@ private: | ||
251 | HANDLE_ERROR(cudaMemcpy( gpuRi + inu, &ri, sizeof(complex<T>), cudaMemcpyHostToDevice )); | 254 | HANDLE_ERROR(cudaMemcpy( gpuRi + inu, &ri, sizeof(complex<T>), cudaMemcpyHostToDevice )); |
252 | 255 | ||
253 | //save the source profile to the GPU | 256 | //save the source profile to the GPU |
254 | - source = 1; | 257 | + source = source_profile(10000 / lambdas[inu]); |
255 | HANDLE_ERROR(cudaMemcpy( gpuSrc + inu, &source, sizeof(T), cudaMemcpyHostToDevice )); | 258 | HANDLE_ERROR(cudaMemcpy( gpuSrc + inu, &source, sizeof(T), cudaMemcpyHostToDevice )); |
256 | 259 | ||
257 | } | 260 | } |
@@ -311,6 +314,11 @@ private: | @@ -311,6 +314,11 @@ private: | ||
311 | scratch = scratch.crop(Z, S); | 314 | scratch = scratch.crop(Z, S); |
312 | } | 315 | } |
313 | 316 | ||
317 | + //save the scratch field as a binary file | ||
318 | + void to_binary(std::string filename){ | ||
319 | + | ||
320 | + } | ||
321 | + | ||
314 | 322 | ||
315 | public: | 323 | public: |
316 | 324 | ||
@@ -322,6 +330,7 @@ public: | @@ -322,6 +330,7 @@ public: | ||
322 | NA[0] = 0; | 330 | NA[0] = 0; |
323 | NA[1] = 0.8; | 331 | NA[1] = 0.8; |
324 | S = 0; | 332 | S = 0; |
333 | + source_profile = 1; | ||
325 | } | 334 | } |
326 | 335 | ||
327 | //add a layer, thickness = microns | 336 | //add a layer, thickness = microns |
@@ -334,6 +343,11 @@ public: | @@ -334,6 +343,11 @@ public: | ||
334 | add_layer(material<T>(filename), thickness); | 343 | add_layer(material<T>(filename), thickness); |
335 | } | 344 | } |
336 | 345 | ||
346 | + //adds a profile spectrum for the light source | ||
347 | + void set_source(std::string filename){ | ||
348 | + source_profile.load(filename); | ||
349 | + } | ||
350 | + | ||
337 | //adds a block of wavenumbers (cm^-1) to the simulation parameters | 351 | //adds a block of wavenumbers (cm^-1) to the simulation parameters |
338 | void add_wavenumbers(unsigned int start, unsigned int stop, unsigned int step){ | 352 | void add_wavenumbers(unsigned int start, unsigned int stop, unsigned int step){ |
339 | unsigned int nu = start; | 353 | unsigned int nu = start; |
@@ -368,6 +382,10 @@ public: | @@ -368,6 +382,10 @@ public: | ||
368 | na(0, out); | 382 | na(0, out); |
369 | } | 383 | } |
370 | 384 | ||
385 | + rts::function<T, T> get_source(){ | ||
386 | + return source_profile; | ||
387 | + } | ||
388 | + | ||
371 | void save_sample(std::string filename){ | 389 | void save_sample(std::string filename){ |
372 | //create a sample and save the magnitude as an image | 390 | //create a sample and save the magnitude as an image |
373 | build_sample(); | 391 | build_sample(); |
@@ -375,7 +393,7 @@ public: | @@ -375,7 +393,7 @@ public: | ||
375 | scratch.toImage(filename, rts::complexfield<T, 1>::magnitude); | 393 | scratch.toImage(filename, rts::complexfield<T, 1>::magnitude); |
376 | } | 394 | } |
377 | 395 | ||
378 | - void save_mirst(std::string filename){ | 396 | + void save_mirst(std::string filename, bool binary = true){ |
379 | //apply the MIRST filter to a sample and save the image | 397 | //apply the MIRST filter to a sample and save the image |
380 | 398 | ||
381 | //build the sample in the Fourier domain | 399 | //build the sample in the Fourier domain |
@@ -390,7 +408,10 @@ public: | @@ -390,7 +408,10 @@ public: | ||
390 | crop(); | 408 | crop(); |
391 | 409 | ||
392 | //save the image | 410 | //save the image |
393 | - scratch.toImage(filename, rts::complexfield<T, 1>::magnitude); | 411 | + if(binary) |
412 | + to_binary(filename); | ||
413 | + else | ||
414 | + scratch.toImage(filename, rts::complexfield<T, 1>::magnitude); | ||
394 | } | 415 | } |
395 | 416 | ||
396 | 417 | ||
@@ -411,6 +432,9 @@ public: | @@ -411,6 +432,9 @@ public: | ||
411 | for(unsigned int l=0; l<layers.size(); l++) | 432 | for(unsigned int l=0; l<layers.size(); l++) |
412 | ss<<"layer "<<l<<": "<<layers[l]<<" um"<<"---------"<<std::endl<<matlist[l].str()<<std::endl; | 433 | ss<<"layer "<<l<<": "<<layers[l]<<" um"<<"---------"<<std::endl<<matlist[l].str()<<std::endl; |
413 | 434 | ||
435 | + ss<<"source profile-----------"<<std::endl; | ||
436 | + ss<<get_source().str()<<std::endl; | ||
437 | + | ||
414 | return ss.str(); | 438 | return ss.str(); |
415 | 439 | ||
416 | 440 |