Commit 9b2a5d713cf6d32a0ba1072319cfa83f4d9ad79a
1 parent
2ce6954b
implemented finite differences and SG filters in stim::envi
Showing
7 changed files
with
521 additions
and
0 deletions
Show diff stats
1 | +function c = fd_coefficients(z,x,m) | ||
2 | +% Calculates FD weights. The parameters are: | ||
3 | +% z location where approximations are to be accurate, | ||
4 | +% x vector with x-coordinates for grid points, | ||
5 | +% m highest derivative that we want to find weights for | ||
6 | +% c array size m+1,lentgh(x) containing (as output) in | ||
7 | +% successive rows the weights for derivatives 0,1,...,m. | ||
8 | + | ||
9 | +n=length(x); c=zeros(m+1,n); c1=1; c4=x(1)-z; c(1,1)=1; | ||
10 | +for i=2:n | ||
11 | + mn=min(i,m+1); c2=1; c5=c4; c4=x(i)-z; | ||
12 | + for j=1:i-1 | ||
13 | + c3=x(i)-x(j); c2=c2*c3; | ||
14 | + if j==i-1 | ||
15 | + c(2:mn,i)=c1*((1:mn-1)'.*c(1:mn-1,i-1)-c5*c(2:mn,i-1))/c2; | ||
16 | + c(1,i)=-c1*c5*c(1,i-1)/c2; | ||
17 | + end | ||
18 | + c(2:mn,j)=(c4*c(2:mn,j)-(1:mn-1)'.*c(1:mn-1,j))/c3; | ||
19 | + c(1,j)=c4*c(1,j)/c3; | ||
20 | + end | ||
21 | + c1=c2; | ||
22 | +end | ||
0 | \ No newline at end of file | 23 | \ No newline at end of file |
1 | +function C = sg_coefficients(n, order) | ||
2 | + | ||
3 | +if(mod(n, 2) == 0) | ||
4 | + disp('The number of coefficients must be odd'); | ||
5 | + return; | ||
6 | +end | ||
7 | + | ||
8 | +%assemble the column vector based on positions | ||
9 | +r = floor(n/2); %maximum extent around zero (0) | ||
10 | +x = -r:1:r; | ||
11 | + | ||
12 | +%calculate J | ||
13 | +J = zeros(n, order + 1); | ||
14 | + | ||
15 | +%columns values are 1, x_i, x_i^2, ... | ||
16 | +for i = 1:order+1 | ||
17 | + J(:, i) = (x').^(i-1); | ||
18 | +end | ||
19 | +C = (J' * J)^(-1) * J'; | ||
0 | \ No newline at end of file | 20 | \ No newline at end of file |
stim/envi/bil.h
@@ -1174,7 +1174,106 @@ public: | @@ -1174,7 +1174,106 @@ public: | ||
1174 | } | 1174 | } |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | + /// Convolve the given band range with a kernel specified by a vector of coefficients. | ||
1177 | 1178 | ||
1179 | + /// @param outfile is an already open stream to the output file | ||
1180 | + /// @param C is an array of coefficients | ||
1181 | + /// @param start is the band to start processing (the first coefficient starts here) | ||
1182 | + /// @param nbands is the number of bands to process | ||
1183 | + /// @param center is the index for the center coefficient for the kernel (used to set the wavelengths in the output file) | ||
1184 | + | ||
1185 | + void convolve(std::string outfile, std::vector<double> C, size_t start, size_t end, bool PROGRESS = false){ | ||
1186 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1187 | + size_t B = end - start + 1; | ||
1188 | + size_t Xb = X() * sizeof(T); //calculate the size of a band (frame) in bytes | ||
1189 | + size_t XBb = Xb * Z(); | ||
1190 | + | ||
1191 | + size_t N = C.size(); //get the number of bands that the kernel spans | ||
1192 | + std::deque<T*> frame(N, NULL); //create an array to store pointers to each frame | ||
1193 | + for(size_t f = 0; f < N; f++) | ||
1194 | + frame[f] = (T*)malloc(Xb); //allocate space for the frame | ||
1195 | + | ||
1196 | + T* outline = (T*)malloc(Xb); //allocate space for the output band | ||
1197 | + | ||
1198 | + //Implementation: In order to minimize reads from secondary storage, each band is only loaded once into the 'frame' deque. | ||
1199 | + // When a new band is loaded, the last band is popped, a new frame is copied to the pointer, and it is | ||
1200 | + // re-inserted into the deque. | ||
1201 | + for(size_t y = 0; y < Y(); y++){ | ||
1202 | + file.seekg(y * XBb + start * Xb, std::ios::beg); //move to the beginning of the 'start' band | ||
1203 | + for(size_t f = 0; f < N; f++) //for each frame | ||
1204 | + file.read((char*)frame[f], Xb); //load the frame | ||
1205 | + for(size_t b = 0; b < B; b++){ //for each band | ||
1206 | + memset(outline, 0, Xb); //set the output band to zero (0) | ||
1207 | + for(size_t c = 0; c < N; c++){ //for each frame (corresponding to each coefficient) | ||
1208 | + for(size_t x = 0; x < X(); x++){ //for each pixel | ||
1209 | + outline[x] += (T)(C[c] * frame[c][x]); //calculate the contribution of the current frame (scaled by the corresponding coefficient) | ||
1210 | + } | ||
1211 | + } | ||
1212 | + out.write((char*)outline, Xb); //output the band | ||
1213 | + file.read((char*)frame[0], Xb); //read the next band | ||
1214 | + frame.push_back(frame.front()); //put the first element in the back | ||
1215 | + frame.pop_front(); //pop the first element | ||
1216 | + } | ||
1217 | + if(PROGRESS) progress = (double)(y+1) / (double)Y() * 100; | ||
1218 | + } | ||
1219 | + } | ||
1220 | + | ||
1221 | + /// Approximate the spectral derivative of the image | ||
1222 | + | ||
1223 | + void deriv(std::string outfile, size_t d, size_t order, const std::vector<double> w = std::vector<double>(), bool PROGRESS = false){ | ||
1224 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1225 | + | ||
1226 | + size_t Xb = X() * sizeof(T); //calculate the size of a line (frame) in bytes | ||
1227 | + size_t XBb = Xb * Z(); | ||
1228 | + size_t B = Z(); | ||
1229 | + | ||
1230 | + file.seekg(0, std::ios::beg); //seek to the beginning of the file | ||
1231 | + | ||
1232 | + size_t N = order + d; //approximating a derivative requires order + d samples | ||
1233 | + std::deque<T*> frame(N, NULL); //create an array to store pointers to each frame | ||
1234 | + for(size_t f = 0; f < N; f++) //for each frame | ||
1235 | + frame[f] = (T*)malloc(Xb); //allocate space for the frame | ||
1236 | + | ||
1237 | + T* outline = (T*)malloc(Xb); //allocate space for the output band | ||
1238 | + | ||
1239 | + //Implementation: In order to minimize reads from secondary storage, each band is only loaded once into the 'frame' deque. | ||
1240 | + // When a new band is loaded, the last band is popped, a new frame is copied to the pointer, and it is | ||
1241 | + // re-inserted into the deque. | ||
1242 | + size_t mid = (size_t)(N / 2); //calculate the mid point of the kernel | ||
1243 | + size_t iw; //index to the first wavelength used to evaluate the derivative at this band | ||
1244 | + | ||
1245 | + for(size_t y = 0; y < Y(); y++){ | ||
1246 | + //file.seekg(y * XBb, std::ios::beg); //seek to the beginning of the current Y plane | ||
1247 | + for(size_t f = 0; f < N; f++) //for each frame | ||
1248 | + file.read((char*)frame[f], Xb); //load a line | ||
1249 | + | ||
1250 | + for(size_t b = 0; b < B; b++){ //for each band | ||
1251 | + if(b < mid) //calculate the first wavelength used to evaluate the derivative at this band | ||
1252 | + iw = 0; | ||
1253 | + else if(b > B - (N - mid + 1)) | ||
1254 | + iw = B - N; | ||
1255 | + else{ | ||
1256 | + iw = b - mid; | ||
1257 | + file.read((char*)frame[0], Xb); //read the next band | ||
1258 | + frame.push_back(frame.front()); //put the first element in the back | ||
1259 | + frame.pop_front(); //pop the first element | ||
1260 | + } | ||
1261 | + std::vector<double> w_pts(w.begin() + iw, w.begin() + iw + N); //get the wavelengths corresponding to each sample | ||
1262 | + std::vector<double> C = diff_coefficients(w[b], w_pts, d); //get the optimal sample weights | ||
1263 | + | ||
1264 | + memset(outline, 0, Xb); //set the output band to zero (0) | ||
1265 | + for(size_t c = 0; c < N; c++){ //for each frame (corresponding to each coefficient) | ||
1266 | + for(size_t x = 0; x < X(); x++){ //for each pixel | ||
1267 | + outline[x] += (T)(C[c] * frame[c][x]); //calculate the contribution of the current frame (scaled by the corresponding coefficient) | ||
1268 | + } | ||
1269 | + } | ||
1270 | + out.write((char*)outline, Xb); //output the band | ||
1271 | + | ||
1272 | + } | ||
1273 | + if(PROGRESS) progress = (double)(y+1) / (double)Y() * 100; | ||
1274 | + } | ||
1275 | + | ||
1276 | + } | ||
1178 | 1277 | ||
1179 | /// Close the file. | 1278 | /// Close the file. |
1180 | bool close(){ | 1279 | bool close(){ |
stim/envi/bip.h
@@ -1250,6 +1250,99 @@ public: | @@ -1250,6 +1250,99 @@ public: | ||
1250 | } | 1250 | } |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | + /// Convolve the given band range with a kernel specified by a vector of coefficients. | ||
1254 | + | ||
1255 | + /// @param outfile is an already open stream to the output file | ||
1256 | + /// @param C is an array of coefficients | ||
1257 | + /// @param start is the band to start processing (the first coefficient starts here) | ||
1258 | + /// @param nbands is the number of bands to process | ||
1259 | + /// @param center is the index for the center coefficient for the kernel (used to set the wavelengths in the output file) | ||
1260 | + | ||
1261 | + void convolve(std::string outfile, std::vector<double> C, size_t start, size_t end, bool PROGRESS = false){ | ||
1262 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1263 | + | ||
1264 | + size_t N = end - start + 1; //number of bands in the output spectrum | ||
1265 | + size_t Nb = N * sizeof(T); //size of the output spectrum in bytes | ||
1266 | + size_t B = Z(); //calculate the number of values in a spectrum | ||
1267 | + size_t Bb = B * sizeof(T); //calculate the size of a spectrum in bytes | ||
1268 | + | ||
1269 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | ||
1270 | + | ||
1271 | + size_t nC = C.size(); //get the number of bands that the kernel spans | ||
1272 | + T* inspec = (T*)malloc(Bb); //allocate space for the input spectrum | ||
1273 | + T* outspec = (T*)malloc(Nb); //allocate space for the output spectrum | ||
1274 | + | ||
1275 | + size_t XY = X() * Y(); //number of pixels in the image | ||
1276 | + for(size_t xy = 0; xy < XY; xy++){ //for each pixel | ||
1277 | + file.read((char*)inspec, Bb); //read an input spectrum | ||
1278 | + memset(outspec, 0, Nb); //set the output spectrum to zero (0) | ||
1279 | + for(size_t b = 0; b < N; b++){ //for each component of the spectrum | ||
1280 | + for(size_t c = 0; c < nC; c++){ //for each coefficient in the kernel | ||
1281 | + outspec[b] += (T)(inspec[b + start + c] * C[c]); //perform the sum/multiply part of the convolution | ||
1282 | + } | ||
1283 | + } | ||
1284 | + out.write((char*)outspec, Nb); //output the band | ||
1285 | + if(PROGRESS) progress = (double)(xy+1) / (double)XY * 100; | ||
1286 | + } | ||
1287 | + } | ||
1288 | + | ||
1289 | + void deriv(std::string outfile, size_t d, size_t order, const std::vector<double> w, bool PROGRESS = false){ | ||
1290 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1291 | + | ||
1292 | + | ||
1293 | + size_t B = Z(); //calculate the number of values in a spectrum | ||
1294 | + size_t Bb = B * sizeof(T); //calculate the size of a spectrum in bytes | ||
1295 | + | ||
1296 | + bool UNIFORM = true; | ||
1297 | + double ds = w[1] - w[0]; //initialize ds | ||
1298 | + for(size_t b = 1; b < B; b++) //test to see if the spectral spacing is uniform (if it is, convolution is much faster) | ||
1299 | + if(w[b] - w[b-1] != ds) UNIFORM = false; | ||
1300 | + | ||
1301 | + size_t nC = order + d; //approximating a derivative requires order + d samples | ||
1302 | + | ||
1303 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | ||
1304 | + | ||
1305 | + T* inspec = (T*)malloc(Bb); //allocate space for the input spectrum | ||
1306 | + T* outspec = (T*)malloc(Bb); //allocate space for the output spectrum | ||
1307 | + | ||
1308 | + size_t XY = X() * Y(); //number of pixels in the image | ||
1309 | + size_t mid = (size_t)(nC / 2); //calculate the mid point of the kernel | ||
1310 | + size_t iw; //index to the first wavelength used to evaluate the derivative at this band | ||
1311 | + for(size_t xy = 0; xy < XY; xy++){ //for each pixel | ||
1312 | + file.read((char*)inspec, Bb); //read an input spectrum | ||
1313 | + memset(outspec, 0, Bb); //set the output spectrum to zero (0) | ||
1314 | + | ||
1315 | + iw = 0; | ||
1316 | + for(size_t b = 0; b < mid; b++){ //for each component of the spectrum | ||
1317 | + std::vector<double> w_pts(w.begin() + iw, w.begin() + iw + nC); //get the wavelengths corresponding to each sample | ||
1318 | + std::vector<double> C = diff_coefficients(w[b], w_pts, d); //get the optimal sample weights | ||
1319 | + for(size_t c = 0; c < nC; c++) //for each coefficient in the kernel | ||
1320 | + outspec[b] += (T)(inspec[iw + c] * C[c]); //perform the sum/multiply part of the convolution | ||
1321 | + } | ||
1322 | + std::vector<double> w_pts(w.begin(), w.begin() + nC); //get the wavelengths corresponding to each sample | ||
1323 | + std::vector<double> C = diff_coefficients(w[0], w_pts, d); //get the optimal sample weights | ||
1324 | + for(size_t b = mid; b <= B - (nC - mid); b++){ | ||
1325 | + iw = b - mid; | ||
1326 | + if(!UNIFORM){ //if the spacing is non-uniform, we have to re-calculate these points every iteration | ||
1327 | + std::vector<double> w_pts(w.begin() + iw, w.begin() + iw + nC); //get the wavelengths corresponding to each sample | ||
1328 | + std::vector<double> C = diff_coefficients(w[b], w_pts, d); //get the optimal sample weights | ||
1329 | + } | ||
1330 | + for(size_t c = 0; c < nC; c++) //for each coefficient in the kernel | ||
1331 | + outspec[b] += (T)(inspec[iw + c] * C[c]); //perform the sum/multiply part of the convolution | ||
1332 | + } | ||
1333 | + iw = B - nC; | ||
1334 | + for(size_t b = B - (nC - mid) + 1; b < B; b++){ | ||
1335 | + std::vector<double> w_pts(w.begin() + iw, w.begin() + iw + nC); //get the wavelengths corresponding to each sample | ||
1336 | + std::vector<double> C = diff_coefficients(w[b], w_pts, d); //get the optimal sample weights | ||
1337 | + for(size_t c = 0; c < nC; c++) //for each coefficient in the kernel | ||
1338 | + outspec[b] += (T)(inspec[iw + c] * C[c]); //perform the sum/multiply part of the convolution | ||
1339 | + } | ||
1340 | + | ||
1341 | + out.write((char*)outspec, Bb); //output the band | ||
1342 | + if(PROGRESS) progress = (double)(xy+1) / (double)XY * 100; | ||
1343 | + } | ||
1344 | + } | ||
1345 | + | ||
1253 | 1346 | ||
1254 | 1347 | ||
1255 | /// Close the file. | 1348 | /// Close the file. |
stim/envi/bsq.h
@@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
7 | #include <cstring> | 7 | #include <cstring> |
8 | #include <utility> | 8 | #include <utility> |
9 | #include <vector> | 9 | #include <vector> |
10 | +#include <deque> | ||
10 | 11 | ||
11 | 12 | ||
12 | 13 | ||
@@ -1058,6 +1059,128 @@ public: | @@ -1058,6 +1059,128 @@ public: | ||
1058 | out.write((char*)dst, band_dst_bytes); //write the combined image to an output file | 1059 | out.write((char*)dst, band_dst_bytes); //write the combined image to an output file |
1059 | if(PROGRESS) progress = (double)(b + 1) / (double) Z() * 100; | 1060 | if(PROGRESS) progress = (double)(b + 1) / (double) Z() * 100; |
1060 | } | 1061 | } |
1062 | + out.close(); | ||
1063 | + } | ||
1064 | + | ||
1065 | + /// Convolve the given band range with a kernel specified by a vector of coefficients. | ||
1066 | + | ||
1067 | + /// @param outfile is an already open stream to the output file | ||
1068 | + /// @param C is an array of coefficients | ||
1069 | + /// @param start is the band to start processing (the first coefficient starts here) | ||
1070 | + /// @param nbands is the number of bands to process | ||
1071 | + /// @param center is the index for the center coefficient for the kernel (used to set the wavelengths in the output file) | ||
1072 | + | ||
1073 | + void convolve(std::ofstream& out, std::vector<double> C, size_t start, size_t end, bool PROGRESS = false){ | ||
1074 | + size_t nbands = end - start + 1; | ||
1075 | + size_t XY = X() * Y(); //calculate the number of values in a band | ||
1076 | + size_t XYb = XY * sizeof(T); //calculate the size of a band (frame) in bytes | ||
1077 | + | ||
1078 | + file.seekg(XYb * start, std::ios::beg); //move to the beginning of the 'start' band | ||
1079 | + | ||
1080 | + size_t nframes = C.size(); //get the number of bands that the kernel spans | ||
1081 | + std::deque<T*> frame(nframes, NULL); //create an array to store pointers to each frame | ||
1082 | + for(size_t f = 0; f < nframes; f++){ //for each frame | ||
1083 | + frame[f] = (T*)malloc(XYb); //allocate space for the frame | ||
1084 | + file.read((char*)frame[f], XYb); //load the frame | ||
1085 | + } | ||
1086 | + | ||
1087 | + T* outband = (T*)malloc(XYb); //allocate space for the output band | ||
1088 | + | ||
1089 | + //Implementation: In order to minimize reads from secondary storage, each band is only loaded once into the 'frame' deque. | ||
1090 | + // When a new band is loaded, the last band is popped, a new frame is copied to the pointer, and it is | ||
1091 | + // re-inserted into the deque. | ||
1092 | + for(size_t b = 0; b < nbands; b++){ //for each band | ||
1093 | + memset(outband, 0, XYb); //set the output band to zero (0) | ||
1094 | + for(size_t c = 0; c < nframes; c++){ //for each frame (corresponding to each coefficient) | ||
1095 | + for(size_t xy = 0; xy < XY; xy++){ //for each pixel | ||
1096 | + outband[xy] += (T)(C[c] * frame[c][xy]); //calculate the contribution of the current frame (scaled by the corresponding coefficient) | ||
1097 | + } | ||
1098 | + } | ||
1099 | + out.write((char*)outband, XYb); //output the band | ||
1100 | + file.read((char*)frame[0], XYb); //read the next band | ||
1101 | + frame.push_back(frame.front()); //put the first element in the back | ||
1102 | + frame.pop_front(); //pop the first element | ||
1103 | + if(PROGRESS) progress = (double)(b+1) / (double)nbands * 100; | ||
1104 | + } | ||
1105 | + } | ||
1106 | + | ||
1107 | + /// Performs a single convolution and saves it to an output file | ||
1108 | + | ||
1109 | + /// @param outfile is the convolved file to be output | ||
1110 | + /// @param C is an array of coefficients | ||
1111 | + /// @param start is the band to start processing (the first coefficient starts here) | ||
1112 | + /// @param nbands is the number of bands to process | ||
1113 | + void convolve(std::string outfile, std::vector<double> C, size_t start, size_t end, bool PROGRESS = false){ | ||
1114 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1115 | + convolve(out, C, start, end, PROGRESS); //start the convolution | ||
1116 | + out.close(); | ||
1117 | + } | ||
1118 | + | ||
1119 | + /// Performs a set of convolutions and chains the results together in a single file | ||
1120 | + | ||
1121 | + /// @param outfile is the convolved file to be output | ||
1122 | + /// @param C is an array containing an array of coefficients for each kernel | ||
1123 | + /// @param start is the list of start bands for each kernel | ||
1124 | + /// @param end is the list of end bands for each kernel | ||
1125 | + void convolve(std::string outfile, std::vector< std::vector<double> > C, std::vector<size_t> start, std::vector<size_t> end, bool PROGRESS = false){ | ||
1126 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1127 | + | ||
1128 | + size_t K = C.size(); //get the number of kernels | ||
1129 | + for(size_t k = 0; k < K; k++){ | ||
1130 | + size_t b0 = start[k]; //calculate the range of the convolution | ||
1131 | + size_t b1 = end[k]; | ||
1132 | + convolve(out, C[k], b0, b1, PROGRESS); //perform the convolution with the current kernel in the given range | ||
1133 | + } | ||
1134 | + out.close(); | ||
1135 | + } | ||
1136 | + | ||
1137 | + /// Approximate the spectral derivative of the image | ||
1138 | + | ||
1139 | + void deriv(std::string outfile, size_t d, size_t order, const std::vector<double> w = std::vector<double>(), bool PROGRESS = false){ | ||
1140 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1141 | + | ||
1142 | + size_t XY = X() * Y(); //calculate the number of values in a band | ||
1143 | + size_t XYb = XY * sizeof(T); //calculate the size of a band (frame) in bytes | ||
1144 | + size_t B = Z(); | ||
1145 | + file.seekg(0, std::ios::beg); //move to the beginning of the file | ||
1146 | + | ||
1147 | + size_t N = order + d; //approximating a derivative requires order + d samples | ||
1148 | + std::deque<T*> frame(N, NULL); //create an array to store pointers to each frame | ||
1149 | + for(size_t f = 0; f < N; f++){ //for each frame | ||
1150 | + frame[f] = (T*)malloc(XYb); //allocate space for the frame | ||
1151 | + file.read((char*)frame[f], XYb); //load the frame | ||
1152 | + } | ||
1153 | + | ||
1154 | + T* outband = (T*)malloc(XYb); //allocate space for the output band | ||
1155 | + | ||
1156 | + //Implementation: In order to minimize reads from secondary storage, each band is only loaded once into the 'frame' deque. | ||
1157 | + // When a new band is loaded, the last band is popped, a new frame is copied to the pointer, and it is | ||
1158 | + // re-inserted into the deque. | ||
1159 | + size_t mid = (size_t)(N / 2); //calculate the mid point of the kernel | ||
1160 | + size_t iw; //index to the first wavelength used to evaluate the derivative at this band | ||
1161 | + for(size_t b = 0; b < B; b++){ //for each band | ||
1162 | + if(b < mid) //calculate the first wavelength used to evaluate the derivative at this band | ||
1163 | + iw = 0; | ||
1164 | + else if(b > B - (N - mid + 1)) | ||
1165 | + iw = B - N; | ||
1166 | + else{ | ||
1167 | + iw = b - mid; | ||
1168 | + file.read((char*)frame[0], XYb); //read the next band | ||
1169 | + frame.push_back(frame.front()); //put the first element in the back | ||
1170 | + frame.pop_front(); //pop the first element | ||
1171 | + } | ||
1172 | + std::vector<double> w_pts(w.begin() + iw, w.begin() + iw + N); //get the wavelengths corresponding to each sample | ||
1173 | + std::vector<double> C = diff_coefficients(w[b], w_pts, d); //get the optimal sample weights | ||
1174 | + | ||
1175 | + memset(outband, 0, XYb); //set the output band to zero (0) | ||
1176 | + for(size_t c = 0; c < N; c++){ //for each frame (corresponding to each coefficient) | ||
1177 | + for(size_t xy = 0; xy < XY; xy++){ //for each pixel | ||
1178 | + outband[xy] += (T)(C[c] * frame[c][xy]); //calculate the contribution of the current frame (scaled by the corresponding coefficient) | ||
1179 | + } | ||
1180 | + } | ||
1181 | + out.write((char*)outband, XYb); //output the band | ||
1182 | + if(PROGRESS) progress = (double)(b+1) / (double)B * 100; | ||
1183 | + } | ||
1061 | 1184 | ||
1062 | } | 1185 | } |
1063 | 1186 |
stim/envi/envi.h
@@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
5 | #include "../envi/bsq.h" | 5 | #include "../envi/bsq.h" |
6 | #include "../envi/bip.h" | 6 | #include "../envi/bip.h" |
7 | #include "../envi/bil.h" | 7 | #include "../envi/bil.h" |
8 | +#include "../math/fd_coefficients.h" | ||
8 | #include <iostream> | 9 | #include <iostream> |
9 | //#include "../image/image.h" | 10 | //#include "../image/image.h" |
10 | 11 | ||
@@ -1341,6 +1342,103 @@ public: | @@ -1341,6 +1342,103 @@ public: | ||
1341 | } | 1342 | } |
1342 | } | 1343 | } |
1343 | } | 1344 | } |
1345 | + | ||
1346 | + /// Convolve the given band range with a kernel specified by a vector of coefficients. | ||
1347 | + | ||
1348 | + /// @param outfile is the combined file to be output | ||
1349 | + /// @param c is an array of coefficients | ||
1350 | + /// @param start is the band to start processing (the first coefficient starts here) | ||
1351 | + /// @param nbands is the number of bands to process | ||
1352 | + /// @param center is the index for the center coefficient for the kernel (used to set the wavelengths in the output file) | ||
1353 | + void convolve(std::string outfile, std::vector<double> C, size_t start, size_t end, size_t center = 0, bool PROGRESS = false){ | ||
1354 | + size_t nbands = end - start + 1; | ||
1355 | + envi_header h = header; //copy the current header | ||
1356 | + h.bands = nbands; //set the number of new bands | ||
1357 | + if(header.wavelength.size() != 0){ | ||
1358 | + h.wavelength.resize(nbands); //set the number of wavelengths to the number of bands | ||
1359 | + for(size_t b = 0; b < nbands; b++) | ||
1360 | + h.wavelength[b] = header.wavelength[b+center]; | ||
1361 | + } | ||
1362 | + if(header.band_names.size() != 0){ | ||
1363 | + h.band_names.resize(nbands); | ||
1364 | + for(size_t b = 0; b < nbands; b++) | ||
1365 | + h.band_names[b] = header.band_names[b+center]; | ||
1366 | + } | ||
1367 | + h.save(outfile + ".hdr"); //save the new header | ||
1368 | + | ||
1369 | + if (header.interleave == envi_header::BSQ){ | ||
1370 | + if (header.data_type == envi_header::float32) | ||
1371 | + ((bsq<float>*)file)->convolve(outfile, C, start, end, PROGRESS); | ||
1372 | + else if (header.data_type == envi_header::float64) | ||
1373 | + ((bsq<double>*)file)->convolve(outfile, C, start, end, PROGRESS); | ||
1374 | + else{ | ||
1375 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1376 | + exit(1); | ||
1377 | + } | ||
1378 | + } | ||
1379 | + else if (header.interleave == envi_header::BIL){ | ||
1380 | + if (header.data_type == envi_header::float32) | ||
1381 | + ((bil<float>*)file)->convolve(outfile, C, start, end, PROGRESS); | ||
1382 | + else if (header.data_type == envi_header::float64) | ||
1383 | + ((bil<double>*)file)->convolve(outfile, C, start, end, PROGRESS); | ||
1384 | + else{ | ||
1385 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1386 | + exit(1); | ||
1387 | + } | ||
1388 | + } | ||
1389 | + else if (header.interleave == envi_header::BIP){ | ||
1390 | + if (header.data_type == envi_header::float32) | ||
1391 | + ((bip<float>*)file)->convolve(outfile, C, start, end, PROGRESS); | ||
1392 | + else if (header.data_type == envi_header::float64) | ||
1393 | + ((bip<double>*)file)->convolve(outfile, C, start, end, PROGRESS); | ||
1394 | + else{ | ||
1395 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1396 | + exit(1); | ||
1397 | + } | ||
1398 | + } | ||
1399 | + } | ||
1400 | + | ||
1401 | + /// Approximates the nth derivative of the spectra to the specified order | ||
1402 | + | ||
1403 | + /// @param outfile is the file where the derivative approximation will be saved | ||
1404 | + /// @n is the derivative to be calculated | ||
1405 | + /// @order is the order of the error (must be even) | ||
1406 | + void deriv(std::string outfile, size_t d, size_t order, bool PROGRESS = false){ | ||
1407 | + header.save(outfile + ".hdr"); | ||
1408 | + if (header.interleave == envi_header::BSQ){ | ||
1409 | + if (header.data_type == envi_header::float32) | ||
1410 | + ((bsq<float>*)file)->deriv(outfile, d, order, header.wavelength, PROGRESS); | ||
1411 | + else if (header.data_type == envi_header::float64) | ||
1412 | + ((bsq<double>*)file)->deriv(outfile, d, order, header.wavelength, PROGRESS); | ||
1413 | + else{ | ||
1414 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1415 | + exit(1); | ||
1416 | + } | ||
1417 | + } | ||
1418 | + | ||
1419 | + else if (header.interleave == envi_header::BIL){ | ||
1420 | + if (header.data_type == envi_header::float32) | ||
1421 | + ((bil<float>*)file)->deriv(outfile, d, order, header.wavelength, PROGRESS); | ||
1422 | + else if (header.data_type == envi_header::float64) | ||
1423 | + ((bil<double>*)file)->deriv(outfile, d, order, header.wavelength, PROGRESS); | ||
1424 | + else{ | ||
1425 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1426 | + exit(1); | ||
1427 | + } | ||
1428 | + } | ||
1429 | + | ||
1430 | + else if (header.interleave == envi_header::BIP){ | ||
1431 | + if (header.data_type == envi_header::float32) | ||
1432 | + ((bip<float>*)file)->deriv(outfile, d, order, header.wavelength, PROGRESS); | ||
1433 | + else if (header.data_type == envi_header::float64) | ||
1434 | + ((bip<double>*)file)->deriv(outfile, d, order, header.wavelength, PROGRESS); | ||
1435 | + else{ | ||
1436 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1437 | + exit(1); | ||
1438 | + } | ||
1439 | + } | ||
1440 | + exit(1); | ||
1441 | + } | ||
1344 | }; | 1442 | }; |
1345 | 1443 | ||
1346 | } //end namespace rts | 1444 | } //end namespace rts |
1 | +#ifndef STIM_FINITE_DIFFERENCE_COEFFICIENTS | ||
2 | +#define STIM_FINITE_DIFFERENCE_COEFFICIENTS | ||
3 | + | ||
4 | +#include <vector> | ||
5 | +#include <algorithm> | ||
6 | + | ||
7 | +/// Calculate the coefficients used for finite differences on arbitrary grids. This code is based on: | ||
8 | +/// Fornberg, "Generation of Finite Difference Formulas on Arbitrarily Spaced Grids", Mathematics of Computation, 51(184) 699-706, 1988 | ||
9 | + | ||
10 | +/// @param Z is the location where the approximation is to be accurate | ||
11 | +/// @param X is a vector of coordinates for grid points | ||
12 | +/// @param M is the highest derivative to be computed | ||
13 | +/// This function returns a matrix C[a][b] where a is the derivative and b is the coefficient for x = b | ||
14 | + | ||
15 | +template <typename T> | ||
16 | +std::vector< std::vector<T> > diff_coefficient_matrix(T Z, std::vector<T> X, size_t M){ | ||
17 | + size_t n = X.size(); //calculate the number of data points available | ||
18 | + std::vector< std::vector<T> > C(M+1); //create an array of m arrays | ||
19 | + for(size_t m = 0; m < M+1; m++) //for each derivative | ||
20 | + C[m].resize(n); //allocate space for n coefficients | ||
21 | + | ||
22 | + T c1, c2, c3, c4, c5; | ||
23 | + c1 = 1; //initialize the matrix | ||
24 | + c4 = X[0] - Z; | ||
25 | + C[0][0] = 1; | ||
26 | + for(size_t i = 2; i <= n; i++){ | ||
27 | + size_t mn = (std::min)(i, M+1); | ||
28 | + c2 = 1; | ||
29 | + c5 = c4; | ||
30 | + c4 = X[i-1] - Z; | ||
31 | + for(size_t j = 1; j <= i-1; j++){ | ||
32 | + c3 = X[i-1] - X[j-1]; | ||
33 | + c2 = c2 * c3; | ||
34 | + if(j == i-1){ | ||
35 | + for(size_t k = 2; k <= mn; k++){ | ||
36 | + C[k-1][i-1] = c1 * ((k-1) * C[k-2][i-2] - c5 * C[k-1][i-2]) / c2; | ||
37 | + } | ||
38 | + C[0][i-1] = -c1 * c5 * C[0][i-2]/c2; | ||
39 | + } | ||
40 | + T c_p0 = C[0][j-1]; | ||
41 | + T c_p1 = C[1][j-1]; | ||
42 | + for(size_t k = 2; k <= mn; k++){ | ||
43 | + c_p1 = C[k-1][j-1]; | ||
44 | + C[k-1][j-1] = (c4 * c_p1 - (k-1) * c_p0) / c3; | ||
45 | + c_p0 = c_p1; | ||
46 | + } | ||
47 | + C[0][j-1] = c4 * C[0][j-1] / c3; | ||
48 | + } | ||
49 | + c1 = c2; | ||
50 | + } | ||
51 | + return C; | ||
52 | +} | ||
53 | + | ||
54 | +/// Returns the coefficients used to estimate the nth derivative at x0 given values at points in x | ||
55 | + | ||
56 | +/// @param x0 is the point where the derivative f'(x0) is to be estimated | ||
57 | +/// @param x is the set of points where the values of f(x) are known | ||
58 | +/// @param n specifies the derivative, ex. 2 estimates the second derivative f''(x0) | ||
59 | +template <typename T> | ||
60 | +std::vector<T> diff_coefficients(T x0, std::vector<T> x, size_t n){ | ||
61 | + std::vector< std::vector<T> > C = diff_coefficient_matrix(x0, x, n); //calculate all derivative coefficients | ||
62 | + return C.back(); | ||
63 | +} | ||
64 | + | ||
65 | + | ||
66 | + | ||
67 | +#endif | ||
0 | \ No newline at end of file | 68 | \ No newline at end of file |